diff options
Diffstat (limited to 'zebra/zebra_vty.c')
| -rw-r--r-- | zebra/zebra_vty.c | 427 |
1 files changed, 323 insertions, 104 deletions
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 6561ac95fa..8ed8abe304 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -630,8 +630,7 @@ static void show_route_nexthop_helper(struct vty *vty, case NEXTHOP_TYPE_IFINDEX: vty_out(vty, " is directly connected, %s", - ifindex2ifname(nexthop->ifindex, - nexthop->vrf_id)); + ifindex2ifname(nexthop->ifindex, nexthop->vrf_id)); break; case NEXTHOP_TYPE_BLACKHOLE: vty_out(vty, " unreachable"); @@ -703,8 +702,10 @@ static void show_route_nexthop_helper(struct vty *vty, seg6local_context2str(buf, sizeof(buf), &nexthop->nh_srv6->seg6local_ctx, nexthop->nh_srv6->seg6local_action); - vty_out(vty, ", seg6local %s %s", seg6local_action2str( - nexthop->nh_srv6->seg6local_action), buf); + vty_out(vty, ", seg6local %s %s", + seg6local_action2str( + nexthop->nh_srv6->seg6local_action), + buf); inet_ntop(AF_INET6, &nexthop->nh_srv6->seg6_segs, buf, sizeof(buf)); @@ -722,6 +723,7 @@ static void show_route_nexthop_helper(struct vty *vty, } } + /* * Render a nexthop into a json object; the caller allocates and owns * the json object memory. @@ -806,9 +808,8 @@ static void show_nexthop_json_helper(json_object *json_nexthop, json_nexthop, "reject"); break; case BLACKHOLE_ADMINPROHIB: - json_object_boolean_true_add( - json_nexthop, - "admin-prohibited"); + json_object_boolean_true_add(json_nexthop, + "adminProhibited"); break; case BLACKHOLE_NULL: json_object_boolean_true_add( @@ -827,7 +828,7 @@ static void show_nexthop_json_helper(json_object *json_nexthop, if (nexthop->rparent) json_object_boolean_true_add(json_nexthop, "resolver"); - if (nexthop->vrf_id != re->vrf_id) + if ((re == NULL || (nexthop->vrf_id != re->vrf_id))) json_object_string_add(json_nexthop, "vrf", vrf_id_to_name(nexthop->vrf_id)); @@ -840,8 +841,7 @@ static void show_nexthop_json_helper(json_object *json_nexthop, "active"); if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) - json_object_boolean_true_add(json_nexthop, - "onLink"); + json_object_boolean_true_add(json_nexthop, "onLink"); if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN)) json_object_boolean_true_add(json_nexthop, "linkDown"); @@ -1370,7 +1370,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, DEFPY (show_ip_nht, show_ip_nht_cmd, - "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib]", + "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib] [json]", SHOW_STR IP_STR IP6_STR @@ -1382,23 +1382,48 @@ DEFPY (show_ip_nht, "IPv4 Address\n" "IPv6 Address\n" VRF_ALL_CMD_HELP_STR - "Show Multicast (MRIB) NHT state\n") + "Show Multicast (MRIB) NHT state\n" + JSON_STR) { afi_t afi = ipv4 ? AFI_IP : AFI_IP6; vrf_id_t vrf_id = VRF_DEFAULT; struct prefix prefix, *p = NULL; safi_t safi = mrib ? SAFI_MULTICAST : SAFI_UNICAST; + bool uj = use_json(argc, argv); + json_object *json = NULL; + json_object *json_vrf = NULL; + json_object *json_nexthop = NULL; + + if (uj) + json = json_object_new_object(); if (vrf_all) { struct vrf *vrf; struct zebra_vrf *zvrf; - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if ((zvrf = vrf->info) != NULL) { - vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); + if (uj) { + json_vrf = json_object_new_object(); + json_nexthop = json_object_new_object(); + json_object_object_add(json, + zvrf_name(zvrf), + json_vrf); + json_object_object_add(json_vrf, + "nexthops", + json_nexthop); + } else { + vty_out(vty, "\nVRF %s:\n", + zvrf_name(zvrf)); + } zebra_print_rnh_table(zvrf_id(zvrf), afi, safi, - vty, NULL); + vty, NULL, json_nexthop); } + } + + if (uj) + vty_json(vty, json); + return CMD_SUCCESS; } if (vrf_name) @@ -1407,11 +1432,29 @@ DEFPY (show_ip_nht, memset(&prefix, 0, sizeof(prefix)); if (addr) { p = sockunion2hostprefix(addr, &prefix); - if (!p) + if (!p) { + if (uj) + json_object_free(json); return CMD_WARNING; + } } - zebra_print_rnh_table(vrf_id, afi, safi, vty, p); + if (uj) { + json_vrf = json_object_new_object(); + json_nexthop = json_object_new_object(); + if (vrf_name) + json_object_object_add(json, vrf_name, json_vrf); + else + json_object_object_add(json, "default", json_vrf); + + json_object_object_add(json_vrf, "nexthops", json_nexthop); + } + + zebra_print_rnh_table(vrf_id, afi, safi, vty, p, json_nexthop); + + if (uj) + vty_json(vty, json); + return CMD_SUCCESS; } @@ -1436,125 +1479,264 @@ DEFUN (ip_nht_default_route, return CMD_SUCCESS; } -static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe) +static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe, + json_object *json_nhe_hdr) { struct nexthop *nexthop = NULL; struct nhg_connected *rb_node_dep = NULL; struct nexthop_group *backup_nhg; char up_str[MONOTIME_STRLEN]; char time_left[MONOTIME_STRLEN]; + json_object *json_dependants = NULL; + json_object *json_depends = NULL; + json_object *json_nexthop_array = NULL; + json_object *json_nexthops = NULL; + json_object *json = NULL; + json_object *json_backup_nexthop_array = NULL; + json_object *json_backup_nexthops = NULL; + uptime2str(nhe->uptime, up_str, sizeof(up_str)); - vty_out(vty, "ID: %u (%s)\n", nhe->id, zebra_route_string(nhe->type)); - vty_out(vty, " RefCnt: %u", nhe->refcnt); - if (thread_is_scheduled(nhe->timer)) - vty_out(vty, " Time to Deletion: %s", - thread_timer_to_hhmmss(time_left, sizeof(time_left), - nhe->timer)); - vty_out(vty, "\n"); + if (json_nhe_hdr) + json = json_object_new_object(); - vty_out(vty, " Uptime: %s\n", up_str); - vty_out(vty, " VRF: %s\n", vrf_id_to_name(nhe->vrf_id)); + if (json) { + json_object_string_add(json, "type", + zebra_route_string(nhe->type)); + json_object_int_add(json, "refCount", nhe->refcnt); + if (thread_is_scheduled(nhe->timer)) + json_object_string_add( + json, "timeToDeletion", + thread_timer_to_hhmmss(time_left, + sizeof(time_left), + nhe->timer)); + json_object_string_add(json, "uptime", up_str); + json_object_string_add(json, "vrf", + vrf_id_to_name(nhe->vrf_id)); + } else { + vty_out(vty, "ID: %u (%s)\n", nhe->id, + zebra_route_string(nhe->type)); + vty_out(vty, " RefCnt: %u", nhe->refcnt); + if (thread_is_scheduled(nhe->timer)) + vty_out(vty, " Time to Deletion: %s", + thread_timer_to_hhmmss(time_left, + sizeof(time_left), + nhe->timer)); + vty_out(vty, "\n"); + + vty_out(vty, " Uptime: %s\n", up_str); + vty_out(vty, " VRF: %s\n", vrf_id_to_name(nhe->vrf_id)); + } if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) { - vty_out(vty, " Valid"); - if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)) - vty_out(vty, ", Installed"); - vty_out(vty, "\n"); + if (json) + json_object_boolean_true_add(json, "valid"); + else + vty_out(vty, " Valid"); + + if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)) { + if (json) + json_object_boolean_true_add(json, "installed"); + else + vty_out(vty, ", Installed"); + } + if (!json) + vty_out(vty, "\n"); + } + if (nhe->ifp) { + if (json) + json_object_int_add(json, "interfaceIndex", + nhe->ifp->ifindex); + else + vty_out(vty, " Interface Index: %d\n", + nhe->ifp->ifindex); } - if (nhe->ifp) - vty_out(vty, " Interface Index: %d\n", nhe->ifp->ifindex); if (!zebra_nhg_depends_is_empty(nhe)) { - vty_out(vty, " Depends:"); + if (json) + json_depends = json_object_new_array(); + else + vty_out(vty, " Depends:"); frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) { - vty_out(vty, " (%u)", rb_node_dep->nhe->id); + if (json_depends) + json_object_array_add( + json_depends, + json_object_new_int( + rb_node_dep->nhe->id)); + else + vty_out(vty, " (%u)", rb_node_dep->nhe->id); } - vty_out(vty, "\n"); + if (!json_depends) + vty_out(vty, "\n"); + else + json_object_object_add(json, "depends", json_depends); } /* Output nexthops */ - for (ALL_NEXTHOPS(nhe->nhg, nexthop)) { - if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out(vty, " "); - else - /* Make recursive nexthops a bit more clear */ - vty_out(vty, " "); + if (json) + json_nexthop_array = json_object_new_array(); - show_route_nexthop_helper(vty, NULL, nexthop); + + for (ALL_NEXTHOPS(nhe->nhg, nexthop)) { + if (json_nexthop_array) { + json_nexthops = json_object_new_object(); + show_nexthop_json_helper(json_nexthops, nexthop, NULL); + } else { + if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + vty_out(vty, " "); + else + /* Make recursive nexthops a bit more clear */ + vty_out(vty, " "); + show_route_nexthop_helper(vty, NULL, nexthop); + } if (nhe->backup_info == NULL || nhe->backup_info->nhe == NULL) { if (CHECK_FLAG(nexthop->flags, - NEXTHOP_FLAG_HAS_BACKUP)) - vty_out(vty, " [backup %d]", - nexthop->backup_idx[0]); + NEXTHOP_FLAG_HAS_BACKUP)) { + if (json) + json_object_int_add( + json_nexthops, "backup", + nexthop->backup_idx[0]); + else + vty_out(vty, " [backup %d]", + nexthop->backup_idx[0]); + } + + if (!json) + vty_out(vty, "\n"); + else + json_object_array_add(json_nexthop_array, + json_nexthops); - vty_out(vty, "\n"); continue; } - /* TODO -- print more useful backup info */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - int i; - - vty_out(vty, "[backup"); - for (i = 0; i < nexthop->backup_num; i++) - vty_out(vty, " %d", nexthop->backup_idx[i]); - - vty_out(vty, "]"); + if (!json) { + /* TODO -- print more useful backup info */ + if (CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_HAS_BACKUP)) { + int i; + + vty_out(vty, "[backup"); + for (i = 0; i < nexthop->backup_num; i++) + vty_out(vty, " %d", + nexthop->backup_idx[i]); + vty_out(vty, "]"); + } + vty_out(vty, "\n"); + } else { + json_object_array_add(json_nexthop_array, + json_nexthops); } - - vty_out(vty, "\n"); } + if (json) + json_object_object_add(json, "nexthops", json_nexthop_array); + /* Output backup nexthops (if any) */ backup_nhg = zebra_nhg_get_backup_nhg(nhe); if (backup_nhg) { - vty_out(vty, " Backups:\n"); + if (json) + json_backup_nexthop_array = json_object_new_array(); + else + vty_out(vty, " Backups:\n"); for (ALL_NEXTHOPS_PTR(backup_nhg, nexthop)) { - if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out(vty, " "); - else - /* Make recursive nexthops a bit more clear */ - vty_out(vty, " "); + if (json_backup_nexthop_array) { + json_backup_nexthops = json_object_new_object(); + show_nexthop_json_helper(json_backup_nexthops, + nexthop, NULL); + json_object_array_add(json_backup_nexthop_array, + json_backup_nexthops); + } else { - show_route_nexthop_helper(vty, NULL, nexthop); - vty_out(vty, "\n"); + if (!CHECK_FLAG(nexthop->flags, + NEXTHOP_FLAG_RECURSIVE)) + vty_out(vty, " "); + else + /* Make recursive nexthops a bit more + * clear + */ + vty_out(vty, " "); + show_route_nexthop_helper(vty, NULL, nexthop); + vty_out(vty, "\n"); + } } + + if (json) + json_object_object_add(json, "backupNexthops", + json_backup_nexthop_array); } if (!zebra_nhg_dependents_is_empty(nhe)) { - vty_out(vty, " Dependents:"); + if (json) + json_dependants = json_object_new_array(); + else + vty_out(vty, " Dependents:"); frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) { - vty_out(vty, " (%u)", rb_node_dep->nhe->id); + if (json) + json_object_array_add( + json_dependants, + json_object_new_int( + rb_node_dep->nhe->id)); + else + vty_out(vty, " (%u)", rb_node_dep->nhe->id); } - vty_out(vty, "\n"); + if (json) + json_object_object_add(json, "dependents", + json_dependants); + else + vty_out(vty, "\n"); } - if (nhe->nhg.nhgr.buckets) - vty_out(vty, - " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64 "\n", - nhe->nhg.nhgr.buckets, nhe->nhg.nhgr.idle_timer, - nhe->nhg.nhgr.unbalanced_timer, - nhe->nhg.nhgr.unbalanced_time); + if (nhe->nhg.nhgr.buckets) { + if (json) { + json_object_int_add(json, "buckets", + nhe->nhg.nhgr.buckets); + json_object_int_add(json, "idleTimer", + nhe->nhg.nhgr.idle_timer); + json_object_int_add(json, "unbalancedTimer", + nhe->nhg.nhgr.unbalanced_timer); + json_object_int_add(json, "unbalancedTime", + nhe->nhg.nhgr.unbalanced_time); + } else { + vty_out(vty, + " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64 + "\n", + nhe->nhg.nhgr.buckets, nhe->nhg.nhgr.idle_timer, + nhe->nhg.nhgr.unbalanced_timer, + nhe->nhg.nhgr.unbalanced_time); + } + } + + if (json_nhe_hdr) + json_object_object_addf(json_nhe_hdr, json, "%u", nhe->id); } -static int show_nexthop_group_id_cmd_helper(struct vty *vty, uint32_t id) +static int show_nexthop_group_id_cmd_helper(struct vty *vty, uint32_t id, + json_object *json) { struct nhg_hash_entry *nhe = NULL; nhe = zebra_nhg_lookup_id(id); if (nhe) - show_nexthop_group_out(vty, nhe); + show_nexthop_group_out(vty, nhe, json); else { - vty_out(vty, "Nexthop Group ID: %u does not exist\n", id); + if (json) + vty_json(vty, json); + else + vty_out(vty, "Nexthop Group ID: %u does not exist\n", + id); return CMD_WARNING; } + + if (json) + vty_json(vty, json); + return CMD_SUCCESS; } @@ -1565,6 +1747,7 @@ struct nhe_show_context { vrf_id_t vrf_id; afi_t afi; int type; + json_object *json; }; static int nhe_show_walker(struct hash_bucket *bucket, void *arg) @@ -1583,7 +1766,7 @@ static int nhe_show_walker(struct hash_bucket *bucket, void *arg) if (ctx->type && nhe->type != ctx->type) goto done; - show_nexthop_group_out(ctx->vty, nhe); + show_nexthop_group_out(ctx->vty, nhe, ctx->json); done: return HASHWALK_CONTINUE; @@ -1591,7 +1774,7 @@ done: static void show_nexthop_group_cmd_helper(struct vty *vty, struct zebra_vrf *zvrf, afi_t afi, - int type) + int type, json_object *json) { struct nhe_show_context ctx; @@ -1599,6 +1782,7 @@ static void show_nexthop_group_cmd_helper(struct vty *vty, ctx.afi = afi; ctx.vrf_id = zvrf->vrf->vrf_id; ctx.type = type; + ctx.json = json; hash_walk(zrouter.nhgs_id, nhe_show_walker, &ctx); } @@ -1616,7 +1800,7 @@ static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp) frr_each(nhg_connected_tree, &zebra_if->nhg_dependents, rb_node_dep) { vty_out(vty, " "); - show_nexthop_group_out(vty, rb_node_dep->nhe); + show_nexthop_group_out(vty, rb_node_dep->nhe, NULL); } } } @@ -1655,29 +1839,36 @@ DEFPY (show_interface_nexthop_group, return CMD_SUCCESS; } -DEFPY (show_nexthop_group, - show_nexthop_group_cmd, - "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [<kernel|zebra|bgp|sharp>$type_str] [vrf <NAME$vrf_name|all$vrf_all>]>", - SHOW_STR - "Show Nexthop Groups\n" - "RIB information\n" - "Nexthop Group ID\n" - "Show Singleton Nexthop-Groups\n" - IP_STR - IP6_STR - "Kernel (not installed via the zebra RIB)\n" - "Zebra (implicitly created by zebra)\n" - "Border Gateway Protocol (BGP)\n" - "Super Happy Advanced Routing Protocol (SHARP)\n" - VRF_FULL_CMD_HELP_STR) +DEFPY(show_nexthop_group, + show_nexthop_group_cmd, + "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [<kernel|zebra|bgp|sharp>$type_str] [vrf <NAME$vrf_name|all$vrf_all>]> [json]", + SHOW_STR + "Show Nexthop Groups\n" + "RIB information\n" + "Nexthop Group ID\n" + "Show Singleton Nexthop-Groups\n" + IP_STR + IP6_STR + "Kernel (not installed via the zebra RIB)\n" + "Zebra (implicitly created by zebra)\n" + "Border Gateway Protocol (BGP)\n" + "Super Happy Advanced Routing Protocol (SHARP)\n" + VRF_FULL_CMD_HELP_STR + JSON_STR) { struct zebra_vrf *zvrf = NULL; afi_t afi = AFI_UNSPEC; int type = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + json_object *json_vrf = NULL; + + if (uj) + json = json_object_new_object(); if (id) - return show_nexthop_group_id_cmd_helper(vty, id); + return show_nexthop_group_id_cmd_helper(vty, id, json); if (v4) afi = AFI_IP; @@ -1693,8 +1884,11 @@ DEFPY (show_nexthop_group, } if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) { - vty_out(vty, - "VRF subcommand does not make any sense in l3mdev based vrf's\n"); + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "VRF subcommand does not make any sense in l3mdev based vrf's\n"); return CMD_WARNING; } @@ -1707,11 +1901,21 @@ DEFPY (show_nexthop_group, zvrf = vrf->info; if (!zvrf) continue; + if (uj) + json_vrf = json_object_new_object(); + else + vty_out(vty, "VRF: %s\n", vrf->name); - vty_out(vty, "VRF: %s\n", vrf->name); - show_nexthop_group_cmd_helper(vty, zvrf, afi, type); + show_nexthop_group_cmd_helper(vty, zvrf, afi, type, + json_vrf); + if (uj) + json_object_object_add(json, vrf->name, + json_vrf); } + if (uj) + vty_json(vty, json); + return CMD_SUCCESS; } @@ -1721,12 +1925,18 @@ DEFPY (show_nexthop_group, zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME); if (!zvrf) { - vty_out(vty, "%% VRF '%s' specified does not exist\n", - vrf_name); + if (uj) + vty_json(vty, json); + else + vty_out(vty, "%% VRF '%s' specified does not exist\n", + vrf_name); return CMD_WARNING; } - show_nexthop_group_cmd_helper(vty, zvrf, afi, type); + show_nexthop_group_cmd_helper(vty, zvrf, afi, type, json); + + if (uj) + vty_json(vty, json); return CMD_SUCCESS; } @@ -4030,6 +4240,15 @@ DEFUN (show_zebra, ttable_add_row(table, "ASIC offload|%s", zrouter.asic_offloaded ? "Used" : "Unavailable"); + /* + * Do not display this unless someone is actually using it + * + * Why this distinction? I think this is effectively dead code + * and should not be exposed. Maybe someone proves me wrong. + */ + if (zrouter.asic_notification_nexthop_control) + ttable_add_row(table, "ASIC offload and nexthop control|Used"); + ttable_add_row(table, "RA|%s", rtadv_compiled_in() ? "Compiled in" : "Not Compiled in"); ttable_add_row(table, "RFC 5549|%s", |
