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.c289
1 files changed, 188 insertions, 101 deletions
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index f99c16ae91..a3f43f947a 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -204,13 +204,18 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
if (json == NULL) {
vty_out(vty, " Remote VTEP: %s",
inet_ntoa(n->r_vtep_ip));
- vty_out(vty, " State: %s", IS_ZEBRA_NEIGH_ACTIVE(n)
- ? "Active"
- : "Inactive");
} else
json_object_string_add(json, "remoteVtep",
inet_ntoa(n->r_vtep_ip));
}
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
+ if (!json) {
+ vty_out(vty, "\n");
+ vty_out(vty, " State: %s",
+ IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active"
+ : "Inactive");
+ }
+ }
if (json == NULL)
vty_out(vty, "\n");
}
@@ -384,8 +389,8 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
vty_out(vty, " Auto Mac ");
}
- vty_out(vty, " ARP ref: %u\n", mac->neigh_refcnt);
+ vty_out(vty, "\n");
/* print all the associated neigh */
vty_out(vty, " Neighbors:\n");
if (!listcount(mac->neigh_list))
@@ -1155,14 +1160,15 @@ static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n)
if (!(n->flags & ZEBRA_NEIGH_REMOTE))
return 0;
- zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
- assert(zvrf);
if (!zvni->vxlan_if) {
zlog_err("VNI %u hash %p couldn't be uninstalled - no intf",
zvni->vni, zvni);
return -1;
}
+ zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+ assert(zvrf);
+
zif = zvni->vxlan_if->info;
if (!zif)
return -1;
@@ -1343,8 +1349,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
zlog_err(
"%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
- prefix_mac2str(macaddr, NULL,
- ETHER_ADDR_STRLEN),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
ifp->name, ifp->ifindex, zvni->vni);
return -1;
}
@@ -1355,14 +1360,11 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
memcpy(&n->emac, macaddr, ETH_ALEN);
n->ifindex = ifp->ifindex;
- /* We have a neigh associated to mac increment the refcnt*/
- mac->neigh_refcnt++;
-
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s add to BGP",
ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
- prefix_mac2str(macaddr, NULL, ETHER_ADDR_STRLEN),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
ipaddr2str(ip, buf2, sizeof(buf2)));
zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, macaddr,
@@ -1380,6 +1382,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
struct zebra_vrf *zvrf = NULL;
zebra_neigh_t *n = NULL;
zebra_mac_t *mac = NULL;
+ char buf1[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
@@ -1393,11 +1396,13 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
/* mac entry should be present */
mac = zvni_mac_lookup(zvni, &n->emac);
- if (!mac)
- zlog_err("%u: MAC %s doesnt exsists for neigh %s on VNI %u",
+ if (!mac) {
+ zlog_err("%u: MAC %s doesnt exists for neigh %s on VNI %u",
ifp->vrf_id,
- prefix_mac2str(&n->emac, NULL, ETHER_ADDR_STRLEN),
+ prefix_mac2str(&n->emac, buf1, sizeof(buf1)),
ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
+ return -1;
+ }
/* If the entry is not local nothing to do*/
if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
@@ -1407,7 +1412,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
zlog_debug(
"%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
ifp->vrf_id, ifp->name, ifp->ifindex, zvni->vni,
- prefix_mac2str(&(n->emac), NULL, ETHER_ADDR_STRLEN),
+ prefix_mac2str(&(n->emac), buf1, sizeof(buf1)),
ipaddr2str(ip, buf2, sizeof(buf2)));
/* Remove neighbor from BGP. */
@@ -1418,7 +1423,8 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
zvni_neigh_del(zvni, n);
/* see if the mac needs to be deleted as well*/
- zvni_deref_ip2mac(zvni, mac, 0);
+ if (mac)
+ zvni_deref_ip2mac(zvni, mac, 0);
return 0;
}
@@ -1431,13 +1437,22 @@ static void zvni_gw_macip_del_for_vni_hash(struct hash_backet *backet,
struct zebra_l2info_vxlan zl2_info;
struct interface *vlan_if = NULL;
struct interface *vrr_if = NULL;
+ struct interface *ifp;
/* Add primary SVI MAC*/
zvni = (zebra_vni_t *)backet->data;
if (!zvni)
return;
- zif = zvni->vxlan_if->info;
+ ifp = zvni->vxlan_if;
+ if (!ifp)
+ return;
+ zif = ifp->info;
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ return;
+
zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
@@ -1464,6 +1479,7 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
struct zebra_l2info_vxlan zl2_info;
struct interface *vlan_if = NULL;
struct interface *vrr_if = NULL;
+ struct interface *ifp = NULL;
zvni = (zebra_vni_t *)backet->data;
if (!zvni)
@@ -1472,7 +1488,14 @@ static void zvni_gw_macip_add_for_vni_hash(struct hash_backet *backet,
if (!advertise_gw_macip_enabled(zvrf, zvni))
return;
- zif = zvni->vxlan_if->info;
+ ifp = zvni->vxlan_if;
+ if (!ifp)
+ return;
+ zif = ifp->info;
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ return;
zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,
@@ -1758,6 +1781,9 @@ static zebra_vni_t *zvni_map_svi(struct interface *ifp, struct interface *br_if)
vlanid_t vid = 0;
zebra_vni_t *zvni;
+ if (!br_if)
+ return NULL;
+
/* Make sure the linked interface is a bridge. */
if (!IS_ZEBRA_IF_BRIDGE(br_if))
return NULL;
@@ -1827,6 +1853,10 @@ static struct interface *zvni_map_to_svi(struct zebra_vrf *zvrf, vlanid_t vid,
struct zebra_l2info_vlan *vl;
u_char bridge_vlan_aware;
+ /* Defensive check, caller expected to invoke only with valid bridge. */
+ if (!br_if)
+ return NULL;
+
/* Determine if bridge is VLAN-aware or not */
zif = br_if->info;
assert(zif);
@@ -1943,10 +1973,8 @@ static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt)
static void zvni_deref_ip2mac(zebra_vni_t *zvni, zebra_mac_t *mac,
int uninstall)
{
- if (mac->neigh_refcnt)
- mac->neigh_refcnt--;
-
- if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) || mac->neigh_refcnt > 0)
+ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)
+ || !list_isempty(mac->neigh_list))
return;
if (uninstall)
@@ -2853,7 +2881,7 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
/* see if the AUTO mac needs to be deleted */
if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
- || !listcount(zmac->neigh_list))
+ && !listcount(zmac->neigh_list))
zvni_mac_del(zvni, zmac);
return 0;
@@ -2872,10 +2900,9 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
zebra_vni_t *zvni;
zebra_neigh_t *n;
struct zebra_vrf *zvrf;
- zebra_mac_t *zmac;
+ zebra_mac_t *zmac, *old_zmac;
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
- int send_upd = 1, send_del = 0;
/* We are only interested in neighbors on an SVI that resides on top
* of a VxLAN bridge.
@@ -2930,19 +2957,33 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
if (memcmp(n->emac.octet, macaddr->octet,
ETH_ALEN)
== 0) {
- if (n->ifindex == ifp->ifindex)
- /* we're not interested in whatever has
- * changed. */
- return 0;
- /* client doesn't care about a purely local
- * change. */
- send_upd = 0;
- } else
- /* If the MAC has changed, issue a delete first
- * as this means a
- * different MACIP route.
+ /* Update any params and return - client doesn't
+ * care about a purely local change.
*/
- send_del = 1;
+ n->ifindex = ifp->ifindex;
+ return 0;
+ }
+
+ /* If the MAC has changed,
+ * need to issue a delete first
+ * as this means a different MACIP route.
+ * Also, need to do some unlinking/relinking.
+ */
+ zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip,
+ &n->emac, 0);
+ old_zmac = zvni_mac_lookup(zvni, &n->emac);
+ if (old_zmac) {
+ listnode_delete(old_zmac->neigh_list, n);
+ zvni_deref_ip2mac(zvni, old_zmac, 0);
+ }
+
+ /* Set "local" forwarding info. */
+ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+ n->ifindex = ifp->ifindex;
+ memcpy(&n->emac, macaddr, ETH_ALEN);
+
+ /* Link to new MAC */
+ listnode_add_sort(zmac->neigh_list, n);
} else if (ext_learned)
/* The neighbor is remote and that is the notification we got.
*/
@@ -2954,6 +2995,8 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
{
UNSET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
n->r_vtep_ip.s_addr = 0;
+ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+ n->ifindex = ifp->ifindex;
}
} else {
n = zvni_neigh_add(zvni, ip, macaddr);
@@ -2965,17 +3008,11 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
ifp->name, ifp->ifindex, zvni->vni);
return -1;
}
+ /* Set "local" forwarding info. */
+ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
+ n->ifindex = ifp->ifindex;
}
- /* Issue delete for older info, if needed. */
- if (send_del)
- zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
- 0);
-
- /* Set "local" forwarding info. */
- SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
- n->ifindex = ifp->ifindex;
-
/* Before we program this in BGP, we need to check if MAC is locally
* learnt as well */
if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) {
@@ -2989,23 +3026,18 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
return 0;
}
- /* Inform BGP if required. */
- if (send_upd) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
- ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- zvni->vni);
-
- ZEBRA_NEIGH_SET_ACTIVE(n);
- return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
- macaddr, 0);
- }
+ /* Inform BGP. */
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%u: neigh %s (MAC %s) is now ACTIVE on VNI %u",
+ ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ zvni->vni);
- return 0;
+ ZEBRA_NEIGH_SET_ACTIVE(n);
+ return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip, macaddr, 0);
}
+
/*
* Handle message from client to delete a remote MACIP for a VNI.
*/
@@ -3023,6 +3055,8 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
u_short l = 0, ipa_len;
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
+ struct interface *ifp = NULL;
+ struct zebra_if *zif = NULL;
s = client->ibuf;
@@ -3065,12 +3099,18 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
zvrf_id(zvrf), vni);
continue;
}
- if (!zvni->vxlan_if) {
+ ifp = zvni->vxlan_if;
+ if (!ifp) {
zlog_err(
"VNI %u hash %p doesn't have intf upon remote MACIP DEL",
vni, zvni);
continue;
}
+ zif = ifp->info;
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ continue;
/* The remote VTEP specified is normally expected to exist, but
* it is
@@ -3083,12 +3123,6 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
if (!zvni_vtep_find(zvni, &vtep_ip))
continue;
- /* If the local VxLAN interface is not up (should be a transient
- * event), there's nothing more to do.
- */
- if (!if_is_operative(zvni->vxlan_if))
- continue;
-
mac = zvni_mac_lookup(zvni, &macaddr);
if (ipa_len)
n = zvni_neigh_lookup(zvni, &ip);
@@ -3132,7 +3166,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
zvni_process_neigh_on_remote_mac_del(zvrf, zvni,
mac);
- if (!mac->neigh_refcnt) {
+ if (list_isempty(mac->neigh_list)) {
zvni_mac_uninstall(zvni, mac, 0);
zvni_mac_del(zvni, mac);
} else
@@ -3166,6 +3200,8 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
u_char sticky;
+ struct interface *ifp = NULL;
+ struct zebra_if *zif = NULL;
assert(EVPN_ENABLED(zvrf));
@@ -3213,16 +3249,17 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
zvrf_id(zvrf), vni);
continue;
}
- if (!zvni->vxlan_if) {
+ ifp = zvni->vxlan_if;
+ if (!ifp) {
zlog_err(
"VNI %u hash %p doesn't have intf upon remote MACIP add",
vni, zvni);
continue;
}
- /* If the local VxLAN interface is not up (should be a transient
- * event), there's nothing more to do.
- */
- if (!if_is_operative(zvni->vxlan_if))
+ zif = ifp->info;
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
continue;
/* The remote VTEP specified should normally exist, but it is
@@ -3272,9 +3309,6 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
/* Is this MAC created for a MACIP? */
if (ipa_len)
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
- } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
- /* Moving from local to remote, issue delete. */
- zvni_mac_uninstall(zvni, mac, 1);
}
/* Set "auto" and "remote" forwarding info. */
@@ -3326,16 +3360,16 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
return -1;
}
- /* New neighbor referring to this MAC. */
- mac->neigh_refcnt++;
} else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
!= 0) {
- /* MAC change, update ref counts for old and new
- * MAC. */
+ /* MAC change, update neigh list for old and new
+ * mac */
old_mac = zvni_mac_lookup(zvni, &n->emac);
- if (old_mac)
+ if (old_mac) {
+ listnode_delete(old_mac->neigh_list, n);
zvni_deref_ip2mac(zvni, old_mac, 1);
- mac->neigh_refcnt++;
+ }
+ listnode_add_sort(mac->neigh_list, n);
memcpy(&n->emac, &macaddr, ETH_ALEN);
}
@@ -3687,6 +3721,8 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
struct in_addr vtep_ip;
zebra_vni_t *zvni;
zebra_vtep_t *zvtep;
+ struct interface *ifp;
+ struct zebra_if *zif;
s = client->ibuf;
@@ -3713,6 +3749,19 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, u_short length,
continue;
}
+ ifp = zvni->vxlan_if;
+ if (!ifp) {
+ zlog_err(
+ "VNI %u hash %p doesn't have intf upon remote VTEP DEL",
+ zvni->vni, zvni);
+ continue;
+ }
+ zif = ifp->info;
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ continue;
+
/* If the remote VTEP does not exist, there's nothing more to
* do.
* Otherwise, uninstall any remote MACs pointing to this VTEP
@@ -3743,6 +3792,8 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
vni_t vni;
struct in_addr vtep_ip;
zebra_vni_t *zvni;
+ struct interface *ifp;
+ struct zebra_if *zif;
assert(EVPN_ENABLED(zvrf));
@@ -3768,24 +3819,24 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, u_short length,
zvrf_id(zvrf), vni);
continue;
}
- if (!zvni->vxlan_if) {
+
+ ifp = zvni->vxlan_if;
+ if (!ifp) {
zlog_err(
"VNI %u hash %p doesn't have intf upon remote VTEP ADD",
zvni->vni, zvni);
continue;
}
+ zif = ifp->info;
- /* If the remote VTEP already exists, or the local VxLAN
- * interface is
- * not up (should be a transient event), there's nothing more
- * to do.
- * Otherwise, add and install the entry.
- */
- if (zvni_vtep_find(zvni, &vtep_ip))
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
continue;
- if (!if_is_operative(zvni->vxlan_if))
+ /* If the remote VTEP already exists,
+ there's nothing more to do. */
+ if (zvni_vtep_find(zvni, &vtep_ip))
continue;
if (zvni_vtep_add(zvni, &vtep_ip) == NULL) {
@@ -3839,7 +3890,11 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
if (!ifp_zif)
return -1;
- svi_if = ifp_zif->link;
+ /*
+ * for a MACVLAN interface the link represents the svi_if
+ */
+ svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+ ifp_zif->link_ifindex);
if (!svi_if) {
zlog_err("%u:MACVLAN %s(%u) without link information",
ifp->vrf_id, ifp->name, ifp->ifindex);
@@ -3847,19 +3902,37 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
}
if (IS_ZEBRA_IF_VLAN(svi_if)) {
+ /*
+ * If it is a vlan aware bridge then the link gives the
+ * bridge information
+ */
+ struct interface *svi_if_link = NULL;
+
svi_if_zif = svi_if->info;
- if (svi_if_zif)
- zvni = zvni_map_svi(svi_if, svi_if_zif->link);
+ if (svi_if_zif) {
+ svi_if_link = if_lookup_by_index_per_ns(
+ zebra_ns_lookup(NS_DEFAULT),
+ svi_if_zif->link_ifindex);
+ zvni = zvni_map_svi(svi_if, svi_if_link);
+ }
} else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
+ /*
+ * If it is a vlan unaware bridge then svi is the bridge
+ * itself
+ */
zvni = zvni_map_svi(svi_if, svi_if);
}
} else if (IS_ZEBRA_IF_VLAN(ifp)) {
struct zebra_if *svi_if_zif =
- NULL; /* Zebra daemon specific info for SVI*/
+ NULL; /* Zebra daemon specific info for SVI */
+ struct interface *svi_if_link =
+ NULL; /* link info for the SVI = bridge info */
svi_if_zif = ifp->info;
- if (svi_if_zif)
- zvni = zvni_map_svi(ifp, svi_if_zif->link);
+ svi_if_link = if_lookup_by_index_per_ns(
+ zebra_ns_lookup(NS_DEFAULT), svi_if_zif->link_ifindex);
+ if (svi_if_zif && svi_if_link)
+ zvni = zvni_map_svi(ifp, svi_if_link);
} else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
zvni = zvni_map_svi(ifp, ifp);
}
@@ -4141,7 +4214,7 @@ int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
vxl->access_vlan, inet_ntoa(vxl->vtep_ip),
zif->brslave_info.bridge_ifindex, chgflags);
- /* Removed from bridge? */
+ /* Removed from bridge? Cleanup and return */
if ((chgflags & ZEBRA_VXLIF_MASTER_CHANGE)
&& (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
/* Delete from client, remove all remote VTEPs */
@@ -4150,7 +4223,11 @@ int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags)
zvni_neigh_del_all(zvrf, zvni, 1, 0, DEL_ALL_NEIGH);
zvni_mac_del_all(zvrf, zvni, 1, 0, DEL_ALL_MAC);
zvni_vtep_del_all(zvni, 1);
- } else if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
+ return 0;
+ }
+
+ /* Handle other changes. */
+ if (chgflags & ZEBRA_VXLIF_VLAN_CHANGE) {
/* Remove all existing local neighbors and MACs for this VNI
* (including from BGP)
*/
@@ -4268,6 +4345,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
int advertise;
vni_t vni = 0;
zebra_vni_t *zvni = NULL;
+ struct interface *ifp = NULL;
s = client->ibuf;
advertise = stream_getc(s);
@@ -4318,7 +4396,16 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, int sock,
zvni->advertise_gw_macip = advertise;
- zif = zvni->vxlan_if->info;
+ ifp = zvni->vxlan_if;
+ if (!ifp)
+ return 0;
+
+ zif = ifp->info;
+
+ /* If down or not mapped to a bridge, we're done. */
+ if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
+ return 0;
+
zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zvrf, zl2_info.access_vlan,