From 9d277b8c5239963bc6037f014e6c5fda5fa1c646 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 27 Sep 2019 11:17:20 +0200 Subject: [PATCH] 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(-) 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; } -- 2.39.5