zebra: add "json" option to "show interface"

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2021-08-02 15:38:26 -03:00
parent 856ed18ae9
commit c15dc24f79
6 changed files with 657 additions and 100 deletions

View File

@ -1139,6 +1139,10 @@ zebra Terminal Mode Commands
Display detailed information about a route. If [nexthop-group] is
included, it will display the nexthop group ID the route is using as well.
.. clicmd:: show interface [NAME] [{vrf VRF|brief}] [json]
.. clicmd:: show interface [NAME] [{vrf all|brief}] [json]
.. clicmd:: show interface [NAME] [{vrf VRF|brief}] [nexthop-group]
.. clicmd:: show interface [NAME] [{vrf all|brief}] [nexthop-group]
@ -1148,6 +1152,8 @@ zebra Terminal Mode Commands
detailed information about that single interface. If [nexthop-group] is
specified, it will display nexthop groups pointing out that interface.
If the ``json`` option is specified, output is displayed in JSON format.
.. clicmd:: show ip prefix-list [NAME]
.. clicmd:: show route-map [NAME]

View File

@ -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;
}

View File

@ -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 (json) {
json_object *json_evpn;
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));
}
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)

View File

@ -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);

View File

@ -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 */

View File

@ -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);