]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: use new per-NS ifp iterators in vxlan code
authorMark Stapp <mjs@cisco.com>
Thu, 24 Oct 2024 21:50:12 +0000 (14:50 -0700)
committerMark Stapp <mjs@cisco.com>
Tue, 29 Oct 2024 17:49:43 +0000 (13:49 -0400)
Replace use of the old if_table with the new per-NS ifp
iterator apis in the zebra vxlan code.

Signed-off-by: Mark Stapp <mjs@cisco.com>
zebra/zebra_evpn.h
zebra/zebra_vxlan.c

index 85bdf542725e5e59a8206be1185ad8bb7118cf21..0ffebdd2774fa637e746aede038546150d0dbe8b 100644 (file)
@@ -119,6 +119,7 @@ struct zebra_from_svi_param {
        struct interface *ret_ifp;
        struct zebra_if *zif;
        struct zebra_evpn *zevpn;
+       struct zebra_l3vni *zl3vni;
        uint8_t bridge_vlan_aware;
        vlanid_t vid;
 };
index 0f72259951b0ba4f29740397382144f5f9f5b059..8a1664440f085876d9ee541d5f36db8e4d81b5e2 100644 (file)
@@ -859,39 +859,30 @@ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data)
                vty_out(vty, "\n");
 }
 
-static int zvni_map_to_svi_ns(struct ns *ns,
-                             void *_in_param,
-                             void **_p_ifp)
+static int zvni_map_to_svi_ns(struct interface *tmp_if, void *_in_param)
 {
-       struct zebra_ns *zns = ns->info;
-       struct route_node *rn;
-       struct zebra_from_svi_param *in_param =
-               (struct zebra_from_svi_param *)_in_param;
+       struct zebra_from_svi_param *in_param = _in_param;
        struct zebra_l2info_vlan *vl;
-       struct interface *tmp_if = NULL;
-       struct interface **p_ifp = (struct interface **)_p_ifp;
        struct zebra_if *zif;
 
-       assert(in_param && p_ifp);
+       assert(in_param);
 
        /* TODO: Optimize with a hash. */
-       for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
-               tmp_if = (struct interface *)rn->info;
-               /* Check oper status of the SVI. */
-               if (!tmp_if || !if_is_operative(tmp_if))
-                       continue;
-               zif = tmp_if->info;
-               if (!zif || zif->zif_type != ZEBRA_IF_VLAN
-                   || zif->link != in_param->br_if)
-                       continue;
-               vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
-
-               if (vl->vid == in_param->vid) {
-                       *p_ifp = tmp_if;
-                       route_unlock_node(rn);
-                       return NS_WALK_STOP;
-               }
+
+       /* Check oper status of the SVI. */
+       if (!tmp_if || !if_is_operative(tmp_if))
+               goto done;
+       zif = tmp_if->info;
+       if (!zif || zif->zif_type != ZEBRA_IF_VLAN || zif->link != in_param->br_if)
+               goto done;
+       vl = (struct zebra_l2info_vlan *)&zif->l2info.vl;
+
+       if (vl->vid == in_param->vid) {
+               in_param->ret_ifp = tmp_if;
+               return NS_WALK_STOP;
        }
+
+done:
        return NS_WALK_CONTINUE;
 }
 
@@ -904,10 +895,9 @@ static int zvni_map_to_svi_ns(struct ns *ns,
  */
 struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
 {
-       struct interface *tmp_if = NULL;
        struct zebra_if *zif;
-       struct zebra_from_svi_param in_param;
-       struct interface **p_ifp;
+       struct zebra_from_svi_param in_param = {};
+
        /* Defensive check, caller expected to invoke only with valid bridge. */
        if (!br_if)
                return NULL;
@@ -922,12 +912,11 @@ struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
 
        in_param.vid = vid;
        in_param.br_if = br_if;
-       in_param.zif = NULL;
-       p_ifp = &tmp_if;
+
        /* Identify corresponding VLAN interface. */
-       ns_walk_func(zvni_map_to_svi_ns, (void *)&in_param,
-                    (void **)p_ifp);
-       return tmp_if;
+       zebra_ns_ifp_walk_all(zvni_map_to_svi_ns, &in_param);
+
+       return in_param.ret_ifp;
 }
 
 int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn)
