From 8353cf5d4c8377d08d7e1efba0aea9174fae0112 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Thu, 24 Oct 2024 14:50:12 -0700 Subject: [PATCH] zebra: use new per-NS ifp iterators in vxlan code 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 --- zebra/zebra_evpn.h | 1 + zebra/zebra_vxlan.c | 368 ++++++++++++++++++++------------------------ 2 files changed, 172 insertions(+), 197 deletions(-) diff --git a/zebra/zebra_evpn.h b/zebra/zebra_evpn.h index 85bdf542725e..0ffebdd2774f 100644 --- a/zebra/zebra_evpn.h +++ b/zebra/zebra_evpn.h @@ -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; }; diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 0f72259951b0..8a1664440f08 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -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); } }