From bdca1974e1cd172bdb0cfa76dab3ed751bbcdaec Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Sat, 17 Nov 2018 16:03:19 -0800 Subject: [PATCH] zebra: dup addr detect mac consolidation Signed-off-by: Chirag Shah --- zebra/zebra_vxlan.c | 407 ++++++++++++++++++-------------------------- 1 file changed, 167 insertions(+), 240 deletions(-) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index a18648aa1c..86f6961118 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -193,6 +193,12 @@ static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, bool do_dad, bool *is_dup_detect, bool is_local); +static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, + zebra_mac_t *mac, + struct in_addr vtep_ip, + bool do_dad, + bool *is_dup_detect, + bool is_local); /* Private functions */ static int host_rb_entry_compare(const struct host_rb_entry *hle1, @@ -370,6 +376,159 @@ static int zebra_vxlan_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, return 0; } +static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, + zebra_mac_t *mac, + struct in_addr vtep_ip, + bool do_dad, + bool *is_dup_detect, + bool is_local) +{ + zebra_neigh_t *nbr; + struct listnode *node = NULL; + struct timeval elapsed = {0, 0}; + char buf[ETHER_ADDR_STRLEN]; + char buf1[INET6_ADDRSTRLEN]; + bool reset_params = false; + + if (!(zvrf->dup_addr_detect && do_dad)) + return; + + /* MAC is detected as duplicate, + * Local MAC event -> hold on advertising to BGP. + * Remote MAC event -> hold on installing it. + */ + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%s: duplicate addr MAC %s flags 0x%x skip update to client, learn count %u recover time %u", + __PRETTY_FUNCTION__, + prefix_mac2str(&mac->macaddr, buf, + sizeof(buf)), + mac->flags, mac->dad_count, + zvrf->dad_freeze_time); + + /* For duplicate MAC do not update + * client but update neigh due to + * this MAC update. + */ + if (zvrf->dad_freeze) + *is_dup_detect = false; + + return; + } + + /* Check if detection time (M-secs) expired. + * Reset learn count and detection start time. + */ + monotime_since(&mac->detect_start_time, &elapsed); + reset_params = (elapsed.tv_sec > zvrf->dad_time); + if (is_local && !reset_params) { + /* RFC-7432: A PE/VTEP that detects a MAC mobility + * event via LOCAL learning starts an M-second timer. + * + * NOTE: This is the START of the probe with count is + * 0 during LOCAL learn event. + * (mac->dad_count == 0 || elapsed.tv_sec >= zvrf->dad_time) + */ + reset_params = !mac->dad_count; + } + + if (reset_params) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u" + , __PRETTY_FUNCTION__, + prefix_mac2str(&mac->macaddr, buf, + sizeof(buf)), + mac->flags, mac->dad_count); + + mac->dad_count = 0; + /* Start dup. addr detection (DAD) start time, + * ONLY during LOCAL learn. + */ + if (is_local) + monotime(&mac->detect_start_time); + + } else if (!is_local) { + /* For REMOTE MAC, increment detection count + * ONLY while in probe window, once window passed, + * next local learn event should trigger DAD. + */ + mac->dad_count++; + } + + /* For LOCAL MAC learn event, once count is reset above via either + * initial/start detection time or passed the probe time, the count + * needs to be incremented. + */ + if (is_local) + mac->dad_count++; + + zlog_debug("%s: MAC DAD %s dad_count %u ", + __PRETTY_FUNCTION__, + prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), + mac->dad_count); + + if (mac->dad_count >= zvrf->dad_max_moves) { + flog_warn(EC_ZEBRA_DUP_MAC_DETECTED, + "VNI %u: MAC %s detected as duplicate during %s VTEP %s", + mac->zvni->vni, + prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), + is_local ? "local update, last" : + "remote update, from", inet_ntoa(vtep_ip)); + + SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE); + + /* Capture Duplicate detection time */ + mac->dad_dup_detect_time = monotime(NULL); + + /* Mark all IPs/Neighs as duplicate + * associcated with this MAC + */ + for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) { + + /* Ony Mark IPs which are Local */ + if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) + continue; + + SET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); + + nbr->dad_dup_detect_time = monotime(NULL); + + flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED, + "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC", + mac->zvni->vni, + prefix_mac2str(&mac->macaddr, + buf, sizeof(buf)), + ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), + is_local ? "local" : "remote"); + } + + /* Start auto recovery timer for this MAC */ + THREAD_OFF(mac->dad_mac_auto_recovery_timer); + if (zvrf->dad_freeze && zvrf->dad_freeze_time) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start" + , __PRETTY_FUNCTION__, + prefix_mac2str(&mac->macaddr, buf, + sizeof(buf)), + mac->flags, zvrf->dad_freeze_time); + + thread_add_timer(zebrad.master, + zebra_vxlan_dad_mac_auto_recovery_exp, + mac, zvrf->dad_freeze_time, + &mac->dad_mac_auto_recovery_timer); + } + + /* Do not inform to client (BGPd), + * upd_neigh for neigh sequence change. + */ + if (zvrf->dad_freeze) + *is_dup_detect = false; + } +} + static void zebra_vxlan_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr, struct in_addr vtep_ip, @@ -4605,8 +4764,6 @@ static void process_remote_macip_add(vni_t vni, bool is_router; bool do_dad = false; bool is_dup_detect = false; - struct listnode *node = NULL; - struct timeval elapsed = {0, 0}; /* Locate VNI hash entry - expected to exist. */ zvni = zvni_lookup(vni); @@ -4762,114 +4919,11 @@ static void process_remote_macip_add(vni_t vni, else UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); - if (zvrf->dup_addr_detect && do_dad) { - /* MAC is detected as duplicate, hold on to - * install as remote entry. - */ - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s skip installing, learn count %u recover time %u", - __PRETTY_FUNCTION__, - prefix_mac2str(macaddr, - buf, sizeof(buf)), - mac->dad_count, - zvrf->dad_freeze_time); - /* Do not install MAC but process neigh - * due to the remote MAC add. - */ - goto process_neigh; - } - - /* Check if detection time (M-secs) expired. - * Reset learn count and detection start time. - */ - monotime_since(&mac->detect_start_time, &elapsed); - if (elapsed.tv_sec > zvrf->dad_time) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("%s: duplicate addr MAC %s flags 0%x detection time passed, reset learn count %u", - __PRETTY_FUNCTION__, - prefix_mac2str(macaddr, buf, - sizeof(buf)), - mac->flags, mac->dad_count); - /* Reset learn count but do not start detection - * during remote learn. - * Next local learn event start time wil be - * resetted. - */ - mac->dad_count = 0; - } else { - /* Increment detection count while in probe - * window - */ - mac->dad_count++; - } + zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac, + mac->fwd_info.r_vtep_ip, + do_dad, &is_dup_detect, + false); - if (mac->dad_count >= zvrf->dad_max_moves) { - flog_warn(EC_ZEBRA_DUP_MAC_DETECTED, - "VNI %u: MAC %s detected as duplicate during remote update, from VTEP %s", - zvni->vni, - prefix_mac2str(&mac->macaddr, - buf, sizeof(buf)), - inet_ntoa(mac->fwd_info.r_vtep_ip)); - - SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE); - - /* Capture Duplicate detection time */ - mac->dad_dup_detect_time = monotime(NULL); - - /* Mark all IPs/Neighs as duplicate associcated - * with this MAC - */ - for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, - node, n)) { - /* Ony Mark IPs which are Remote */ - if (!CHECK_FLAG(n->flags, - ZEBRA_NEIGH_REMOTE)) - continue; - - SET_FLAG(n->flags, - ZEBRA_NEIGH_DUPLICATE); - - /* Capture Duplicate detection time */ - n->dad_dup_detect_time = monotime(NULL); - - flog_warn( - EC_ZEBRA_DUP_IP_INHERIT_DETECTED, - "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC", - zvni->vni, - prefix_mac2str(&mac->macaddr, - buf, sizeof(buf)), - ipaddr2str(&n->ip, buf1, - sizeof(buf1))); - } - - /* Start auto recovery timer for this - * MAC - */ - THREAD_OFF(mac->dad_mac_auto_recovery_timer); - if (zvrf->dad_freeze && zvrf->dad_freeze_time) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("%s: duplicate addr MAC %s flags 0%x auto recovery time %u start", - __PRETTY_FUNCTION__, - prefix_mac2str(&mac->macaddr, - buf, sizeof(buf)), - mac->flags, - zvrf->dad_freeze_time); - - thread_add_timer(zebrad.master, - zebra_vxlan_dad_mac_auto_recovery_exp, - mac, - zvrf->dad_freeze_time, - &mac->dad_mac_auto_recovery_timer); - } - - if (zvrf->dad_freeze) - is_dup_detect = true; - } - - } -process_neigh: zvni_process_neigh_on_remote_mac_add(zvni, mac); /* Install the entry. */ @@ -6990,11 +7044,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, bool mac_sticky = false; bool inform_client = false; bool upd_neigh = false; - zebra_neigh_t *n = NULL; - struct listnode *node = NULL; struct in_addr vtep_ip = {.s_addr = 0}; - struct timeval elapsed = {0, 0}; - char buf2[INET6_ADDRSTRLEN]; /* We are interested in MACs only on ports or (port, VLAN) that * map to a VNI. @@ -7139,136 +7189,13 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp, inform_client = true; upd_neigh = true; - if (zvrf->dup_addr_detect && do_dad) { - /* MAC is detected as duplicate, hold on - * advertising to BGP. - */ - if (CHECK_FLAG(mac->flags, - ZEBRA_MAC_DUPLICATE)) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "%s: duplicate addr MAC %s skip update to client, learn count %u recover time %u", - __PRETTY_FUNCTION__, - prefix_mac2str(macaddr, - buf, sizeof(buf)), - mac->dad_count, - zvrf->dad_freeze_time); - /* For duplicate MAC do not update - * client but update neigh due to - * this MAC update. - */ - if (zvrf->dad_freeze) - inform_client = false; - - goto send_notif; - } - - /* Check if detection time (M-secs) expired. - * Reset learn count and detection start time. - */ - monotime_since(&mac->detect_start_time, - &elapsed); - if (mac->dad_count == 0 || - elapsed.tv_sec >= zvrf->dad_time) { - - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("%s: duplicate addr MAC %s flags 0x%x detection time passed, reset learn count %u", - __PRETTY_FUNCTION__, - prefix_mac2str( - macaddr, buf, - sizeof(buf)), - mac->flags, - mac->dad_count); - - mac->dad_count = 0; - /* Capture start dup. detection time */ - monotime(&mac->detect_start_time); - } - - /* Increment move count */ - mac->dad_count++; - - if (mac->dad_count >= zvrf->dad_max_moves) { - flog_warn(EC_ZEBRA_DUP_MAC_DETECTED, - "VNI %u: MAC %s detected as duplicate during local update, last VTEP %s", - zvni->vni, - prefix_mac2str(&mac->macaddr, - buf, sizeof(buf)), - inet_ntoa(vtep_ip)); - - SET_FLAG(mac->flags, - ZEBRA_MAC_DUPLICATE); - - /* Capture Duplicate detection time */ - mac->dad_dup_detect_time = - monotime(NULL); - - /* Mark all IPs/Neighs as duplicate - * associcated with this MAC - */ - for (ALL_LIST_ELEMENTS_RO( - mac->neigh_list, - node, n)) { - - /* Ony Mark IPs which are Local - */ - if (!CHECK_FLAG(n->flags, - ZEBRA_NEIGH_LOCAL)) - continue; - - SET_FLAG(n->flags, - ZEBRA_NEIGH_DUPLICATE); - - n->dad_dup_detect_time = - monotime(NULL); - - flog_warn( - EC_ZEBRA_DUP_IP_INHERIT_DETECTED - , - "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC", - zvni->vni, - prefix_mac2str(&mac->macaddr, - buf, sizeof(buf)), - ipaddr2str(&n->ip, buf2, - sizeof(buf2))); - } - - /* Start auto recovery timer for this - * MAC - */ - THREAD_OFF( - mac->dad_mac_auto_recovery_timer); - if (zvrf->dad_freeze && - zvrf->dad_freeze_time) { - if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("%s: duplicate addr MAC %s flags 0x%x auto recovery time %u start", - __PRETTY_FUNCTION__, - prefix_mac2str( - &mac->macaddr, - buf, - sizeof(buf)), - mac->flags, - zvrf->dad_freeze_time); - - thread_add_timer(zebrad.master, - zebra_vxlan_dad_mac_auto_recovery_exp, - mac, - zvrf->dad_freeze_time, - &mac->dad_mac_auto_recovery_timer); - } - - /* Do not inform to client (BGPd), - * upd_neigh for neigh sequence change. - */ - if (zvrf->dad_freeze) - inform_client = false; - } - } + zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac, vtep_ip, + do_dad, + &inform_client, + true); } } -send_notif: - /* Inform BGP if required. */ if (inform_client) { if (zvni_mac_send_add_to_client(zvni->vni, macaddr, -- 2.39.5