@@ -1007,9 +996,9 @@ static int zevpn_build_vni_hash_table(struct zebra_if *zif,
                 */
                zevpn = zebra_evpn_lookup(vni);
                if (zevpn) {
-                       zlog_debug(
-                               "EVPN hash already present for IF %s(%u) L2-VNI %u",
-                               ifp->name, ifp->ifindex, vni);
+                       if (IS_ZEBRA_DEBUG_VXLAN)
+                               zlog_debug("EVPN hash already present for IF %s(%u) L2-VNI %u",
+                                          ifp->name, ifp->ifindex, vni);
 
                        /*
                         * Inform BGP if intf is up and mapped to
@@ -1072,48 +1061,32 @@ static int zevpn_build_vni_hash_table(struct zebra_if *zif,
        return 0;
 }
 
-static int zevpn_build_hash_table_zns(struct ns *ns,
-                                    void *param_in __attribute__((unused)),
-                                    void **param_out __attribute__((unused)))
+static int zevpn_build_hash_table_zns(struct interface *ifp, void *arg)
 {
-       struct zebra_ns *zns = ns->info;
-       struct route_node *rn;
-       struct interface *ifp;
-       struct zebra_vrf *zvrf;
-
-       zvrf = zebra_vrf_get_evpn();
+       struct zebra_vrf *zvrf = arg;
+       struct zebra_if *zif;
+       struct zebra_l2info_vxlan *vxl;
 
-       /* Walk VxLAN interfaces and create EVPN hash. */
-       for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
-               struct zebra_if *zif;
-               struct zebra_l2info_vxlan *vxl;
+       zif = ifp->info;
+       if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
+               goto done;
 
-               ifp = (struct interface *)rn->info;
-               if (!ifp)
-                       continue;
-               zif = ifp->info;
-               if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
-                       continue;
+       vxl = &zif->l2info.vxl;
+       /* link of VXLAN interface should be in zebra_evpn_vrf */
+       if (zvrf->zns->ns_id != vxl->link_nsid) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("Intf %s(%u) link not in same namespace as BGP EVPN core instance",
+                                  ifp->name, ifp->ifindex);
+               goto done;
+       }
 
-               vxl = &zif->l2info.vxl;
-               /* link of VXLAN interface should be in zebra_evpn_vrf */
-               if (zvrf->zns->ns_id != vxl->link_nsid) {
-                       if (IS_ZEBRA_DEBUG_VXLAN)
-                               zlog_debug(
-                                       "Intf %s(%u) link not in same "
-                                       "namespace than BGP EVPN core instance ",
-                                       ifp->name, ifp->ifindex);
-                       continue;
-               }
+       if (IS_ZEBRA_DEBUG_VXLAN)
+               zlog_debug("Building vni table for %s-if %s",
+                          IS_ZEBRA_VXLAN_IF_VNI(zif) ? "vni" : "svd", ifp->name);
 
-               if (IS_ZEBRA_DEBUG_VXLAN)
-                       zlog_debug("Building vni table for %s-if %s",
-                                  IS_ZEBRA_VXLAN_IF_VNI(zif) ? "vni" : "svd",
-                                  ifp->name);
+       zebra_vxlan_if_vni_iterate(zif, zevpn_build_vni_hash_table, NULL);
 
-               zebra_vxlan_if_vni_iterate(zif, zevpn_build_vni_hash_table,
-                                          NULL);
-       }
+done:
        return NS_WALK_CONTINUE;
 }
 
