zebra: dup addr detect operation commands

Display duplicate detected list of MACs and VNIs.
- Per VNI
- Across all VNIs

Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
This commit is contained in:
Chirag Shah 2018-11-04 10:17:29 -08:00
parent 87454e6bd1
commit 1374d4dbc2
4 changed files with 325 additions and 7 deletions

View File

@ -1970,7 +1970,7 @@ DEFUN (show_evpn_mac_vni_all,
bool uj = use_json(argc, argv);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_all_vni(vty, zvrf, uj);
zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
return CMD_SUCCESS;
}
@ -2059,6 +2059,90 @@ DEFUN (show_evpn_mac_vni_vtep,
return CMD_SUCCESS;
}
DEFPY (show_evpn_mac_vni_all_dad,
show_evpn_mac_vni_all_dad_cmd,
"show evpn mac vni all duplicate [json]",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"All VNIs\n"
"Duplicate address list\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
bool uj = use_json(argc, argv);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
return CMD_SUCCESS;
}
DEFPY (show_evpn_mac_vni_dad,
show_evpn_mac_vni_dad_cmd,
"show evpn mac vni " CMD_VNI_RANGE " duplicate" "[json]",
SHOW_STR
"EVPN\n"
"MAC addresses\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"Duplicate address list\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
vni_t vni;
bool uj = use_json(argc, argv);
vni = strtoul(argv[4]->arg, NULL, 10);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
return CMD_SUCCESS;
}
DEFPY (show_evpn_neigh_vni_dad,
show_evpn_neigh_vni_dad_cmd,
"show evpn arp-cache vni " CMD_VNI_RANGE "duplicate" "[json]",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"VNI number\n"
"Duplicate address list\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
vni_t vni;
bool uj = use_json(argc, argv);
vni = strtoul(argv[4]->arg, NULL, 10);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
return CMD_SUCCESS;
}
DEFPY (show_evpn_neigh_vni_all_dad,
show_evpn_neigh_vni_all_dad_cmd,
"show evpn arp-cache vni all duplicate [json]",
SHOW_STR
"EVPN\n"
"ARP and ND cache\n"
"VxLAN Network Identifier\n"
"All VNIs\n"
"Duplicate address list\n"
JSON_STR)
{
struct zebra_vrf *zvrf;
bool uj = use_json(argc, argv);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
return CMD_SUCCESS;
}
DEFUN (show_evpn_neigh_vni,
show_evpn_neigh_vni_cmd,
"show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
@ -2093,7 +2177,7 @@ DEFUN (show_evpn_neigh_vni_all,
bool uj = use_json(argc, argv);
zvrf = vrf_info_lookup(VRF_DEFAULT);
zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj);
zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
return CMD_SUCCESS;
}
@ -2755,10 +2839,14 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
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(VIEW_NODE, &show_pbr_ipset_cmd);
install_element(VIEW_NODE, &show_pbr_iptable_cmd);

View File

