mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-01-05 01:03:31 +00:00
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:
parent
7cbae20ade
commit
036daaca3e
@ -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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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. */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user