@@ -1124,7 +1097,13 @@ static int zevpn_build_hash_table_zns(struct ns *ns,
 
 static void zevpn_build_hash_table(void)
 {
-       ns_walk_func(zevpn_build_hash_table_zns, NULL, NULL);
+       struct zebra_vrf *zvrf;
+
+       zvrf = zebra_vrf_get_evpn();
+       if (zvrf == NULL)
+               return;
+
+       zebra_ns_ifp_walk_all(zevpn_build_hash_table_zns, zvrf);
 }
 
 /*
@@ -1968,70 +1947,63 @@ static int zl3vni_del(struct zebra_l3vni *zl3vni)
        return 0;
 }
 
-static int zl3vni_map_to_vxlan_if_ns(struct ns *ns,
-                                    void *_zl3vni,
-                                    void **_pifp)
-{
-       struct zebra_ns *zns = ns->info;
-       struct zebra_l3vni *zl3vni = (struct zebra_l3vni *)_zl3vni;
-       struct route_node *rn = NULL;
-       struct interface *ifp = NULL;
+/* Context arg for zl3vni map iteration */
+struct zl3vni_map_arg {
        struct zebra_vrf *zvrf;
+       struct zebra_l3vni *zl3vni;
+       struct interface *ret_ifp;
+};
 
-       zvrf = zebra_vrf_get_evpn();
-
-       assert(_pifp);
-
-       /* loop through all vxlan-interface */
-       for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
+static int zl3vni_map_to_vxlan_if_ns(struct interface *ifp, void *arg)
+{
+       struct zl3vni_map_arg *ctx = arg;
+       struct zebra_l3vni *zl3vni = ctx->zl3vni;
+       struct zebra_vrf *zvrf = ctx->zvrf;
+       struct zebra_if *zif = NULL;
+       struct zebra_l2info_vxlan *vxl;
+       struct zebra_vxlan_vni *vni = NULL;
 
-               struct zebra_if *zif = NULL;
-               struct zebra_l2info_vxlan *vxl;
-               struct zebra_vxlan_vni *vni = NULL;
+       /* look for vxlan-interface */
 
-               ifp = (struct interface *)rn->info;
-               if (!ifp)
-                       continue;
-
-               zif = ifp->info;
-               if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
-                       continue;
+       zif = ifp->info;
+       if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
+               goto done;
 
-               vxl = &zif->l2info.vxl;
-               vni = zebra_vxlan_if_vni_find(zif, zl3vni->vni);
-               if (!vni || vni->vni != zl3vni->vni)
-                       continue;
+       vxl = &zif->l2info.vxl;
+       vni = zebra_vxlan_if_vni_find(zif, zl3vni->vni);
+       if (!vni || vni->vni != zl3vni->vni)
+               goto done;
 
-               /* link of VXLAN interface should be in zebra_evpn_vrf */
-               if (zvrf->zns->ns_id != vxl->link_nsid) {
-                       if (IS_ZEBRA_DEBUG_VXLAN)
-                               zlog_debug(
-                                       "Intf %s(%u) VNI %u, link not in same "
-                                       "namespace than BGP EVPN core instance ",
-                                       ifp->name, ifp->ifindex, vni->vni);
-                       continue;
-               }
+       /* link of VXLAN interface should be in zebra_evpn_vrf */
+       if (zvrf->zns->ns_id != vxl->link_nsid) {
+               if (IS_ZEBRA_DEBUG_VXLAN)
+                       zlog_debug("Intf %s(%u) VNI %u, link not in same namespace as BGP EVPN core instance",
+                                  ifp->name, ifp->ifindex, vni->vni);
+               goto done;
+       }
 
+       zl3vni->local_vtep_ip = zif->l2info.vxl.vtep_ip;
+       ctx->ret_ifp = ifp;
 
-               zl3vni->local_vtep_ip = zif->l2info.vxl.vtep_ip;
-               *_pifp = (void *)ifp;
-               route_unlock_node(rn);
-               return NS_WALK_STOP;
-       }
+       return NS_WALK_STOP;
 
+done:
        return NS_WALK_CONTINUE;
 }
 
 struct interface *zl3vni_map_to_vxlan_if(struct zebra_l3vni *zl3vni)
 {
-       struct interface **p_ifp;
-       struct interface *ifp = NULL;
+       struct zl3vni_map_arg arg = {};
 
-       p_ifp = &ifp;
+       arg.zl3vni = zl3vni;
+       arg.zvrf = zebra_vrf_get_evpn();
 
-       ns_walk_func(zl3vni_map_to_vxlan_if_ns,
-                    (void *)zl3vni, (void **)p_ifp);
-       return ifp;
+       if (arg.zvrf == NULL)
+               return NULL;
+
+       zebra_ns_ifp_walk_all(zl3vni_map_to_vxlan_if_ns, &arg);
+
+       return arg.ret_ifp;
 }
 
 struct interface *zl3vni_map_to_svi_if(struct zebra_l3vni *zl3vni)
@@ -2086,57 +2058,35 @@ struct zebra_l3vni *zl3vni_from_vrf(vrf_id_t vrf_id)
        return zl3vni_lookup(zvrf->l3vni);
 }
 
