summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/interface.c10
-rw-r--r--zebra/interface.h6
-rw-r--r--zebra/kernel_netlink.c9
-rw-r--r--zebra/rt_netlink.c3
-rw-r--r--zebra/rtadv.c68
-rw-r--r--zebra/rtadv.h3
-rw-r--r--zebra/zebra_nhg.c31
-rw-r--r--zebra/zebra_router.h7
-rw-r--r--zebra/zebra_vty.c40
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");