From 24cdbd0d8becedf0b9c3634c548a85179dda7bf8 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Fri, 26 Oct 2018 20:57:23 +0000 Subject: [PATCH] zebra: add json support to show evpn mac vni mac Added the json output capability in order to improve troubleshooting capabilities. Signed-off-by: Don Slice --- zebra/zebra_vty.c | 9 +- zebra/zebra_vxlan.c | 197 +++++++++++++++++++++++++++++++++----------- zebra/zebra_vxlan.h | 3 +- 3 files changed, 156 insertions(+), 53 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index cf704f24be..3873009cfb 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -2006,18 +2006,21 @@ DEFUN (show_evpn_mac_vni_all_vtep, DEFUN (show_evpn_mac_vni_mac, show_evpn_mac_vni_mac_cmd, - "show evpn mac vni " CMD_VNI_RANGE " mac WORD", + "show evpn mac vni " CMD_VNI_RANGE " mac WORD [json]", SHOW_STR "EVPN\n" "MAC addresses\n" "VxLAN Network Identifier\n" "VNI number\n" "MAC\n" - "MAC address (e.g., 00:e0:ec:20:12:62)\n") + "MAC address (e.g., 00:e0:ec:20:12:62)\n" + JSON_STR) + { struct zebra_vrf *zvrf; vni_t vni; struct ethaddr mac; + bool uj = use_json(argc, argv); vni = strtoul(argv[4]->arg, NULL, 10); if (!prefix_str2mac(argv[6]->arg, &mac)) { @@ -2025,7 +2028,7 @@ DEFUN (show_evpn_mac_vni_mac, return CMD_WARNING; } zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac); + zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj); return CMD_SUCCESS; } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 974b4d5bef..e694d36994 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -71,7 +71,7 @@ static void zl3vni_print_nh(zebra_neigh_t *n, struct vty *vty, json_object *json); static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty, json_object *json); -static void zvni_print_mac(zebra_mac_t *mac, void *ctxt); +static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json); static void zvni_print_mac_hash(struct hash_backet *backet, void *ctxt); static void zvni_print_mac_hash_all_vni(struct hash_backet *backet, void *ctxt); static void zvni_print(zebra_vni_t *zvni, void **ctxt); @@ -569,7 +569,7 @@ static void zl3vni_print_rmac(zebra_mac_t *zrmac, struct vty *vty, /* * Print a specific MAC entry. */ -static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) +static void zvni_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json) { struct vty *vty; zebra_neigh_t *n = NULL; @@ -578,56 +578,142 @@ static void zvni_print_mac(zebra_mac_t *mac, void *ctxt) char buf2[INET6_ADDRSTRLEN]; vty = (struct vty *)ctxt; - vty_out(vty, "MAC: %s", - prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1))); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { - struct zebra_ns *zns; - struct interface *ifp; - ifindex_t ifindex; + prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)); - ifindex = mac->fwd_info.local.ifindex; - zns = zebra_ns_lookup(NS_DEFAULT); - ifp = if_lookup_by_index_per_ns(zns, ifindex); - if (!ifp) // unexpected - return; - vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex); - if (mac->fwd_info.local.vid) - vty_out(vty, " VLAN: %u", mac->fwd_info.local.vid); - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - vty_out(vty, " Remote VTEP: %s", - inet_ntoa(mac->fwd_info.r_vtep_ip)); - } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) { - vty_out(vty, " Auto Mac "); - } + if (json) { + json_object *json_mac = json_object_new_object(); + + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + struct zebra_ns *zns; + struct interface *ifp; + ifindex_t ifindex; + + ifindex = mac->fwd_info.local.ifindex; + zns = zebra_ns_lookup(NS_DEFAULT); + ifp = if_lookup_by_index_per_ns(zns, ifindex); + if (!ifp) + return; + json_object_string_add(json_mac, "type", "local"); + json_object_string_add(json_mac, "intf", ifp->name); + json_object_int_add(json_mac, "ifindex", ifindex); + if (mac->fwd_info.local.vid) + json_object_int_add(json_mac, "vlan", + mac->fwd_info.local.vid); + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { + json_object_string_add(json_mac, "type", "remote"); + json_object_string_add( + json_mac, "remoteVtep", + inet_ntoa(mac->fwd_info.r_vtep_ip)); + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) + json_object_string_add(json_mac, "type", "auto mac"); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) - vty_out(vty, " Sticky Mac "); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) + json_object_boolean_true_add(json_mac, "stickyMac"); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) - vty_out(vty, " Default-gateway Mac "); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) + json_object_boolean_true_add(json_mac, + "defaultGateway"); - if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)) - vty_out(vty, " Remote-gateway Mac "); + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)) + json_object_boolean_true_add(json_mac, + "remoteGatewayMac"); - vty_out(vty, "\n"); - vty_out(vty, " Local Seq: %u Remote Seq: %u", - mac->loc_seq, mac->rem_seq); - vty_out(vty, "\n"); + json_object_int_add(json_mac, "localSequence", mac->loc_seq); + json_object_int_add(json_mac, "remoteSequence", mac->rem_seq); - /* print all the associated neigh */ - vty_out(vty, " Neighbors:\n"); - if (!listcount(mac->neigh_list)) - vty_out(vty, " No Neighbors\n"); - else { - for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) { - vty_out(vty, " %s %s\n", - ipaddr2str(&n->ip, buf2, sizeof(buf2)), - (IS_ZEBRA_NEIGH_ACTIVE(n) - ? "Active" : "Inactive")); + /* print all the associated neigh */ + if (!listcount(mac->neigh_list)) + json_object_string_add(json_mac, "neighbors", "none"); + else { + json_object *json_active_nbrs = json_object_new_array(); + json_object *json_inactive_nbrs = + json_object_new_array(); + json_object *json_nbrs = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) { + if (IS_ZEBRA_NEIGH_ACTIVE(n)) + json_object_array_add( + json_active_nbrs, + json_object_new_string( + ipaddr2str( + &n->ip, buf2, + sizeof(buf2)))); + else + json_object_array_add( + json_inactive_nbrs, + json_object_new_string( + ipaddr2str( + &n->ip, buf2, + sizeof(buf2)))); + } + + json_object_object_add(json_nbrs, "active", + json_active_nbrs); + json_object_object_add(json_nbrs, "inactive", + json_inactive_nbrs); + json_object_object_add(json_mac, "neighbors", + json_nbrs); } - } - vty_out(vty, "\n"); + 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); + + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { + struct zebra_ns *zns; + struct interface *ifp; + ifindex_t ifindex; + + ifindex = mac->fwd_info.local.ifindex; + zns = zebra_ns_lookup(NS_DEFAULT); + ifp = if_lookup_by_index_per_ns(zns, ifindex); + if (!ifp) + return; + vty_out(vty, " Intf: %s(%u)", ifp->name, ifindex); + if (mac->fwd_info.local.vid) + vty_out(vty, " VLAN: %u", + mac->fwd_info.local.vid); + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { + vty_out(vty, " Remote VTEP: %s", + inet_ntoa(mac->fwd_info.r_vtep_ip)); + } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) { + vty_out(vty, " Auto Mac "); + } + + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) + vty_out(vty, " Sticky Mac "); + + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) + vty_out(vty, " Default-gateway Mac "); + + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)) + vty_out(vty, " Remote-gateway Mac "); + + vty_out(vty, "\n"); + vty_out(vty, " Local Seq: %u Remote Seq: %u", mac->loc_seq, + mac->rem_seq); + vty_out(vty, "\n"); + + /* print all the associated neigh */ + vty_out(vty, " Neighbors:\n"); + if (!listcount(mac->neigh_list)) + vty_out(vty, " No Neighbors\n"); + else { + for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) { + vty_out(vty, " %s %s\n", + ipaddr2str(&n->ip, buf2, sizeof(buf2)), + (IS_ZEBRA_NEIGH_ACTIVE(n) + ? "Active" + : "Inactive")); + } + } + + vty_out(vty, "\n"); + } } /* @@ -5151,26 +5237,39 @@ void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, * Display specific MAC for a VNI, if present (VTY command handler). */ void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ethaddr *macaddr) + vni_t vni, struct ethaddr *macaddr, + bool use_json) { zebra_vni_t *zvni; zebra_mac_t *mac; + 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); + if (use_json) + vty_out(vty, "{}\n"); + else + 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); + if (use_json) + vty_out(vty, "{}\n"); + else + vty_out(vty, + "%% Requested MAC does not exist in VNI %u\n", + vni); return; } - zvni_print_mac(mac, vty); + if (use_json) + json = json_object_new_object(); + + zvni_print_mac(mac, vty, json); } /* diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index f03cd3d541..1c394e9eff 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -94,7 +94,8 @@ extern void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, bool use_json); extern void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ethaddr *mac); + vni_t vni, struct ethaddr *mac, + bool use_json); extern void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni, struct in_addr vtep_ip, -- 2.39.5