-static int zl3vni_from_svi_ns(struct ns *ns, void *_in_param, void **_p_zl3vni)
+/* loop through all vxlan-interface */
+static int zl3vni_from_svi_ns(struct interface *tmp_if, void *_in_param)
 {
        int found = 0;
        vni_t vni_id = 0;
-       struct zebra_ns *zns = ns->info;
-       struct zebra_l3vni **p_zl3vni = (struct zebra_l3vni **)_p_zl3vni;
-       struct zebra_from_svi_param *in_param =
-               (struct zebra_from_svi_param *)_in_param;
-       struct route_node *rn = NULL;
-       struct interface *tmp_if = NULL;
+       struct zebra_from_svi_param *in_param = _in_param;
        struct zebra_if *zif = NULL;
-       struct zebra_if *br_zif = NULL;
 
-       assert(in_param && p_zl3vni);
+       assert(in_param);
 
-       br_zif = in_param->br_if->info;
-       assert(br_zif);
+       zif = tmp_if->info;
+       if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
+               goto done;
+       if (!if_is_operative(tmp_if))
+               goto done;
 
-       if (in_param->bridge_vlan_aware) {
-               vni_id = zebra_l2_bridge_if_vni_find(br_zif, in_param->vid);
-               if (vni_id)
-                       found = 1;
-       } else {
-               /* loop through all vxlan-interface */
-               for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
-                       tmp_if = (struct interface *)rn->info;
-                       if (!tmp_if)
-                               continue;
-                       zif = tmp_if->info;
-                       if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
-                               continue;
-                       if (!if_is_operative(tmp_if))
-                               continue;
-
-                       if (zif->brslave_info.br_if != in_param->br_if)
-                               continue;
-
-                       vni_id = zebra_vxlan_if_access_vlan_vni_find(
-                               zif, in_param->br_if);
-                       if (vni_id) {
-                               found = 1;
-                               route_unlock_node(rn);
-                               break;
-                       }
-               }
+       if (zif->brslave_info.br_if != in_param->br_if)
+               goto done;
+
+       vni_id = zebra_vxlan_if_access_vlan_vni_find(zif, in_param->br_if);
+       if (vni_id) {
+               in_param->zl3vni = zl3vni_lookup(vni_id);
+               found = 1;
        }
 
+done:
        if (!found)
                return NS_WALK_CONTINUE;
 
-       *p_zl3vni = zl3vni_lookup(vni_id);
        return NS_WALK_STOP;
 }
 
