From 2259a03020fe043af123bbc9e749cf7fa1b4346c Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Mon, 21 Sep 2020 20:02:26 +0000 Subject: [PATCH] Rework part of routing code to reduce difference to D26449. * Split rt_setmetrics into get_info_weight() and rt_set_expire_info(), as these two can be applied at different entities and at different times. * Start filling route weight in route change notifications * Pass flowid to UDP/raw IP route lookups * Rework nd6_subscription_cb() and sysctl_dumpentry() to prepare for the fact that rtentry can contain multiple nexthops. Differential Revision: https://reviews.freebsd.org/D26497 --- sys/net/route.c | 12 ------------ sys/net/route.h | 4 ++++ sys/net/route/route_ctl.c | 33 +++++++++++++++++++++++++++++---- sys/net/route/route_var.h | 1 - sys/net/rtsock.c | 21 ++++++++++++++++++--- sys/netinet/ip_output.c | 3 ++- sys/netinet6/nd6.c | 25 +++++++++++++++---------- 7 files changed, 68 insertions(+), 31 deletions(-) diff --git a/sys/net/route.c b/sys/net/route.c index e9e950fd926..d19a4cfc0af 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -848,18 +848,6 @@ rt_mpath_unlink(struct rib_head *rnh, struct rt_addrinfo *info, } #endif -void -rt_setmetrics(const struct rt_addrinfo *info, struct rtentry *rt) -{ - - if (info->rti_mflags & RTV_WEIGHT) - rt->rt_weight = info->rti_rmx->rmx_weight; - /* 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; -} - void rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, struct sockaddr *netmask) { diff --git a/sys/net/route.h b/sys/net/route.h index d09e6b21ed7..19c9ce0eb51 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -104,6 +104,10 @@ struct rt_metrics { /* lle state is exported in rmx_state rt_metrics field */ #define rmx_state rmx_weight +/* default route weight */ +#define RT_DEFAULT_WEIGHT 1 +#define RT_MAX_WEIGHT 16777215 /* 3 bytes */ + /* * Keep a generation count of routing table, incremented on route addition, * so we can invalidate caches. This is accessed without a lock, as precision diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c index 75cc3c2a527..37c23e2cb1c 100644 --- a/sys/net/route/route_ctl.c +++ b/sys/net/route/route_ctl.c @@ -175,6 +175,32 @@ get_rnh(uint32_t fibnum, const struct rt_addrinfo *info) return (rnh); } +static int +get_info_weight(const struct rt_addrinfo *info, uint32_t default_weight) +{ + uint32_t weight; + + if (info->rti_mflags & RTV_WEIGHT) + weight = info->rti_rmx->rmx_weight; + else + weight = default_weight; + /* Keep upper 1 byte for adm distance purposes */ + if (weight > RT_MAX_WEIGHT) + weight = RT_MAX_WEIGHT; + + return (weight); +} + +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. * @@ -423,9 +449,8 @@ create_rtentry(struct rib_head *rnh, struct rt_addrinfo *info, * examine the ifa and ifa->ifa_ifp if it so desires. */ ifa = info->rti_ifa; - rt->rt_weight = 1; - - rt_setmetrics(info, rt); + rt->rt_weight = get_info_weight(info, RT_DEFAULT_WEIGHT); + rt_set_expire_info(rt, info); *prt = rt; return (0); @@ -815,7 +840,7 @@ change_route_nhop(struct rib_head *rnh, struct rtentry *rt, if (rnd->rnd_nhop != NULL) { /* Changing expiration & nexthop & weight to a new one */ - rt_setmetrics(info, rt); + rt_set_expire_info(rt, info); rt->rt_nhop = rnd->rnd_nhop; rt->rt_weight = rnd->rnd_weight; if (rt->rt_expire > 0) diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h index 1ed4f5e95d6..6164ec08850 100644 --- a/sys/net/route/route_var.h +++ b/sys/net/route/route_var.h @@ -115,7 +115,6 @@ _Static_assert(__offsetof(struct route, ro_dst) == __offsetof(_ro_new, _dst_new) struct rib_head *rt_tables_get_rnh(uint32_t table, sa_family_t family); void rt_mpath_init_rnh(struct rib_head *rnh); int rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum); -void rt_setmetrics(const struct rt_addrinfo *info, struct rtentry *rt); #ifdef RADIX_MPATH struct radix_node *rt_mpath_unlink(struct rib_head *rnh, struct rt_addrinfo *info, struct rtentry *rto, int *perror); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index dea5f8b4ebb..f3b0ecec243 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -175,6 +175,8 @@ static int rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, static int rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo); static int sysctl_dumpentry(struct radix_node *rn, void *vw); +static int sysctl_dumpnhop(struct rtentry *rt, struct nhop_object *nh, + uint32_t weight, struct walkarg *w); static int sysctl_iflist(int af, struct walkarg *w); static int sysctl_ifmalist(int af, struct walkarg *w); static int route_output(struct mbuf *m, struct socket *so, ...); @@ -740,6 +742,7 @@ handle_rtm_get(struct rt_addrinfo *info, u_int fibnum, } } rc->rc_nh_new = rc->rc_rt->rt_nhop; + rc->rc_nh_weight = rc->rc_rt->rt_weight; RIB_RUNLOCK(rnh); return (0); @@ -1696,9 +1699,7 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) struct walkarg *w = vw; struct rtentry *rt = (struct rtentry *)rn; struct nhop_object *nh; - int error = 0, size; - struct rt_addrinfo info; - struct sockaddr_storage ss; + int error = 0; NET_EPOCH_ASSERT(); @@ -1707,6 +1708,20 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) if (!can_export_rte(w->w_req->td->td_ucred, rt)) return (0); nh = rt->rt_nhop; + error = sysctl_dumpnhop(rt, nh, rt->rt_weight, w); + + return (0); +} + + +static int +sysctl_dumpnhop(struct rtentry *rt, struct nhop_object *nh, uint32_t weight, + struct walkarg *w) +{ + struct rt_addrinfo info; + int error = 0, size; + struct sockaddr_storage ss; + bzero((caddr_t)&info, sizeof(info)); info.rti_info[RTAX_DST] = rt_key(rt); info.rti_info[RTAX_GATEWAY] = &nh->gw_sa; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index dde8a1389f9..a26722c97f8 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -512,7 +512,8 @@ again: } else { struct nhop_object *nh; - nh = fib4_lookup(M_GETFIB(m), ip->ip_dst, 0, NHR_NONE, 0); + nh = fib4_lookup(M_GETFIB(m), ip->ip_dst, 0, NHR_NONE, + m->m_pkthdr.flowid); if (nh == NULL) { #if defined(IPSEC) || defined(IPSEC_SUPPORT) /* diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 7af9cc385b8..ad31d750eb7 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1570,25 +1570,30 @@ nd6_free_redirect(const struct llentry *ln) /* * Updates status of the default router route. */ -void -nd6_subscription_cb(struct rib_head *rnh, struct rib_cmd_info *rc, void *arg) +static void +check_release_defrouter(struct rib_cmd_info *rc, void *_cbdata) { struct nd_defrouter *dr; struct nhop_object *nh; - if (rc->rc_cmd == RTM_DELETE) { - nh = rc->rc_nh_old; + nh = rc->rc_nh_old; - if (nh->nh_flags & NHF_DEFAULT) { - dr = defrouter_lookup(&nh->gw6_sa.sin6_addr, nh->nh_ifp); - if (dr != NULL) { - dr->installed = 0; - defrouter_rele(dr); - } + if ((nh != NULL) && (nh->nh_flags & NHF_DEFAULT)) { + dr = defrouter_lookup(&nh->gw6_sa.sin6_addr, nh->nh_ifp); + if (dr != NULL) { + dr->installed = 0; + defrouter_rele(dr); } } } +void +nd6_subscription_cb(struct rib_head *rnh, struct rib_cmd_info *rc, void *arg) +{ + + check_release_defrouter(rc, NULL); +} + int nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp) {