diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index fa83a457bf..f353abead0 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -12249,6 +12249,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd, bool first = true; uint16_t show_flags = 0; enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED; + struct prefix p; if (uj) { argc--; @@ -12401,7 +12402,6 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd, if (argv_find(argv, argc, "A.B.C.D/M", &idx) || argv_find(argv, argc, "X:X::X:X/M", &idx)) { const char *prefix_str = argv[idx]->arg; - struct prefix p; if (!str2prefix(prefix_str, &p)) { vty_out(vty, "%% Malformed Prefix\n"); diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 9ed6b6dd7f..7ca473ceb6 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -1155,7 +1155,9 @@ zebra Terminal Mode Commands .. clicmd:: show zebra Display various statistics related to the installation and deletion - of routes, neighbor updates, and LSP's into the kernel. + of routes, neighbor updates, and LSP's into the kernel. In addition + show various zebra state that is useful when debugging an operator's + setup. .. clicmd:: show zebra client [summary] diff --git a/lib/command.c b/lib/command.c index 9cf93ea192..ebdbf162d1 100644 --- a/lib/command.c +++ b/lib/command.c @@ -106,6 +106,21 @@ const char *cmd_domainname_get(void) return host.domainname; } +const char *cmd_system_get(void) +{ + return host.system; +} + +const char *cmd_release_get(void) +{ + return host.release; +} + +const char *cmd_version_get(void) +{ + return host.version; +} + static int root_on_exit(struct vty *vty); /* Standard command node structures. */ @@ -1398,8 +1413,9 @@ DEFUN (show_version, SHOW_STR "Displays zebra version\n") { - vty_out(vty, "%s %s (%s).\n", FRR_FULL_NAME, FRR_VERSION, - cmd_hostname_get() ? cmd_hostname_get() : ""); + vty_out(vty, "%s %s (%s) on %s(%s).\n", FRR_FULL_NAME, FRR_VERSION, + cmd_hostname_get() ? cmd_hostname_get() : "", cmd_system_get(), + cmd_release_get()); vty_out(vty, "%s%s\n", FRR_COPYRIGHT, GIT_INFO); #ifdef ENABLE_VERSION_BUILD_CONFIG vty_out(vty, "configured with:\n %s\n", FRR_CONFIG_ARGS); @@ -2445,6 +2461,10 @@ void cmd_init(int terminal) /* Default host value settings. */ host.name = XSTRDUP(MTYPE_HOST, names.nodename); + host.system = XSTRDUP(MTYPE_HOST, names.sysname); + host.release = XSTRDUP(MTYPE_HOST, names.release); + host.version = XSTRDUP(MTYPE_HOST, names.version); + #ifdef HAVE_STRUCT_UTSNAME_DOMAINNAME if ((strcmp(names.domainname, "(none)") == 0)) host.domainname = NULL; @@ -2563,6 +2583,9 @@ void cmd_terminate(void) } XFREE(MTYPE_HOST, host.name); + XFREE(MTYPE_HOST, host.system); + XFREE(MTYPE_HOST, host.release); + XFREE(MTYPE_HOST, host.version); XFREE(MTYPE_HOST, host.domainname); XFREE(MTYPE_HOST, host.password); XFREE(MTYPE_HOST, host.password_encrypt); diff --git a/lib/command.h b/lib/command.h index c888356d61..a540bdc5c5 100644 --- a/lib/command.h +++ b/lib/command.h @@ -55,6 +55,13 @@ struct host { /* Domainname of this router */ char *domainname; + /* + * Some extra system data that is useful + */ + char *system; + char *release; + char *version; + /* Password for vty interface. */ char *password; char *password_encrypt; @@ -600,6 +607,9 @@ extern int cmd_domainname_set(const char *domainname); extern int cmd_hostname_set(const char *hostname); extern const char *cmd_hostname_get(void); extern const char *cmd_domainname_get(void); +extern const char *cmd_system_get(void); +extern const char *cmd_release_get(void); +extern const char *cmd_version_get(void); /* NOT safe for general use; call this only if DEV_BUILD! */ extern void grammar_sandbox_init(void); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 24c01b7f51..2d12ad4c8e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -3027,11 +3027,12 @@ int netlink_nexthop_read(struct zebra_ns *zns) * this kernel must support them. */ supports_nh = true; - if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_NHG) zlog_debug("Nexthop objects %ssupported on this kernel", supports_nh ? "" : "not "); + zebra_router_set_supports_nhgs(supports_nh); + return ret; } diff --git a/zebra/rtadv.c b/zebra/rtadv.c index d64d563771..3bbee83d77 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -47,6 +47,8 @@ extern struct zebra_privs_t zserv_privs; +static uint32_t interfaces_configured_for_ra_from_bgp; + #if defined(HAVE_RTADV) #ifndef VTYSH_EXTRACT_PL @@ -1303,6 +1305,9 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable) zif = ifp->info; if (enable) { + if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED)) + interfaces_configured_for_ra_from_bgp++; + SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED); ipv6_nd_suppress_ra_set(ifp, RA_ENABLE); if (ra_interval @@ -1311,6 +1316,9 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable) VTY_RA_INTERVAL_CONFIGURED)) zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000; } else { + if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED)) + interfaces_configured_for_ra_from_bgp--; + UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED); if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) @@ -2787,6 +2795,8 @@ void rtadv_vrf_terminate(struct zebra_vrf *zvrf) void rtadv_cmd_init(void) { + interfaces_configured_for_ra_from_bgp = 0; + hook_register(zebra_if_extra_info, nd_dump_vty); hook_register(zebra_if_config_wr, rtadv_config_write); @@ -2886,6 +2896,11 @@ static int if_leave_all_router(int sock, struct interface *ifp) return 0; } +bool rtadv_compiled_in(void) +{ + return true; +} + #else void rtadv_vrf_init(struct zebra_vrf *zvrf) { @@ -2941,4 +2956,14 @@ void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS) return; } +bool rtadv_compiled_in(void) +{ + return false; +} + #endif /* HAVE_RTADV */ + +uint32_t rtadv_get_interfaces_configured_from_bgp(void) +{ + return interfaces_configured_for_ra_from_bgp; +} diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 7b71ee45a2..a95174b22b 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -22,6 +22,7 @@ #ifndef _ZEBRA_RTADV_H #define _ZEBRA_RTADV_H +#include "zebra.h" #include "vty.h" #include "zebra/interface.h" @@ -161,6 +162,8 @@ extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS); extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS); extern void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p); extern void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p); +extern uint32_t rtadv_get_interfaces_configured_from_bgp(void); +extern bool rtadv_compiled_in(void); #ifdef __cplusplus } diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index dd788216c7..dafe925c26 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -209,6 +209,8 @@ struct zebra_router { */ bool asic_offloaded; bool notify_on_ack; + + bool supports_nhgs; }; #define GRACEFUL_RESTART_TIME 60 @@ -256,6 +258,11 @@ extern enum multicast_mode multicast_mode_ipv4_get(void); extern bool zebra_router_notify_on_ack(void); +static inline void zebra_router_set_supports_nhgs(bool support) +{ + zrouter.supports_nhgs = support; +} + /* zebra_northbound.c */ extern const struct frr_yang_module_info frr_zebra_info; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index fab1e7b897..1d9ed4ddd9 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -33,6 +33,7 @@ #include "routemap.h" #include "srcdest_table.h" #include "vxlan.h" +#include "termtable.h" #include "zebra/zebra_router.h" #include "zebra/zserv.h" @@ -61,6 +62,7 @@ #include "zebra/kernel_netlink.h" #include "zebra/table_manager.h" #include "zebra/zebra_script.h" +#include "zebra/rtadv.h" extern int allow_delete; @@ -3969,9 +3971,43 @@ DEFUN (show_zebra, ZEBRA_STR) { struct vrf *vrf; + struct ttable *table = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + char *out; - if (zrouter.asic_offloaded) - vty_out(vty, "Asic Offload is being used\n"); + ttable_rowseps(table, 0, BOTTOM, true, '-'); + ttable_add_row(table, "OS|%s(%s)", cmd_system_get(), cmd_release_get()); + ttable_add_row(table, "v4 Forwarding|%s", ipforward() ? "On" : "Off"); + ttable_add_row(table, "v6 Forwarding|%s", + ipforward_ipv6() ? "On" : "Off"); + ttable_add_row(table, "MPLS|%s", mpls_enabled ? "On" : "Off"); + ttable_add_row(table, "EVPN|%s", is_evpn_enabled() ? "On" : "Off"); + + +#ifdef GNU_LINUX + if (!vrf_is_backend_netns()) + ttable_add_row(table, "VRF|l3mdev Available"); + else + ttable_add_row(table, "VRF|Namespaces"); +#else + ttable_add_row(table, "VRF|Not Available"); +#endif + + ttable_add_row(table, "ASIC offload|%s", + zrouter.asic_offloaded ? "Used" : "Unavailable"); + + ttable_add_row(table, "RA|%s", + rtadv_compiled_in() ? "Compiled in" : "Not Compiled in"); + ttable_add_row(table, "RFC 5549|%s", + rtadv_get_interfaces_configured_from_bgp() + ? "BGP is using" + : "BGP is not using"); + + ttable_add_row(table, "Kernel NHG|%s", + zrouter.supports_nhgs ? "Available" : "Unavailable"); + + out = ttable_dump(table, "\n"); + vty_out(vty, "%s\n", out); + XFREE(MTYPE_TMP, out); vty_out(vty, " Route Route Neighbor LSP LSP\n");