summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorvivek <vivek@cumulusnetworks.com>2019-09-06 06:11:07 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2020-03-10 15:02:43 +0100
commit4b3f26f4c97e5ed0f88f2c9355c7b0c4d3c5968a (patch)
tree620b646e3956e943f90e5220d2726fec12c94e5e /zebra
parentlib: immediately ping systemd when started (diff)
downloadfrr-4b3f26f4c97e5ed0f88f2c9355c7b0c4d3c5968a.tar.xz
frr-4b3f26f4c97e5ed0f88f2c9355c7b0c4d3c5968a.zip
zebra: Readd special flood MAC upon del notification
Readd the special MAC that represents the flood (head-end replication) entry for EVPN-VxLAN upon getting a delete notification for it. Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com> Reviewed-by: Chirag Shah <chirag@cumulusnetworks.com> Ticket: CM-25797 Ticket: CM-26238 Testing Done: 1. evpn-min, evpn-smoke - results summarized in CM-25798
Diffstat (limited to 'zebra')
-rw-r--r--zebra/rt_netlink.c114
-rw-r--r--zebra/zebra_vxlan.c46
-rw-r--r--zebra/zebra_vxlan.h2
3 files changed, 99 insertions, 63 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 08d229619..b76eb6be4 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -2588,7 +2588,7 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
struct interface *br_if;
struct ethaddr mac;
vlanid_t vid = 0;
- struct prefix vtep_ip;
+ struct in_addr vtep_ip;
int vid_present = 0, dst_present = 0;
char buf[ETHER_ADDR_STRLEN];
char vid_buf[20];
@@ -2601,66 +2601,25 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (!is_evpn_enabled())
return 0;
- /* The interface should exist. */
- ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
- ndm->ndm_ifindex);
- if (!ifp || !ifp->info) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("\t%s without associated interface: %u",
- __func__, ndm->ndm_ifindex);
- return 0;
- }
-
- /* The interface should be something we're interested in. */
- if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("\t%s Not interested in %s, not a slave",
- __func__, ifp->name);
- return 0;
- }
-
- /* Drop "permanent" entries. */
- if (ndm->ndm_state & NUD_PERMANENT) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("\t%s Entry is PERMANENT, dropping",
- __func__);
- return 0;
- }
-
- zif = (struct zebra_if *)ifp->info;
- if ((br_if = zif->brslave_info.br_if) == NULL) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug(
- "%s family %s IF %s(%u) brIF %u - no bridge master",
- nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex,
- zif->brslave_info.bridge_ifindex);
- return 0;
- }
-
- /* Parse attributes and extract fields of interest. */
- memset(tb, 0, sizeof(tb));
+ /* Parse attributes and extract fields of interest. Do basic
+ * validation of the fields.
+ */
+ memset(tb, 0, sizeof tb);
netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
if (!tb[NDA_LLADDR]) {
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s family %s IF %s(%u) brIF %u - no LLADDR",
+ zlog_debug("%s AF_BRIDGE IF %u - no LLADDR",
nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex,
- zif->brslave_info.bridge_ifindex);
+ ndm->ndm_ifindex);
return 0;
}
if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
- nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex,
- zif->brslave_info.bridge_ifindex,
+ "%s AF_BRIDGE IF %u - LLADDR is not MAC, len %lu",
+ nl_msg_type_to_str(h->nlmsg_type), ndm->ndm_ifindex,
(unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
return 0;
}
@@ -2676,24 +2635,42 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (tb[NDA_DST]) {
/* TODO: Only IPv4 supported now. */
dst_present = 1;
- vtep_ip.family = AF_INET;
- vtep_ip.prefixlen = IPV4_MAX_BITLEN;
- memcpy(&(vtep_ip.u.prefix4.s_addr), RTA_DATA(tb[NDA_DST]),
+ memcpy(&vtep_ip.s_addr, RTA_DATA(tb[NDA_DST]),
IPV4_MAX_BYTELEN);
- sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip.u.prefix4));
+ sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
}
- sticky = !!(ndm->ndm_state & NUD_NOARP);
-
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Rx %s family %s IF %s(%u)%s %sMAC %s%s",
+ zlog_debug("Rx %s AF_BRIDGE IF %u%s st 0x%x fl 0x%x MAC %s%s",
nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(ndm->ndm_family), ifp->name,
ndm->ndm_ifindex, vid_present ? vid_buf : "",
- sticky ? "sticky " : "",
+ ndm->ndm_state, ndm->ndm_flags,
prefix_mac2str(&mac, buf, sizeof(buf)),
dst_present ? dst_buf : "");
+ /* The interface should exist. */
+ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
+ ndm->ndm_ifindex);
+ if (!ifp || !ifp->info)
+ return 0;
+
+ /* The interface should be something we're interested in. */
+ if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
+ return 0;
+
+ zif = (struct zebra_if *)ifp->info;
+ if ((br_if = zif->brslave_info.br_if) == NULL) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "%s AF_BRIDGE IF %s(%u) brIF %u - no bridge master",
+ nl_msg_type_to_str(h->nlmsg_type), ifp->name,
+ ndm->ndm_ifindex,
+ zif->brslave_info.bridge_ifindex);
+ return 0;
+ }
+
+ sticky = !!(ndm->ndm_state & NUD_NOARP);
+
if (filter_vlan && vid != filter_vlan) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("\tFiltered due to filter vlan: %d",
@@ -2707,6 +2684,13 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
* so perform an implicit delete of any local entry (if it exists).
*/
if (h->nlmsg_type == RTM_NEWNEIGH) {
+ /* Drop "permanent" entries. */
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("\tDropping entry because of NUD_PERMANENT");
+ return 0;
+ }
+
if (IS_ZEBRA_IF_VXLAN(ifp))
return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
vid);
@@ -2716,16 +2700,20 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
}
/* This is a delete notification.
+ * Ignore the notification with IP dest as it may just signify that the
+ * MAC has moved from remote to local. The exception is the special
+ * all-zeros MAC that represents the BUM flooding entry; we may have
+ * to readd it. Otherwise,
* 1. For a MAC over VxLan, check if it needs to be refreshed(readded)
* 2. For a MAC over "local" interface, delete the mac
* Note: We will get notifications from both bridge driver and VxLAN
* driver.
- * Ignore the notification from VxLan driver as it is also generated
- * when mac moves from remote to local.
*/
if (dst_present) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("\tNo Destination Present");
+ u_char zero_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+ if (!memcmp(zero_mac, mac.octet, ETH_ALEN))
+ return zebra_vxlan_check_readd_vtep(ifp, vtep_ip);
return 0;
}
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index dce48d39b..61865e5ba 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -7788,6 +7788,52 @@ stream_failure:
}
/*
+ * Handle remote vtep delete by kernel; re-add the vtep if we have it
+ */
+int zebra_vxlan_check_readd_vtep(struct interface *ifp,
+ struct in_addr vtep_ip)
+{
+ struct zebra_if *zif;
+ struct zebra_vrf *zvrf = NULL;
+ struct zebra_l2info_vxlan *vxl;
+ vni_t vni;
+ zebra_vni_t *zvni = NULL;
+ zebra_vtep_t *zvtep = NULL;
+
+ zif = ifp->info;
+ assert(zif);
+ vxl = &zif->l2info.vxl;
+ vni = vxl->vni;
+
+ /* If EVPN is not enabled, nothing to do. */
+ if (!is_evpn_enabled())
+ return 0;
+
+ /* Locate VRF corresponding to interface. */
+ zvrf = vrf_info_lookup(ifp->vrf_id);
+ if (!zvrf)
+ return -1;
+
+ /* Locate hash entry; it is expected to exist. */
+ zvni = zvni_lookup(vni);
+ if (!zvni)
+ return 0;
+
+ /* If the remote vtep entry doesn't exists nothing to do */
+ zvtep = zvni_vtep_find(zvni, &vtep_ip);
+ if (!zvtep)
+ return 0;
+
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "Del MAC for remote VTEP %s intf %s(%u) VNI %u - readd",
+ inet_ntoa(vtep_ip), ifp->name, ifp->ifindex, vni);
+
+ zvni_vtep_install(zvni, zvtep);
+ return 0;
+}
+
+/*
* Handle notification of MAC add/update over VxLAN. If the kernel is notifying
* us, this must involve a multihoming scenario. Treat this as implicit delete
* of any prior local MAC.
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index b551ba8df..6ca93f6cb 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -183,6 +183,8 @@ extern int zebra_vxlan_check_readd_remote_mac(struct interface *ifp,
extern int zebra_vxlan_check_del_local_mac(struct interface *ifp,
struct interface *br_if,
struct ethaddr *mac, vlanid_t vid);
+extern int zebra_vxlan_check_readd_vtep(struct interface *ifp,
+ struct in_addr vtep_ip);
extern int zebra_vxlan_if_up(struct interface *ifp);
extern int zebra_vxlan_if_down(struct interface *ifp);
extern int zebra_vxlan_if_add(struct interface *ifp);