zebra: accept bgp remote mac-ip update if the higher-seq-local mac is not bgp-ready

If a local-MAC or local-neigh is not active locally it is not sent to BGP.
At this point if BGP rxes a remote route it accepts it and installs in
zebra. Zebra was rejecting BGP's update if it had a higher seq local (inactive)
entry. This would result in bgp and zebra falling out of sync.

In some cases zebra would delete the local-inactive entries in sometime (as
a part of the dplane/kernel garbage collection). This would leave zebra
with missing remote entries (which were still present in bgpd).

This change allows lower-seq BGP updates to overwrite zebra's local entry if
that entry happens to be local-inactive.

Note: This logic was already in use for sync-mac-ip updates. Extended the
same logic to remote-mac-ip updates.

Ticket: CM-31626

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
This commit is contained in:
Anuradha Karuppiah 2020-10-01 14:19:52 -07:00 committed by Anuradha Karuppiah
parent 6c111b51a1
commit 16de1338a9
4 changed files with 41 additions and 64 deletions

View File

@ -1336,7 +1336,8 @@ zebra_evpn_process_sync_macip_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
if (ipa_len) {
n = zebra_evpn_neigh_lookup(zevpn, ipaddr);
if (n
&& !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq))
&& !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq,
true))
return;
}

View File

@ -1395,16 +1395,21 @@ void zebra_evpn_sync_mac_del(zebra_mac_t *mac)
static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
zebra_mac_t *mac, uint32_t seq,
uint16_t ipa_len,
struct ipaddr *ipaddr)
struct ipaddr *ipaddr,
bool sync)
{
char macbuf[ETHER_ADDR_STRLEN];
char ipbuf[INET6_ADDRSTRLEN];
uint32_t tmp_seq;
const char *n_type;
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
tmp_seq = mac->loc_seq;
else
n_type = "local";
} else {
tmp_seq = mac->rem_seq;
n_type = "remote";
}
if (seq < tmp_seq) {
/* if the mac was never advertised to bgp we must accept
@ -1413,10 +1418,11 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
*/
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
&& !zebra_evpn_mac_is_ready_for_bgp(mac->flags)) {
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"sync-macip accept vni %u mac %s%s%s lower seq %u f 0x%x",
zevpn->vni,
"%s-macip accept vni %u %s-mac %s%s%s lower seq %u f 0x%x",
sync ? "sync" : "rem", zevpn->vni,
n_type,
prefix_mac2str(&mac->macaddr, macbuf,
sizeof(macbuf)),
ipa_len ? " IP " : "",
@ -1427,10 +1433,10 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
return true;
}
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"sync-macip ignore vni %u mac %s%s%s as existing has higher seq %u f 0x%x",
zevpn->vni,
"%s-macip ignore vni %u %s-mac %s%s%s as existing has higher seq %u f 0x%x",
sync ? "sync" : "rem", zevpn->vni, n_type,
prefix_mac2str(&mac->macaddr, macbuf,
sizeof(macbuf)),
ipa_len ? " IP " : "",
@ -1518,7 +1524,7 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
return NULL;
}
if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, ipa_len,
ipaddr)) {
ipaddr, true)) {
ctx->ignore_macip = true;
return NULL;
}
@ -1768,7 +1774,6 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
{
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
uint32_t tmp_seq;
bool sticky;
bool remote_gw;
int update_mac = 0;
@ -1836,26 +1841,9 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
* the sequence number and ignore this update
* if appropriate.
*/
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
tmp_seq = mac->loc_seq;
else
tmp_seq = mac->rem_seq;
if (seq < tmp_seq) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing MAC has higher seq %u flags 0x%x",
zevpn->vni,
prefix_mac2str(macaddr, buf,
sizeof(buf)),
ipa_len ? " IP " : "",
ipa_len ? ipaddr2str(
ipaddr, buf1,
sizeof(buf1))
: "",
tmp_seq, mac->flags);
if (!zebra_evpn_mac_is_bgp_seq_ok(
zevpn, mac, seq, ipa_len, ipaddr, false))
return -1;
}
zebra_evpn_es_mac_ref(mac, esi);
}

View File

@ -529,16 +529,21 @@ static void zebra_evpn_local_neigh_deref_mac(zebra_neigh_t *n,
}
bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
struct ethaddr *macaddr, uint32_t seq)
struct ethaddr *macaddr, uint32_t seq,
bool sync)
{
char macbuf[ETHER_ADDR_STRLEN];
char ipbuf[INET6_ADDRSTRLEN];
uint32_t tmp_seq;
const char *n_type;
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL))
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
tmp_seq = n->loc_seq;
else
n_type = "local";
} else {
tmp_seq = n->rem_seq;
n_type = "remote";
}
if (seq < tmp_seq) {
/* if the neigh was never advertised to bgp we must accept
@ -547,10 +552,12 @@ bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
*/
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)
&& !zebra_evpn_neigh_is_ready_for_bgp(n)) {
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
|| IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"sync-macip accept vni %u mac %s IP %s lower seq %u f 0x%x",
zevpn->vni,
"%s-macip accept vni %u %s mac %s IP %s lower seq %u f 0x%x",
sync ? "sync" : "remote", zevpn->vni,
n_type,
prefix_mac2str(macaddr, macbuf,
sizeof(macbuf)),
ipaddr2str(&n->ip, ipbuf,
@ -559,10 +566,10 @@ bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
return true;
}
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH || IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"sync-macip ignore vni %u mac %s IP %s as existing has higher seq %u f 0x%x",
zevpn->vni,
"%s-macip ignore vni %u %s mac %s IP %s as existing has higher seq %u f 0x%x",
sync ? "sync" : "remote", zevpn->vni, n_type,
prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),
ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
tmp_seq, n->flags);
@ -2133,7 +2140,6 @@ void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
{
zebra_neigh_t *n;
int update_neigh = 0;
uint32_t tmp_seq;
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
zebra_mac_t *old_mac = NULL;
@ -2170,8 +2176,6 @@ void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
}
} else {
const char *n_type;
/* When host moves but changes its (MAC,IP)
* binding, BGP may install a MACIP entry that
* corresponds to "older" location of the host
@ -2180,27 +2184,10 @@ void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
* the sequence number and ignore this update
* if appropriate.
*/
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
tmp_seq = n->loc_seq;
n_type = "local";
} else {
tmp_seq = n->rem_seq;
n_type = "remote";
}
if (seq < tmp_seq) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"Ignore remote MACIP ADD VNI %u MAC %s%s%s as existing %s Neigh has higher seq %u",
zevpn->vni,
prefix_mac2str(&mac->macaddr,
buf,
sizeof(buf)),
" IP ",
ipaddr2str(ipaddr, buf1,
sizeof(buf1)),
n_type, tmp_seq);
if (!zebra_evpn_neigh_is_bgp_seq_ok(
zevpn, n, &mac->macaddr, seq, false))
return;
}
if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) {
old_static = zebra_evpn_neigh_is_static(n);
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)

View File

@ -237,7 +237,8 @@ int zebra_evpn_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
struct ethaddr *macaddr, uint32_t flags,
int state, bool force);
bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
struct ethaddr *macaddr, uint32_t seq);
struct ethaddr *macaddr, uint32_t seq,
bool sync);
int zebra_evpn_neigh_del(zebra_evpn_t *zevpn, zebra_neigh_t *n);
void zebra_evpn_sync_neigh_del(zebra_neigh_t *n);
zebra_neigh_t *