On Tue, Apr 29, 2025 at 5:59 PM Mark Michelson <mmich...@redhat.com> wrote:

> Hi Ales,
>
> I have a couple of notes below.
>

Hi Mark,

thank you for the review.


> On 4/28/25 05:34, Ales Musil via dev 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>
> > ---
> > v3: Rebase on top of current main.
> > v2: Rebase on top of current main.
> > ---
> >   controller/mac-cache.c | 190 +++++++++++++++++------------------------
> >   controller/mac-cache.h |  41 +++++----
> >   controller/pinctrl.c   |  13 ++-
> >   controller/statctrl.c  |  53 ++++++------
> >   4 files changed, 139 insertions(+), 158 deletions(-)
> >
> > diff --git a/controller/mac-cache.c b/controller/mac-cache.c
> > index 18236c440..304304bee 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,14 +668,14 @@ 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);
> >       }
>
> Should we vector_destoy(&ctx->ready_packets_data) here?
>

Good catch, we definitely should.


> >
> > @@ -707,16 +686,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 +784,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 +831,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 +886,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 +894,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 +901,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 +927,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..295dc9e23 100644
> > --- a/controller/mac-cache.h
> > +++ b/controller/mac-cache.h
> > @@ -28,6 +28,9 @@
> >   #include "ovn-sb-idl.h"
> >
> >   struct ovsdb_idl_index;
> > +struct vector;
> > +
> > +#define MAC_CACHE_VEC_CAPACITY_THRESHOLD 1024
> >
> >   struct mac_cache_data {
> >       /* 'struct mac_cache_threshold' by datapath's tunnel_key. */
> > @@ -89,9 +92,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 +114,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 +127,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 +189,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 +214,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 +233,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 f67a61758..a51957761 100644
> > --- a/controller/pinctrl.c
> > +++ b/controller/pinctrl.c
> > @@ -1569,8 +1569,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();
> > @@ -4734,15 +4733,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) >= MAC_CACHE_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..28c794df8 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"
> > @@ -53,39 +54,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 +138,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 +148,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 +159,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 +191,19 @@ 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) >=
> > +            MAC_CACHE_VEC_CAPACITY_THRESHOLD) {
>
> This strikes me as odd. Specifically, if all stats nodes have the same
> threshold, then the name should probably be changed away from
> MAC_CACHE_VEC_CAPACITY_THRESHOLD.
>
>
The whole module is called mac-cache.c so it seemed fitting to use that
name.
It is also used in pinctrl, I have changed the name of both to better
reflect
what's going on.


>
> > +            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 +236,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 +257,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 +367,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 +402,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;
> >           }
>
>
Thanks,
Ales
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to