On Wed, Apr 30, 2025 at 7:54 AM Ales Musil <amu...@redhat.com> wrote:
> The vector has the same functionality as the x2nrealloc > for insert. Use vector instead which slightly simplifies > the final code. > > 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. > --- > northd/en-advertised-route-sync.c | 41 ++-- > northd/en-lr-nat.c | 17 +- > northd/en-multicast.c | 47 ++--- > northd/en-multicast.h | 3 +- > northd/northd.c | 321 ++++++++++++++---------------- > northd/northd.h | 19 +- > 6 files changed, 207 insertions(+), 241 deletions(-) > > diff --git a/northd/en-advertised-route-sync.c > b/northd/en-advertised-route-sync.c > index 0f5c5e403..75fbbd942 100644 > --- a/northd/en-advertised-route-sync.c > +++ b/northd/en-advertised-route-sync.c > @@ -338,11 +338,8 @@ build_nat_connected_routes( > struct ovn_datapath *peer_od = op->peer->od; > ovs_assert(peer_od->nbs || peer_od->nbr); > > - const struct ovn_port *peer_port = NULL; > /* This is a directly connected LR peer. */ > if (peer_od->nbr) { > - peer_port = op->peer; > - > const struct lr_stateful_record *peer_lr_stateful = > lr_stateful_table_find_by_index(lr_stateful_table, > peer_od->index); > @@ -358,16 +355,16 @@ build_nat_connected_routes( > > /* This peer is LSP, we need to check all connected router ports > * for NAT.*/ > - for (size_t i = 0; i < peer_od->n_router_ports; i++) { > - peer_port = peer_od->router_ports[i]->peer; > - if (peer_port == op) { > + const struct ovn_port *rp; > + VECTOR_FOR_EACH (&peer_od->router_ports, rp) { > + if (rp->peer == op) { > /* Skip advertising router. */ > continue; > } > > const struct lr_stateful_record *peer_lr_stateful = > lr_stateful_table_find_by_index(lr_stateful_table, > - peer_port->od->index); > + rp->peer->od->index); > if (!peer_lr_stateful) { > continue; > } > @@ -423,30 +420,28 @@ build_lb_connected_routes(const struct ovn_datapath > *od, > ovs_assert(peer_od->nbs || peer_od->nbr); > > const struct lr_stateful_record *lr_stateful_rec; > - const struct ovn_port *peer_port = NULL; > /* This is directly connected LR peer. */ > if (peer_od->nbr) { > lr_stateful_rec = lr_stateful_table_find_by_index( > lr_stateful_table, peer_od->index); > - peer_port = op->peer; > - build_lb_route_for_port(op, peer_port, > lr_stateful_rec->lb_ips, > + build_lb_route_for_port(op, op->peer, lr_stateful_rec->lb_ips, > routes); > return; > } > > /* This peer is LSP, we need to check all connected router ports > for > * LBs.*/ > - for (size_t i = 0; i < peer_od->n_router_ports; i++) { > - peer_port = peer_od->router_ports[i]->peer; > - if (peer_port == op) { > + struct ovn_port *rp; > + VECTOR_FOR_EACH (&peer_od->router_ports, rp) { > + if (rp->peer == op) { > /* no need to check for LBs on ovn_port that initiated > this > * function.*/ > continue; > } > lr_stateful_rec = lr_stateful_table_find_by_index( > - lr_stateful_table, peer_port->od->index); > + lr_stateful_table, rp->peer->od->index); > > - build_lb_route_for_port(op, peer_port, > lr_stateful_rec->lb_ips, > + build_lb_route_for_port(op, rp->peer, lr_stateful_rec->lb_ips, > routes); > } > } > @@ -470,14 +465,14 @@ build_lb_routes(const struct ovn_datapath *od, > * > * Advertise the LB IPs via all 'op' if this is a gateway router > or > * throuh all DGPs of this distributed router otherwise. */ > - struct ovn_port *op_ = NULL; > - size_t n_tracked_ports = !od->is_gw_router ? od->n_l3dgw_ports : > 1; > - struct ovn_port **tracked_ports = !od->is_gw_router > - ? od->l3dgw_ports > - : &op_; > - > - for (size_t i = 0; i < n_tracked_ports; i++) { > - build_lb_route_for_port(op, tracked_ports[i], lb_ips, routes); > + > + if (od->is_gw_router) { > + build_lb_route_for_port(op, NULL, lb_ips, routes); > + } else { > + struct ovn_port *dgp; > + VECTOR_FOR_EACH (&od->l3dgw_ports, dgp) { > + build_lb_route_for_port(op, dgp, lb_ips, routes); > + } > } > } > } > diff --git a/northd/en-lr-nat.c b/northd/en-lr-nat.c > index 44009ca6f..68c4d0e29 100644 > --- a/northd/en-lr-nat.c > +++ b/northd/en-lr-nat.c > @@ -295,13 +295,15 @@ lr_nat_entry_set_dgw_port(const struct ovn_datapath > *od, > /* Validate gateway_port of NAT rule. */ > nat_entry->l3dgw_port = NULL; > if (nat->gateway_port == NULL) { > - if (od->n_l3dgw_ports == 1) { > - nat_entry->l3dgw_port = od->l3dgw_ports[0]; > - } else if (od->n_l3dgw_ports > 1) { > + if (vector_len(&od->l3dgw_ports) == 1) { > + nat_entry->l3dgw_port = vector_get(&od->l3dgw_ports, 0, > + struct ovn_port *); > + } else if (vector_len(&od->l3dgw_ports) > 1) { > /* Find the DGP reachable for the NAT external IP. */ > - for (size_t i = 0; i < od->n_l3dgw_ports; i++) { > - if (lrp_find_member_ip(od->l3dgw_ports[i], > nat->external_ip)) { > - nat_entry->l3dgw_port = od->l3dgw_ports[i]; > + struct ovn_port *dgp; > + VECTOR_FOR_EACH (&od->l3dgw_ports, dgp) { > + if (lrp_find_member_ip(dgp, nat->external_ip)) { > + nat_entry->l3dgw_port = dgp; > break; > } > } > @@ -342,7 +344,8 @@ lr_nat_entry_set_dgw_port(const struct ovn_datapath > *od, > return true; > } > > - if (od->n_l3dgw_ports && nat_entry->type == DNAT_AND_SNAT && > + if (!vector_is_empty(&od->l3dgw_ports) && > + nat_entry->type == DNAT_AND_SNAT && > nat->logical_port && nat->external_mac) { > nat_entry->is_distributed = true; > } > diff --git a/northd/en-multicast.c b/northd/en-multicast.c > index 7f3a6077c..3d918f15f 100644 > --- a/northd/en-multicast.c > +++ b/northd/en-multicast.c > @@ -332,8 +332,8 @@ build_mcast_groups(struct multicast_igmp_data *data, > * The router IGMP groups are based on the groups learnt by their > * multicast enabled peers. > */ > - for (size_t i = 0; i < od->n_router_ports; i++) { > - struct ovn_port *router_port = od->router_ports[i]->peer; > + VECTOR_FOR_EACH (&od->router_ports, op) { > + struct ovn_port *router_port = op->peer; > > /* If the router the port connects to doesn't have multicast > * relay enabled or if it was already configured to flood > @@ -483,24 +483,10 @@ ovn_multicast_add_ports(struct hmap *mcgroups, > struct ovn_datapath *od, > hmap_insert(mcgroups, &mc->hmap_node, ovn_multicast_hash(od, > group)); > mc->datapath = od; > mc->group = group; > - mc->n_ports = 0; > - mc->allocated_ports = 4; > - mc->ports = xmalloc(mc->allocated_ports * sizeof *mc->ports); > + mc->ports = VECTOR_CAPACITY_INITIALIZER(struct ovn_port *, 4); > } > > - size_t n_ports_total = mc->n_ports + n_ports; > - > - if (n_ports_total > 2 * mc->allocated_ports) { > - mc->allocated_ports = n_ports_total; > - mc->ports = xrealloc(mc->ports, > - mc->allocated_ports * sizeof *mc->ports); > - } else if (n_ports_total > mc->allocated_ports) { > - mc->ports = x2nrealloc(mc->ports, &mc->allocated_ports, > - sizeof *mc->ports); > - } > - > - memcpy(&mc->ports[mc->n_ports], &ports[0], n_ports * sizeof *ports); > - mc->n_ports += n_ports; > + vector_push_array(&mc->ports, ports, n_ports); > } > > static void > @@ -521,7 +507,7 @@ ovn_multicast_destroy(struct hmap *mcgroups, struct > ovn_multicast *mc) > { > if (mc) { > hmap_remove(mcgroups, &mc->hmap_node); > - free(mc->ports); > + vector_destroy(&mc->ports); > free(mc); > } > } > @@ -530,12 +516,17 @@ static void > ovn_multicast_update_sbrec(const struct ovn_multicast *mc, > const struct sbrec_multicast_group *sb) > { > - struct sbrec_port_binding **ports = xmalloc(mc->n_ports * sizeof > *ports); > - for (size_t i = 0; i < mc->n_ports; i++) { > - ports[i] = CONST_CAST(struct sbrec_port_binding *, > mc->ports[i]->sb); > + struct vector sb_ports = > + VECTOR_CAPACITY_INITIALIZER(struct sbrec_port_binding *, > + vector_len(&mc->ports)); > + > + struct ovn_port *op; > + VECTOR_FOR_EACH (&mc->ports, op) { > + vector_push(&sb_ports, &op->sb); > } > - sbrec_multicast_group_set_ports(sb, ports, mc->n_ports); > - free(ports); > + sbrec_multicast_group_set_ports(sb, vector_get_array(&sb_ports), > + vector_len(&sb_ports)); > + vector_destroy(&sb_ports); > } > > static void > @@ -716,11 +707,11 @@ ovn_igmp_group_aggregate_ports(struct ovn_igmp_group > *igmp_group, > free(entry); > } > > - if (igmp_group->datapath->n_localnet_ports) { > + if (!vector_is_empty(&igmp_group->datapath->localnet_ports)) { > ovn_multicast_add_ports(mcast_groups, igmp_group->datapath, > - &igmp_group->mcgroup, > - igmp_group->datapath->localnet_ports, > - igmp_group->datapath->n_localnet_ports); > + &igmp_group->mcgroup, > + vector_get_array(&igmp_group->datapath->localnet_ports), > + vector_len(&igmp_group->datapath->localnet_ports)); > } > } > > diff --git a/northd/en-multicast.h b/northd/en-multicast.h > index 131c01d65..c1ff7820d 100644 > --- a/northd/en-multicast.h > +++ b/northd/en-multicast.h > @@ -43,8 +43,7 @@ struct ovn_multicast { > struct ovn_datapath *datapath; > const struct multicast_group *group; > > - struct ovn_port **ports; > - size_t n_ports, allocated_ports; > + struct vector ports; /* Vector of struct ovn_port *. */ > }; > > /* > diff --git a/northd/northd.c b/northd/northd.c > index bed05e614..464b3798a 100644 > --- a/northd/northd.c > +++ b/northd/northd.c > @@ -499,6 +499,10 @@ ovn_datapath_create(struct hmap *datapaths, const > struct uuid *key, > od->lr_group = NULL; > hmap_init(&od->ports); > sset_init(&od->router_ips); > + od->ls_peers = VECTOR_EMPTY_INITIALIZER(struct ovn_datapath *); > + od->router_ports = VECTOR_EMPTY_INITIALIZER(struct ovn_port *); > + od->l3dgw_ports = VECTOR_EMPTY_INITIALIZER(struct ovn_port *); > + od->localnet_ports = VECTOR_EMPTY_INITIALIZER(struct ovn_port *); > return od; > } > > @@ -521,10 +525,10 @@ ovn_datapath_destroy(struct hmap *datapaths, struct > ovn_datapath *od) > hmap_remove(datapaths, &od->key_node); > ovn_destroy_tnlids(&od->port_tnlids); > destroy_ipam_info(&od->ipam_info); > - free(od->router_ports); > - free(od->ls_peers); > - free(od->localnet_ports); > - free(od->l3dgw_ports); > + vector_destroy(&od->router_ports); > + vector_destroy(&od->ls_peers); > + vector_destroy(&od->localnet_ports); > + vector_destroy(&od->l3dgw_ports); > destroy_mcast_info_for_datapath(od); > destroy_ports_for_datapath(od); > sset_destroy(&od->router_ips); > @@ -593,27 +597,6 @@ ovn_datapath_from_sbrec(const struct hmap > *ls_datapaths, > return NULL; > } > > -static void > -ovn_datapath_add_router_port(struct ovn_datapath *od, struct ovn_port *op) > -{ > - if (od->n_router_ports == od->n_allocated_router_ports) { > - od->router_ports = x2nrealloc(od->router_ports, > - &od->n_allocated_router_ports, > - sizeof *od->router_ports); > - } > - od->router_ports[od->n_router_ports++] = op; > -} > - > -static void > -ovn_datapath_add_ls_peer(struct ovn_datapath *od, struct ovn_datapath > *peer) > -{ > - if (od->n_ls_peers == od->n_allocated_ls_peers) { > - od->ls_peers = x2nrealloc(od->ls_peers, &od->n_allocated_ls_peers, > - sizeof *od->ls_peers); > - } > - od->ls_peers[od->n_ls_peers++] = peer; > -} > - > static bool > lrouter_is_enabled(const struct nbrec_logical_router *lrouter) > { > @@ -1601,7 +1584,7 @@ ipam_add_port_addresses(struct ovn_datapath *od, > struct ovn_port *op) > static bool > is_nat_gateway_port(const struct nbrec_nat *nat, const struct ovn_port > *op) > { > - if (op->od->n_l3dgw_ports > 1 > + if (vector_len(&op->od->l3dgw_ports) > 1 > && ((!nat->gateway_port && !lrp_find_member_ip(op, > nat->external_ip)) > || (nat->gateway_port && nat->gateway_port != op->nbrp))) { > return false; > @@ -2302,12 +2285,7 @@ join_logical_ports_lsp(struct hmap *ports, > } > > if (lsp_is_localnet(nbsp)) { > - if (od->n_localnet_ports >= od->n_allocated_localnet_ports) { > - od->localnet_ports = x2nrealloc( > - od->localnet_ports, &od->n_allocated_localnet_ports, > - sizeof *od->localnet_ports); > - } > - od->localnet_ports[od->n_localnet_ports++] = op; > + vector_push(&od->localnet_ports, &op); > } > > if (lsp_is_vtep(nbsp)) { > @@ -2456,8 +2434,8 @@ static bool > peer_needs_cr_port_creation(struct ovn_port *op) > { > if ((op->nbrp->n_gateway_chassis || op->nbrp->ha_chassis_group) > - && op->od->n_l3dgw_ports == 1 && op->peer && op->peer->nbsp > - && !op->peer->od->n_localnet_ports) { > + && vector_len(&op->od->l3dgw_ports) == 1 && op->peer && > op->peer->nbsp > + && vector_is_empty(&op->peer->od->localnet_ports)) { > return true; > } > > @@ -2552,8 +2530,8 @@ join_logical_ports(const struct > sbrec_port_binding_table *sbrec_pb_table, > continue; > } > > - ovn_datapath_add_router_port(op->od, op); > - ovn_datapath_add_ls_peer(peer->od, op->od); > + vector_push(&op->od->router_ports, &op); > + vector_push(&peer->od->ls_peers, &op->od); > peer->peer = op; > op->peer = peer; > > @@ -2659,12 +2637,7 @@ join_logical_ports(const struct > sbrec_port_binding_table *sbrec_pb_table, > ovs_assert(crp); > > /* Add to l3dgw_ports in od, for later use during flow creation. > */ > - if (od->n_l3dgw_ports == od->n_allocated_l3dgw_ports) { > - od->l3dgw_ports = x2nrealloc(od->l3dgw_ports, > - &od->n_allocated_l3dgw_ports, > - sizeof *od->l3dgw_ports); > - } > - od->l3dgw_ports[od->n_l3dgw_ports++] = op; > + vector_push(&od->l3dgw_ports, &op); > > if (op->peer && op->peer->nbsp) { > /* Only used for the router type LSP whose peer is l3dgw_port > */ > @@ -2770,8 +2743,9 @@ get_nat_addresses(const struct ovn_port *op, size_t > *n, bool routable_only, > > /* Determine whether this NAT rule satisfies the conditions for > * distributed NAT processing. */ > - if (op->od->n_l3dgw_ports && !strcmp(nat->type, "dnat_and_snat") > - && nat->logical_port && nat->external_mac) { > + if (!vector_is_empty(&op->od->l3dgw_ports) && > + !strcmp(nat->type, "dnat_and_snat") && > + nat->logical_port && nat->external_mac) { > /* Distributed NAT rule. */ > if (eth_addr_from_string(nat->external_mac, &mac)) { > struct ds address = DS_EMPTY_INITIALIZER; > @@ -3410,8 +3384,9 @@ ovn_port_update_sbrec(struct ovsdb_idl_txn > *ovnsb_txn, > smap_clone(&options, &op->nbsp->options); > > if (queue_id) { > - if (op->od->n_localnet_ports) { > - struct ovn_port *port = op->od->localnet_ports[0]; > + if (!vector_is_empty(&op->od->localnet_ports)) { > + struct ovn_port *port = > vector_get(&op->od->localnet_ports, > + 0, struct ovn_port > *); > const char *physical_network = smap_get( > &port->nbsp->options, "network_name"); > if (physical_network) { > @@ -4090,7 +4065,8 @@ build_lswitch_lbs_from_lrouter(struct ovn_datapaths > *lr_datapaths, > HMAP_FOR_EACH (lb_dps, hmap_node, lb_dps_map) { > BITMAP_FOR_EACH_1 (index, ods_size(lr_datapaths), > lb_dps->nb_lr_map) { > struct ovn_datapath *od = lr_datapaths->array[index]; > - ovn_lb_datapaths_add_ls(lb_dps, od->n_ls_peers, od->ls_peers); > + ovn_lb_datapaths_add_ls(lb_dps, vector_len(&od->ls_peers), > + vector_get_array(&od->ls_peers)); > } > } > > @@ -4098,14 +4074,16 @@ build_lswitch_lbs_from_lrouter(struct > ovn_datapaths *lr_datapaths, > HMAP_FOR_EACH (lb_group_dps, hmap_node, lb_group_dps_map) { > for (size_t i = 0; i < lb_group_dps->n_lr; i++) { > struct ovn_datapath *od = lb_group_dps->lr[i]; > - ovn_lb_group_datapaths_add_ls(lb_group_dps, od->n_ls_peers, > - od->ls_peers); > + ovn_lb_group_datapaths_add_ls(lb_group_dps, > + vector_len(&od->ls_peers), > + > vector_get_array(&od->ls_peers)); > for (size_t j = 0; j < lb_group_dps->lb_group->n_lbs; j++) { > const struct uuid *lb_uuid = > &lb_group_dps->lb_group->lbs[j]->nlb->header_.uuid; > lb_dps = ovn_lb_datapaths_find(lb_dps_map, lb_uuid); > ovs_assert(lb_dps); > - ovn_lb_datapaths_add_ls(lb_dps, od->n_ls_peers, > od->ls_peers); > + ovn_lb_datapaths_add_ls(lb_dps, vector_len(&od->ls_peers), > + vector_get_array(&od->ls_peers)); > } > } > } > @@ -4170,12 +4148,13 @@ should_add_router_port_garp(const struct ovn_port > *op, const char *chassis) > } > > bool add_router_port_garp = false; > - if (op->peer && op->peer->nbrp && op->peer->od->n_l3dgw_ports) { > + if (op->peer && op->peer->nbrp && > + !vector_is_empty(&op->peer->od->l3dgw_ports)) { > if (lrp_is_l3dgw(op->peer)) { > add_router_port_garp = true; > } else if (smap_get_bool(&op->peer->nbrp->options, > "reside-on-redirect-chassis", false)) { > - if (op->peer->od->n_l3dgw_ports == 1) { > + if (vector_len(&op->peer->od->l3dgw_ports) == 1) { > add_router_port_garp = true; > } else { > static struct vlog_rate_limit rl = > @@ -4187,10 +4166,10 @@ should_add_router_port_garp(const struct ovn_port > *op, const char *chassis) > "option can only be used when there is " > "a single distributed gateway port.", > op->peer->key, op->peer->od->nbr->name, > - op->peer->od->n_l3dgw_ports); > + vector_len(&op->peer->od->l3dgw_ports)); > } > } > - } else if (chassis && op->od->n_localnet_ports) { > + } else if (chassis && !vector_is_empty(&op->od->localnet_ports)) { > add_router_port_garp = true; > } > > @@ -4217,10 +4196,10 @@ sync_pb_for_lsp(struct ovn_port *op, > size_t n_nats = 0; > char **nats = NULL; > bool l3dgw_ports = op->peer && op->peer->od && > - op->peer->od->n_l3dgw_ports; > + !vector_is_empty(&op->peer->od->l3dgw_ports); > if (nat_addresses && !strcmp(nat_addresses, "router")) { > if (op->peer && op->peer->od > - && (chassis || op->peer->od->n_l3dgw_ports)) { > + && (chassis || > !vector_is_empty(&op->peer->od->l3dgw_ports))) { > bool include_lb_vips = !smap_get_bool(&op->nbsp->options, > "exclude-lb-vips-from-garp", false); > > @@ -4249,7 +4228,8 @@ sync_pb_for_lsp(struct ovn_port *op, > const struct ovn_port *l3dgw_port = ( > lrp_is_l3dgw(op->peer) > ? op->peer > - : op->peer->od->l3dgw_ports[0]); > + : vector_get(&op->peer->od->l3dgw_ports, 0, > + struct ovn_port *)); > ds_put_format(&nat_addr, " is_chassis_resident(%s)", > l3dgw_port->cr_port->json_key); > } > @@ -4286,11 +4266,12 @@ sync_pb_for_lsp(struct ovn_port *op, > > op->peer->lrp_networks.ipv4_addrs[i].addr_s); > } > > - if (op->peer->od->n_l3dgw_ports) { > + if (!vector_is_empty(&op->peer->od->l3dgw_ports)) { > const struct ovn_port *l3dgw_port = ( > lrp_is_l3dgw(op->peer) > ? op->peer > - : op->peer->od->l3dgw_ports[0]); > + : vector_get(&op->peer->od->l3dgw_ports, 0, > + struct ovn_port *)); > ds_put_format(&garp_info, " is_chassis_resident(%s)", > l3dgw_port->cr_port->json_key); > } > @@ -4999,8 +4980,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn > *ovnsb_idl_txn, > return true; > } > > - bool ls_had_only_router_ports = (od->n_router_ports > - && (od->n_router_ports == hmap_count(&od->ports))); > + bool ls_had_only_router_ports = (!vector_is_empty(&od->router_ports) > + && (vector_len(&od->router_ports) == hmap_count(&od->ports))); > > struct ovn_port *op; > HMAP_FOR_EACH (op, dp_node, &od->ports) { > @@ -5102,8 +5083,8 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn > *ovnsb_idl_txn, > } > } > > - bool ls_has_only_router_ports = (od->n_router_ports > - && (od->n_router_ports == hmap_count(&od->ports))); > + bool ls_has_only_router_ports = (!vector_is_empty(&od->router_ports) > + && (vector_len(&od->router_ports) == > hmap_count(&od->ports))); > > /* There are lflows related to router ports that depend on whether > * there are switch ports on the logical switch (see > @@ -5112,8 +5093,7 @@ ls_handle_lsp_changes(struct ovsdb_idl_txn > *ovnsb_idl_txn, > * to the tracked 'updated' ovn ports so that lflow engine can > * regenerate lflows for these router ports. */ > if (ls_had_only_router_ports != ls_has_only_router_ports) { > - for (size_t i = 0; i < od->n_router_ports; i++) { > - op = od->router_ports[i]; > + VECTOR_FOR_EACH (&od->router_ports, op) { > add_op_to_northd_tracked_ports(&trk_lsps->updated, op); > } > } > @@ -6058,7 +6038,8 @@ build_lswitch_port_sec_op(struct ovn_port *op, > struct lflow_table *lflows, > op->key, &op->nbsp->header_, > op->lflow_ref); > > - if (!lsp_is_localnet(op->nbsp) && !op->od->n_localnet_ports) { > + if (!lsp_is_localnet(op->nbsp) && > + vector_is_empty(&op->od->localnet_ports)) { > return; > } > > @@ -6073,16 +6054,15 @@ build_lswitch_port_sec_op(struct ovn_port *op, > struct lflow_table *lflows, > ds_cstr(match), > ds_cstr(actions), > op->key, &op->nbsp->header_, > op->lflow_ref); > - } else if (op->od->n_localnet_ports) { > + } else if (!vector_is_empty(&op->od->localnet_ports)) { > + const struct ovn_port *lp = > vector_get(&op->od->localnet_ports, 0, > + struct ovn_port *); > ds_put_format(match, "outport == %s && inport == %s", > - op->od->localnet_ports[0]->json_key, > - op->json_key); > + lp->json_key, op->json_key); > ovn_lflow_add_with_lport_and_hint(lflows, op->od, > S_SWITCH_OUT_APPLY_PORT_SEC, 110, > ds_cstr(match), ds_cstr(actions), > - op->od->localnet_ports[0]->key, > - &op->od->localnet_ports[0]->nbsp->header_, > - op->lflow_ref); > + lp->key, &lp->nbsp->header_, op->lflow_ref); > } > } else if (lsp_is_router(op->nbsp)) { > ds_put_format(actions, REGBIT_FROM_ROUTER_PORT" = 1; next;"); > @@ -6304,8 +6284,8 @@ build_ls_stateful_rec_pre_acls( > * send IP packets for some (allow) filters through the conntrack > action, > * which handles defragmentation, in order to match L4 headers. */ > if (ls_stateful_rec->has_stateful_acl) { > - for (size_t i = 0; i < od->n_router_ports; i++) { > - struct ovn_port *op = od->router_ports[i]; > + struct ovn_port *op; > + VECTOR_FOR_EACH (&od->router_ports, op) { > if (op->enable_router_port_acl) { > continue; > } > @@ -6313,11 +6293,11 @@ build_ls_stateful_rec_pre_acls( > S_SWITCH_IN_PRE_ACL, > S_SWITCH_OUT_PRE_ACL, > 110, lflows, lflow_ref); > } > - for (size_t i = 0; i < od->n_localnet_ports; i++) { > - skip_port_from_conntrack(od, od->localnet_ports[i], true, > - S_SWITCH_IN_PRE_ACL, > - S_SWITCH_OUT_PRE_ACL, > - 110, lflows, lflow_ref); > + struct ovn_port *lp; > + VECTOR_FOR_EACH (&od->localnet_ports, lp) { > + skip_port_from_conntrack(od, lp, true, S_SWITCH_IN_PRE_ACL, > + S_SWITCH_OUT_PRE_ACL, 110, lflows, > + lflow_ref); > } > > /* stateless filters always take precedence over stateful ACLs. */ > @@ -6515,9 +6495,9 @@ build_ls_stateful_rec_pre_lb(const struct > ls_stateful_record *ls_stateful_rec, > struct lflow_table *lflows, > struct lflow_ref *lflow_ref) > { > - for (size_t i = 0; i < od->n_router_ports; i++) { > - skip_port_from_conntrack(od, od->router_ports[i], > - ls_stateful_rec->has_stateful_acl, > + struct ovn_port *op; > + VECTOR_FOR_EACH (&od->router_ports, op) { > + skip_port_from_conntrack(od, op, > ls_stateful_rec->has_stateful_acl, > S_SWITCH_IN_PRE_LB, S_SWITCH_OUT_PRE_LB, > 110, lflows, lflow_ref); > } > @@ -6528,9 +6508,9 @@ build_ls_stateful_rec_pre_lb(const struct > ls_stateful_record *ls_stateful_rec, > * balanced. > */ > if (!ls_stateful_rec->has_lb_vip) { > - for (size_t i = 0; i < od->n_localnet_ports; i++) { > - skip_port_from_conntrack(od, od->localnet_ports[i], > - ls_stateful_rec->has_stateful_acl, > + struct ovn_port *lp; > + VECTOR_FOR_EACH (&od->localnet_ports, lp) { > + skip_port_from_conntrack(od, lp, > ls_stateful_rec->has_stateful_acl, > S_SWITCH_IN_PRE_LB, > S_SWITCH_OUT_PRE_LB, > 110, lflows, lflow_ref); > } > @@ -8721,8 +8701,9 @@ build_vtep_hairpin(struct ovn_datapath *od, struct > lflow_table *lflows, > * current chassis, should be passed to next table for ARP/ND hairpin > * processing. */ > struct ds match = DS_EMPTY_INITIALIZER; > - for (int i = 0; i < od->n_router_ports; i++) { > - struct ovn_port *op = od->router_ports[i]->peer; > + struct ovn_port *rp; > + VECTOR_FOR_EACH (&od->router_ports, rp) { > + struct ovn_port *op = rp->peer; > if (lrp_is_l3dgw(op)) { > ds_clear(&match); > ds_put_format(&match, > @@ -8825,8 +8806,9 @@ build_lrouter_groups__(struct hmap *lr_ports, struct > ovn_datapath *od) > /* For logical router with distributed gateway ports. If it > * has HA_Chassis_Group associated to it in SB DB, then store the > * ha chassis group name. */ > - for (size_t i = 0; i < od->n_l3dgw_ports; i++) { > - struct ovn_port *crp = od->l3dgw_ports[i]->cr_port; > + struct ovn_port *dgp; > + VECTOR_FOR_EACH (&od->l3dgw_ports, dgp) { > + struct ovn_port *crp = dgp->cr_port; > if (crp->sb->ha_chassis_group && > crp->sb->ha_chassis_group->n_ha_chassis > 1) { > sset_add(&od->lr_group->ha_chassis_groups, > @@ -8852,15 +8834,16 @@ build_lrouter_groups__(struct hmap *lr_ports, > struct ovn_datapath *od) > build_lrouter_groups__(lr_ports, peer_dp); > } > } else { > - for (size_t j = 0; j < peer_dp->n_router_ports; j++) { > - if (!peer_dp->router_ports[j]->peer) { > + struct ovn_port *op; > + VECTOR_FOR_EACH (&peer_dp->router_ports, op) { > + if (!op->peer) { > /* If there is no peer port connecting to the > * router port, ignore it. */ > continue; > } > > struct ovn_datapath *router_dp; > - router_dp = peer_dp->router_ports[j]->peer->od; > + router_dp = op->peer->od; > if (router_dp == od) { > continue; > } > @@ -9056,7 +9039,7 @@ build_lswitch_rport_arp_req_flow( > /* Send a the packet to the router pipeline. If the switch has > non-router > * ports then flood it there as well. > */ > - if (od->n_router_ports != od->nbs->n_ports) { > + if (vector_len(&od->router_ports) != od->nbs->n_ports) { > ds_put_format(&actions, "clone {outport = %s; output; }; " > "outport = \""MC_FLOOD_L2"\"; output;", > patch_op->json_key); > @@ -9078,7 +9061,7 @@ build_lswitch_rport_arp_req_flow( > ds_put_format(&match, "%s && !is_chassis_resident(%s)", > ds_cstr(&m), > patch_op->cr_port->json_key); > ds_clear(&actions); > - if (od->n_router_ports != od->nbs->n_ports) { > + if (vector_len(&od->router_ports) != od->nbs->n_ports) { > ds_put_format(&actions, "clone {outport = %s; output; }; " > "outport = \""MC_FLOOD_L2"\"; > output;", > patch_op->cr_port->json_key); > @@ -9206,7 +9189,7 @@ build_lswitch_rport_arp_req_flows_for_lbnats( > * > * Priority: 75. > */ > - if (sw_od->n_router_ports != sw_od->nbs->n_ports) { > + if (vector_len(&sw_od->router_ports) != sw_od->nbs->n_ports) { > build_lswitch_rport_arp_req_self_orig_flow(op, 75, sw_od, > > lr_stateful_rec->lrnat_rec, > lflows, lflow_ref); > @@ -9496,7 +9479,7 @@ build_lswitch_dhcp_relay_flows(struct ovn_port *op, > return; > } > > - if (!op->od || !op->od->n_router_ports || !op->od->nbs) { > + if (!op->od || vector_is_empty(&op->od->router_ports) || > !op->od->nbs) { > return; > } > > @@ -9566,8 +9549,8 @@ > build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, > struct ds match = DS_EMPTY_INITIALIZER; > > for (size_t i = 0; i < op->n_lsp_addrs; i++) { > - for (size_t j = 0; j < op->od->n_router_ports; j++) { > - struct ovn_port *rp = op->od->router_ports[j]; > + struct ovn_port *rp; > + VECTOR_FOR_EACH (&op->od->router_ports, rp) { > for (size_t k = 0; k < rp->n_lsp_addrs; k++) { > for (size_t l = 0; l < rp->lsp_addrs[k].n_ipv4_addrs; > l++) { > ds_clear(&match); > @@ -10187,7 +10170,7 @@ build_lswitch_dhcp_options_and_response(struct > ovn_port *op, > } > > bool is_external = lsp_is_external(op->nbsp); > - if (is_external && (!op->od->n_localnet_ports || > + if (is_external && (vector_is_empty(&op->od->localnet_ports) || > !op->nbsp->ha_chassis_group)) { > /* If it's an external port and there are no localnet ports > * and if it doesn't belong to an HA chassis group ignore it. */ > @@ -10196,14 +10179,13 @@ build_lswitch_dhcp_options_and_response(struct > ovn_port *op, > > for (size_t i = 0; i < op->n_lsp_addrs; i++) { > if (is_external) { > - for (size_t j = 0; j < op->od->n_localnet_ports; j++) { > + struct ovn_port *lp; > + VECTOR_FOR_EACH (&op->od->localnet_ports, lp) { > build_dhcpv4_options_flows( > - op, &op->lsp_addrs[i], > - op->od->localnet_ports[j], is_external, > + op, &op->lsp_addrs[i], lp, is_external, > meter_groups, lflows, op->lflow_ref); > build_dhcpv6_options_flows( > - op, &op->lsp_addrs[i], > - op->od->localnet_ports[j], is_external, > + op, &op->lsp_addrs[i], lp, is_external, > meter_groups, lflows, op->lflow_ref); > } > } else { > @@ -10284,10 +10266,10 @@ build_lswitch_external_port(struct ovn_port *op, > if (!lsp_is_external(op->nbsp)) { > return; > } > - for (size_t i = 0; i < op->od->n_localnet_ports; i++) { > - build_drop_arp_nd_flows_for_unbound_router_ports( > - op, op->od->localnet_ports[i], lflows, > - op->lflow_ref); > + struct ovn_port *lp; > + VECTOR_FOR_EACH (&op->od->localnet_ports, lp) { > + build_drop_arp_nd_flows_for_unbound_router_ports(op, lp, lflows, > + op->lflow_ref); > } > } > > @@ -10524,7 +10506,8 @@ build_lswitch_ip_unicast_lookup(struct ovn_port > *op, > ds_put_format(match, "eth.dst == %s", > op->peer->lrp_networks.ea_s); > } > > - if (op->peer->od->n_l3dgw_ports && op->od->n_localnet_ports) { > + if (!vector_is_empty(&op->peer->od->l3dgw_ports) && > + !vector_is_empty(&op->od->localnet_ports)) { > bool add_chassis_resident_check = false; > const char *json_key; > if (lrp_is_l3dgw(op->peer)) { > @@ -10545,8 +10528,9 @@ build_lswitch_ip_unicast_lookup(struct ovn_port > *op, > add_chassis_resident_check = smap_get_bool( > &op->peer->nbrp->options, > "reside-on-redirect-chassis", false) && > - op->peer->od->n_l3dgw_ports == 1; > - json_key = > op->peer->od->l3dgw_ports[0]->cr_port->json_key; > + vector_len(&op->peer->od->l3dgw_ports) == 1; > + json_key = vector_get(&op->peer->od->l3dgw_ports, 0, > + struct ovn_port > *)->cr_port->json_key; > } > > if (add_chassis_resident_check) { > @@ -12546,16 +12530,16 @@ build_lrouter_nat_flows_for_lb( > type = LROUTER_NAT_LB_FLOW_NORMAL; > } > > - if (!od->n_l3dgw_ports) { > + if (vector_is_empty(&od->l3dgw_ports)) { > bitmap_set1(gw_dp_bitmap[type], index); > } else { > /* Create stateless LB NAT rules when using multiple DGPs and > * use_stateless_nat is true. > */ > - bool stateless_nat = (od->n_l3dgw_ports > 1) > + bool stateless_nat = (vector_len(&od->l3dgw_ports) > 1) > ? use_stateless_nat : false; > - for (size_t i = 0; i < od->n_l3dgw_ports; i++) { > - struct ovn_port *dgp = od->l3dgw_ports[i]; > + struct ovn_port *dgp; > + VECTOR_FOR_EACH (&od->l3dgw_ports, dgp) { > build_distr_lrouter_nat_flows_for_lb(&ctx, type, od, > lb_dps->lflow_ref, > dgp, > stateless_nat); > @@ -12873,7 +12857,7 @@ lrouter_nat_get_priority(const struct ovn_datapath > *od, > * nat->logical_ip with the longest mask gets a higher > * priority. */ > uint16_t priority = prefix_len + 1; > - if (!od->is_gw_router && od->n_l3dgw_ports) { > + if (!od->is_gw_router && !vector_is_empty(&od->l3dgw_ports)) { > priority += 128; > } > > @@ -13560,9 +13544,9 @@ build_gateway_get_l2_hdr_size(struct ovn_port *op) > /* Check if vlans are enabled on a localnet port running the > logical > * switch connected to this logical router. > */ > - for (size_t i = 0; i < peer->od->n_localnet_ports; i++) { > - struct ovn_port *localnet_port = peer->od->localnet_ports[i]; > - const struct nbrec_logical_switch_port *nbsp = > localnet_port->nbsp; > + struct ovn_port *lp; > + VECTOR_FOR_EACH (&peer->od->localnet_ports, lp) { > + const struct nbrec_logical_switch_port *nbsp = lp->nbsp; > > if (!nbsp || !nbsp->tag_request) { > continue; > @@ -14813,7 +14797,8 @@ build_arp_resolve_flows_for_lsp( > return; > } > > - if (op->od->n_router_ports && !lsp_is_router(op->nbsp) > + struct ovn_port *rp; > + if (!vector_is_empty(&op->od->router_ports) && > !lsp_is_router(op->nbsp) > && strcmp(op->nbsp->type, "virtual")) { > /* This is a logical switch port that backs a VM or a container. > * Extract its addresses. For each of the address, go through all > @@ -14825,12 +14810,11 @@ build_arp_resolve_flows_for_lsp( > const char *ea_s = op->lsp_addrs[i].ea_s; > for (size_t j = 0; j < op->lsp_addrs[i].n_ipv4_addrs; j++) { > const char *ip_s = op->lsp_addrs[i].ipv4_addrs[j].addr_s; > - for (size_t k = 0; k < op->od->n_router_ports; k++) { > + VECTOR_FOR_EACH (&op->od->router_ports, rp) { > /* Get the Logical_Router_Port that the > * Logical_Switch_Port is connected to, as > * 'peer'. */ > - struct ovn_port *peer = ovn_port_get_peer( > - lr_ports, op->od->router_ports[k]); > + struct ovn_port *peer = ovn_port_get_peer(lr_ports, > rp); > if (!peer || !peer->nbrp) { > continue; > } > @@ -14857,12 +14841,11 @@ build_arp_resolve_flows_for_lsp( > > for (size_t j = 0; j < op->lsp_addrs[i].n_ipv6_addrs; j++) { > const char *ip_s = op->lsp_addrs[i].ipv6_addrs[j].addr_s; > - for (size_t k = 0; k < op->od->n_router_ports; k++) { > + VECTOR_FOR_EACH (&op->od->router_ports, rp) { > /* Get the Logical_Router_Port that the > * Logical_Switch_Port is connected to, as > * 'peer'. */ > - struct ovn_port *peer = ovn_port_get_peer( > - lr_ports, op->od->router_ports[k]); > + struct ovn_port *peer = ovn_port_get_peer(lr_ports, > rp); > if (!peer || !peer->nbrp) { > continue; > } > @@ -14904,10 +14887,8 @@ build_arp_resolve_flows_for_lsp( > "dynamic_neigh_routers", false)) { > return; > } > - > - for (size_t i = 0; i < op->od->n_router_ports; i++) { > - struct ovn_port *router_port = > - ovn_port_get_peer(lr_ports, op->od->router_ports[i]); > + VECTOR_FOR_EACH (&op->od->router_ports, rp) { > + struct ovn_port *router_port = ovn_port_get_peer(lr_ports, > rp); > if (!router_port || !router_port->nbrp) { > continue; > } > @@ -15165,8 +15146,9 @@ build_gateway_redirect_flows_for_lrouter( > struct lflow_ref *lflow_ref) > { > ovs_assert(od->nbr); > - for (size_t i = 0; i < od->n_l3dgw_ports; i++) { > - if (l3dgw_port_has_associated_vtep_lports(od->l3dgw_ports[i])) { > + const struct ovn_port *dgp; > + VECTOR_FOR_EACH (&od->l3dgw_ports, dgp) { > + if (l3dgw_port_has_associated_vtep_lports(dgp)) { > /* Skip adding redirect lflow for vtep-enabled l3dgw ports. > * Traffic from hypervisor to VTEP (ramp) switch should go in > * distributed manner. Only returning routed traffic must go > @@ -15179,8 +15161,8 @@ build_gateway_redirect_flows_for_lrouter( > > const struct ovsdb_idl_row *stage_hint = NULL; > > - if (od->l3dgw_ports[i]->nbrp) { > - stage_hint = &od->l3dgw_ports[i]->nbrp->header_; > + if (dgp->nbrp) { > + stage_hint = &dgp->nbrp->header_; > } > > /* For traffic with outport == l3dgw_port, if the > @@ -15188,11 +15170,9 @@ build_gateway_redirect_flows_for_lrouter( > * rule, then the traffic is redirected to the central > * instance of the l3dgw_port. */ > ds_clear(match); > - ds_put_format(match, "outport == %s", > - od->l3dgw_ports[i]->json_key); > + ds_put_format(match, "outport == %s", dgp->json_key); > ds_clear(actions); > - ds_put_format(actions, "outport = %s; next;", > - od->l3dgw_ports[i]->cr_port->json_key); > + ds_put_format(actions, "outport = %s; next;", > dgp->cr_port->json_key); > ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT, 50, > ds_cstr(match), ds_cstr(actions), > stage_hint, lflow_ref); > @@ -15211,8 +15191,9 @@ build_lr_gateway_redirect_flows_for_nats( > struct lflow_ref *lflow_ref) > { > ovs_assert(od->nbr); > - for (size_t i = 0; i < od->n_l3dgw_ports; i++) { > - if (l3dgw_port_has_associated_vtep_lports(od->l3dgw_ports[i])) { > + const struct ovn_port *dgp; > + VECTOR_FOR_EACH (&od->l3dgw_ports, dgp) { > + if (l3dgw_port_has_associated_vtep_lports(dgp)) { > /* Skip adding redirect lflow for vtep-enabled l3dgw ports. > * Traffic from hypervisor to VTEP (ramp) switch should go in > * distributed manner. Only returning routed traffic must go > @@ -15235,8 +15216,8 @@ build_lr_gateway_redirect_flows_for_nats( > > const struct ovsdb_idl_row *stage_hint = NULL; > > - if (od->l3dgw_ports[i]->nbrp) { > - stage_hint = &od->l3dgw_ports[i]->nbrp->header_; > + if (dgp->nbrp) { > + stage_hint = &dgp->nbrp->header_; > } > > struct ds match_ext = DS_EMPTY_INITIALIZER; > @@ -15823,7 +15804,7 @@ build_ipv6_input_flows_for_lrouter_port( > } > > /* UDP/TCP/SCTP port unreachable */ > - if (!op->od->is_gw_router && !op->od->n_l3dgw_ports) { > + if (!op->od->is_gw_router && vector_is_empty(&op->od->l3dgw_ports)) { > for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) { > ds_clear(match); > ds_put_format(match, > @@ -16087,8 +16068,8 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, > op->lrp_networks.ipv4_addrs[i].network_s, > op->lrp_networks.ipv4_addrs[i].plen); > > - if (op->od->n_l3dgw_ports && op->peer > - && op->peer->od->n_localnet_ports) { > + if (!vector_is_empty(&op->od->l3dgw_ports) && op->peer > + && !vector_is_empty(&op->peer->od->localnet_ports)) { > bool add_chassis_resident_check = false; > const char *json_key; > if (lrp_is_l3dgw(op)) { > @@ -16111,8 +16092,9 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, > add_chassis_resident_check = smap_get_bool( > &op->nbrp->options, > "reside-on-redirect-chassis", false) && > - op->od->n_l3dgw_ports == 1; > - json_key = op->od->l3dgw_ports[0]->cr_port->json_key; > + vector_len(&op->od->l3dgw_ports) == 1; > + json_key = vector_get(&op->od->l3dgw_ports, 0, > + struct ovn_port > *)->cr_port->json_key; > } > > if (add_chassis_resident_check) { > @@ -16127,7 +16109,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, > &op->nbrp->header_, lflows, lflow_ref); > } > > - if (!op->od->is_gw_router && !op->od->n_l3dgw_ports) { > + if (!op->od->is_gw_router && vector_is_empty(&op->od->l3dgw_ports)) { > /* UDP/TCP/SCTP port unreachable. */ > for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) { > ds_clear(match); > @@ -16321,7 +16303,7 @@ build_lrouter_in_unsnat_match(const struct > ovn_datapath *od, > /* Traffic received on l3dgw_port is subject to NAT. */ > ds_put_format(match, " && inport == %s", l3dgw_port->json_key); > > - if (!distributed_nat && od->n_l3dgw_ports) { > + if (!distributed_nat && !vector_is_empty(&od->l3dgw_ports)) { > /* Flows for NAT rules that are centralized are only > * programmed on the gateway chassis. */ > ds_put_format(match, " && is_chassis_resident(%s)", > @@ -16459,7 +16441,7 @@ build_lrouter_in_dnat_flow(struct lflow_table > *lflows, > > /* Traffic received on l3dgw_port is subject to NAT. */ > ds_put_format(match, " && inport == %s", l3dgw_port->json_key); > - if (!distributed_nat && od->n_l3dgw_ports) { > + if (!distributed_nat && !vector_is_empty(&od->l3dgw_ports)) { > /* Flows for NAT rules that are centralized are only > * programmed on the gateway chassis. */ > ds_put_format(match, " && is_chassis_resident(%s)", > @@ -16509,7 +16491,7 @@ build_lrouter_out_undnat_flow(struct lflow_table > *lflows, > * > * Note that this only applies for NAT on a distributed router. > */ > - if (!od->n_l3dgw_ports || > + if (vector_is_empty(&od->l3dgw_ports) || > !(nat_entry->type == DNAT || nat_entry->type == DNAT_AND_SNAT)) { > return; > } > @@ -16521,7 +16503,7 @@ build_lrouter_out_undnat_flow(struct lflow_table > *lflows, > ds_put_format(match, "ip && ip%c.src == %s && outport == %s", > is_v6 ? '6' : '4', nat->logical_ip, > l3dgw_port->json_key); > - if (!distributed_nat && od->n_l3dgw_ports) { > + if (!distributed_nat && !vector_is_empty(&od->l3dgw_ports)) { > /* Flows for NAT rules that are centralized are only > * programmed on the gateway chassis. */ > ds_put_format(match, " && is_chassis_resident(%s)", > @@ -16556,7 +16538,7 @@ build_lrouter_out_is_dnat_local(struct lflow_table > *lflows, > { > /* Note that this only applies for NAT on a distributed router. > */ > - if (!od->n_l3dgw_ports) { > + if (vector_is_empty(&od->l3dgw_ports)) { > return; > } > > @@ -16601,7 +16583,7 @@ build_lrouter_out_snat_match(struct lflow_table > *lflows, > ds_put_format(match, " && %s == %s", > is_reverse ? "inport" : "outport", > l3dgw_port->json_key); > - if (od->n_l3dgw_ports) { > + if (!vector_is_empty(&od->l3dgw_ports)) { > ds_put_format(match, " && is_chassis_resident(\"%s\")", > distributed_nat > ? nat->logical_port > @@ -16871,7 +16853,7 @@ build_lrouter_ingress_flow(struct lflow_table > *lflows, > struct lflow_ref *lflow_ref) > { > const struct nbrec_nat *nat = nat_entry->nb; > - if (od->n_l3dgw_ports && nat_entry->type == SNAT) { > + if (!vector_is_empty(&od->l3dgw_ports) && nat_entry->type == SNAT) { > ds_clear(match); > ds_put_format( > match, "inport == %s && %s == %s", > @@ -17011,7 +16993,7 @@ build_dgp_lrouter_commit_all(const struct > ovn_datapath *od, > const struct chassis_features *features, > struct ds *match, struct lflow_ref > *lflow_ref) > { > - ovs_assert(od->n_l3dgw_ports); > + ovs_assert(!vector_is_empty(&od->l3dgw_ports)); > if (!(features->ct_commit_to_zone && features->ct_next_zone)) { > return; > } > @@ -17155,7 +17137,7 @@ build_lrouter_nat_defrag_and_lb( > /* NAT rules are only valid on Gateway routers and routers with > * l3dgw_ports (router has port(s) with gateway chassis > * specified). */ > - if (!od->is_gw_router && !od->n_l3dgw_ports) { > + if (!od->is_gw_router && vector_is_empty(&od->l3dgw_ports)) { > return; > } > > @@ -17262,7 +17244,8 @@ build_lrouter_nat_defrag_and_lb( > match, > "outport == %s && ip%s.src == %s " > "&& is_chassis_resident(\"%s\")", > - od->l3dgw_ports[0]->json_key, > + vector_get(&od->l3dgw_ports, 0, > + const struct ovn_port *)->json_key, > is_v6 ? "6" : "4", nat->logical_ip, > nat->logical_port); > ds_clear(actions); > @@ -17375,7 +17358,7 @@ build_lrouter_nat_defrag_and_lb( > * gateway port have ip.dst matching a NAT external IP, then > * loop a clone of the packet back to the beginning of the > * ingress pipeline with inport = outport. */ > - if (od->n_l3dgw_ports) { > + if (!vector_is_empty(&od->l3dgw_ports)) { > /* Distributed router. */ > ds_clear(match); > ds_put_format(match, "ip%s.dst == %s && outport == %s", > @@ -17441,10 +17424,10 @@ build_lrouter_nat_defrag_and_lb( > build_gw_lrouter_commit_all(od, lflows, features, lflow_ref); > } > > - for (size_t i = 0; i < od->n_l3dgw_ports; i++) { > - struct ovn_port *l3dgw_port = od->l3dgw_ports[i]; > - build_dgp_lrouter_commit_all(od, l3dgw_port, lflows, > - features, match, lflow_ref); > + const struct ovn_port *dgp; > + VECTOR_FOR_EACH (&od->l3dgw_ports, dgp) { > + build_dgp_lrouter_commit_all(od, dgp, lflows, features, > + match, lflow_ref); > } > } > > @@ -17548,8 +17531,9 @@ build_routable_flows_for_router_port( > struct ovn_port_routable_addresses ra = > get_op_routable_addresses(lrp, lr_stateful_rec); > > - for (size_t i = 0; i < peer_ls->n_router_ports; i++) { > - struct ovn_port *router_port = peer_ls->router_ports[i]->peer; > + struct ovn_port *op; > + VECTOR_FOR_EACH (&peer_ls->router_ports, op) { > + struct ovn_port *router_port = op->peer; > struct lport_addresses *lrpaddrs = &router_port->lrp_networks; > char *router_port_lla_s = NULL; > > @@ -19513,12 +19497,13 @@ collect_lr_groups_for_ha_chassis_groups(const > struct sbrec_port_binding *sb, > struct hmapx *lr_groups) > { > struct lrouter_group *lr_group = NULL; > - for (size_t i = 0; i < op->od->n_router_ports; i++) { > - if (!op->od->router_ports[i]->peer) { > + struct ovn_port *rp; > + VECTOR_FOR_EACH (&op->od->router_ports, rp) { > + if (!rp->peer) { > continue; > } > > - lr_group = op->od->router_ports[i]->peer->od->lr_group; > + lr_group = rp->peer->od->lr_group; > /* If a logical switch has multiple router ports, then > * all the logical routers belong to the same logical > * router group. */ > diff --git a/northd/northd.h b/northd/northd.h > index d5294e9bf..5a698458f 100644 > --- a/northd/northd.h > +++ b/northd/northd.h > @@ -26,6 +26,7 @@ > #include "simap.h" > #include "ovs-thread.h" > #include "en-lr-stateful.h" > +#include "vec.h" > > struct northd_input { > /* Northbound table references */ > @@ -365,15 +366,11 @@ struct ovn_datapath { > uint32_t tunnel_key; > > /* Logical router data. */ > - struct ovn_datapath **ls_peers; > - size_t n_ls_peers; > - size_t n_allocated_ls_peers; > + struct vector ls_peers; /* Vector of struct ovn_datapath *. */ > struct sset router_ips; /* Router port IPs except the IPv6 LLAs. */ > > /* Logical switch data. */ > - struct ovn_port **router_ports; > - size_t n_router_ports; > - size_t n_allocated_router_ports; > + struct vector router_ports; /* Vector of struct ovn_port *. */ > > struct hmap port_tnlids; > uint32_t port_key_hint; > @@ -402,9 +399,7 @@ struct ovn_datapath { > * populated only when there is a gateway chassis or ha chassis group > * specified for some of the ports on the logical router. Otherwise > this > * will be NULL. */ > - struct ovn_port **l3dgw_ports; > - size_t n_l3dgw_ports; > - size_t n_allocated_l3dgw_ports; > + struct vector l3dgw_ports; /* Vector of struct ovn_port *. */ > > /* router datapath has a logical port with redirect-type set to > bridged. */ > bool redirect_bridged; > @@ -413,9 +408,7 @@ struct ovn_datapath { > /* The modes contained in the nbr option > "dynamic-routing-redistribute". */ > enum dynamic_routing_redistribute_mode dynamic_routing_redistribute; > > - struct ovn_port **localnet_ports; > - size_t n_localnet_ports; > - size_t n_allocated_localnet_ports; > + struct vector localnet_ports; /* Vector of struct ovn_port *. */ > > struct ovs_list lr_list; /* In list of logical router datapaths. */ > /* The logical router group to which this datapath belongs. > @@ -971,7 +964,7 @@ bool lrouter_port_ipv6_reachable(const struct ovn_port > *, > static inline bool > lr_has_multiple_gw_ports(const struct ovn_datapath *od) > { > - return od->n_l3dgw_ports > 1 && !od->is_gw_router; > + return vector_len(&od->l3dgw_ports) > 1 && !od->is_gw_router; > } > > bool > -- > 2.49.0 > > Recheck-request: github-robot _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev