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
This commit is contained in:
Alexander V. Chernikov 2020-09-21 20:02:26 +00:00
parent 7b3286c189
commit 2259a03020
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=365973
7 changed files with 68 additions and 31 deletions

View File

@ -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)
{

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -512,7 +512,8 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
} 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)
/*

View File

@ -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)
{