diff options
Diffstat (limited to 'ospf6d')
| -rw-r--r-- | ospf6d/ospf6_abr.c | 119 | ||||
| -rw-r--r-- | ospf6d/ospf6_asbr.c | 94 | ||||
| -rw-r--r-- | ospf6d/ospf6_flood.c | 12 | ||||
| -rw-r--r-- | ospf6d/ospf6_interface.c | 22 | ||||
| -rw-r--r-- | ospf6d/ospf6_interface.h | 1 | ||||
| -rw-r--r-- | ospf6d/ospf6_intra.c | 205 | ||||
| -rw-r--r-- | ospf6d/ospf6_lsa.c | 238 | ||||
| -rw-r--r-- | ospf6d/ospf6_lsa.h | 20 | ||||
| -rw-r--r-- | ospf6d/ospf6_lsdb.c | 49 | ||||
| -rw-r--r-- | ospf6d/ospf6_lsdb.h | 3 | ||||
| -rw-r--r-- | ospf6d/ospf6_route.c | 381 | ||||
| -rw-r--r-- | ospf6d/ospf6_route.h | 13 | ||||
| -rw-r--r-- | ospf6d/ospf6_spf.c | 7 | ||||
| -rw-r--r-- | ospf6d/ospf6_spf.h | 1 | ||||
| -rw-r--r-- | ospf6d/ospf6_top.c | 170 | ||||
| -rw-r--r-- | ospf6d/ospf6_top.h | 5 | ||||
| -rw-r--r-- | ospf6d/ospf6_zebra.c | 9 | ||||
| -rw-r--r-- | ospf6d/ospf6d.c | 770 |
18 files changed, 1241 insertions, 878 deletions
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 8cfdf2642c..abcdb40547 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -160,35 +160,22 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, && route->type != OSPF6_DEST_TYPE_RANGE && ((route->type != OSPF6_DEST_TYPE_ROUTER) || !CHECK_FLAG(route->path.router_bits, OSPF6_ROUTER_BIT_E))) { -#if 0 - zlog_debug( - "Route type is none of network, range nor ASBR, ignore"); -#endif return 0; } /* AS External routes are never considered */ if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 || route->path.type == OSPF6_PATH_TYPE_EXTERNAL2) { -#if 0 - zlog_debug("Path type is external, skip"); -#endif return 0; } /* do not generate if the path's area is the same as target area */ if (route->path.area_id == area->area_id) { -#if 0 - zlog_debug("The route is in the area itself, ignore"); -#endif return 0; } /* do not generate if the nexthops belongs to the target area */ if (ospf6_abr_nexthops_belong_to_area(route, area)) { -#if 0 - zlog_debug("The route's nexthop is in the same area, ignore"); -#endif return 0; } @@ -770,6 +757,10 @@ void ospf6_abr_old_path_update(struct ospf6_route *old_route, void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old, struct ospf6_route_table *table) { + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("%s: route %pFX, paths %d", __func__, &old->prefix, + listcount(old->paths)); + if (listcount(old->paths) > 1) { struct listnode *anode, *anext, *nnode, *rnode, *rnext; struct ospf6_path *o_path; @@ -778,13 +769,15 @@ void ospf6_abr_old_route_remove(struct ospf6_lsa *lsa, struct ospf6_route *old, for (ALL_LIST_ELEMENTS(old->paths, anode, anext, o_path)) { if (o_path->origin.adv_router != lsa->header->adv_router - && o_path->origin.id != lsa->header->id) + || o_path->origin.id != lsa->header->id) continue; for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) { for (ALL_LIST_ELEMENTS(old->nh_list, rnode, rnext, rnh)) { if (!ospf6_nexthop_is_same(rnh, nh)) continue; + if (IS_OSPF6_DEBUG_ABR) + zlog_debug("deleted nexthop"); listnode_delete(old->nh_list, rnh); ospf6_nexthop_delete(rnh); } @@ -847,14 +840,16 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) bool old_entry_updated = false; struct ospf6_path *path, *o_path, *ecmp_path; struct listnode *anode; + bool add_route = false; memset(&prefix, 0, sizeof(prefix)); if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_PREFIX)) { if (IS_OSPF6_DEBUG_EXAMIN(INTER_PREFIX)) { is_debug++; - zlog_debug("%s: Examin %s in area %s", __func__, - lsa->name, oa->name); + zlog_debug("%s: LSA %s age %d in area %s", __func__, + lsa->name, ospf6_lsa_age_current(lsa), + oa->name); } prefix_lsa = @@ -873,8 +868,9 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) } else if (lsa->header->type == htons(OSPF6_LSTYPE_INTER_ROUTER)) { if (IS_OSPF6_DEBUG_EXAMIN(INTER_ROUTER)) { is_debug++; - zlog_debug("%s: Examin %s in area %s", __func__, - lsa->name, oa->name); + zlog_debug("%s: LSA %s age %d in area %s", __func__, + lsa->name, ospf6_lsa_age_current(lsa), + oa->name); } router_lsa = @@ -898,8 +894,12 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) /* Find existing route */ route = ospf6_route_lookup(&prefix, table); - if (route) + if (route) { ospf6_route_lock(route); + if (is_debug) + zlog_debug("%s: route %pFX, paths %d", __func__, + &prefix, listcount(route->paths)); + } while (route && ospf6_route_is_prefix(&prefix, route)) { if (route->path.area_id == oa->area_id && route->path.origin.type == lsa->header->type @@ -952,6 +952,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) return; } + /* (2) if the LSA is self-originated, ignore */ if (lsa->header->adv_router == oa->ospf6->router_id) { if (is_debug) @@ -1026,8 +1027,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) || !CHECK_FLAG(abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B)) { if (is_debug) zlog_debug( - "%s: ABR router entry does not exist, ignore", - __func__); + "%s: ABR router entry %pFX does not exist, ignore", + __func__, &abr_prefix); if (old) { if (old->type == OSPF6_DEST_TYPE_ROUTER && oa->intra_brouter_calc) { @@ -1040,7 +1041,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) zlog_debug( "%s: remove old entry: %s %p ", __func__, buf, (void *)old); - ospf6_route_remove(old, table); + ospf6_abr_old_route_remove(lsa, old, table); } } return; @@ -1104,7 +1105,11 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) are identical. */ old = ospf6_route_lookup(&prefix, table); - + if (old) { + if (is_debug) + zlog_debug("%s: found old route %pFX, paths %d", + __func__, &prefix, listcount(old->paths)); + } for (old_route = old; old_route; old_route = old_route->next) { if (!ospf6_route_is_same(old_route, route) || (old_route->type != route->type) || @@ -1186,7 +1191,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) "%s: Update route: %s %p old cost %u new cost %u nh %u", __func__, buf, (void *)old_route, old_route->path.cost, route->path.cost, - listcount(route->nh_list)); + listcount(old_route->nh_list)); /* For Inter-Prefix route: Update RIB/FIB, * For Inter-Router trigger summary update @@ -1199,10 +1204,19 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa) break; } + /* If the old entry is not updated and old entry not found or old entry + * does not match with the new entry then add the new route + */ if (old_entry_updated == false) { + if ((old == NULL) || (old->type != route->type) + || (old->path.type != route->path.type)) + add_route = true; + } + + if (add_route) { if (is_debug) { zlog_debug( - "%s: Install route: %s cost %u nh %u adv_router %pI4", + "%s: Install new route: %s cost %u nh %u adv_router %pI4", __func__, buf, route->path.cost, listcount(route->nh_list), &route->path.origin.adv_router); @@ -1296,7 +1310,9 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa, } static int ospf6_inter_area_prefix_lsa_show(struct vty *vty, - struct ospf6_lsa *lsa) + struct ospf6_lsa *lsa, + json_object *json_obj, + bool use_json) { struct ospf6_inter_prefix_lsa *prefix_lsa; char buf[INET6_ADDRSTRLEN]; @@ -1304,16 +1320,29 @@ static int ospf6_inter_area_prefix_lsa_show(struct vty *vty, prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END( lsa->header); - vty_out(vty, " Metric: %lu\n", - (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa)); + if (use_json) { + json_object_int_add( + json_obj, "metric", + (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa)); + ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options, + buf, sizeof(buf)); + json_object_string_add(json_obj, "prefixOptions", buf); + json_object_string_add( + json_obj, "prefix", + ospf6_inter_area_prefix_lsa_get_prefix_str( + lsa, buf, sizeof(buf), 0)); + } else { + vty_out(vty, " Metric: %lu\n", + (unsigned long)OSPF6_ABR_SUMMARY_METRIC(prefix_lsa)); - ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options, buf, - sizeof(buf)); - vty_out(vty, " Prefix Options: %s\n", buf); + ospf6_prefix_options_printbuf(prefix_lsa->prefix.prefix_options, + buf, sizeof(buf)); + vty_out(vty, " Prefix Options: %s\n", buf); - vty_out(vty, " Prefix: %s\n", - ospf6_inter_area_prefix_lsa_get_prefix_str(lsa, buf, - sizeof(buf), 0)); + vty_out(vty, " Prefix: %s\n", + ospf6_inter_area_prefix_lsa_get_prefix_str( + lsa, buf, sizeof(buf), 0)); + } return 0; } @@ -1338,7 +1367,9 @@ static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa, } static int ospf6_inter_area_router_lsa_show(struct vty *vty, - struct ospf6_lsa *lsa) + struct ospf6_lsa *lsa, + json_object *json_obj, + bool use_json) { struct ospf6_inter_router_lsa *router_lsa; char buf[64]; @@ -1347,12 +1378,22 @@ static int ospf6_inter_area_router_lsa_show(struct vty *vty, lsa->header); ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf)); - vty_out(vty, " Options: %s\n", buf); - vty_out(vty, " Metric: %lu\n", - (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa)); + if (use_json) { + json_object_string_add(json_obj, "options", buf); + json_object_int_add( + json_obj, "metric", + (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa)); + } else { + vty_out(vty, " Options: %s\n", buf); + vty_out(vty, " Metric: %lu\n", + (unsigned long)OSPF6_ABR_SUMMARY_METRIC(router_lsa)); + } inet_ntop(AF_INET, &router_lsa->router_id, buf, sizeof(buf)); - vty_out(vty, " Destination Router ID: %s\n", buf); + if (use_json) + json_object_string_add(json_obj, "destinationRouterId", buf); + else + vty_out(vty, " Destination Router ID: %s\n", buf); return 0; } diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 0e419cbff6..3449f48267 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -210,7 +210,7 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, struct ospf6_route *route, struct ospf6 *ospf6) { - struct ospf6_route *old_route; + struct ospf6_route *old_route, *next_route; struct ospf6_path *ecmp_path, *o_path = NULL; struct listnode *anode, *anext; struct listnode *nnode, *rnode, *rnext; @@ -220,9 +220,11 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, /* check for old entry match with new route origin, * delete old entry. */ - for (old_route = old; old_route; old_route = old_route->next) { + for (old_route = old; old_route; old_route = next_route) { bool route_updated = false; + next_route = old_route->next; + if (!ospf6_route_is_same(old_route, route) || (old_route->path.type != route->path.type)) continue; @@ -315,6 +317,8 @@ void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old, old_route->path.cost, route->path.cost); } + if (old == old_route) + old = next_route; ospf6_route_remove(old_route, ospf6->route_table); } @@ -1439,8 +1443,7 @@ static void ospf6_redistribute_show_config(struct vty *vty, struct ospf6 *ospf6, struct ospf6_redist *red; total = 0; - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) - nroute[type] = 0; + memset(nroute, 0, sizeof(nroute)); for (route = ospf6_route_head(ospf6->external_table); route; route = ospf6_route_next(route)) { info = route->route_option; @@ -1448,12 +1451,11 @@ static void ospf6_redistribute_show_config(struct vty *vty, struct ospf6 *ospf6, total++; } - if (use_json) - json_route = json_object_new_object(); - else + if (!use_json) vty_out(vty, "Redistributing External Routes from:\n"); for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + red = ospf6_redist_lookup(ospf6, type, 0); if (!red) @@ -1462,6 +1464,7 @@ static void ospf6_redistribute_show_config(struct vty *vty, struct ospf6 *ospf6, continue; if (use_json) { + json_route = json_object_new_object(); json_object_string_add(json_route, "routeType", ZROUTE_NAME(type)); json_object_int_add(json_route, "numberOfRoutes", @@ -1890,7 +1893,8 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa, return (buf); } -static int ospf6_as_external_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_as_external_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_obj, bool use_json) { struct ospf6_as_external_lsa *external; char buf[64]; @@ -1908,31 +1912,65 @@ static int ospf6_as_external_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-')); - vty_out(vty, " Bits: %s\n", buf); - vty_out(vty, " Metric: %5lu\n", - (unsigned long)OSPF6_ASBR_METRIC(external)); - - ospf6_prefix_options_printbuf(external->prefix.prefix_options, buf, - sizeof(buf)); - vty_out(vty, " Prefix Options: %s\n", buf); + if (use_json) { + json_object_string_add(json_obj, "bits", buf); + json_object_int_add(json_obj, "metric", + (unsigned long)OSPF6_ASBR_METRIC(external)); + ospf6_prefix_options_printbuf(external->prefix.prefix_options, + buf, sizeof(buf)); + json_object_string_add(json_obj, "prefixOptions", buf); + json_object_int_add( + json_obj, "referenceLsType", + ntohs(external->prefix.prefix_refer_lstype)); + json_object_string_add(json_obj, "prefix", + ospf6_as_external_lsa_get_prefix_str( + lsa, buf, sizeof(buf), 0)); + + /* Forwarding-Address */ + json_object_boolean_add( + json_obj, "forwardingAddressPresent", + CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F)); + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F)) + json_object_string_add( + json_obj, "forwardingAddress", + ospf6_as_external_lsa_get_prefix_str( + lsa, buf, sizeof(buf), 1)); + + /* Tag */ + json_object_boolean_add( + json_obj, "tagPresent", + CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T)); + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T)) + json_object_int_add(json_obj, "tag", + ospf6_as_external_lsa_get_tag(lsa)); + } else { + vty_out(vty, " Bits: %s\n", buf); + vty_out(vty, " Metric: %5lu\n", + (unsigned long)OSPF6_ASBR_METRIC(external)); - vty_out(vty, " Referenced LSType: %d\n", - ntohs(external->prefix.prefix_refer_lstype)); + ospf6_prefix_options_printbuf(external->prefix.prefix_options, + buf, sizeof(buf)); + vty_out(vty, " Prefix Options: %s\n", buf); - vty_out(vty, " Prefix: %s\n", - ospf6_as_external_lsa_get_prefix_str(lsa, buf, sizeof(buf), 0)); + vty_out(vty, " Referenced LSType: %d\n", + ntohs(external->prefix.prefix_refer_lstype)); - /* Forwarding-Address */ - if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F)) { - vty_out(vty, " Forwarding-Address: %s\n", + vty_out(vty, " Prefix: %s\n", ospf6_as_external_lsa_get_prefix_str(lsa, buf, - sizeof(buf), 1)); - } + sizeof(buf), 0)); - /* Tag */ - if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T)) { - vty_out(vty, " Tag: %" ROUTE_TAG_PRI "\n", - ospf6_as_external_lsa_get_tag(lsa)); + /* Forwarding-Address */ + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_F)) { + vty_out(vty, " Forwarding-Address: %s\n", + ospf6_as_external_lsa_get_prefix_str( + lsa, buf, sizeof(buf), 1)); + } + + /* Tag */ + if (CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T)) { + vty_out(vty, " Tag: %" ROUTE_TAG_PRI "\n", + ospf6_as_external_lsa_get_tag(lsa)); + } } return 0; diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 0662cfd683..2d896546fa 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -452,12 +452,6 @@ void ospf6_flood_area(struct ospf6_neighbor *from, struct ospf6_lsa *lsa, && oi != OSPF6_INTERFACE(lsa->lsdb->data)) continue; -#if 0 - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && - ospf6_is_interface_virtual_link (oi)) - continue; -#endif /*0*/ - ospf6_flood_interface(from, lsa, oi); } } @@ -527,12 +521,6 @@ static void ospf6_flood_clear_area(struct ospf6_lsa *lsa, struct ospf6_area *oa) && oi != OSPF6_INTERFACE(lsa->lsdb->data)) continue; -#if 0 - if (OSPF6_LSA_SCOPE (lsa->header->type) == OSPF6_SCOPE_AS && - ospf6_is_interface_virtual_link (oi)) - continue; -#endif /*0*/ - ospf6_flood_clear_interface(lsa, oi); } } diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 4988cee7d8..0cc3bd2cc9 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -250,6 +250,7 @@ void ospf6_interface_delete(struct ospf6_interface *oi) THREAD_OFF(oi->thread_send_lsupdate); THREAD_OFF(oi->thread_send_lsack); THREAD_OFF(oi->thread_sso); + THREAD_OFF(oi->thread_wait_timer); ospf6_lsdb_remove_all(oi->lsdb); ospf6_lsdb_remove_all(oi->lsupdate_list); @@ -304,6 +305,7 @@ void ospf6_interface_disable(struct ospf6_interface *oi) THREAD_OFF(oi->thread_link_lsa); THREAD_OFF(oi->thread_intra_prefix_lsa); THREAD_OFF(oi->thread_as_extern_lsa); + THREAD_OFF(oi->thread_wait_timer); } static struct in6_addr * @@ -793,7 +795,7 @@ int interface_up(struct thread *thread) else { ospf6_interface_state_change(OSPF6_INTERFACE_WAITING, oi); thread_add_timer(master, wait_timer, oi, oi->dead_interval, - NULL); + &oi->thread_wait_timer); } return 0; @@ -1414,7 +1416,7 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix, [<\ detail\ |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ - >]", + >] [json]", SHOW_STR IP6_STR OSPF6_STR @@ -1425,12 +1427,14 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix, OSPF6_ROUTE_ADDRESS_STR OSPF6_ROUTE_PREFIX_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_prefix = 6; struct interface *ifp; struct ospf6_interface *oi; + bool uj = use_json(argc, argv); ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT); if (ifp == NULL) { @@ -1445,8 +1449,8 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix, return CMD_WARNING; } - ospf6_route_table_show(vty, idx_prefix, argc, argv, - oi->route_connected); + ospf6_route_table_show(vty, idx_prefix, argc, argv, oi->route_connected, + uj); return CMD_SUCCESS; } @@ -1457,7 +1461,7 @@ DEFUN (show_ipv6_ospf6_interface_prefix, [<\ detail\ |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ - >]", + >] [json]", SHOW_STR IP6_STR OSPF6_STR @@ -1467,12 +1471,14 @@ DEFUN (show_ipv6_ospf6_interface_prefix, OSPF6_ROUTE_ADDRESS_STR OSPF6_ROUTE_PREFIX_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); int idx_prefix = 5; struct ospf6_interface *oi; struct interface *ifp; + bool uj = use_json(argc, argv); FOR_ALL_INTERFACES (vrf, ifp) { oi = (struct ospf6_interface *)ifp->info; @@ -1480,7 +1486,7 @@ DEFUN (show_ipv6_ospf6_interface_prefix, continue; ospf6_route_table_show(vty, idx_prefix, argc, argv, - oi->route_connected); + oi->route_connected, uj); } return CMD_SUCCESS; diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index dd7f4d1b1e..6e4692920c 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -111,6 +111,7 @@ struct ospf6_interface { struct thread *thread_link_lsa; struct thread *thread_intra_prefix_lsa; struct thread *thread_as_extern_lsa; + struct thread *thread_wait_timer; struct ospf6_route_table *route_connected; diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index 17538c466a..2abe64ac60 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -76,7 +76,8 @@ static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf, *)(start + pos * (sizeof(struct ospf6_router_lsdesc))); - if ((char *)lsdesc < end) { + if ((char *)lsdesc + sizeof(struct ospf6_router_lsdesc) + <= end) { if (buf && (buflen > INET_ADDRSTRLEN * 2)) { inet_ntop(AF_INET, &lsdesc->neighbor_interface_id, buf1, @@ -84,20 +85,24 @@ static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf, inet_ntop(AF_INET, &lsdesc->neighbor_router_id, buf2, sizeof(buf2)); sprintf(buf, "%s/%s", buf2, buf1); + + return buf; } - } else - return NULL; + } } - return buf; + return NULL; } -static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_obj, bool use_json) { char *start, *end, *current; char buf[32], name[32], bits[16], options[32]; struct ospf6_router_lsa *router_lsa; struct ospf6_router_lsdesc *lsdesc; + json_object *json_arr; + json_object *json_loop; router_lsa = (struct ospf6_router_lsa *)((char *)lsa->header @@ -105,7 +110,12 @@ static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) ospf6_capability_printbuf(router_lsa->bits, bits, sizeof(bits)); ospf6_options_printbuf(router_lsa->options, options, sizeof(options)); - vty_out(vty, " Bits: %s Options: %s\n", bits, options); + if (use_json) { + json_object_string_add(json_obj, "bits", bits); + json_object_string_add(json_obj, "options", options); + json_arr = json_object_new_array(); + } else + vty_out(vty, " Bits: %s Options: %s\n", bits, options); start = (char *)router_lsa + sizeof(struct ospf6_router_lsa); end = (char *)lsa->header + ntohs(lsa->header->length); @@ -126,18 +136,43 @@ static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) snprintf(name, sizeof(name), "Unknown (%#x)", lsdesc->type); - vty_out(vty, " Type: %s Metric: %d\n", name, - ntohs(lsdesc->metric)); - vty_out(vty, " Interface ID: %s\n", - inet_ntop(AF_INET, &lsdesc->interface_id, buf, - sizeof(buf))); - vty_out(vty, " Neighbor Interface ID: %s\n", - inet_ntop(AF_INET, &lsdesc->neighbor_interface_id, buf, - sizeof(buf))); - vty_out(vty, " Neighbor Router ID: %s\n", - inet_ntop(AF_INET, &lsdesc->neighbor_router_id, buf, - sizeof(buf))); + if (use_json) { + json_loop = json_object_new_object(); + json_object_string_add(json_loop, "type", name); + json_object_int_add(json_loop, "metric", + ntohs(lsdesc->metric)); + json_object_string_add(json_loop, "interfaceId", + inet_ntop(AF_INET, + &lsdesc->interface_id, + buf, sizeof(buf))); + json_object_string_add( + json_loop, "neighborInterfaceId", + inet_ntop(AF_INET, + &lsdesc->neighbor_interface_id, buf, + sizeof(buf))); + json_object_string_add( + json_loop, "neighborRouterId", + inet_ntop(AF_INET, &lsdesc->neighbor_router_id, + buf, sizeof(buf))); + json_object_array_add(json_arr, json_loop); + } else { + vty_out(vty, " Type: %s Metric: %d\n", name, + ntohs(lsdesc->metric)); + vty_out(vty, " Interface ID: %s\n", + inet_ntop(AF_INET, &lsdesc->interface_id, buf, + sizeof(buf))); + vty_out(vty, " Neighbor Interface ID: %s\n", + inet_ntop(AF_INET, + &lsdesc->neighbor_interface_id, buf, + sizeof(buf))); + vty_out(vty, " Neighbor Router ID: %s\n", + inet_ntop(AF_INET, &lsdesc->neighbor_router_id, + buf, sizeof(buf))); + } } + if (use_json) + json_object_object_add(json_obj, "lsaDescription", json_arr); + return 0; } @@ -411,39 +446,55 @@ static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa *lsa, char *buf, if ((current + sizeof(struct ospf6_network_lsdesc)) <= end) { lsdesc = (struct ospf6_network_lsdesc *)current; - if (buf) + if (buf) { inet_ntop(AF_INET, &lsdesc->router_id, buf, buflen); - } else - return NULL; + return buf; + } + } } - return (buf); + return NULL; } -static int ospf6_network_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_network_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_obj, bool use_json) { char *start, *end, *current; struct ospf6_network_lsa *network_lsa; struct ospf6_network_lsdesc *lsdesc; char buf[128], options[32]; + json_object *json_arr; network_lsa = (struct ospf6_network_lsa *)((caddr_t)lsa->header + sizeof(struct ospf6_lsa_header)); ospf6_options_printbuf(network_lsa->options, options, sizeof(options)); - vty_out(vty, " Options: %s\n", options); + if (use_json) + json_object_string_add(json_obj, "options", options); + else + vty_out(vty, " Options: %s\n", options); start = (char *)network_lsa + sizeof(struct ospf6_network_lsa); end = (char *)lsa->header + ntohs(lsa->header->length); + if (use_json) + json_arr = json_object_new_array(); + for (current = start; current + sizeof(struct ospf6_network_lsdesc) <= end; current += sizeof(struct ospf6_network_lsdesc)) { lsdesc = (struct ospf6_network_lsdesc *)current; inet_ntop(AF_INET, &lsdesc->router_id, buf, sizeof(buf)); - vty_out(vty, " Attached Router: %s\n", buf); + if (use_json) + json_object_array_add(json_arr, + json_object_new_string(buf)); + else + vty_out(vty, " Attached Router: %s\n", buf); } + if (use_json) + json_object_object_add(json_obj, "attachedRouter", json_arr); + return 0; } @@ -602,7 +653,7 @@ static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf, end = (char *)lsa->header + ntohs(lsa->header->length); current = start; - do { + while (current + sizeof(struct ospf6_prefix) <= end) { prefix = (struct ospf6_prefix *)current; if (prefix->prefix_length == 0 || current + OSPF6_PREFIX_SIZE(prefix) > end) { @@ -620,12 +671,13 @@ static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf, inet_ntop(AF_INET6, &in6, buf, buflen); return (buf); } - } while (current <= end); + } } return NULL; } -static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_obj, bool use_json) { char *start, *end, *current; struct ospf6_link_lsa *link_lsa; @@ -634,6 +686,10 @@ static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) struct ospf6_prefix *prefix; const char *p, *mc, *la, *nu; struct in6_addr in6; + json_object *json_loop; + json_object *json_arr = NULL; + char str[15]; + char prefix_string[133]; link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa->header + sizeof(struct ospf6_lsa_header)); @@ -642,10 +698,18 @@ static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf, sizeof(buf)); prefixnum = ntohl(link_lsa->prefix_num); - vty_out(vty, " Priority: %d Options: %s\n", link_lsa->priority, - options); - vty_out(vty, " LinkLocal Address: %s\n", buf); - vty_out(vty, " Number of Prefix: %d\n", prefixnum); + if (use_json) { + json_arr = json_object_new_array(); + json_object_int_add(json_obj, "priority", link_lsa->priority); + json_object_string_add(json_obj, "options", options); + json_object_string_add(json_obj, "linkLocalAddress", buf); + json_object_int_add(json_obj, "numberOfPrefix", prefixnum); + } else { + vty_out(vty, " Priority: %d Options: %s\n", + link_lsa->priority, options); + vty_out(vty, " LinkLocal Address: %s\n", buf); + vty_out(vty, " Number of Prefix: %d\n", prefixnum); + } start = (char *)link_lsa + sizeof(struct ospf6_link_lsa); end = (char *)lsa->header + ntohs(lsa->header->length); @@ -668,16 +732,31 @@ static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) nu = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ? "NU" : "--"); - vty_out(vty, " Prefix Options: %s|%s|%s|%s\n", p, mc, la, - nu); + if (use_json) { + json_loop = json_object_new_object(); + snprintf(str, sizeof(str), "%s|%s|%s|%s", p, mc, la, + nu); + json_object_string_add(json_loop, "prefixOption", str); + } else + vty_out(vty, " Prefix Options: %s|%s|%s|%s\n", p, + mc, la, nu); memset(&in6, 0, sizeof(in6)); memcpy(&in6, OSPF6_PREFIX_BODY(prefix), OSPF6_PREFIX_SPACE(prefix->prefix_length)); inet_ntop(AF_INET6, &in6, buf, sizeof(buf)); - vty_out(vty, " Prefix: %s/%d\n", buf, - prefix->prefix_length); + if (use_json) { + snprintf(prefix_string, sizeof(prefix_string), "%s/%d", + buf, prefix->prefix_length); + json_object_string_add(json_loop, "prefix", + prefix_string); + json_object_array_add(json_arr, json_loop); + } else + vty_out(vty, " Prefix: %s/%d\n", buf, + prefix->prefix_length); } + if (use_json) + json_object_object_add(json_obj, "prefix", json_arr); return 0; } @@ -803,7 +882,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa, end = (char *)lsa->header + ntohs(lsa->header->length); current = start; - do { + while (current + sizeof(struct ospf6_prefix) <= end) { prefix = (struct ospf6_prefix *)current; if (prefix->prefix_length == 0 || current + OSPF6_PREFIX_SIZE(prefix) > end) { @@ -823,12 +902,13 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa, prefix->prefix_length); return (buf); } - } while (current <= end); + } } - return (buf); + return NULL; } -static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_obj, bool use_json) { char *start, *end, *current; struct ospf6_intra_prefix_lsa *intra_prefix_lsa; @@ -838,6 +918,10 @@ static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) char id[16], adv_router[16]; const char *p, *mc, *la, *nu; struct in6_addr in6; + json_object *json_loop; + json_object *json_arr = NULL; + char str[15]; + char prefix_string[133]; intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)((caddr_t)lsa->header @@ -845,13 +929,25 @@ static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) prefixnum = ntohs(intra_prefix_lsa->prefix_num); - vty_out(vty, " Number of Prefix: %d\n", prefixnum); + if (use_json) { + json_arr = json_object_new_array(); + json_object_int_add(json_obj, "numberOfPrefix", prefixnum); + } else + vty_out(vty, " Number of Prefix: %d\n", prefixnum); inet_ntop(AF_INET, &intra_prefix_lsa->ref_id, id, sizeof(id)); inet_ntop(AF_INET, &intra_prefix_lsa->ref_adv_router, adv_router, sizeof(adv_router)); - vty_out(vty, " Reference: %s Id: %s Adv: %s\n", - ospf6_lstype_name(intra_prefix_lsa->ref_type), id, adv_router); + if (use_json) { + json_object_string_add( + json_obj, "reference", + ospf6_lstype_name(intra_prefix_lsa->ref_type)); + json_object_string_add(json_obj, "referenceId", id); + json_object_string_add(json_obj, "referenceAdv", adv_router); + } else + vty_out(vty, " Reference: %s Id: %s Adv: %s\n", + ospf6_lstype_name(intra_prefix_lsa->ref_type), id, + adv_router); start = (char *)intra_prefix_lsa + sizeof(struct ospf6_intra_prefix_lsa); @@ -875,16 +971,31 @@ static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) nu = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ? "NU" : "--"); - vty_out(vty, " Prefix Options: %s|%s|%s|%s\n", p, mc, la, - nu); + if (use_json) { + json_loop = json_object_new_object(); + snprintf(str, sizeof(str), "%s|%s|%s|%s", p, mc, la, + nu); + json_object_string_add(json_loop, "prefixOption", str); + } else + vty_out(vty, " Prefix Options: %s|%s|%s|%s\n", p, + mc, la, nu); memset(&in6, 0, sizeof(in6)); memcpy(&in6, OSPF6_PREFIX_BODY(prefix), OSPF6_PREFIX_SPACE(prefix->prefix_length)); inet_ntop(AF_INET6, &in6, buf, sizeof(buf)); - vty_out(vty, " Prefix: %s/%d\n", buf, - prefix->prefix_length); + if (use_json) { + snprintf(prefix_string, sizeof(prefix_string), "%s/%d", + buf, prefix->prefix_length); + json_object_string_add(json_loop, "prefix", + prefix_string); + json_object_array_add(json_arr, json_loop); + } else + vty_out(vty, " Prefix: %s/%d\n", buf, + prefix->prefix_length); } + if (use_json) + json_object_object_add(json_obj, "prefix", json_arr); return 0; } @@ -1338,6 +1449,8 @@ static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route, g_route->path.origin.id = h_path->origin.id; g_route->path.origin.adv_router = h_path->origin.adv_router; + if (nroute) + ospf6_route_unlock(nroute); break; } } diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c index 29141ee7f8..f1b04c9bec 100644 --- a/ospf6d/ospf6_lsa.c +++ b/ospf6d/ospf6_lsa.c @@ -66,7 +66,8 @@ struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa) return ospf6; } -static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) +static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_obj, bool use_json) { uint8_t *start, *end, *current; char byte[4]; @@ -74,18 +75,22 @@ static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) start = (uint8_t *)lsa->header + sizeof(struct ospf6_lsa_header); end = (uint8_t *)lsa->header + ntohs(lsa->header->length); - vty_out(vty, " Unknown contents:\n"); - for (current = start; current < end; current++) { - if ((current - start) % 16 == 0) - vty_out(vty, "\n "); - else if ((current - start) % 4 == 0) - vty_out(vty, " "); + if (use_json) + json_object_string_add(json_obj, "LsaType", "unknown"); + else { + vty_out(vty, " Unknown contents:\n"); + for (current = start; current < end; current++) { + if ((current - start) % 16 == 0) + vty_out(vty, "\n "); + else if ((current - start) % 4 == 0) + vty_out(vty, " "); + + snprintf(byte, sizeof(byte), "%02x", *current); + vty_out(vty, "%s", byte); + } - snprintf(byte, sizeof(byte), "%02x", *current); - vty_out(vty, "%s", byte); + vty_out(vty, "\n\n"); } - - vty_out(vty, "\n\n"); return 0; } @@ -392,13 +397,15 @@ void ospf6_lsa_show_summary_header(struct vty *vty) "AdvRouter", "Age", "SeqNum", "Payload"); } -void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa) +void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_array, bool use_json) { char adv_router[16], id[16]; int type; const struct ospf6_lsa_handler *handler; - char buf[64], tmpbuf[80]; + char buf[64]; int cnt = 0; + json_object *json_obj = NULL; assert(lsa); assert(lsa->header); @@ -409,34 +416,95 @@ void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa) type = ntohs(lsa->header->type); handler = ospf6_get_lsa_handler(lsa->header->type); + + if (use_json) + json_obj = json_object_new_object(); + if ((type == OSPF6_LSTYPE_INTER_PREFIX) || (type == OSPF6_LSTYPE_INTER_ROUTER) || (type == OSPF6_LSTYPE_AS_EXTERNAL)) { - vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n", - ospf6_lstype_short_name(lsa->header->type), id, - adv_router, ospf6_lsa_age_current(lsa), - (unsigned long)ntohl(lsa->header->seqnum), - handler->lh_get_prefix_str(lsa, buf, sizeof(buf), 0)); + if (use_json) { + json_object_string_add( + json_obj, "type", + ospf6_lstype_short_name(lsa->header->type)); + json_object_string_add(json_obj, "lsId", id); + json_object_string_add(json_obj, "advRouter", + adv_router); + json_object_int_add(json_obj, "age", + ospf6_lsa_age_current(lsa)); + json_object_int_add( + json_obj, "seqNum", + (unsigned long)ntohl(lsa->header->seqnum)); + json_object_string_add( + json_obj, "payload", + handler->lh_get_prefix_str(lsa, buf, + sizeof(buf), 0)); + json_object_array_add(json_array, json_obj); + } else + vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n", + ospf6_lstype_short_name(lsa->header->type), id, + adv_router, ospf6_lsa_age_current(lsa), + (unsigned long)ntohl(lsa->header->seqnum), + handler->lh_get_prefix_str(lsa, buf, + sizeof(buf), 0)); } else if (type != OSPF6_LSTYPE_UNKNOWN) { - snprintf(tmpbuf, sizeof(tmpbuf), "%-4s %-15s%-15s%4hu %8lx", - ospf6_lstype_short_name(lsa->header->type), id, - adv_router, ospf6_lsa_age_current(lsa), - (unsigned long)ntohl(lsa->header->seqnum)); - while (handler->lh_get_prefix_str(lsa, buf, sizeof(buf), cnt) != NULL) { - vty_out(vty, "%s %30s\n", tmpbuf, buf); + if (use_json) { + json_object_string_add( + json_obj, "type", + ospf6_lstype_short_name( + lsa->header->type)); + json_object_string_add(json_obj, "lsId", id); + json_object_string_add(json_obj, "advRouter", + adv_router); + json_object_int_add(json_obj, "age", + ospf6_lsa_age_current(lsa)); + json_object_int_add( + json_obj, "seqNum", + (unsigned long)ntohl( + lsa->header->seqnum)); + json_object_string_add(json_obj, "payload", + buf); + json_object_array_add(json_array, json_obj); + json_obj = json_object_new_object(); + } else + vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n", + ospf6_lstype_short_name( + lsa->header->type), + id, adv_router, + ospf6_lsa_age_current(lsa), + (unsigned long)ntohl( + lsa->header->seqnum), + buf); cnt++; } + if (use_json) + json_object_free(json_obj); } else { - vty_out(vty, "%-4s %-15s%-15s%4hu %8lx\n", - ospf6_lstype_short_name(lsa->header->type), id, - adv_router, ospf6_lsa_age_current(lsa), - (unsigned long)ntohl(lsa->header->seqnum)); + if (use_json) { + json_object_string_add( + json_obj, "type", + ospf6_lstype_short_name(lsa->header->type)); + json_object_string_add(json_obj, "lsId", id); + json_object_string_add(json_obj, "advRouter", + adv_router); + json_object_int_add(json_obj, "age", + ospf6_lsa_age_current(lsa)); + json_object_int_add( + json_obj, "seqNum", + (unsigned long)ntohl(lsa->header->seqnum)); + json_object_array_add(json_array, json_obj); + } else + vty_out(vty, "%-4s %-15s%-15s%4hu %8lx\n", + ospf6_lstype_short_name(lsa->header->type), id, + adv_router, ospf6_lsa_age_current(lsa), + (unsigned long)ntohl(lsa->header->seqnum)); } } -void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa) +void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_array, bool use_json) { uint8_t *start, *end, *current; char byte[4]; @@ -444,6 +512,9 @@ void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa) start = (uint8_t *)lsa->header; end = (uint8_t *)lsa->header + ntohs(lsa->header->length); + if (use_json) + return; + vty_out(vty, "\n"); vty_out(vty, "%s:\n", lsa->name); @@ -458,12 +529,15 @@ void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa) } vty_out(vty, "\n\n"); + return; } -void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa) +void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_array, bool use_json) { char adv_router[64], id[64]; + json_object *json_obj; assert(lsa && lsa->header); @@ -471,30 +545,56 @@ void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa) inet_ntop(AF_INET, &lsa->header->adv_router, adv_router, sizeof(adv_router)); - vty_out(vty, "\n"); - vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa), - ospf6_lstype_name(lsa->header->type)); - vty_out(vty, "Link State ID: %s\n", id); - vty_out(vty, "Advertising Router: %s\n", adv_router); - vty_out(vty, "LS Sequence Number: %#010lx\n", - (unsigned long)ntohl(lsa->header->seqnum)); - vty_out(vty, "CheckSum: %#06hx Length: %hu\n", - ntohs(lsa->header->checksum), ntohs(lsa->header->length)); - vty_out(vty, "Flag: %x \n", lsa->flag); - vty_out(vty, "Lock: %d \n", lsa->lock); - vty_out(vty, "ReTx Count: %d\n", lsa->retrans_count); - vty_out(vty, "Threads: Expire: 0x%p, Refresh: 0x%p \n", - (void *)lsa->expire, (void *)lsa->refresh); - vty_out(vty, "\n"); + if (use_json) { + json_obj = json_object_new_object(); + json_object_int_add(json_obj, "age", + ospf6_lsa_age_current(lsa)); + json_object_string_add(json_obj, "type", + ospf6_lstype_name(lsa->header->type)); + json_object_string_add(json_obj, "linkStateId", id); + json_object_string_add(json_obj, "advertisingRouter", + adv_router); + json_object_int_add(json_obj, "lsSequenceNumber", + (unsigned long)ntohl(lsa->header->seqnum)); + json_object_int_add(json_obj, "checksum", + ntohs(lsa->header->checksum)); + json_object_int_add(json_obj, "length", + ntohs(lsa->header->length)); + json_object_int_add(json_obj, "flag", lsa->flag); + json_object_int_add(json_obj, "lock", lsa->lock); + json_object_int_add(json_obj, "reTxCount", lsa->retrans_count); + + /* Threads Data not added */ + json_object_array_add(json_array, json_obj); + } else { + vty_out(vty, "\n"); + vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa), + ospf6_lstype_name(lsa->header->type)); + vty_out(vty, "Link State ID: %s\n", id); + vty_out(vty, "Advertising Router: %s\n", adv_router); + vty_out(vty, "LS Sequence Number: %#010lx\n", + (unsigned long)ntohl(lsa->header->seqnum)); + vty_out(vty, "CheckSum: %#06hx Length: %hu\n", + ntohs(lsa->header->checksum), + ntohs(lsa->header->length)); + vty_out(vty, "Flag: %x \n", lsa->flag); + vty_out(vty, "Lock: %d \n", lsa->lock); + vty_out(vty, "ReTx Count: %d\n", lsa->retrans_count); + vty_out(vty, "Threads: Expire: 0x%p, Refresh: 0x%p \n", + (void *)lsa->expire, (void *)lsa->refresh); + vty_out(vty, "\n"); + } return; } -void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) +void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json_array, bool use_json) { char adv_router[64], id[64]; const struct ospf6_lsa_handler *handler; struct timeval now, res; char duration[64]; + json_object *json_obj = NULL; assert(lsa && lsa->header); @@ -505,27 +605,47 @@ void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa) monotime(&now); timersub(&now, &lsa->installed, &res); timerstring(&res, duration, sizeof(duration)); - - vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa), - ospf6_lstype_name(lsa->header->type)); - vty_out(vty, "Link State ID: %s\n", id); - vty_out(vty, "Advertising Router: %s\n", adv_router); - vty_out(vty, "LS Sequence Number: %#010lx\n", - (unsigned long)ntohl(lsa->header->seqnum)); - vty_out(vty, "CheckSum: %#06hx Length: %hu\n", - ntohs(lsa->header->checksum), ntohs(lsa->header->length)); - vty_out(vty, "Duration: %s\n", duration); + if (use_json) { + json_obj = json_object_new_object(); + json_object_int_add(json_obj, "age", + ospf6_lsa_age_current(lsa)); + json_object_string_add(json_obj, "type", + ospf6_lstype_name(lsa->header->type)); + json_object_string_add(json_obj, "advertisingRouter", + adv_router); + json_object_int_add(json_obj, "lsSequenceNumber", + (unsigned long)ntohl(lsa->header->seqnum)); + json_object_int_add(json_obj, "checkSum", + ntohs(lsa->header->checksum)); + json_object_int_add(json_obj, "length", + ntohs(lsa->header->length)); + json_object_string_add(json_obj, "duration", duration); + } else { + vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa), + ospf6_lstype_name(lsa->header->type)); + vty_out(vty, "Link State ID: %s\n", id); + vty_out(vty, "Advertising Router: %s\n", adv_router); + vty_out(vty, "LS Sequence Number: %#010lx\n", + (unsigned long)ntohl(lsa->header->seqnum)); + vty_out(vty, "CheckSum: %#06hx Length: %hu\n", + ntohs(lsa->header->checksum), + ntohs(lsa->header->length)); + vty_out(vty, "Duration: %s\n", duration); + } handler = ospf6_get_lsa_handler(lsa->header->type); if (handler->lh_show != NULL) - handler->lh_show(vty, lsa); + handler->lh_show(vty, lsa, json_obj, use_json); else { assert(unknown_handler.lh_show != NULL); - unknown_handler.lh_show(vty, lsa); + unknown_handler.lh_show(vty, lsa, json_obj, use_json); } - vty_out(vty, "\n"); + if (use_json) + json_object_array_add(json_array, json_obj); + else + vty_out(vty, "\n"); } /* OSPFv3 LSA creation/deletion function */ diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index 814e276796..7fa9c5fe40 100644 --- a/ospf6d/ospf6_lsa.h +++ b/ospf6d/ospf6_lsa.h @@ -21,6 +21,7 @@ #ifndef OSPF6_LSA_H #define OSPF6_LSA_H #include "ospf6_top.h" +#include "lib/json.h" /* Debug option */ #define OSPF6_LSA_DEBUG 0x01 @@ -141,9 +142,10 @@ struct ospf6_lsa_handler { uint16_t lh_type; /* host byte order */ const char *lh_name; const char *lh_short_name; - int (*lh_show)(struct vty *, struct ospf6_lsa *); - char *(*lh_get_prefix_str)(struct ospf6_lsa *, char *buf, - int buflen, int pos); + int (*lh_show)(struct vty *, struct ospf6_lsa *, json_object *json_obj, + bool use_json); + char *(*lh_get_prefix_str)(struct ospf6_lsa *, char *buf, int buflen, + int pos); uint8_t lh_debug; }; @@ -206,10 +208,14 @@ extern char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size); extern void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header); extern void ospf6_lsa_header_print(struct ospf6_lsa *lsa); extern void ospf6_lsa_show_summary_header(struct vty *vty); -extern void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa); -extern void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa); -extern void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa); -extern void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa); +extern void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json, bool use_json); +extern void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json, bool use_json); +extern void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json, bool use_json); +extern void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa, + json_object *json, bool use_json); extern struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header); extern struct ospf6_lsa * diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c index c136c558cb..9636e1a230 100644 --- a/ospf6d/ospf6_lsdb.c +++ b/ospf6d/ospf6_lsdb.c @@ -346,55 +346,6 @@ int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb) return (reschedule); } -void ospf6_lsdb_show(struct vty *vty, enum ospf_lsdb_show_level level, - uint16_t *type, uint32_t *id, uint32_t *adv_router, - struct ospf6_lsdb *lsdb) -{ - struct ospf6_lsa *lsa; - const struct route_node *end = NULL; - void (*showfunc)(struct vty *, struct ospf6_lsa *) = NULL; - - switch (level) { - case OSPF6_LSDB_SHOW_LEVEL_DETAIL: - showfunc = ospf6_lsa_show; - break; - case OSPF6_LSDB_SHOW_LEVEL_INTERNAL: - showfunc = ospf6_lsa_show_internal; - break; - case OSPF6_LSDB_SHOW_LEVEL_DUMP: - showfunc = ospf6_lsa_show_dump; - break; - case OSPF6_LSDB_SHOW_LEVEL_NORMAL: - default: - showfunc = ospf6_lsa_show_summary; - } - - if (type && id && adv_router) { - lsa = ospf6_lsdb_lookup(*type, *id, *adv_router, lsdb); - if (lsa) { - if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) - ospf6_lsa_show(vty, lsa); - else - (*showfunc)(vty, lsa); - } - return; - } - - if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) - ospf6_lsa_show_summary_header(vty); - - end = ospf6_lsdb_head(lsdb, !!type + !!(type && adv_router), - type ? *type : 0, adv_router ? *adv_router : 0, - &lsa); - while (lsa) { - if ((!adv_router || lsa->header->adv_router == *adv_router) - && (!id || lsa->header->id == *id)) - (*showfunc)(vty, lsa); - - lsa = ospf6_lsdb_next(end, lsa); - } -} - uint32_t ospf6_new_ls_id(uint16_t type, uint32_t adv_router, struct ospf6_lsdb *lsdb) { diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h index 457e3dc4e4..7a62c46b02 100644 --- a/ospf6d/ospf6_lsdb.h +++ b/ospf6d/ospf6_lsdb.h @@ -92,7 +92,8 @@ enum ospf_lsdb_show_level { extern void ospf6_lsdb_show(struct vty *vty, enum ospf_lsdb_show_level level, uint16_t *type, uint32_t *id, uint32_t *adv_router, - struct ospf6_lsdb *lsdb); + struct ospf6_lsdb *lsdb, json_object *json, + bool use_json); extern uint32_t ospf6_new_ls_id(uint16_t type, uint32_t adv_router, struct ospf6_lsdb *lsdb); diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 60c208437b..b77f968179 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -163,6 +163,10 @@ const char *const ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] = { "??", "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) { @@ -1030,7 +1034,8 @@ void ospf6_route_table_delete(struct ospf6_route_table *table) /* 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]; @@ -1038,6 +1043,9 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route) 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"); @@ -1058,34 +1066,74 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route) 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"); @@ -1103,84 +1151,177 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route) 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; @@ -1203,111 +1344,164 @@ static void ospf6_route_show_table_summary(struct vty *vty, } 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; @@ -1317,10 +1511,15 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc, 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; @@ -1363,14 +1562,24 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc, 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; } @@ -1378,20 +1587,36 @@ int ospf6_route_table_show(struct vty *vty, int argc_start, int argc, 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; } @@ -1439,7 +1664,7 @@ static void ospf6_linkstate_show_table_exact(struct vty *vty, 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) @@ -1457,7 +1682,7 @@ static void ospf6_linkstate_show_table(struct vty *vty, int detail, 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); diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index e2118003d5..a791a82cd4 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -23,6 +23,7 @@ #include "command.h" #include "zclient.h" +#include "lib/json.h" #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) \ (0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? ospf6_path_type_substr[(x)] \ : 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_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_show(struct vty *vty, struct ospf6_route *route); -extern void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route); +extern void ospf6_route_show(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 **, - 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, struct cmd_token **argv, struct ospf6_route_table *table); diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index 70771c6060..f94252991c 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -432,9 +432,8 @@ void ospf6_spf_table_finish(struct ospf6_route_table *result_table) } } -static const char *const ospf6_spf_reason_str[] = { - "R+", "R-", "N+", "N-", "L+", "L-", "R*", "N*", -}; +static const char *const ospf6_spf_reason_str[] = {"R+", "R-", "N+", "N-", "L+", + "L-", "R*", "N*", "C"}; void ospf6_spf_reason_string(unsigned int reason, char *buf, int size) { @@ -655,7 +654,7 @@ static int ospf6_spf_calculation_thread(struct thread *t) (long long)runtime.tv_usec); zlog_info( - "SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, Reason: %s\n", + "SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, Reason: %s", areas_processed, (long long)runtime.tv_sec, (long long)runtime.tv_usec, rbuf); diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h index 853ce4de07..253888d8ce 100644 --- a/ospf6d/ospf6_spf.h +++ b/ospf6d/ospf6_spf.h @@ -88,6 +88,7 @@ struct ospf6_vertex { #define OSPF6_SPF_FLAGS_LINK_LSA_REMOVED (1 << 5) #define OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED (1 << 6) #define OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED (1 << 7) +#define OSPF6_SPF_FLAGS_CONFIG_CHANGE (1 << 8) static inline void ospf6_set_spf_reason(struct ospf6 *ospf, unsigned int reason) { diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 7b4ed84d53..3f72ec828e 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -51,6 +51,7 @@ #include "ospf6_intra.h" #include "ospf6_spf.h" #include "ospf6d.h" +#include "lib/json.h" DEFINE_QOBJ_TYPE(ospf6) @@ -267,6 +268,8 @@ static struct ospf6 *ospf6_create(const char *name) o->distance_table = route_table_init(); o->fd = -1; + o->max_multipath = MULTIPATH_NUM; + QOBJ_REG(o, ospf6); /* Make ospf protocol socket. */ @@ -718,39 +721,6 @@ DEFUN (no_ospf6_distance_ospf6, return CMD_SUCCESS; } -#if 0 -DEFUN (ospf6_distance_source, - ospf6_distance_source_cmd, - "distance (1-255) X:X::X:X/M [WORD]", - "Administrative distance\n" - "Distance value\n" - "IP source prefix\n" - "Access list name\n") -{ - VTY_DECLVAR_CONTEXT(ospf6, o); - char *alname = (argc == 4) ? argv[3]->arg : NULL; - ospf6_distance_set (vty, o, argv[1]->arg, argv[2]->arg, alname); - - return CMD_SUCCESS; -} - -DEFUN (no_ospf6_distance_source, - no_ospf6_distance_source_cmd, - "no distance (1-255) X:X::X:X/M [WORD]", - NO_STR - "Administrative distance\n" - "Distance value\n" - "IP source prefix\n" - "Access list name\n") -{ - VTY_DECLVAR_CONTEXT(ospf6, o); - char *alname = (argc == 5) ? argv[4]->arg : NULL; - ospf6_distance_unset (vty, o, argv[2]->arg, argv[3]->arg, alname); - - return CMD_SUCCESS; -} -#endif - DEFUN (ospf6_interface_area, ospf6_interface_area_cmd, "interface IFNAME area <A.B.C.D|(0-4294967295)>", @@ -911,54 +881,61 @@ DEFUN (no_ospf6_stub_router_admin, return CMD_SUCCESS; } -#if 0 -DEFUN (ospf6_stub_router_startup, - ospf6_stub_router_startup_cmd, - "stub-router on-startup (5-86400)", - "Make router a stub router\n" - "Advertise inability to be a transit router\n" - "Automatically advertise as stub-router on startup of OSPF6\n" - "Time (seconds) to advertise self as stub-router\n") +/* Restart OSPF SPF algorithm*/ +static void ospf6_restart_spf(struct ospf6 *ospf6) { - return CMD_SUCCESS; + ospf6_route_remove_all(ospf6->route_table); + ospf6_route_remove_all(ospf6->brouter_table); + ospf6_route_remove_all(ospf6->external_table); + + /* Trigger SPF */ + ospf6_spf_schedule(ospf6, OSPF6_SPF_FLAGS_CONFIG_CHANGE); } -DEFUN (no_ospf6_stub_router_startup, - no_ospf6_stub_router_startup_cmd, - "no stub-router on-startup", - NO_STR - "Make router a stub router\n" - "Advertise inability to be a transit router\n" - "Automatically advertise as stub-router on startup of OSPF6\n" - "Time (seconds) to advertise self as stub-router\n") +/* Set the max paths */ +static void ospf6_maxpath_set(struct ospf6 *ospf6, uint16_t paths) { - return CMD_SUCCESS; + if (ospf6->max_multipath == paths) + return; + + ospf6->max_multipath = paths; + + /* Send deletion to zebra to delete all + * ospf specific routes and reinitiate + * SPF to reflect the new max multipath. + */ + ospf6_restart_spf(ospf6); } -DEFUN (ospf6_stub_router_shutdown, - ospf6_stub_router_shutdown_cmd, - "stub-router on-shutdown (5-86400)", - "Make router a stub router\n" - "Advertise inability to be a transit router\n" - "Automatically advertise as stub-router before shutdown\n" - "Time (seconds) to advertise self as stub-router\n") +/* Ospf Maximum-paths config support */ +DEFUN(ospf6_max_multipath, + ospf6_max_multipath_cmd, + "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM), + "Max no of multiple paths for ECMP support\n" + "Number of paths\n") { - return CMD_SUCCESS; + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + int idx_number = 1; + int maximum_paths = strtol(argv[idx_number]->arg, NULL, 10); + + ospf6_maxpath_set(ospf6, maximum_paths); + + return CMD_SUCCESS; } -DEFUN (no_ospf6_stub_router_shutdown, - no_ospf6_stub_router_shutdown_cmd, - "no stub-router on-shutdown", - NO_STR - "Make router a stub router\n" - "Advertise inability to be a transit router\n" - "Automatically advertise as stub-router before shutdown\n" - "Time (seconds) to advertise self as stub-router\n") +DEFUN(no_ospf6_max_multipath, + no_ospf6_max_multipath_cmd, + "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM)"]", + NO_STR + "Max no of multiple paths for ECMP support\n" + "Number of paths\n") { - return CMD_SUCCESS; -} -#endif + VTY_DECLVAR_CONTEXT(ospf6, ospf6); + ospf6_maxpath_set(ospf6, MULTIPATH_NUM); + + return CMD_SUCCESS; +} static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json, bool use_json) @@ -998,6 +975,7 @@ static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json, json_object_int_add(json, "holdTimeMultiplier", o->spf_hold_multiplier); + json_object_int_add(json, "maximumPaths", o->max_multipath); if (o->ts_spf.tv_sec || o->ts_spf.tv_usec) { timersub(&now, &o->ts_spf, &result); @@ -1080,6 +1058,7 @@ static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json, vty_out(vty, " LSA minimum arrival %d msecs\n", o->lsa_minarrival); + vty_out(vty, " Maximum-paths %u\n", o->max_multipath); /* Show SPF parameters */ vty_out(vty, @@ -1165,7 +1144,7 @@ DEFUN(show_ipv6_ospf6, DEFUN (show_ipv6_ospf6_route, 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 IP6_STR OSPF6_STR @@ -1177,41 +1156,44 @@ DEFUN (show_ipv6_ospf6_route, "Specify IPv6 address\n" "Specify IPv6 prefix\n" "Detailed information\n" - "Summary of route table\n") + "Summary of route table\n" + JSON_STR) { struct ospf6 *ospf6; + bool uj = use_json(argc, argv); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); 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; } DEFUN (show_ipv6_ospf6_route_match, 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 IP6_STR OSPF6_STR ROUTE_STR "Specify IPv6 prefix\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; + bool uj = use_json(argc, argv); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); 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; } DEFUN (show_ipv6_ospf6_route_match_detail, 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 IP6_STR OSPF6_STR @@ -1219,21 +1201,22 @@ DEFUN (show_ipv6_ospf6_route_match_detail, "Specify IPv6 prefix\n" "Display routes which match the specified route\n" "Detailed information\n" - ) + JSON_STR) { struct ospf6 *ospf6; + bool uj = use_json(argc, argv); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); 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; } DEFUN (show_ipv6_ospf6_route_type_detail, 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 IP6_STR OSPF6_STR @@ -1243,14 +1226,15 @@ DEFUN (show_ipv6_ospf6_route_type_detail, "Display Type-1 External routes\n" "Display Type-2 External routes\n" "Detailed information\n" - ) + JSON_STR) { struct ospf6 *ospf6; + bool uj = use_json(argc, argv); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); 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; } @@ -1333,6 +1317,11 @@ static int config_write_ospf6(struct vty *vty) vty_out(vty, " timers lsa min-arrival %d\n", ospf6->lsa_minarrival); + /* ECMP max path config */ + if (ospf6->max_multipath != MULTIPATH_NUM) + vty_out(vty, " maximum-paths %d\n", + ospf6->max_multipath); + ospf6_stub_router_config_write(vty, ospf6); ospf6_redistribute_config_write(vty, ospf6); ospf6_area_config_write(vty, ospf6); @@ -1390,20 +1379,13 @@ void ospf6_top_init(void) install_element(OSPF6_NODE, &no_ospf6_interface_area_cmd); install_element(OSPF6_NODE, &ospf6_stub_router_admin_cmd); install_element(OSPF6_NODE, &no_ospf6_stub_router_admin_cmd); -/* For a later time */ -#if 0 - install_element (OSPF6_NODE, &ospf6_stub_router_startup_cmd); - install_element (OSPF6_NODE, &no_ospf6_stub_router_startup_cmd); - install_element (OSPF6_NODE, &ospf6_stub_router_shutdown_cmd); - install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd); -#endif + + /* maximum-paths command */ + install_element(OSPF6_NODE, &ospf6_max_multipath_cmd); + install_element(OSPF6_NODE, &no_ospf6_max_multipath_cmd); install_element(OSPF6_NODE, &ospf6_distance_cmd); install_element(OSPF6_NODE, &no_ospf6_distance_cmd); install_element(OSPF6_NODE, &ospf6_distance_ospf6_cmd); install_element(OSPF6_NODE, &no_ospf6_distance_ospf6_cmd); -#if 0 - install_element (OSPF6_NODE, &ospf6_distance_source_cmd); - install_element (OSPF6_NODE, &no_ospf6_distance_source_cmd); -#endif } diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 93e25d7599..75dff86cd7 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -127,6 +127,11 @@ struct ospf6 { * update to neighbors immediatly */ uint8_t inst_shutdown; + /* Max number of multiple paths + * to support ECMP. + */ + uint16_t max_multipath; + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(ospf6) diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 7a8027a37f..2b7072d34f 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -343,7 +343,14 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request, api.safi = SAFI_UNICAST; api.prefix = *dest; SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = MIN(nhcount, MULTIPATH_NUM); + + if (nhcount > ospf6->max_multipath) { + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + zlog_debug( + " Nexthop count is greater than configured maximum-path, hence ignore the extra nexthops"); + } + api.nexthop_num = MIN(nhcount, ospf6->max_multipath); + ospf6_route_zebra_copy_nexthops(request, api.nexthops, api.nexthop_num, api.vrf_id); SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 4b958e550f..8d9c85fd08 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -44,6 +44,7 @@ #include "ospf6_flood.h" #include "ospf6d.h" #include "ospf6_bfd.h" +#include "lib/json.h" struct route_node *route_prev(struct route_node *node) { @@ -154,53 +155,264 @@ static uint16_t parse_type_spec(int idx_lsa, int argc, struct cmd_token **argv) return type; } +void ospf6_lsdb_show(struct vty *vty, enum ospf_lsdb_show_level level, + uint16_t *type, uint32_t *id, uint32_t *adv_router, + struct ospf6_lsdb *lsdb, json_object *json_obj, + bool use_json) +{ + struct ospf6_lsa *lsa; + const struct route_node *end = NULL; + void (*showfunc)(struct vty *, struct ospf6_lsa *, json_object *, + bool) = NULL; + json_object *json_array = NULL; + + switch (level) { + case OSPF6_LSDB_SHOW_LEVEL_DETAIL: + showfunc = ospf6_lsa_show; + break; + case OSPF6_LSDB_SHOW_LEVEL_INTERNAL: + showfunc = ospf6_lsa_show_internal; + break; + case OSPF6_LSDB_SHOW_LEVEL_DUMP: + showfunc = ospf6_lsa_show_dump; + break; + case OSPF6_LSDB_SHOW_LEVEL_NORMAL: + default: + showfunc = ospf6_lsa_show_summary; + } + + if (use_json) + json_array = json_object_new_array(); + + if (type && id && adv_router) { + lsa = ospf6_lsdb_lookup(*type, *id, *adv_router, lsdb); + if (lsa) { + if (level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) + ospf6_lsa_show(vty, lsa, json_array, use_json); + else + (*showfunc)(vty, lsa, json_array, use_json); + } + + if (use_json) + json_object_object_add(json_obj, "lsa", json_array); + return; + } + + if ((level == OSPF6_LSDB_SHOW_LEVEL_NORMAL) && !use_json) + ospf6_lsa_show_summary_header(vty); + + end = ospf6_lsdb_head(lsdb, !!type + !!(type && adv_router), + type ? *type : 0, adv_router ? *adv_router : 0, + &lsa); + while (lsa) { + if ((!adv_router || lsa->header->adv_router == *adv_router) + && (!id || lsa->header->id == *id)) + (*showfunc)(vty, lsa, json_array, use_json); + lsa = ospf6_lsdb_next(end, lsa); + } + + if (use_json) + json_object_object_add(json_obj, "lsa", json_array); +} + +static void ospf6_lsdb_show_wrapper(struct vty *vty, + enum ospf_lsdb_show_level level, + uint16_t *type, uint32_t *id, + uint32_t *adv_router, bool uj, + struct ospf6 *ospf6) +{ + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + json_object *json = NULL; + json_object *json_array = NULL; + json_object *json_obj = NULL; + + if (uj) { + json = json_object_new_object(); + json_array = json_object_new_array(); + } + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + if (uj) { + json_obj = json_object_new_object(); + json_object_string_add(json_obj, "areaId", oa->name); + } else + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + ospf6_lsdb_show(vty, level, type, id, adv_router, oa->lsdb, + json_obj, uj); + if (uj) + json_object_array_add(json_array, json_obj); + } + if (uj) + json_object_object_add(json, "areaScopedLinkStateDb", + json_array); + + if (uj) + json_array = json_object_new_array(); + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + if (uj) { + json_obj = json_object_new_object(); + json_object_string_add(json_obj, "areaId", + oa->name); + json_object_string_add(json_obj, "interface", + oi->interface->name); + } else + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + ospf6_lsdb_show(vty, level, type, id, adv_router, + oi->lsdb, json_obj, uj); + if (uj) + json_object_array_add(json_array, json_obj); + } + } + if (uj) + json_object_object_add(json, "interfaceScopedLinkStateDb", + json_array); + if (uj) { + json_array = json_object_new_array(); + json_obj = json_object_new_object(); + } else + vty_out(vty, AS_LSDB_TITLE_FORMAT); + + ospf6_lsdb_show(vty, level, type, id, adv_router, o->lsdb, json_obj, + uj); + + if (uj) { + json_object_array_add(json_array, json_obj); + json_object_object_add(json, "asScopedLinkStateDb", json_array); + + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); +} + +static void ospf6_lsdb_type_show_wrapper(struct vty *vty, + enum ospf_lsdb_show_level level, + uint16_t *type, uint32_t *id, + uint32_t *adv_router, bool uj, + struct ospf6 *ospf6) +{ + struct listnode *i, *j; + struct ospf6 *o = ospf6; + struct ospf6_area *oa; + struct ospf6_interface *oi; + json_object *json = NULL; + json_object *json_array = NULL; + json_object *json_obj = NULL; + + if (uj) { + json = json_object_new_object(); + json_array = json_object_new_array(); + } + + switch (OSPF6_LSA_SCOPE(*type)) { + case OSPF6_SCOPE_AREA: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + if (uj) { + json_obj = json_object_new_object(); + json_object_string_add(json_obj, "areaId", + oa->name); + } else + vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); + + ospf6_lsdb_show(vty, level, type, id, adv_router, + oa->lsdb, json_obj, uj); + if (uj) + json_object_array_add(json_array, json_obj); + } + if (uj) + json_object_object_add(json, "areaScopedLinkStateDb", + json_array); + break; + + case OSPF6_SCOPE_LINKLOCAL: + for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) { + for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { + if (uj) { + json_obj = json_object_new_object(); + json_object_string_add( + json_obj, "areaId", oa->name); + json_object_string_add( + json_obj, "interface", + oi->interface->name); + } else + vty_out(vty, IF_LSDB_TITLE_FORMAT, + oi->interface->name, oa->name); + + ospf6_lsdb_show(vty, level, type, id, + adv_router, oi->lsdb, json_obj, + uj); + + if (uj) + json_object_array_add(json_array, + json_obj); + } + } + if (uj) + json_object_object_add( + json, "interfaceScopedLinkStateDb", json_array); + break; + + case OSPF6_SCOPE_AS: + if (uj) + json_obj = json_object_new_object(); + else + vty_out(vty, AS_LSDB_TITLE_FORMAT); + + ospf6_lsdb_show(vty, level, type, id, adv_router, o->lsdb, + json_obj, uj); + if (uj) { + json_object_array_add(json_array, json_obj); + json_object_object_add(json, "asScopedLinkStateDb", + json_array); + } + break; + + default: + assert(0); + break; + } + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } else + vty_out(vty, "\n"); +} + DEFUN (show_ipv6_ospf6_database, show_ipv6_ospf6_database_cmd, - "show ipv6 ospf6 database [<detail|dump|internal>]", + "show ipv6 ospf6 database [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR "Display Link state database\n" "Display details of LSAs\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_level = 4; int level; - struct listnode *i, *j; + bool uj = use_json(argc, argv); struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; - ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); OSPF6_CMD_CHECK_RUNNING(ospf6); level = parse_show_level(idx_level, argc, argv); - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, NULL, NULL, NULL, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, - oa->name); - ospf6_lsdb_show(vty, level, NULL, NULL, NULL, oi->lsdb); - } - } - - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, NULL, NULL, NULL, ospf6->lsdb); - - vty_out(vty, "\n"); + ospf6_lsdb_show_wrapper(vty, level, NULL, NULL, NULL, uj, ospf6); return CMD_SUCCESS; } -DEFUN (show_ipv6_ospf6_database_type, - show_ipv6_ospf6_database_type_cmd, - "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [<detail|dump|internal>]", +DEFUN (show_ipv6_ospf6_database_type, show_ipv6_ospf6_database_type_cmd, + "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -217,16 +429,14 @@ DEFUN (show_ipv6_ospf6_database_type, "Display details of LSAs\n" "Dump LSAs\n" "Display LSA's internal information\n" - ) + JSON_STR) { int idx_lsa = 4; int idx_level = 5; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint16_t type = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); @@ -235,43 +445,13 @@ DEFUN (show_ipv6_ospf6_database_type, type = parse_type_spec(idx_lsa, argc, argv); level = parse_show_level(idx_level, argc, argv); - switch (OSPF6_LSA_SCOPE(type)) { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, &type, NULL, NULL, - oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show(vty, level, &type, NULL, NULL, - oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, &type, NULL, NULL, ospf6->lsdb); - break; - - default: - assert(0); - break; - } - - vty_out(vty, "\n"); + ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL, NULL, uj, ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_id, show_ipv6_ospf6_database_id_cmd, - "show ipv6 ospf6 database <*|linkstate-id> A.B.C.D [<detail|dump|internal>]", + "show ipv6 ospf6 database <*|linkstate-id> A.B.C.D [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -281,16 +461,15 @@ DEFUN (show_ipv6_ospf6_database_id, "Specify Link state ID as IPv4 address notation\n" "Display details of LSAs\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_ipv4 = 5; int idx_level = 6; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint32_t id = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); @@ -300,30 +479,14 @@ DEFUN (show_ipv6_ospf6_database_id, inet_pton(AF_INET, argv[idx_ipv4]->arg, &id); level = parse_show_level(idx_level, argc, argv); + ospf6_lsdb_show_wrapper(vty, level, NULL, &id, NULL, uj, ospf6); - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, NULL, &id, NULL, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, - oa->name); - ospf6_lsdb_show(vty, level, NULL, &id, NULL, oi->lsdb); - } - } - - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, NULL, &id, NULL, ospf6->lsdb); - - vty_out(vty, "\n"); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_router, show_ipv6_ospf6_database_router_cmd, - "show ipv6 ospf6 database <*|adv-router> * A.B.C.D <detail|dump|internal>", + "show ipv6 ospf6 database <*|adv-router> * A.B.C.D <detail|dump|internal> [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -334,16 +497,15 @@ DEFUN (show_ipv6_ospf6_database_router, "Specify Advertising Router as IPv4 address notation\n" "Display details of LSAs\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_ipv4 = 6; int idx_level = 7; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint32_t adv_router = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); @@ -351,24 +513,7 @@ DEFUN (show_ipv6_ospf6_database_router, inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router); level = parse_show_level(idx_level, argc, argv); - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, - oa->name); - ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, - oi->lsdb); - } - } - - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, ospf6->lsdb); - - vty_out(vty, "\n"); + ospf6_lsdb_show_wrapper(vty, level, NULL, NULL, &adv_router, uj, ospf6); return CMD_SUCCESS; } @@ -408,7 +553,7 @@ DEFUN_HIDDEN (show_ipv6_ospf6_database_aggr_router, return CMD_SUCCESS; } ospf6_lsdb_show(vty, level, &type, NULL, NULL, - oa->temp_router_lsa_lsdb); + oa->temp_router_lsa_lsdb, NULL, false); /* Remove the temp cache */ ospf6_remove_temp_router_lsa(oa); } @@ -420,7 +565,7 @@ DEFUN_HIDDEN (show_ipv6_ospf6_database_aggr_router, DEFUN (show_ipv6_ospf6_database_type_id, show_ipv6_ospf6_database_type_id_cmd, - "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> linkstate-id A.B.C.D [<detail|dump|internal>]", + "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> linkstate-id A.B.C.D [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -439,18 +584,16 @@ DEFUN (show_ipv6_ospf6_database_type_id, "Display details of LSAs\n" "Dump LSAs\n" "Display LSA's internal information\n" - ) + JSON_STR) { int idx_lsa = 4; int idx_ipv4 = 6; int idx_level = 7; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint16_t type = 0; uint32_t id = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); @@ -460,42 +603,13 @@ DEFUN (show_ipv6_ospf6_database_type_id, inet_pton(AF_INET, argv[idx_ipv4]->arg, &id); level = parse_show_level(idx_level, argc, argv); - switch (OSPF6_LSA_SCOPE(type)) { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, NULL, oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, NULL, - oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, &type, &id, NULL, ospf6->lsdb); - break; - - default: - assert(0); - break; - } - - vty_out(vty, "\n"); + ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, NULL, uj, ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_router, show_ipv6_ospf6_database_type_router_cmd, - "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> <*|adv-router> A.B.C.D [<detail|dump|internal>]", + "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> <*|adv-router> A.B.C.D [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -515,18 +629,16 @@ DEFUN (show_ipv6_ospf6_database_type_router, "Display details of LSAs\n" "Dump LSAs\n" "Display LSA's internal information\n" - ) + JSON_STR) { int idx_lsa = 4; int idx_ipv4 = 6; int idx_level = 7; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint16_t type = 0; uint32_t adv_router = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); @@ -535,45 +647,15 @@ DEFUN (show_ipv6_ospf6_database_type_router, inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router); level = parse_show_level(idx_level, argc, argv); - switch (OSPF6_LSA_SCOPE(type)) { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, &type, NULL, &adv_router, - oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show(vty, level, &type, NULL, - &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, &type, NULL, &adv_router, - ospf6->lsdb); - break; - - default: - assert(0); - break; - } - - vty_out(vty, "\n"); + ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL, &adv_router, uj, + ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_id_router, show_ipv6_ospf6_database_id_router_cmd, - "show ipv6 ospf6 database * A.B.C.D A.B.C.D [<detail|dump|internal>]", + "show ipv6 ospf6 database * A.B.C.D A.B.C.D [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -584,18 +666,16 @@ DEFUN (show_ipv6_ospf6_database_id_router, "Display details of LSAs\n" "Dump LSAs\n" "Display LSA's internal information\n" - ) + JSON_STR) { int idx_ls_id = 5; int idx_adv_rtr = 6; int idx_level = 7; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint32_t id = 0; uint32_t adv_router = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); OSPF6_CMD_CHECK_RUNNING(ospf6); @@ -603,31 +683,14 @@ DEFUN (show_ipv6_ospf6_database_id_router, inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router); level = parse_show_level(idx_level, argc, argv); - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, - oa->name); - ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, - oi->lsdb); - } - } - - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, ospf6->lsdb); - - vty_out(vty, "\n"); + ospf6_lsdb_show_wrapper(vty, level, NULL, &id, &adv_router, uj, ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_adv_router_linkstate_id, show_ipv6_ospf6_database_adv_router_linkstate_id_cmd, - "show ipv6 ospf6 database adv-router A.B.C.D linkstate-id A.B.C.D [<detail|dump|internal>]", + "show ipv6 ospf6 database adv-router A.B.C.D linkstate-id A.B.C.D [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -638,18 +701,17 @@ DEFUN (show_ipv6_ospf6_database_adv_router_linkstate_id, "Specify Link state ID as IPv4 address notation\n" "Display details of LSAs\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_adv_rtr = 5; int idx_ls_id = 7; int idx_level = 8; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint32_t id = 0; uint32_t adv_router = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); @@ -658,30 +720,13 @@ DEFUN (show_ipv6_ospf6_database_adv_router_linkstate_id, inet_pton(AF_INET, argv[idx_ls_id]->arg, &id); level = parse_show_level(idx_level, argc, argv); - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, - oa->name); - ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, - oi->lsdb); - } - } - - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, NULL, &id, &adv_router, ospf6->lsdb); - - vty_out(vty, "\n"); + ospf6_lsdb_show_wrapper(vty, level, NULL, &id, &adv_router, uj, ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_id_router, show_ipv6_ospf6_database_type_id_router_cmd, - "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> A.B.C.D A.B.C.D [<dump|internal>]", + "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> A.B.C.D A.B.C.D [<dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -698,20 +743,19 @@ DEFUN (show_ipv6_ospf6_database_type_id_router, "Specify Link state ID as IPv4 address notation\n" "Specify Advertising Router as IPv4 address notation\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_lsa = 4; int idx_ls_id = 5; int idx_adv_rtr = 6; int idx_level = 7; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint16_t type = 0; uint32_t id = 0; uint32_t adv_router = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); @@ -722,45 +766,15 @@ DEFUN (show_ipv6_ospf6_database_type_id_router, inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router); level = parse_show_level(idx_level, argc, argv); - switch (OSPF6_LSA_SCOPE(type)) { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, &adv_router, - oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, - &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, &type, &id, &adv_router, - ospf6->lsdb); - break; - - default: - assert(0); - break; - } - - vty_out(vty, "\n"); + ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, &adv_router, uj, + ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id, show_ipv6_ospf6_database_type_adv_router_linkstate_id_cmd, - "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> adv-router A.B.C.D linkstate-id A.B.C.D [<dump|internal>]", + "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> adv-router A.B.C.D linkstate-id A.B.C.D [<dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -779,20 +793,19 @@ DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id, "Search by Link state ID\n" "Specify Link state ID as IPv4 address notation\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_lsa = 4; int idx_adv_rtr = 6; int idx_ls_id = 8; int idx_level = 9; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint16_t type = 0; uint32_t id = 0; uint32_t adv_router = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); @@ -803,44 +816,14 @@ DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id, inet_pton(AF_INET, argv[idx_ls_id]->arg, &id); level = parse_show_level(idx_level, argc, argv); - switch (OSPF6_LSA_SCOPE(type)) { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, &adv_router, - oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, - &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, &type, &id, &adv_router, - ospf6->lsdb); - break; - - default: - assert(0); - break; - } - - vty_out(vty, "\n"); + ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, &adv_router, uj, + ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_self_originated, show_ipv6_ospf6_database_self_originated_cmd, - "show ipv6 ospf6 database self-originated [<detail|dump|internal>]", + "show ipv6 ospf6 database self-originated [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -848,46 +831,28 @@ DEFUN (show_ipv6_ospf6_database_self_originated, "Display Self-originated LSAs\n" "Display details of LSAs\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_level = 5; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint32_t adv_router = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); OSPF6_CMD_CHECK_RUNNING(ospf6); level = parse_show_level(idx_level, argc, argv); adv_router = ospf6->router_id; - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, oa->lsdb); - } - - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, oi->interface->name, - oa->name); - ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, - oi->lsdb); - } - } - - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, NULL, NULL, &adv_router, ospf6->lsdb); - - vty_out(vty, "\n"); + ospf6_lsdb_show_wrapper(vty, level, NULL, NULL, &adv_router, uj, ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_self_originated, show_ipv6_ospf6_database_type_self_originated_cmd, - "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> self-originated [<detail|dump|internal>]", + "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> self-originated [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -904,17 +869,16 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated, "Display Self-originated LSAs\n" "Display details of LSAs\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_lsa = 4; int idx_level = 6; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint16_t type = 0; uint32_t adv_router = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); OSPF6_CMD_CHECK_RUNNING(ospf6); @@ -923,44 +887,14 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated, adv_router = ospf6->router_id; - switch (OSPF6_LSA_SCOPE(type)) { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, &type, NULL, &adv_router, - oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show(vty, level, &type, NULL, - &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, &type, NULL, &adv_router, - ospf6->lsdb); - break; - - default: - assert(0); - break; - } - - vty_out(vty, "\n"); + ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL, &adv_router, uj, + ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd, - "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> self-originated linkstate-id A.B.C.D [<detail|dump|internal>]", + "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> self-originated linkstate-id A.B.C.D [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -979,19 +913,18 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, "Specify Link state ID as IPv4 address notation\n" "Display details of LSAs\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_lsa = 4; int idx_ls_id = 7; int idx_level = 8; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint16_t type = 0; uint32_t adv_router = 0; uint32_t id = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); OSPF6_CMD_CHECK_RUNNING(ospf6); @@ -1000,44 +933,14 @@ DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id, level = parse_show_level(idx_level, argc, argv); adv_router = ospf6->router_id; - switch (OSPF6_LSA_SCOPE(type)) { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, &adv_router, - oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, - &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, &type, &id, &adv_router, - ospf6->lsdb); - break; - - default: - assert(0); - break; - } - - vty_out(vty, "\n"); + ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, &adv_router, uj, + ospf6); return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_database_type_id_self_originated, show_ipv6_ospf6_database_type_id_self_originated_cmd, - "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> A.B.C.D self-originated [<detail|dump|internal>]", + "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> A.B.C.D self-originated [<detail|dump|internal>] [json]", SHOW_STR IPV6_STR OSPF6_STR @@ -1055,19 +958,18 @@ DEFUN (show_ipv6_ospf6_database_type_id_self_originated, "Display Self-originated LSAs\n" "Display details of LSAs\n" "Dump LSAs\n" - "Display LSA's internal information\n") + "Display LSA's internal information\n" + JSON_STR) { int idx_lsa = 4; int idx_ls_id = 5; int idx_level = 7; int level; - struct listnode *i, *j; - struct ospf6 *ospf6; - struct ospf6_area *oa; - struct ospf6_interface *oi; uint16_t type = 0; uint32_t adv_router = 0; uint32_t id = 0; + bool uj = use_json(argc, argv); + struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); OSPF6_CMD_CHECK_RUNNING(ospf6); @@ -1076,38 +978,8 @@ DEFUN (show_ipv6_ospf6_database_type_id_self_originated, level = parse_show_level(idx_level, argc, argv); adv_router = ospf6->router_id; - switch (OSPF6_LSA_SCOPE(type)) { - case OSPF6_SCOPE_AREA: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - vty_out(vty, AREA_LSDB_TITLE_FORMAT, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, &adv_router, - oa->lsdb); - } - break; - - case OSPF6_SCOPE_LINKLOCAL: - for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) { - for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) { - vty_out(vty, IF_LSDB_TITLE_FORMAT, - oi->interface->name, oa->name); - ospf6_lsdb_show(vty, level, &type, &id, - &adv_router, oi->lsdb); - } - } - break; - - case OSPF6_SCOPE_AS: - vty_out(vty, AS_LSDB_TITLE_FORMAT); - ospf6_lsdb_show(vty, level, &type, &id, &adv_router, - ospf6->lsdb); - break; - - default: - assert(0); - break; - } - - vty_out(vty, "\n"); + ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, &adv_router, uj, + ospf6); return CMD_SUCCESS; } @@ -1134,7 +1006,7 @@ DEFUN (show_ipv6_ospf6_border_routers, if (strmatch(argv[idx_ipv4]->text, "detail")) { for (ro = ospf6_route_head(ospf6->brouter_table); ro; ro = ospf6_route_next(ro)) - ospf6_route_show_detail(vty, ro); + ospf6_route_show_detail(vty, ro, NULL, false); } else { inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router); @@ -1147,7 +1019,7 @@ DEFUN (show_ipv6_ospf6_border_routers, return CMD_SUCCESS; } - ospf6_route_show_detail(vty, ro); + ospf6_route_show_detail(vty, ro, NULL, false); return CMD_SUCCESS; } } else { |
