diff options
author | Renato Westphal <renato@opensourcerouting.org> | 2021-08-02 20:38:26 +0200 |
---|---|---|
committer | Renato Westphal <renato@opensourcerouting.org> | 2021-08-02 22:19:45 +0200 |
commit | c15dc24f79c97c670dd2114621ae9f6236b13348 (patch) | |
tree | 43462ba34fdbadbaf0a214cf8d45dcab68844ac2 /zebra | |
parent | lib: add "json" option to "show route-map" (diff) | |
download | frr-c15dc24f79c97c670dd2114621ae9f6236b13348.tar.xz frr-c15dc24f79c97c670dd2114621ae9f6236b13348.zip |
zebra: add "json" option to "show interface"
Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/interface.c | 631 | ||||
-rw-r--r-- | zebra/zebra_evpn_mh.c | 95 | ||||
-rw-r--r-- | zebra/zebra_evpn_mh.h | 3 | ||||
-rw-r--r-- | zebra/zebra_ptm.c | 21 | ||||
-rw-r--r-- | zebra/zebra_ptm.h | 3 |
5 files changed, 652 insertions, 101 deletions
diff --git a/zebra/interface.c b/zebra/interface.c index 408c01649..8558bf91d 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1205,59 +1205,77 @@ void zebra_if_set_protodown(struct interface *ifp, bool down) #endif } -/* Output prefix string to vty. */ -static int prefix_vty_out(struct vty *vty, struct prefix *p) -{ - char str[INET6_ADDRSTRLEN]; - - inet_ntop(p->family, &p->u.prefix, str, sizeof(str)); - vty_out(vty, "%s", str); - return strlen(str); -} - /* Dump if address information to vty. */ -static void connected_dump_vty(struct vty *vty, struct connected *connected) +static void connected_dump_vty(struct vty *vty, json_object *json, + struct connected *connected) { struct prefix *p; + json_object *json_addr = NULL; + char buf[PREFIX2STR_BUFFER]; /* Print interface address. */ p = connected->address; - vty_out(vty, " %s ", prefix_family_str(p)); - prefix_vty_out(vty, p); - vty_out(vty, "/%d", p->prefixlen); + + if (json) { + json_addr = json_object_new_object(); + json_object_array_add(json, json_addr); + json_object_string_add(json_addr, "address", + prefix2str(p, buf, sizeof(buf))); + } else { + vty_out(vty, " %s %pFX", prefix_family_str(p), p); + } /* If there is destination address, print it. */ if (CONNECTED_PEER(connected) && connected->destination) { - vty_out(vty, " peer "); - prefix_vty_out(vty, connected->destination); - vty_out(vty, "/%d", connected->destination->prefixlen); + if (json) { + json_object_string_add( + json_addr, "peer", + prefix2str(connected->destination, buf, + sizeof(buf))); + } else { + vty_out(vty, " peer %pFX", connected->destination); + } } - if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY)) + if (json) + json_object_boolean_add( + json_addr, "secondary", + CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY)); + else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY)) vty_out(vty, " secondary"); - if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED)) + if (json) + json_object_boolean_add( + json_addr, "unnumbered", + CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED)); + else if (CHECK_FLAG(connected->flags, ZEBRA_IFA_UNNUMBERED)) vty_out(vty, " unnumbered"); - if (connected->label) - vty_out(vty, " %s", connected->label); + if (connected->label) { + if (json) + json_object_string_add(json_addr, "label", + connected->label); + else + vty_out(vty, " %s", connected->label); + } - vty_out(vty, "\n"); + if (!json) + vty_out(vty, "\n"); } /* Dump interface neighbor address information to vty. */ -static void nbr_connected_dump_vty(struct vty *vty, +static void nbr_connected_dump_vty(struct vty *vty, json_object *json, struct nbr_connected *connected) { struct prefix *p; + char buf[PREFIX2STR_BUFFER]; /* Print interface address. */ p = connected->address; - vty_out(vty, " %s ", prefix_family_str(p)); - prefix_vty_out(vty, p); - vty_out(vty, "/%d", p->prefixlen); - - vty_out(vty, "\n"); + if (json) + json_array_string_add(json, prefix2str(p, buf, sizeof(buf))); + else + vty_out(vty, " %s %pFX\n", prefix_family_str(p), p); } static const char *zebra_zifslavetype_2str(zebra_slave_iftype_t zif_slave_type) @@ -1413,6 +1431,43 @@ static void ifs_dump_brief_vty(struct vty *vty, struct vrf *vrf) vty_out(vty, "\n"); } +static void ifs_dump_brief_vty_json(json_object *json, struct vrf *vrf) +{ + struct connected *connected; + struct listnode *node; + struct interface *ifp; + + FOR_ALL_INTERFACES (vrf, ifp) { + json_object *json_if; + json_object *json_addrs; + + json_if = json_object_new_object(); + json_object_object_add(json, ifp->name, json_if); + + json_object_string_add(json_if, "status", + if_is_up(ifp) ? "up" : "down"); + json_object_string_add(json_if, "vrfName", vrf->name); + + json_addrs = json_object_new_array(); + json_object_object_add(json_if, "addresses", json_addrs); + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) + && !CHECK_FLAG(connected->flags, + ZEBRA_IFA_SECONDARY) + && !(connected->address->family == AF_INET6 + && IN6_IS_ADDR_LINKLOCAL( + &connected->address->u.prefix6))) { + char buf[PREFIX2STR_BUFFER]; + + json_array_string_add( + json_addrs, + prefix2str(connected->address, buf, + sizeof(buf))); + } + } + } +} + const char *zebra_protodown_rc_str(enum protodown_reasons protodown_rc, char *pd_buf, uint32_t pd_buf_len) { @@ -1483,7 +1538,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) vty_out(vty, " Link downs: %5u last: %s\n", zebra_if->down_count, zebra_if->down_last[0] ? zebra_if->down_last : "(never)"); - zebra_ptm_show_status(vty, ifp); + zebra_ptm_show_status(vty, NULL, ifp); vrf = vrf_lookup_by_id(ifp->vrf_id); vty_out(vty, " vrf: %s\n", vrf->name); @@ -1531,13 +1586,13 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, connected)) - connected_dump_vty(vty, connected); + connected_dump_vty(vty, NULL, connected); } for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) && (connected->address->family == AF_INET6)) - connected_dump_vty(vty, connected); + connected_dump_vty(vty, NULL, connected); } vty_out(vty, " Interface Type %s\n", @@ -1637,7 +1692,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) if (zebra_if->flags & ZIF_FLAG_LACP_BYPASS) vty_out(vty, " LACP bypass: on\n"); - zebra_evpn_if_es_print(vty, zebra_if); + zebra_evpn_if_es_print(vty, NULL, zebra_if); vty_out(vty, " protodown: %s %s\n", (zebra_if->flags & ZIF_FLAG_PROTODOWN) ? "on" : "off", if_is_protodown_applicable(ifp) ? "" : "(n/a)"); @@ -1716,7 +1771,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) if (listhead(ifp->nbr_connected)) vty_out(vty, " Neighbor address(s):\n"); for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, nbr_connected)) - nbr_connected_dump_vty(vty, nbr_connected); + nbr_connected_dump_vty(vty, NULL, nbr_connected); #ifdef HAVE_PROC_NET_DEV /* Statistics print out using proc file system. */ @@ -1774,6 +1829,382 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp) #endif /* HAVE_NET_RT_IFLIST */ } +static void if_dump_vty_json(struct vty *vty, struct interface *ifp, + json_object *json) +{ + struct connected *connected; + struct nbr_connected *nbr_connected; + struct listnode *node; + struct route_node *rn; + struct zebra_if *zebra_if; + struct vrf *vrf; + char pd_buf[ZEBRA_PROTODOWN_RC_STR_LEN]; + char buf[BUFSIZ]; + json_object *json_if; + json_object *json_addrs; + + json_if = json_object_new_object(); + json_object_object_add(json, ifp->name, json_if); + + if (if_is_up(ifp)) { + json_object_string_add(json_if, "administrativeStatus", "up"); + + if (CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)) { + json_object_string_add(json_if, "operationalStatus", + if_is_running(ifp) ? "up" + : "down"); + json_object_boolean_add(json_if, "linkDetection", true); + } else { + json_object_boolean_add(json_if, "linkDetection", + false); + } + } else { + json_object_string_add(json_if, "administrativeStatus", "down"); + } + + zebra_if = ifp->info; + + json_object_int_add(json_if, "linkUps", zebra_if->up_count); + json_object_int_add(json_if, "linkDowns", zebra_if->down_count); + if (zebra_if->up_last[0]) + json_object_string_add(json_if, "lastLinkUp", + zebra_if->up_last); + if (zebra_if->down_last[0]) + json_object_string_add(json_if, "lastLinkDown", + zebra_if->down_last); + + zebra_ptm_show_status(vty, json, ifp); + + vrf = vrf_lookup_by_id(ifp->vrf_id); + json_object_string_add(json_if, "vrfName", vrf->name); + + if (ifp->desc) + json_object_string_add(json_if, "description", ifp->desc); + if (zebra_if->desc) + json_object_string_add(json_if, "OsDescription", + zebra_if->desc); + + if (ifp->ifindex == IFINDEX_INTERNAL) { + json_object_boolean_add(json_if, "pseudoInterface", true); + return; + } else if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { + json_object_int_add(json_if, "index", ifp->ifindex); + return; + } + + json_object_boolean_add(json_if, "pseudoInterface", false); + json_object_int_add(json_if, "index", ifp->ifindex); + json_object_int_add(json_if, "metric", ifp->metric); + json_object_int_add(json_if, "mtu", ifp->mtu); + if (ifp->mtu6 != ifp->mtu) + json_object_int_add(json_if, "mtu6", ifp->mtu6); + json_object_int_add(json_if, "speed", ifp->speed); + json_object_string_add(json_if, "flags", if_flag_dump(ifp->flags)); + + /* Hardware address. */ + json_object_string_add(json_if, "type", if_link_type_str(ifp->ll_type)); + if (ifp->hw_addr_len != 0) { + char hwbuf[BUFSIZ]; + + hwbuf[0] = '\0'; + for (int i = 0; i < ifp->hw_addr_len; i++) { + snprintf(buf, sizeof(buf), "%s%02x", i == 0 ? "" : ":", + ifp->hw_addr[i]); + strlcat(hwbuf, buf, sizeof(hwbuf)); + } + json_object_string_add(json_if, "hardwareAddress", hwbuf); + } + + /* Bandwidth in Mbps */ + if (ifp->bandwidth != 0) + json_object_int_add(json_if, "bandwidth", ifp->bandwidth); + + + /* IP addresses. */ + json_addrs = json_object_new_array(); + json_object_object_add(json_if, "ipAddresses", json_addrs); + + for (rn = route_top(zebra_if->ipv4_subnets); rn; rn = route_next(rn)) { + if (!rn->info) + continue; + + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, + connected)) + connected_dump_vty(vty, json_addrs, connected); + } + + for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { + if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL) + && (connected->address->family == AF_INET6)) + connected_dump_vty(vty, json_addrs, connected); + } + + json_object_string_add(json_if, "interfaceType", + zebra_ziftype_2str(zebra_if->zif_type)); + json_object_string_add( + json_if, "interfaceSlaveType", + zebra_zifslavetype_2str(zebra_if->zif_slave_type)); + + if (IS_ZEBRA_IF_BRIDGE(ifp)) { + struct zebra_l2info_bridge *bridge_info; + + bridge_info = &zebra_if->l2info.br; + json_object_boolean_add(json_if, "bridgeVlanAware", + bridge_info->vlan_aware); + } else if (IS_ZEBRA_IF_VLAN(ifp)) { + struct zebra_l2info_vlan *vlan_info; + + vlan_info = &zebra_if->l2info.vl; + json_object_int_add(json_if, "vlanId", vlan_info->vid); + } else if (IS_ZEBRA_IF_VXLAN(ifp)) { + struct zebra_l2info_vxlan *vxlan_info; + + vxlan_info = &zebra_if->l2info.vxl; + json_object_int_add(json_if, "vxlanId", vxlan_info->vni); + if (vxlan_info->vtep_ip.s_addr != INADDR_ANY) + json_object_string_add(json_if, "vtepIp", + inet_ntop(AF_INET, + &vxlan_info->vtep_ip, + buf, sizeof(buf))); + if (vxlan_info->access_vlan) + json_object_int_add(json_if, "accessVlanId", + vxlan_info->access_vlan); + if (vxlan_info->mcast_grp.s_addr != INADDR_ANY) + json_object_string_add(json_if, "mcastGroup", + inet_ntop(AF_INET, + &vxlan_info->mcast_grp, + buf, sizeof(buf))); + if (vxlan_info->ifindex_link + && (vxlan_info->link_nsid != NS_UNKNOWN)) { + struct interface *ifp; + + ifp = if_lookup_by_index_per_ns( + zebra_ns_lookup(vxlan_info->link_nsid), + vxlan_info->ifindex_link); + json_object_string_add(json_if, "linkInterface", + ifp == NULL ? "Unknown" + : ifp->name); + } + } else if (IS_ZEBRA_IF_GRE(ifp)) { + struct zebra_l2info_gre *gre_info; + + gre_info = &zebra_if->l2info.gre; + if (gre_info->vtep_ip.s_addr != INADDR_ANY) { + json_object_string_add(json_if, "vtepIp", + inet_ntop(AF_INET, + &gre_info->vtep_ip, + buf, sizeof(buf))); + if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY) + json_object_string_add( + json_if, "vtepRemoteIp", + inet_ntop(AF_INET, + &gre_info->vtep_ip_remote, + buf, sizeof(buf))); + } + if (gre_info->ifindex_link + && (gre_info->link_nsid != NS_UNKNOWN)) { + struct interface *ifp; + + ifp = if_lookup_by_index_per_ns( + zebra_ns_lookup(gre_info->link_nsid), + gre_info->ifindex_link); + json_object_string_add(json_if, "linkInterface", + ifp == NULL ? "Unknown" + : ifp->name); + } + } + + if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) { + struct zebra_l2info_brslave *br_slave; + + br_slave = &zebra_if->brslave_info; + if (br_slave->bridge_ifindex != IFINDEX_INTERNAL) { + if (br_slave->br_if) + json_object_string_add(json_if, + "masterInterface", + br_slave->br_if->name); + else + json_object_int_add(json_if, "masterIfindex", + br_slave->bridge_ifindex); + } + } + + if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) { + struct zebra_l2info_bondslave *bond_slave; + + bond_slave = &zebra_if->bondslave_info; + if (bond_slave->bond_ifindex != IFINDEX_INTERNAL) { + if (bond_slave->bond_if) + json_object_string_add( + json_if, "masterInterface", + bond_slave->bond_if->name); + else + json_object_int_add(json_if, "masterIfindex", + bond_slave->bond_ifindex); + } + } + + json_object_boolean_add( + json_if, "lacpBypass", + CHECK_FLAG(zebra_if->flags, ZIF_FLAG_LACP_BYPASS)); + + zebra_evpn_if_es_print(vty, json_if, zebra_if); + + if (if_is_protodown_applicable(ifp)) { + json_object_string_add( + json_if, "protodown", + (zebra_if->flags & ZIF_FLAG_PROTODOWN) ? "on" : "off"); + if (zebra_if->protodown_rc) + json_object_string_add( + json_if, "protodownReason", + zebra_protodown_rc_str(zebra_if->protodown_rc, + pd_buf, sizeof(pd_buf))); + } + + if (zebra_if->link_ifindex != IFINDEX_INTERNAL) { + if (zebra_if->link) + json_object_string_add(json_if, "parentInterface", + zebra_if->link->name); + else + json_object_int_add(json_if, "parentIfindex", + zebra_if->link_ifindex); + } + + if (HAS_LINK_PARAMS(ifp)) { + struct if_link_params *iflp = ifp->link_params; + json_object *json_te; + + json_te = json_object_new_object(); + json_object_object_add( + json_if, "trafficEngineeringLinkParameters", json_te); + + if (IS_PARAM_SET(iflp, LP_TE_METRIC)) + json_object_int_add(json_te, "teMetric", + iflp->te_metric); + if (IS_PARAM_SET(iflp, LP_MAX_BW)) + json_object_double_add(json_te, "maximumBandwidth", + iflp->max_bw); + if (IS_PARAM_SET(iflp, LP_MAX_RSV_BW)) + json_object_double_add(json_te, + "maximumReservableBandwidth", + iflp->max_rsv_bw); + if (IS_PARAM_SET(iflp, LP_UNRSV_BW)) { + json_object *json_bws; + + json_bws = json_object_new_object(); + json_object_object_add(json_te, "unreservedBandwidth", + json_bws); + for (unsigned int i = 0; i < MAX_CLASS_TYPE; ++i) { + char buf_ct[64]; + + snprintf(buf_ct, sizeof(buf_ct), "classType%u", + i); + json_object_double_add(json_bws, buf_ct, + iflp->unrsv_bw[i]); + } + } + + if (IS_PARAM_SET(iflp, LP_ADM_GRP)) + json_object_int_add(json_te, "administrativeGroup", + iflp->admin_grp); + if (IS_PARAM_SET(iflp, LP_DELAY)) { + json_object_int_add(json_te, "linkDelayAverage", + iflp->av_delay); + if (IS_PARAM_SET(iflp, LP_MM_DELAY)) { + json_object_int_add(json_te, "linkDelayMinimum", + iflp->min_delay); + json_object_int_add(json_te, "linkDelayMaximum", + iflp->max_delay); + } + } + if (IS_PARAM_SET(iflp, LP_DELAY_VAR)) + json_object_int_add(json_te, "linkDelayVariation", + iflp->delay_var); + if (IS_PARAM_SET(iflp, LP_PKT_LOSS)) + json_object_double_add(json_te, "linkPacketLoss", + iflp->pkt_loss); + if (IS_PARAM_SET(iflp, LP_AVA_BW)) + json_object_double_add(json_te, "availableBandwidth", + iflp->ava_bw); + if (IS_PARAM_SET(iflp, LP_RES_BW)) + json_object_double_add(json_te, "residualBandwidth", + iflp->res_bw); + if (IS_PARAM_SET(iflp, LP_USE_BW)) + json_object_double_add(json_te, "utilizedBandwidth", + iflp->use_bw); + if (IS_PARAM_SET(iflp, LP_RMT_AS)) + json_object_string_add(json_te, "neighborAsbrIp", + inet_ntop(AF_INET, &iflp->rmt_ip, + buf, sizeof(buf))); + json_object_int_add(json_te, "neighborAsbrAs", iflp->rmt_as); + } + + if (listhead(ifp->nbr_connected)) { + json_object *json_nbr_addrs; + + json_nbr_addrs = json_object_new_array(); + json_object_object_add(json_if, "neighborIpAddresses", + json_nbr_addrs); + + for (ALL_LIST_ELEMENTS_RO(ifp->nbr_connected, node, + nbr_connected)) + nbr_connected_dump_vty(vty, json_nbr_addrs, + nbr_connected); + } + +#ifdef HAVE_PROC_NET_DEV + json_object_int_add(json_if, "inputPackets", stats.rx_packets); + json_object_int_add(json_if, "inputBytes", ifp->stats.rx_bytes); + json_object_int_add(json_if, "inputDropped", ifp->stats.rx_dropped); + json_object_int_add(json_if, "inputMulticastPackets", + ifp->stats.rx_multicast); + json_object_int_add(json_if, "inputErrors", ifp->stats.rx_errors); + json_object_int_add(json_if, "inputLengthErrors", + ifp->stats.rx_length_errors); + json_object_int_add(json_if, "inputOverrunErrors", + ifp->stats.rx_over_errors); + json_object_int_add(json_if, "inputCrcErrors", + ifp->stats.rx_crc_errors); + json_object_int_add(json_if, "inputFrameErrors", + ifp->stats.rx_frame_errors); + json_object_int_add(json_if, "inputFifoErrors", + ifp->stats.rx_fifo_errors); + json_object_int_add(json_if, "inputMissedErrors", + ifp->stats.rx_missed_errors); + json_object_int_add(json_if, "outputPackets", ifp->stats.tx_packets); + json_object_int_add(json_if, "outputBytes", ifp->stats.tx_bytes); + json_object_int_add(json_if, "outputDroppedPackets", + ifp->stats.tx_dropped); + json_object_int_add(json_if, "outputErrors", ifp->stats.tx_errors); + json_object_int_add(json_if, "outputAbortedErrors", + ifp->stats.tx_aborted_errors); + json_object_int_add(json_if, "outputCarrierErrors", + ifp->stats.tx_carrier_errors); + json_object_int_add(json_if, "outputFifoErrors", + ifp->stats.tx_fifo_errors); + json_object_int_add(json_if, "outputHeartbeatErrors", + ifp->stats.tx_heartbeat_errors); + json_object_int_add(json_if, "outputWindowErrors", + ifp->stats.tx_window_errors); + json_object_int_add(json_if, "collisions", ifp->stats.collisions); +#endif /* HAVE_PROC_NET_DEV */ + +#ifdef HAVE_NET_RT_IFLIST + json_object_int_add(json_if, "inputPackets", ifp->stats.ifi_ipackets); + json_object_int_add(json_if, "inputBytes", ifp->stats.ifi_ibytes); + json_object_int_add(json_if, "inputDropd", ifp->stats.ifi_iqdrops); + json_object_int_add(json_if, "inputMulticastPackets", + ifp->stats.ifi_imcasts); + json_object_int_add(json_if, "inputErrors", ifp->stats.ifi_ierrors); + json_object_int_add(json_if, "outputPackets", ifp->stats.ifi_opackets); + json_object_int_add(json_if, "outputBytes", ifp->stats.ifi_obytes); + json_object_int_add(json_if, "outputMulticastPackets", + ifp->stats.ifi_omcasts); + json_object_int_add(json_if, "outputErrors", ifp->stats.ifi_oerrors); + json_object_int_add(json_if, "collisions", ifp->stats.ifi_collisions); +#endif /* HAVE_NET_RT_IFLIST */ +} + static void interface_update_stats(void) { #ifdef HAVE_PROC_NET_DEV @@ -1800,31 +2231,52 @@ struct cmd_node interface_node = { #endif /* Show all interfaces to vty. */ DEFPY(show_interface, show_interface_cmd, - "show interface vrf NAME$vrf_name [brief$brief]", + "show interface vrf NAME$vrf_name [brief$brief] [json$uj]", SHOW_STR "Interface status and configuration\n" VRF_CMD_HELP_STR - "Interface status and configuration summary\n") + "Interface status and configuration summary\n" + JSON_STR) { struct vrf *vrf; struct interface *ifp; + json_object *json = NULL; interface_update_stats(); vrf = vrf_lookup_by_name(vrf_name); if (!vrf) { - vty_out(vty, "%% VRF %s not found\n", vrf_name); + if (uj) + vty_out(vty, "{}\n"); + else + vty_out(vty, "%% VRF %s not found\n", vrf_name); return CMD_WARNING; } + if (uj) + json = json_object_new_object(); + if (brief) { - ifs_dump_brief_vty(vty, vrf); + if (json) + ifs_dump_brief_vty_json(json, vrf); + else + ifs_dump_brief_vty(vty, vrf); } else { FOR_ALL_INTERFACES (vrf, ifp) { - if_dump_vty(vty, ifp); + if (json) + if_dump_vty_json(vty, ifp, json); + else + if_dump_vty(vty, ifp); } } + if (json) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + return CMD_SUCCESS; } @@ -1832,85 +2284,140 @@ DEFPY(show_interface, show_interface_cmd, /* Show all interfaces to vty. */ DEFPY (show_interface_vrf_all, show_interface_vrf_all_cmd, - "show interface [vrf all] [brief$brief]", + "show interface [vrf all] [brief$brief] [json$uj]", SHOW_STR "Interface status and configuration\n" VRF_ALL_CMD_HELP_STR - "Interface status and configuration summary\n") + "Interface status and configuration summary\n" + JSON_STR) { struct vrf *vrf; struct interface *ifp; + json_object *json = NULL; interface_update_stats(); + if (uj) + json = json_object_new_object(); + /* All interface print. */ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if (brief) { - ifs_dump_brief_vty(vty, vrf); + if (json) + ifs_dump_brief_vty_json(json, vrf); + else + ifs_dump_brief_vty(vty, vrf); } else { - FOR_ALL_INTERFACES (vrf, ifp) - if_dump_vty(vty, ifp); + FOR_ALL_INTERFACES (vrf, ifp) { + if (json) + if_dump_vty_json(vty, ifp, json); + else + if_dump_vty(vty, ifp); + } } } + if (json) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } + return CMD_SUCCESS; } /* Show specified interface to vty. */ -DEFUN (show_interface_name_vrf, +DEFPY (show_interface_name_vrf, show_interface_name_vrf_cmd, - "show interface IFNAME vrf NAME", + "show interface IFNAME$ifname vrf NAME$vrf_name [json$uj]", SHOW_STR "Interface status and configuration\n" "Interface name\n" - VRF_CMD_HELP_STR) + VRF_CMD_HELP_STR + JSON_STR) { - int idx_ifname = 2; - int idx_name = 4; struct interface *ifp; struct vrf *vrf; + json_object *json = NULL; interface_update_stats(); - vrf = vrf_lookup_by_name(argv[idx_name]->arg); + vrf = vrf_lookup_by_name(vrf_name); if (!vrf) { - vty_out(vty, "%% VRF %s not found\n", argv[idx_name]->arg); + if (uj) + vty_out(vty, "{}\n"); + else + vty_out(vty, "%% VRF %s not found\n", vrf_name); return CMD_WARNING; } - ifp = if_lookup_by_name_vrf(argv[idx_ifname]->arg, vrf); + ifp = if_lookup_by_name_vrf(ifname, vrf); if (ifp == NULL) { - vty_out(vty, "%% Can't find interface %s\n", - argv[idx_ifname]->arg); + if (uj) + vty_out(vty, "{}\n"); + else + vty_out(vty, "%% Can't find interface %s\n", ifname); return CMD_WARNING; } - if_dump_vty(vty, ifp); + + if (uj) + json = json_object_new_object(); + + if (json) + if_dump_vty_json(vty, ifp, json); + else + if_dump_vty(vty, ifp); + + if (json) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } return CMD_SUCCESS; } /* Show specified interface to vty. */ -DEFUN (show_interface_name_vrf_all, +DEFPY (show_interface_name_vrf_all, show_interface_name_vrf_all_cmd, - "show interface IFNAME [vrf all]", + "show interface IFNAME$ifname [vrf all] [json$uj]", SHOW_STR "Interface status and configuration\n" "Interface name\n" - VRF_ALL_CMD_HELP_STR) + VRF_ALL_CMD_HELP_STR + JSON_STR) { - int idx_ifname = 2; struct interface *ifp; + json_object *json = NULL; interface_update_stats(); - ifp = if_lookup_by_name_all_vrf(argv[idx_ifname]->arg); + ifp = if_lookup_by_name_all_vrf(ifname); if (ifp == NULL) { - vty_out(vty, "%% Can't find interface %s\n", - argv[idx_ifname]->arg); + if (uj) + vty_out(vty, "{}\n"); + else + vty_out(vty, "%% Can't find interface %s\n", ifname); return CMD_WARNING; } - if_dump_vty(vty, ifp); + + if (uj) + json = json_object_new_object(); + + if (json) + if_dump_vty_json(vty, ifp, json); + else + if_dump_vty(vty, ifp); + + if (json) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } return CMD_SUCCESS; } diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index 05947faf4..f44b19b78 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -2781,41 +2781,76 @@ bool zebra_evpn_is_if_es_capable(struct zebra_if *zif) return false; } -void zebra_evpn_if_es_print(struct vty *vty, struct zebra_if *zif) +void zebra_evpn_if_es_print(struct vty *vty, json_object *json, + struct zebra_if *zif) { char buf[ETHER_ADDR_STRLEN]; - char mh_buf[80]; - bool vty_print = false; char esi_buf[ESI_STR_LEN]; - mh_buf[0] = '\0'; - strlcat(mh_buf, " EVPN-MH:", sizeof(mh_buf)); - if (zif->es_info.lid || !is_zero_mac(&zif->es_info.sysmac)) { - vty_print = true; - snprintf( - mh_buf + strlen(mh_buf), - sizeof(mh_buf) - strlen(mh_buf), - " ES id %u ES sysmac %s", zif->es_info.lid, - prefix_mac2str(&zif->es_info.sysmac, buf, sizeof(buf))); - } else if (memcmp(&zif->es_info.esi, zero_esi, sizeof(*zero_esi))) { - vty_print = true; - snprintf(mh_buf + strnlen(mh_buf, sizeof(mh_buf)), - sizeof(mh_buf) - strnlen(mh_buf, sizeof(mh_buf)), - " ES id %s", - esi_to_str(&zif->es_info.esi, esi_buf, - sizeof(esi_buf))); - } - - if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK) { - vty_print = true; - if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP) - strlcat(mh_buf, " uplink (up)", sizeof(mh_buf)); - else - strlcat(mh_buf, " uplink (down)", sizeof(mh_buf)); - } + if (json) { + json_object *json_evpn; + + json_evpn = json_object_new_object(); + json_object_object_add(json, "evpnMh", json_evpn); - if (vty_print) - vty_out(vty, "%s\n", mh_buf); + if (zif->es_info.lid || !is_zero_mac(&zif->es_info.sysmac)) { + json_object_int_add(json_evpn, "esId", + zif->es_info.lid); + json_object_string_add( + json_evpn, "esSysmac", + prefix_mac2str(&zif->es_info.sysmac, buf, + sizeof(buf))); + } else if (memcmp(&zif->es_info.esi, zero_esi, + sizeof(*zero_esi))) { + json_object_string_add(json_evpn, "esId", + esi_to_str(&zif->es_info.esi, + esi_buf, + sizeof(esi_buf))); + } + + if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK) + json_object_string_add( + json_evpn, "uplink", + CHECK_FLAG(zif->flags, + ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP) + ? "up" + : "down"); + } else { + char mh_buf[80]; + bool vty_print = false; + + mh_buf[0] = '\0'; + strlcat(mh_buf, " EVPN-MH:", sizeof(mh_buf)); + if (zif->es_info.lid || !is_zero_mac(&zif->es_info.sysmac)) { + vty_print = true; + snprintf(mh_buf + strlen(mh_buf), + sizeof(mh_buf) - strlen(mh_buf), + " ES id %u ES sysmac %s", zif->es_info.lid, + prefix_mac2str(&zif->es_info.sysmac, buf, + sizeof(buf))); + } else if (memcmp(&zif->es_info.esi, zero_esi, + sizeof(*zero_esi))) { + vty_print = true; + snprintf(mh_buf + strnlen(mh_buf, sizeof(mh_buf)), + sizeof(mh_buf) + - strnlen(mh_buf, sizeof(mh_buf)), + " ES id %s", + esi_to_str(&zif->es_info.esi, esi_buf, + sizeof(esi_buf))); + } + + if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK) { + vty_print = true; + if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP) + strlcat(mh_buf, " uplink (up)", sizeof(mh_buf)); + else + strlcat(mh_buf, " uplink (down)", + sizeof(mh_buf)); + } + + if (vty_print) + vty_out(vty, "%s\n", mh_buf); + } } static void zebra_evpn_local_mac_oper_state_change(struct zebra_evpn_es *es) diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h index a828056f1..cba536ea8 100644 --- a/zebra/zebra_evpn_mh.h +++ b/zebra/zebra_evpn_mh.h @@ -346,7 +346,8 @@ extern int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp); extern void zebra_evpn_acc_vl_show(struct vty *vty, bool uj); extern void zebra_evpn_acc_vl_show_detail(struct vty *vty, bool uj); extern void zebra_evpn_acc_vl_show_vid(struct vty *vty, bool uj, vlanid_t vid); -extern void zebra_evpn_if_es_print(struct vty *vty, struct zebra_if *zif); +extern void zebra_evpn_if_es_print(struct vty *vty, json_object *json, + struct zebra_if *zif); extern void zebra_evpn_es_cleanup(void); extern int zebra_evpn_mh_mac_holdtime_update(struct vty *vty, uint32_t duration, bool set_default); diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 37d939905..7e9382518 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -1092,14 +1092,20 @@ static const char *zebra_ptm_get_status_str(int status) } } -void zebra_ptm_show_status(struct vty *vty, struct interface *ifp) +void zebra_ptm_show_status(struct vty *vty, json_object *json, + struct interface *ifp) { - vty_out(vty, " PTM status: "); - if (ifp->ptm_enable) { - vty_out(vty, "%s\n", zebra_ptm_get_status_str(ifp->ptm_status)); - } else { - vty_out(vty, "disabled\n"); - } + const char *status; + + if (ifp->ptm_enable) + status = zebra_ptm_get_status_str(ifp->ptm_status); + else + status = "disabled"; + + if (json) + json_object_string_add(json, "ptmStatus", status); + else + vty_out(vty, " PTM status: %s\n", status); } void zebra_ptm_send_status_req(void) @@ -1537,6 +1543,7 @@ int zebra_ptm_get_enable_state(void) } void zebra_ptm_show_status(struct vty *vty __attribute__((__unused__)), + json_object *json __attribute__((__unused__)), struct interface *ifp __attribute__((__unused__))) { /* NOTHING */ diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index e578a02a9..88c9bccb4 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -86,7 +86,8 @@ void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS); void zebra_ptm_bfd_dst_replay(ZAPI_HANDLER_ARGS); #endif /* HAVE_BFDD */ -void zebra_ptm_show_status(struct vty *vty, struct interface *ifp); +void zebra_ptm_show_status(struct vty *vty, json_object *json, + struct interface *ifp); void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); |