diff options
| -rw-r--r-- | lib/nexthop.h | 3 | ||||
| -rw-r--r-- | zebra/interface.c | 17 | ||||
| -rw-r--r-- | zebra/interface.h | 3 | ||||
| -rw-r--r-- | zebra/netconf_netlink.c | 32 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 3 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 49 | ||||
| -rw-r--r-- | zebra/zebra_dplane.h | 10 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 27 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 9 |
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"); |
