Index: head/sys/net/route.h =================================================================== --- head/sys/net/route.h +++ head/sys/net/route.h @@ -104,6 +104,10 @@ /* 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 Index: head/sys/net/route.c =================================================================== --- head/sys/net/route.c +++ head/sys/net/route.c @@ -849,18 +849,6 @@ #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) { u_char *cp1 = (u_char *)src; Index: head/sys/net/route/route_ctl.c =================================================================== --- head/sys/net/route/route_ctl.c +++ head/sys/net/route/route_ctl.c @@ -175,6 +175,32 @@ 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,10 +449,9 @@ * examine the ifa and ifa->ifa_ifp if it so desires. */ ifa = info->rti_ifa; - rt->rt_weight = 1; + rt->rt_weight = get_info_weight(info, RT_DEFAULT_WEIGHT); + rt_set_expire_info(rt, info); - rt_setmetrics(info, rt); - *prt = rt; return (0); } @@ -815,7 +840,7 @@ 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) Index: head/sys/net/route/route_var.h =================================================================== --- head/sys/net/route/route_var.h +++ head/sys/net/route/route_var.h @@ -115,7 +115,6 @@ 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); Index: head/sys/net/rtsock.c =================================================================== --- head/sys/net/rtsock.c +++ head/sys/net/rtsock.c @@ -175,6 +175,8 @@ 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 @@ } } 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 @@ 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 @@ 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; Index: head/sys/netinet/ip_output.c =================================================================== --- head/sys/netinet/ip_output.c +++ head/sys/netinet/ip_output.c @@ -512,7 +512,8 @@ } 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) /* Index: head/sys/netinet6/nd6.c =================================================================== --- head/sys/netinet6/nd6.c +++ head/sys/netinet6/nd6.c @@ -1570,23 +1570,28 @@ /* * 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