summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2021-08-02 20:38:26 +0200
committerRenato Westphal <renato@opensourcerouting.org>2021-08-02 22:19:45 +0200
commitc15dc24f79c97c670dd2114621ae9f6236b13348 (patch)
tree43462ba34fdbadbaf0a214cf8d45dcab68844ac2 /zebra
parentlib: add "json" option to "show route-map" (diff)
downloadfrr-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.c631
-rw-r--r--zebra/zebra_evpn_mh.c95
-rw-r--r--zebra/zebra_evpn_mh.h3
-rw-r--r--zebra/zebra_ptm.c21
-rw-r--r--zebra/zebra_ptm.h3
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);