On Wed, Apr 30, 2025 at 7:54 AM Ales Musil <amu...@redhat.com> wrote:

> The statistics were stored as allocated object for each individual
> statistic and linked together via list. Store them in vector instead
> which allows us to avoid a lot of small allocations and free right
> after using the statistic.
>
> The same applies to the buffered packets, use vector instead of moving
> around single allocated objects. This should reduce the fragmentation.
>
> Signed-off-by: Ales Musil <amu...@redhat.com>
> ---
> v4: Rebase on top of current main.
>     Adjust the thhreshold define names.
>     Add missing vector_destroy.
> v3: Rebase on top of current main.
> v2: Rebase on top of current main.
> ---
>  controller/mac-cache.c | 191 +++++++++++++++++------------------------
>  controller/mac-cache.h |  39 +++++----
>  controller/pinctrl.c   |  15 +++-
>  controller/statctrl.c  |  54 ++++++------
>  4 files changed, 141 insertions(+), 158 deletions(-)
>
> diff --git a/controller/mac-cache.c b/controller/mac-cache.c
> index 18236c440..3237677dc 100644
> --- a/controller/mac-cache.c
> +++ b/controller/mac-cache.c
> @@ -18,6 +18,7 @@
>
>  #include "lflow.h"
>  #include "lib/mac-binding-index.h"
> +#include "lib/vec.h"
>  #include "local_data.h"
>  #include "lport.h"
>  #include "mac-cache.h"
> @@ -339,43 +340,30 @@ fdbs_clear(struct hmap *map)
>      }
>  }
>
> -struct mac_cache_stats {
> -    struct ovs_list list_node;
> -
> -    int64_t idle_age_ms;
> -
> -    union {
> -        /* Common data to identify MAC binding. */
> -        struct mac_binding_data mb;
> -        /* Common data to identify FDB. */
> -        struct fdb_data fdb;
> -    } data;
> -};
> -
>  /* MAC binding stat processing. */
>  void
> -mac_binding_stats_process_flow_stats(struct ovs_list *stats_list,
> +mac_binding_stats_process_flow_stats(struct vector *stats_vec,
>                                       struct ofputil_flow_stats *ofp_stats)
>  {
> -    struct mac_cache_stats *stats = xmalloc(sizeof *stats);
> -
> -    stats->idle_age_ms = ofp_stats->idle_age * 1000;
> -    stats->data.mb = (struct mac_binding_data) {
> -        .cookie = ntohll(ofp_stats->cookie),
> -        /* The port_key must be zero to match
> mac_binding_data_from_sbrec. */
> -        .port_key = 0,
> -        .dp_key = ntohll(ofp_stats->match.flow.metadata),
> -        .mac = ofp_stats->match.flow.dl_src
> +    struct mac_cache_stats stats = (struct mac_cache_stats) {
> +        .idle_age_ms = ofp_stats->idle_age * 1000,
> +        .data.mb = (struct mac_binding_data) {
> +            .cookie = ntohll(ofp_stats->cookie),
> +            /* The port_key must be zero to match
> +             * mac_binding_data_from_sbrec. */
> +            .port_key = 0,
> +            .dp_key = ntohll(ofp_stats->match.flow.metadata),
> +            .mac = ofp_stats->match.flow.dl_src
> +        },
>      };
>
>      if (ofp_stats->match.flow.dl_type == htons(ETH_TYPE_IP) ||
>          ofp_stats->match.flow.dl_type == htons(ETH_TYPE_ARP)) {
> -        stats->data.mb.ip =
> in6_addr_mapped_ipv4(ofp_stats->match.flow.nw_src);
> +        stats.data.mb.ip =
> in6_addr_mapped_ipv4(ofp_stats->match.flow.nw_src);
>      } else {
> -        stats->data.mb.ip = ofp_stats->match.flow.ipv6_src;
> +        stats.data.mb.ip = ofp_stats->match.flow.ipv6_src;
>      }
> -
> -    ovs_list_push_back(stats_list, &stats->list_node);
> +    vector_push(stats_vec, &stats);
>  }
>
>  static void
> @@ -409,19 +397,18 @@ void
>  mac_binding_stats_run(
>          struct rconn *swconn OVS_UNUSED,
>          struct ovsdb_idl_index *sbrec_port_binding_by_name OVS_UNUSED,
> -        struct ovs_list *stats_list, uint64_t *req_delay, void *data)
> +        struct vector *stats_vec, uint64_t *req_delay, void *data)
>  {
>      struct mac_cache_data *cache_data = data;
>      long long timewall_now = time_wall_msec();
>
>      struct mac_cache_stats *stats;
> -    LIST_FOR_EACH_POP (stats, list_node, stats_list) {
> +    VECTOR_FOR_EACH_PTR (stats_vec, stats) {
>          struct mac_binding *mb =
> mac_binding_find(&cache_data->mac_bindings,
>                                                    &stats->data.mb);
>          if (!mb) {
>              mac_binding_update_log("Not found in the cache:",
> &stats->data.mb,
>                                     false, NULL, 0, 0);
> -            free(stats);
>              continue;
>          }
>
> @@ -449,7 +436,6 @@ mac_binding_stats_run(
>                                     threshold, stats->idle_age_ms,
>                                     since_updated_ms);
>          }
> -        free(stats);
>      }
>
>      mac_cache_update_req_delay(&cache_data->thresholds, req_delay);
> @@ -460,19 +446,18 @@ mac_binding_stats_run(
>
>  /* FDB stat processing. */
>  void
> -fdb_stats_process_flow_stats(struct ovs_list *stats_list,
> +fdb_stats_process_flow_stats(struct vector *stats_vec,
>                               struct ofputil_flow_stats *ofp_stats)
>  {
> -    struct mac_cache_stats *stats = xmalloc(sizeof *stats);
> -
> -    stats->idle_age_ms = ofp_stats->idle_age * 1000;
> -    stats->data.fdb = (struct fdb_data) {
> +    struct mac_cache_stats stats = (struct mac_cache_stats) {
> +        .idle_age_ms = ofp_stats->idle_age * 1000,
> +        .data.fdb = (struct fdb_data) {
>              .port_key = ofp_stats->match.flow.regs[MFF_LOG_INPORT -
> MFF_REG0],
>              .dp_key = ntohll(ofp_stats->match.flow.metadata),
>              .mac = ofp_stats->match.flow.dl_src
> +        },
>      };
> -
> -    ovs_list_push_back(stats_list, &stats->list_node);
> +    vector_push(stats_vec, &stats);
>  }
>
>  static void
> @@ -506,20 +491,19 @@ fdb_update_log(const char *action,
>  void
>  fdb_stats_run(struct rconn *swconn OVS_UNUSED,
>                struct ovsdb_idl_index *sbrec_port_binding_by_name
> OVS_UNUSED,
> -              struct ovs_list *stats_list,
> +              struct vector *stats_vec,
>                uint64_t *req_delay, void *data)
>  {
>      struct mac_cache_data *cache_data = data;
>      long long timewall_now = time_wall_msec();
>
>      struct mac_cache_stats *stats;
> -    LIST_FOR_EACH_POP (stats, list_node, stats_list) {
> +    VECTOR_FOR_EACH_PTR (stats_vec, stats) {
>          struct fdb *fdb = fdb_find(&cache_data->fdbs, &stats->data.fdb);
>
>          if (!fdb) {
>              fdb_update_log("Not found in the cache:", &stats->data.fdb,
>                             false, NULL, 0, 0);
> -            free(stats);
>              continue;
>          }
>
> @@ -546,8 +530,6 @@ fdb_stats_run(struct rconn *swconn OVS_UNUSED,
>              fdb_update_log("Not updating non-active", &fdb->data, true,
>                             threshold, stats->idle_age_ms,
> since_updated_ms);
>          }
> -
> -        free(stats);
>      }
>
>      mac_cache_update_req_delay(&cache_data->thresholds, req_delay);
> @@ -557,34 +539,10 @@ fdb_stats_run(struct rconn *swconn OVS_UNUSED,
>  }
>
>  /* Packet buffering. */
> -struct bp_packet_data *
> -bp_packet_data_create(const struct ofputil_packet_in *pin,
> -                      const struct ofpbuf *continuation) {
> -    struct bp_packet_data *pd = xmalloc(sizeof *pd);
> -
> -    pd->pin = (struct ofputil_packet_in) {
> -            .packet = xmemdup(pin->packet, pin->packet_len),
> -            .packet_len = pin->packet_len,
> -            .flow_metadata = pin->flow_metadata,
> -            .reason = pin->reason,
> -            .table_id = pin->table_id,
> -            .cookie = pin->cookie,
> -            /* Userdata are empty on purpose,
> -             * it is not needed for the continuation. */
> -            .userdata = NULL,
> -            .userdata_len = 0,
> -    };
> -    pd->continuation = ofpbuf_clone(continuation);
> -
> -    return pd;
> -}
> -
> -
>  void
>  bp_packet_data_destroy(struct bp_packet_data *pd) {
>      free(pd->pin.packet);
>      ofpbuf_delete(pd->continuation);
> -    free(pd);
>  }
>
>  struct buffered_packets *
> @@ -604,7 +562,8 @@ buffered_packets_add(struct buffered_packets_ctx *ctx,
>          /* Schedule the freshly added buffered packet to do lookup
>           * immediately. */
>          bp->lookup_at_ms = 0;
> -        ovs_list_init(&bp->queue);
> +        bp->queue = VECTOR_CAPACITY_INITIALIZER(struct bp_packet_data,
> +                                                BUFFER_QUEUE_DEPTH);
>      }
>
>      bp->expire_at_ms = time_msec() + BUFFERED_PACKETS_TIMEOUT_MS;
> @@ -614,14 +573,32 @@ buffered_packets_add(struct buffered_packets_ctx
> *ctx,
>
>  void
>  buffered_packets_packet_data_enqueue(struct buffered_packets *bp,
> -                                     struct bp_packet_data *pd) {
> -    if (ovs_list_size(&bp->queue) == BUFFER_QUEUE_DEPTH) {
> -        struct bp_packet_data *p =
> CONTAINER_OF(ovs_list_pop_front(&bp->queue),
> -                                                struct bp_packet_data,
> node);
> -
> -        bp_packet_data_destroy(p);
> +                                     const struct ofputil_packet_in *pin,
> +                                     const struct ofpbuf *continuation)
> +{
> +    if (vector_len(&bp->queue) == BUFFER_QUEUE_DEPTH) {
> +        struct bp_packet_data pd;
> +        vector_remove(&bp->queue, 0, &pd);
> +        bp_packet_data_destroy(&pd);
>      }
> -    ovs_list_push_back(&bp->queue, &pd->node);
> +
> +    struct bp_packet_data pd = (struct bp_packet_data) {
> +        .pin = (struct ofputil_packet_in) {
> +            .packet = xmemdup(pin->packet, pin->packet_len),
> +            .packet_len = pin->packet_len,
> +            .flow_metadata = pin->flow_metadata,
> +            .reason = pin->reason,
> +            .table_id = pin->table_id,
> +            .cookie = pin->cookie,
> +            /* Userdata are empty on purpose,
> +             * it is not needed for the continuation. */
> +            .userdata = NULL,
> +            .userdata_len = 0,
> +        },
> +        .continuation = ofpbuf_clone(continuation),
> +    };
> +
> +    vector_push(&bp->queue, &pd);
>  }
>
>  void
> @@ -661,16 +638,18 @@ buffered_packets_ctx_run(struct buffered_packets_ctx
> *ctx,
>          }
>
>          struct bp_packet_data *pd;
> -        LIST_FOR_EACH_POP (pd, node, &bp->queue) {
> +        VECTOR_FOR_EACH_PTR (&bp->queue, pd) {
>              struct dp_packet packet;
>              dp_packet_use_const(&packet, pd->pin.packet,
> pd->pin.packet_len);
>
>              struct eth_header *eth = dp_packet_data(&packet);
>              eth->eth_dst = mac;
> -
> -            ovs_list_push_back(&ctx->ready_packets_data, &pd->node);
>          }
>
> +        vector_push_array(&ctx->ready_packets_data,
> +                          vector_get_array(&bp->queue),
> +                          vector_len(&bp->queue));
> +        vector_clear(&bp->queue);
>          buffered_packets_remove(ctx, bp);
>      }
>
> @@ -679,7 +658,7 @@ buffered_packets_ctx_run(struct buffered_packets_ctx
> *ctx,
>
>  bool
>  buffered_packets_ctx_is_ready_to_send(struct buffered_packets_ctx *ctx) {
> -    return !ovs_list_is_empty(&ctx->ready_packets_data);
> +    return !vector_is_empty(&ctx->ready_packets_data);
>  }
>
>  bool
> @@ -689,16 +668,17 @@ buffered_packets_ctx_has_packets(struct
> buffered_packets_ctx *ctx) {
>
>  void
>  buffered_packets_ctx_init(struct buffered_packets_ctx *ctx) {
> +    ctx->ready_packets_data = VECTOR_EMPTY_INITIALIZER(struct
> bp_packet_data);
>      hmap_init(&ctx->buffered_packets);
> -    ovs_list_init(&ctx->ready_packets_data);
>  }
>
>  void
>  buffered_packets_ctx_destroy(struct buffered_packets_ctx *ctx) {
>      struct bp_packet_data *pd;
> -    LIST_FOR_EACH_POP (pd, node, &ctx->ready_packets_data) {
> +    VECTOR_FOR_EACH_PTR (&ctx->ready_packets_data, pd) {
>          bp_packet_data_destroy(pd);
>      }
> +    vector_destroy(&ctx->ready_packets_data);
>
>      struct buffered_packets *bp;
>      HMAP_FOR_EACH_SAFE (bp, hmap_node, &ctx->buffered_packets) {
> @@ -707,16 +687,6 @@ buffered_packets_ctx_destroy(struct
> buffered_packets_ctx *ctx) {
>      hmap_destroy(&ctx->buffered_packets);
>  }
>
> -
> -void
> -mac_cache_stats_destroy(struct ovs_list *stats_list)
> -{
> -    struct mac_cache_stats *stats;
> -    LIST_FOR_EACH_POP (stats, list_node, stats_list) {
> -        free(stats);
> -    }
> -}
> -
>  static uint32_t
>  mac_binding_data_hash(const struct mac_binding_data *mb_data)
>  {
> @@ -815,11 +785,12 @@ static void
>  buffered_packets_remove(struct buffered_packets_ctx *ctx,
>                          struct buffered_packets *bp) {
>      struct bp_packet_data *pd;
> -    LIST_FOR_EACH_POP (pd, node, &bp->queue) {
> +    VECTOR_FOR_EACH_PTR (&bp->queue, pd) {
>          bp_packet_data_destroy(pd);
>      }
>
>      hmap_remove(&ctx->buffered_packets, &bp->hmap_node);
> +    vector_destroy(&bp->queue);
>      free(bp);
>  }
>
> @@ -861,48 +832,49 @@ buffered_packets_db_lookup(struct buffered_packets
> *bp, struct ds *ip,
>
>  void
>  mac_binding_probe_stats_process_flow_stats(
> -        struct ovs_list *stats_list,
> +        struct vector *stats_vec,
>          struct ofputil_flow_stats *ofp_stats)
>  {
> -    struct mac_cache_stats *stats = xmalloc(sizeof *stats);
> -
> -    stats->idle_age_ms = ofp_stats->idle_age * 1000;
> -    stats->data.mb = (struct mac_binding_data) {
> -        .cookie = ntohll(ofp_stats->cookie),
> -        /* The port_key must be zero to match
> mac_binding_data_from_sbrec. */
> -        .port_key = 0,
> -        .dp_key = ntohll(ofp_stats->match.flow.metadata),
> +    struct mac_cache_stats stats = (struct mac_cache_stats) {
> +        .idle_age_ms = ofp_stats->idle_age * 1000,
> +        .data.mb = (struct mac_binding_data) {
> +            .cookie = ntohll(ofp_stats->cookie),
> +            /* The port_key must be zero to match
> +             * mac_binding_data_from_sbrec. */
> +            .port_key = 0,
> +            .dp_key = ntohll(ofp_stats->match.flow.metadata),
> +            .mac = ofp_stats->match.flow.dl_src
> +        },
>      };
>
>      if (ofp_stats->match.flow.regs[0]) {
> -        stats->data.mb.ip =
> +        stats.data.mb.ip =
>              in6_addr_mapped_ipv4(htonl(ofp_stats->match.flow.regs[0]));
>      } else {
>          ovs_be128 ip6 = hton128(flow_get_xxreg(&ofp_stats->match.flow,
> 1));
> -        memcpy(&stats->data.mb.ip, &ip6, sizeof stats->data.mb.ip);
> +        memcpy(&stats.data.mb.ip, &ip6, sizeof stats.data.mb.ip);
>      }
>
> -    ovs_list_push_back(stats_list, &stats->list_node);
> +    vector_push(stats_vec, &stats);
>  }
>
>  void
>  mac_binding_probe_stats_run(
>          struct rconn *swconn,
>          struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -        struct ovs_list *stats_list,
> +        struct vector *stats_vec,
>          uint64_t *req_delay, void *data)
>  {
>      long long timewall_now = time_wall_msec();
>      struct mac_cache_data *cache_data = data;
>
>      struct mac_cache_stats *stats;
> -    LIST_FOR_EACH_POP (stats, list_node, stats_list) {
> +    VECTOR_FOR_EACH_PTR (stats_vec, stats) {
>          struct mac_binding *mb =
> mac_binding_find(&cache_data->mac_bindings,
>                                                    &stats->data.mb);
>          if (!mb) {
>              mac_binding_update_log("Probe: not found in the cache:",
>                                     &stats->data.mb, false, NULL, 0, 0);
> -            free(stats);
>              continue;
>          }
>
> @@ -915,7 +887,6 @@ mac_binding_probe_stats_run(
>              mac_binding_update_log("Not sending ARP/ND request for
> non-active",
>                                     &mb->data, true, threshold,
>                                     stats->idle_age_ms, since_updated_ms);
> -            free(stats);
>              continue;
>          }
>
> @@ -924,7 +895,6 @@ mac_binding_probe_stats_run(
>                      "Not sending ARP/ND request for recently updated",
>                      &mb->data, true, threshold, stats->idle_age_ms,
>                      since_updated_ms);
> -            free(stats);
>              continue;
>          }
>
> @@ -932,13 +902,11 @@ mac_binding_probe_stats_run(
>              lport_lookup_by_name(sbrec_port_binding_by_name,
>                                   sbrec->logical_port);
>          if (!pb) {
> -            free(stats);
>              continue;
>          }
>
>          struct lport_addresses laddr;
>          if (!extract_lsp_addresses(pb->mac[0], &laddr)) {
> -            free(stats);
>              continue;
>          }
>
> @@ -960,7 +928,6 @@ mac_binding_probe_stats_run(
>                                                OFTABLE_LOCAL_OUTPUT);
>          }
>
> -        free(stats);
>          destroy_lport_addresses(&laddr);
>      }
>
> diff --git a/controller/mac-cache.h b/controller/mac-cache.h
> index f5dbaf813..bdaec064b 100644
> --- a/controller/mac-cache.h
> +++ b/controller/mac-cache.h
> @@ -28,6 +28,7 @@
>  #include "ovn-sb-idl.h"
>
>  struct ovsdb_idl_index;
> +struct vector;
>
>  struct mac_cache_data {
>      /* 'struct mac_cache_threshold' by datapath's tunnel_key. */
> @@ -89,9 +90,18 @@ struct fdb {
>      long long timestamp;
>  };
>
> -struct bp_packet_data {
> -    struct ovs_list node;
> +struct mac_cache_stats {
> +    int64_t idle_age_ms;
> +
> +    union {
> +        /* Common data to identify MAC binding. */
> +        struct mac_binding_data mb;
> +        /* Common data to identify FDB. */
> +        struct fdb_data fdb;
> +    } data;
> +};
>
> +struct bp_packet_data {
>      struct ofpbuf *continuation;
>      struct ofputil_packet_in pin;
>  };
> @@ -102,7 +112,7 @@ struct buffered_packets {
>      struct mac_binding_data mb_data;
>
>      /* Queue of packet_data associated with this struct. */
> -    struct ovs_list queue;
> +    struct vector queue;
>
>      /* Timestamp in ms when the buffered packet should expire. */
>      long long int expire_at_ms;
> @@ -115,7 +125,7 @@ struct buffered_packets_ctx {
>      /* Map of all buffered packets waiting for the MAC address. */
>      struct hmap buffered_packets;
>      /* List of packet data that are ready to be sent. */
> -    struct ovs_list ready_packets_data;
> +    struct vector ready_packets_data;
>  };
>
>  /* Thresholds. */
> @@ -177,30 +187,24 @@ void fdbs_clear(struct hmap *map);
>
>  /* MAC binding stat processing. */
>  void
> -mac_binding_stats_process_flow_stats(struct ovs_list *stats_list,
> +mac_binding_stats_process_flow_stats(struct vector *stats_vec,
>                                       struct ofputil_flow_stats
> *ofp_stats);
>
>  void mac_binding_stats_run(
>          struct rconn *swconn OVS_UNUSED,
>          struct ovsdb_idl_index *sbrec_port_binding_by_name OVS_UNUSED,
> -        struct ovs_list *stats_list, uint64_t *req_delay, void *data);
> +        struct vector *stats_vec, uint64_t *req_delay, void *data);
>
>  /* FDB stat processing. */
> -void fdb_stats_process_flow_stats(struct ovs_list *stats_list,
> +void fdb_stats_process_flow_stats(struct vector *stats_vec,
>                                    struct ofputil_flow_stats *ofp_stats);
>
>  void fdb_stats_run(
>          struct rconn *swconn OVS_UNUSED,
>          struct ovsdb_idl_index *sbrec_port_binding_by_name OVS_UNUSED,
> -        struct ovs_list *stats_list, uint64_t *req_delay, void *data);
> -
> -void mac_cache_stats_destroy(struct ovs_list *stats_list);
> +        struct vector *stats_vec, uint64_t *req_delay, void *data);
>
>  /* Packet buffering. */
> -struct bp_packet_data *
> -bp_packet_data_create(const struct ofputil_packet_in *pin,
> -                      const struct ofpbuf *continuation);
> -
>  void bp_packet_data_destroy(struct bp_packet_data *pd);
>
>  struct buffered_packets *
> @@ -208,7 +212,8 @@ buffered_packets_add(struct buffered_packets_ctx *ctx,
>                       struct mac_binding_data mb_data);
>
>  void buffered_packets_packet_data_enqueue(struct buffered_packets *bp,
> -                                          struct bp_packet_data *pd);
> +                                          const struct ofputil_packet_in
> *pin,
> +                                          const struct ofpbuf
> *continuation);
>
>  void buffered_packets_ctx_run(struct buffered_packets_ctx *ctx,
>                                const struct hmap *recent_mbs,
> @@ -226,12 +231,12 @@ bool buffered_packets_ctx_is_ready_to_send(struct
> buffered_packets_ctx *ctx);
>  bool buffered_packets_ctx_has_packets(struct buffered_packets_ctx *ctx);
>
>  void mac_binding_probe_stats_process_flow_stats(
> -        struct ovs_list *stats_list,
> +        struct vector *stats_vec,
>          struct ofputil_flow_stats *ofp_stats);
>
>  void mac_binding_probe_stats_run(
>          struct rconn *swconn,
>          struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -        struct ovs_list *stats_list, uint64_t *req_delay, void *data);
> +        struct vector *stats_vec, uint64_t *req_delay, void *data);
>
>  #endif /* controller/mac-cache.h */
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index 34fb2e6bf..0647f053d 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -1570,8 +1570,7 @@ OVS_REQUIRES(pinctrl_mutex)
>          return;
>      }
>
> -    struct bp_packet_data *pd = bp_packet_data_create(pin, continuation);
> -    buffered_packets_packet_data_enqueue(bp, pd);
> +    buffered_packets_packet_data_enqueue(bp, pin, continuation);
>
>      /* There is a chance that the MAC binding was already created. */
>      notify_pinctrl_main();
> @@ -4738,6 +4737,8 @@ pinctrl_handle_put_mac_binding(const struct flow *md,
>      notify_pinctrl_main();
>  }
>
> +#define READY_PACKETS_VEC_CAPACITY_THRESHOLD 1024
> +
>  /* Called with in the pinctrl_handler thread context. */
>  static void
>  send_mac_binding_buffered_pkts(struct rconn *swconn)
> @@ -4745,15 +4746,21 @@ send_mac_binding_buffered_pkts(struct rconn
> *swconn)
>  {
>      enum ofp_version version = rconn_get_version(swconn);
>      enum ofputil_protocol proto =
> ofputil_protocol_from_ofp_version(version);
> +    struct vector *rpd = &buffered_packets_ctx.ready_packets_data;
>
>      struct bp_packet_data *pd;
> -    LIST_FOR_EACH_POP (pd, node,
> &buffered_packets_ctx.ready_packets_data) {
> +    VECTOR_FOR_EACH_PTR (rpd, pd) {
>          queue_msg(swconn, ofputil_encode_resume(&pd->pin,
> pd->continuation,
>                                                  proto));
>          bp_packet_data_destroy(pd);
>      }
>
> -    ovs_list_init(&buffered_packets_ctx.ready_packets_data);
> +    vector_clear(rpd);
> +    if (vector_capacity(rpd) >= READY_PACKETS_VEC_CAPACITY_THRESHOLD) {
> +        VLOG_DBG("The ready_packets_data vector capacity (%"PRIuSIZE") "
> +                 "is over threshold.", vector_capacity(rpd));
> +        vector_shrink_to_fit(rpd);
> +    }
>  }
>
>  /* Update or add an IP-MAC binding for 'logical_port'.
> diff --git a/controller/statctrl.c b/controller/statctrl.c
> index f0c5bd904..454314dda 100644
> --- a/controller/statctrl.c
> +++ b/controller/statctrl.c
> @@ -19,6 +19,7 @@
>  #include "dirs.h"
>  #include "latch.h"
>  #include "lflow.h"
> +#include "lib/vec.h"
>  #include "mac-cache.h"
>  #include "openvswitch/ofp-errors.h"
>  #include "openvswitch/ofp-flow.h"
> @@ -37,6 +38,8 @@
>
>  VLOG_DEFINE_THIS_MODULE(statctrl);
>
> +#define STATS_VEC_CAPACITY_THRESHOLD 1024
> +
>  enum stat_type {
>      STATS_MAC_BINDING = 0,
>      STATS_FDB,
> @@ -53,39 +56,33 @@ struct stats_node {
>      int64_t next_request_timestamp;
>      /* Request delay in ms. */
>      uint64_t request_delay;
> -    /* List of processed statistics. */
> -    struct ovs_list stats_list;
> -    /* Function to clean up the node.
> -     * This function runs in main thread. */
> -    void (*destroy)(struct ovs_list *stats_list);
> +    /* Vector of processed statistics. */
> +    struct vector stats;
>      /* Function to process the response and store it in the list.
>       * This function runs in statctrl thread locked behind mutex. */
> -    void (*process_flow_stats)(struct ovs_list *stats_list,
> +    void (*process_flow_stats)(struct vector *stats,
>                                 struct ofputil_flow_stats *ofp_stats);
>      /* Function to process the parsed stats.
>       * This function runs in main thread locked behind mutex. */
>      void (*run)(struct rconn *swconn,
>                  struct ovsdb_idl_index *sbrec_port_binding_by_name,
> -                struct ovs_list *stats_list,
> +                struct vector *stats,
>                  uint64_t *req_delay, void *data);
> -    /* Name of the stats node corresponding stopwatch. */
> -    const char *stopwatch_name;
> +    /* Name of the stats node. */
> +    const char *name;
>  };
>
> -#define STATS_NODE(NAME, REQUEST, DESTROY, PROCESS, RUN)
>  \
> +#define STATS_NODE(NAME, REQUEST, STAT_TYPE, PROCESS, RUN)
>  \
>      do {
>  \
>          statctrl_ctx.nodes[STATS_##NAME] = (struct stats_node) {
>  \
>              .request = REQUEST,
>   \
>              .xid = 0,
>   \
>              .next_request_timestamp = INT64_MAX,
>  \
>              .request_delay = 0,
>   \
> -            .stats_list =
>   \
> -                OVS_LIST_INITIALIZER(
>   \
> -                    &statctrl_ctx.nodes[STATS_##NAME].stats_list),
>  \
> -            .destroy = DESTROY,
>   \
> +            .stats = VECTOR_EMPTY_INITIALIZER(STAT_TYPE),
>   \
>              .process_flow_stats = PROCESS,
>  \
>              .run = RUN,
>   \
> -            .stopwatch_name = OVS_STRINGIZE(stats_##NAME),
>  \
> +            .name = OVS_STRINGIZE(stats_##NAME),                 \
>          };
>  \
>          stopwatch_create(OVS_STRINGIZE(stats_##NAME), SW_MS);
>   \
>      } while (0)
> @@ -143,7 +140,7 @@ statctrl_init(void)
>              .out_group = OFPG_ANY,
>              .table_id = OFTABLE_MAC_CACHE_USE,
>      };
> -    STATS_NODE(MAC_BINDING, mac_binding_request, mac_cache_stats_destroy,
> +    STATS_NODE(MAC_BINDING, mac_binding_request, struct mac_cache_stats,
>                 mac_binding_stats_process_flow_stats,
> mac_binding_stats_run);
>
>      struct ofputil_flow_stats_request fdb_request = {
> @@ -153,7 +150,7 @@ statctrl_init(void)
>              .out_group = OFPG_ANY,
>              .table_id = OFTABLE_LOOKUP_FDB,
>      };
> -    STATS_NODE(FDB, fdb_request, mac_cache_stats_destroy,
> +    STATS_NODE(FDB, fdb_request, struct mac_cache_stats,
>                 fdb_stats_process_flow_stats, fdb_stats_run);
>
>      struct ofputil_flow_stats_request mac_binding_probe_request = {
> @@ -164,7 +161,7 @@ statctrl_init(void)
>              .table_id = OFTABLE_MAC_BINDING,
>      };
>      STATS_NODE(MAC_BINDING_PROBE, mac_binding_probe_request,
> -               mac_cache_stats_destroy,
> +               struct mac_cache_stats,
>                 mac_binding_probe_stats_process_flow_stats,
>                 mac_binding_probe_stats_run);
>
> @@ -196,11 +193,18 @@ statctrl_run(struct ovsdb_idl_txn *ovnsb_idl_txn,
>          struct stats_node *node = &statctrl_ctx.nodes[i];
>          uint64_t prev_delay = node->request_delay;
>
> -        stopwatch_start(node->stopwatch_name, time_msec());
> +        stopwatch_start(node->name, time_msec());
>          node->run(statctrl_ctx.swconn,
> -                  sbrec_port_binding_by_name, &node->stats_list,
> +                  sbrec_port_binding_by_name, &node->stats,
>                    &node->request_delay, node_data[i]);
> -        stopwatch_stop(node->stopwatch_name, time_msec());
> +        vector_clear(&node->stats);
> +        if (vector_capacity(&node->stats) >=
> STATS_VEC_CAPACITY_THRESHOLD) {
> +            VLOG_DBG("The statistics vector for node '%s' capacity "
> +                     "(%"PRIuSIZE") is over threshold.", node->name,
> +                     vector_capacity(&node->stats));
> +            vector_shrink_to_fit(&node->stats);
> +        }
> +        stopwatch_stop(node->name, time_msec());
>
>          schedule_updated |=
>                  statctrl_update_next_request_timestamp(node, now,
> prev_delay);
> @@ -233,7 +237,7 @@ statctrl_wait(struct ovsdb_idl_txn *ovnsb_idl_txn)
>      ovs_mutex_lock(&mutex);
>      for (size_t i = 0; i < STATS_MAX; i++) {
>          struct stats_node *node = &statctrl_ctx.nodes[i];
> -        if (!ovs_list_is_empty(&node->stats_list)) {
> +        if (!vector_is_empty(&node->stats)) {
>              poll_immediate_wake();
>          }
>      }
> @@ -254,7 +258,7 @@ statctrl_destroy(void)
>
>      for (size_t i = 0; i < STATS_MAX; i++) {
>          struct stats_node *node = &statctrl_ctx.nodes[i];
> -        node->destroy(&node->stats_list);
> +        vector_destroy(&node->stats);
>      }
>  }
>
> @@ -364,7 +368,7 @@ statctrl_decode_statistics_reply(struct stats_node
> *node, struct ofpbuf *msg)
>              break;
>          }
>
> -        node->process_flow_stats(&node->stats_list, &fs);
> +        node->process_flow_stats(&node->stats, &fs);
>      }
>
>      ofpbuf_uninit(&ofpacts);
> @@ -399,7 +403,7 @@ static void
>  statctrl_notify_main_thread(struct statctrl_ctx *ctx)
>  {
>      for (size_t i = 0; i < STATS_MAX; i++) {
> -        if (!ovs_list_is_empty(&ctx->nodes[i].stats_list)) {
> +        if (!vector_is_empty(&ctx->nodes[i].stats)) {
>              seq_change(ctx->main_seq);
>              return;
>          }
> --
> 2.49.0
>
>
Recheck-request: github-robot
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to