diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/interface.c | 10 | ||||
| -rw-r--r-- | zebra/interface.h | 6 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 9 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 3 | ||||
| -rw-r--r-- | zebra/rtadv.c | 68 | ||||
| -rw-r--r-- | zebra/rtadv.h | 3 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 31 | ||||
| -rw-r--r-- | zebra/zebra_router.h | 7 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 40 |
9 files changed, 156 insertions, 21 deletions
diff --git a/zebra/interface.c b/zebra/interface.c index e4e80ec4e9..2e13cfd55c 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -158,6 +158,16 @@ static int if_zebra_new_hook(struct interface *ifp) rtadv->AdvReachableTime = 0; rtadv->AdvRetransTimer = 0; rtadv->AdvCurHopLimit = RTADV_DEFAULT_HOPLIMIT; + memset(&rtadv->lastadvcurhoplimit, 0, + sizeof(rtadv->lastadvcurhoplimit)); + memset(&rtadv->lastadvmanagedflag, 0, + sizeof(rtadv->lastadvmanagedflag)); + memset(&rtadv->lastadvotherconfigflag, 0, + sizeof(rtadv->lastadvotherconfigflag)); + memset(&rtadv->lastadvreachabletime, 0, + sizeof(rtadv->lastadvreachabletime)); + memset(&rtadv->lastadvretranstimer, 0, + sizeof(rtadv->lastadvretranstimer)); rtadv->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */ rtadv->HomeAgentPreference = 0; diff --git a/zebra/interface.h b/zebra/interface.h index 771398b547..413a67469a 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -81,6 +81,7 @@ struct rtadvconf { Default: false */ int AdvManagedFlag; + struct timeval lastadvmanagedflag; /* The true/false value to be placed in the "Other stateful @@ -89,6 +90,7 @@ struct rtadvconf { Default: false */ int AdvOtherConfigFlag; + struct timeval lastadvotherconfigflag; /* The value to be placed in MTU options sent by the router. A value of zero indicates that no MTU options are sent. @@ -105,6 +107,7 @@ struct rtadvconf { Default: 0 */ uint32_t AdvReachableTime; #define RTADV_MAX_REACHABLE_TIME 3600000 + struct timeval lastadvreachabletime; /* The value to be placed in the Retrans Timer field in the Router Advertisement messages sent by the router. The value zero means @@ -112,6 +115,7 @@ struct rtadvconf { Default: 0 */ int AdvRetransTimer; + struct timeval lastadvretranstimer; /* The default value to be placed in the Cur Hop Limit field in the Router Advertisement messages sent by the router. The value @@ -121,6 +125,8 @@ struct rtadvconf { Default: The value specified in the "Assigned Numbers" RFC [ASSIGNED] that was in effect at the time of implementation. */ int AdvCurHopLimit; + struct timeval lastadvcurhoplimit; + #define RTADV_DEFAULT_HOPLIMIT 64 /* 64 hops */ /* The value to be placed in the Router Lifetime field of Router diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 08f9782cf7..e3b2f9cb66 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1500,7 +1500,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list) netlink_socket (). */ void kernel_init(struct zebra_ns *zns) { - uint32_t groups; + uint32_t groups, dplane_groups; #if defined SOL_NETLINK int one, ret; #endif @@ -1525,6 +1525,10 @@ void kernel_init(struct zebra_ns *zns) ((uint32_t) 1 << (RTNLGRP_IPV6_RULE - 1)) | ((uint32_t) 1 << (RTNLGRP_NEXTHOP - 1)); + dplane_groups = (RTMGRP_LINK | + RTMGRP_IPV4_IFADDR | + RTMGRP_IPV6_IFADDR); + snprintf(zns->netlink.name, sizeof(zns->netlink.name), "netlink-listen (NS %u)", zns->ns_id); zns->netlink.sock = -1; @@ -1559,7 +1563,8 @@ void kernel_init(struct zebra_ns *zns) sizeof(zns->netlink_dplane_in.name), "netlink-dp-in (NS %u)", zns->ns_id); zns->netlink_dplane_in.sock = -1; - if (netlink_socket(&zns->netlink_dplane_in, groups, zns->ns_id) < 0) { + if (netlink_socket(&zns->netlink_dplane_in, dplane_groups, + zns->ns_id) < 0) { zlog_err("Failure to create %s socket", zns->netlink_dplane_in.name); exit(-1); 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 350b97cc5d..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 @@ -632,45 +634,66 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len, radvert = (struct nd_router_advert *)msg; - if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) - && (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) { +#define SIXHOUR2USEC (int64_t)6 * 60 * 60 * 1000000 + + if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit) && + (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit) && + (monotime_since(&zif->rtadv.lastadvcurhoplimit, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvcurhoplimit.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvcurhoplimit); } - if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) - && !zif->rtadv.AdvManagedFlag) { + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) && + !zif->rtadv.AdvManagedFlag && + (monotime_since(&zif->rtadv.lastadvmanagedflag, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvmanagedflag.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvmanagedflag); } - if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) - && !zif->rtadv.AdvOtherConfigFlag) { + if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) && + !zif->rtadv.AdvOtherConfigFlag && + (monotime_since(&zif->rtadv.lastadvotherconfigflag, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvotherconfigflag.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvotherconfigflag); } - if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) - && (ntohl(radvert->nd_ra_reachable) - != zif->rtadv.AdvReachableTime)) { + if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime) && + (ntohl(radvert->nd_ra_reachable) != zif->rtadv.AdvReachableTime) && + (monotime_since(&zif->rtadv.lastadvreachabletime, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvreachabletime.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvreachabletime); } - if ((ntohl(radvert->nd_ra_retransmit) - != (unsigned int)zif->rtadv.AdvRetransTimer)) { + if ((ntohl(radvert->nd_ra_retransmit) != + (unsigned int)zif->rtadv.AdvRetransTimer) && + (monotime_since(&zif->rtadv.lastadvretranstimer, NULL) > + SIXHOUR2USEC || + zif->rtadv.lastadvretranstimer.tv_sec == 0)) { flog_warn( EC_ZEBRA_RA_PARAM_MISMATCH, "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s", ifp->name, ifp->ifindex, addr_str); + monotime(&zif->rtadv.lastadvretranstimer); } /* Create entry for neighbor if not known. */ @@ -1282,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 @@ -1290,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)) @@ -2766,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); @@ -2865,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) { @@ -2920,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_nhg.c b/zebra/zebra_nhg.c index aa015992d5..fac312cf7c 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2995,7 +2995,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) dplane_ctx_fini(&ctx); } -static void zebra_nhg_sweep_entry(struct hash_bucket *bucket, void *arg) +static int zebra_nhg_sweep_entry(struct hash_bucket *bucket, void *arg) { struct nhg_hash_entry *nhe = NULL; @@ -3009,7 +3009,7 @@ static void zebra_nhg_sweep_entry(struct hash_bucket *bucket, void *arg) * from an upper level proto. */ if (zrouter.startup_time < nhe->uptime) - return; + return HASHWALK_CONTINUE; /* * If it's proto-owned and not being used by a route, remove it since @@ -3019,20 +3019,41 @@ static void zebra_nhg_sweep_entry(struct hash_bucket *bucket, void *arg) */ if (PROTO_OWNED(nhe) && nhe->refcnt == 1) { zebra_nhg_decrement_ref(nhe); - return; + return HASHWALK_ABORT; } /* * If its being ref'd by routes, just let it be uninstalled via a route * removal. */ - if (ZEBRA_NHG_CREATED(nhe) && nhe->refcnt <= 0) + if (ZEBRA_NHG_CREATED(nhe) && nhe->refcnt <= 0) { zebra_nhg_uninstall_kernel(nhe); + return HASHWALK_ABORT; + } + + return HASHWALK_CONTINUE; } void zebra_nhg_sweep_table(struct hash *hash) { - hash_iterate(hash, zebra_nhg_sweep_entry, NULL); + uint32_t count; + + /* + * Yes this is extremely odd. Effectively nhg's have + * other nexthop groups that depend on them and when you + * remove them, you can have other entries blown up. + * our hash code does not work with deleting multiple + * entries at a time and will possibly cause crashes + * So what to do? Whenever zebra_nhg_sweep_entry + * deletes an entry it will return HASHWALK_ABORT, + * cause that deletion might have triggered more. + * then we can just keep sweeping this table + * until nothing more is found to do. + */ + do { + count = hashcount(hash); + hash_walk(hash, zebra_nhg_sweep_entry, NULL); + } while (count != hashcount(hash)); } static void zebra_nhg_mark_keep_entry(struct hash_bucket *bucket, void *arg) 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"); |
