summaryrefslogtreecommitdiff
path: root/zebra/zebra_vxlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_vxlan.c')
-rw-r--r--zebra/zebra_vxlan.c93
1 files changed, 60 insertions, 33 deletions
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index aede4098b4..c13c867d2a 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -1798,6 +1798,51 @@ 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)
+{
+ int found = 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_if *zif = NULL;
+ struct zebra_l2info_vxlan *vxl = NULL;
+
+ if (!in_param)
+ return NS_WALK_STOP;
+
+ /* 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;
+ vxl = &zif->l2info.vxl;
+
+ if (zif->brslave_info.br_if != in_param->br_if)
+ continue;
+
+ if (!in_param->bridge_vlan_aware
+ || vxl->access_vlan == in_param->vid) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return NS_WALK_CONTINUE;
+
+ if (p_zl3vni)
+ *p_zl3vni = zl3vni_lookup(vxl->vni);
+ return NS_WALK_STOP;
+}
+
/*
* Map SVI and associated bridge to a VNI. This is invoked upon getting
* neighbor notifications, to see if they are of interest.
@@ -1805,16 +1850,11 @@ struct zebra_l3vni *zl3vni_from_vrf(vrf_id_t vrf_id)
static struct zebra_l3vni *zl3vni_from_svi(struct interface *ifp,
struct interface *br_if)
{
- int found = 0;
- vlanid_t vid = 0;
- uint8_t bridge_vlan_aware = 0;
struct zebra_l3vni *zl3vni = NULL;
- struct zebra_ns *zns = NULL;
- struct route_node *rn = NULL;
struct zebra_if *zif = NULL;
- struct interface *tmp_if = NULL;
struct zebra_l2info_bridge *br = NULL;
- struct zebra_l2info_vxlan *vxl = NULL;
+ struct zebra_from_svi_param in_param = {};
+ struct zebra_l3vni **p_zl3vni;
if (!br_if)
return NULL;
@@ -1822,13 +1862,14 @@ 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);
br = &zif->l2info.br;
- bridge_vlan_aware = br->vlan_aware;
- if (bridge_vlan_aware) {
+ in_param.bridge_vlan_aware = br->vlan_aware;
+ if (in_param.bridge_vlan_aware) {
struct zebra_l2info_vlan *vl;
if (!IS_ZEBRA_IF_VLAN(ifp))
@@ -1837,36 +1878,15 @@ static struct zebra_l3vni *zl3vni_from_svi(struct interface *ifp,
zif = ifp->info;
assert(zif);
vl = &zif->l2info.vl;
- vid = vl->vid;
+ in_param.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)
- continue;
- zif = tmp_if->info;
- if (!zif || zif->zif_type != ZEBRA_IF_VXLAN)
- continue;
- if (!if_is_operative(tmp_if))
- continue;
- vxl = &zif->l2info.vxl;
-
- if (zif->brslave_info.br_if != br_if)
- continue;
- if (!bridge_vlan_aware || vxl->access_vlan == vid) {
- found = 1;
- break;
- }
- }
+ p_zl3vni = &zl3vni;
- if (!found)
- return NULL;
-
- zl3vni = zl3vni_lookup(vxl->vni);
+ ns_walk_func(zl3vni_from_svi_ns, (void *)&in_param, (void **)p_zl3vni);
return zl3vni;
}
@@ -5023,6 +5043,13 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
return 0;
}
+ if ((chgflags & ZEBRA_VXLIF_MASTER_MAC_CHANGE)
+ && if_is_operative(ifp) && is_l3vni_oper_up(zl3vni)) {
+ zebra_vxlan_process_l3vni_oper_down(zl3vni);
+ zebra_vxlan_process_l3vni_oper_up(zl3vni);
+ return 0;
+ }
+
/* access-vlan change - process oper down, associate with new
* svi_if and then process oper up again
*/