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;
}
*/
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;
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)
*/
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
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;
}
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);
}
/*
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)
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;
}
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;
/* 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;
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)
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
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",
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 */
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);
}
}