From 036daaca3e81bb0260eadef695c0c69a006ef147 Mon Sep 17 00:00:00 2001 From: Pat Ruddy Date: Fri, 24 Apr 2020 13:48:31 +0100 Subject: [PATCH] zebra: extract neigbor processing from remote_macip_add extract the neighbor part of process_remote_macip_add into a new function process_neigh_remote_macip_add in zebra_evpn_neigh.c. Signed-off-by: Pat Ruddy --- zebra/zebra_evpn_neigh.c | 182 +++++++++++++++++++++++++++++++++++++-- zebra/zebra_evpn_neigh.h | 13 +-- zebra/zebra_vxlan.c | 156 +-------------------------------- 3 files changed, 180 insertions(+), 171 deletions(-) diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c index 98ef4a28f2..858f0b99f6 100644 --- a/zebra/zebra_evpn_neigh.c +++ b/zebra/zebra_evpn_neigh.c @@ -1081,7 +1081,8 @@ static int zebra_evpn_neigh_probe(zebra_evpn_t *zevpn, zebra_neigh_t *n) return 0; } -void zebra_evpn_probe_neigh_on_mac_add(zebra_evpn_t *zevpn, zebra_mac_t *zmac) +static void zebra_evpn_probe_neigh_on_mac_add(zebra_evpn_t *zevpn, + zebra_mac_t *zmac) { zebra_neigh_t *nbr = NULL; struct listnode *node = NULL; @@ -1119,10 +1120,10 @@ static inline void zebra_evpn_local_neigh_update_log( * MAC binding changes, ensure to inherit duplicate flag * from MAC. */ -int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, - zebra_mac_t *old_zmac, - zebra_mac_t *new_zmac, - zebra_neigh_t *nbr) +static int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, + zebra_mac_t *old_zmac, + zebra_mac_t *new_zmac, + zebra_neigh_t *nbr) { bool is_old_mac_dup = false; bool is_new_mac_dup = false; @@ -1213,10 +1214,10 @@ static int zebra_evpn_dad_ip_auto_recovery_exp(struct thread *t) return 0; } -void zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, - zebra_neigh_t *nbr, - struct in_addr vtep_ip, bool do_dad, - bool *is_dup_detect, bool is_local) +static void +zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr, + struct in_addr vtep_ip, bool do_dad, + bool *is_dup_detect, bool is_local) { struct timeval elapsed = {0, 0}; @@ -2121,3 +2122,166 @@ void zebra_evpn_print_dad_neigh_hash_detail(struct hash_bucket *bucket, if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) zebra_evpn_print_neigh_hash_detail(bucket, ctxt); } + +void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf, + struct ipaddr *ipaddr, zebra_mac_t *mac, + struct in_addr vtep_ip, uint8_t flags, + uint32_t seq) +{ + 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; + bool old_static = false; + bool do_dad = false; + bool is_dup_detect = false; + bool is_router; + + is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); + + /* Check if the remote neighbor itself is unknown or has a + * change. If so, create or update and then install the entry. + */ + n = zebra_evpn_neigh_lookup(zevpn, ipaddr); + if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + || is_router != !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) + || (memcmp(&n->emac, &mac->macaddr, sizeof(struct ethaddr)) != 0) + || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip) || seq != n->rem_seq) + update_neigh = 1; + + if (update_neigh) { + if (!n) { + n = zebra_evpn_neigh_add(zevpn, ipaddr, &mac->macaddr, + mac, 0); + if (!n) { + zlog_warn( + "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", + ipaddr2str(ipaddr, buf1, sizeof(buf1)), + prefix_mac2str(&mac->macaddr, buf, + sizeof(buf)), + zevpn->vni, inet_ntoa(vtep_ip)); + return; + } + + } 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 + * in transient situations (because {IP1,M1} + * is a different route from {IP1,M2}). Check + * 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); + return; + } + if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + old_static = zebra_evpn_neigh_is_static(n); + if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH) + zlog_debug( + "sync->remote neigh vni %u ip %s mac %s seq %d f0x%x", + n->zevpn->vni, + ipaddr2str(&n->ip, buf1, + sizeof(buf1)), + prefix_mac2str(&n->emac, buf, + sizeof(buf)), + seq, n->flags); + zebra_evpn_neigh_clear_sync_info(n); + if (IS_ZEBRA_NEIGH_ACTIVE(n)) + zebra_evpn_mac_send_del_to_client( + zevpn->vni, &mac->macaddr, + mac->flags, false /*force*/); + } + if (memcmp(&n->emac, &mac->macaddr, + sizeof(struct ethaddr)) + != 0) { + /* update neigh list for macs */ + old_mac = + zebra_evpn_mac_lookup(zevpn, &n->emac); + if (old_mac) { + listnode_delete(old_mac->neigh_list, n); + n->mac = NULL; + zebra_evpn_deref_ip2mac(zevpn, old_mac); + } + n->mac = mac; + listnode_add_sort(mac->neigh_list, n); + memcpy(&n->emac, &mac->macaddr, ETH_ALEN); + + /* Check Neigh's curent state is local + * (this is the case where neigh/host has moved + * from L->R) and check previous detction + * started via local learning. + * + * RFC-7432: A PE/VTEP that detects a MAC + * mobilit event via local learning starts + * an M-second timer. + * VTEP-IP or seq. change along is not + * considered for dup. detection. + * + * Mobilty event scenario-B IP-MAC binding + * changed. + */ + if ((!CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) + && n->dad_count) + do_dad = true; + } + } + + /* Set "remote" forwarding info. */ + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ALL_LOCAL_FLAGS); + n->r_vtep_ip = vtep_ip; + SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); + + /* Set router flag (R-bit) to this Neighbor entry */ + if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + + /* Check old or new MAC detected as duplicate, + * inherit duplicate flag to this neigh. + */ + if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_mac, mac, n)) { + flog_warn( + EC_ZEBRA_DUP_IP_INHERIT_DETECTED, + "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC", + zevpn->vni, + prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), + ipaddr2str(&n->ip, buf1, sizeof(buf1))); + } + + /* Check duplicate address detection for IP */ + zebra_evpn_dup_addr_detect_for_neigh( + zvrf, n, n->r_vtep_ip, do_dad, &is_dup_detect, false); + /* Install the entry. */ + if (!is_dup_detect) + zebra_evpn_rem_neigh_install(zevpn, n, old_static); + } + + zebra_evpn_probe_neigh_on_mac_add(zevpn, mac); + + /* Update seq number. */ + n->rem_seq = seq; +} diff --git a/zebra/zebra_evpn_neigh.h b/zebra/zebra_evpn_neigh.h index 7520a515bb..ddeb6ab8ba 100644 --- a/zebra/zebra_evpn_neigh.h +++ b/zebra/zebra_evpn_neigh.h @@ -275,19 +275,14 @@ void zebra_evpn_print_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt); void zebra_evpn_print_dad_neigh_hash(struct hash_bucket *bucket, void *ctxt); void zebra_evpn_print_dad_neigh_hash_detail(struct hash_bucket *bucket, void *ctxt); +void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf, + struct ipaddr *ipaddr, zebra_mac_t *mac, + struct in_addr vtep_ip, uint8_t flags, + uint32_t seq); -void zebra_evpn_probe_neigh_on_mac_add(zebra_evpn_t *zevpn, zebra_mac_t *zmac); zebra_neigh_t *zebra_evpn_neigh_add(zebra_evpn_t *zevpn, struct ipaddr *ip, struct ethaddr *mac, zebra_mac_t *zmac, uint32_t n_flags); -int zebra_evpn_ip_inherit_dad_from_mac(struct zebra_vrf *zvrf, - zebra_mac_t *old_zmac, - zebra_mac_t *new_zmac, - zebra_neigh_t *nbr); -void zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, - zebra_neigh_t *nbr, - struct in_addr vtep_ip, bool do_dad, - bool *is_dup_detect, bool is_local); int zebra_evpn_neigh_uninstall(zebra_evpn_t *zevpn, zebra_neigh_t *n); void zebra_evpn_neigh_send_add_del_to_client(zebra_neigh_t *n, bool old_bgp_ready, diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 3ba4be855f..5cb124682b 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -3345,19 +3345,10 @@ static void process_remote_macip_add(vni_t vni, { zebra_evpn_t *zevpn; zebra_vtep_t *zvtep; - zebra_mac_t *mac = NULL, *old_mac = NULL; - zebra_neigh_t *n = NULL; - int update_neigh = 0; - char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; + zebra_mac_t *mac = NULL; struct interface *ifp = NULL; struct zebra_if *zif = NULL; struct zebra_vrf *zvrf; - uint32_t tmp_seq; - bool is_router; - bool do_dad = false; - bool is_dup_detect = false; - bool old_static = false; /* Locate EVPN hash entry - expected to exist. */ zevpn = zevpn_lookup(vni); @@ -3410,8 +3401,6 @@ static void process_remote_macip_add(vni_t vni, } } - is_router = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); - zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id); if (!zvrf) return; @@ -3422,147 +3411,8 @@ static void process_remote_macip_add(vni_t vni, != 0) return; - /* Check if the remote neighbor itself is unknown or has a - * change. If so, create or update and then install the entry. - */ - n = zebra_evpn_neigh_lookup(zevpn, ipaddr); - if (!n - || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) - || is_router != !!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) - || (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) - || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip) - || seq != n->rem_seq) - update_neigh = 1; - - if (update_neigh) { - if (!n) { - n = zebra_evpn_neigh_add(zevpn, ipaddr, macaddr, mac, - 0); - if (!n) { - zlog_warn( - "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %s", - ipaddr2str(ipaddr, buf1, - sizeof(buf1)), - prefix_mac2str(macaddr, buf, - sizeof(buf)), - vni, inet_ntoa(vtep_ip)); - return; - } - - } 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 - * in transient situations (because {IP1,M1} - * is a different route from {IP1,M2}). Check - * 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", - vni, - prefix_mac2str(macaddr, - buf, sizeof(buf)), - " IP ", - ipaddr2str(ipaddr, buf1, sizeof(buf1)), - n_type, - tmp_seq); - return; - } - if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { - old_static = zebra_evpn_neigh_is_static(n); - if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH) - zlog_debug("sync->remote neigh vni %u ip %s mac %s seq %d f0x%x", - n->zevpn->vni, - ipaddr2str(&n->ip, buf1, - sizeof(buf1)), - prefix_mac2str(&n->emac, buf, - sizeof(buf)), - seq, n->flags); - zebra_evpn_neigh_clear_sync_info(n); - if (IS_ZEBRA_NEIGH_ACTIVE(n)) - zebra_evpn_mac_send_del_to_client( - zevpn->vni, macaddr, mac->flags, - false /*force*/); - } - if (memcmp(&n->emac, macaddr, sizeof(*macaddr)) != 0) { - /* update neigh list for macs */ - old_mac = - zebra_evpn_mac_lookup(zevpn, &n->emac); - if (old_mac) { - listnode_delete(old_mac->neigh_list, n); - n->mac = NULL; - zebra_evpn_deref_ip2mac(zevpn, old_mac); - } - n->mac = mac; - listnode_add_sort(mac->neigh_list, n); - memcpy(&n->emac, macaddr, ETH_ALEN); - - /* Check Neigh's curent state is local - * (this is the case where neigh/host has moved - * from L->R) and check previous detction - * started via local learning. - * - * RFC-7432: A PE/VTEP that detects a MAC - * mobilit event via local learning starts - * an M-second timer. - * VTEP-IP or seq. change along is not - * considered for dup. detection. - * - * Mobilty event scenario-B IP-MAC binding - * changed. - */ - if ((!CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)) - && n->dad_count) - do_dad = true; - - } - } - - /* Set "remote" forwarding info. */ - UNSET_FLAG(n->flags, ZEBRA_NEIGH_ALL_LOCAL_FLAGS); - n->r_vtep_ip = vtep_ip; - SET_FLAG(n->flags, ZEBRA_NEIGH_REMOTE); - - /* Set router flag (R-bit) to this Neighbor entry */ - if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) - SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - else - UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - - /* Check old or new MAC detected as duplicate, - * inherit duplicate flag to this neigh. - */ - if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_mac, mac, n)) { - flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED, - "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC", - zevpn->vni, - prefix_mac2str(&mac->macaddr, buf, sizeof(buf)), - ipaddr2str(&n->ip, buf1, sizeof(buf1))); - } - - /* Check duplicate address detection for IP */ - zebra_evpn_dup_addr_detect_for_neigh( - zvrf, n, n->r_vtep_ip, do_dad, &is_dup_detect, false); - /* Install the entry. */ - if (!is_dup_detect) - zebra_evpn_rem_neigh_install(zevpn, n, old_static); - } - - zebra_evpn_probe_neigh_on_mac_add(zevpn, mac); - - /* Update seq number. */ - n->rem_seq = seq; + process_neigh_remote_macip_add(zevpn, zvrf, ipaddr, mac, vtep_ip, flags, + seq); } /* Process a remote MACIP delete from BGP. */ -- 2.39.5