forked from Mirror/frr
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>
This commit is contained in:
parent
640751c7ac
commit
b6938a74e5
|
@ -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", mac->neigh_refcnt);
|
||||
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, "\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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue