summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitesh Kanjariya <mitesh@marvel-07.cumulusnetworks.com>2017-07-05 15:03:14 -0700
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-08-08 10:28:51 -0400
commitb6938a74e5f73a2f29df12efb46e7121e79d3b86 (patch)
treed63cb21ae9fc8e3bd5e441a653bf89c1a083ca44
parent640751c7acc8ea2236a0d46d9663849573e56e3f (diff)
zebra: Provide neigh-mac tie-in in zebra
Currently, FRR does not do any linking between local MACs and neighbors. We found this necessary when dealing with centralized GW. A neigh is considered local only when the mac is learnt locally as well. Ticket: CM-16544 Review: CCR-6388 Unit-test: Manual/Evpn-Smoke Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
-rw-r--r--zebra/zebra_vxlan.c331
-rw-r--r--zebra/zebra_vxlan_private.h19
2 files changed, 323 insertions, 27 deletions
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index cb555ff1ee..393ac997b3 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -74,7 +74,8 @@ static int zvni_macip_send_msg_to_client(struct zebra_vrf *zvrf, vni_t vni,
static unsigned int neigh_hash_keymake(void *p);
static int neigh_cmp(const void *p1, const void *p2);
static void *zvni_neigh_alloc(void *p);
-static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip);
+static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
+ struct ethaddr *mac);
static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n);
static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg);
static void zvni_neigh_del_from_vtep(zebra_vni_t *zvni, int uninstall,
@@ -200,10 +201,13 @@ static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json)
json_object_string_add(json, "mac", buf1);
}
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
- if (json == NULL)
+ if (json == NULL) {
vty_out(vty, " Remote VTEP: %s",
inet_ntoa(n->r_vtep_ip));
- else
+ 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));
}
@@ -353,7 +357,10 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
{
struct vty *vty;
+ zebra_neigh_t *n = NULL;
+ struct listnode *node = NULL;
char buf1[20];
+ char buf2[INET6_ADDRSTRLEN];
vty = (struct vty *)ctxt;
vty_out(vty, "MAC: %s",
@@ -371,11 +378,30 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex);
if (mac->fwd_info.local.vid)
vty_out(vty, " VLAN: %u", mac->fwd_info.local.vid);
- } else {
+ } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
vty_out(vty, " Remote VTEP: %s",
inet_ntoa(mac->fwd_info.r_vtep_ip));
+ } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
+ vty_out(vty, " Auto Mac ");
+ }
+ vty_out(vty, " ARP ref: %u\n", mac->neigh_refcnt);
+
+ /* print all the associated neigh */
+ vty_out(vty, " Neighbors:\n");
+ if (!listcount(mac->neigh_list))
+ vty_out(vty, " No Neighbors\n");
+ else {
+ for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
+ vty_out(vty, " %s %s\n",
+ ipaddr2str(&n->ip, buf2, sizeof(buf2)),
+ CHECK_FLAG(n->flags, ZEBRA_MAC_LOCAL)
+ ? (IS_ZEBRA_NEIGH_ACTIVE(n)
+ ? "Active"
+ : "Inactive")
+ : "");
+ }
}
- vty_out(vty, " ARP ref: %u", mac->neigh_refcnt);
+
vty_out(vty, "\n");
}
@@ -432,7 +458,7 @@ static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt)
else
json_object_object_add(json_mac_hdr, buf1, json_mac);
wctx->count++;
- } else {
+ } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) {
if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
&wctx->r_vtep_ip)) {
@@ -789,16 +815,26 @@ static void *zvni_neigh_alloc(void *p)
/*
* Add neighbor entry.
*/
-static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip)
+static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
+ struct ethaddr *mac)
{
zebra_neigh_t tmp_n;
zebra_neigh_t *n = NULL;
+ zebra_mac_t *zmac = NULL;
memset(&tmp_n, 0, sizeof(zebra_neigh_t));
memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc);
assert(n);
+ memcpy(&n->emac, mac, ETH_ALEN);
+ n->state = ZEBRA_NEIGH_INACTIVE;
+
+ /* Associate the neigh to mac */
+ zmac = zvni_mac_lookup(zvni, mac);
+ if (zmac)
+ listnode_add_sort(zmac->neigh_list, n);
+
return n;
}
@@ -808,6 +844,11 @@ static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip)
static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n)
{
zebra_neigh_t *tmp_n;
+ zebra_mac_t *zmac = NULL;
+
+ zmac = zvni_mac_lookup(zvni, &n->emac);
+ if (zmac)
+ listnode_delete(zmac->neigh_list, n);
/* Free the VNI hash entry and allocated memory. */
tmp_n = hash_release(zvni->neigh_table, n);
@@ -907,6 +948,146 @@ static zebra_neigh_t *zvni_neigh_lookup(zebra_vni_t *zvni, struct ipaddr *ip)
return n;
}
+/* Process all neigh associated to a mac upon local mac add event */
+static void zvni_process_neigh_on_local_mac_add(struct zebra_vrf *zvrf,
+ zebra_vni_t *zvni,
+ zebra_mac_t *zmac)
+{
+ zebra_neigh_t *n = NULL;
+ struct listnode *node = NULL;
+ char buf[ETHER_ADDR_STRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+
+ for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
+ /* MAC is learnt locally, program all inactive neigh
+ * pointing to this mac */
+ if (IS_ZEBRA_NEIGH_INACTIVE(n)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "%u: neigh %s (MAC %s) on VNI %u is now ACTIVE",
+ zvrf_id(zvrf),
+ ipaddr2str(&n->ip, buf2,
+ sizeof(buf2)),
+ prefix_mac2str(&n->emac, buf,
+ sizeof(buf)),
+ zvni->vni);
+
+ ZEBRA_NEIGH_SET_ACTIVE(n);
+ zvni_neigh_send_add_to_client(
+ zvrf, zvni->vni, &n->ip, &n->emac, 0);
+ } else {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "%u: neigh %s (MAC %s) on VNI %u should NOT be ACTIVE",
+ zvrf_id(zvrf),
+ ipaddr2str(&n->ip, buf2,
+ sizeof(buf2)),
+ prefix_mac2str(&n->emac, buf,
+ sizeof(buf)),
+ zvni->vni);
+ }
+ } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
+ /* TODO: assume the neigh has moved too ?? */
+ }
+ }
+}
+
+/* Process all neigh associated to a mac upon local mac del event */
+static void zvni_process_neigh_on_local_mac_del(struct zebra_vrf *zvrf,
+ zebra_vni_t *zvni,
+ zebra_mac_t *zmac)
+{
+ zebra_neigh_t *n = NULL;
+ struct listnode *node = NULL;
+ char buf[ETHER_ADDR_STRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+
+ for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
+ if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "%u: neigh %s (MAC %s) on VNI %u is now INACTIVE",
+ zvrf_id(zvrf),
+ ipaddr2str(&n->ip, buf2,
+ sizeof(buf2)),
+ prefix_mac2str(&n->emac, buf,
+ sizeof(buf)),
+ zvni->vni);
+
+ ZEBRA_NEIGH_SET_INACTIVE(n);
+ zvni_neigh_send_del_to_client(
+ zvrf, zvni->vni, &n->ip, &n->emac, 0);
+ }
+ } else if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_err(
+ "%u: local MAC %s getting deleted on VNI %u has remote neigh %s",
+ zvrf_id(zvrf),
+ prefix_mac2str(&n->emac, buf,
+ sizeof(buf)),
+ zvni->vni,
+ ipaddr2str(&n->ip, buf2, sizeof(buf2)));
+ }
+ }
+}
+
+/* process all neigh associated to a mac entry upon remote mac add */
+static void zvni_process_neigh_on_remote_mac_add(struct zebra_vrf *zvrf,
+ zebra_vni_t *zvni,
+ zebra_mac_t *zmac)
+{
+ zebra_neigh_t *n = NULL;
+ struct listnode *node = NULL;
+ char buf[ETHER_ADDR_STRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+
+ for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
+ if (IS_ZEBRA_NEIGH_ACTIVE(n)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "%u: neigh %s (MAC %s) on VNI %u INACTIVE",
+ zvrf_id(zvrf),
+ ipaddr2str(&n->ip, buf2,
+ sizeof(buf2)),
+ prefix_mac2str(&n->emac, buf,
+ sizeof(buf)),
+ zvni->vni);
+
+ ZEBRA_NEIGH_SET_INACTIVE(n);
+ zvni_neigh_send_del_to_client(
+ zvrf, zvni->vni, &n->ip, &n->emac, 0);
+ }
+ }
+ }
+}
+
+/* process all neigh associated to mac entry upon remote mac del */
+static void zvni_process_neigh_on_remote_mac_del(struct zebra_vrf *zvrf,
+ zebra_vni_t *zvni,
+ zebra_mac_t *zmac)
+{
+ zebra_neigh_t *n = NULL;
+ struct listnode *node = NULL;
+ char buf[ETHER_ADDR_STRLEN];
+ char buf2[INET6_ADDRSTRLEN];
+
+ for (ALL_LIST_ELEMENTS_RO(zmac->neigh_list, node, n)) {
+ if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_err(
+ "%u: remote MAC %s getting deleted on VNI %u has local neigh %s",
+ zvrf_id(zvrf),
+ prefix_mac2str(&n->emac, buf,
+ sizeof(buf)),
+ zvni->vni,
+ ipaddr2str(&n->ip, buf2, sizeof(buf2)));
+ }
+ }
+}
+
/*
* Inform BGP about local neighbor addition.
*/
@@ -1153,7 +1334,7 @@ static int zvni_gw_macip_add(struct interface *ifp, zebra_vni_t *zvni,
n = zvni_neigh_lookup(zvni, ip);
if (!n) {
- n = zvni_neigh_add(zvni, ip);
+ n = zvni_neigh_add(zvni, ip, macaddr);
if (!n) {
zlog_err(
"%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
@@ -1366,6 +1547,9 @@ static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr)
mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
assert(mac);
+ mac->neigh_list = list_new();
+ mac->neigh_list->cmp = (int (*)(void *, void *))neigh_cmp;
+
return mac;
}
@@ -1376,6 +1560,8 @@ static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
{
zebra_mac_t *tmp_mac;
+ list_delete(mac->neigh_list);
+
/* Free the VNI hash entry and allocated memory. */
tmp_mac = hash_release(zvni->mac_table, mac);
if (tmp_mac)
@@ -2599,6 +2785,8 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
zebra_neigh_t *n;
struct zebra_vrf *zvrf;
char buf[INET6_ADDRSTRLEN];
+ char buf2[ETHER_ADDR_STRLEN];
+ zebra_mac_t *zmac;
/* We are only interested in neighbors on an SVI that resides on top
* of a VxLAN bridge.
@@ -2623,6 +2811,18 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
if (!n)
return 0;
+ zmac = zvni_mac_lookup(zvni, &n->emac);
+ if (!zmac) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_err(
+ "%u: trying to del a neigh %s without a mac %s on VNI %u",
+ ifp->vrf_id, ipaddr2str(ip, buf, sizeof(buf)),
+ prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
+ zvni->vni);
+
+ return 0;
+ }
+
/* If it is a remote entry, the kernel has aged this out or someone has
* deleted it, it needs to be re-installed as Quagga is the owner.
*/
@@ -2636,11 +2836,18 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
assert(zvrf);
/* Remove neighbor from BGP. */
- zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac, 0);
+ if (IS_ZEBRA_NEIGH_ACTIVE(n))
+ zvni_neigh_send_del_to_client(zvrf, zvni->vni, &n->ip, &n->emac,
+ 0);
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);
+ /* see if the AUTO mac needs to be deleted */
+ if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
+ || !listcount(zmac->neigh_list))
+ zvni_mac_del(zvni, zmac);
+
return 0;
}
@@ -2657,6 +2864,7 @@ 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;
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
int send_upd = 1, send_del = 0;
@@ -2681,6 +2889,30 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
ifp->ifindex, state, ext_learned ? "ext-learned " : "",
zvni->vni);
+ /* create a dummy MAC if the MAC is not already present */
+ zmac = zvni_mac_lookup(zvni, macaddr);
+ if (!zmac) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "%u: AUTO MAC %s created for neigh %s on VNI %u",
+ ifp->vrf_id,
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni);
+
+ zmac = zvni_mac_add(zvni, macaddr);
+ if (!zmac) {
+ zlog_warn("%u:Failed to add MAC %s VNI %u",
+ zvrf_id(zvrf),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ zvni->vni);
+ return -1;
+ }
+
+ memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
+ memset(&zmac->flags, 0, sizeof(u_int32_t));
+ SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
+ }
+
/* If same entry already exists, it might be a change or it might be a
* move from remote to local.
*/
@@ -2716,7 +2948,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
n->r_vtep_ip.s_addr = 0;
}
} else {
- n = zvni_neigh_add(zvni, ip);
+ n = zvni_neigh_add(zvni, ip, macaddr);
if (!n) {
zlog_err(
"%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
@@ -2734,13 +2966,34 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
/* Set "local" forwarding info. */
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
- memcpy(&n->emac, macaddr, ETH_ALEN);
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)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "%u: Skipping neigh %s add to client as MAC %s is not local on VNI %u",
+ ifp->vrf_id, ipaddr2str(ip, buf2, sizeof(buf2)),
+ prefix_mac2str(macaddr, buf, sizeof(buf)),
+ zvni->vni);
+
+ return 0;
+ }
+
/* Inform BGP if required. */
- if (send_upd)
+ 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);
+ }
return 0;
}
@@ -2868,6 +3121,9 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
}
} else {
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
+ zvni_process_neigh_on_remote_mac_del(zvrf, zvni,
+ mac);
+
if (!mac->neigh_refcnt) {
zvni_mac_uninstall(zvni, mac, 0);
zvni_mac_del(zvni, mac);
@@ -3024,6 +3280,8 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
else
UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
+ zvni_process_neigh_on_remote_mac_add(zvrf, zvni, mac);
+
/* Install the entry. */
zvni_mac_install(zvni, mac);
}
@@ -3047,7 +3305,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
if (update_neigh) {
if (!n) {
- n = zvni_neigh_add(zvni, &ip);
+ n = zvni_neigh_add(zvni, &ip, &macaddr);
if (!n) {
zlog_warn(
"%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
@@ -3070,12 +3328,12 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
if (old_mac)
zvni_deref_ip2mac(zvni, old_mac, 1);
mac->neigh_refcnt++;
+ memcpy(&n->emac, &macaddr, ETH_ALEN);
}
/* Set "remote" forwarding info. */
UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
/* TODO: Handle MAC change. */
- memcpy(&n->emac, &macaddr, ETH_ALEN);
n->r_vtep_ip = vtep_ip;
SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
@@ -3143,8 +3401,16 @@ int zebra_vxlan_check_del_local_mac(struct interface *ifp,
zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
- /* Delete this MAC entry. */
- zvni_mac_del(zvni, mac);
+ /*
+ * If there are no neigh associated with the mac delete the mac
+ * else mark it as AUTO for forward reference
+ */
+ if (!listcount(mac->neigh_list)) {
+ zvni_mac_del(zvni, mac);
+ } else {
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
+ SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
+ }
return 0;
}
@@ -3251,8 +3517,19 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
- /* Delete this MAC entry. */
- zvni_mac_del(zvni, mac);
+ /* Update all the neigh entries associated with this mac */
+ zvni_process_neigh_on_local_mac_del(zvrf, zvni, mac);
+
+ /*
+ * If there are no neigh associated with the mac delete the mac
+ * else mark it as AUTO for forward reference
+ */
+ if (!listcount(mac->neigh_list)) {
+ zvni_mac_del(zvni, mac);
+ } else {
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
+ SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
+ }
return 0;
}
@@ -3307,6 +3584,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
? 1
: 0;
+
/*
* return if nothing has changed.
* inform bgp if sticky flag has changed
@@ -3327,11 +3605,12 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
ifp->name, ifp->ifindex, vid,
zvni->vni);
return 0;
- } else if (mac_sticky != sticky)
+ } else if (mac_sticky != sticky) {
add = 1;
- else
+ } else {
add = 0; /* This is an update of local
interface. */
+ }
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
/*
* If we have already learned the MAC as a remote sticky
@@ -3367,8 +3646,9 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
/* Set "local" forwarding info. */
UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
- memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
+ memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.vid = vid;
@@ -3378,10 +3658,11 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
/* Inform BGP if required. */
- if (add)
- return zvni_mac_send_add_to_client(
- zvrf, zvni->vni, macaddr,
- (sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
+ if (add) {
+ zvni_process_neigh_on_local_mac_add(zvrf, zvni, mac);
+ return zvni_mac_send_add_to_client(zvrf, zvni->vni, macaddr,
+ sticky);
+ }
return 0;
}
diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h
index 2bf00291e7..8539311eab 100644
--- a/zebra/zebra_vxlan_private.h
+++ b/zebra/zebra_vxlan_private.h
@@ -115,6 +115,9 @@ struct zebra_mac_t_ {
} fwd_info;
u_int32_t neigh_refcnt;
+
+ /* List of neigh associated with this mac */
+ struct list *neigh_list;
};
/*
@@ -140,6 +143,16 @@ struct mac_walk_ctx {
struct json_object *json; /* Used for JSON Output */
};
+enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
+
+#define IS_ZEBRA_NEIGH_ACTIVE(n) n->state == ZEBRA_NEIGH_ACTIVE
+
+#define IS_ZEBRA_NEIGH_INACTIVE(n) n->state == ZEBRA_NEIGH_INACTIVE
+
+#define ZEBRA_NEIGH_SET_ACTIVE(n) n->state = ZEBRA_NEIGH_ACTIVE
+
+#define ZEBRA_NEIGH_SET_INACTIVE(n) n->state = ZEBRA_NEIGH_INACTIVE
+
/*
* Neighbor hash table.
*
@@ -162,8 +175,10 @@ struct zebra_neigh_t_ {
ifindex_t ifindex;
u_int32_t flags;
-#define ZEBRA_NEIGH_LOCAL 0x01
-#define ZEBRA_NEIGH_REMOTE 0x02
+#define ZEBRA_NEIGH_LOCAL 0x01
+#define ZEBRA_NEIGH_REMOTE 0x02
+
+ enum zebra_neigh_state state;
/* Remote VTEP IP - applicable only for remote neighbors. */
struct in_addr r_vtep_ip;