From cffe7580fd709d1878b2605b2057a1b8ae67175c Mon Sep 17 00:00:00 2001 From: Nitin Soni Date: Thu, 22 Nov 2018 00:18:10 -0800 Subject: [PATCH] zebra: Add "show evpn mac vni all detail" command Change helps display detailed output for all possible VNI MACs without specifying VNI or mac. It helps in troubleshooting - a single command can be fired to capture detailed info on all VNIs. Also fixed and existing json related bug where json object is created by a parent function and freed in child function. Ticket: CM-22832 Signed-off-by: Nitin Soni Reviewed-by: CCR-8028 --- zebra/zebra_vty.c | 19 ++++++ zebra/zebra_vxlan.c | 144 ++++++++++++++++++++++++++++++++++++++++++-- zebra/zebra_vxlan.h | 4 ++ 3 files changed, 163 insertions(+), 4 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 536fdabcbc..9c910e9f11 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1974,6 +1974,24 @@ DEFUN (show_evpn_mac_vni_all, return CMD_SUCCESS; } +DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd, + "show evpn mac vni all detail [json]", + SHOW_STR + "EVPN\n" + "MAC addresses\n" + "VxLAN Network Identifier\n" + "All VNIs\n" + "Detailed Information On Each VNI MAC\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_detail(vty, zvrf, false, uj); + return CMD_SUCCESS; +} + DEFUN (show_evpn_mac_vni_all_vtep, show_evpn_mac_vni_all_vtep_cmd, "show evpn mac vni all vtep A.B.C.D [json]", @@ -2885,6 +2903,7 @@ void zebra_vty_init(void) install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd); install_element(VIEW_NODE, &show_evpn_mac_vni_cmd); install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd); + install_element(VIEW_NODE, &show_evpn_mac_vni_all_detail_cmd); 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); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 86f6961118..07f2606fc8 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1126,10 +1126,6 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json) } json_object_object_add(json, buf1, json_mac); - vty_out(vty, "%s\n", - json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); } else { vty_out(vty, "MAC: %s\n", buf1); @@ -1326,6 +1322,43 @@ static void zvni_print_dad_mac_hash(struct hash_backet *backet, void *ctxt) zvni_print_mac_hash(backet, ctxt); } +/* + * Print MAC hash entry in detail - called for display of all MACs. + */ +static void zvni_print_mac_hash_detail(struct hash_backet *backet, void *ctxt) +{ + struct vty *vty; + json_object *json_mac_hdr = NULL; + zebra_mac_t *mac; + struct mac_walk_ctx *wctx = ctxt; + char buf1[20]; + + vty = wctx->vty; + json_mac_hdr = wctx->json; + mac = (zebra_mac_t *)backet->data; + if (!mac) + return; + + wctx->count++; + prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); + + zvni_print_mac(mac, vty, json_mac_hdr); +} + +/* Print Duplicate MAC in detail */ +static void zvni_print_dad_mac_hash_detail(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_detail(backet, ctxt); +} + /* * Print MACs for all VNI. */ @@ -1396,6 +1429,72 @@ static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt) } } +/* + * Print MACs in detail for all VNI. + */ +static void zvni_print_mac_hash_all_vni_detail(struct hash_backet *backet, + void *ctxt) +{ + struct vty *vty; + json_object *json = NULL, *json_vni = NULL; + json_object *json_mac = NULL; + zebra_vni_t *zvni; + uint32_t num_macs; + struct mac_walk_ctx *wctx = ctxt; + char vni_str[VNI_STR_LEN]; + + vty = (struct vty *)wctx->vty; + json = (struct json_object *)wctx->json; + + zvni = (zebra_vni_t *)backet->data; + if (!zvni) { + if (json) + vty_out(vty, "{}\n"); + return; + } + wctx->zvni = zvni; + + /*We are iterating over a new VNI, set the count to 0*/ + wctx->count = 0; + + num_macs = num_valid_macs(zvni); + if (!num_macs) + return; + + if (wctx->print_dup && (num_dup_detected_macs(zvni) == 0)) + return; + + if (json) { + json_vni = json_object_new_object(); + json_mac = json_object_new_object(); + snprintf(vni_str, VNI_STR_LEN, "%u", zvni->vni); + } + + if (!CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)) { + if (json == NULL) { + vty_out(vty, "\nVNI %u #MACs (local and remote) %u\n\n", + zvni->vni, num_macs); + } else + json_object_int_add(json_vni, "numMacs", num_macs); + } + /* 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; + if (wctx->print_dup) + hash_iterate(zvni->mac_table, zvni_print_dad_mac_hash_detail, + wctx); + else + hash_iterate(zvni->mac_table, zvni_print_mac_hash_detail, wctx); + wctx->json = json; + if (json) { + if (wctx->count) + json_object_object_add(json_vni, "macs", json_mac); + json_object_object_add(json, vni_str, json_vni); + } +} + static void zl3vni_print_nh_hash(struct hash_backet *backet, void *ctx) { struct nh_walk_ctx *wctx = NULL; @@ -5900,6 +5999,38 @@ void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf, } } +/* + * Display MACs in detail for all VNIs (VTY command handler). + */ +void zebra_vxlan_print_macs_all_vni_detail(struct vty *vty, + struct zebra_vrf *zvrf, + bool print_dup, bool use_json) +{ + struct mac_walk_ctx wctx; + json_object *json = NULL; + + if (!is_evpn_enabled()) { + if (use_json) + vty_out(vty, "{}\n"); + return; + } + if (use_json) + json = json_object_new_object(); + + 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_detail, + &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 all VNIs (VTY command handler). */ @@ -5967,6 +6098,11 @@ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, json = json_object_new_object(); zvni_print_mac(mac, vty, json); + if (use_json) { + vty_out(vty, "%s\n", json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } } /* Print Duplicate MACs per VNI */ diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index bf6e4290dc..5c4b721341 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -90,6 +90,10 @@ 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_detail(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, struct in_addr vtep_ip, -- 2.39.5