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>
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;
}
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
*/
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 " : "",
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 " : "",
return NULL;
}
if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, ipa_len,
- ipaddr)) {
+ ipaddr, true)) {
ctx->ignore_macip = true;
return NULL;
}
{
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
- uint32_t tmp_seq;
bool sticky;
bool remote_gw;
int update_mac = 0;
* 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);
}
}
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
*/
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,
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);
{
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;
}
} 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
* 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)
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 *