Replace several lists in the controller code with vectors. The change
allows us to avoid small allocations just to keep to have the list
reference. The vector can store elements directly and allocates in
batches rather than one by one. This also simplifies the code to some
extent.

Signed-off-by: Ales Musil <amu...@redhat.com>
Acked-by: Mark Michelson <mmich...@redhat.com>
---
v4: Rebase on top of current main.
    Add ack from Mark.
v3: Rebase on top of current main.
v2: Rebase on top of current main.
---
 controller/binding.c                |  70 ++++------
 controller/mirror.c                 |  60 ++++-----
 controller/ofctrl-seqno.c           | 193 +++++++++++++---------------
 controller/ofctrl-seqno.h           |  11 +-
 controller/ovn-controller.c         |   2 +-
 controller/physical.c               |  79 ++++--------
 controller/route-exchange-netlink.c |  33 ++---
 controller/route-exchange-netlink.h |   6 +-
 controller/route-exchange.c         |  10 +-
 controller/test-ofctrl-seqno.c      |  27 ++--
 10 files changed, 204 insertions(+), 287 deletions(-)

diff --git a/controller/binding.c b/controller/binding.c
index 9aec6708f..f5091d2cf 100644
--- a/controller/binding.c
+++ b/controller/binding.c
@@ -2168,16 +2168,14 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct 
binding_ctx_out *b_ctx_out)
         build_local_bindings(b_ctx_in, b_ctx_out);
     }
 
-    struct ovs_list localnet_lports = OVS_LIST_INITIALIZER(&localnet_lports);
-    struct ovs_list external_lports = OVS_LIST_INITIALIZER(&external_lports);
-    struct ovs_list multichassis_ports = OVS_LIST_INITIALIZER(
-                                                        &multichassis_ports);
-    struct ovs_list vtep_lports = OVS_LIST_INITIALIZER(&vtep_lports);
-
-    struct lport {
-        struct ovs_list list_node;
-        const struct sbrec_port_binding *pb;
-    };
+    struct vector localnet_lports =
+        VECTOR_EMPTY_INITIALIZER(struct sbrec_port_binding *);
+    struct vector external_lports =
+        VECTOR_EMPTY_INITIALIZER(struct sbrec_port_binding *);
+    struct vector multichassis_ports =
+        VECTOR_EMPTY_INITIALIZER(struct sbrec_port_binding *);
+    struct vector vtep_lports =
+        VECTOR_EMPTY_INITIALIZER(struct sbrec_port_binding *);
 
     /* Run through each binding record to see if it is resident on this
      * chassis and update the binding accordingly.  This includes both
@@ -2202,9 +2200,7 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct 
binding_ctx_out *b_ctx_out)
 
         case LP_VTEP:
             update_related_lport(pb, b_ctx_out);
-            struct lport *vtep_lport = xmalloc(sizeof *vtep_lport);
-            vtep_lport->pb = pb;
-            ovs_list_push_back(&vtep_lports, &vtep_lport->list_node);
+            vector_push(&vtep_lports, &pb);
             break;
 
         case LP_LOCALPORT:
@@ -2214,11 +2210,7 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct 
binding_ctx_out *b_ctx_out)
         case LP_VIF:
             consider_vif_lport(pb, b_ctx_in, b_ctx_out, NULL);
             if (pb->additional_chassis) {
-                struct lport *multichassis_lport = xmalloc(
-                    sizeof *multichassis_lport);
-                multichassis_lport->pb = pb;
-                ovs_list_push_back(&multichassis_ports,
-                                   &multichassis_lport->list_node);
+                vector_push(&multichassis_ports, &pb);
             }
             break;
 
@@ -2248,17 +2240,12 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct 
binding_ctx_out *b_ctx_out)
 
         case LP_EXTERNAL:
             consider_external_lport(pb, b_ctx_in, b_ctx_out);
-            struct lport *ext_lport = xmalloc(sizeof *ext_lport);
-            ext_lport->pb = pb;
-            ovs_list_push_back(&external_lports, &ext_lport->list_node);
+            vector_push(&external_lports, &pb);
             break;
 
-        case LP_LOCALNET: {
-            struct lport *lnet_lport = xmalloc(sizeof *lnet_lport);
-            lnet_lport->pb = pb;
-            ovs_list_push_back(&localnet_lports, &lnet_lport->list_node);
+        case LP_LOCALNET:
+            vector_push(&localnet_lports, &pb);
             break;
-        }
 
         case LP_REMOTE:
             /* Remote ports are related, since we can have rules in the
@@ -2283,41 +2270,36 @@ binding_run(struct binding_ctx_in *b_ctx_in, struct 
binding_ctx_out *b_ctx_out)
     /* Run through each localnet lport list to see if it is a localnet port
      * on local datapaths discovered from above loop, and handles it
      * accordingly. */
