nhrpd: add json support to show nhrp vty commands

- add json support for show nhrp vty commands.
- support for 'show dmvpn [json]' format.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2020-02-18 14:29:05 +01:00
parent 0886f49ea9
commit 87b9e98203

View file

@ -12,6 +12,7 @@
#include "zclient.h" #include "zclient.h"
#include "stream.h" #include "stream.h"
#include "filter.h" #include "filter.h"
#include "json.h"
#include "nhrpd.h" #include "nhrpd.h"
#include "netlink.h" #include "netlink.h"
@ -594,6 +595,7 @@ struct info_ctx {
struct vty *vty; struct vty *vty;
afi_t afi; afi_t afi;
int count; int count;
struct json_object *json;
}; };
static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx) static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
@ -601,22 +603,60 @@ static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx)
struct info_ctx *ctx = pctx; struct info_ctx *ctx = pctx;
struct vty *vty = ctx->vty; struct vty *vty = ctx->vty;
char buf[2][SU_ADDRSTRLEN]; char buf[2][SU_ADDRSTRLEN];
struct json_object *json = NULL;
if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
return; return;
if (!ctx->count) {
if (!ctx->count && !ctx->json) {
vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s\n", "Iface", "Type", vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s\n", "Iface", "Type",
"Protocol", "NBMA", "Flags", "Identity"); "Protocol", "NBMA", "Flags", "Identity");
} }
ctx->count++; ctx->count++;
sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0]));
if (c->cur.peer)
sockunion2str(&c->cur.peer->vc->remote.nbma,
buf[1], sizeof(buf[1]));
else
snprintf(buf[1], sizeof(buf[1]), "-");
if (json) {
json = json_object_new_object();
json_object_string_add(json, "interface", c->ifp->name);
json_object_string_add(json, "type",
nhrp_cache_type_str[c->cur.type]);
json_object_string_add(json, "protocol", buf[0]);
json_object_string_add(json, "nbma", buf[1]);
if (c->used)
json_object_boolean_true_add(json, "used");
else
json_object_boolean_false_add(json, "used");
if (c->t_timeout)
json_object_boolean_true_add(json, "timeout");
else
json_object_boolean_false_add(json, "timeout");
if (c->t_auth)
json_object_boolean_true_add(json, "auth");
else
json_object_boolean_false_add(json, "auth");
if (c->cur.peer)
json_object_string_add(json, "identity",
c->cur.peer->vc->remote.id);
else
json_object_string_add(json, "identity", "-");
json_object_array_add(ctx->json, json);
return;
}
vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s\n", c->ifp->name, vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s\n", c->ifp->name,
nhrp_cache_type_str[c->cur.type], nhrp_cache_type_str[c->cur.type],
sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])), buf[0], buf[1],
c->cur.peer ? sockunion2str(&c->cur.peer->vc->remote.nbma,
buf[1], sizeof(buf[1]))
: "-",
c->used ? 'U' : ' ', c->t_timeout ? 'T' : ' ', c->used ? 'U' : ' ', c->t_timeout ? 'T' : ' ',
c->t_auth ? 'A' : ' ', c->t_auth ? 'A' : ' ',
c->cur.peer ? c->cur.peer->vc->remote.id : "-"); c->cur.peer ? c->cur.peer->vc->remote.id : "-");
@ -628,19 +668,35 @@ static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg,
struct info_ctx *ctx = pctx; struct info_ctx *ctx = pctx;
struct vty *vty = ctx->vty; struct vty *vty = ctx->vty;
char buf[2][SU_ADDRSTRLEN]; char buf[2][SU_ADDRSTRLEN];
struct json_object *json = NULL;
if (!ctx->count) { if (!ctx->count && !ctx->json) {
vty_out(vty, "%-8s %-24s %-16s %-16s\n", "Iface", "FQDN", vty_out(vty, "%-8s %-24s %-16s %-16s\n", "Iface", "FQDN",
"NBMA", "Protocol"); "NBMA", "Protocol");
} }
ctx->count++; ctx->count++;
if (reg && reg->peer)
sockunion2str(&reg->peer->vc->remote.nbma,
buf[0], sizeof(buf[0]));
else
snprintf(buf[0], sizeof(buf[0]), "-");
sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1],
sizeof(buf[1]));
if (ctx->json) {
json = json_object_new_object();
json_object_string_add(json, "interface", n->ifp->name);
json_object_string_add(json, "fqdn", n->nbma_fqdn);
json_object_string_add(json, "nbma", buf[0]);
json_object_string_add(json, "protocol", buf[1]);
json_object_array_add(ctx->json, json);
return;
}
vty_out(vty, "%-8s %-24s %-16s %-16s\n", n->ifp->name, n->nbma_fqdn, vty_out(vty, "%-8s %-24s %-16s %-16s\n", n->ifp->name, n->nbma_fqdn,
(reg && reg->peer) ? sockunion2str(&reg->peer->vc->remote.nbma, buf[0], buf[1]);
buf[0], sizeof(buf[0]))
: "-",
sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1],
sizeof(buf[1])));
} }
static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx) static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
@ -649,6 +705,7 @@ static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
struct nhrp_cache *c; struct nhrp_cache *c;
struct vty *vty = ctx->vty; struct vty *vty = ctx->vty;
char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN]; char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN];
struct json_object *json = NULL;
if (!ctx->count) { if (!ctx->count) {
vty_out(vty, "%-8s %-24s %-24s %s\n", "Type", "Prefix", "Via", vty_out(vty, "%-8s %-24s %-24s %s\n", "Type", "Prefix", "Via",
@ -657,20 +714,82 @@ static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx)
ctx->count++; ctx->count++;
c = s->cache; c = s->cache;
vty_out(ctx->vty, "%-8s %-24s %-24s %s\n", nhrp_cache_type_str[s->type], if (c)
prefix2str(s->p, buf1, sizeof(buf1)), sockunion2str(&c->remote_addr, buf2, sizeof(buf2));
c ? sockunion2str(&c->remote_addr, buf2, sizeof(buf2)) : "", prefix2str(s->p, buf1, sizeof(buf1));
if (ctx->json) {
json = json_object_new_object();
json_object_string_add(json, "type",
nhrp_cache_type_str[s->type]);
json_object_string_add(json, "prefix", buf1);
if (c)
json_object_string_add(json, "via", buf2);
if (c && c->cur.peer)
json_object_string_add(json, "identity",
c->cur.peer->vc->remote.id);
else
json_object_string_add(json, "identity", "");
json_object_array_add(ctx->json, json);
return;
}
vty_out(ctx->vty, "%-8s %-24s %-24s %s\n",
nhrp_cache_type_str[s->type],
buf1, buf2,
(c && c->cur.peer) ? c->cur.peer->vc->remote.id : ""); (c && c->cur.peer) ? c->cur.peer->vc->remote.id : "");
} }
static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
{ {
struct info_ctx *ctx = pctx; struct info_ctx *ctx = pctx;
char buf[SU_ADDRSTRLEN]; char buf[3][SU_ADDRSTRLEN];
struct json_object *json = NULL;
if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) if (ctx->afi != family2afi(sockunion_family(&c->remote_addr)))
return; return;
sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0]));
if (c->cur.peer)
sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1],
sizeof(buf[1]));
if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC)
sockunion2str(&c->cur.remote_nbma_natoa, buf[2],
sizeof(buf[2]));
if (ctx->json) {
json = json_object_new_object();
json_object_string_add(json, "type",
nhrp_cache_type_str[c->cur.type]);
if (c->cur.peer && c->cur.peer->online)
json_object_boolean_true_add(json, "up");
else
json_object_boolean_false_add(json, "up");
if (c->used)
json_object_boolean_true_add(json, "used");
else
json_object_boolean_false_add(json, "used");
json_object_string_add(json, "protocolAddress", buf[0]);
json_object_int_add(json, "protocolAddressSize",
8 * family2addrsize(sockunion_family
(&c->remote_addr)));
if (c->cur.peer)
json_object_string_add(json, "nbmaAddress", buf[1]);
if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC)
json_object_string_add(json, "nbmaNatOaAddress",
buf[2]);
json_object_array_add(ctx->json, json);
return;
}
vty_out(ctx->vty, vty_out(ctx->vty,
"Type: %s\n" "Type: %s\n"
"Flags:%s%s\n" "Flags:%s%s\n"
@ -678,40 +797,45 @@ static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx)
nhrp_cache_type_str[c->cur.type], nhrp_cache_type_str[c->cur.type],
(c->cur.peer && c->cur.peer->online) ? " up" : "", (c->cur.peer && c->cur.peer->online) ? " up" : "",
c->used ? " used" : "", c->used ? " used" : "",
sockunion2str(&c->remote_addr, buf, sizeof(buf)), buf[0],
8 * family2addrsize(sockunion_family(&c->remote_addr))); 8 * family2addrsize(sockunion_family(&c->remote_addr)));
if (c->cur.peer) { if (c->cur.peer)
vty_out(ctx->vty, "NBMA-Address: %s\n", vty_out(ctx->vty, "NBMA-Address: %s\n", buf[1]);
sockunion2str(&c->cur.peer->vc->remote.nbma, buf,
sizeof(buf)));
}
if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) { if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC)
vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n", vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n", buf[2]);
sockunion2str(&c->cur.remote_nbma_natoa, buf,
sizeof(buf)));
}
vty_out(ctx->vty, "\n\n"); vty_out(ctx->vty, "\n\n");
} }
DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
"show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp]", "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp] [json]",
SHOW_STR SHOW_STR
AFI_STR AFI_STR
"NHRP information\n" "NHRP information\n"
"Forwarding cache information\n" "Forwarding cache information\n"
"Next hop server information\n" "Next hop server information\n"
"Shortcut information\n" "Shortcut information\n"
"opennhrpctl style cache dump\n") "opennhrpctl style cache dump\n"
JSON_STR)
{ {
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp; struct interface *ifp;
struct info_ctx ctx = { struct info_ctx ctx = {
.vty = vty, .afi = cmd_to_afi(argv[1]), .vty = vty, .afi = cmd_to_afi(argv[1]), .json = NULL
}; };
bool uj = use_json(argc, argv);
struct json_object *json_path = NULL;
struct json_object *json_vrf = NULL, *json_vrf_path = NULL;
int ret = CMD_SUCCESS;
if (uj) {
json_vrf = json_object_new_object();
json_vrf_path = json_object_new_object();
json_path = json_object_new_array();
ctx.json = json_path;
}
if (argc <= 3 || argv[3]->text[0] == 'c') { if (argc <= 3 || argv[3]->text[0] == 'c') {
FOR_ALL_INTERFACES (vrf, ifp) FOR_ALL_INTERFACES (vrf, ifp)
nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx); nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx);
@ -721,42 +845,97 @@ DEFUN(show_ip_nhrp, show_ip_nhrp_cmd,
} else if (argv[3]->text[0] == 's') { } else if (argv[3]->text[0] == 's') {
nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx); nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx);
} else { } else {
vty_out(vty, "Status: ok\n\n"); if (!ctx.json)
vty_out(vty, "Status: ok\n\n");
else
json_object_string_add(json_vrf, "status", "ok");
ctx.count++; ctx.count++;
FOR_ALL_INTERFACES (vrf, ifp) FOR_ALL_INTERFACES (vrf, ifp)
nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx); nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx);
} }
if (uj)
json_object_int_add(json_vrf, "entriesCount", ctx.count);
if (!ctx.count) { if (!ctx.count) {
vty_out(vty, "%% No entries\n"); if (!ctx.json)
return CMD_WARNING; vty_out(vty, "%% No entries\n");
ret = CMD_WARNING;
} }
if (uj) {
return CMD_SUCCESS; json_object_object_add(json_vrf_path, "attr", json_vrf);
json_object_object_add(json_vrf_path, "table", ctx.json);
vty_out(vty, "%s",
json_object_to_json_string_ext(
json_vrf_path, JSON_C_TO_STRING_PRETTY));
json_object_free(json_vrf_path);
}
return ret;
} }
struct dmvpn_cfg {
struct vty *vty;
struct json_object *json;
};
static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx) static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx)
{ {
struct vty *vty = ctx; struct dmvpn_cfg *ctxt = ctx;
struct vty *vty;
char buf[2][SU_ADDRSTRLEN]; char buf[2][SU_ADDRSTRLEN];
struct json_object *json = NULL;
vty_out(vty, "%-24s %-24s %c %-4d %-24s\n", if (!ctxt || !ctxt->vty)
sockunion2str(&vc->local.nbma, buf[0], sizeof(buf[0])), return;
sockunion2str(&vc->remote.nbma, buf[1], sizeof(buf[1])), vty = ctxt->vty;
notifier_active(&vc->notifier_list) ? 'n' : ' ', vc->ipsec, sockunion2str(&vc->local.nbma, buf[0], sizeof(buf[0]));
vc->remote.id); sockunion2str(&vc->remote.nbma, buf[1], sizeof(buf[1]));
if (ctxt->json) {
json = json_object_new_object();
json_object_string_add(json, "src", buf[0]);
json_object_string_add(json, "dst", buf[1]);
if (notifier_active(&vc->notifier_list))
json_object_boolean_true_add(json, "notifierActive");
else
json_object_boolean_false_add(json, "notifierActive");
json_object_int_add(json, "sas", vc->ipsec);
json_object_string_add(json, "identity", vc->remote.id);
json_object_array_add(ctxt->json, json);
} else {
vty_out(vty, "%-24s %-24s %c %-4d %-24s\n",
buf[0], buf[1], notifier_active(&vc->notifier_list) ?
'n' : ' ', vc->ipsec, vc->remote.id);
}
} }
DEFUN(show_dmvpn, show_dmvpn_cmd, DEFUN(show_dmvpn, show_dmvpn_cmd,
"show dmvpn", "show dmvpn [json]",
SHOW_STR SHOW_STR
"DMVPN information\n") "DMVPN information\n"
JSON_STR)
{ {
vty_out(vty, "%-24s %-24s %-6s %-4s %-24s\n", "Src", "Dst", "Flags", bool uj = use_json(argc, argv);
"SAs", "Identity"); struct dmvpn_cfg ctxt;
struct json_object *json_path = NULL;
nhrp_vc_foreach(show_dmvpn_entry, vty);
ctxt.vty = vty;
if (!uj) {
ctxt.json = NULL;
vty_out(vty, "%-24s %-24s %-6s %-4s %-24s\n",
"Src", "Dst", "Flags", "SAs", "Identity");
} else {
json_path = json_object_new_array();
ctxt.json = json_path;
}
nhrp_vc_foreach(show_dmvpn_entry, &ctxt);
if (uj) {
vty_out(vty, "%s",
json_object_to_json_string_ext(
json_path, JSON_C_TO_STRING_PRETTY));
json_object_free(json_path);
}
return CMD_SUCCESS; return CMD_SUCCESS;
} }