Merge pull request #7402 from ranjanyash54/dev_2

ospf6d: Json support added for command "show ipv6 ospf6 route [json]"
This commit is contained in:
Donald Sharp 2021-02-01 21:07:57 -05:00 committed by GitHub
commit d512cb376a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 366 additions and 102 deletions

View File

@ -240,6 +240,28 @@ Showing OSPF6 information
Shows the routes which are redistributed by the router. JSON output can Shows the routes which are redistributed by the router. JSON output can
be obtained by appending 'json' at the end. be obtained by appending 'json' at the end.
.. index:: show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]
.. clicmd:: show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]
This command displays the ospfv3 routing table as determined by the most
recent SPF calculations. Options are provided to view the different types
of routes. Other than the standard view there are two other options, detail
and summary. JSON output can be obtained by appending 'json' to the end of
command.
.. index:: show ipv6 ospf6 route X:X::X:X/M match [detail] [json]
.. clicmd:: show ipv6 ospf6 route X:X::X:X/M match [detail] [json]
The additional match option will match the given address to the destination
of the routes, and return the result accordingly.
.. index:: show ipv6 ospf6 interface [IFNAME] prefix [detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]] [json]
.. clicmd:: show ipv6 ospf6 interface [IFNAME] prefix [detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]] [json]
This command shows the prefixes present in the interface routing table.
Interface name can also be given. JSON output can be obtained by appending
'json' to the end of command.
OSPF6 Configuration Examples OSPF6 Configuration Examples
============================ ============================

View File

