From 9d277b8c5239963bc6037f014e6c5fda5fa1c646 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 27 Sep 2019 11:17:20 +0200 Subject: zebra: zvni_from_svi() adaptation for other network namespaces other network namespaces are parsed because bridge interface can be bridged with vxlan interfaces with a link in the default vrf that hosts l2vpn. Signed-off-by: Philippe Guibert --- zebra/zebra_evpn.c | 109 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 37 deletions(-) (limited to 'zebra/zebra_evpn.c') diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index 73df93258e..b704c32c5c 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -675,51 +675,35 @@ zebra_evpn_t *zebra_evpn_map_vlan(struct interface *ifp, return zevpn; } -/* - * Map SVI and associated bridge to an EVPN. This is invoked upon getting - * neighbor notifications, to see if they are of interest. - */ -zebra_evpn_t *zebra_evpn_from_svi(struct interface *ifp, - struct interface *br_if) +struct zevpn_from_svi_param { + struct interface *br_if; + struct zebra_if *zif; + uint8_t bridge_vlan_aware; + vlanid_t vid; +}; + +static int zebra_evpn_from_svi_zns(struct zebra_ns *zns, + void *_in_param, + void **_p_zevpn) { - struct zebra_ns *zns; struct route_node *rn; + struct interface *br_if; + zebra_evpn_t **p_zevpn = (zebra_evpn_t **)_p_zevpn; + zebra_evpn_t *zevpn; struct interface *tmp_if = NULL; struct zebra_if *zif; - struct zebra_l2info_bridge *br; struct zebra_l2info_vxlan *vxl = NULL; - uint8_t bridge_vlan_aware; - vlanid_t vid = 0; - zebra_evpn_t *zevpn; + struct zevpn_from_svi_param *in_param = + (struct zevpn_from_svi_param *)_in_param; int found = 0; - if (!br_if) - return NULL; - - /* Make sure the linked interface is a bridge. */ - if (!IS_ZEBRA_IF_BRIDGE(br_if)) - return NULL; - - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; + if (!in_param) + return ZNS_WALK_STOP; + br_if = in_param->br_if; + zif = in_param->zif; assert(zif); - br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; - if (bridge_vlan_aware) { - struct zebra_l2info_vlan *vl; - if (!IS_ZEBRA_IF_VLAN(ifp)) - return NULL; - - zif = ifp->info; - assert(zif); - vl = &zif->l2info.vl; - vid = vl->vid; - } - - /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ /* TODO: Optimize with a hash. */ - zns = zebra_ns_lookup(NS_DEFAULT); for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { tmp_if = (struct interface *)rn->info; if (!tmp_if) @@ -734,16 +718,67 @@ zebra_evpn_t *zebra_evpn_from_svi(struct interface *ifp, if (zif->brslave_info.br_if != br_if) continue; - if (!bridge_vlan_aware || vxl->access_vlan == vid) { + if (!in_param->bridge_vlan_aware + || vxl->access_vlan == in_param->vid) { found = 1; break; } } if (!found) - return NULL; + return ZNS_WALK_CONTINUE; zevpn = zebra_evpn_lookup(vxl->vni); + if (p_zevpn) + *p_zevpn = zevpn; + return ZNS_WALK_STOP; +} + +/* + * Map SVI and associated bridge to an EVPN. This is invoked upon getting + * neighbor notifications, to see if they are of interest. + */ +zebra_evpn_t *zebra_evpn_from_svi(struct interface *ifp, + struct interface *br_if) +{ + struct zebra_l2info_bridge *br; + zebra_evpn_t *zevpn = NULL; + zebra_evpn_t **p_zevpn; + struct zebra_if *zif; + struct zevpn_from_svi_param in_param; + + if (!br_if) + return NULL; + + /* Make sure the linked interface is a bridge. */ + if (!IS_ZEBRA_IF_BRIDGE(br_if)) + return NULL; + + /* Determine if bridge is VLAN-aware or not */ + zif = br_if->info; + assert(zif); + br = &zif->l2info.br; + in_param.bridge_vlan_aware = br->vlan_aware; + in_param.vid = 0; + + if (in_param.bridge_vlan_aware) { + struct zebra_l2info_vlan *vl; + + if (!IS_ZEBRA_IF_VLAN(ifp)) + return NULL; + + zif = ifp->info; + assert(zif); + vl = &zif->l2info.vl; + in_param.vid = vl->vid; + } + + in_param.br_if = br_if; + in_param.zif = zif; + p_zevpn = &zevpn; + /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ + zebra_ns_list_walk(zebra_evpn_from_svi_zns, (void *)&in_param, + (void **)p_zevpn); return zevpn; } -- cgit v1.2.3 From a237058f59d46af115dafa82c5ca1026418e0518 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 27 Sep 2019 15:45:42 +0200 Subject: zebra: zvni_map_to_svi() adaptation for other network namespaces the function is called with all the network namespaces. Signed-off-by: Philippe Guibert --- zebra/zebra_evpn.c | 13 +++------ zebra/zebra_evpn.h | 8 ++++++ zebra/zebra_vxlan.c | 76 +++++++++++++++++++++++++++++++++-------------------- 3 files changed, 58 insertions(+), 39 deletions(-) (limited to 'zebra/zebra_evpn.c') diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index b704c32c5c..eb9f99f2dd 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -675,13 +675,6 @@ zebra_evpn_t *zebra_evpn_map_vlan(struct interface *ifp, return zevpn; } -struct zevpn_from_svi_param { - struct interface *br_if; - struct zebra_if *zif; - uint8_t bridge_vlan_aware; - vlanid_t vid; -}; - static int zebra_evpn_from_svi_zns(struct zebra_ns *zns, void *_in_param, void **_p_zevpn) @@ -693,8 +686,8 @@ static int zebra_evpn_from_svi_zns(struct zebra_ns *zns, struct interface *tmp_if = NULL; struct zebra_if *zif; struct zebra_l2info_vxlan *vxl = NULL; - struct zevpn_from_svi_param *in_param = - (struct zevpn_from_svi_param *)_in_param; + struct zebra_from_svi_param *in_param = + (struct zebra_from_svi_param *)_in_param; int found = 0; if (!in_param) @@ -745,7 +738,7 @@ zebra_evpn_t *zebra_evpn_from_svi(struct interface *ifp, zebra_evpn_t *zevpn = NULL; zebra_evpn_t **p_zevpn; struct zebra_if *zif; - struct zevpn_from_svi_param in_param; + struct zebra_from_svi_param in_param; if (!br_if) return NULL; diff --git a/zebra/zebra_evpn.h b/zebra/zebra_evpn.h index 3b6a5b21e8..7b08a3f485 100644 --- a/zebra/zebra_evpn.h +++ b/zebra/zebra_evpn.h @@ -123,6 +123,14 @@ struct zebra_evpn_t_ { struct list *local_es_evi_list; }; +/* for parsing evpn and vni contexts */ +struct zebra_from_svi_param { + struct interface *br_if; + struct zebra_if *zif; + uint8_t bridge_vlan_aware; + vlanid_t vid; +}; + struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if); static inline struct interface *zevpn_map_to_svi(zebra_evpn_t *zevpn) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 7079184a34..5a58794378 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -782,6 +782,42 @@ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data) vty_out(vty, "\n"); } +static int zvni_map_to_svi_ns(struct zebra_ns *zns, + void *_in_param, + void **_p_ifp) +{ + struct route_node *rn; + struct zebra_from_svi_param *in_param = + (struct zebra_from_svi_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; + + if (!in_param) + return ZNS_WALK_STOP; + + /* 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) { + if (p_ifp) + *p_ifp = tmp_if; + return ZNS_WALK_STOP; + } + } + return ZNS_WALK_CONTINUE; +} + /* Map to SVI on bridge corresponding to specified VLAN. This can be one * of two cases: * (a) In the case of a VLAN-aware bridge, the SVI is a L3 VLAN interface @@ -791,15 +827,11 @@ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data) */ struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if) { - struct zebra_ns *zns; - struct route_node *rn; struct interface *tmp_if = NULL; struct zebra_if *zif; struct zebra_l2info_bridge *br; - struct zebra_l2info_vlan *vl; - uint8_t bridge_vlan_aware; - int found = 0; - + struct zebra_from_svi_param in_param; + struct interface **p_ifp; /* Defensive check, caller expected to invoke only with valid bridge. */ if (!br_if) return NULL; @@ -808,33 +840,19 @@ struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if) zif = br_if->info; assert(zif); br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; - + in_param.bridge_vlan_aware = br->vlan_aware; /* Check oper status of the SVI. */ - if (!bridge_vlan_aware) + if (!in_param.bridge_vlan_aware) return if_is_operative(br_if) ? br_if : NULL; + in_param.vid = vid; + in_param.br_if = br_if; + in_param.zif = NULL; + p_ifp = &tmp_if; /* Identify corresponding VLAN interface. */ - /* TODO: Optimize with a hash. */ - zns = zebra_ns_lookup(NS_DEFAULT); - 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 != br_if) - continue; - vl = &zif->l2info.vl; - - if (vl->vid == vid) { - found = 1; - break; - } - } - - return found ? tmp_if : NULL; + zebra_ns_list_walk(zvni_map_to_svi_ns, (void *)&in_param, + (void **)p_ifp); + return tmp_if; } static int zebra_evpn_vxlan_del(zebra_evpn_t *zevpn) -- cgit v1.2.3 From 9609fab712c41a7e92dd3f51a4089bf852cce5a7 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 9 Oct 2019 13:59:37 +0200 Subject: zebra: zvni_map_to_vlan() adaptation for all namespaces this change is needed when a MAC/IP entry is learned by zebra, and the entry happens to be in a different namespace. So that the entry be active, the correct vni match has to be found. Signed-off-by: Philippe Guibert --- zebra/zebra_evpn.c | 65 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 18 deletions(-) (limited to 'zebra/zebra_evpn.c') diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index eb9f99f2dd..da4ba4f705 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -622,32 +622,30 @@ void zebra_evpn_svi_macip_del_for_evpn_hash(struct hash_bucket *bucket, return; } -/* - * Map port or (port, VLAN) to an EVPN. This is invoked upon getting MAC - * notifications, to see if they are of interest. - */ -zebra_evpn_t *zebra_evpn_map_vlan(struct interface *ifp, - struct interface *br_if, vlanid_t vid) +static int zebra_evpn_map_vlan_zns(struct zebra_ns *zns, + void *_in_param, + void **_p_zevpn) { - struct zebra_ns *zns; struct route_node *rn; + struct interface *br_if; + zebra_evpn_t **p_zevpn = (zebra_evpn_t **)_p_zevpn; + zebra_evpn_t *zevpn; struct interface *tmp_if = NULL; struct zebra_if *zif; - struct zebra_l2info_bridge *br; struct zebra_l2info_vxlan *vxl = NULL; - uint8_t bridge_vlan_aware; - zebra_evpn_t *zevpn; + struct zebra_from_svi_param *in_param = + (struct zebra_from_svi_param *)_in_param; int found = 0; - /* Determine if bridge is VLAN-aware or not */ - zif = br_if->info; + if (!in_param) + return ZNS_WALK_STOP; + br_if = in_param->br_if; + zif = in_param->zif; assert(zif); - br = &zif->l2info.br; - bridge_vlan_aware = br->vlan_aware; + assert(br_if); /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ /* TODO: Optimize with a hash. */ - zns = zebra_ns_lookup(NS_DEFAULT); for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { tmp_if = (struct interface *)rn->info; if (!tmp_if) @@ -662,16 +660,47 @@ zebra_evpn_t *zebra_evpn_map_vlan(struct interface *ifp, if (zif->brslave_info.br_if != br_if) continue; - if (!bridge_vlan_aware || vxl->access_vlan == vid) { + if (!in_param->bridge_vlan_aware + || vxl->access_vlan == in_param->vid) { found = 1; break; } } - if (!found) - return NULL; + return ZNS_WALK_CONTINUE; zevpn = zebra_evpn_lookup(vxl->vni); + if (p_zevpn) + *p_zevpn = zevpn; + return ZNS_WALK_STOP; +} + +/* + * Map port or (port, VLAN) to an EVPN. This is invoked upon getting MAC + * notifications, to see if they are of interest. + */ +zebra_evpn_t *zebra_evpn_map_vlan(struct interface *ifp, + struct interface *br_if, vlanid_t vid) +{ + struct zebra_if *zif; + struct zebra_l2info_bridge *br; + zebra_evpn_t **p_zevpn; + zebra_evpn_t *zevpn = NULL; + struct zebra_from_svi_param in_param; + + /* Determine if bridge is VLAN-aware or not */ + zif = br_if->info; + assert(zif); + br = &zif->l2info.br; + in_param.bridge_vlan_aware = br->vlan_aware; + in_param.vid = vid; + in_param.br_if = br_if; + in_param.zif = zif; + p_zevpn = &zevpn; + + zebra_ns_list_walk(zebra_evpn_map_vlan_zns, + (void *)&in_param, + (void **)p_zevpn); return zevpn; } -- cgit v1.2.3 From d6bf8f136da0e1afce0ef6c9c7a232a30851742c Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 25 Oct 2019 14:25:00 +0200 Subject: zebra: when parsing local entry against dad, retrieve config when duplicate address detection is observed, some incrementation, some timing mechanisms need to be done. For that the main evpn configuration is retrieved. Until now, the VRF that was storing the dad config parameters was the same VRF that hosted the VXLAN interface. With netns backend, this is not true, as the VXLAN interface is in the same VRF as the bridge interface. The modification takes same definition as in BGP, that is to say that there is a single bgp evpn instance, and this is that instance that will give the correct config settings. Signed-off-by: Philippe Guibert --- zebra/zebra_evpn.c | 2 +- zebra/zebra_vxlan.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'zebra/zebra_evpn.c') diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index da4ba4f705..d78ee57af3 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -1372,7 +1372,7 @@ void process_remote_macip_add(vni_t vni, struct ethaddr *macaddr, } } - zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id); + zvrf = zebra_vrf_get_evpn(); if (!zvrf) return; diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index a0046e6031..6332854e73 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -4062,11 +4062,10 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, return -1; } - zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id); + zvrf = zebra_vrf_get_evpn(); if (!zvrf) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug(" No Vrf found for vrf_id: %d", - zevpn->vxlan_if->vrf_id); + zlog_debug(" No Evpn Global Vrf found"); return -1; } -- cgit v1.2.3 From b5fde6fd5c41b99ff205b1139490db49acab1667 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 28 Oct 2019 12:02:17 +0100 Subject: zebra: local mac entries populated in correct netnamespace MAC address neighbours are read on the same netnamespace where the vxlan interface is. Signed-off-by: Philippe Guibert --- zebra/zebra_evpn.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'zebra/zebra_evpn.c') diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index d78ee57af3..542f36156e 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -869,6 +869,7 @@ void zebra_evpn_install_mac_hash(struct hash_bucket *bucket, void *ctxt) void zebra_evpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp) { struct zebra_ns *zns; + struct zebra_vrf *zvrf; struct zebra_if *zif; struct interface *vlan_if; struct zebra_l2info_vxlan *vxl; @@ -876,7 +877,10 @@ void zebra_evpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp) zif = ifp->info; vxl = &zif->l2info.vxl; - zns = zebra_ns_lookup(NS_DEFAULT); + zvrf = zebra_vrf_lookup_by_id(zevpn->vrf_id); + if (!zvrf || !zvrf->zns) + return; + zns = zvrf->zns; if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( -- cgit v1.2.3 From 2961d0601c7d168eed5bbe8e95f80a642f9cb4b5 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 20 Dec 2019 17:51:37 +0100 Subject: lib, zebra: reuse and adapt ns_list walk functionality the walk routine is used by vxlan service to identify some contexts in each specific network namespace, when vrf netns backend is used. that walk mechanism is extended with some additional paramters to the walk routine. Signed-off-by: Philippe Guibert --- lib/netns_linux.c | 16 +++++++++---- lib/netns_other.c | 2 +- lib/ns.h | 11 ++++++--- zebra/main.c | 4 ++-- zebra/zebra_evpn.c | 36 +++++++++++++++------------- zebra/zebra_ns.c | 35 +++++++-------------------- zebra/zebra_ns.h | 17 +++++-------- zebra/zebra_vxlan.c | 69 +++++++++++++++++++++++++++++------------------------ 8 files changed, 95 insertions(+), 95 deletions(-) (limited to 'zebra/zebra_evpn.c') diff --git a/lib/netns_linux.c b/lib/netns_linux.c index 0109b3db6a..e8d549b4e0 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) -struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); +static struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); static struct ns *default_ns; static int ns_current_ns_fd; @@ -379,12 +379,20 @@ struct ns *ns_lookup(ns_id_t ns_id) return ns_lookup_internal(ns_id); } -void ns_walk_func(int (*func)(struct ns *)) +void ns_walk_func(int (*func)(struct ns *, + void *param_in, + void **param_out), + void *param_in, + void **param_out) { struct ns *ns = NULL; + int ret; - RB_FOREACH (ns, ns_head, &ns_tree) - func(ns); + RB_FOREACH (ns, ns_head, &ns_tree) { + ret = func(ns, param_in, param_out); + if (ret == NS_WALK_STOP) + return; + } } const char *ns_get_name(struct ns *ns) diff --git a/lib/netns_other.c b/lib/netns_other.c index b0aae4f8df..740d2b621e 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) -struct ns_head ns_tree = RB_INITIALIZER(&ns_tree); +static 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 0dfd977429..286ff5b295 100644 --- a/lib/ns.h +++ b/lib/ns.h @@ -76,8 +76,6 @@ 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... @@ -127,7 +125,14 @@ int ns_socket(int domain, int type, int protocol, ns_id_t ns_id); extern char *ns_netns_pathname(struct vty *vty, const char *name); /* Parse and execute a function on all the NETNS */ -extern void ns_walk_func(int (*func)(struct ns *)); +#define NS_WALK_CONTINUE 0 +#define NS_WALK_STOP 1 + +extern void ns_walk_func(int (*func)(struct ns *, + void *, + void **), + void *param_in, + void **param_out); /* API to get the NETNS name, from the ns pointer */ extern const char *ns_get_name(struct ns *ns); diff --git a/zebra/main.c b/zebra/main.c index 64746f7166..2b97e915fb 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -187,7 +187,7 @@ static void sigint(void) vrf_terminate(); rtadv_terminate(); - ns_walk_func(zebra_ns_early_shutdown); + ns_walk_func(zebra_ns_early_shutdown, NULL, NULL); zebra_ns_notify_close(); access_list_reset(); @@ -218,7 +218,7 @@ int zebra_finalize(struct thread *dummy) zlog_info("Zebra final shutdown"); /* Final shutdown of ns resources */ - ns_walk_func(zebra_ns_final_shutdown); + ns_walk_func(zebra_ns_final_shutdown, NULL, NULL); /* Stop dplane thread and finish any cleanup */ zebra_dplane_shutdown(); diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index 542f36156e..0f5e77ac65 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -622,10 +622,11 @@ void zebra_evpn_svi_macip_del_for_evpn_hash(struct hash_bucket *bucket, return; } -static int zebra_evpn_map_vlan_zns(struct zebra_ns *zns, - void *_in_param, - void **_p_zevpn) +static int zebra_evpn_map_vlan_ns(struct ns *ns, + void *_in_param, + void **_p_zevpn) { + struct zebra_ns *zns = ns->info; struct route_node *rn; struct interface *br_if; zebra_evpn_t **p_zevpn = (zebra_evpn_t **)_p_zevpn; @@ -638,7 +639,7 @@ static int zebra_evpn_map_vlan_zns(struct zebra_ns *zns, int found = 0; if (!in_param) - return ZNS_WALK_STOP; + return NS_WALK_STOP; br_if = in_param->br_if; zif = in_param->zif; assert(zif); @@ -667,12 +668,12 @@ static int zebra_evpn_map_vlan_zns(struct zebra_ns *zns, } } if (!found) - return ZNS_WALK_CONTINUE; + return NS_WALK_CONTINUE; zevpn = zebra_evpn_lookup(vxl->vni); if (p_zevpn) *p_zevpn = zevpn; - return ZNS_WALK_STOP; + return NS_WALK_STOP; } /* @@ -698,16 +699,17 @@ zebra_evpn_t *zebra_evpn_map_vlan(struct interface *ifp, in_param.zif = zif; p_zevpn = &zevpn; - zebra_ns_list_walk(zebra_evpn_map_vlan_zns, - (void *)&in_param, - (void **)p_zevpn); + ns_walk_func(zebra_evpn_map_vlan_ns, + (void *)&in_param, + (void **)p_zevpn); return zevpn; } -static int zebra_evpn_from_svi_zns(struct zebra_ns *zns, - void *_in_param, - void **_p_zevpn) +static int zebra_evpn_from_svi_ns(struct ns *ns, + void *_in_param, + void **_p_zevpn) { + struct zebra_ns *zns = ns->info; struct route_node *rn; struct interface *br_if; zebra_evpn_t **p_zevpn = (zebra_evpn_t **)_p_zevpn; @@ -720,7 +722,7 @@ static int zebra_evpn_from_svi_zns(struct zebra_ns *zns, int found = 0; if (!in_param) - return ZNS_WALK_STOP; + return NS_WALK_STOP; br_if = in_param->br_if; zif = in_param->zif; assert(zif); @@ -748,12 +750,12 @@ static int zebra_evpn_from_svi_zns(struct zebra_ns *zns, } if (!found) - return ZNS_WALK_CONTINUE; + return NS_WALK_CONTINUE; zevpn = zebra_evpn_lookup(vxl->vni); if (p_zevpn) *p_zevpn = zevpn; - return ZNS_WALK_STOP; + return NS_WALK_STOP; } /* @@ -799,8 +801,8 @@ zebra_evpn_t *zebra_evpn_from_svi(struct interface *ifp, in_param.zif = zif; p_zevpn = &zevpn; /* See if this interface (or interface plus VLAN Id) maps to a VxLAN */ - zebra_ns_list_walk(zebra_evpn_from_svi_zns, (void *)&in_param, - (void **)p_zevpn); + ns_walk_func(zebra_evpn_from_svi_ns, (void *)&in_param, + (void **)p_zevpn); return zevpn; } diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 13864cd429..6462daf687 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -153,20 +153,25 @@ static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete) /* During zebra shutdown, do partial cleanup while the async dataplane * is still running. */ -int zebra_ns_early_shutdown(struct ns *ns) +int zebra_ns_early_shutdown(struct ns *ns, + void *param_in __attribute__((unused)), + void **param_out __attribute__((unused))) { struct zebra_ns *zns = ns->info; if (zns == NULL) return 0; - return zebra_ns_disable_internal(zns, false); + zebra_ns_disable_internal(zns, false); + return NS_WALK_CONTINUE; } /* During zebra shutdown, do final cleanup * after all dataplane work is complete. */ -int zebra_ns_final_shutdown(struct ns *ns) +int zebra_ns_final_shutdown(struct ns *ns, + void *param_in __attribute__((unused)), + void **param_out __attribute__((unused))) { struct zebra_ns *zns = ns->info; @@ -175,7 +180,7 @@ int zebra_ns_final_shutdown(struct ns *ns) kernel_terminate(zns, true); - return 0; + return NS_WALK_CONTINUE; } int zebra_ns_init(const char *optional_default_name) @@ -233,25 +238,3 @@ 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 fa2fd47c25..f7d1f40782 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -67,19 +67,14 @@ struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id); int zebra_ns_init(const char *optional_default_name); int zebra_ns_enable(ns_id_t ns_id, void **info); int zebra_ns_disabled(struct ns *ns); -int zebra_ns_early_shutdown(struct ns *ns); -int zebra_ns_final_shutdown(struct ns *ns); - +int zebra_ns_early_shutdown(struct ns *ns, + void *param_in __attribute__((unused)), + void **param_out __attribute__((unused))); +int zebra_ns_final_shutdown(struct ns *ns, + void *param_in __attribute__((unused)), + void **param_out __attribute__((unused))); 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 6332854e73..61498973e9 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -782,10 +782,11 @@ static void zl3vni_print_hash_detail(struct hash_bucket *bucket, void *data) vty_out(vty, "\n"); } -static int zvni_map_to_svi_ns(struct zebra_ns *zns, +static int zvni_map_to_svi_ns(struct ns *ns, void *_in_param, void **_p_ifp) { + struct zebra_ns *zns = ns->info; struct route_node *rn; struct zebra_from_svi_param *in_param = (struct zebra_from_svi_param *)_in_param; @@ -795,7 +796,7 @@ static int zvni_map_to_svi_ns(struct zebra_ns *zns, struct zebra_if *zif; if (!in_param) - return ZNS_WALK_STOP; + return NS_WALK_STOP; /* TODO: Optimize with a hash. */ for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { @@ -812,10 +813,10 @@ static int zvni_map_to_svi_ns(struct zebra_ns *zns, if (vl->vid == in_param->vid) { if (p_ifp) *p_ifp = tmp_if; - return ZNS_WALK_STOP; + return NS_WALK_STOP; } } - return ZNS_WALK_CONTINUE; + return NS_WALK_CONTINUE; } /* Map to SVI on bridge corresponding to specified VLAN. This can be one @@ -850,8 +851,8 @@ struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if) in_param.zif = NULL; p_ifp = &tmp_if; /* Identify corresponding VLAN interface. */ - zebra_ns_list_walk(zvni_map_to_svi_ns, (void *)&in_param, - (void **)p_ifp); + ns_walk_func(zvni_map_to_svi_ns, (void *)&in_param, + (void **)p_ifp); return tmp_if; } @@ -865,10 +866,11 @@ static int zebra_evpn_vxlan_del(zebra_evpn_t *zevpn) return zebra_evpn_del(zevpn); } -static int zevpn_build_hash_table_zns(struct zebra_ns *zns, +static int zevpn_build_hash_table_zns(struct ns *ns, void *param_in __attribute__((unused)), void **param_out __attribute__((unused))) { + struct zebra_ns *zns = ns->info; struct route_node *rn; struct interface *ifp; struct zebra_vrf *zvrf; @@ -876,7 +878,7 @@ static int zevpn_build_hash_table_zns(struct zebra_ns *zns, zvrf = zebra_vrf_get_evpn(); if (!zvrf) - return ZNS_WALK_STOP; + return NS_WALK_STOP; /* Walk VxLAN interfaces and create EVPN hash. */ for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { @@ -972,7 +974,7 @@ static int zevpn_build_hash_table_zns(struct zebra_ns *zns, zlog_debug( "Failed to add EVPN hash, IF %s(%u) L2-VNI %u", ifp->name, ifp->ifindex, vni); - return ZNS_WALK_CONTINUE; + return NS_WALK_CONTINUE; } if (zevpn->local_vtep_ip.s_addr != @@ -1014,7 +1016,7 @@ static int zevpn_build_hash_table_zns(struct zebra_ns *zns, } } } - return ZNS_WALK_CONTINUE; + return NS_WALK_CONTINUE; } /* @@ -1024,9 +1026,9 @@ static int zevpn_build_hash_table_zns(struct zebra_ns *zns, static void zevpn_build_hash_table(void) { - zebra_ns_list_walk(zevpn_build_hash_table_zns, - (void *)NULL, - (void **)NULL); + ns_walk_func(zevpn_build_hash_table_zns, + (void *)NULL, + (void **)NULL); } /* @@ -1659,10 +1661,11 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni) return 0; } -static int zl3vni_map_to_vxlan_if_zns(struct zebra_ns *zns, - void *_zl3vni, - void **_pifp) +static int zl3vni_map_to_vxlan_if_ns(struct ns *ns, + void *_zl3vni, + void **_pifp) { + struct zebra_ns *zns = ns->info; zebra_l3vni_t *zl3vni = (zebra_l3vni_t *)_zl3vni; struct route_node *rn = NULL; struct interface *ifp = NULL; @@ -1671,7 +1674,7 @@ static int zl3vni_map_to_vxlan_if_zns(struct zebra_ns *zns, zvrf = zebra_vrf_get_evpn(); if (!zvrf) - return ZNS_WALK_STOP; + return NS_WALK_STOP; /* loop through all vxlan-interface */ for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) { @@ -1705,10 +1708,10 @@ static int zl3vni_map_to_vxlan_if_zns(struct zebra_ns *zns, zl3vni->local_vtep_ip = vxl->vtep_ip; if (_pifp) *_pifp = (void *)ifp; - return ZNS_WALK_STOP; + return NS_WALK_STOP; } - return ZNS_WALK_CONTINUE; + return NS_WALK_CONTINUE; } struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni) @@ -1718,8 +1721,8 @@ struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni) p_ifp = &ifp; - zebra_ns_list_walk(zl3vni_map_to_vxlan_if_zns, - (void *)zl3vni, (void **)p_ifp); + ns_walk_func(zl3vni_map_to_vxlan_if_ns, + (void *)zl3vni, (void **)p_ifp); return ifp; } @@ -5521,20 +5524,24 @@ stream_failure: return; } -static int macfdb_read_zns(struct zebra_ns *zns, - void *_in_param __attribute__((unused)), - void **out_param __attribute__((unused))) +static int macfdb_read_ns(struct ns *ns, + void *_in_param __attribute__((unused)), + void **out_param __attribute__((unused))) { + struct zebra_ns *zns = ns->info; + macfdb_read(zns); - return ZNS_WALK_CONTINUE; + return NS_WALK_CONTINUE; } -static int neigh_read_zns(struct zebra_ns *zns, - void *_in_param __attribute__((unused)), - void **out_param __attribute__((unused))) +static int neigh_read_ns(struct ns *ns, + void *_in_param __attribute__((unused)), + void **out_param __attribute__((unused))) { + struct zebra_ns *zns = ns->info; + neigh_read(zns); - return ZNS_WALK_CONTINUE; + return NS_WALK_CONTINUE; } /* @@ -5588,10 +5595,10 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) zebra_evpn_gw_macip_add_for_evpn_hash, NULL); /* Read the MAC FDB */ - zebra_ns_list_walk(macfdb_read_zns, NULL, NULL); + ns_walk_func(macfdb_read_ns, NULL, NULL); /* Read neighbors */ - zebra_ns_list_walk(neigh_read_zns, NULL, NULL); + ns_walk_func(neigh_read_ns, NULL, NULL); } else { /* Cleanup VTEPs for all EVPNs - uninstall from * kernel and free entries. -- cgit v1.2.3 From a1ce03e1fd7280799b6433ae51f5af57a5cacf5e Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 6 Feb 2020 09:33:21 +0100 Subject: zebra: support for macvlan interfaces mac vlan interfaces are supported in different network namespaces. Signed-off-by: Philippe Guibert --- zebra/zebra_evpn.c | 69 +++++++++++++++++++++++++++++++++++++----------------- zebra/zebra_evpn.h | 1 + 2 files changed, 49 insertions(+), 21 deletions(-) (limited to 'zebra/zebra_evpn.c') diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index 0f5e77ac65..80124f92b3 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -806,16 +806,51 @@ zebra_evpn_t *zebra_evpn_from_svi(struct interface *ifp, return zevpn; } +static int zvni_map_to_macvlan_ns(struct ns *ns, + void *_in_param, + void **_p_ifp) +{ + struct zebra_ns *zns = ns->info; + struct zebra_from_svi_param *in_param = + (struct zebra_from_svi_param *)_in_param; + struct interface **p_ifp = (struct interface **)_p_ifp; + struct route_node *rn; + struct interface *tmp_if = NULL; + struct zebra_if *zif; + + if (!in_param) + return NS_WALK_STOP; + + /* Identify corresponding VLAN interface. */ + 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_MACVLAN) + continue; + + if (zif->link == in_param->svi_if) { + if (p_ifp) + *p_ifp = tmp_if; + return NS_WALK_STOP; + } + } + + return NS_WALK_CONTINUE; +} + /* Map to MAC-VLAN interface corresponding to specified SVI interface. */ struct interface *zebra_evpn_map_to_macvlan(struct interface *br_if, struct interface *svi_if) { - struct zebra_ns *zns; - struct route_node *rn; struct interface *tmp_if = NULL; struct zebra_if *zif; - int found = 0; + struct interface **p_ifp; + struct zebra_from_svi_param in_param; /* Defensive check, caller expected to invoke only with valid bridge. */ if (!br_if) @@ -830,25 +865,17 @@ struct interface *zebra_evpn_map_to_macvlan(struct interface *br_if, zif = br_if->info; assert(zif); - /* Identify corresponding VLAN interface. */ - zns = zebra_ns_lookup(NS_DEFAULT); - 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_MACVLAN) - continue; - - if (zif->link == svi_if) { - found = 1; - break; - } - } + in_param.vid = 0; + in_param.br_if = br_if; + in_param.zif = NULL; + in_param.svi_if = svi_if; + p_ifp = &tmp_if; - return found ? tmp_if : NULL; + /* Identify corresponding VLAN interface. */ + ns_walk_func(zvni_map_to_macvlan_ns, + (void *)&in_param, + (void **)p_ifp); + return tmp_if; } /* diff --git a/zebra/zebra_evpn.h b/zebra/zebra_evpn.h index 7b08a3f485..27392ec85c 100644 --- a/zebra/zebra_evpn.h +++ b/zebra/zebra_evpn.h @@ -126,6 +126,7 @@ struct zebra_evpn_t_ { /* for parsing evpn and vni contexts */ struct zebra_from_svi_param { struct interface *br_if; + struct interface *svi_if; struct zebra_if *zif; uint8_t bridge_vlan_aware; vlanid_t vid; -- cgit v1.2.3