@@ -2147,10 +2097,11 @@ static int zl3vni_from_svi_ns(struct ns *ns, void *_in_param, void **_p_zl3vni)
 static struct zebra_l3vni *zl3vni_from_svi(struct interface *ifp,
                                           struct interface *br_if)
 {
-       struct zebra_l3vni *zl3vni = NULL;
        struct zebra_if *zif = NULL;
+       vni_t vni_id = 0;
+       struct zebra_if *br_zif = NULL;
        struct zebra_from_svi_param in_param = {};
-       struct zebra_l3vni **p_zl3vni;
+       struct zebra_l2info_vlan *vl;
 
        if (!br_if)
                return NULL;
@@ -2158,15 +2109,15 @@ static struct zebra_l3vni *zl3vni_from_svi(struct interface *ifp,
        /* Make sure the linked interface is a bridge. */
        if (!IS_ZEBRA_IF_BRIDGE(br_if))
                return NULL;
+
        in_param.br_if = br_if;
 
        /* Determine if bridge is VLAN-aware or not */
-       zif = br_if->info;
-       assert(zif);
-       in_param.bridge_vlan_aware = IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(zif);
-       if (in_param.bridge_vlan_aware) {
-               struct zebra_l2info_vlan *vl;
+       br_zif = br_if->info;
+       assert(br_zif);
 
+       in_param.bridge_vlan_aware = IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif);
+       if (in_param.bridge_vlan_aware) {
                if (!IS_ZEBRA_IF_VLAN(ifp))
                        return NULL;
 
@@ -2174,15 +2125,18 @@ static struct zebra_l3vni *zl3vni_from_svi(struct interface *ifp,
                assert(zif);
                vl = &zif->l2info.vl;
                in_param.vid = vl->vid;
+
+               vni_id = zebra_l2_bridge_if_vni_find(br_zif, in_param.vid);
+               if (vni_id)
+                       return zl3vni_lookup(vni_id);
        }
 
        /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */
        /* TODO: Optimize with a hash. */
 
-       p_zl3vni = &zl3vni;
+       zebra_ns_ifp_walk_all(zl3vni_from_svi_ns, &in_param);
 
-       ns_walk_func(zl3vni_from_svi_ns, (void *)&in_param, (void **)p_zl3vni);
-       return zl3vni;
+       return in_param.zl3vni;
 }
 
 vni_t vni_id_from_svi(struct interface *ifp, struct interface *br_if)
@@ -2336,6 +2290,36 @@ static void zevpn_add_to_l3vni_list(struct hash_bucket *bucket, void *ctxt)
                listnode_add_sort(zl3vni->l2vnis, zevpn);
 }
 
+/* Helper for vni transition iterator */
+
+struct vni_trans_ctx {
+       vni_t vni;
+       struct zebra_vxlan_vni *vnip;
+       struct interface *ret_ifp;
+};
+
+static int vni_trans_cb(struct interface *ifp, void *arg)
+{
+       struct vni_trans_ctx *ctx = arg;
+       struct zebra_if *zif;
+       struct zebra_vxlan_vni *vnip;
+
+       /* Find VxLAN interface for this VNI. */
+       zif = ifp->info;
+       if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
+               goto done;
+
+       vnip = zebra_vxlan_if_vni_find(zif, ctx->vni);
+       if (vnip) {
+               ctx->ret_ifp = ifp;
+               ctx->vnip = vnip;
+               return NS_WALK_STOP;
+       }
+
+done:
+       return NS_WALK_CONTINUE;
+}
+
 /*
  * Handle transition of vni from l2 to l3 and vice versa.
  * This function handles only the L2VNI add/delete part of
@@ -2386,39 +2370,25 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
                        return -1;
                }
        } else {
-               struct zebra_ns *zns;
-               struct route_node *rn;
-               struct interface *ifp;
-               struct zebra_if *zif;
                struct zebra_vxlan_vni *vnip;
                struct zebra_l2info_vxlan *vxl;
                struct interface *vlan_if;
-               bool found = false;
+               struct zebra_if *zif;
+               struct zebra_ns *zns;
+               struct vni_trans_ctx ctx = {};
 
                if (IS_ZEBRA_DEBUG_VXLAN)
                        zlog_debug("Adding L2-VNI %u - transition from L3-VNI",
                                   vni);
 
-               /* Find VxLAN interface for this VNI. */
                zns = zebra_ns_lookup(NS_DEFAULT);
-               for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
-                       ifp = (struct interface *)rn->info;
-                       if (!ifp)
-                               continue;
-                       zif = ifp->info;
-                       if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
-                               continue;
-
-                       vxl = &zif->l2info.vxl;
-                       vnip = zebra_vxlan_if_vni_find(zif, vni);
-                       if (vnip) {
-                               found = true;
-                               route_unlock_node(rn);
-                               break;
-                       }
-               }
 
-               if (!found) {
+               ctx.vni = vni;
+
+               /* Find VxLAN interface for this VNI. */
+               zebra_ns_ifp_walk(zns, vni_trans_cb, &ctx);
+
+               if (ctx.ret_ifp == NULL) {
                        if (IS_ZEBRA_DEBUG_VXLAN)
                                zlog_err(
                                        "Adding L2-VNI - Failed to find VxLAN interface for VNI %u",
@@ -2431,6 +2401,10 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
                if (zevpn)
                        return 0;
 
+               zif = ctx.ret_ifp->info;
+               vnip = ctx.vnip;
+               vxl = &zif->l2info.vxl;
+
                zevpn = zebra_evpn_add(vni);
 
                /* Find bridge interface for the VNI */
@@ -2443,13 +2417,13 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
                                listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
                }
 
-               zevpn->vxlan_if = ifp;
+               zevpn->vxlan_if = ctx.ret_ifp;
                zevpn->local_vtep_ip = vxl->vtep_ip;
 
                /* Inform BGP if the VNI is up and mapped to a bridge. */
-               if (if_is_operative(ifp) && zif->brslave_info.br_if) {
+               if (if_is_operative(ctx.ret_ifp) && zif->brslave_info.br_if) {
                        zebra_evpn_send_add_to_client(zevpn);
-                       zebra_evpn_read_mac_neigh(zevpn, ifp);
+                       zebra_evpn_read_mac_neigh(zevpn, ctx.ret_ifp);
                }
        }