From 54c174250c381580b0477e6eade2c03c4109ed64 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Mon, 13 Aug 2018 17:07:22 -0700 Subject: [PATCH 1/3] zebra: mark router flag for neigh update The neigh update can come prior to mac add update. In this case, the mac will be auto created for the vni. set router flag to local neigh update for mac with auto flag. The neigh update will be informed to bgpd once local mac is learnt. Unset router flag if the neigh update comes without the router flag for an existing neigh entry. Signed-off-by: Chirag Shah --- zebra/zebra_vxlan.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 04f9be8ade..a4f5f7b954 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -2060,6 +2060,12 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n->ifindex = ifp->ifindex; } + /*Mark Router flag (R-bit) */ + if (router_flag) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + /* Before we program this in BGP, we need to check if MAC is locally * learnt as well */ @@ -2074,10 +2080,6 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, return 0; } - /*Set router flag (R-bit) */ - if (router_flag) - SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - /* Inform BGP. */ if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x", @@ -4965,10 +4967,11 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u", + "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, state, ext_learned ? "ext-learned " : "", + router_flag ? "router " : "", zvni->vni); /* Is this about a local neighbor or a remote one? */ From 29c2ce7cfc283337e60d5498fb72f291528603b4 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Wed, 15 Aug 2018 13:32:03 -0700 Subject: [PATCH 2/3] zebra: check router_flag change for neigh update Neigh update can have router_flag change, from unset to set and viceversa. This is the case where MAC, IP and VLAN are same but entry's flag moved from R to not R bit and reverse case. Router flag change needs to trigger bgpd to inform all evpn peers to remove from the evpn route. Testing Done: Send GARP with and without R bit from host and validate neigh entry and evpn neigh and mac-ip route entry in zebra and bgpd. Check Peer VTEP evpn route entry where router flag is (un)set. With R-bit Route [2]:[0]:[0]:[48]:[00:1f:2f:db:45:a6]:[128]:[2006:33:33:2::10] VNI 1001 Imported from 27.0.0.16:5:[2]:[0]:[0]:[48]:[00:1f:2f:db:45:a6]:[128]:[2006:33:33:2::10] 4435 5551 27.0.0.16 from MSP1(uplink-1) (27.0.0.9) Origin IGP, valid, external, bestpath-from-AS 4435, best Extended Community: RT:5551:1001 ET:8 ND:Router Flag AddPath ID: RX 0, TX 1261 Last update: Wed Aug 15 20:52:14 2018 Without R-bit Route [2]:[0]:[0]:[48]:[00:1f:2f:db:45:a6]:[128]:[2006:33:33:2::10] VNI 1001 Imported from 27.0.0.16:5:[2]:[0]:[0]:[48]:[00:1f:2f:db:45:a6]:[128]:[2006:33:33:2::10] 4435 5551 27.0.0.16 from MSP2(uplink-2) (27.0.0.10) Origin IGP, valid, external, bestpath-from-AS 4435, best Extended Community: RT:5551:1001 ET:8 AddPath ID: RX 0, TX 1263 Last update: Wed Aug 15 20:53:10 2018 Signed-off-by: Chirag Shah --- zebra/zebra_vxlan.c | 61 +++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index a4f5f7b954..0b034fd3b5 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1961,6 +1961,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, char buf2[INET6_ADDRSTRLEN]; zebra_neigh_t *n = NULL; zebra_mac_t *zmac = NULL, *old_zmac = NULL; + bool check_rbit = false; /* create a dummy MAC if the MAC is not already present */ zmac = zvni_mac_lookup(zvni, macaddr); @@ -1990,35 +1991,41 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n = zvni_neigh_lookup(zvni, ip); if (n) { if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + + if (router_flag != + (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) + ? 1 : 0)) + check_rbit = true; + if (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0) { /* Update any params and return - client doesn't * care about a purely local change. */ n->ifindex = ifp->ifindex; - return 0; - } + } else { - /* 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(zvni->vni, &n->ip, + /* 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(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); + 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); + } + + /* Update the forwarding info. */ + n->ifindex = ifp->ifindex; + memcpy(&n->emac, macaddr, ETH_ALEN); + + /* Link to new MAC */ + listnode_add_sort(zmac->neigh_list, n); } - /* Update the forwarding info. */ - n->ifindex = ifp->ifindex; - memcpy(&n->emac, macaddr, ETH_ALEN); - - /* Link to new MAC */ - listnode_add_sort(zmac->neigh_list, n); - } else /* Neighbor has moved from remote to local. */ { @@ -2042,6 +2049,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n->r_vtep_ip.s_addr = 0; SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); n->ifindex = ifp->ifindex; + check_rbit = true; } } else { /* New neighbor - create */ @@ -2058,6 +2066,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, /* Set "local" forwarding info. */ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); n->ifindex = ifp->ifindex; + check_rbit = true; } /*Mark Router flag (R-bit) */ @@ -2072,11 +2081,21 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Skipping neigh %s add to client as MAC %s is not local on VNI %u", + "Skipping neigh %s add to client as MAC %s is not local on VNI %u with flags 0x%x", + ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), + zvni->vni, n->flags); + + return 0; + } + + if (!check_rbit) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Skipping neigh %s with MAC %s on VNI %u add to client as router flag is not set.", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), zvni->vni); - return 0; } From 7d08917b321f480c26a1a7f794906d65fff0fdfa Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Fri, 17 Aug 2018 13:38:06 -0700 Subject: [PATCH 3/3] zebra: mark router flag for remote neigh update Handle Remote Neigh entry state change from Router to Host. Remote MAC-IP update may not continue EVPN NA Extended community, Zebra need to accomodate if router_flag change for existing neigh and install with or without Router Flag (R-bit). Testing: Have locally run MAC/IP (neigh entry) with R-bit set, Checke on remote VTEP 'show bgp evpn route ...mac ip' and 'show evpn arp-cache ...' contians router flag. Change host to remove R-bit, which locally learnt entry removes Router flag. This results in remote vtep to remove R-bit from neigh entry. Signed-off-by: Chirag Shah --- zebra/zebra_vxlan.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 0b034fd3b5..f63879159d 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -5173,7 +5173,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; uint8_t sticky = 0; - u_char remote_gw = 0; + uint8_t remote_gw = 0; + uint8_t router_flag = 0; uint8_t flags = 0; struct interface *ifp = NULL; struct zebra_if *zif = NULL; @@ -5216,6 +5217,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) STREAM_GETC(s, flags); sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + router_flag = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); l++; if (IS_ZEBRA_DEBUG_VXLAN) @@ -5347,6 +5349,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) */ n = zvni_neigh_lookup(zvni, &ip); if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + || ((CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) ? 1 : 0) + != router_flag) || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0) || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)) update_neigh = 1; @@ -5387,6 +5391,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) /* Set router flag (R-bit) to this Neighbor entry */ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); /* Install the entry. */ zvni_neigh_install(zvni, n);