diff options
author | vivek <vivek@cumulusnetworks.com> | 2019-09-06 06:11:07 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2020-03-10 15:02:43 +0100 |
commit | 4b3f26f4c97e5ed0f88f2c9355c7b0c4d3c5968a (patch) | |
tree | 620b646e3956e943f90e5220d2726fec12c94e5e /zebra | |
parent | lib: immediately ping systemd when started (diff) | |
download | frr-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.c | 114 | ||||
-rw-r--r-- | zebra/zebra_vxlan.c | 46 | ||||
-rw-r--r-- | zebra/zebra_vxlan.h | 2 |
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); |