diff --git a/sys/net/route/nhop.h b/sys/net/route/nhop.h --- a/sys/net/route/nhop.h +++ b/sys/net/route/nhop.h @@ -183,6 +183,8 @@ int nhop_get_upper_family(const struct nhop_object *nh); int nhop_get_neigh_family(const struct nhop_object *nh); uint32_t nhop_get_fibnum(const struct nhop_object *nh); +uint32_t nhop_get_expire(const struct nhop_object *nh); +void nhop_set_expire(struct nhop_object *nh, uint32_t expire); #endif /* _KERNEL */ diff --git a/sys/net/route/nhop_ctl.c b/sys/net/route/nhop_ctl.c --- a/sys/net/route/nhop_ctl.c +++ b/sys/net/route/nhop_ctl.c @@ -272,6 +272,17 @@ return (res); } +static void +set_nhop_expire_from_info(struct nhop_object *nh, const struct rt_addrinfo *info) +{ + uint32_t nh_expire = 0; + + /* Kernel -> userland timebase conversion. */ + if ((info->rti_mflags & RTV_EXPIRE) && (info->rti_rmx->rmx_expire > 0)) + nh_expire = info->rti_rmx->rmx_expire - time_second + time_uptime; + nhop_set_expire(nh, nh_expire); +} + static int fill_nhop_from_info(struct nhop_priv *nh_priv, struct rt_addrinfo *info) { @@ -294,6 +305,7 @@ nh_priv->nh_neigh_family = nh_priv->nh_upper_family; else nh_priv->nh_neigh_family = nh->gw_sa.sa_family; + set_nhop_expire_from_info(nh, info); nh->nh_ifp = (info->rti_ifp != NULL) ? info->rti_ifp : info->rti_ifa->ifa_ifp; nh->nh_ifa = info->rti_ifa; @@ -802,6 +814,19 @@ return (nh->nh_priv->nh_fibnum); } +uint32_t +nhop_get_expire(const struct nhop_object *nh) +{ + return (nh->nh_priv->nh_expire); +} + +void +nhop_set_expire(struct nhop_object *nh, uint32_t expire) +{ + MPASS(!NH_IS_LINKED(nh)); + nh->nh_priv->nh_expire = expire; +} + void nhops_update_ifmtu(struct rib_head *rh, struct ifnet *ifp, uint32_t mtu) { diff --git a/sys/net/route/nhop_var.h b/sys/net/route/nhop_var.h --- a/sys/net/route/nhop_var.h +++ b/sys/net/route/nhop_var.h @@ -78,6 +78,7 @@ uint8_t nh_neigh_family;/* neighbor address family */ uint16_t nh_type; /* nexthop type */ uint32_t rt_flags; /* routing flags for the control plane */ + uint32_t nh_expire; /* path expiration time */ /* nhop lookup comparison end */ uint32_t nh_idx; /* nexthop index */ uint32_t nh_fibnum; /* nexthop fib */ @@ -95,6 +96,7 @@ #define NH_IS_PINNED(_nh) ((!NH_IS_NHGRP(_nh)) && \ ((_nh)->nh_priv->rt_flags & RTF_PINNED)) +#define NH_IS_LINKED(_nh) ((_nh)->nh_priv->nh_idx != 0) /* nhop.c */ struct nhop_priv *find_nhop(struct nh_control *ctl, diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c --- a/sys/net/route/route_ctl.c +++ b/sys/net/route/route_ctl.c @@ -416,16 +416,6 @@ } #endif -static void -rt_set_expire_info(struct rtentry *rt, const struct rt_addrinfo *info) -{ - - /* Kernel -> userland timebase conversion. */ - if (info->rti_mflags & RTV_EXPIRE) - rt->rt_expire = info->rti_rmx->rmx_expire ? - info->rti_rmx->rmx_expire - time_second + time_uptime : 0; -} - /* * Check if specified @gw matches gw data in the nexthop @nh. * @@ -702,7 +692,6 @@ * examine the ifa and ifa->ifa_ifp if it so desires. */ rt->rt_weight = get_info_weight(info, RT_DEFAULT_WEIGHT); - rt_set_expire_info(rt, info); *prt = rt; return (0); @@ -1112,8 +1101,8 @@ rn = rnh->rnh_addaddr(ndst, netmask, &rnh->head, rt->rt_nodes); if (rn != NULL) { - if (rt->rt_expire > 0) - tmproutes_update(rnh, rt); + if (!NH_IS_NHGRP(rnd->rnd_nhop) && nhop_get_expire(rnd->rnd_nhop)) + tmproutes_update(rnh, rt, rnd->rnd_nhop); /* Finalize notification */ rib_bump_gen(rnh); @@ -1136,7 +1125,6 @@ /* * Switch @rt nhop/weigh to the ones specified in @rnd. - * Conditionally set rt_expire if set in @info. * Returns 0 on success. */ int @@ -1151,12 +1139,11 @@ nh_orig = rt->rt_nhop; if (rnd->rnd_nhop != NULL) { - /* Changing expiration & nexthop & weight to a new one */ - rt_set_expire_info(rt, info); + /* Changing nexthop & weight to a new one */ rt->rt_nhop = rnd->rnd_nhop; rt->rt_weight = rnd->rnd_weight; - if (rt->rt_expire > 0) - tmproutes_update(rnh, rt); + if (!NH_IS_NHGRP(rnd->rnd_nhop) && nhop_get_expire(rnd->rnd_nhop)) + tmproutes_update(rnh, rt, rnd->rnd_nhop); } else { /* Route deletion requested. */ struct sockaddr *ndst, *netmask; diff --git a/sys/net/route/route_temporal.c b/sys/net/route/route_temporal.c --- a/sys/net/route/route_temporal.c +++ b/sys/net/route/route_temporal.c @@ -55,12 +55,13 @@ static int expire_route(const struct rtentry *rt, const struct nhop_object *nh, void *arg) { + uint32_t nh_expire = nhop_get_expire(nh); time_t *next_callout; - if (rt->rt_expire == 0) + if (nh_expire == 0) return (0); - if (rt->rt_expire <= time_uptime) + if (nh_expire <= time_uptime) return (1); next_callout = (time_t *)arg; @@ -69,8 +70,8 @@ * Update next_callout to determine the next ts to * run the callback at. */ - if (*next_callout == 0 || *next_callout > rt->rt_expire) - *next_callout = rt->rt_expire; + if (*next_callout == 0 || *next_callout > nh_expire) + *next_callout = nh_expire; return (0); } @@ -78,7 +79,7 @@ /* * Per-rnh callout function traversing the tree and deleting * expired routes. Calculates next callout run by looking at - * the rt_expire time for the remaining temporal routes. + * the nh_expire time for the remaining temporal routes. */ static void expire_callout(void *arg) @@ -123,26 +124,27 @@ * to the tree. RIB_WLOCK must be held. */ void -tmproutes_update(struct rib_head *rnh, struct rtentry *rt) +tmproutes_update(struct rib_head *rnh, struct rtentry *rt, struct nhop_object *nh) { int seconds; + uint32_t nh_expire = nhop_get_expire(nh); RIB_WLOCK_ASSERT(rnh); - if (rnh->next_expire == 0 || rnh->next_expire > rt->rt_expire) { + if (rnh->next_expire == 0 || rnh->next_expire > nh_expire) { /* * Callback is not scheduled, is executing, * or is scheduled for a later time than we need. * * Schedule the one for the current @rt expiration time. */ - seconds = (rt->rt_expire - time_uptime); + seconds = (nh_expire - time_uptime); if (seconds < 0) seconds = 0; callout_reset_sbt(&rnh->expire_callout, SBT_1S * seconds, SBT_1MS * 500, expire_callout, rnh, 0); - rnh->next_expire = rt->rt_expire; + rnh->next_expire = nh_expire; } } diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h --- a/sys/net/route/route_var.h +++ b/sys/net/route/route_var.h @@ -183,7 +183,6 @@ int rte_flags; /* up/down?, host/net */ u_long rt_weight; /* absolute weight */ - u_long rt_expire; /* lifetime for route, e.g. redirect */ struct rtentry *rt_chain; /* pointer to next rtentry to delete */ struct epoch_context rt_epoch_ctx; /* net epoch tracker */ }; @@ -214,7 +213,7 @@ #define RTE_RT_FLAG_MASK (RTF_UP | RTF_HOST) /* route_temporal.c */ -void tmproutes_update(struct rib_head *rnh, struct rtentry *rt); +void tmproutes_update(struct rib_head *rnh, struct rtentry *rt, struct nhop_object *nh); void tmproutes_init(struct rib_head *rh); void tmproutes_destroy(struct rib_head *rh); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1293,8 +1293,8 @@ out->rmx_weight = rt->rt_weight; out->rmx_nhidx = nhop_get_idx(nh); /* Kernel -> userland timebase conversion. */ - out->rmx_expire = rt->rt_expire ? - rt->rt_expire - time_uptime + time_second : 0; + out->rmx_expire = nhop_get_expire(nh) ? + nhop_get_expire(nh) - time_uptime + time_second : 0; } /*