@ -1416,7 +1416,7 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
[<\ [<\
detail\ detail\
|<X:X::X:X|X:X::X:X/M> [<match|detail>]\ |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
>]", >] [json]",
SHOW_STR SHOW_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
@ -1427,12 +1427,14 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
OSPF6_ROUTE_ADDRESS_STR OSPF6_ROUTE_ADDRESS_STR
OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_PREFIX_STR
OSPF6_ROUTE_MATCH_STR OSPF6_ROUTE_MATCH_STR
"Display details of the prefixes\n") "Display details of the prefixes\n"
JSON_STR)
{ {
int idx_ifname = 4; int idx_ifname = 4;
int idx_prefix = 6; int idx_prefix = 6;
struct interface *ifp; struct interface *ifp;
struct ospf6_interface *oi; struct ospf6_interface *oi;
bool uj = use_json(argc, argv);
ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT);
if (ifp == NULL) { if (ifp == NULL) {
@ -1447,8 +1449,8 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
return CMD_WARNING; return CMD_WARNING;
} }
ospf6_route_table_show(vty, idx_prefix, argc, argv, ospf6_route_table_show(vty, idx_prefix, argc, argv, oi->route_connected,
oi->route_connected); uj);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -1459,7 +1461,7 @@ DEFUN (show_ipv6_ospf6_interface_prefix,
[<\ [<\
detail\ detail\
|<X:X::X:X|X:X::X:X/M> [<match|detail>]\ |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
>]", >] [json]",
SHOW_STR SHOW_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
@ -1469,12 +1471,14 @@ DEFUN (show_ipv6_ospf6_interface_prefix,
OSPF6_ROUTE_ADDRESS_STR OSPF6_ROUTE_ADDRESS_STR
OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_PREFIX_STR
OSPF6_ROUTE_MATCH_STR OSPF6_ROUTE_MATCH_STR
"Display details of the prefixes\n") "Display details of the prefixes\n"
JSON_STR)
{ {
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
int idx_prefix = 5; int idx_prefix = 5;
struct ospf6_interface *oi; struct ospf6_interface *oi;
struct interface *ifp; struct interface *ifp;
bool uj = use_json(argc, argv);
FOR_ALL_INTERFACES (vrf, ifp) { FOR_ALL_INTERFACES (vrf, ifp) {
oi = (struct ospf6_interface *)ifp->info; oi = (struct ospf6_interface *)ifp->info;
@ -1482,7 +1486,7 @@ DEFUN (show_ipv6_ospf6_interface_prefix,
continue; continue;
ospf6_route_table_show(vty, idx_prefix, argc, argv, ospf6_route_table_show(vty, idx_prefix, argc, argv,
oi->route_connected); oi->route_connected, uj);
} }
return CMD_SUCCESS; return CMD_SUCCESS;

View File

@ -163,6 +163,10 @@ const char *const ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] = {
"??", "IA", "IE", "E1", "E2", "??", "IA", "IE", "E1", "E2",
}; };
const char *ospf6_path_type_json[OSPF6_PATH_TYPE_MAX] = {
"UnknownRoute", "IntraArea", "InterArea", "External1", "External2",
};
struct ospf6_nexthop *ospf6_nexthop_create(void) struct ospf6_nexthop *ospf6_nexthop_create(void)
{ {
@ -1030,7 +1034,8 @@ void ospf6_route_table_delete(struct ospf6_route_table *table)
/* VTY commands */ /* VTY commands */
void ospf6_route_show(struct vty *vty, struct ospf6_route *route) void ospf6_route_show(struct vty *vty, struct ospf6_route *route,
json_object *json_array_routes, bool use_json)
{ {
int i; int i;
char destination[PREFIX2STR_BUFFER], nexthop[64]; char destination[PREFIX2STR_BUFFER], nexthop[64];
@ -1038,6 +1043,9 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route)
struct timeval now, res; struct timeval now, res;
struct listnode *node; struct listnode *node;
struct ospf6_nexthop *nh; struct ospf6_nexthop *nh;
json_object *json_route = NULL;
json_object *json_array_next_hops = NULL;
json_object *json_next_hop;
if (om6->ospf6 == NULL) { if (om6->ospf6 == NULL) {
vty_out(vty, "OSPFv3 is not running\n"); vty_out(vty, "OSPFv3 is not running\n");
@ -1058,34 +1066,74 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route)
else else
prefix2str(&route->prefix, destination, sizeof(destination)); prefix2str(&route->prefix, destination, sizeof(destination));
i = 0; if (use_json) {
json_route = json_object_new_object();
json_object_string_add(json_route, "destination", destination);
json_object_boolean_add(json_route, "isBestRoute",
ospf6_route_is_best(route));
json_object_string_add(json_route, "destinationType",
OSPF6_DEST_TYPE_SUBSTR(route->type));
json_object_string_add(
json_route, "pathType",
OSPF6_PATH_TYPE_SUBSTR(route->path.type));
json_object_string_add(json_route, "duration", duration);
}
/* Nexthops */
if (use_json)
json_array_next_hops = json_object_new_array();
else
i = 0;
for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) { for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) {
struct interface *ifp; struct interface *ifp;
/* nexthop */ /* nexthop */
inet_ntop(AF_INET6, &nh->address, nexthop, sizeof(nexthop)); inet_ntop(AF_INET6, &nh->address, nexthop, sizeof(nexthop));
ifp = if_lookup_by_index_all_vrf(nh->ifindex); ifp = if_lookup_by_index_all_vrf(nh->ifindex);
if (!i) { if (use_json) {
vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s\n", json_next_hop = json_object_new_object();
(ospf6_route_is_best(route) ? '*' : ' '), json_object_string_add(json_next_hop, "nextHop",
OSPF6_DEST_TYPE_SUBSTR(route->type), nexthop);
OSPF6_PATH_TYPE_SUBSTR(route->path.type), json_object_string_add(json_next_hop, "interfaceName",
destination, nexthop, IFNAMSIZ, ifp->name, ifp->name);
duration); json_object_array_add(json_array_next_hops,
i++; json_next_hop);
} else } else {
vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s\n", ' ', if (!i) {
"", "", "", nexthop, IFNAMSIZ, ifp->name, ""); vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s\n",
(ospf6_route_is_best(route) ? '*'
: ' '),
OSPF6_DEST_TYPE_SUBSTR(route->type),
OSPF6_PATH_TYPE_SUBSTR(
route->path.type),
destination, nexthop, IFNAMSIZ,
ifp->name, duration);
i++;
} else
vty_out(vty, "%c%1s %2s %-30s %-25s %6.*s %s\n",
' ', "", "", "", nexthop, IFNAMSIZ,
ifp->name, "");
}
}
if (use_json) {
json_object_object_add(json_route, "nextHops",
json_array_next_hops);
json_object_array_add(json_array_routes, json_route);
} }
} }
void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route) void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
json_object *json_array_routes, bool use_json)
{ {
char destination[PREFIX2STR_BUFFER]; char destination[PREFIX2STR_BUFFER], nexthop[64];
char area_id[16], id[16], adv_router[16], capa[16], options[16]; char area_id[16], id[16], adv_router[16], capa[16], options[16];
struct timeval now, res; struct timeval now, res;
char duration[64]; char duration[64];
struct listnode *node; struct listnode *node;
struct ospf6_nexthop *nh; struct ospf6_nexthop *nh;
char flag[6];
json_object *json_route = NULL;
json_object *json_array_next_hops = NULL;
json_object *json_next_hop;
if (om6->ospf6 == NULL) { if (om6->ospf6 == NULL) {
vty_out(vty, "OSPFv3 is not running\n"); vty_out(vty, "OSPFv3 is not running\n");
@ -1103,84 +1151,177 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route)
destination, sizeof(destination)); destination, sizeof(destination));
else else
prefix2str(&route->prefix, destination, sizeof(destination)); prefix2str(&route->prefix, destination, sizeof(destination));
vty_out(vty, "Destination: %s\n", destination);
/* destination type */ if (use_json) {
vty_out(vty, "Destination type: %s\n", json_route = json_object_new_object();
OSPF6_DEST_TYPE_NAME(route->type)); json_object_string_add(json_route, "destination", destination);
json_object_string_add(json_route, "destinationType",
OSPF6_DEST_TYPE_NAME(route->type));
} else {
vty_out(vty, "Destination: %s\n", destination);
vty_out(vty, "Destination type: %s\n",
OSPF6_DEST_TYPE_NAME(route->type));
}
/* Time */ /* Time */
timersub(&now, &route->installed, &res); timersub(&now, &route->installed, &res);
timerstring(&res, duration, sizeof(duration)); timerstring(&res, duration, sizeof(duration));
vty_out(vty, "Installed Time: %s ago\n", duration); if (use_json)
json_object_string_add(json_route, "installedTimeSince",
duration);
else
vty_out(vty, "Installed Time: %s ago\n", duration);
timersub(&now, &route->changed, &res); timersub(&now, &route->changed, &res);
timerstring(&res, duration, sizeof(duration)); timerstring(&res, duration, sizeof(duration));
vty_out(vty, " Changed Time: %s ago\n", duration); if (use_json)
json_object_string_add(json_route, "changedTimeSince",
duration);
else
vty_out(vty, "Changed Time: %s ago\n", duration);
/* Debugging info */ /* Debugging info */
vty_out(vty, "Lock: %d Flags: %s%s%s%s\n", route->lock, if (use_json) {
(CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"), json_object_int_add(json_route, "numberOfLock", route->lock);
(CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"), snprintf(
(CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"), flag, sizeof(flag), "%s%s%s%s",
(CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-")); (CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
vty_out(vty, "Memory: prev: %p this: %p next: %p\n", (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
(void *)route->prev, (void *)route, (void *)route->next); (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE) ? "R"
: "-"),
(CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE) ? "C"
: "-"));
json_object_string_add(json_route, "flags", flag);
} else {
vty_out(vty, "Lock: %d Flags: %s%s%s%s\n", route->lock,
(CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
(CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
(CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE) ? "R"
: "-"),
(CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE) ? "C"
: "-"));
vty_out(vty, "Memory: prev: %p this: %p next: %p\n",
(void *)route->prev, (void *)route,
(void *)route->next);
}
/* Path section */ /* Path section */
/* Area-ID */ /* Area-ID */
inet_ntop(AF_INET, &route->path.area_id, area_id, sizeof(area_id)); inet_ntop(AF_INET, &route->path.area_id, area_id, sizeof(area_id));
vty_out(vty, "Associated Area: %s\n", area_id); if (use_json)
json_object_string_add(json_route, "associatedArea", area_id);
else
vty_out(vty, "Associated Area: %s\n", area_id);
/* Path type */ /* Path type */
vty_out(vty, "Path Type: %s\n", OSPF6_PATH_TYPE_NAME(route->path.type)); if (use_json)
json_object_string_add(json_route, "pathType",
OSPF6_PATH_TYPE_NAME(route->path.type));
else
vty_out(vty, "Path Type: %s\n",
OSPF6_PATH_TYPE_NAME(route->path.type));
/* LS Origin */ /* LS Origin */
inet_ntop(AF_INET, &route->path.origin.id, id, sizeof(id)); inet_ntop(AF_INET, &route->path.origin.id, id, sizeof(id));
inet_ntop(AF_INET, &route->path.origin.adv_router, adv_router, inet_ntop(AF_INET, &route->path.origin.adv_router, adv_router,
sizeof(adv_router)); sizeof(adv_router));
vty_out(vty, "LS Origin: %s Id: %s Adv: %s\n", if (use_json) {
ospf6_lstype_name(route->path.origin.type), id, adv_router); json_object_string_add(
json_route, "lsOriginRoutePathType",
ospf6_lstype_name(route->path.origin.type));
json_object_string_add(json_route, "lsId", id);
json_object_string_add(json_route, "lsAdvertisingRouter",
adv_router);
} else {
vty_out(vty, "LS Origin: %s Id: %s Adv: %s\n",
ospf6_lstype_name(route->path.origin.type), id,
adv_router);
}
/* Options */ /* Options */
ospf6_options_printbuf(route->path.options, options, sizeof(options)); ospf6_options_printbuf(route->path.options, options, sizeof(options));
vty_out(vty, "Options: %s\n", options); if (use_json)
json_object_string_add(json_route, "options", options);
else
vty_out(vty, "Options: %s\n", options);
/* Router Bits */ /* Router Bits */
ospf6_capability_printbuf(route->path.router_bits, capa, sizeof(capa)); ospf6_capability_printbuf(route->path.router_bits, capa, sizeof(capa));
vty_out(vty, "Router Bits: %s\n", capa); if (use_json)
json_object_string_add(json_route, "routerBits", capa);
else
vty_out(vty, "Router Bits: %s\n", capa);
/* Prefix Options */ /* Prefix Options */
vty_out(vty, "Prefix Options: xxx\n"); if (use_json)
json_object_string_add(json_route, "prefixOptions", "xxx");
else
vty_out(vty, "Prefix Options: xxx\n");
/* Metrics */ /* Metrics */
vty_out(vty, "Metric Type: %d\n", route->path.metric_type); if (use_json) {
vty_out(vty, "Metric: %d (%d)\n", route->path.cost, json_object_int_add(json_route, "metricType",
route->path.u.cost_e2); route->path.metric_type);
json_object_int_add(json_route, "metricCost", route->path.cost);
json_object_int_add(json_route, "metricCostE2",
route->path.u.cost_e2);
json_object_int_add(json_route, "pathsCount",
route->paths->count);
json_object_int_add(json_route, "nextHopCount",
route->nh_list->count);
} else {
vty_out(vty, "Metric Type: %d\n", route->path.metric_type);
vty_out(vty, "Metric: %d (%d)\n", route->path.cost,
route->path.u.cost_e2);
vty_out(vty, "Paths count: %u\n", route->paths->count);
vty_out(vty, "Nexthop count: %u\n", route->nh_list->count);
}
vty_out(vty, "Paths count: %u\n", route->paths->count);
vty_out(vty, "Nexthop count: %u\n", route->nh_list->count);
/* Nexthops */ /* Nexthops */
vty_out(vty, "Nexthop:\n"); if (use_json)
json_array_next_hops = json_object_new_array();
else
vty_out(vty, "Nexthop:\n");
for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) { for (ALL_LIST_ELEMENTS_RO(route->nh_list, node, nh)) {
struct interface *ifp; struct interface *ifp;
/* nexthop */
ifp = if_lookup_by_index_all_vrf(nh->ifindex); ifp = if_lookup_by_index_all_vrf(nh->ifindex);
vty_out(vty, " %pI6 %.*s\n", &nh->address, IFNAMSIZ, ifp->name); /* nexthop */
if (use_json) {
inet_ntop(AF_INET6, &nh->address, nexthop,
sizeof(nexthop));
json_next_hop = json_object_new_object();
json_object_string_add(json_next_hop, "nextHop",
nexthop);
json_object_string_add(json_next_hop, "interfaceName",
ifp->name);
json_object_array_add(json_array_next_hops,
json_next_hop);
} else
vty_out(vty, " %pI6 %.*s\n", &nh->address, IFNAMSIZ,
ifp->name);
} }
vty_out(vty, "\n"); if (use_json) {
json_object_object_add(json_route, "nextHops",
json_array_next_hops);
json_object_array_add(json_array_routes, json_route);
} else
vty_out(vty, "\n");
} }
static void ospf6_route_show_table_summary(struct vty *vty, static void ospf6_route_show_table_summary(struct vty *vty,
struct ospf6_route_table *table) struct ospf6_route_table *table,
json_object *json, bool use_json)
{ {
struct ospf6_route *route, *prev = NULL; struct ospf6_route *route, *prev = NULL;
int i, pathtype[OSPF6_PATH_TYPE_MAX]; int i, pathtype[OSPF6_PATH_TYPE_MAX];
unsigned int number = 0; unsigned int number = 0;
int nh_count = 0, nhinval = 0, ecmp = 0; int nh_count = 0, nhinval = 0, ecmp = 0;
int alternative = 0, destination = 0; int alternative = 0, destination = 0;
char path_str[30];
for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++) for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
pathtype[i] = 0; pathtype[i] = 0;
@ -1203,111 +1344,164 @@ static void ospf6_route_show_table_summary(struct vty *vty,
} }
assert(number == table->count); assert(number == table->count);
if (use_json) {
vty_out(vty, "Number of OSPFv3 routes: %d\n", number); json_object_int_add(json, "numberOfOspfv3Routes", number);
vty_out(vty, "Number of Destination: %d\n", destination); json_object_int_add(json, "numberOfDestination", destination);
vty_out(vty, "Number of Alternative routes: %d\n", alternative); json_object_int_add(json, "numberOfAlternativeRoutes",
vty_out(vty, "Number of Equal Cost Multi Path: %d\n", ecmp); alternative);
json_object_int_add(json, "numberOfEcmp", ecmp);
} else {
vty_out(vty, "Number of OSPFv3 routes: %d\n", number);
vty_out(vty, "Number of Destination: %d\n", destination);
vty_out(vty, "Number of Alternative routes: %d\n", alternative);
vty_out(vty, "Number of Equal Cost Multi Path: %d\n", ecmp);
}
for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++) { for (i = OSPF6_PATH_TYPE_INTRA; i <= OSPF6_PATH_TYPE_EXTERNAL2; i++) {
vty_out(vty, "Number of %s routes: %d\n", if (use_json) {
OSPF6_PATH_TYPE_NAME(i), pathtype[i]); snprintf(path_str, sizeof(path_str), "numberOf%sRoutes",
OSPF6_PATH_TYPE_JSON(i));
json_object_int_add(json, path_str, pathtype[i]);
} else
vty_out(vty, "Number of %s routes: %d\n",
OSPF6_PATH_TYPE_NAME(i), pathtype[i]);
} }
} }
static void ospf6_route_show_table_prefix(struct vty *vty, static void ospf6_route_show_table_prefix(struct vty *vty,
struct prefix *prefix, struct prefix *prefix,
struct ospf6_route_table *table) struct ospf6_route_table *table,
json_object *json, bool use_json)
{ {
struct ospf6_route *route; struct ospf6_route *route;
json_object *json_array_routes = NULL;
route = ospf6_route_lookup(prefix, table); route = ospf6_route_lookup(prefix, table);
if (route == NULL) if (route == NULL)
return; return;
if (use_json)
json_array_routes = json_object_new_array();
ospf6_route_lock(route); ospf6_route_lock(route);
while (route && ospf6_route_is_prefix(prefix, route)) { while (route && ospf6_route_is_prefix(prefix, route)) {
/* Specifying a prefix will always display details */ /* Specifying a prefix will always display details */
ospf6_route_show_detail(vty, route); ospf6_route_show_detail(vty, route, json_array_routes,
use_json);
route = ospf6_route_next(route); route = ospf6_route_next(route);
} }
if (use_json)
json_object_object_add(json, "routes", json_array_routes);
if (route) if (route)
ospf6_route_unlock(route); ospf6_route_unlock(route);
} }
static void ospf6_route_show_table_address(struct vty *vty, static void ospf6_route_show_table_address(struct vty *vty,
struct prefix *prefix, struct prefix *prefix,
struct ospf6_route_table *table) struct ospf6_route_table *table,
json_object *json, bool use_json)
{ {
struct ospf6_route *route; struct ospf6_route *route;
json_object *json_array_routes = NULL;
route = ospf6_route_lookup_bestmatch(prefix, table); route = ospf6_route_lookup_bestmatch(prefix, table);
if (route == NULL) if (route == NULL)
return; return;
if (use_json)
json_array_routes = json_object_new_array();
prefix = &route->prefix; prefix = &route->prefix;
ospf6_route_lock(route); ospf6_route_lock(route);
while (route && ospf6_route_is_prefix(prefix, route)) { while (route && ospf6_route_is_prefix(prefix, route)) {
/* Specifying a prefix will always display details */ /* Specifying a prefix will always display details */
ospf6_route_show_detail(vty, route); ospf6_route_show_detail(vty, route, json_array_routes,
use_json);
route = ospf6_route_next(route); route = ospf6_route_next(route);
} }
if (use_json)
json_object_object_add(json, "routes", json_array_routes);
if (route) if (route)
ospf6_route_unlock(route); ospf6_route_unlock(route);
} }
static void ospf6_route_show_table_match(struct vty *vty, int detail, static void ospf6_route_show_table_match(struct vty *vty, int detail,
struct prefix *prefix, struct prefix *prefix,
struct ospf6_route_table *table) struct ospf6_route_table *table,
json_object *json, bool use_json)
{ {
struct ospf6_route *route; struct ospf6_route *route;
json_object *json_array_routes = NULL;
assert(prefix->family); assert(prefix->family);
route = ospf6_route_match_head(prefix, table); route = ospf6_route_match_head(prefix, table);
if (use_json)
json_array_routes = json_object_new_array();
while (route) { while (route) {
if (detail) if (detail)
ospf6_route_show_detail(vty, route); ospf6_route_show_detail(vty, route, json_array_routes,
use_json);
else else
ospf6_route_show(vty, route); ospf6_route_show(vty, route, json_array_routes,
use_json);
route = ospf6_route_match_next(prefix, route); route = ospf6_route_match_next(prefix, route);
} }
if (use_json)
json_object_object_add(json, "routes", json_array_routes);
} }
static void ospf6_route_show_table_type(struct vty *vty, int detail, static void ospf6_route_show_table_type(struct vty *vty, int detail,
uint8_t type, uint8_t type,
struct ospf6_route_table *table) struct ospf6_route_table *table,
json_object *json, bool use_json)
{ {
struct ospf6_route *route; struct ospf6_route *route;
json_object *json_array_routes = NULL;
route = ospf6_route_head(table); route = ospf6_route_head(table);
if (use_json)
json_array_routes = json_object_new_array();
while (route) { while (route) {
if (route->path.type == type) { if (route->path.type == type) {
if (detail) if (detail)
ospf6_route_show_detail(vty, route); ospf6_route_show_detail(vty, route,
json_array_routes,
use_json);
else else
ospf6_route_show(vty, route); ospf6_route_show(vty, route, json_array_routes,
use_json);
} }
route = ospf6_route_next(route); route = ospf6_route_next(route);
} }
if (use_json)
json_object_object_add(json, "routes", json_array_routes);
} }
static void ospf6_route_show_table(struct vty *vty, int detail, static void ospf6_route_show_table(struct vty *vty, int detail,
struct ospf6_route_table *table) struct ospf6_route_table *table,
json_object *json, bool use_json)
{ {
struct ospf6_route *route; struct ospf6_route *route;
json_object *json_array_routes = NULL;
route = ospf6_route_head(table); route = ospf6_route_head(table);
if (use_json)
json_array_routes = json_object_new_array();
while (route) { while (route) {
if (detail) if (detail)
ospf6_route_show_detail(vty, route); ospf6_route_show_detail(vty, route, json_array_routes,
use_json);
else else
ospf6_route_show(vty, route); ospf6_route_show(vty, route, json_array_routes,
use_json);
route = ospf6_route_next(route); route = ospf6_route_next(route);
} }
if (use_json)
json_object_object_add(json, "routes", json_array_routes);
} }
int ospf6_route_table_show(struct vty *vty, int argc_start, int argc, int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
struct cmd_token **argv, struct cmd_token **argv,
struct ospf6_route_table *table) struct ospf6_route_table *table, bool use_json)
{ {
int summary = 0; int summary = 0;
int match = 0; int match = 0;
@ -1317,10 +1511,15 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
int i, ret; int i, ret;
struct prefix prefix; struct prefix prefix;
uint8_t type = 0; uint8_t type = 0;
int arg_end = use_json ? (argc - 1) : argc;
json_object *json = NULL;
memset(&prefix, 0, sizeof(struct prefix)); memset(&prefix, 0, sizeof(struct prefix));
for (i = argc_start; i < argc; i++) { if (use_json)
json = json_object_new_object();
for (i = argc_start; i < arg_end; i++) {
if (strmatch(argv[i]->text, "summary")) { if (strmatch(argv[i]->text, "summary")) {
summary++; summary++;
continue; continue;
@ -1363,14 +1562,24 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
slash++; slash++;
continue; continue;
} }
if (use_json)
json_object_string_add(json, "malformedArgument",
argv[i]->arg);
else
vty_out(vty, "Malformed argument: %s\n", argv[i]->arg);
vty_out(vty, "Malformed argument: %s\n", argv[i]->arg);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
/* Give summary of this route table */ /* Give summary of this route table */
if (summary) { if (summary) {
ospf6_route_show_table_summary(vty, table); ospf6_route_show_table_summary(vty, table, json, use_json);
if (use_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; return CMD_SUCCESS;
} }
@ -1378,20 +1587,36 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
if (isprefix && !match) { if (isprefix && !match) {
/* If exact address, give best matching route */ /* If exact address, give best matching route */
if (!slash) if (!slash)
ospf6_route_show_table_address(vty, &prefix, table); ospf6_route_show_table_address(vty, &prefix, table,
json, use_json);
else else
ospf6_route_show_table_prefix(vty, &prefix, table); ospf6_route_show_table_prefix(vty, &prefix, table, json,
use_json);
if (use_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; return CMD_SUCCESS;
} }
if (match) if (match)
ospf6_route_show_table_match(vty, detail, &prefix, table); ospf6_route_show_table_match(vty, detail, &prefix, table, json,
use_json);
else if (type) else if (type)
ospf6_route_show_table_type(vty, detail, type, table); ospf6_route_show_table_type(vty, detail, type, table, json,
use_json);
else else
ospf6_route_show_table(vty, detail, table); ospf6_route_show_table(vty, detail, table, json, use_json);
if (use_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; return CMD_SUCCESS;
} }
@ -1439,7 +1664,7 @@ static void ospf6_linkstate_show_table_exact(struct vty *vty,
ospf6_route_lock(route); ospf6_route_lock(route);
while (route && ospf6_route_is_prefix(prefix, route)) { while (route && ospf6_route_is_prefix(prefix, route)) {
/* Specifying a prefix will always display details */ /* Specifying a prefix will always display details */
ospf6_route_show_detail(vty, route); ospf6_route_show_detail(vty, route, NULL, false);
route = ospf6_route_next(route); route = ospf6_route_next(route);
} }
if (route) if (route)
@ -1457,7 +1682,7 @@ static void ospf6_linkstate_show_table(struct vty *vty, int detail,
route = ospf6_route_head(table); route = ospf6_route_head(table);
while (route) { while (route) {
if (detail) if (detail)
ospf6_route_show_detail(vty, route); ospf6_route_show_detail(vty, route, NULL, false);
else else
ospf6_linkstate_show(vty, route); ospf6_linkstate_show(vty, route);
route = ospf6_route_next(route); route = ospf6_route_next(route);

View File

@ -23,6 +23,7 @@
#include "command.h" #include "command.h"
#include "zclient.h" #include "zclient.h"
#include "lib/json.h"
#define OSPF6_MULTI_PATH_LIMIT 4 #define OSPF6_MULTI_PATH_LIMIT 4
@ -233,6 +234,9 @@ extern const char *const ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX];
#define OSPF6_PATH_TYPE_SUBSTR(x) \ #define OSPF6_PATH_TYPE_SUBSTR(x) \
(0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? ospf6_path_type_substr[(x)] \ (0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? ospf6_path_type_substr[(x)] \
: ospf6_path_type_substr[0]) : ospf6_path_type_substr[0])
#define OSPF6_PATH_TYPE_JSON(x) \
(0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? ospf6_path_type_json[(x)] \
: ospf6_path_type_json[0])
#define OSPF6_ROUTE_ADDRESS_STR "Display the route bestmatches the address\n" #define OSPF6_ROUTE_ADDRESS_STR "Display the route bestmatches the address\n"
#define OSPF6_ROUTE_PREFIX_STR "Display the route\n" #define OSPF6_ROUTE_PREFIX_STR "Display the route\n"
@ -326,11 +330,14 @@ extern void ospf6_route_table_delete(struct ospf6_route_table *table);
extern void ospf6_route_dump(struct ospf6_route_table *table); extern void ospf6_route_dump(struct ospf6_route_table *table);
extern void ospf6_route_show(struct vty *vty, struct ospf6_route *route); extern void ospf6_route_show(struct vty *vty, struct ospf6_route *route,
extern void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route); json_object *json, bool use_json);
extern void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
json_object *json, bool use_json);
extern int ospf6_route_table_show(struct vty *, int, int, struct cmd_token **, extern int ospf6_route_table_show(struct vty *, int, int, struct cmd_token **,
struct ospf6_route_table *); struct ospf6_route_table *, bool use_json);
extern int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc, extern int ospf6_linkstate_table_show(struct vty *vty, int idx_ipv4, int argc,
struct cmd_token **argv, struct cmd_token **argv,
struct ospf6_route_table *table); struct ospf6_route_table *table);

View File

@ -51,6 +51,7 @@
#include "ospf6_intra.h" #include "ospf6_intra.h"
#include "ospf6_spf.h" #include "ospf6_spf.h"
#include "ospf6d.h" #include "ospf6d.h"
#include "lib/json.h"
DEFINE_QOBJ_TYPE(ospf6) DEFINE_QOBJ_TYPE(ospf6)
@ -1083,7 +1084,7 @@ DEFUN(show_ipv6_ospf6,
DEFUN (show_ipv6_ospf6_route, DEFUN (show_ipv6_ospf6_route,
show_ipv6_ospf6_route_cmd, show_ipv6_ospf6_route_cmd,
"show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>]", "show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]",
SHOW_STR SHOW_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
@ -1095,41 +1096,44 @@ DEFUN (show_ipv6_ospf6_route,
"Specify IPv6 address\n" "Specify IPv6 address\n"
"Specify IPv6 prefix\n" "Specify IPv6 prefix\n"
"Detailed information\n" "Detailed information\n"
"Summary of route table\n") "Summary of route table\n"
JSON_STR)
{ {
struct ospf6 *ospf6; struct ospf6 *ospf6;
bool uj = use_json(argc, argv);
ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
OSPF6_CMD_CHECK_RUNNING(ospf6); OSPF6_CMD_CHECK_RUNNING(ospf6);
ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table); ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table, uj);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (show_ipv6_ospf6_route_match, DEFUN (show_ipv6_ospf6_route_match,
show_ipv6_ospf6_route_match_cmd, show_ipv6_ospf6_route_match_cmd,
"show ipv6 ospf6 route X:X::X:X/M <match|longer>", "show ipv6 ospf6 route X:X::X:X/M <match|longer> [json]",
SHOW_STR SHOW_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
ROUTE_STR ROUTE_STR
"Specify IPv6 prefix\n" "Specify IPv6 prefix\n"
"Display routes which match the specified route\n" "Display routes which match the specified route\n"
"Display routes longer than the specified route\n") "Display routes longer than the specified route\n"
JSON_STR)
{ {
struct ospf6 *ospf6; struct ospf6 *ospf6;
bool uj = use_json(argc, argv);
ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
OSPF6_CMD_CHECK_RUNNING(ospf6); OSPF6_CMD_CHECK_RUNNING(ospf6);
ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table); ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table, uj);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (show_ipv6_ospf6_route_match_detail, DEFUN (show_ipv6_ospf6_route_match_detail,
show_ipv6_ospf6_route_match_detail_cmd, show_ipv6_ospf6_route_match_detail_cmd,
"show ipv6 ospf6 route X:X::X:X/M match detail", "show ipv6 ospf6 route X:X::X:X/M match detail [json]",
SHOW_STR SHOW_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
@ -1137,21 +1141,22 @@ DEFUN (show_ipv6_ospf6_route_match_detail,
"Specify IPv6 prefix\n" "Specify IPv6 prefix\n"
"Display routes which match the specified route\n" "Display routes which match the specified route\n"
"Detailed information\n" "Detailed information\n"
) JSON_STR)
{ {
struct ospf6 *ospf6; struct ospf6 *ospf6;
bool uj = use_json(argc, argv);
ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
OSPF6_CMD_CHECK_RUNNING(ospf6); OSPF6_CMD_CHECK_RUNNING(ospf6);
ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table); ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table, uj);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (show_ipv6_ospf6_route_type_detail, DEFUN (show_ipv6_ospf6_route_type_detail,
show_ipv6_ospf6_route_type_detail_cmd, show_ipv6_ospf6_route_type_detail_cmd,
"show ipv6 ospf6 route <intra-area|inter-area|external-1|external-2> detail", "show ipv6 ospf6 route <intra-area|inter-area|external-1|external-2> detail [json]",
SHOW_STR SHOW_STR
IP6_STR IP6_STR
OSPF6_STR OSPF6_STR
@ -1161,14 +1166,15 @@ DEFUN (show_ipv6_ospf6_route_type_detail,
"Display Type-1 External routes\n" "Display Type-1 External routes\n"
"Display Type-2 External routes\n" "Display Type-2 External routes\n"
"Detailed information\n" "Detailed information\n"
) JSON_STR)
{ {
struct ospf6 *ospf6; struct ospf6 *ospf6;
bool uj = use_json(argc, argv);
ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
OSPF6_CMD_CHECK_RUNNING(ospf6); OSPF6_CMD_CHECK_RUNNING(ospf6);
ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table); ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table, uj);
return CMD_SUCCESS; return CMD_SUCCESS;
} }

View File

@ -1006,7 +1006,7 @@ DEFUN (show_ipv6_ospf6_border_routers,
if (strmatch(argv[idx_ipv4]->text, "detail")) { if (strmatch(argv[idx_ipv4]->text, "detail")) {
for (ro = ospf6_route_head(ospf6->brouter_table); ro; for (ro = ospf6_route_head(ospf6->brouter_table); ro;
ro = ospf6_route_next(ro)) ro = ospf6_route_next(ro))
ospf6_route_show_detail(vty, ro); ospf6_route_show_detail(vty, ro, NULL, false);
} else { } else {
inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router); inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router);
@ -1019,7 +1019,7 @@ DEFUN (show_ipv6_ospf6_border_routers,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
ospf6_route_show_detail(vty, ro); ospf6_route_show_detail(vty, ro, NULL, false);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
} else { } else {