-    struct lport *lnet_lport;
-    LIST_FOR_EACH_POP (lnet_lport, list_node, &localnet_lports) {
-        consider_localnet_lport(lnet_lport->pb, b_ctx_out);
-        update_ld_localnet_port(lnet_lport->pb, &bridge_mappings,
+    VECTOR_FOR_EACH (&localnet_lports, pb) {
+        consider_localnet_lport(pb, b_ctx_out);
+        update_ld_localnet_port(pb, &bridge_mappings,
                                 b_ctx_out->local_datapaths);
-        free(lnet_lport);
     }
+    vector_destroy(&localnet_lports);
 
     /* Run through external lport list to see if there are external ports
      * on local datapaths discovered from above loop, and update the
      * corresponding local datapath accordingly. */
-    struct lport *ext_lport;
-    LIST_FOR_EACH_POP (ext_lport, list_node, &external_lports) {
-        update_ld_external_ports(ext_lport->pb, b_ctx_out->local_datapaths);
-        free(ext_lport);
+    VECTOR_FOR_EACH (&external_lports, pb) {
+        update_ld_external_ports(pb, b_ctx_out->local_datapaths);
     }
+    vector_destroy(&external_lports);
 
     /* Run through multichassis lport list to see if there are ports
      * on local datapaths discovered from above loop, and update the
      * corresponding local datapath accordingly. */
-    struct lport *multichassis_lport;
-    LIST_FOR_EACH_POP (multichassis_lport, list_node, &multichassis_ports) {
-        update_ld_multichassis_ports(multichassis_lport->pb,
-                                     b_ctx_out->local_datapaths);
-        free(multichassis_lport);
+    VECTOR_FOR_EACH (&multichassis_ports, pb) {
+        update_ld_multichassis_ports(pb, b_ctx_out->local_datapaths);
     }
+    vector_destroy(&multichassis_ports);
 
     /* Run through vtep lport list to see if there are vtep ports
      * on local datapaths discovered from above loop, and update the
      * corresponding local datapath accordingly. */
-    struct lport *vtep_lport;
-    LIST_FOR_EACH_POP (vtep_lport, list_node, &vtep_lports) {
-        update_ld_vtep_port(vtep_lport->pb, b_ctx_out->local_datapaths);
-        free(vtep_lport);
+    VECTOR_FOR_EACH (&vtep_lports, pb) {
+        update_ld_vtep_port(pb, b_ctx_out->local_datapaths);
     }
+    vector_destroy(&vtep_lports);
 
     shash_destroy(&bridge_mappings);
     /* Remove stale QoS entries. */
diff --git a/controller/mirror.c b/controller/mirror.c
index 2f1c811a0..62b4ac98a 100644
--- a/controller/mirror.c
+++ b/controller/mirror.c
@@ -30,6 +30,7 @@
 #include "binding.h"
 #include "lib/ovn-sb-idl.h"
 #include "mirror.h"
+#include "vec.h"
 
 VLOG_DEFINE_THIS_MODULE(port_mirror);
 
@@ -37,14 +38,8 @@ struct ovn_mirror {
     char *name;
     const struct sbrec_mirror *sb_mirror;
     const struct ovsrec_mirror *ovs_mirror;
-    struct ovs_list mirror_src_lports;
-    struct ovs_list mirror_dst_lports;
-};
-
-struct mirror_lport {
-    struct ovs_list list_node;
-
-    struct local_binding *lbinding;
+    struct vector mirror_src_lports; /* Vector of struct local_binding *. */
+    struct vector mirror_dst_lports; /* Vector of struct local_binding *. */
 };
 
 static struct ovn_mirror *ovn_mirror_create(char *mirror_name);
@@ -238,8 +233,8 @@ ovn_mirror_create(char *mirror_name)
 {
     struct ovn_mirror *m = xzalloc(sizeof *m);
     m->name = xstrdup(mirror_name);
-    ovs_list_init(&m->mirror_src_lports);
-    ovs_list_init(&m->mirror_dst_lports);
+    m->mirror_src_lports = VECTOR_EMPTY_INITIALIZER(struct local_binding *);
+    m->mirror_dst_lports = VECTOR_EMPTY_INITIALIZER(struct local_binding *);
     return m;
 }
 
@@ -259,15 +254,8 @@ static void
 ovn_mirror_delete(struct ovn_mirror *m)
 {
     free(m->name);
-    struct mirror_lport *m_lport;
-    LIST_FOR_EACH_POP (m_lport, list_node, &m->mirror_src_lports) {
-        free(m_lport);
-    }
-
-    LIST_FOR_EACH_POP (m_lport, list_node, &m->mirror_dst_lports) {
-        free(m_lport);
-    }
-
+    vector_destroy(&m->mirror_src_lports);
+    vector_destroy(&m->mirror_dst_lports);
     free(m);
 }
 
@@ -276,16 +264,12 @@ ovn_mirror_add_lport(struct ovn_mirror *m, struct 
local_binding *lbinding)
 {
     if (!strcmp(m->sb_mirror->filter, "from-lport") ||
         !strcmp(m->sb_mirror->filter, "both")) {
-        struct mirror_lport *m_lport = xzalloc(sizeof *m_lport);
-        m_lport->lbinding = lbinding;
-        ovs_list_push_back(&m->mirror_src_lports, &m_lport->list_node);
+        vector_push(&m->mirror_src_lports, &lbinding);
     }
 
     if (!strcmp(m->sb_mirror->filter, "to-lport") ||
         !strcmp(m->sb_mirror->filter, "both")) {
-        struct mirror_lport *m_lport = xzalloc(sizeof *m_lport);
-        m_lport->lbinding = lbinding;
-        ovs_list_push_back(&m->mirror_dst_lports, &m_lport->list_node);
+        vector_push(&m->mirror_dst_lports, &lbinding);
     }
 }
 
@@ -350,8 +334,8 @@ sync_ovn_mirror(struct ovn_mirror *m, struct ovsdb_idl_txn 
*ovs_idl_txn,
         return;
     }
 
-    if (ovs_list_is_empty(&m->mirror_src_lports) &&
-            ovs_list_is_empty(&m->mirror_dst_lports)) {
+    if (vector_is_empty(&m->mirror_src_lports) &&
+        vector_is_empty(&m->mirror_dst_lports)) {
         /* Nothing to do. */
         return;
     }
@@ -399,8 +383,8 @@ should_delete_ovs_mirror(struct ovn_mirror *m)
         return true;
     }
 
-    return (ovs_list_is_empty(&m->mirror_src_lports) &&
-            ovs_list_is_empty(&m->mirror_dst_lports));
+    return (vector_is_empty(&m->mirror_src_lports) &&
+            vector_is_empty(&m->mirror_dst_lports));
 }
 
 static const struct ovsrec_port *
@@ -474,18 +458,18 @@ create_ovs_mirror(struct ovn_mirror *m, struct 
ovsdb_idl_txn *ovs_idl_txn,
 static void
 sync_ovs_mirror_ports(struct ovn_mirror *m, const struct ovsrec_bridge *br_int)
 {
-    struct mirror_lport *m_lport;
+    struct local_binding *lbinding;
 
-    if (ovs_list_is_empty(&m->mirror_src_lports)) {
+    if (vector_is_empty(&m->mirror_src_lports)) {
         ovsrec_mirror_set_select_src_port(m->ovs_mirror, NULL, 0);
     } else {
-        size_t n_lports = ovs_list_size(&m->mirror_src_lports);
+        size_t n_lports = vector_len(&m->mirror_src_lports);
         struct ovsrec_port **ovs_ports = xmalloc(sizeof *ovs_ports * n_lports);
 
         size_t i = 0;
-        LIST_FOR_EACH (m_lport, list_node, &m->mirror_src_lports) {
+        VECTOR_FOR_EACH (&m->mirror_src_lports, lbinding) {
             const struct ovsrec_port *p =
-                get_iface_port(m_lport->lbinding->iface, br_int);
+                get_iface_port(lbinding->iface, br_int);
             ovs_assert(p);
             ovs_ports[i++] = (struct ovsrec_port *) p;
         }
@@ -494,16 +478,16 @@ sync_ovs_mirror_ports(struct ovn_mirror *m, const struct 
ovsrec_bridge *br_int)
         free(ovs_ports);
     }
 
-    if (ovs_list_is_empty(&m->mirror_dst_lports)) {
+    if (vector_is_empty(&m->mirror_dst_lports)) {
         ovsrec_mirror_set_select_dst_port(m->ovs_mirror, NULL, 0);
     } else {
-        size_t n_lports = ovs_list_size(&m->mirror_dst_lports);
+        size_t n_lports = vector_len(&m->mirror_dst_lports);
         struct ovsrec_port **ovs_ports = xmalloc(sizeof *ovs_ports * n_lports);
 
         size_t i = 0;
-        LIST_FOR_EACH (m_lport, list_node, &m->mirror_dst_lports) {
+        VECTOR_FOR_EACH (&m->mirror_dst_lports, lbinding) {
             const struct ovsrec_port *p =
-                get_iface_port(m_lport->lbinding->iface, br_int);
+                get_iface_port(lbinding->iface, br_int);
             ovs_assert(p);
             ovs_ports[i++] = (struct ovsrec_port *) p;
         }
diff --git a/controller/ofctrl-seqno.c b/controller/ofctrl-seqno.c
index 95373aa57..83c17c0e5 100644
--- a/controller/ofctrl-seqno.c
+++ b/controller/ofctrl-seqno.c
@@ -19,13 +19,15 @@
 #include "ofctrl-seqno.h"
 #include "openvswitch/list.h"
 #include "util.h"
+#include "vec.h"
+
+#define VECTOR_THRESHOLD 1024
 
 /* A sequence number update request, i.e., when the barrier corresponding to
  * the 'flow_cfg' sequence number is replied to by OVS then it is safe
  * to inform the application that the 'req_cfg' seqno has been processed.
  */
 struct ofctrl_seqno_update {
-    struct ovs_list list_node; /* In 'ofctrl_seqno_updates'. */
     size_t seqno_type;         /* Application specific seqno type.
                                 * Relevant only for 'req_cfg'.
                                 */
@@ -37,14 +39,15 @@ struct ofctrl_seqno_update {
 };
 
 /* List of in flight sequence number updates. */
-static struct ovs_list ofctrl_seqno_updates;
+static struct vector ofctrl_seqno_updates =
+    VECTOR_EMPTY_INITIALIZER(struct ofctrl_seqno_update);
 
 /* Last sequence number request sent to OVS. */
 static uint64_t ofctrl_req_seqno;
 
 /* State of seqno requests for a given application seqno type. */
 struct ofctrl_seqno_state {
-    struct ovs_list acked_cfgs; /* Acked requests since the last time the
+    struct vector acked_cfgs;   /* Acked requests since the last time the
                                  * application consumed acked requests.
                                  */
     uint64_t cur_cfg;           /* Last acked application seqno. */
@@ -52,20 +55,11 @@ struct ofctrl_seqno_state {
 };
 
 /* Per application seqno type states. */
-static size_t n_ofctrl_seqno_states;
-static struct ofctrl_seqno_state *ofctrl_seqno_states;
-
-/* ofctrl_acked_seqnos related static function prototypes. */
-static void ofctrl_acked_seqnos_init(struct ofctrl_acked_seqnos *seqnos,
-                                     uint64_t last_acked);
-static void ofctrl_acked_seqnos_add(struct ofctrl_acked_seqnos *seqnos,
-                                    uint64_t val);
+static struct vector ofctrl_seqno_states =
+    VECTOR_EMPTY_INITIALIZER(struct ofctrl_seqno_state);
 
-/* ofctrl_seqno_update related static function prototypes. */
-static void ofctrl_seqno_update_create__(size_t seqno_type, uint64_t req_cfg);
-static void ofctrl_seqno_update_list_destroy(struct ovs_list *seqno_list);
-static void ofctrl_seqno_cfg_run(size_t seqno_type,
-                                 struct ofctrl_seqno_update *update);
+/* ofctrl_seqno_state related static function prototypes. */
+static struct ofctrl_seqno_state *ofctrl_seqno_state_get(size_t seqno_type);
 
 /* Returns the collection of acked ofctrl_seqno_update requests of type
  * 'seqno_type'.  It's the responsibility of the caller to free memory by
@@ -74,17 +68,17 @@ static void ofctrl_seqno_cfg_run(size_t seqno_type,
 struct ofctrl_acked_seqnos *
 ofctrl_acked_seqnos_get(size_t seqno_type)
 {
-    struct ofctrl_acked_seqnos *acked_seqnos = xmalloc(sizeof *acked_seqnos);
-    struct ofctrl_seqno_state *state = &ofctrl_seqno_states[seqno_type];
-    struct ofctrl_seqno_update *update;
+    struct ofctrl_seqno_state *state = ofctrl_seqno_state_get(seqno_type);
 
-    ofctrl_acked_seqnos_init(acked_seqnos, state->cur_cfg);
+    struct ofctrl_acked_seqnos *acked_seqnos = xmalloc(sizeof *acked_seqnos);
+    acked_seqnos->acked = vector_clone(&state->acked_cfgs);
+    acked_seqnos->last_acked = state->cur_cfg;
 
-    ovs_assert(seqno_type < n_ofctrl_seqno_states);
-    LIST_FOR_EACH_POP (update, list_node, &state->acked_cfgs) {
-        ofctrl_acked_seqnos_add(acked_seqnos, update->req_cfg);
-        free(update);
+    vector_clear(&state->acked_cfgs);
+    if (vector_capacity(&state->acked_cfgs) >= VECTOR_THRESHOLD) {
+        vector_shrink_to_fit(&state->acked_cfgs);
     }
+
     return acked_seqnos;
 }
 
@@ -95,11 +89,7 @@ ofctrl_acked_seqnos_destroy(struct ofctrl_acked_seqnos 
*seqnos)
         return;
     }
 
-    struct ofctrl_ack_seqno *seqno_node;
-    HMAP_FOR_EACH_POP (seqno_node, node, &seqnos->acked) {
-        free(seqno_node);
-    }
-    hmap_destroy(&seqnos->acked);
+    vector_destroy(&seqnos->acked);
     free(seqnos);
 }
 
@@ -108,40 +98,52 @@ bool
 ofctrl_acked_seqnos_contains(const struct ofctrl_acked_seqnos *seqnos,
                              uint64_t val)
 {
-    struct ofctrl_ack_seqno *sn;
+    if (vector_is_empty(&seqnos->acked)) {
+        return false;
+    }
+
+    size_t low = 0;
+    size_t high = vector_len(&seqnos->acked) -1;
+    uint64_t *acked = vector_get_array(&seqnos->acked);
 
-    HMAP_FOR_EACH_WITH_HASH (sn, node, hash_uint64(val), &seqnos->acked) {
-        if (sn->seqno == val) {
+    while (low <= high) {
+        size_t mid = low + (high - low) / 2;
+
+        if (acked[mid] == val) {
             return true;
         }
+
+        if (acked[mid] >= acked[low]) {
+            if (val >= acked[low] && val < acked[mid]) {
+                high = mid - 1;
+            } else {
+                low = mid + 1;
+            }
+        } else {
+            if (val > acked[mid] && val <= acked[high]) {
+                low = mid + 1;
+            } else {
+                high = mid - 1;
+            }
+        }
     }
-    return false;
-}
 
-void
-ofctrl_seqno_init(void)
-{
-    ovs_list_init(&ofctrl_seqno_updates);
+    return false;
 }
 
 /* Adds a new type of application specific seqno updates. */
 size_t
 ofctrl_seqno_add_type(void)
 {
-    size_t new_type = n_ofctrl_seqno_states;
-    n_ofctrl_seqno_states++;
-
-    struct ofctrl_seqno_state *new_states =
-        xzalloc(n_ofctrl_seqno_states * sizeof *new_states);
+    size_t new_type = vector_len(&ofctrl_seqno_states);
 
-    for (size_t i = 0; i < n_ofctrl_seqno_states - 1; i++) {
-        ovs_list_move(&new_states[i].acked_cfgs,
-                      &ofctrl_seqno_states[i].acked_cfgs);
-    }
-    ovs_list_init(&new_states[new_type].acked_cfgs);
+    struct ofctrl_seqno_state state = (struct ofctrl_seqno_state) {
+        .acked_cfgs = VECTOR_EMPTY_INITIALIZER(uint64_t),
+        .cur_cfg = 0,
+        .req_cfg = 0,
+    };
+    vector_push(&ofctrl_seqno_states, &state);
 
-    free(ofctrl_seqno_states);
-    ofctrl_seqno_states = new_states;
     return new_type;
 }
 
@@ -151,9 +153,7 @@ ofctrl_seqno_add_type(void)
 void
 ofctrl_seqno_update_create(size_t seqno_type, uint64_t new_cfg)
 {
-    ovs_assert(seqno_type < n_ofctrl_seqno_states);
-
-    struct ofctrl_seqno_state *state = &ofctrl_seqno_states[seqno_type];
+    struct ofctrl_seqno_state *state = ofctrl_seqno_state_get(seqno_type);
 
     /* If new_cfg didn't change since the last request there should already
      * be an update pending.
@@ -163,7 +163,14 @@ ofctrl_seqno_update_create(size_t seqno_type, uint64_t 
new_cfg)
     }
 
     state->req_cfg = new_cfg;
-    ofctrl_seqno_update_create__(seqno_type, new_cfg);
+
+    ofctrl_req_seqno++;
+    struct ofctrl_seqno_update update = (struct ofctrl_seqno_update) {
+        .seqno_type = seqno_type,
+        .flow_cfg = ofctrl_req_seqno,
+        .req_cfg = new_cfg,
+    };
+    vector_push(&ofctrl_seqno_updates, &update);
 }
 
 /* Should be called when the application is certain that all OVS flow updates
@@ -173,14 +180,25 @@ ofctrl_seqno_update_create(size_t seqno_type, uint64_t 
new_cfg)
 void
 ofctrl_seqno_run(uint64_t flow_cfg)
 {
+    size_t index = 0;
+
     struct ofctrl_seqno_update *update;
-    LIST_FOR_EACH_SAFE (update, list_node, &ofctrl_seqno_updates) {
+    VECTOR_FOR_EACH_PTR (&ofctrl_seqno_updates, update) {
         if (flow_cfg < update->flow_cfg) {
             break;
         }
+        struct ofctrl_seqno_state *state =
+            ofctrl_seqno_state_get(update->seqno_type);
+        state->cur_cfg = update->req_cfg;
+        vector_push(&state->acked_cfgs, &update->req_cfg);
+
+        index++;
+    }
+
+    vector_remove_block(&ofctrl_seqno_updates, 0, index);
 
-        ovs_list_remove(&update->list_node);
-        ofctrl_seqno_cfg_run(update->seqno_type, update);
+    if (vector_capacity(&ofctrl_seqno_updates) >= VECTOR_THRESHOLD) {
+        vector_shrink_to_fit(&ofctrl_seqno_updates);
     }
 }
 
@@ -197,58 +215,31 @@ ofctrl_seqno_get_req_cfg(void)
 void
 ofctrl_seqno_flush(void)
 {
-    for (size_t i = 0; i < n_ofctrl_seqno_states; i++) {
-        ofctrl_seqno_update_list_destroy(&ofctrl_seqno_states[i].acked_cfgs);
-    }
-    ofctrl_seqno_update_list_destroy(&ofctrl_seqno_updates);
-    ofctrl_req_seqno = 0;
-}
-
-static void
-ofctrl_acked_seqnos_init(struct ofctrl_acked_seqnos *seqnos,
-                         uint64_t last_acked)
-{
-    hmap_init(&seqnos->acked);
-    seqnos->last_acked = last_acked;
-}
+    vector_clear(&ofctrl_seqno_updates);
 
-static void
-ofctrl_acked_seqnos_add(struct ofctrl_acked_seqnos *seqnos, uint64_t val)
-{
-    seqnos->last_acked = val;
-
-    struct ofctrl_ack_seqno *sn = xmalloc(sizeof *sn);
-    hmap_insert(&seqnos->acked, &sn->node, hash_uint64(val));
-    sn->seqno = val;
-}
-
-static void
-ofctrl_seqno_update_create__(size_t seqno_type, uint64_t req_cfg)
-{
-    struct ofctrl_seqno_update *update = xmalloc(sizeof *update);
+    struct ofctrl_seqno_state *state;
+    VECTOR_FOR_EACH_PTR (&ofctrl_seqno_states, state) {
+        vector_clear(&state->acked_cfgs);
+    }
 
-    ofctrl_req_seqno++;
-    ovs_list_push_back(&ofctrl_seqno_updates, &update->list_node);
-    update->seqno_type = seqno_type;
-    update->flow_cfg = ofctrl_req_seqno;
-    update->req_cfg = req_cfg;
+    ofctrl_req_seqno = 0;
 }
 
-static void
-ofctrl_seqno_update_list_destroy(struct ovs_list *seqno_list)
+void
+ofctrl_seqno_destroy(void)
 {
-    struct ofctrl_seqno_update *update;
+    vector_destroy(&ofctrl_seqno_updates);
 
-    LIST_FOR_EACH_POP (update, list_node, seqno_list) {
-        free(update);
+    struct ofctrl_seqno_state *state;
+    VECTOR_FOR_EACH_PTR (&ofctrl_seqno_states, state) {
+        vector_destroy(&state->acked_cfgs);
     }
+    vector_destroy(&ofctrl_seqno_states);
 }
 
-static void
-ofctrl_seqno_cfg_run(size_t seqno_type, struct ofctrl_seqno_update *update)
+static struct ofctrl_seqno_state *
+ofctrl_seqno_state_get(size_t seqno_type)
 {
-    ovs_assert(seqno_type < n_ofctrl_seqno_states);
-    ovs_list_push_back(&ofctrl_seqno_states[seqno_type].acked_cfgs,
-                       &update->list_node);
-    ofctrl_seqno_states[seqno_type].cur_cfg = update->req_cfg;
+    ovs_assert(seqno_type < vector_len(&ofctrl_seqno_states));
+    return vector_get_ptr(&ofctrl_seqno_states, seqno_type);
 }
diff --git a/controller/ofctrl-seqno.h b/controller/ofctrl-seqno.h
index adcc5a0d3..faa97cc53 100644
--- a/controller/ofctrl-seqno.h
+++ b/controller/ofctrl-seqno.h
@@ -19,31 +19,26 @@
 #include <stdint.h>
 
 #include <openvswitch/hmap.h>
+#include "vec.h"
 
 /* Collection of acked ofctrl_seqno_update requests and the most recent
  * 'last_acked' value.
  */
 struct ofctrl_acked_seqnos {
-    struct hmap acked;
+    struct vector acked;
     uint64_t last_acked;
 };
 
-/* Acked application specific seqno.  Stored in ofctrl_acked_seqnos.acked. */
-struct ofctrl_ack_seqno {
-    struct hmap_node node;
-    uint64_t seqno;
-};
-
 struct ofctrl_acked_seqnos *ofctrl_acked_seqnos_get(size_t seqno_type);
 void ofctrl_acked_seqnos_destroy(struct ofctrl_acked_seqnos *seqnos);
 bool ofctrl_acked_seqnos_contains(const struct ofctrl_acked_seqnos *seqnos,
                                   uint64_t val);
 
-void ofctrl_seqno_init(void);
 size_t ofctrl_seqno_add_type(void);
 void ofctrl_seqno_update_create(size_t seqno_type, uint64_t new_cfg);
 void ofctrl_seqno_run(uint64_t flow_cfg);
 uint64_t ofctrl_seqno_get_req_cfg(void);
 void ofctrl_seqno_flush(void);
+void ofctrl_seqno_destroy(void);
 
 #endif /* controller/ofctrl-seqno.h */
diff --git a/controller/ovn-controller.c b/controller/ovn-controller.c
index 180b8a8d2..1cf5bb45f 100644
--- a/controller/ovn-controller.c
+++ b/controller/ovn-controller.c
@@ -5926,7 +5926,6 @@ main(int argc, char *argv[])
 
     ofctrl_init(&lflow_output_data->group_table,
                 &lflow_output_data->meter_table);
-    ofctrl_seqno_init();
 
     unixctl_command_register("group-table-list", "", 0, 0,
                              extend_table_list,
@@ -6640,6 +6639,7 @@ loop_done:
     free(ovn_version);
     lflow_destroy();
     ofctrl_destroy();
+    ofctrl_seqno_destroy();
     pinctrl_destroy();
     binding_destroy();
     patch_destroy();
diff --git a/controller/physical.c b/controller/physical.c
index a17d792c3..65b4c7335 100644
--- a/controller/physical.c
+++ b/controller/physical.c
@@ -64,11 +64,6 @@ struct zone_ids {
     int snat;                   /* MFF_LOG_SNAT_ZONE. */
 };
 
-struct tunnel {
-    struct ovs_list list_node;
-    const struct chassis_tunnel *tun;
-};
-
 static void
 load_logical_ingress_metadata(const struct sbrec_port_binding *binding,
                               const struct zone_ids *zone_ids,
@@ -415,16 +410,14 @@ find_additional_encap_for_chassis(const struct 
sbrec_port_binding *pb,
     return NULL;
 }
 
-static struct ovs_list *
+static struct vector
 get_remote_tunnels(const struct sbrec_port_binding *binding,
                    const struct physical_ctx *ctx,
                    const char *local_encap_ip)
 {
+    struct vector tunnels =
+        VECTOR_EMPTY_INITIALIZER(const struct chassis_tunnel *);
     const struct chassis_tunnel *tun;
-
-    struct ovs_list *tunnels = xmalloc(sizeof *tunnels);
-    ovs_list_init(tunnels);
-
     if (binding->chassis && binding->chassis != ctx->chassis) {
         tun = get_port_binding_tun(binding->encap, binding->chassis,
                 ctx->chassis_tunnels, local_encap_ip);
@@ -435,9 +428,7 @@ get_remote_tunnels(const struct sbrec_port_binding *binding,
                      "for port %s.",
                 binding->chassis->name, binding->logical_port);
         } else {
-            struct tunnel *tun_elem = xmalloc(sizeof *tun_elem);
-            tun_elem->tun = tun;
-            ovs_list_push_back(tunnels, &tun_elem->list_node);
+            vector_push(&tunnels, &tun);
         }
     }
 
@@ -459,9 +450,7 @@ get_remote_tunnels(const struct sbrec_port_binding *binding,
                 binding->additional_chassis[i]->name, binding->logical_port);
             continue;
         }
-        struct tunnel *tun_elem = xmalloc(sizeof *tun_elem);
-        tun_elem->tun = tun;
-        ovs_list_push_back(tunnels, &tun_elem->list_node);
+        vector_push(&tunnels, &tun);
     }
     return tunnels;
 }
@@ -482,8 +471,8 @@ put_remote_port_redirect_overlay(const struct 
sbrec_port_binding *binding,
 
         match_set_reg_masked(match, MFF_LOG_ENCAP_ID - MFF_REG0, i << 16,
                              (uint32_t) 0xFFFF << 16);
-        struct ovs_list *tuns = get_remote_tunnels(binding, ctx, encap_ip);
-        if (!ovs_list_is_empty(tuns)) {
+        struct vector tuns = get_remote_tunnels(binding, ctx, encap_ip);
+        if (!vector_is_empty(&tuns)) {
             bool is_vtep_port = type == LP_VTEP;
             /* rewrite MFF_IN_PORT to bypass OpenFlow loopback check for ARP/ND
              * responder in L3 networks. */
@@ -492,24 +481,18 @@ put_remote_port_redirect_overlay(const struct 
sbrec_port_binding *binding,
                          ofpacts_clone);
             }
 
-            struct tunnel *tun;
-            LIST_FOR_EACH (tun, list_node, tuns) {
-                put_encapsulation(ctx->mff_ovn_geneve, tun->tun,
-                                  binding->datapath, port_key, is_vtep_port,
-                                  ofpacts_clone);
-                ofpact_put_OUTPUT(ofpacts_clone)->port = tun->tun->ofport;
+            const struct chassis_tunnel *tun;
+            VECTOR_FOR_EACH (&tuns, tun) {
+                put_encapsulation(ctx->mff_ovn_geneve, tun, binding->datapath,
+                                  port_key, is_vtep_port, ofpacts_clone);
+                ofpact_put_OUTPUT(ofpacts_clone)->port = tun->ofport;
             }
             put_resubmit(OFTABLE_LOCAL_OUTPUT, ofpacts_clone);
             ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 100,
                             binding->header_.uuid.parts[0], match,
                             ofpacts_clone, &binding->header_.uuid);
         }
-        struct tunnel *tun_elem;
-        LIST_FOR_EACH_POP (tun_elem, list_node, tuns) {
-            free(tun_elem);
-        }
-        free(tuns);
-
+        vector_destroy(&tuns);
         ofpbuf_delete(ofpacts_clone);
     }
 }
@@ -1612,7 +1595,7 @@ get_tunnel_overhead(struct chassis_tunnel const *tun)
 
 static uint16_t
 get_effective_mtu(const struct sbrec_port_binding *mcp,
-                  struct ovs_list *remote_tunnels,
+                  struct vector *remote_tunnels,
                   const struct if_status_mgr *if_mgr)
 {
     /* Use interface MTU as a base for calculation */
@@ -1624,9 +1607,9 @@ get_effective_mtu(const struct sbrec_port_binding *mcp,
 
     /* Iterate over all peer tunnels and find the biggest tunnel overhead */
     uint16_t overhead = 0;
-    struct tunnel *tun;
-    LIST_FOR_EACH (tun, list_node, remote_tunnels) {
-        overhead = MAX(overhead, get_tunnel_overhead(tun->tun));
+    const struct chassis_tunnel *tun;
+    VECTOR_FOR_EACH (remote_tunnels, tun) {
+        overhead = MAX(overhead, get_tunnel_overhead(tun));
     }
     if (!overhead) {
         return 0;
@@ -1656,7 +1639,7 @@ handle_pkt_too_big_for_ip_version(struct 
ovn_desired_flow_table *flow_table,
 
 static void
 handle_pkt_too_big(struct ovn_desired_flow_table *flow_table,
-                   struct ovs_list *remote_tunnels,
+                   struct vector *remote_tunnels,
                    const struct sbrec_port_binding *binding,
                    const struct sbrec_port_binding *mcp,
                    const struct if_status_mgr *if_mgr)
@@ -1681,9 +1664,9 @@ enforce_tunneling_for_multichassis_ports(
         return;
     }
 
-    struct ovs_list *tuns = get_remote_tunnels(binding, ctx, NULL);
-    if (ovs_list_is_empty(tuns)) {
-        free(tuns);
+    struct vector tuns = get_remote_tunnels(binding, ctx, NULL);
+    if (vector_is_empty(&tuns)) {
+        vector_destroy(&tuns);
         return;
     }
 
@@ -1708,26 +1691,20 @@ enforce_tunneling_for_multichassis_ports(
         match_outport_dp_and_port_keys(&match, dp_key, port_key);
         match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, mcp->tunnel_key);
 
-        struct tunnel *tun;
-        LIST_FOR_EACH (tun, list_node, tuns) {
-            put_encapsulation(ctx->mff_ovn_geneve, tun->tun,
-                              binding->datapath, port_key, is_vtep_port,
-                              &ofpacts);
-            ofpact_put_OUTPUT(&ofpacts)->port = tun->tun->ofport;
+        const struct chassis_tunnel *tun;
+        VECTOR_FOR_EACH (&tuns, tun) {
+            put_encapsulation(ctx->mff_ovn_geneve, tun, binding->datapath,
+                              port_key, is_vtep_port, &ofpacts);
+            ofpact_put_OUTPUT(&ofpacts)->port = tun->ofport;
         }
         ofctrl_add_flow(flow_table, OFTABLE_REMOTE_OUTPUT, 110,
                         binding->header_.uuid.parts[0], &match, &ofpacts,
                         &binding->header_.uuid);
         ofpbuf_uninit(&ofpacts);
 
-        handle_pkt_too_big(flow_table, tuns, binding, mcp, ctx->if_mgr);
-    }
-
-    struct tunnel *tun_elem;
-    LIST_FOR_EACH_POP (tun_elem, list_node, tuns) {
-        free(tun_elem);
+        handle_pkt_too_big(flow_table, &tuns, binding, mcp, ctx->if_mgr);
     }
-    free(tuns);
+    vector_destroy(&tuns);
 }
 
 static void
diff --git a/controller/route-exchange-netlink.c 
b/controller/route-exchange-netlink.c
index ad0c25989..83deb13e6 100644
--- a/controller/route-exchange-netlink.c
+++ b/controller/route-exchange-netlink.c
@@ -31,6 +31,7 @@
 #include "ovn-util.h"
 #include "route-table.h"
 #include "route.h"
+#include "vec.h"
 
 #include "route-exchange-netlink.h"
 
@@ -188,19 +189,10 @@ re_nl_delete_route(uint32_t table_id, const struct 
in6_addr *dst,
     return modify_route(RTM_DELROUTE, 0, table_id, dst, plen, priority);
 }
 
-void
-re_nl_learned_routes_destroy(struct ovs_list *learned_routes)
-{
-    struct re_nl_received_route_node *rr;
-    LIST_FOR_EACH_POP (rr, list_node, learned_routes) {
-        free(rr);
-    }
-}
-
 struct route_msg_handle_data {
     const struct sbrec_datapath_binding *db;
     struct hmapx *routes_to_advertise;
-    struct ovs_list *learned_routes;
+    struct vector *learned_routes;
     const struct hmap *routes;
 };
 
@@ -227,14 +219,17 @@ handle_route_msg(const struct route_table_msg *msg, void 
*data)
                  * As we just want to learn remote routes we do not need it.*/
                 continue;
             }
-            struct re_nl_received_route_node *rr = xmalloc(sizeof *rr);
-            rr->db = handle_data->db;
-            rr->prefix = rd->rta_dst;
-            rr->plen = rd->rtm_dst_len;
-            rr->nexthop = nexthop->addr;
-            memcpy(rr->ifname, nexthop->ifname, IFNAMSIZ);
-            rr->ifname[IFNAMSIZ] = 0;
-            ovs_list_push_back(handle_data->learned_routes, &rr->list_node);
+            struct re_nl_received_route_node rr;
+            rr = (struct re_nl_received_route_node) {
+                .db = handle_data->db,
+                .prefix = rd->rta_dst,
+                .plen = rd->rtm_dst_len,
+                .nexthop = nexthop->addr,
+            };
+            memcpy(rr.ifname, nexthop->ifname, IFNAMSIZ);
+            rr.ifname[IFNAMSIZ] = '\0';
+
+            vector_push(handle_data->learned_routes, &rr);
         }
         return;
     }
@@ -266,7 +261,7 @@ handle_route_msg(const struct route_table_msg *msg, void 
*data)
 
 void
 re_nl_sync_routes(uint32_t table_id, const struct hmap *routes,
-                  struct ovs_list *learned_routes,
+                  struct vector *learned_routes,
                   const struct sbrec_datapath_binding *db)
 {
     struct hmapx routes_to_advertise = HMAPX_INITIALIZER(&routes_to_advertise);
diff --git a/controller/route-exchange-netlink.h 
b/controller/route-exchange-netlink.h
index de59d87a5..e37cfe711 100644
--- a/controller/route-exchange-netlink.h
+++ b/controller/route-exchange-netlink.h
@@ -19,7 +19,6 @@
 #define ROUTE_EXCHANGE_NETLINK_H 1
 
 #include <stdint.h>
-#include "openvswitch/list.h"
 #include <netinet/in.h>
 #include <net/if.h>
 
@@ -31,10 +30,10 @@
 
 struct in6_addr;
 struct hmap;
+struct vector;
 
 struct re_nl_received_route_node {
     const struct sbrec_datapath_binding *db;
-    struct ovs_list list_node;
     struct in6_addr prefix;
     unsigned int plen;
     struct in6_addr nexthop;
@@ -52,9 +51,8 @@ int re_nl_delete_route(uint32_t table_id, const struct 
in6_addr *dst,
 
 void re_nl_dump(uint32_t table_id);
 
-void re_nl_learned_routes_destroy(struct ovs_list *learned_routes);
 void re_nl_sync_routes(uint32_t table_id, const struct hmap *routes,
-                       struct ovs_list *learned_routes,
+                       struct vector *learned_routes,
                        const struct sbrec_datapath_binding *db);
 
 void re_nl_cleanup_routes(uint32_t table_id);
diff --git a/controller/route-exchange.c b/controller/route-exchange.c
index 98ce93d43..79a046f60 100644
--- a/controller/route-exchange.c
+++ b/controller/route-exchange.c
@@ -132,7 +132,7 @@ route_lookup(struct hmap *route_map,
 }
 
 static void
-sb_sync_learned_routes(const struct ovs_list *learned_routes,
+sb_sync_learned_routes(const struct vector *learned_routes,
                        const struct sbrec_datapath_binding *datapath,
                        const struct smap *bound_ports,
                        struct ovsdb_idl_txn *ovnsb_idl_txn,
@@ -160,7 +160,7 @@ sb_sync_learned_routes(const struct ovs_list 
*learned_routes,
     sbrec_learned_route_index_destroy_row(filter);
 
     struct re_nl_received_route_node *learned_route;
-    LIST_FOR_EACH (learned_route, list_node, learned_routes) {
+    VECTOR_FOR_EACH_PTR (learned_routes, learned_route) {
         char *ip_prefix = normalize_v46_prefix(&learned_route->prefix,
                                                learned_route->plen);
         char *nexthop = normalize_v46(&learned_route->nexthop);
@@ -240,8 +240,8 @@ route_exchange_run(const struct route_exchange_ctx_in 
*r_ctx_in,
 
         maintained_route_table_add(table_id);
 
-        struct ovs_list received_routes =
-            OVS_LIST_INITIALIZER(&received_routes);
+        struct vector received_routes =
+            VECTOR_EMPTY_INITIALIZER(struct re_nl_received_route_node);
 
         re_nl_sync_routes(ad->db->tunnel_key, &ad->routes,
                           &received_routes, ad->db);
@@ -254,7 +254,7 @@ route_exchange_run(const struct route_exchange_ctx_in 
*r_ctx_in,
         route_table_add_watch_request(&r_ctx_out->route_table_watches,
                                       table_id);
 
-        re_nl_learned_routes_destroy(&received_routes);
+        vector_destroy(&received_routes);
     }
 
     /* Remove routes in tables previously maintained by us. */
diff --git a/controller/test-ofctrl-seqno.c b/controller/test-ofctrl-seqno.c
index cd3821e04..7d478c033 100644
--- a/controller/test-ofctrl-seqno.c
+++ b/controller/test-ofctrl-seqno.c
@@ -22,12 +22,6 @@
 
 #include "ofctrl-seqno.h"
 
-static void
-test_init(void)
-{
-    ofctrl_seqno_init();
-}
-
 static int
 test_seqno_compare(size_t a, size_t b, void *values_)
 {
@@ -55,20 +49,20 @@ test_dump_acked_seqnos(size_t seqno_type)
     printf("ofctrl-seqno-type: %"PRIuSIZE"\n", seqno_type);
     printf("  last-acked %"PRIu64"\n", acked_seqnos->last_acked);
 
-    size_t n_acked = hmap_count(&acked_seqnos->acked);
+    size_t n_acked = vector_len(&acked_seqnos->acked);
     uint64_t *acked = xmalloc(n_acked * sizeof *acked);
-    struct ofctrl_ack_seqno *ack_seqno;
     size_t i = 0;
 
     /* A bit hacky but ignoring overflows the "total of all seqno + 1" should
      * be a number that is not part of the acked seqnos.
      */
     uint64_t total_seqno = 1;
-    HMAP_FOR_EACH (ack_seqno, node, &acked_seqnos->acked) {
-        ovs_assert(ofctrl_acked_seqnos_contains(acked_seqnos,
-                                                ack_seqno->seqno));
-        total_seqno += ack_seqno->seqno;
-        acked[i++] = ack_seqno->seqno;
+
+    uint64_t ack_seqno;
+    VECTOR_FOR_EACH (&acked_seqnos->acked, ack_seqno) {
+        ovs_assert(ofctrl_acked_seqnos_contains(acked_seqnos, ack_seqno));
+        total_seqno += ack_seqno;
+        acked[i++] = ack_seqno;
     }
     ovs_assert(!ofctrl_acked_seqnos_contains(acked_seqnos, total_seqno));
 
@@ -87,14 +81,14 @@ test_ofctrl_seqno_add_type(struct ovs_cmdl_context *ctx)
 {
     unsigned int n_types;
 
-    test_init();
-
     if (!test_read_uint_value(ctx, 1, "n_types", &n_types)) {
         return;
     }
     for (unsigned int i = 0; i < n_types; i++) {
         printf("%"PRIuSIZE"\n", ofctrl_seqno_add_type());
     }
+
+    ofctrl_seqno_destroy();
 }
 
 static void
@@ -105,7 +99,6 @@ test_ofctrl_seqno_ack_seqnos(struct ovs_cmdl_context *ctx)
     unsigned int n_types;
     unsigned int n_acks;
 
-    test_init();
     bool batch_acks = !strcmp(ctx->argv[1], "true");
 
     if (!test_read_uint_value(ctx, shift++, "n_types", &n_types)) {
@@ -157,6 +150,8 @@ test_ofctrl_seqno_ack_seqnos(struct ovs_cmdl_context *ctx)
             test_dump_acked_seqnos(st);
         }
     }
+
+    ofctrl_seqno_destroy();
 }
 
 static void
-- 
2.49.0

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to