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 <pat@voltanet.io>
This commit is contained in:
Pat Ruddy 2020-04-24 13:48:31 +01:00
parent 7cbae20ade
commit 036daaca3e
3 changed files with 180 additions and 171 deletions

View File

@ -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;
}

View File

@ -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,

View File

@ -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. */