mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:53:55 +00:00
zebra: dup addr detect clear command
Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
This commit is contained in:
parent
1374d4dbc2
commit
09de9258a9
@ -2277,6 +2277,55 @@ DEFUN (show_pbr_iptable,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (clear_evpn_dup_addr,
|
||||
clear_evpn_dup_addr_cmd,
|
||||
"clear evpn dup-addr vni <all$vni_all |" CMD_VNI_RANGE"$vni_val [mac M:A:C$mac_val | ip <A.B.C.D|X:X::X:X>]>",
|
||||
CLEAR_STR
|
||||
"EVPN\n"
|
||||
"Duplicate address \n"
|
||||
"VxLAN Network Identifier\n"
|
||||
"VNI number\n"
|
||||
"All VNIs\n"
|
||||
"MAC\n"
|
||||
"MAC address (e.g., 00:e0:ec:20:12:62)\n"
|
||||
"IP\n"
|
||||
"IPv4 address\n"
|
||||
"IPv6 address\n")
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
vni_t vni = 0;
|
||||
struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
|
||||
struct ethaddr mac_addr;
|
||||
|
||||
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||
if (vni_val) {
|
||||
vni = strtoul(vni_val, NULL, 10);
|
||||
|
||||
if (mac_val) {
|
||||
prefix_str2mac(mac_val, &mac_addr);
|
||||
zebra_vxlan_clear_dup_detect_vni_mac(vty, zvrf, vni,
|
||||
&mac_addr);
|
||||
} else if (ip) {
|
||||
if (sockunion_family(ip) == AF_INET) {
|
||||
host_ip.ipa_type = IPADDR_V4;
|
||||
host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
|
||||
} else {
|
||||
host_ip.ipa_type = IPADDR_V6;
|
||||
memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
}
|
||||
zebra_vxlan_clear_dup_detect_vni_ip(vty, zvrf, vni,
|
||||
&host_ip);
|
||||
} else
|
||||
zebra_vxlan_clear_dup_detect_vni(vty, zvrf, vni);
|
||||
|
||||
} else {
|
||||
zebra_vxlan_clear_dup_detect_vni_all(vty, zvrf);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Static ip route configuration write function. */
|
||||
static int zebra_ip_config(struct vty *vty)
|
||||
{
|
||||
@ -2847,6 +2896,7 @@ void zebra_vty_init(void)
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
|
||||
install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
|
||||
install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
|
||||
|
||||
install_element(VIEW_NODE, &show_pbr_ipset_cmd);
|
||||
install_element(VIEW_NODE, &show_pbr_iptable_cmd);
|
||||
|
@ -6011,6 +6011,335 @@ void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
|
||||
|
||||
}
|
||||
|
||||
void zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni, struct ethaddr *macaddr)
|
||||
{
|
||||
zebra_vni_t *zvni;
|
||||
zebra_mac_t *mac;
|
||||
struct listnode *node = NULL;
|
||||
zebra_neigh_t *nbr = NULL;
|
||||
|
||||
if (!is_evpn_enabled())
|
||||
return;
|
||||
zvni = zvni_lookup(vni);
|
||||
if (!zvni) {
|
||||
vty_out(vty, "%% VNI %u does not exist\n", vni);
|
||||
return;
|
||||
}
|
||||
|
||||
mac = zvni_mac_lookup(zvni, macaddr);
|
||||
if (!mac) {
|
||||
vty_out(vty, "%% Requested MAC does not exist in VNI %u\n",
|
||||
vni);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
|
||||
vty_out(vty, "%% Requested MAC is not duplicate detected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove all IPs as duplicate associcated with this MAC */
|
||||
for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
|
||||
/* For local neigh mark inactive so MACIP update is generated
|
||||
* to BGP. This is a scenario where MAC update received
|
||||
* and detected as duplicate which marked neigh as duplicate.
|
||||
* Later local neigh update did not get a chance to relay
|
||||
* to BGP. Similarly remote macip update, neigh needs to be
|
||||
* installed locally.
|
||||
*/
|
||||
if (nbr->dad_count) {
|
||||
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
|
||||
ZEBRA_NEIGH_SET_INACTIVE(nbr);
|
||||
else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
|
||||
zvni_neigh_install(zvni, nbr);
|
||||
}
|
||||
|
||||
UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
|
||||
nbr->dad_count = 0;
|
||||
nbr->detect_start_time.tv_sec = 0;
|
||||
nbr->dad_dup_detect_time = 0;
|
||||
}
|
||||
|
||||
UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
|
||||
mac->dad_count = 0;
|
||||
mac->detect_start_time.tv_sec = 0;
|
||||
mac->detect_start_time.tv_usec = 0;
|
||||
mac->dad_dup_detect_time = 0;
|
||||
THREAD_OFF(mac->dad_mac_auto_recovery_timer);
|
||||
|
||||
/* Local: Notify Peer VTEPs, Remote: Install the entry */
|
||||
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
|
||||
/* Inform to BGP */
|
||||
if (zvni_mac_send_add_to_client(zvni->vni,
|
||||
&mac->macaddr,
|
||||
mac->flags,
|
||||
mac->loc_seq))
|
||||
return;
|
||||
|
||||
/* Process all neighbors associated with this MAC. */
|
||||
zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
|
||||
|
||||
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
||||
zvni_process_neigh_on_remote_mac_add(zvni, mac);
|
||||
|
||||
/* Install the entry. */
|
||||
zvni_mac_install(zvni, mac);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni, struct ipaddr *ip)
|
||||
{
|
||||
zebra_vni_t *zvni;
|
||||
zebra_neigh_t *nbr;
|
||||
zebra_mac_t *mac;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
char buf2[ETHER_ADDR_STRLEN];
|
||||
|
||||
if (!is_evpn_enabled())
|
||||
return;
|
||||
|
||||
zvni = zvni_lookup(vni);
|
||||
if (!zvni) {
|
||||
vty_out(vty, "%% VNI %u does not exist\n", vni);
|
||||
return;
|
||||
}
|
||||
|
||||
nbr = zvni_neigh_lookup(zvni, ip);
|
||||
if (!nbr) {
|
||||
vty_out(vty,
|
||||
"%% Requested host IP does not exist in VNI %u\n",
|
||||
vni);
|
||||
return;
|
||||
}
|
||||
|
||||
ipaddr2str(&nbr->ip, buf, sizeof(buf));
|
||||
|
||||
if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
|
||||
vty_out(vty,
|
||||
"%% Requsted host IP %s is not duplicate detected\n",
|
||||
buf);
|
||||
return;
|
||||
}
|
||||
|
||||
mac = zvni_mac_lookup(zvni, &nbr->emac);
|
||||
|
||||
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
|
||||
vty_out(vty,
|
||||
"%% Requested IP's associated MAC %s is still in duplicate state\n",
|
||||
prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug("%s: clear neigh %s in dup state, flags 0x%x seq %u",
|
||||
__PRETTY_FUNCTION__, buf, nbr->flags,
|
||||
nbr->loc_seq);
|
||||
|
||||
UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
|
||||
nbr->dad_count = 0;
|
||||
nbr->detect_start_time.tv_sec = 0;
|
||||
nbr->detect_start_time.tv_usec = 0;
|
||||
nbr->dad_dup_detect_time = 0;
|
||||
THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
|
||||
|
||||
if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
|
||||
zvni_neigh_send_add_to_client(zvni->vni, ip,
|
||||
&nbr->emac,
|
||||
nbr->flags, nbr->loc_seq);
|
||||
} else if (!!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
|
||||
zvni_neigh_install(zvni, nbr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void zvni_clear_dup_mac_hash(struct hash_backet *backet, void *ctxt)
|
||||
{
|
||||
struct mac_walk_ctx *wctx = ctxt;
|
||||
zebra_mac_t *mac;
|
||||
zebra_vni_t *zvni;
|
||||
struct listnode *node = NULL;
|
||||
zebra_neigh_t *nbr = NULL;
|
||||
|
||||
mac = (zebra_mac_t *)backet->data;
|
||||
if (!mac)
|
||||
return;
|
||||
|
||||
zvni = wctx->zvni;
|
||||
|
||||
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
|
||||
return;
|
||||
|
||||
UNSET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
|
||||
mac->dad_count = 0;
|
||||
mac->detect_start_time.tv_sec = 0;
|
||||
mac->detect_start_time.tv_usec = 0;
|
||||
mac->dad_dup_detect_time = 0;
|
||||
THREAD_OFF(mac->dad_mac_auto_recovery_timer);
|
||||
|
||||
/* Remove all IPs as duplicate associcated with this MAC */
|
||||
for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
|
||||
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)
|
||||
&& nbr->dad_count)
|
||||
ZEBRA_NEIGH_SET_INACTIVE(nbr);
|
||||
|
||||
UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
|
||||
nbr->dad_count = 0;
|
||||
nbr->detect_start_time.tv_sec = 0;
|
||||
nbr->dad_dup_detect_time = 0;
|
||||
}
|
||||
|
||||
/* Local: Notify Peer VTEPs, Remote: Install the entry */
|
||||
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
|
||||
/* Inform to BGP */
|
||||
if (zvni_mac_send_add_to_client(zvni->vni,
|
||||
&mac->macaddr,
|
||||
mac->flags, mac->loc_seq))
|
||||
return;
|
||||
|
||||
/* Process all neighbors associated with this MAC. */
|
||||
zvni_process_neigh_on_local_mac_change(zvni, mac, 0);
|
||||
|
||||
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
|
||||
zvni_process_neigh_on_remote_mac_add(zvni, mac);
|
||||
|
||||
/* Install the entry. */
|
||||
zvni_mac_install(zvni, mac);
|
||||
}
|
||||
}
|
||||
|
||||
static void zvni_clear_dup_neigh_hash(struct hash_backet *backet, void *ctxt)
|
||||
{
|
||||
struct neigh_walk_ctx *wctx = ctxt;
|
||||
zebra_neigh_t *nbr;
|
||||
zebra_vni_t *zvni;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
nbr = (zebra_neigh_t *)backet->data;
|
||||
if (!nbr)
|
||||
return;
|
||||
|
||||
zvni = wctx->zvni;
|
||||
|
||||
if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
|
||||
return;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN) {
|
||||
ipaddr2str(&nbr->ip, buf, sizeof(buf));
|
||||
zlog_debug(
|
||||
"%s: clear neigh %s dup state, flags 0x%x seq %u",
|
||||
__PRETTY_FUNCTION__, buf,
|
||||
nbr->flags, nbr->loc_seq);
|
||||
}
|
||||
|
||||
UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
|
||||
nbr->dad_count = 0;
|
||||
nbr->detect_start_time.tv_sec = 0;
|
||||
nbr->detect_start_time.tv_usec = 0;
|
||||
nbr->dad_dup_detect_time = 0;
|
||||
THREAD_OFF(nbr->dad_ip_auto_recovery_timer);
|
||||
|
||||
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) {
|
||||
zvni_neigh_send_add_to_client(zvni->vni, &nbr->ip,
|
||||
&nbr->emac,
|
||||
nbr->flags, nbr->loc_seq);
|
||||
} else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) {
|
||||
zvni_neigh_install(zvni, nbr);
|
||||
}
|
||||
}
|
||||
|
||||
static void zvni_clear_dup_detect_hash_vni_all(struct hash_backet *backet,
|
||||
void **args)
|
||||
{
|
||||
struct vty *vty;
|
||||
zebra_vni_t *zvni;
|
||||
struct zebra_vrf *zvrf;
|
||||
struct mac_walk_ctx m_wctx;
|
||||
struct neigh_walk_ctx n_wctx;
|
||||
|
||||
zvni = (zebra_vni_t *)backet->data;
|
||||
if (!zvni)
|
||||
return;
|
||||
|
||||
vty = (struct vty *)args[0];
|
||||
zvrf = (struct zebra_vrf *)args[1];
|
||||
|
||||
if (hashcount(zvni->neigh_table)) {
|
||||
memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
|
||||
n_wctx.vty = vty;
|
||||
n_wctx.zvni = zvni;
|
||||
n_wctx.zvrf = zvrf;
|
||||
hash_iterate(zvni->neigh_table, zvni_clear_dup_neigh_hash,
|
||||
&n_wctx);
|
||||
}
|
||||
|
||||
if (num_valid_macs(zvni)) {
|
||||
memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
|
||||
m_wctx.zvni = zvni;
|
||||
m_wctx.vty = vty;
|
||||
m_wctx.zvrf = zvrf;
|
||||
hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
|
||||
struct zebra_vrf *zvrf)
|
||||
{
|
||||
void *args[2];
|
||||
|
||||
if (!is_evpn_enabled())
|
||||
return;
|
||||
|
||||
args[0] = vty;
|
||||
args[1] = zvrf;
|
||||
|
||||
hash_iterate(zvrf->vni_table,
|
||||
(void (*)(struct hash_backet *, void *))
|
||||
zvni_clear_dup_detect_hash_vni_all, args);
|
||||
|
||||
}
|
||||
|
||||
void zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni)
|
||||
{
|
||||
zebra_vni_t *zvni;
|
||||
struct mac_walk_ctx m_wctx;
|
||||
struct neigh_walk_ctx n_wctx;
|
||||
|
||||
if (!is_evpn_enabled())
|
||||
return;
|
||||
|
||||
zvni = zvni_lookup(vni);
|
||||
if (!zvni) {
|
||||
vty_out(vty, "%% VNI %u does not exist\n", vni);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hashcount(zvni->neigh_table)) {
|
||||
memset(&n_wctx, 0, sizeof(struct neigh_walk_ctx));
|
||||
n_wctx.vty = vty;
|
||||
n_wctx.zvni = zvni;
|
||||
n_wctx.zvrf = zvrf;
|
||||
hash_iterate(zvni->neigh_table, zvni_clear_dup_neigh_hash,
|
||||
&n_wctx);
|
||||
}
|
||||
|
||||
if (num_valid_macs(zvni)) {
|
||||
memset(&m_wctx, 0, sizeof(struct mac_walk_ctx));
|
||||
m_wctx.zvni = zvni;
|
||||
m_wctx.vty = vty;
|
||||
m_wctx.zvrf = zvrf;
|
||||
hash_iterate(zvni->mac_table, zvni_clear_dup_mac_hash, &m_wctx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Display MACs for a VNI from specific VTEP (VTY command handler).
|
||||
*/
|
||||
@ -6200,6 +6529,12 @@ void zebra_vxlan_dup_addr_detection(ZAPI_HANDLER_ARGS)
|
||||
STREAM_GETL(s, freeze);
|
||||
STREAM_GETL(s, freeze_time);
|
||||
|
||||
/* DAD previous state was enabled, and new state is disable,
|
||||
* clear all duplicate detected addresses.
|
||||
*/
|
||||
if (zvrf->dup_addr_detect && !dup_addr_detect)
|
||||
zebra_vxlan_clear_dup_detect_vni_all(NULL, zvrf);
|
||||
|
||||
zvrf->dup_addr_detect = dup_addr_detect;
|
||||
zvrf->dad_time = time;
|
||||
zvrf->dad_max_moves = max_moves;
|
||||
|
@ -181,5 +181,17 @@ extern void zebra_vxlan_evpn_vrf_route_add(vrf_id_t vrf_id,
|
||||
extern void zebra_vxlan_evpn_vrf_route_del(vrf_id_t vrf_id,
|
||||
struct ipaddr *vtep_ip,
|
||||
struct prefix *host_prefix);
|
||||
extern void zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni,
|
||||
struct ethaddr *macaddr);
|
||||
extern void zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni, struct ipaddr *ip);
|
||||
extern void zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
|
||||
struct zebra_vrf *zvrf);
|
||||
extern void zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
|
||||
struct zebra_vrf *zvrf,
|
||||
vni_t vni);
|
||||
|
||||
#endif /* _ZEBRA_VXLAN_H */
|
||||
|
Loading…
Reference in New Issue
Block a user