summaryrefslogtreecommitdiff
path: root/zebra/zebra_vxlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_vxlan.c')
-rw-r--r--zebra/zebra_vxlan.c85
1 files changed, 65 insertions, 20 deletions
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 86a7812780..45e6caebbe 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -81,7 +81,7 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[]);
static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
struct ipaddr *ip, uint8_t flags,
- uint32_t seq, uint16_t cmd);
+ uint32_t seq, int state, uint16_t cmd);
static unsigned int neigh_hash_keymake(void *p);
static void *zvni_neigh_alloc(void *p);
static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
@@ -97,7 +97,7 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
uint8_t flags, uint32_t seq);
static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
struct ethaddr *macaddr,
- uint8_t flags);
+ uint8_t flags, int state);
static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
static zebra_vni_t *zvni_from_svi(struct interface *ifp,
@@ -163,7 +163,7 @@ static zebra_vni_t *zvni_add(vni_t vni);
static int zvni_del(zebra_vni_t *zvni);
static int zvni_send_add_to_client(zebra_vni_t *zvni);
static int zvni_send_del_to_client(vni_t vni);
-static void zvni_build_hash_table();
+static void zvni_build_hash_table(void);
static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep);
static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip);
static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip);
@@ -2046,7 +2046,7 @@ static void zvni_print_hash_detail(struct hash_backet *backet, void *data)
*/
static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
struct ipaddr *ip, uint8_t flags,
- uint32_t seq, uint16_t cmd)
+ uint32_t seq, int state, uint16_t cmd)
{
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
@@ -2080,6 +2080,8 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
if (cmd == ZEBRA_MACIP_ADD) {
stream_putc(s, flags); /* sticky mac/gateway mac */
stream_putl(s, seq); /* sequence number */
+ } else {
+ stream_putl(s, state); /* state - active/inactive */
}
@@ -2218,7 +2220,7 @@ static void zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg)
&& IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
if (wctx->uninstall)
zvni_neigh_uninstall(wctx->zvni, n);
@@ -2354,7 +2356,7 @@ static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni,
ZEBRA_NEIGH_SET_INACTIVE(n);
n->loc_seq = 0;
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
}
}
}
@@ -2385,7 +2387,7 @@ static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni,
ZEBRA_NEIGH_SET_INACTIVE(n);
n->loc_seq = 0;
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
}
}
}
@@ -2418,17 +2420,18 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
- seq, ZEBRA_MACIP_ADD);
+ seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
}
/*
* Inform BGP about local neighbor deletion.
*/
static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
- struct ethaddr *macaddr, uint8_t flags)
+ struct ethaddr *macaddr, uint8_t flags,
+ int state)
{
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
- 0, ZEBRA_MACIP_DEL);
+ 0, state, ZEBRA_MACIP_DEL);
}
/*
@@ -2749,7 +2752,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni,
/* Remove neighbor from BGP. */
zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
- ZEBRA_MACIP_TYPE_GW);
+ ZEBRA_MACIP_TYPE_GW, ZEBRA_NEIGH_ACTIVE);
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);
@@ -2963,7 +2966,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
*/
if (IS_ZEBRA_NEIGH_ACTIVE(n))
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
old_zmac = zvni_mac_lookup(zvni, &n->emac);
if (old_zmac) {
old_mac_seq = CHECK_FLAG(old_zmac->flags,
@@ -3319,7 +3322,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
- seq, ZEBRA_MACIP_ADD);
+ seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
}
/*
@@ -3328,7 +3331,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr,
static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr)
{
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */,
- 0 /* seq */, ZEBRA_MACIP_DEL);
+ 0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL);
}
/*
@@ -3841,7 +3844,7 @@ static int zvni_send_del_to_client(vni_t vni)
* Build the VNI hash table by going over the VxLAN interfaces. This
* is called when EVPN (advertise-all-vni) is enabled.
*/
-static void zvni_build_hash_table()
+static void zvni_build_hash_table(void)
{
struct zebra_ns *zns;
struct route_node *rn;
@@ -5255,7 +5258,7 @@ static void process_remote_macip_add(vni_t vni,
IS_ZEBRA_NEIGH_ACTIVE(n))
zvni_neigh_send_del_to_client(
zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
/* update neigh list for macs */
old_mac = zvni_mac_lookup(zvni, &n->emac);
@@ -5337,6 +5340,9 @@ static void process_remote_macip_del(vni_t vni,
zebra_neigh_t *n = NULL;
struct interface *ifp = NULL;
struct zebra_if *zif = NULL;
+ struct zebra_ns *zns;
+ struct zebra_l2info_vxlan *vxl;
+ struct zebra_vrf *zvrf;
char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
@@ -5360,6 +5366,8 @@ static void process_remote_macip_del(vni_t vni,
vni);
return;
}
+ zns = zebra_ns_lookup(NS_DEFAULT);
+ vxl = &zif->l2info.vxl;
/* The remote VTEP specified is normally expected to exist, but
* it is possible that the peer may delete the VTEP before deleting
@@ -5386,9 +5394,10 @@ static void process_remote_macip_del(vni_t vni,
if (!mac && !n)
return;
+ zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
+
/* Ignore the delete if this mac is a gateway mac-ip */
- if (mac
- && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
&& CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
zlog_warn(
"Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
@@ -5402,6 +5411,23 @@ static void process_remote_macip_del(vni_t vni,
/* Uninstall remote neighbor or MAC. */
if (n) {
+ if (zvrf->dad_freeze &&
+ CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE) &&
+ CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) &&
+ (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) {
+ struct interface *vlan_if;
+
+ vlan_if = zvni_map_to_svi(vxl->access_vlan,
+ zif->brslave_info.br_if);
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
+ __PRETTY_FUNCTION__,
+ ipaddr2str(ipaddr, buf1,
+ sizeof(buf1)), n->flags,
+ vlan_if->name);
+ neigh_read_specific_ip(ipaddr, vlan_if);
+ }
+
/* When the MAC changes for an IP, it is possible the
* client may update the new MAC before trying to delete the
* "old" neighbor (as these are two different MACIP routes).
@@ -5414,6 +5440,25 @@ static void process_remote_macip_del(vni_t vni,
zvni_deref_ip2mac(zvni, mac);
}
} else {
+ /* DAD: when MAC is freeze state as remote learn event,
+ * remote mac-ip delete event is received will result in freeze
+ * entry removal, first fetch kernel for the same entry present
+ * as LOCAL and reachable, avoid deleting this entry instead
+ * use kerenel local entry to update during unfreeze time.
+ */
+ if (zvrf->dad_freeze &&
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) &&
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
+ __PRETTY_FUNCTION__,
+ prefix_mac2str(macaddr, buf,
+ sizeof(buf)),
+ mac->flags);
+ macfdb_read_specific_mac(zns, zif->brslave_info.br_if,
+ macaddr, vxl->access_vlan);
+ }
+
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
zvni_process_neigh_on_remote_mac_del(zvni, mac);
/*
@@ -7032,8 +7077,8 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
}
/* Remove neighbor from BGP. */
- if (IS_ZEBRA_NEIGH_ACTIVE(n))
- zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0);
+ zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
+ 0, n->state);
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);