From 010dd8edcb4e1fec3c252570efbf98ac1a02a34a Mon Sep 17 00:00:00 2001 From: Wesley Coakley Date: Wed, 20 May 2020 10:49:54 -0400 Subject: [PATCH] pbrd, lib: opt. json for `show pbr nexthop-group` Signed-off-by: Wesley Coakley --- doc/user/pbr.rst | 5 +++-- lib/nexthop_group.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ lib/nexthop_group.h | 3 +++ pbrd/pbr_nht.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ pbrd/pbr_nht.h | 2 ++ pbrd/pbr_vty.c | 22 +++++++++++++++--- 6 files changed, 135 insertions(+), 5 deletions(-) diff --git a/doc/user/pbr.rst b/doc/user/pbr.rst index b41a2ddacb..2815b040f2 100644 --- a/doc/user/pbr.rst +++ b/doc/user/pbr.rst @@ -56,10 +56,11 @@ listing of ECMP nexthops used to forward packets for when a pbr-map is matched. Showing Nexthop Group Information --------------------------------- -.. clicmd:: show pbr nexthop-groups [NAME] +.. clicmd:: show pbr nexthop-groups [NAME] [json] Display information on a PBR nexthop-group. If ``NAME`` is omitted, all - nexthop groups are shown. + nexthop groups are shown. Setting ``json`` will provide the same information + in a predictable and parsable format. .. _pbr-maps: diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index c23c57d2e1..f9e337d753 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -996,6 +996,60 @@ void nexthop_group_write_nexthop(struct vty *vty, struct nexthop *nh) vty_out(vty, "\n"); } +void nexthop_group_json_nexthop(json_object *j, struct nexthop *nh) +{ + char buf[100]; + struct vrf *vrf; + + switch (nh->type) { + case NEXTHOP_TYPE_IFINDEX: + json_object_string_add(j, "nexthop", + ifindex2ifname(nh->ifindex, nh->vrf_id)); + break; + case NEXTHOP_TYPE_IPV4: + json_object_string_add(j, "nexthop", inet_ntoa(nh->gate.ipv4)); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + json_object_string_add(j, "nexthop", inet_ntoa(nh->gate.ipv4)); + json_object_string_add(j, "vrfId", + ifindex2ifname(nh->ifindex, nh->vrf_id)); + break; + case NEXTHOP_TYPE_IPV6: + json_object_string_add( + j, "nexthop", + inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf))); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + json_object_string_add( + j, "nexthop", + inet_ntop(AF_INET6, &nh->gate.ipv6, buf, sizeof(buf))); + json_object_string_add(j, "vrfId", + ifindex2ifname(nh->ifindex, nh->vrf_id)); + break; + case NEXTHOP_TYPE_BLACKHOLE: + break; + } + + if (nh->vrf_id != VRF_DEFAULT) { + vrf = vrf_lookup_by_id(nh->vrf_id); + json_object_string_add(j, "nexthopVrf", vrf->name); + } + + if (nh->nh_label && nh->nh_label->num_labels > 0) { + char buf[200]; + + mpls_label2str(nh->nh_label->num_labels, nh->nh_label->label, + buf, sizeof(buf), 0); + json_object_string_add(j, "label", buf); + } + + if (nh->weight) + json_object_int_add(j, "weight", nh->weight); + + if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) + json_object_int_add(j, "backupIdx", nh->backup_idx); +} + static void nexthop_group_write_nexthop_internal(struct vty *vty, struct nexthop_hold *nh) { diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h index 3a5a1299c1..9888dad982 100644 --- a/lib/nexthop_group.h +++ b/lib/nexthop_group.h @@ -22,6 +22,7 @@ #define __NEXTHOP_GROUP__ #include +#include "json.h" #ifdef __cplusplus extern "C" { @@ -136,6 +137,8 @@ extern struct nexthop_group_cmd *nhgc_find(const char *name); extern void nexthop_group_write_nexthop(struct vty *vty, struct nexthop *nh); +extern void nexthop_group_json_nexthop(json_object *j, struct nexthop *nh); + /* Return the number of nexthops in this nhg */ extern uint8_t nexthop_group_nexthop_num(const struct nexthop_group *nhg); extern uint8_t diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index 2f3591ac8d..ae7a8017c2 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -1030,8 +1030,22 @@ static void pbr_nht_show_nhg_nexthops(struct hash_bucket *b, void *data) nexthop_group_write_nexthop(vty, pnhc->nexthop); } +static void pbr_nht_json_nhg_nexthops(struct hash_bucket *b, void *data) +{ + struct pbr_nexthop_cache *pnhc = b->data; + json_object *all_hops = data; + json_object *this_hop; + + this_hop = json_object_new_object(); + json_object_boolean_add(this_hop, "valid", pnhc->valid); + nexthop_group_json_nexthop(this_hop, pnhc->nexthop); + + json_object_array_add(all_hops, this_hop); +} + struct pbr_nht_show { struct vty *vty; + json_object *json; const char *name; }; @@ -1051,6 +1065,36 @@ static void pbr_nht_show_nhg(struct hash_bucket *b, void *data) hash_iterate(pnhgc->nhh, pbr_nht_show_nhg_nexthops, vty); } +static void pbr_nht_json_nhg(struct hash_bucket *b, void *data) +{ + struct pbr_nexthop_group_cache *pnhgc = b->data; + struct pbr_nht_show *pns = data; + json_object *j, *this_group, *group_hops; + + if (pns->name && strcmp(pns->name, pnhgc->name) != 0) + return; + + j = pns->json; + this_group = json_object_new_object(); + + if (!j || !this_group) + return; + + json_object_string_add(this_group, "name", pnhgc->name); + json_object_int_add(this_group, "id", pnhgc->table_id); + json_object_boolean_add(this_group, "valid", pnhgc->valid); + json_object_boolean_add(this_group, "installed", pnhgc->installed); + + group_hops = json_object_new_array(); + + if (group_hops) { + hash_iterate(pnhgc->nhh, pbr_nht_json_nhg_nexthops, group_hops); + json_object_object_add(this_group, "nexthops", group_hops); + } + + json_object_object_add(j, pnhgc->name, this_group); +} + void pbr_nht_show_nexthop_group(struct vty *vty, const char *name) { struct pbr_nht_show pns; @@ -1061,6 +1105,16 @@ void pbr_nht_show_nexthop_group(struct vty *vty, const char *name) hash_iterate(pbr_nhg_hash, pbr_nht_show_nhg, &pns); } +void pbr_nht_json_nexthop_group(json_object *j, const char *name) +{ + struct pbr_nht_show pns; + + pns.name = name; + pns.json = j; + + hash_iterate(pbr_nhg_hash, pbr_nht_json_nhg, &pns); +} + void pbr_nht_init(void) { pbr_nhg_hash = hash_create_size( diff --git a/pbrd/pbr_nht.h b/pbrd/pbr_nht.h index 2533942547..cbcf71d2f5 100644 --- a/pbrd/pbr_nht.h +++ b/pbrd/pbr_nht.h @@ -24,6 +24,7 @@ #include #include "pbr_map.h" +#include "json.h" #define PBR_NHC_NAMELEN PBR_MAP_NAMELEN + 10 @@ -112,6 +113,7 @@ extern char *pbr_nht_nexthop_make_name(char *name, size_t l, uint32_t seqno, char *buffer); extern void pbr_nht_show_nexthop_group(struct vty *vty, const char *name); +extern void pbr_nht_json_nexthop_group(json_object *j, const char *name); /* * When we get a callback from zebra about a nexthop changing diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 61882eb75b..f94a4d43b0 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -733,13 +733,29 @@ DEFPY (show_pbr_map, DEFPY(show_pbr_nexthop_group, show_pbr_nexthop_group_cmd, - "show pbr nexthop-groups [WORD$word]", + "show pbr nexthop-groups [WORD$word] [json$json]", SHOW_STR PBR_STR "Nexthop Groups\n" - "Optional Name of the nexthop group\n") + "Optional Name of the nexthop group\n" + JSON_STR) { - pbr_nht_show_nexthop_group(vty, word); + json_object *j = NULL; + + if (json) + j = json_object_new_object(); + + if (j) { + pbr_nht_json_nexthop_group(j, word); + + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + j, JSON_C_TO_STRING_PRETTY)); + + json_object_free(j); + } else + pbr_nht_show_nexthop_group(vty, word); + return CMD_SUCCESS; } -- 2.39.5