@ -66,6 +66,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
uint16_t cmd);
static void zvni_print_neigh(zebra_neigh_t *n, void *ctxt, json_object *json);
static void zvni_print_neigh_hash(struct hash_backet *backet, void *ctxt);
static void zvni_print_dad_neigh_hash(struct hash_backet *backet, void *ctxt);
static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
void **args);
static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
@ -261,6 +262,50 @@ static uint32_t num_valid_macs(zebra_vni_t *zvni)
return num_macs;
}
static uint32_t num_dup_detected_macs(zebra_vni_t *zvni)
{
unsigned int i;
uint32_t num_macs = 0;
struct hash *hash;
struct hash_backet *hb;
zebra_mac_t *mac;
hash = zvni->mac_table;
if (!hash)
return num_macs;
for (i = 0; i < hash->size; i++) {
for (hb = hash->index[i]; hb; hb = hb->next) {
mac = (zebra_mac_t *)hb->data;
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
num_macs++;
}
}
return num_macs;
}
static uint32_t num_dup_detected_neighs(zebra_vni_t *zvni)
{
unsigned int i;
uint32_t num_neighs = 0;
struct hash *hash;
struct hash_backet *hb;
zebra_neigh_t *nbr;
hash = zvni->neigh_table;
if (!hash)
return num_neighs;
for (i = 0; i < hash->size; i++) {
for (hb = hash->index[i]; hb; hb = hb->next) {
nbr = (zebra_neigh_t *)hb->data;
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
num_neighs++;
}
}
return num_neighs;
}
static int advertise_gw_macip_enabled(zebra_vni_t *zvni)
{
struct zebra_vrf *zvrf;
@ -541,13 +586,19 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
uint32_t num_neigh;
struct neigh_walk_ctx wctx;
char vni_str[VNI_STR_LEN];
uint32_t print_dup;
vty = (struct vty *)args[0];
json = (json_object *)args[1];
print_dup = (uint32_t)(uintptr_t)args[2];
zvni = (zebra_vni_t *)backet->data;
num_neigh = hashcount(zvni->neigh_table);
if (print_dup)
num_neigh = num_dup_detected_neighs(zvni);
if (json == NULL) {
vty_out(vty,
"\nVNI %u #ARP (IPv4 and IPv6, local and remote) %u\n\n",
@ -557,6 +608,7 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
json_object_int_add(json_vni, "numArpNd", num_neigh);
snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni);
}
if (!num_neigh) {
if (json)
json_object_object_add(json, vni_str, json_vni);
@ -579,12 +631,28 @@ static void zvni_print_neigh_hash_all_vni(struct hash_backet *backet,
-wctx.addr_width, "IP", "Type",
"State", "MAC", "Remote VTEP");
}
hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
if (print_dup)
hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash,
&wctx);
else
hash_iterate(zvni->neigh_table, zvni_print_neigh_hash, &wctx);
if (json)
json_object_object_add(json, vni_str, json_vni);
}
static void zvni_print_dad_neigh_hash(struct hash_backet *backet, void *ctxt)
{
zebra_neigh_t *nbr;
nbr = (zebra_neigh_t *)backet->data;
if (!nbr)
return;
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE))
zvni_print_neigh_hash(backet, ctxt);
}
/* print a specific next hop for an l3vni */
static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty,
json_object *json)
@ -948,6 +1016,19 @@ static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt)
}
}
/* Print Duplicate MAC */
static void zvni_print_dad_mac_hash(struct hash_backet *backet, void *ctxt)
{
zebra_mac_t *mac;
mac = (zebra_mac_t *)backet->data;
if (!mac)
return;
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
zvni_print_mac_hash(backet, ctxt);
}
/*
* Print MACs for all VNI.
*/
@ -974,6 +1055,9 @@ static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt)
if (!num_macs)
return;
if (wctx->print_dup)
num_macs = num_dup_detected_macs(zvni);
if (json) {
json_vni = json_object_new_object();
json_mac = json_object_new_object();
@ -989,12 +1073,24 @@ static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt)
} else
json_object_int_add(json_vni, "numMacs", num_macs);
}
if (!num_macs) {
if (json) {
json_object_int_add(json_vni, "numMacs", num_macs);
json_object_object_add(json, vni_str, json_vni);
}
return;
}
/* assign per-vni to wctx->json object to fill macs
* under the vni. Re-assign primary json object to fill
* next vni information.
*/
wctx->json = json_mac;
hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx);
if (wctx->print_dup)
hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, wctx);
else
hash_iterate(zvni->mac_table, zvni_print_mac_hash, wctx);
wctx->json = json;
if (json) {
if (wctx->count)
@ -5528,10 +5624,10 @@ void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
* Display neighbors across all VNIs (VTY command handler).
*/
void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
bool use_json)
bool print_dup, bool use_json)
{
json_object *json = NULL;
void *args[2];
void *args[3];
if (!is_evpn_enabled())
return;
@ -5541,6 +5637,8 @@ void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
args[0] = vty;
args[1] = json;
args[2] = (void *)(ptrdiff_t)print_dup;
hash_iterate(zvrf->vni_table,
(void (*)(struct hash_backet *,
void *))zvni_print_neigh_hash_all_vni,
@ -5637,6 +5735,70 @@ void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf,
}
}
/*
* Display Duplicate detected Neighbors for a VNI
* (VTY command handler).
*/
void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
struct zebra_vrf *zvrf,
vni_t vni,
bool use_json)
{
zebra_vni_t *zvni;
uint32_t num_neigh;
struct neigh_walk_ctx wctx;
json_object *json = NULL;
if (!is_evpn_enabled())
return;
zvni = zvni_lookup(vni);
if (!zvni) {
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
}
num_neigh = hashcount(zvni->neigh_table);
if (!num_neigh)
return;
num_neigh = num_dup_detected_neighs(zvni);
if (!num_neigh)
return;
if (use_json)
json = json_object_new_object();
/* Since we have IPv6 addresses to deal with which can vary widely in
* size, we try to be a bit more elegant in display by first computing
* the maximum width.
*/
memset(&wctx, 0, sizeof(struct neigh_walk_ctx));
wctx.zvni = zvni;
wctx.vty = vty;
wctx.addr_width = 15;
wctx.json = json;
hash_iterate(zvni->neigh_table, zvni_find_neigh_addr_width, &wctx);
if (!use_json) {
vty_out(vty,
"Number of ARPs (local and remote) known for this VNI: %u\n",
num_neigh);
vty_out(vty, "%*s %-6s %-8s %-17s %-21s\n",
-wctx.addr_width, "IP", "Type",
"State", "MAC", "Remote VTEP");
} else
json_object_int_add(json, "numArpNd", num_neigh);
hash_iterate(zvni->neigh_table, zvni_print_dad_neigh_hash, &wctx);
if (use_json) {
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
}
/*
* Display MACs for a VNI (VTY command handler).
*/
@ -5696,7 +5858,7 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
* Display MACs for all VNIs (VTY command handler).
*/
void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
bool use_json)
bool print_dup, bool use_json)
{
struct mac_walk_ctx wctx;
json_object *json = NULL;
@ -5712,6 +5874,7 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf,
memset(&wctx, 0, sizeof(struct mac_walk_ctx));
wctx.vty = vty;
wctx.json = json;
wctx.print_dup = print_dup;
hash_iterate(zvrf->vni_table, zvni_print_mac_hash_all_vni, &wctx);
if (use_json) {
@ -5790,6 +5953,64 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf,
zvni_print_mac(mac, vty, json);
}
/* Print Duplicate MACs per VNI */
void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
struct zebra_vrf *zvrf,
vni_t vni, bool use_json)
{
zebra_vni_t *zvni;
struct mac_walk_ctx wctx;
uint32_t num_macs;
json_object *json = NULL;
json_object *json_mac = NULL;
if (!is_evpn_enabled())
return;
zvni = zvni_lookup(vni);
if (!zvni) {
vty_out(vty, "%% VNI %u does not exist\n", vni);
return;
}
num_macs = num_valid_macs(zvni);
if (!num_macs)
return;
num_macs = num_dup_detected_macs(zvni);
if (!num_macs)
return;
if (use_json) {
json = json_object_new_object();
json_mac = json_object_new_object();
}
memset(&wctx, 0, sizeof(struct mac_walk_ctx));
wctx.zvni = zvni;
wctx.vty = vty;
wctx.json = json_mac;
if (!use_json) {
vty_out(vty,
"Number of MACs (local and remote) known for this VNI: %u\n",
num_macs);
vty_out(vty, "%-17s %-6s %-21s %-5s\n", "MAC", "Type",
"Intf/Remote VTEP", "VLAN");
} else
json_object_int_add(json, "numMacs", num_macs);
hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash, &wctx);
if (use_json) {
json_object_object_add(json, "macs", json_mac);
vty_out(vty, "%s\n", json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
}
/*
* Display MACs for a VNI from specific VTEP (VTY command handler).
*/

View File

@ -88,6 +88,7 @@ extern void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni, bool use_json);
extern void zebra_vxlan_print_macs_all_vni(struct vty *vty,
struct zebra_vrf *zvrf,
bool print_dup,
bool use_json);
extern void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty,
struct zebra_vrf *zvrf,
@ -101,10 +102,14 @@ extern void zebra_vxlan_print_macs_vni_vtep(struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni,
struct in_addr vtep_ip,
bool use_json);
extern void zebra_vxlan_print_macs_vni_dad(struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni,
bool use_json);
extern void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni, bool use_json);
extern void zebra_vxlan_print_neigh_all_vni(struct vty *vty,
struct zebra_vrf *zvrf,
bool print_dup,
bool use_json);
extern void zebra_vxlan_print_specific_neigh_vni(struct vty *vty,
struct zebra_vrf *zvrf,
@ -114,6 +119,9 @@ extern void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni,
struct in_addr vtep_ip,
bool use_json);
extern void zebra_vxlan_print_neigh_vni_dad(struct vty *vty,
struct zebra_vrf *zvrf, vni_t vni,
bool use_json);
extern void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf,
vni_t vni, bool use_json);
extern void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf,

View File

@ -305,6 +305,7 @@ struct mac_walk_ctx {
struct vty *vty; /* Used by VTY handlers */
uint32_t count; /* Used by VTY handlers */
struct json_object *json; /* Used for JSON Output */
bool print_dup; /* Used to print dup addr list */
};
struct rmac_walk_ctx {