summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/nexthop.h3
-rw-r--r--zebra/interface.c17
-rw-r--r--zebra/interface.h3
-rw-r--r--zebra/netconf_netlink.c32
-rw-r--r--zebra/rt_netlink.c3
-rw-r--r--zebra/zebra_dplane.c49
-rw-r--r--zebra/zebra_dplane.h10
-rw-r--r--zebra/zebra_nhg.c27
-rw-r--r--zebra/zebra_vty.c9
9 files changed, 89 insertions, 64 deletions
diff --git a/lib/nexthop.h b/lib/nexthop.h
index e324e58491..f1309aa525 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -81,7 +81,7 @@ struct nexthop {
enum nexthop_types_t type;
- uint8_t flags;
+ uint16_t flags;
#define NEXTHOP_FLAG_ACTIVE (1 << 0) /* This nexthop is alive. */
#define NEXTHOP_FLAG_FIB (1 << 1) /* FIB nexthop. */
#define NEXTHOP_FLAG_RECURSIVE (1 << 2) /* Recursive nexthop. */
@@ -95,6 +95,7 @@ struct nexthop {
#define NEXTHOP_FLAG_HAS_BACKUP (1 << 6) /* Backup nexthop index is set */
#define NEXTHOP_FLAG_SRTE (1 << 7) /* SR-TE color used for BGP traffic */
#define NEXTHOP_FLAG_EVPN (1 << 8) /* nexthop is EVPN */
+#define NEXTHOP_FLAG_LINKDOWN (1 << 9) /* is not removed on link down */
#define NEXTHOP_IS_ACTIVE(flags) \
(CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \
diff --git a/zebra/interface.c b/zebra/interface.c
index 93ffeb437c..5f36b88a1c 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1407,7 +1407,7 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
struct interface *ifp)
{
struct zebra_if *zif;
- enum dplane_netconf_status_e mpls;
+ enum dplane_netconf_status_e mpls, linkdown;
zif = ifp->info;
if (!zif) {
@@ -1424,10 +1424,17 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
else if (mpls == DPLANE_NETCONF_STATUS_DISABLED)
zif->mpls = false;
+ linkdown = dplane_ctx_get_netconf_linkdown(ctx);
+ if (linkdown == DPLANE_NETCONF_STATUS_ENABLED)
+ zif->linkdown = true;
+ else if (linkdown == DPLANE_NETCONF_STATUS_DISABLED)
+ zif->linkdown = false;
+
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s: if %s, ifindex %d, mpls %s",
+ zlog_debug("%s: if %s, ifindex %d, mpls %s linkdown %s",
__func__, ifp->name, ifp->ifindex,
- (zif->mpls ? "ON" : "OFF"));
+ (zif->mpls ? "ON" : "OFF"),
+ (zif->linkdown ? "ON" : "OFF"));
}
void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx)
@@ -1890,6 +1897,9 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
if (zebra_if->mpls)
vty_out(vty, " MPLS enabled\n");
+ if (zebra_if->linkdown)
+ vty_out(vty, " Ignore all routes with linkdown\n");
+
/* Hardware address. */
vty_out(vty, " Type: %s\n", if_link_type_str(ifp->ll_type));
if (ifp->hw_addr_len != 0) {
@@ -2211,6 +2221,7 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
zebra_if->desc);
json_object_boolean_add(json_if, "mplsEnabled", zebra_if->mpls);
+ json_object_boolean_add(json_if, "linkDown", zebra_if->linkdown);
if (ifp->ifindex == IFINDEX_INTERNAL) {
json_object_boolean_add(json_if, "pseudoInterface", true);
diff --git a/zebra/interface.h b/zebra/interface.h
index 5569711aa7..54ad91a0b2 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -129,6 +129,9 @@ struct zebra_if {
/* MPLS status. */
bool mpls;
+ /* Linkdown status */
+ bool linkdown;
+
/* Router advertise configuration. */
uint8_t rtadv_enable;
diff --git a/zebra/netconf_netlink.c b/zebra/netconf_netlink.c
index 587f6c749e..cc6a1201a5 100644
--- a/zebra/netconf_netlink.c
+++ b/zebra/netconf_netlink.c
@@ -45,19 +45,22 @@ static struct rtattr *netconf_rta(struct netconfmsg *ncm)
* Handle netconf update about a single interface: create dplane
* context, and enqueue for processing in the main zebra pthread.
*/
-static int netlink_netconf_dplane_update(ns_id_t ns_id, ifindex_t ifindex,
- enum dplane_netconf_status_e mpls_on,
- enum dplane_netconf_status_e mcast_on)
+static int
+netlink_netconf_dplane_update(ns_id_t ns_id, ifindex_t ifindex,
+ enum dplane_netconf_status_e mpls_on,
+ enum dplane_netconf_status_e mcast_on,
+ enum dplane_netconf_status_e linkdown_on)
{
struct zebra_dplane_ctx *ctx;
ctx = dplane_ctx_alloc();
dplane_ctx_set_op(ctx, DPLANE_OP_INTF_NETCONFIG);
- dplane_ctx_set_netconf_ns_id(ctx, ns_id);
- dplane_ctx_set_netconf_ifindex(ctx, ifindex);
+ dplane_ctx_set_ns_id(ctx, ns_id);
+ dplane_ctx_set_ifindex(ctx, ifindex);
dplane_ctx_set_netconf_mpls(ctx, mpls_on);
dplane_ctx_set_netconf_mcast(ctx, mcast_on);
+ dplane_ctx_set_netconf_linkdown(ctx, linkdown_on);
/* Enqueue ctx for main pthread to process */
dplane_provider_enqueue_to_zebra(ctx);
@@ -77,6 +80,8 @@ int netlink_netconf_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
uint32_t ival;
enum dplane_netconf_status_e mpls_on = DPLANE_NETCONF_STATUS_UNKNOWN;
enum dplane_netconf_status_e mcast_on = DPLANE_NETCONF_STATUS_UNKNOWN;
+ enum dplane_netconf_status_e linkdown_on =
+ DPLANE_NETCONF_STATUS_UNKNOWN;
if (h->nlmsg_type != RTM_NEWNETCONF && h->nlmsg_type != RTM_DELNETCONF)
return 0;
@@ -133,12 +138,23 @@ int netlink_netconf_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
mcast_on = DPLANE_NETCONF_STATUS_DISABLED;
}
+ if (tb[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN]) {
+ ival = *(uint32_t *)RTA_DATA(
+ tb[NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN]);
+ if (ival != 0)
+ linkdown_on = DPLANE_NETCONF_STATUS_ENABLED;
+ else
+ linkdown_on = DPLANE_NETCONF_STATUS_DISABLED;
+ }
+
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s: interface %u is mpls on: %d multicast on: %d",
- __func__, ifindex, mpls_on, mcast_on);
+ zlog_debug(
+ "%s: interface %u is mpls on: %d multicast on: %d linkdown: %d",
+ __func__, ifindex, mpls_on, mcast_on, linkdown_on);
/* Create a dplane context and pass it along for processing */
- netlink_netconf_dplane_update(ns_id, ifindex, mpls_on, mcast_on);
+ netlink_netconf_dplane_update(ns_id, ifindex, mpls_on, mcast_on,
+ linkdown_on);
return 0;
}
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 22f2d742e2..ad9e13a0f8 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -535,6 +535,9 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
if (rtm->rtm_flags & RTNH_F_ONLINK)
SET_FLAG(nh.flags, NEXTHOP_FLAG_ONLINK);
+ if (rtm->rtm_flags & RTNH_F_LINKDOWN)
+ SET_FLAG(nh.flags, NEXTHOP_FLAG_LINKDOWN);
+
if (num_labels)
nexthop_add_labels(&nh, ZEBRA_LSP_STATIC, num_labels, labels);
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index bb03d33e99..3a3bac6c74 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -301,10 +301,9 @@ struct dplane_gre_ctx {
* info. The flags values are public, in the dplane.h file...
*/
struct dplane_netconf_info {
- ns_id_t ns_id;
- ifindex_t ifindex;
enum dplane_netconf_status_e mpls_val;
enum dplane_netconf_status_e mcast_val;
+ enum dplane_netconf_status_e linkdown_val;
};
/*
@@ -2334,49 +2333,28 @@ dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx)
return ctx->u.neightable.mcast_probes;
}
-ifindex_t dplane_ctx_get_netconf_ifindex(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.netconf.ifindex;
-}
-
-ns_id_t dplane_ctx_get_netconf_ns_id(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.netconf.ns_id;
-}
-
-void dplane_ctx_set_netconf_ifindex(struct zebra_dplane_ctx *ctx,
- ifindex_t ifindex)
-{
- DPLANE_CTX_VALID(ctx);
-
- ctx->u.netconf.ifindex = ifindex;
-}
-
-void dplane_ctx_set_netconf_ns_id(struct zebra_dplane_ctx *ctx, ns_id_t ns_id)
+enum dplane_netconf_status_e
+dplane_ctx_get_netconf_mpls(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- ctx->u.netconf.ns_id = ns_id;
+ return ctx->u.netconf.mpls_val;
}
enum dplane_netconf_status_e
-dplane_ctx_get_netconf_mpls(const struct zebra_dplane_ctx *ctx)
+dplane_ctx_get_netconf_mcast(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.netconf.mpls_val;
+ return ctx->u.netconf.mcast_val;
}
enum dplane_netconf_status_e
-dplane_ctx_get_netconf_mcast(const struct zebra_dplane_ctx *ctx)
+dplane_ctx_get_netconf_linkdown(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.netconf.mcast_val;
+ return ctx->u.netconf.linkdown_val;
}
void dplane_ctx_set_netconf_mpls(struct zebra_dplane_ctx *ctx,
@@ -2395,6 +2373,15 @@ void dplane_ctx_set_netconf_mcast(struct zebra_dplane_ctx *ctx,
ctx->u.netconf.mcast_val = val;
}
+void dplane_ctx_set_netconf_linkdown(struct zebra_dplane_ctx *ctx,
+ enum dplane_netconf_status_e val)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.netconf.linkdown_val = val;
+}
+
+
/*
* Retrieve the limit on the number of pending, unprocessed updates.
*/
@@ -5439,7 +5426,7 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_NETCONFIG:
zlog_debug("%s: ifindex %d, mpls %d, mcast %d",
dplane_op2str(dplane_ctx_get_op(ctx)),
- dplane_ctx_get_netconf_ifindex(ctx),
+ dplane_ctx_get_ifindex(ctx),
dplane_ctx_get_netconf_mpls(ctx),
dplane_ctx_get_netconf_mcast(ctx));
break;
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 334d440a2f..d147a3e21c 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -592,19 +592,19 @@ const struct zebra_l2info_gre *
dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx);
/* Interface netconf info */
-ifindex_t dplane_ctx_get_netconf_ifindex(const struct zebra_dplane_ctx *ctx);
-ns_id_t dplane_ctx_get_netconf_ns_id(const struct zebra_dplane_ctx *ctx);
-void dplane_ctx_set_netconf_ifindex(struct zebra_dplane_ctx *ctx,
- ifindex_t ifindex);
-void dplane_ctx_set_netconf_ns_id(struct zebra_dplane_ctx *ctx, ns_id_t ns_id);
enum dplane_netconf_status_e
dplane_ctx_get_netconf_mpls(const struct zebra_dplane_ctx *ctx);
enum dplane_netconf_status_e
dplane_ctx_get_netconf_mcast(const struct zebra_dplane_ctx *ctx);
+enum dplane_netconf_status_e
+dplane_ctx_get_netconf_linkdown(const struct zebra_dplane_ctx *ctx);
+
void dplane_ctx_set_netconf_mpls(struct zebra_dplane_ctx *ctx,
enum dplane_netconf_status_e val);
void dplane_ctx_set_netconf_mcast(struct zebra_dplane_ctx *ctx,
enum dplane_netconf_status_e val);
+void dplane_ctx_set_netconf_linkdown(struct zebra_dplane_ctx *ctx,
+ enum dplane_netconf_status_e val);
/* Namespace fd info - esp. for netlink communication */
const struct zebra_dplane_info *dplane_ctx_get_ns(
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index f025507f7d..9a0f48158f 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -2084,11 +2084,7 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
* route and interface is up, its active. We trust kernel routes
* to be good.
*/
- if (ifp
- && (if_is_operative(ifp)
- || (if_is_up(ifp)
- && (type == ZEBRA_ROUTE_KERNEL
- || type == ZEBRA_ROUTE_SYSTEM))))
+ if (ifp && (if_is_operative(ifp)))
return 1;
else
return 0;
@@ -2457,20 +2453,19 @@ static unsigned nexthop_active_check(struct route_node *rn,
zlog_debug("%s: re %p, nexthop %pNHv", __func__, re, nexthop);
/*
- * If the kernel has sent us a NEW route, then
+ * If this is a kernel route, then if the interface is *up* then
* by golly gee whiz it's a good route.
- *
- * If its an already INSTALLED route we have already handled, then the
- * kernel route's nexthop might have became unreachable
- * and we have to handle that.
*/
- if (!CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED) &&
- (re->type == ZEBRA_ROUTE_KERNEL ||
- re->type == ZEBRA_ROUTE_SYSTEM)) {
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
- goto skip_check;
- }
+ if (re->type == ZEBRA_ROUTE_KERNEL || re->type == ZEBRA_ROUTE_SYSTEM) {
+ struct interface *ifp;
+
+ ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
+ if (ifp && (if_is_operative(ifp) || if_is_up(ifp))) {
+ SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ goto skip_check;
+ }
+ }
vrf_id = zvrf_id(rib_dest_vrf(rib_dest_from_rnode(rn)));
switch (nexthop->type) {
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 9149da8b0d..011fa2a1e5 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -376,6 +376,9 @@ static void show_nexthop_detail_helper(struct vty *vty,
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
vty_out(vty, " onlink");
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
+ vty_out(vty, " linkdown");
+
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
vty_out(vty, " (recursive)");
@@ -657,6 +660,9 @@ static void show_route_nexthop_helper(struct vty *vty,
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
vty_out(vty, " onlink");
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
+ vty_out(vty, " linkdown");
+
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
vty_out(vty, " (recursive)");
@@ -837,6 +843,9 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
json_object_boolean_true_add(json_nexthop,
"onLink");
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
+ json_object_boolean_true_add(json_nexthop, "linkDown");
+
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
json_object_boolean_true_add(json_nexthop,
"recursive");