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 unsigned int neigh_hash_keymake(void *p);
|
||||||
static int neigh_cmp(const void *p1, const void *p2);
|
static int neigh_cmp(const void *p1, const void *p2);
|
||||||
static void *zvni_neigh_alloc(void *p);
|
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(zebra_vni_t *zvni, zebra_neigh_t *n);
|
||||||
static int zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg);
|
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,
|
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);
|
json_object_string_add(json, "mac", buf1);
|
||||||
}
|
}
|
||||||
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
|
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) {
|
||||||
if (json == NULL)
|
if (json == NULL) {
|
||||||
vty_out(vty, " Remote VTEP: %s",
|
vty_out(vty, " Remote VTEP: %s",
|
||||||
inet_ntoa(n->r_vtep_ip));
|
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",
|
json_object_string_add(json, "remoteVtep",
|
||||||
inet_ntoa(n->r_vtep_ip));
|
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)
|
static void zvni_print_mac(zebra_mac_t *mac, void *ctxt)
|
||||||
{
|
{
|
||||||
struct vty *vty;
|
struct vty *vty;
|
||||||
|
zebra_neigh_t *n = NULL;
|
||||||
|
struct listnode *node = NULL;
|
||||||
char buf1[20];
|
char buf1[20];
|
||||||
|
char buf2[INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
vty = (struct vty *)ctxt;
|
vty = (struct vty *)ctxt;
|
||||||
vty_out(vty, "MAC: %s",
|
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);
|
vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex);
|
||||||
if (mac->fwd_info.local.vid)
|
if (mac->fwd_info.local.vid)
|
||||||
vty_out(vty, " VLAN: %u", 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",
|
vty_out(vty, " Remote VTEP: %s",
|
||||||
inet_ntoa(mac->fwd_info.r_vtep_ip));
|
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");
|
vty_out(vty, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,7 +458,7 @@ static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt)
|
||||||
else
|
else
|
||||||
json_object_object_add(json_mac_hdr, buf1, json_mac);
|
json_object_object_add(json_mac_hdr, buf1, json_mac);
|
||||||
wctx->count++;
|
wctx->count++;
|
||||||
} else {
|
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
||||||
if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) {
|
if (wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) {
|
||||||
if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
|
if (IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
|
||||||
&wctx->r_vtep_ip)) {
|
&wctx->r_vtep_ip)) {
|
||||||
|
@ -789,16 +815,26 @@ static void *zvni_neigh_alloc(void *p)
|
||||||
/*
|
/*
|
||||||
* Add neighbor entry.
|
* 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 tmp_n;
|
||||||
zebra_neigh_t *n = NULL;
|
zebra_neigh_t *n = NULL;
|
||||||
|
zebra_mac_t *zmac = NULL;
|
||||||
|
|
||||||
memset(&tmp_n, 0, sizeof(zebra_neigh_t));
|
memset(&tmp_n, 0, sizeof(zebra_neigh_t));
|
||||||
memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
|
memcpy(&tmp_n.ip, ip, sizeof(struct ipaddr));
|
||||||
n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc);
|
n = hash_get(zvni->neigh_table, &tmp_n, zvni_neigh_alloc);
|
||||||
assert(n);
|
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;
|
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)
|
static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n)
|
||||||
{
|
{
|
||||||
zebra_neigh_t *tmp_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. */
|
/* Free the VNI hash entry and allocated memory. */
|
||||||
tmp_n = hash_release(zvni->neigh_table, n);
|
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;
|
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.
|
* 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);
|
n = zvni_neigh_lookup(zvni, ip);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
n = zvni_neigh_add(zvni, ip);
|
n = zvni_neigh_add(zvni, ip, macaddr);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
zlog_err(
|
zlog_err(
|
||||||
"%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
|
"%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);
|
mac = hash_get(zvni->mac_table, &tmp_mac, zvni_mac_alloc);
|
||||||
assert(mac);
|
assert(mac);
|
||||||
|
|
||||||
|
mac->neigh_list = list_new();
|
||||||
|
mac->neigh_list->cmp = (int (*)(void *, void *))neigh_cmp;
|
||||||
|
|
||||||
return mac;
|
return mac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1376,6 +1560,8 @@ static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
|
||||||
{
|
{
|
||||||
zebra_mac_t *tmp_mac;
|
zebra_mac_t *tmp_mac;
|
||||||
|
|
||||||
|
list_delete(mac->neigh_list);
|
||||||
|
|
||||||
/* Free the VNI hash entry and allocated memory. */
|
/* Free the VNI hash entry and allocated memory. */
|
||||||
tmp_mac = hash_release(zvni->mac_table, mac);
|
tmp_mac = hash_release(zvni->mac_table, mac);
|
||||||
if (tmp_mac)
|
if (tmp_mac)
|
||||||
|
@ -2599,6 +2785,8 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
|
||||||
zebra_neigh_t *n;
|
zebra_neigh_t *n;
|
||||||
struct zebra_vrf *zvrf;
|
struct zebra_vrf *zvrf;
|
||||||
char buf[INET6_ADDRSTRLEN];
|
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
|
/* We are only interested in neighbors on an SVI that resides on top
|
||||||
* of a VxLAN bridge.
|
* of a VxLAN bridge.
|
||||||
|
@ -2623,6 +2811,18 @@ int zebra_vxlan_local_neigh_del(struct interface *ifp,
|
||||||
if (!n)
|
if (!n)
|
||||||
return 0;
|
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
|
/* 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.
|
* 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);
|
assert(zvrf);
|
||||||
|
|
||||||
/* Remove neighbor from BGP. */
|
/* 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. */
|
/* Delete this neighbor entry. */
|
||||||
zvni_neigh_del(zvni, n);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2657,6 +2864,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
|
||||||
zebra_vni_t *zvni;
|
zebra_vni_t *zvni;
|
||||||
zebra_neigh_t *n;
|
zebra_neigh_t *n;
|
||||||
struct zebra_vrf *zvrf;
|
struct zebra_vrf *zvrf;
|
||||||
|
zebra_mac_t *zmac;
|
||||||
char buf[ETHER_ADDR_STRLEN];
|
char buf[ETHER_ADDR_STRLEN];
|
||||||
char buf2[INET6_ADDRSTRLEN];
|
char buf2[INET6_ADDRSTRLEN];
|
||||||
int send_upd = 1, send_del = 0;
|
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 " : "",
|
ifp->ifindex, state, ext_learned ? "ext-learned " : "",
|
||||||
zvni->vni);
|
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
|
/* If same entry already exists, it might be a change or it might be a
|
||||||
* move from remote to local.
|
* 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;
|
n->r_vtep_ip.s_addr = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
n = zvni_neigh_add(zvni, ip);
|
n = zvni_neigh_add(zvni, ip, macaddr);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
zlog_err(
|
zlog_err(
|
||||||
"%u:Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
|
"%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 "local" forwarding info. */
|
||||||
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
||||||
memcpy(&n->emac, macaddr, ETH_ALEN);
|
|
||||||
n->ifindex = ifp->ifindex;
|
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. */
|
/* 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,
|
return zvni_neigh_send_add_to_client(zvrf, zvni->vni, ip,
|
||||||
macaddr, 0);
|
macaddr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2868,6 +3121,9 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, u_short length,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
||||||
|
zvni_process_neigh_on_remote_mac_del(zvrf, zvni,
|
||||||
|
mac);
|
||||||
|
|
||||||
if (!mac->neigh_refcnt) {
|
if (!mac->neigh_refcnt) {
|
||||||
zvni_mac_uninstall(zvni, mac, 0);
|
zvni_mac_uninstall(zvni, mac, 0);
|
||||||
zvni_mac_del(zvni, mac);
|
zvni_mac_del(zvni, mac);
|
||||||
|
@ -3024,6 +3280,8 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, u_short length,
|
||||||
else
|
else
|
||||||
UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
|
UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
|
||||||
|
|
||||||
|
zvni_process_neigh_on_remote_mac_add(zvrf, zvni, mac);
|
||||||
|
|
||||||
/* Install the entry. */
|
/* Install the entry. */
|
||||||
zvni_mac_install(zvni, mac);
|
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 (update_neigh) {
|
||||||
if (!n) {
|
if (!n) {
|
||||||
n = zvni_neigh_add(zvni, &ip);
|
n = zvni_neigh_add(zvni, &ip, &macaddr);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
zlog_warn(
|
zlog_warn(
|
||||||
"%u:Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s",
|
"%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)
|
if (old_mac)
|
||||||
zvni_deref_ip2mac(zvni, old_mac, 1);
|
zvni_deref_ip2mac(zvni, old_mac, 1);
|
||||||
mac->neigh_refcnt++;
|
mac->neigh_refcnt++;
|
||||||
|
memcpy(&n->emac, &macaddr, ETH_ALEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set "remote" forwarding info. */
|
/* Set "remote" forwarding info. */
|
||||||
UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
UNSET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL);
|
||||||
/* TODO: Handle MAC change. */
|
/* TODO: Handle MAC change. */
|
||||||
memcpy(&n->emac, &macaddr, ETH_ALEN);
|
|
||||||
n->r_vtep_ip = vtep_ip;
|
n->r_vtep_ip = vtep_ip;
|
||||||
SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE);
|
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,
|
zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
|
||||||
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
(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;
|
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,
|
zvni_mac_send_del_to_client(zvrf, zvni->vni, macaddr,
|
||||||
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
||||||
|
|
||||||
/* Delete this MAC entry. */
|
/* Update all the neigh entries associated with this mac */
|
||||||
zvni_mac_del(zvni, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3307,6 +3584,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
|
||||||
? 1
|
? 1
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return if nothing has changed.
|
* return if nothing has changed.
|
||||||
* inform bgp if sticky flag 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,
|
ifp->name, ifp->ifindex, vid,
|
||||||
zvni->vni);
|
zvni->vni);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (mac_sticky != sticky)
|
} else if (mac_sticky != sticky) {
|
||||||
add = 1;
|
add = 1;
|
||||||
else
|
} else {
|
||||||
add = 0; /* This is an update of local
|
add = 0; /* This is an update of local
|
||||||
interface. */
|
interface. */
|
||||||
|
}
|
||||||
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
||||||
/*
|
/*
|
||||||
* If we have already learned the MAC as a remote sticky
|
* 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. */
|
/* Set "local" forwarding info. */
|
||||||
UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
|
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);
|
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.ifindex = ifp->ifindex;
|
||||||
mac->fwd_info.local.vid = vid;
|
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);
|
UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
|
||||||
|
|
||||||
/* Inform BGP if required. */
|
/* Inform BGP if required. */
|
||||||
if (add)
|
if (add) {
|
||||||
return zvni_mac_send_add_to_client(
|
zvni_process_neigh_on_local_mac_add(zvrf, zvni, mac);
|
||||||
zvrf, zvni->vni, macaddr,
|
return zvni_mac_send_add_to_client(zvrf, zvni->vni, macaddr,
|
||||||
(sticky ? ZEBRA_MAC_TYPE_STICKY : 0));
|
sticky);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,9 @@ struct zebra_mac_t_ {
|
||||||
} fwd_info;
|
} fwd_info;
|
||||||
|
|
||||||
u_int32_t neigh_refcnt;
|
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 */
|
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.
|
* Neighbor hash table.
|
||||||
*
|
*
|
||||||
|
@ -162,8 +175,10 @@ struct zebra_neigh_t_ {
|
||||||
ifindex_t ifindex;
|
ifindex_t ifindex;
|
||||||
|
|
||||||
u_int32_t flags;
|
u_int32_t flags;
|
||||||
#define ZEBRA_NEIGH_LOCAL 0x01
|
#define ZEBRA_NEIGH_LOCAL 0x01
|
||||||
#define ZEBRA_NEIGH_REMOTE 0x02
|
#define ZEBRA_NEIGH_REMOTE 0x02
|
||||||
|
|
||||||
|
enum zebra_neigh_state state;
|
||||||
|
|
||||||
/* Remote VTEP IP - applicable only for remote neighbors. */
|
/* Remote VTEP IP - applicable only for remote neighbors. */
|
||||||
struct in_addr r_vtep_ip;
|
struct in_addr r_vtep_ip;
|
||||||
|
|
Loading…
Reference in a new issue