"??", "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)
{
/* 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;
char destination[PREFIX2STR_BUFFER], nexthop[64];
struct timeval now, res;
struct listnode *node;
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) {
vty_out(vty, "OSPFv3 is not running\n");
else
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)) {
struct interface *ifp;
/* nexthop */
inet_ntop(AF_INET6, &nh->address, nexthop, sizeof(nexthop));
ifp = if_lookup_by_index_all_vrf(nh->ifindex);
- if (!i) {
- 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_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 {
+ if (!i) {
+ 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];
struct timeval now, res;
char duration[64];
struct listnode *node;
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) {
vty_out(vty, "OSPFv3 is not running\n");
destination, sizeof(destination));
else
prefix2str(&route->prefix, destination, sizeof(destination));
- vty_out(vty, "Destination: %s\n", destination);
- /* destination type */
- vty_out(vty, "Destination type: %s\n",
- OSPF6_DEST_TYPE_NAME(route->type));
+ if (use_json) {
+ json_route = json_object_new_object();
+ 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 */
timersub(&now, &route->installed, &res);
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);
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 */
- 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);
+ if (use_json) {
+ json_object_int_add(json_route, "numberOfLock", route->lock);
+ snprintf(
+ flag, sizeof(flag), "%s%s%s%s",
+ (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"
+ : "-"));
+ 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 */
/* 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 */
- 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 */
inet_ntop(AF_INET, &route->path.origin.id, id, sizeof(id));
inet_ntop(AF_INET, &route->path.origin.adv_router, adv_router,
sizeof(adv_router));
- vty_out(vty, "LS Origin: %s Id: %s Adv: %s\n",
- ospf6_lstype_name(route->path.origin.type), id, adv_router);
+ if (use_json) {
+ 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 */
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 */
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 */
- 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 */
- 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);
+ if (use_json) {
+ json_object_int_add(json_route, "metricType",
+ 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 */
- 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)) {
struct interface *ifp;
- /* nexthop */
-
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,
- struct ospf6_route_table *table)
+ struct ospf6_route_table *table,
+ json_object *json, bool use_json)
{
struct ospf6_route *route, *prev = NULL;
int i, pathtype[OSPF6_PATH_TYPE_MAX];
unsigned int number = 0;
int nh_count = 0, nhinval = 0, ecmp = 0;
int alternative = 0, destination = 0;
+ char path_str[30];
for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
pathtype[i] = 0;
}
assert(number == table->count);
-
- 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);
+ if (use_json) {
+ json_object_int_add(json, "numberOfOspfv3Routes", number);
+ json_object_int_add(json, "numberOfDestination", destination);
+ json_object_int_add(json, "numberOfAlternativeRoutes",
+ 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++) {
- vty_out(vty, "Number of %s routes: %d\n",
- OSPF6_PATH_TYPE_NAME(i), pathtype[i]);
+ if (use_json) {
+ 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,
struct prefix *prefix,
- struct ospf6_route_table *table)
+ struct ospf6_route_table *table,
+ json_object *json, bool use_json)
{
struct ospf6_route *route;
+ json_object *json_array_routes = NULL;
route = ospf6_route_lookup(prefix, table);
if (route == NULL)
return;
+ if (use_json)
+ json_array_routes = json_object_new_array();
ospf6_route_lock(route);
while (route && ospf6_route_is_prefix(prefix, route)) {
/* 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);
}
+
+ if (use_json)
+ json_object_object_add(json, "routes", json_array_routes);
if (route)
ospf6_route_unlock(route);
}
static void ospf6_route_show_table_address(struct vty *vty,
struct prefix *prefix,
- struct ospf6_route_table *table)
+ struct ospf6_route_table *table,
+ json_object *json, bool use_json)
{
struct ospf6_route *route;
+ json_object *json_array_routes = NULL;
route = ospf6_route_lookup_bestmatch(prefix, table);
if (route == NULL)
return;
+ if (use_json)
+ json_array_routes = json_object_new_array();
prefix = &route->prefix;
ospf6_route_lock(route);
while (route && ospf6_route_is_prefix(prefix, route)) {
/* 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);
}
+ if (use_json)
+ json_object_object_add(json, "routes", json_array_routes);
if (route)
ospf6_route_unlock(route);
}
static void ospf6_route_show_table_match(struct vty *vty, int detail,
struct prefix *prefix,
- struct ospf6_route_table *table)
+ struct ospf6_route_table *table,
+ json_object *json, bool use_json)
{
struct ospf6_route *route;
+ json_object *json_array_routes = NULL;
+
assert(prefix->family);
route = ospf6_route_match_head(prefix, table);
+ if (use_json)
+ json_array_routes = json_object_new_array();
while (route) {
if (detail)
- ospf6_route_show_detail(vty, route);
+ ospf6_route_show_detail(vty, route, json_array_routes,
+ use_json);
else
- ospf6_route_show(vty, route);
+ ospf6_route_show(vty, route, json_array_routes,
+ use_json);
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,
uint8_t type,
- struct ospf6_route_table *table)
+ struct ospf6_route_table *table,
+ json_object *json, bool use_json)
{
struct ospf6_route *route;
+ json_object *json_array_routes = NULL;
route = ospf6_route_head(table);
+ if (use_json)
+ json_array_routes = json_object_new_array();
while (route) {
if (route->path.type == type) {
if (detail)
- ospf6_route_show_detail(vty, route);
+ ospf6_route_show_detail(vty, route,
+ json_array_routes,
+ use_json);
else
- ospf6_route_show(vty, route);
+ ospf6_route_show(vty, route, json_array_routes,
+ use_json);
}
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,
- struct ospf6_route_table *table)
+ struct ospf6_route_table *table,
+ json_object *json, bool use_json)
{
struct ospf6_route *route;
+ json_object *json_array_routes = NULL;
route = ospf6_route_head(table);
+ if (use_json)
+ json_array_routes = json_object_new_array();
while (route) {
if (detail)
- ospf6_route_show_detail(vty, route);
+ ospf6_route_show_detail(vty, route, json_array_routes,
+ use_json);
else
- ospf6_route_show(vty, route);
+ ospf6_route_show(vty, route, json_array_routes,
+ use_json);
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,
struct cmd_token **argv,
- struct ospf6_route_table *table)
+ struct ospf6_route_table *table, bool use_json)
{
int summary = 0;
int match = 0;
int i, ret;
struct prefix prefix;
uint8_t type = 0;
+ int arg_end = use_json ? (argc - 1) : argc;
+ json_object *json = NULL;
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")) {
summary++;
continue;
slash++;
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;
}
/* Give summary of this route table */
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;
}
if (isprefix && !match) {
/* If exact address, give best matching route */
if (!slash)
- ospf6_route_show_table_address(vty, &prefix, table);
+ ospf6_route_show_table_address(vty, &prefix, table,
+ json, use_json);
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;
}
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)
- ospf6_route_show_table_type(vty, detail, type, table);
+ ospf6_route_show_table_type(vty, detail, type, table, json,
+ use_json);
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;
}
ospf6_route_lock(route);
while (route && ospf6_route_is_prefix(prefix, route)) {
/* 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);
}
if (route)
route = ospf6_route_head(table);
while (route) {
if (detail)
- ospf6_route_show_detail(vty, route);
+ ospf6_route_show_detail(vty, route, NULL, false);
else
ospf6_linkstate_show(vty, route);
route = ospf6_route_next(route);