diff --git a/lib/netns_linux.c b/lib/netns_linux.c index 98f359401e..09a42b850b 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -51,7 +51,7 @@ static struct ns *ns_lookup_name_internal(const char *name); RB_GENERATE(ns_head, ns, entry, ns_compare) -static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); +struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); static struct ns *default_ns; static int ns_current_ns_fd; diff --git a/lib/netns_other.c b/lib/netns_other.c index 740d2b621e..b0aae4f8df 100644 --- a/lib/netns_other.c +++ b/lib/netns_other.c @@ -34,7 +34,7 @@ static inline int ns_compare(const struct ns *ns, const struct ns *ns2); RB_GENERATE(ns_head, ns, entry, ns_compare) -static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); +struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); static inline int ns_compare(const struct ns *a, const struct ns *b) { diff --git a/lib/ns.h b/lib/ns.h index 20e0a38e3b..1963b8a359 100644 --- a/lib/ns.h +++ b/lib/ns.h @@ -71,6 +71,8 @@ struct ns { RB_HEAD(ns_head, ns); RB_PROTOTYPE(ns_head, ns, entry, ns_compare) +extern struct ns_head ns_tree; + /* * API for managing NETNS. eg from zebra daemon * one want to manage the list of NETNS, etc... diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 4e51437337..4e23ca2f03 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -229,3 +229,25 @@ int zebra_ns_config_write(struct vty *vty, struct ns *ns) vty_out(vty, " netns %s\n", ns->name); return 0; } + +void zebra_ns_list_walk(int (*exec_for_each_zns)(struct zebra_ns *zns, + void *param_in, + void **param_out), + void *param_in, + void **param_out) +{ + struct ns *ns; + struct zebra_ns *zns; + int ret; + + RB_FOREACH (ns, ns_head, &ns_tree) { + zns = (struct zebra_ns *)ns->info; + if (!zns && ns->ns_id == NS_DEFAULT) + zns = zebra_ns_lookup(ns->ns_id); + if (!zns) + continue; + ret = exec_for_each_zns(zns, param_in, param_out); + if (ret == ZNS_WALK_STOP) + return; + } +} diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index dc79a83db0..fa2fd47c25 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -72,6 +72,14 @@ int zebra_ns_final_shutdown(struct ns *ns); int zebra_ns_config_write(struct vty *vty, struct ns *ns); +#define ZNS_WALK_CONTINUE 0 +#define ZNS_WALK_STOP 1 +void zebra_ns_list_walk(int (*exec_for_each_zns)(struct zebra_ns *zns, + void *param_in, + void **param_out), + void *param_in, + void **param_out); + #ifdef __cplusplus } #endif diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index d85f48e570..863eef17a3 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -4115,18 +4115,20 @@ static int zvni_send_del_to_client(vni_t vni) return zserv_send_message(client, s); } -/* - * Build the VNI hash table by going over the VxLAN interfaces. This - * is called when EVPN (advertise-all-vni) is enabled. - */ -static void zvni_build_hash_table(void) +static int zvni_build_hash_table_zns(struct zebra_ns *zns, + void *param_in __attribute__((unused)), + void **param_out __attribute__((unused))) { - struct zebra_ns *zns; struct route_node *rn; struct interface *ifp; + struct zebra_vrf *zvrf; + + zvrf = zebra_vrf_get_evpn(); + + if (!zvrf) + return ZNS_WALK_STOP; /* Walk VxLAN interfaces and create VNI hash. */ - zns = zebra_ns_lookup(NS_DEFAULT); for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { vni_t vni; zebra_vni_t *zvni = NULL; @@ -4143,7 +4145,15 @@ static void zvni_build_hash_table(void) vxl = &zif->l2info.vxl; vni = vxl->vni; - + /* 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); + continue; + } /* L3-VNI and L2-VNI are handled seperately */ zl3vni = zl3vni_lookup(vni); if (zl3vni) { @@ -4212,7 +4222,7 @@ static void zvni_build_hash_table(void) zlog_debug( "Failed to add VNI hash, IF %s(%u) L2-VNI %u", ifp->name, ifp->ifindex, vni); - return; + return ZNS_WALK_CONTINUE; } if (zvni->local_vtep_ip.s_addr != @@ -4249,6 +4259,19 @@ static void zvni_build_hash_table(void) } } } + return ZNS_WALK_CONTINUE; +} + +/* + * Build the VNI hash table by going over the VxLAN interfaces. This + * is called when EVPN (advertise-all-vni) is enabled. + */ + +static void zvni_build_hash_table(void) +{ + zebra_ns_list_walk(zvni_build_hash_table_zns, + (void *)NULL, + (void **)NULL); } /* @@ -5033,14 +5056,21 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni) return 0; } -struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni) +static int zl3vni_map_to_vxlan_if_zns(struct zebra_ns *zns, + void *_zl3vni, + void **_pifp) { - struct zebra_ns *zns = NULL; + zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)_zl3vni; struct route_node *rn = NULL; struct interface *ifp = NULL; + struct zebra_vrf *zvrf; + + zvrf = zebra_vrf_get_evpn(); + + if (!zvrf) + return ZNS_WALK_STOP; /* loop through all vxlan-interface */ - zns = zebra_ns_lookup(NS_DEFAULT); for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { struct zebra_if *zif = NULL; @@ -5055,13 +5085,39 @@ struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni) continue; vxl = &zif->l2info.vxl; - if (vxl->vni == zl3vni->vni) { - zl3vni->local_vtep_ip = vxl->vtep_ip; - return ifp; + if (vxl->vni != zl3vni->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 than BGP EVPN core instance ", + ifp->name, ifp->ifindex, vxl->vni); + continue; } + + + zl3vni->local_vtep_ip = vxl->vtep_ip; + if (_pifp) + *_pifp = (void *)ifp; + return ZNS_WALK_STOP; } - return NULL; + return ZNS_WALK_CONTINUE; +} + +struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni) +{ + struct interface **p_ifp; + struct interface *ifp = NULL; + + p_ifp = &ifp; + + zebra_ns_list_walk(zl3vni_map_to_vxlan_if_zns, + (void *)zl3vni, (void **)p_ifp); + return ifp; } struct interface *zl3vni_map_to_svi_if(zebra_l3vni_t *zl3vni)