Page MenuHomeFreeBSD

D24340.diff
No OneTemporary

D24340.diff

Index: sys/kern/uipc_ktls.c
===================================================================
--- sys/kern/uipc_ktls.c
+++ sys/kern/uipc_ktls.c
@@ -58,6 +58,7 @@
#include <net/if_var.h>
#ifdef RSS
#include <net/netisr.h>
+#include <net/nhop.h>
#include <net/rss_config.h>
#endif
#if defined(INET) || defined(INET6)
@@ -754,7 +755,7 @@
{
union if_snd_tag_alloc_params params;
struct ifnet *ifp;
- struct rtentry *rt;
+ struct nhop_object *nh;
struct tcpcb *tp;
int error;
@@ -792,12 +793,12 @@
* enabled after a connection has completed key negotiation in
* userland, the cached route will be present in practice.
*/
- rt = inp->inp_route.ro_rt;
- if (rt == NULL || rt->rt_ifp == NULL) {
+ nh = inp->inp_route.ro_nh;
+ if (nh == NULL) {
INP_RUNLOCK(inp);
return (ENXIO);
}
- ifp = rt->rt_ifp;
+ ifp = nh->nh_ifp;
if_ref(ifp);
params.hdr.type = IF_SND_TAG_TYPE_TLS;
Index: sys/net/radix_mpath.c
===================================================================
--- sys/net/radix_mpath.c
+++ sys/net/radix_mpath.c
@@ -54,6 +54,8 @@
#include <net/radix_mpath.h>
#include <sys/rmlock.h>
#include <net/route.h>
+#include <net/route/nhop.h>
+#include <net/route/shared.h>
#include <net/route_var.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -253,42 +255,41 @@
void
rtalloc_mpath_fib(struct route *ro, uint32_t hash, u_int fibnum)
{
- struct rtentry *rt;
+ struct rtentry *rt, *rt_tmp;
/*
* XXX we don't attempt to lookup cached route again; what should
* be done for sendto(3) case?
*/
- if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)
- && RT_LINK_IS_UP(ro->ro_rt->rt_ifp))
+ if (ro->ro_nh && RT_LINK_IS_UP(ro->ro_nh->nh_ifp))
return;
- ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum);
+ ro->ro_nh = NULL;
+ rt_tmp = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum);
/* if the route does not exist or it is not multipath, don't care */
- if (ro->ro_rt == NULL)
+ if (rt_tmp == NULL)
return;
- if (rn_mpath_next((struct radix_node *)ro->ro_rt) == NULL) {
- RT_UNLOCK(ro->ro_rt);
+ if (rn_mpath_next((struct radix_node *)rt_tmp) == NULL) {
+ ro->ro_nh = rt_tmp->rt_nhop;
+ nhop_ref_object(ro->ro_nh);
+ RT_UNLOCK(rt_tmp);
return;
}
- rt = rt_mpath_selectrte(ro->ro_rt, hash);
+ rt = rt_mpath_selectrte(rt_tmp, hash);
/* XXX try filling rt_gwroute and avoid unreachable gw */
/* gw selection has failed - there must be only zero weight routes */
if (!rt) {
- RT_UNLOCK(ro->ro_rt);
- ro->ro_rt = NULL;
+ RT_UNLOCK(rt_tmp);
return;
}
- if (ro->ro_rt != rt) {
- RTFREE_LOCKED(ro->ro_rt);
- ro->ro_rt = rt;
- RT_LOCK(ro->ro_rt);
- RT_ADDREF(ro->ro_rt);
-
- }
- RT_UNLOCK(ro->ro_rt);
+ if (rt_tmp != rt) {
+ RTFREE_LOCKED(rt_tmp);
+ ro->ro_nh = rt->rt_nhop;
+ nhop_ref_object(ro->ro_nh);
+ } else
+ RT_UNLOCK(rt_tmp);
}
void
Index: sys/net/route.h
===================================================================
--- sys/net/route.h
+++ sys/net/route.h
@@ -51,7 +51,7 @@
* with its length.
*/
struct route {
- struct rtentry *ro_rt;
+ struct nhop_object *ro_nh;
struct llentry *ro_lle;
/*
* ro_prepend and ro_plen are only used for bpf to pass in a
@@ -227,21 +227,6 @@
/* Control plane route request flags */
#define NHR_COPY 0x100 /* Copy rte data */
-#ifdef _KERNEL
-/* rte<>ro_flags translation */
-static inline void
-rt_update_ro_flags(struct route *ro)
-{
- int rt_flags = ro->ro_rt->rt_flags;
-
- ro->ro_flags &= ~ (RT_REJECT|RT_BLACKHOLE|RT_HAS_GW);
-
- ro->ro_flags |= (rt_flags & RTF_REJECT) ? RT_REJECT : 0;
- ro->ro_flags |= (rt_flags & RTF_BLACKHOLE) ? RT_BLACKHOLE : 0;
- ro->ro_flags |= (rt_flags & RTF_GATEWAY) ? RT_HAS_GW : 0;
-}
-#endif
-
/*
* Routing statistics.
*/
@@ -427,12 +412,22 @@
RTFREE((_ro)->ro_rt); \
} while (0)
+#define RO_NHFREE(_ro) do { \
+ if ((_ro)->ro_nh) { \
+ NH_FREE((_ro)->ro_nh); \
+ (_ro)->ro_nh = NULL; \
+ } \
+} while (0)
+
#define RO_INVALIDATE_CACHE(ro) do { \
- RO_RTFREE(ro); \
if ((ro)->ro_lle != NULL) { \
LLE_FREE((ro)->ro_lle); \
(ro)->ro_lle = NULL; \
} \
+ if ((ro)->ro_nh != NULL) { \
+ NH_FREE((ro)->ro_nh); \
+ (ro)->ro_nh = NULL; \
+ } \
} while (0)
/*
@@ -440,7 +435,7 @@
* out-of-date cache, simply free it. Update the generation number
* for the new allocation
*/
-#define RT_VALIDATE(ro, cookiep, fibnum) do { \
+#define NH_VALIDATE(ro, cookiep, fibnum) do { \
rt_gen_t cookie = RT_GEN(fibnum, (ro)->ro_dst.sa_family); \
if (*(cookiep) != cookie) { \
RO_INVALIDATE_CACHE(ro); \
Index: sys/net/route.c
===================================================================
--- sys/net/route.c
+++ sys/net/route.c
@@ -440,15 +440,18 @@
{
struct rtentry *rt;
- if ((rt = ro->ro_rt) != NULL) {
- if (rt->rt_ifp != NULL && rt->rt_flags & RTF_UP)
+ if (ro->ro_nh != NULL) {
+ if (NH_IS_VALID(ro->ro_nh))
return;
- RTFREE(rt);
- ro->ro_rt = NULL;
+ NH_FREE(ro->ro_nh);
+ ro->ro_nh = NULL;
+ }
+ rt = rtalloc1_fib(&ro->ro_dst, 1, ignore, fibnum);
+ if (rt != NULL) {
+ ro->ro_nh = rt->rt_nhop;
+ nhop_ref_object(rt->rt_nhop);
+ RT_UNLOCK(rt);
}
- ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, ignore, fibnum);
- if (ro->ro_rt)
- RT_UNLOCK(ro->ro_rt);
}
/*
Index: sys/net/route_var.h
===================================================================
--- sys/net/route_var.h
+++ sys/net/route_var.h
@@ -80,7 +80,7 @@
CHK_STRUCT_FIELD_GENERIC(struct route, _field, _route_new, _field)
#define CHK_STRUCT_ROUTE_FIELDS(_route_new) \
- _CHK_ROUTE_FIELD(_route_new, ro_rt) \
+ _CHK_ROUTE_FIELD(_route_new, ro_nh) \
_CHK_ROUTE_FIELD(_route_new, ro_lle) \
_CHK_ROUTE_FIELD(_route_new, ro_prepend)\
_CHK_ROUTE_FIELD(_route_new, ro_plen) \
Index: sys/netinet/in_fib.h
===================================================================
--- sys/netinet/in_fib.h
+++ sys/netinet/in_fib.h
@@ -32,6 +32,19 @@
#ifndef _NETINET_IN_FIB_H_
#define _NETINET_IN_FIB_H_
+struct route_in {
+ /* common fields shared among all 'struct route' */
+ struct nhop_object *ro_nh;
+ struct llentry *ro_lle;
+ char *ro_prepend;
+ uint16_t ro_plen;
+ uint16_t ro_flags;
+ uint16_t ro_mtu; /* saved ro_rt mtu */
+ uint16_t spare;
+ /* custom sockaddr */
+ struct sockaddr_in ro_dst4;
+};
+
/* Basic nexthop info used for uRPF/mtu checks */
struct nhop4_basic {
struct ifnet *nh_ifp; /* Logical egress interface */
Index: sys/netinet/in_fib.c
===================================================================
--- sys/netinet/in_fib.c
+++ sys/netinet/in_fib.c
@@ -62,6 +62,10 @@
#include <netinet/in_fib.h>
#ifdef INET
+
+/* Verify struct route compatiblity */
+/* Assert 'struct route_in' is compatible with 'struct route' */
+CHK_STRUCT_ROUTE_COMPAT(struct route_in, ro_dst4);
static void fib4_rte_to_nh_basic(struct nhop_object *nh, struct in_addr dst,
uint32_t flags, struct nhop4_basic *pnh4);
static void fib4_rte_to_nh_extended(struct nhop_object *nh, struct in_addr dst,
Index: sys/netinet/ip_input.c
===================================================================
--- sys/netinet/ip_input.c
+++ sys/netinet/ip_input.c
@@ -63,6 +63,7 @@
#include <net/if_dl.h>
#include <net/pfil.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/netisr.h>
#include <net/rss_config.h>
#include <net/vnet.h>
@@ -72,6 +73,7 @@
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
+#include <netinet/in_fib.h>
#include <netinet/in_pcb.h>
#include <netinet/ip_var.h>
#include <netinet/ip_fw.h>
@@ -980,10 +982,11 @@
ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr),
M_GETFIB(m));
#else
- in_rtalloc_ign(&ro, 0, M_GETFIB(m));
+ ro.ro_nh = fib4_lookup(M_GETFIB(m), ip->ip_dst, 0, NHR_REF,
+ m->m_pkthdr.flowid);
#endif
- if (ro.ro_rt != NULL) {
- ia = ifatoia(ro.ro_rt->rt_ifa);
+ if (ro.ro_nh != NULL) {
+ ia = ifatoia(ro.ro_nh->nh_ifa);
} else
ia = NULL;
/*
@@ -1045,19 +1048,18 @@
dest.s_addr = 0;
if (!srcrt && V_ipsendredirects &&
ia != NULL && ia->ia_ifp == m->m_pkthdr.rcvif) {
- struct rtentry *rt;
+ struct nhop_object *nh;
- rt = ro.ro_rt;
+ nh = ro.ro_nh;
- if (rt && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
- satosin(rt_key(rt))->sin_addr.s_addr != 0) {
-#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
+ if (nh != NULL && ((nh->nh_flags & (NHF_REDIRECT|NHF_DEFAULT)) == 0)) {
+ struct in_ifaddr *nh_ia = (struct in_ifaddr *)(nh->nh_ifa);
u_long src = ntohl(ip->ip_src.s_addr);
- if (RTA(rt) &&
- (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) {
- if (rt->rt_flags & RTF_GATEWAY)
- dest.s_addr = satosin(rt->rt_gateway)->sin_addr.s_addr;
+ if (nh_ia != NULL &&
+ (src & nh_ia->ia_subnetmask) == nh_ia->ia_subnet) {
+ if (nh->nh_flags & NHF_GATEWAY)
+ dest.s_addr = nh->gw4_sa.sin_addr.s_addr;
else
dest.s_addr = ip->ip_dst.s_addr;
/* Router requirements says to only send host redirects */
@@ -1069,9 +1071,9 @@
error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, NULL);
- if (error == EMSGSIZE && ro.ro_rt)
- mtu = ro.ro_rt->rt_mtu;
- RO_RTFREE(&ro);
+ if (error == EMSGSIZE && ro.ro_nh)
+ mtu = ro.ro_nh->nh_mtu;
+ RO_NHFREE(&ro);
if (error)
IPSTAT_INC(ips_cantforward);
Index: sys/netinet/ip_output.c
===================================================================
--- sys/netinet/ip_output.c
+++ sys/netinet/ip_output.c
@@ -67,6 +67,7 @@
#include <net/netisr.h>
#include <net/pfil.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#ifdef RADIX_MPATH
#include <net/radix_mpath.h>
#endif
@@ -78,6 +79,7 @@
#include <netinet/in_kdtrace.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <netinet/in_fib.h>
#include <netinet/in_pcb.h>
#include <netinet/in_rss.h>
#include <netinet/in_var.h>
@@ -287,6 +289,19 @@
return (error);
}
+/* rte<>ro_flags translation */
+static inline void
+rt_update_ro_flags(struct route *ro)
+{
+ int nh_flags = ro->ro_nh->nh_flags;
+
+ ro->ro_flags &= ~ (RT_REJECT|RT_BLACKHOLE|RT_HAS_GW);
+
+ ro->ro_flags |= (nh_flags & NHF_REJECT) ? RT_REJECT : 0;
+ ro->ro_flags |= (nh_flags & NHF_BLACKHOLE) ? RT_BLACKHOLE : 0;
+ ro->ro_flags |= (nh_flags & NHF_GATEWAY) ? RT_HAS_GW : 0;
+}
+
/*
* IP output. The packet in mbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst).
@@ -368,7 +383,7 @@
dst = (struct sockaddr_in *)&ro->ro_dst;
else
dst = &sin;
- if (ro == NULL || ro->ro_rt == NULL) {
+ if (ro == NULL || ro->ro_nh == NULL) {
bzero(dst, sizeof(*dst));
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
@@ -380,8 +395,8 @@
* Validate route against routing table additions;
* a better/more specific route might have been added.
*/
- if (inp != NULL && ro != NULL && ro->ro_rt != NULL)
- RT_VALIDATE(ro, &inp->inp_rt_cookie, fibnum);
+ if (inp != NULL && ro != NULL && ro->ro_nh != NULL)
+ NH_VALIDATE(ro, &inp->inp_rt_cookie, fibnum);
/*
* If there is a cached route,
* check that it is to the same destination
@@ -390,9 +405,8 @@
* cache with IPv6.
* Also check whether routing cache needs invalidation.
*/
- if (ro != NULL && ro->ro_rt != NULL &&
- ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- ro->ro_rt->rt_ifp == NULL || !RT_LINK_IS_UP(ro->ro_rt->rt_ifp) ||
+ if (ro != NULL && ro->ro_nh != NULL &&
+ ((!NH_IS_VALID(ro->ro_nh)) || !RT_LINK_IS_UP(ro->ro_nh->nh_ifp) ||
dst->sin_family != AF_INET ||
dst->sin_addr.s_addr != ip->ip_dst.s_addr))
RO_INVALIDATE_CACHE(ro);
@@ -450,7 +464,7 @@
else
src.s_addr = INADDR_ANY;
} else if (ro != NULL) {
- if (ro->ro_rt == NULL) {
+ if (ro->ro_nh == NULL) {
/*
* We want to do any cloning requested by the link
* layer, as this is probably required in all cases
@@ -461,12 +475,11 @@
ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr),
fibnum);
#else
- in_rtalloc_ign(ro, 0, fibnum);
+ ro->ro_nh = fib4_lookup(fibnum, dst->sin_addr, 0,
+ NHR_REF, m->m_pkthdr.flowid);
#endif
- if (ro->ro_rt == NULL ||
- (ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- ro->ro_rt->rt_ifp == NULL ||
- !RT_LINK_IS_UP(ro->ro_rt->rt_ifp)) {
+ if (ro->ro_nh == NULL || (!NH_IS_VALID(ro->ro_nh)) ||
+ !RT_LINK_IS_UP(ro->ro_nh->nh_ifp)) {
#if defined(IPSEC) || defined(IPSEC_SUPPORT)
/*
* There is no route for this packet, but it is
@@ -481,20 +494,20 @@
goto bad;
}
}
- ia = ifatoia(ro->ro_rt->rt_ifa);
- ifp = ro->ro_rt->rt_ifp;
- counter_u64_add(ro->ro_rt->rt_pksent, 1);
+ ia = ifatoia(ro->ro_nh->nh_ifa);
+ ifp = ro->ro_nh->nh_ifp;
+ counter_u64_add(ro->ro_nh->nh_pksent, 1);
rt_update_ro_flags(ro);
- if (ro->ro_rt->rt_flags & RTF_GATEWAY)
- gw = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
- if (ro->ro_rt->rt_flags & RTF_HOST)
- isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST);
+ if (ro->ro_nh->nh_flags & NHF_GATEWAY)
+ gw = &ro->ro_nh->gw4_sa;
+ if (ro->ro_nh->nh_flags & NHF_HOST)
+ isbroadcast = (ro->ro_nh->nh_flags & NHF_BROADCAST);
else if (ifp->if_flags & IFF_BROADCAST)
isbroadcast = in_ifaddr_broadcast(gw->sin_addr, ia);
else
isbroadcast = 0;
- if (ro->ro_rt->rt_flags & RTF_HOST)
- mtu = ro->ro_rt->rt_mtu;
+ if (ro->ro_nh->nh_flags & NHF_HOST)
+ mtu = ro->ro_nh->nh_mtu;
else
mtu = ifp->if_mtu;
src = IA_SIN(ia)->sin_addr;
@@ -537,9 +550,9 @@
}
/* Catch a possible divide by zero later. */
- KASSERT(mtu > 0, ("%s: mtu %d <= 0, ro=%p (rt_flags=0x%08x) ifp=%p",
+ KASSERT(mtu > 0, ("%s: mtu %d <= 0, ro=%p (nh_flags=0x%08x) ifp=%p",
__func__, mtu, ro,
- (ro != NULL && ro->ro_rt != NULL) ? ro->ro_rt->rt_flags : 0, ifp));
+ (ro != NULL && ro->ro_nh != NULL) ? ro->ro_nh->nh_flags : 0, ifp));
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
m->m_flags |= M_MCAST;
@@ -702,7 +715,7 @@
case -1: /* Need to try again */
/* Reset everything for a new round */
if (ro != NULL) {
- RO_RTFREE(ro);
+ RO_NHFREE(ro);
ro->ro_prepend = NULL;
}
gw = dst;
Index: sys/netinet/sctp_asconf.c
===================================================================
--- sys/netinet/sctp_asconf.c
+++ sys/netinet/sctp_asconf.c
@@ -980,8 +980,7 @@
((ifn == NULL) ||
(SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) {
/* clear any cached route */
- RTFREE(net->ro.ro_rt);
- net->ro.ro_rt = NULL;
+ RO_NHFREE(&net->ro);
}
/* clear any cached source address */
if (net->src_addr_selected) {
@@ -1090,10 +1089,7 @@
if (addrnum == 1) {
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
/* clear any cached route and source address */
- if (net->ro.ro_rt) {
- RTFREE(net->ro.ro_rt);
- net->ro.ro_rt = NULL;
- }
+ RO_NHFREE(&net->ro);
if (net->src_addr_selected) {
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
@@ -1112,10 +1108,7 @@
/* Multiple local addresses exsist in the association. */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
/* clear any cached route and source address */
- if (net->ro.ro_rt) {
- RTFREE(net->ro.ro_rt);
- net->ro.ro_rt = NULL;
- }
+ RO_NHFREE(&net->ro);
if (net->src_addr_selected) {
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
@@ -1131,7 +1124,7 @@
SCTP_RTALLOC((sctp_route_t *)&net->ro,
stcb->sctp_ep->def_vrf_id,
stcb->sctp_ep->fibnum);
- if (net->ro.ro_rt == NULL)
+ if (net->ro.ro_nh == NULL)
continue;
changed = 0;
@@ -2214,18 +2207,13 @@
struct sctp_nets *net;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- sctp_rtentry_t *rt;
/* delete this address if cached */
if (net->ro._s_addr == ifa) {
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
net->src_addr_selected = 0;
- rt = net->ro.ro_rt;
- if (rt) {
- RTFREE(rt);
- net->ro.ro_rt = NULL;
- }
+ RO_NHFREE(&net->ro);
/*
* Now we deleted our src address,
* should we not also now reset the
Index: sys/netinet/sctp_os_bsd.h
===================================================================
--- sys/netinet/sctp_os_bsd.h
+++ sys/netinet/sctp_os_bsd.h
@@ -71,11 +71,13 @@
#include <net/if_types.h>
#include <net/if_var.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/vnet.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#include <netinet/in_fib.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
#include <netinet/ip_var.h>
@@ -85,6 +87,7 @@
#ifdef INET6
#include <sys/domain.h>
#include <netinet/ip6.h>
+#include <netinet6/in6_fib.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_pcb.h>
#include <netinet6/ip6protosw.h>
@@ -199,15 +202,15 @@
#define SCTP_INIT_VRF_TABLEID(vrf)
#define SCTP_IFN_IS_IFT_LOOP(ifn) ((ifn)->ifn_type == IFT_LOOP)
-#define SCTP_ROUTE_IS_REAL_LOOP(ro) ((ro)->ro_rt && (ro)->ro_rt->rt_ifa && (ro)->ro_rt->rt_ifa->ifa_ifp && (ro)->ro_rt->rt_ifa->ifa_ifp->if_type == IFT_LOOP)
+#define SCTP_ROUTE_IS_REAL_LOOP(ro) ((ro)->ro_nh && (ro)->ro_nh->nh_ifa && (ro)->ro_nh->nh_ifa->ifa_ifp && (ro)->ro_nh->nh_ifa->ifa_ifp->if_type == IFT_LOOP)
/*
* Access to IFN's to help with src-addr-selection
*/
/* This could return VOID if the index works but for BSD we provide both. */
-#define SCTP_GET_IFN_VOID_FROM_ROUTE(ro) (void *)ro->ro_rt->rt_ifp
-#define SCTP_GET_IF_INDEX_FROM_ROUTE(ro) (ro)->ro_rt->rt_ifp->if_index
-#define SCTP_ROUTE_HAS_VALID_IFN(ro) ((ro)->ro_rt && (ro)->ro_rt->rt_ifp)
+#define SCTP_GET_IFN_VOID_FROM_ROUTE(ro) (void *)ro->ro_nh->nh_ifp
+#define SCTP_GET_IF_INDEX_FROM_ROUTE(ro) (ro)->ro_nh->nh_ifp->if_index
+#define SCTP_ROUTE_HAS_VALID_IFN(ro) ((ro)->ro_nh && (ro)->ro_nh->nh_ifp)
/*
* general memory allocation
@@ -304,12 +307,10 @@
/* MTU */
/*************************/
#define SCTP_GATHER_MTU_FROM_IFN_INFO(ifn, ifn_index, af) ((struct ifnet *)ifn)->if_mtu
-#define SCTP_GATHER_MTU_FROM_ROUTE(sctp_ifa, sa, rt) ((uint32_t)((rt != NULL) ? rt->rt_mtu : 0))
+#define SCTP_GATHER_MTU_FROM_ROUTE(sctp_ifa, sa, nh) ((uint32_t)((nh != NULL) ? nh->nh_mtu : 0))
#define SCTP_GATHER_MTU_FROM_INTFC(sctp_ifn) ((sctp_ifn->ifn_p != NULL) ? ((struct ifnet *)(sctp_ifn->ifn_p))->if_mtu : 0)
-#define SCTP_SET_MTU_OF_ROUTE(sa, rt, mtu) do { \
- if (rt != NULL) \
- rt->rt_mtu = mtu; \
- } while(0)
+/* XXX: Setting MTU from the protocol in this way is simply incorrect */
+#define SCTP_SET_MTU_OF_ROUTE(sa, rt, mtu)
/* (de-)register interface event notifications */
#define SCTP_REGISTER_INTERFACE(ifhandle, af)
@@ -365,7 +366,7 @@
*/
/* get the v6 hop limit */
-#define SCTP_GET_HLIM(inp, ro) in6_selecthlim(&inp->ip_inp.inp, (ro ? (ro->ro_rt ? (ro->ro_rt->rt_ifp) : (NULL)) : (NULL)));
+#define SCTP_GET_HLIM(inp, ro) in6_selecthlim(&inp->ip_inp.inp, (ro ? (ro->ro_nh ? (ro->ro_nh->nh_ifp) : (NULL)) : (NULL)));
/* is the endpoint v6only? */
#define SCTP_IPV6_V6ONLY(sctp_inpcb) ((sctp_inpcb)->ip_inp.inp.inp_flags & IN6P_IPV6_V6ONLY)
@@ -397,10 +398,16 @@
* routes, output, etc.
*/
typedef struct route sctp_route_t;
-typedef struct rtentry sctp_rtentry_t;
#define SCTP_RTALLOC(ro, vrf_id, fibnum) \
- rtalloc_ign_fib((struct route *)ro, 0UL, fibnum)
+{ \
+ if ((ro)->ro_nh == NULL) { \
+ if ((ro)->ro_dst.sa_family == AF_INET) \
+ (ro)->ro_nh = fib4_lookup(fibnum, ((struct sockaddr_in *)&(ro)->ro_dst)->sin_addr, NHR_REF, 0, 0); \
+ if ((ro)->ro_dst.sa_family == AF_INET6) \
+ (ro)->ro_nh = fib6_lookup(fibnum, &((struct sockaddr_in6 *)&(ro)->ro_dst)->sin6_addr, NHR_REF, 0, 0); \
+ } \
+}
/*
* SCTP protocol specific mbuf flags.
Index: sys/netinet/sctp_output.c
===================================================================
--- sys/netinet/sctp_output.c
+++ sys/netinet/sctp_output.c
@@ -3387,13 +3387,13 @@
* addresses. If the bound set is NOT assigned to the interface then
* we must use rotation amongst the bound addresses..
*/
- if (ro->ro_rt == NULL) {
+ if (ro->ro_nh == NULL) {
/*
* Need a route to cache.
*/
SCTP_RTALLOC(ro, vrf_id, inp->fibnum);
}
- if (ro->ro_rt == NULL) {
+ if (ro->ro_nh == NULL) {
return (NULL);
}
fam = ro->ro_dst.sa_family;
@@ -4131,10 +4131,7 @@
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
net->src_addr_selected = 0;
- if (ro->ro_rt) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = NULL;
- }
+ RO_NHFREE(ro);
}
if (net->src_addr_selected == 0) {
/* Cache the source address */
@@ -4206,7 +4203,7 @@
* catch that somewhere and abort the association
* right away (assuming this is an INIT being sent).
*/
- if (ro->ro_rt == NULL) {
+ if (ro->ro_nh == NULL) {
/*
* src addr selection failed to find a route
* (or valid source addr), so we can't get
@@ -4225,7 +4222,7 @@
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Destination is %x\n",
(uint32_t)(ntohl(ip->ip_dst.s_addr)));
SCTPDBG(SCTP_DEBUG_OUTPUT3, "RTP route is %p through\n",
- (void *)ro->ro_rt);
+ (void *)ro->ro_nh);
if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
/* failed to prepend data, give up */
@@ -4278,13 +4275,13 @@
SCTPDBG(SCTP_DEBUG_OUTPUT3, "IP output returns %d\n", ret);
if (net == NULL) {
/* free tempy routes */
- RO_RTFREE(ro);
+ RO_NHFREE(ro);
} else {
- if ((ro->ro_rt != NULL) && (net->ro._s_addr) &&
+ if ((ro->ro_nh != NULL) && (net->ro._s_addr) &&
((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0)) {
uint32_t mtu;
- mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
+ mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_nh);
if (mtu > 0) {
if (net->port) {
mtu -= sizeof(struct udphdr);
@@ -4296,7 +4293,7 @@
net->mtu = mtu;
}
}
- } else if (ro->ro_rt == NULL) {
+ } else if (ro->ro_nh == NULL) {
/* route was freed */
if (net->ro._s_addr &&
net->src_addr_selected) {
@@ -4426,10 +4423,7 @@
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
net->src_addr_selected = 0;
- if (ro->ro_rt) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = NULL;
- }
+ RO_NHFREE(ro);
}
if (net->src_addr_selected == 0) {
sin6 = (struct sockaddr_in6 *)&net->ro._l_addr;
@@ -4489,7 +4483,7 @@
}
lsa6->sin6_port = inp->sctp_lport;
- if (ro->ro_rt == NULL) {
+ if (ro->ro_nh == NULL) {
/*
* src addr selection failed to find a route
* (or valid source addr), so we can't get
@@ -4625,13 +4619,13 @@
}
if (net == NULL) {
/* Now if we had a temp route free it */
- RO_RTFREE(ro);
+ RO_NHFREE(ro);
} else {
/*
* PMTU check versus smallest asoc MTU goes
* here
*/
- if (ro->ro_rt == NULL) {
+ if (ro->ro_nh == NULL) {
/* Route was freed */
if (net->ro._s_addr &&
net->src_addr_selected) {
@@ -4640,11 +4634,11 @@
}
net->src_addr_selected = 0;
}
- if ((ro->ro_rt != NULL) && (net->ro._s_addr) &&
+ if ((ro->ro_nh != NULL) && (net->ro._s_addr) &&
((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0)) {
uint32_t mtu;
- mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
+ mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_nh);
if (mtu > 0) {
if (net->port) {
mtu -= sizeof(struct udphdr);
@@ -13838,7 +13832,7 @@
struct nd_pfxrouter *pfxrtr = NULL;
struct sockaddr_in6 gw6;
- if (ro == NULL || ro->ro_rt == NULL || src6->sin6_family != AF_INET6)
+ if (ro == NULL || ro->ro_nh == NULL || src6->sin6_family != AF_INET6)
return (0);
/* get prefix entry of address */
@@ -13871,8 +13865,8 @@
SCTPDBG(SCTP_DEBUG_OUTPUT2, "prefix router is ");
SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&gw6);
SCTPDBG(SCTP_DEBUG_OUTPUT2, "installed router is ");
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, ro->ro_rt->rt_gateway);
- if (sctp_cmpaddr((struct sockaddr *)&gw6, ro->ro_rt->rt_gateway)) {
+ SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, &ro->ro_nh->gw_sa);
+ if (sctp_cmpaddr((struct sockaddr *)&gw6, &ro->ro_nh->gw_sa)) {
ND6_RUNLOCK();
SCTPDBG(SCTP_DEBUG_OUTPUT2, "pfxrouter is installed\n");
return (1);
@@ -13892,7 +13886,7 @@
struct ifaddr *ifa;
struct in_addr srcnetaddr, gwnetaddr;
- if (ro == NULL || ro->ro_rt == NULL ||
+ if (ro == NULL || ro->ro_nh == NULL ||
sifa->address.sa.sa_family != AF_INET) {
return (0);
}
@@ -13904,10 +13898,10 @@
SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, &sifa->address.sa);
SCTPDBG(SCTP_DEBUG_OUTPUT1, "network address is %x\n", srcnetaddr.s_addr);
- sin = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
+ sin = &ro->ro_nh->gw4_sa;
gwnetaddr.s_addr = (sin->sin_addr.s_addr & mask->sin_addr.s_addr);
SCTPDBG(SCTP_DEBUG_OUTPUT1, "match_nexthop4: nexthop is ");
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, ro->ro_rt->rt_gateway);
+ SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, &ro->ro_nh->gw4_sa);
SCTPDBG(SCTP_DEBUG_OUTPUT1, "network address is %x\n", gwnetaddr.s_addr);
if (srcnetaddr.s_addr == gwnetaddr.s_addr) {
return (1);
Index: sys/netinet/sctp_pcb.c
===================================================================
--- sys/netinet/sctp_pcb.c
+++ sys/netinet/sctp_pcb.c
@@ -3976,17 +3976,9 @@
} else {
imtu = 0;
}
- rmtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, net->ro.ro_rt);
+ rmtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, net->ro.ro_nh);
hcmtu = sctp_hc_get_mtu(&net->ro._l_addr, stcb->sctp_ep->fibnum);
net->mtu = sctp_min_mtu(hcmtu, rmtu, imtu);
- if (rmtu == 0) {
- /*
- * Start things off to match mtu of
- * interface please.
- */
- SCTP_SET_MTU_OF_ROUTE(&net->ro._l_addr.sa,
- net->ro.ro_rt, net->mtu);
- }
}
}
if (net->mtu == 0) {
@@ -4067,19 +4059,19 @@
*netp = net;
}
netfirst = TAILQ_FIRST(&stcb->asoc.nets);
- if (net->ro.ro_rt == NULL) {
+ if (net->ro.ro_nh == NULL) {
/* Since we have no route put it at the back */
TAILQ_INSERT_TAIL(&stcb->asoc.nets, net, sctp_next);
} else if (netfirst == NULL) {
/* We are the first one in the pool. */
TAILQ_INSERT_HEAD(&stcb->asoc.nets, net, sctp_next);
- } else if (netfirst->ro.ro_rt == NULL) {
+ } else if (netfirst->ro.ro_nh == NULL) {
/*
* First one has NO route. Place this one ahead of the first
* one.
*/
TAILQ_INSERT_HEAD(&stcb->asoc.nets, net, sctp_next);
- } else if (net->ro.ro_rt->rt_ifp != netfirst->ro.ro_rt->rt_ifp) {
+ } else if (net->ro.ro_nh->nh_ifp != netfirst->ro.ro_nh->nh_ifp) {
/*
* This one has a different interface than the one at the
* top of the list. Place it ahead.
@@ -4100,11 +4092,11 @@
/* End of the list */
TAILQ_INSERT_TAIL(&stcb->asoc.nets, net, sctp_next);
break;
- } else if (netlook->ro.ro_rt == NULL) {
+ } else if (netlook->ro.ro_nh == NULL) {
/* next one has NO route */
TAILQ_INSERT_BEFORE(netfirst, net, sctp_next);
break;
- } else if (netlook->ro.ro_rt->rt_ifp != net->ro.ro_rt->rt_ifp) {
+ } else if (netlook->ro.ro_nh->nh_ifp != net->ro.ro_nh->nh_ifp) {
TAILQ_INSERT_AFTER(&stcb->asoc.nets, netlook,
net, sctp_next);
break;
@@ -4117,8 +4109,8 @@
/* got to have a primary set */
if (stcb->asoc.primary_destination == 0) {
stcb->asoc.primary_destination = net;
- } else if ((stcb->asoc.primary_destination->ro.ro_rt == NULL) &&
- (net->ro.ro_rt) &&
+ } else if ((stcb->asoc.primary_destination->ro.ro_nh == NULL) &&
+ (net->ro.ro_nh) &&
((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0)) {
/* No route to current primary adopt new primary */
stcb->asoc.primary_destination = net;
@@ -5459,14 +5451,9 @@
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
if (net->ro._s_addr == laddr->ifa) {
/* Yep, purge src address selected */
- sctp_rtentry_t *rt;
/* delete this address if cached */
- rt = net->ro.ro_rt;
- if (rt != NULL) {
- RTFREE(rt);
- net->ro.ro_rt = NULL;
- }
+ RO_NHFREE(&net->ro);
sctp_free_ifa(net->ro._s_addr);
net->ro._s_addr = NULL;
net->src_addr_selected = 0;
Index: sys/netinet/sctp_structs.h
===================================================================
--- sys/netinet/sctp_structs.h
+++ sys/netinet/sctp_structs.h
@@ -189,7 +189,7 @@
#define SCTP_ITERATOR_STOP_CUR_INP 0x00000008
struct sctp_net_route {
- sctp_rtentry_t *ro_rt;
+ struct nhop_object *ro_nh;
struct llentry *ro_lle;
char *ro_prepend;
uint16_t ro_plen;
Index: sys/netinet/sctp_timer.c
===================================================================
--- sys/netinet/sctp_timer.c
+++ sys/netinet/sctp_timer.c
@@ -350,7 +350,7 @@
return (NULL);
}
}
- if (alt->ro.ro_rt == NULL) {
+ if (alt->ro.ro_nh == NULL) {
if (alt->ro._s_addr) {
sctp_free_ifa(alt->ro._s_addr);
alt->ro._s_addr = NULL;
@@ -358,7 +358,7 @@
alt->src_addr_selected = 0;
}
if (((alt->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE) &&
- (alt->ro.ro_rt != NULL) &&
+ (alt->ro.ro_nh != NULL) &&
(!(alt->dest_state & SCTP_ADDR_UNCONFIRMED))) {
/* Found a reachable address */
break;
@@ -937,10 +937,7 @@
net->src_addr_selected = 0;
/* Force a route allocation too */
- if (net->ro.ro_rt) {
- RTFREE(net->ro.ro_rt);
- net->ro.ro_rt = NULL;
- }
+ RO_NHFREE(&net->ro);
/* Was it our primary? */
if ((stcb->asoc.primary_destination == net) && (alt != net)) {
@@ -1502,7 +1499,7 @@
net->src_addr_selected = 1;
}
if (net->ro._s_addr) {
- mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_rt);
+ mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._s_addr.sa, net->ro.ro_nh);
#if defined(INET) || defined(INET6)
if (net->port) {
mtu -= sizeof(struct udphdr);
Index: sys/netinet/sctp_var.h
===================================================================
--- sys/netinet/sctp_var.h
+++ sys/netinet/sctp_var.h
@@ -187,10 +187,7 @@
if ((__net)) { \
if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \
(void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \
- if ((__net)->ro.ro_rt) { \
- RTFREE((__net)->ro.ro_rt); \
- (__net)->ro.ro_rt = NULL; \
- } \
+ RO_NHFREE(&(__net)->ro); \
if ((__net)->src_addr_selected) { \
sctp_free_ifa((__net)->ro._s_addr); \
(__net)->ro._s_addr = NULL; \
Index: sys/netinet/tcp_output.c
===================================================================
--- sys/netinet/tcp_output.c
+++ sys/netinet/tcp_output.c
@@ -64,6 +64,7 @@
#include <net/if.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -1411,8 +1412,8 @@
((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0),
NULL, NULL, tp->t_inpcb);
- if (error == EMSGSIZE && tp->t_inpcb->inp_route6.ro_rt != NULL)
- mtu = tp->t_inpcb->inp_route6.ro_rt->rt_mtu;
+ if (error == EMSGSIZE && tp->t_inpcb->inp_route6.ro_nh != NULL)
+ mtu = tp->t_inpcb->inp_route6.ro_nh->nh_mtu;
}
#endif /* INET6 */
#if defined(INET) && defined(INET6)
@@ -1454,8 +1455,8 @@
((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0,
tp->t_inpcb);
- if (error == EMSGSIZE && tp->t_inpcb->inp_route.ro_rt != NULL)
- mtu = tp->t_inpcb->inp_route.ro_rt->rt_mtu;
+ if (error == EMSGSIZE && tp->t_inpcb->inp_route.ro_nh != NULL)
+ mtu = tp->t_inpcb->inp_route.ro_nh->nh_mtu;
}
#endif /* INET */
Index: sys/netinet/tcp_stacks/bbr.c
===================================================================
--- sys/netinet/tcp_stacks/bbr.c
+++ sys/netinet/tcp_stacks/bbr.c
@@ -5601,8 +5601,8 @@
if (bbr->r_ctl.crte == NULL)
return;
- if ((bbr->rc_inp->inp_route.ro_rt == NULL) ||
- (bbr->rc_inp->inp_route.ro_rt->rt_ifp == NULL)) {
+ if ((bbr->rc_inp->inp_route.ro_nh == NULL) ||
+ (bbr->rc_inp->inp_route.ro_nh->nh_ifp == NULL)) {
/* Lost our routes? */
/* Clear the way for a re-attempt */
bbr->bbr_attempt_hdwr_pace = 0;
@@ -5618,7 +5618,7 @@
rate = bbr_get_hardware_rate(bbr);
nrte = tcp_chg_pacing_rate(bbr->r_ctl.crte,
bbr->rc_tp,
- bbr->rc_inp->inp_route.ro_rt->rt_ifp,
+ bbr->rc_inp->inp_route.ro_nh->nh_ifp,
rate,
(RS_PACING_GEQ|RS_PACING_SUB_OK),
&error);
@@ -13975,8 +13975,8 @@
((rsm || sack_rxmit) ? IP_NO_SND_TAG_RL : 0),
NULL, NULL, inp);
- if (error == EMSGSIZE && inp->inp_route6.ro_rt != NULL)
- mtu = inp->inp_route6.ro_rt->rt_mtu;
+ if (error == EMSGSIZE && inp->inp_route6.ro_nh != NULL)
+ mtu = inp->inp_route6.ro_nh->nh_mtu;
}
#endif /* INET6 */
#if defined(INET) && defined(INET6)
@@ -14016,8 +14016,8 @@
error = ip_output(m, inp->inp_options, &inp->inp_route,
((rsm || sack_rxmit) ? IP_NO_SND_TAG_RL : 0), 0,
inp);
- if (error == EMSGSIZE && inp->inp_route.ro_rt != NULL)
- mtu = inp->inp_route.ro_rt->rt_mtu;
+ if (error == EMSGSIZE && inp->inp_route.ro_nh != NULL)
+ mtu = inp->inp_route.ro_nh->nh_mtu;
}
#endif /* INET */
out:
@@ -14302,8 +14302,8 @@
(bbr->rc_past_init_win) &&
(bbr->rc_bbr_state != BBR_STATE_STARTUP) &&
(get_filter_value(&bbr->r_ctl.rc_delrate)) &&
- (inp->inp_route.ro_rt &&
- inp->inp_route.ro_rt->rt_ifp)) {
+ (inp->inp_route.ro_nh &&
+ inp->inp_route.ro_nh->nh_ifp)) {
/*
* We are past the initial window and
* have at least one measurement so we
@@ -14317,7 +14317,7 @@
rate_wanted = bbr_get_hardware_rate(bbr);
bbr->bbr_attempt_hdwr_pace = 1;
bbr->r_ctl.crte = tcp_set_pacing_rate(bbr->rc_tp,
- inp->inp_route.ro_rt->rt_ifp,
+ inp->inp_route.ro_nh->nh_ifp,
rate_wanted,
(RS_PACING_GEQ|RS_PACING_SUB_OK),
&err);
@@ -14344,7 +14344,7 @@
tcp_bbr_tso_size_check(bbr, cts);
} else {
bbr_type_log_hdwr_pacing(bbr,
- inp->inp_route.ro_rt->rt_ifp,
+ inp->inp_route.ro_nh->nh_ifp,
rate_wanted,
0,
__LINE__, cts, err);
@@ -14361,8 +14361,8 @@
if (inp->inp_snd_tag == NULL) {
/* A change during ip output disabled hw pacing? */
bbr->bbr_hdrw_pacing = 0;
- } else if ((inp->inp_route.ro_rt == NULL) ||
- (inp->inp_route.ro_rt->rt_ifp != inp->inp_snd_tag->ifp)) {
+ } else if ((inp->inp_route.ro_nh == NULL) ||
+ (inp->inp_route.ro_nh->nh_ifp != inp->inp_snd_tag->ifp)) {
/*
* We had an interface or route change,
* detach from the current hdwr pacing
Index: sys/netinet/tcp_subr.c
===================================================================
--- sys/netinet/tcp_subr.c
+++ sys/netinet/tcp_subr.c
@@ -76,6 +76,7 @@
#include <vm/uma.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/vnet.h>
@@ -2199,9 +2200,9 @@
if (tp->t_state == TCPS_ESTABLISHED &&
(error == EHOSTUNREACH || error == ENETUNREACH ||
error == EHOSTDOWN)) {
- if (inp->inp_route.ro_rt) {
- RTFREE(inp->inp_route.ro_rt);
- inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ if (inp->inp_route.ro_nh) {
+ NH_FREE(inp->inp_route.ro_nh);
+ inp->inp_route.ro_nh = (struct nhop_object *)NULL;
}
return (inp);
} else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
Index: sys/netinet/udp_usrreq.c
===================================================================
--- sys/netinet/udp_usrreq.c
+++ sys/netinet/udp_usrreq.c
@@ -71,6 +71,7 @@
#include <net/if.h>
#include <net/if_var.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/rss_config.h>
#include <netinet/in.h>
@@ -761,9 +762,9 @@
INP_WLOCK_ASSERT(inp);
if ((errno == EHOSTUNREACH || errno == ENETUNREACH ||
- errno == EHOSTDOWN) && inp->inp_route.ro_rt) {
- RTFREE(inp->inp_route.ro_rt);
- inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ errno == EHOSTDOWN) && inp->inp_route.ro_nh) {
+ NH_FREE(inp->inp_route.ro_nh);
+ inp->inp_route.ro_nh = (struct nhop_object *)NULL;
}
inp->inp_socket->so_error = errno;
Index: sys/netinet6/in6.h
===================================================================
--- sys/netinet6/in6.h
+++ sys/netinet6/in6.h
@@ -375,8 +375,9 @@
* IP6 route structure
*/
#if __BSD_VISIBLE
+struct nhop_object;
struct route_in6 {
- struct rtentry *ro_rt;
+ struct nhop_object *ro_nh;
struct llentry *ro_lle;
/*
* ro_prepend and ro_plen are only used for bpf to pass in a
Index: sys/netinet6/in6_pcb.c
===================================================================
--- sys/netinet6/in6_pcb.c
+++ sys/netinet6/in6_pcb.c
@@ -97,6 +97,7 @@
#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
@@ -109,6 +110,7 @@
#include <netinet6/nd6.h>
#include <netinet/in_pcb.h>
#include <netinet6/in6_pcb.h>
+#include <netinet6/in6_fib.h>
#include <netinet6/scope6_var.h>
static struct inpcb *in6_pcblookup_hash_locked(struct inpcbinfo *,
Index: sys/netinet6/in6_src.c
===================================================================
--- sys/netinet6/in6_src.c
+++ sys/netinet6/in6_src.c
@@ -91,6 +91,7 @@
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/if_llatbl.h>
#ifdef RADIX_MPATH
#include <net/radix_mpath.h>
@@ -134,7 +135,7 @@
static int selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, int, u_int);
+ struct nhop_object **, int, u_int, uint32_t);
static int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct ifnet **,
struct ifnet *, u_int);
@@ -625,11 +626,12 @@
static int
selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, int norouteok, u_int fibnum)
+ struct ifnet **retifp, struct nhop_object **retnh, int norouteok,
+ u_int fibnum, uint32_t flowid)
{
int error = 0;
struct ifnet *ifp = NULL;
- struct rtentry *rt = NULL;
+ struct nhop_object *nh = NULL;
struct sockaddr_in6 *sin6_next;
struct in6_pktinfo *pi = NULL;
struct in6_addr *dst = &dstsock->sin6_addr;
@@ -654,7 +656,7 @@
/* XXX boundary check is assumed to be already done. */
ifp = ifnet_byindex(pi->ipi6_ifindex);
if (ifp != NULL &&
- (norouteok || retrt == NULL ||
+ (norouteok || retnh == NULL ||
IN6_IS_ADDR_MULTICAST(dst))) {
/*
* we do not have to check or get the route for
@@ -707,26 +709,31 @@
}
ron = &opts->ip6po_nextroute;
/* Use a cached route if it exists and is valid. */
- if (ron->ro_rt != NULL && (
- (ron->ro_rt->rt_flags & RTF_UP) == 0 ||
+ if (ron->ro_nh != NULL && (
+ !NH_IS_VALID(ron->ro_nh) ||
ron->ro_dst.sin6_family != AF_INET6 ||
!IN6_ARE_ADDR_EQUAL(&ron->ro_dst.sin6_addr,
&sin6_next->sin6_addr)))
- RO_RTFREE(ron);
- if (ron->ro_rt == NULL) {
+ RO_NHFREE(ron);
+ if (ron->ro_nh == NULL) {
ron->ro_dst = *sin6_next;
- in6_rtalloc(ron, fibnum); /* multi path case? */
+ /*
+ * sin6_next is not link-local OR scopeid is 0,
+ * no need to clear scope
+ */
+ ron->ro_nh = fib6_lookup(fibnum,
+ &sin6_next->sin6_addr, 0, NHR_REF, flowid);
}
/*
* The node identified by that address must be a
* neighbor of the sending host.
*/
- if (ron->ro_rt == NULL ||
- (ron->ro_rt->rt_flags & RTF_GATEWAY) != 0)
+ if (ron->ro_nh == NULL ||
+ (ron->ro_nh->nh_flags & NHF_GATEWAY) != 0)
error = EHOSTUNREACH;
else {
- rt = ron->ro_rt;
- ifp = rt->rt_ifp;
+ nh = ron->ro_nh;
+ ifp = nh->nh_ifp;
}
goto done;
}
@@ -737,15 +744,14 @@
* cached destination, in case of sharing the cache with IPv4.
*/
if (ro) {
- if (ro->ro_rt &&
- (!(ro->ro_rt->rt_flags & RTF_UP) ||
+ if (ro->ro_nh &&
+ (!NH_IS_VALID(ro->ro_nh) ||
((struct sockaddr *)(&ro->ro_dst))->sa_family != AF_INET6 ||
!IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr,
dst))) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = (struct rtentry *)NULL;
+ RO_NHFREE(ro);
}
- if (ro->ro_rt == (struct rtentry *)NULL) {
+ if (ro->ro_nh == (struct nhop_object *)NULL) {
struct sockaddr_in6 *sa6;
/* No route yet, so try to acquire one */
@@ -754,15 +760,28 @@
*sa6 = *dstsock;
sa6->sin6_scope_id = 0;
+ /*
+ * Currently dst has scopeid embedded iff it is LL.
+ * New routing API accepts scopeid as a separate argument.
+ * Convert dst before/after doing lookup
+ */
+ uint32_t scopeid = 0;
+ if (IN6_IS_SCOPE_LINKLOCAL(&sa6->sin6_addr)) {
+ /* Unwrap in6_getscope() and in6_clearscope() */
+ scopeid = ntohs(sa6->sin6_addr.s6_addr16[1]);
+ sa6->sin6_addr.s6_addr16[1] = 0;
+
+ }
+
#ifdef RADIX_MPATH
rtalloc_mpath_fib((struct route *)ro,
ntohl(sa6->sin6_addr.s6_addr32[3]), fibnum);
#else
- ro->ro_rt = in6_rtalloc1((struct sockaddr *)
- &ro->ro_dst, 0, 0UL, fibnum);
- if (ro->ro_rt)
- RT_UNLOCK(ro->ro_rt);
+ ro->ro_nh = fib6_lookup(fibnum,
+ &sa6->sin6_addr, scopeid, NHR_REF, flowid);
#endif
+ if (IN6_IS_SCOPE_LINKLOCAL(&sa6->sin6_addr))
+ sa6->sin6_addr.s6_addr16[1] = htons(scopeid);
}
/*
@@ -772,17 +791,11 @@
if (opts && opts->ip6po_nexthop)
goto done;
- if (ro->ro_rt) {
- ifp = ro->ro_rt->rt_ifp;
-
- if (ifp == NULL) { /* can this really happen? */
- RTFREE(ro->ro_rt);
- ro->ro_rt = NULL;
- }
- }
- if (ro->ro_rt == NULL)
+ if (ro->ro_nh)
+ ifp = ro->ro_nh->nh_ifp;
+ else
error = EHOSTUNREACH;
- rt = ro->ro_rt;
+ nh = ro->ro_nh;
/*
* Check if the outgoing interface conflicts with
@@ -803,7 +816,7 @@
}
done:
- if (ifp == NULL && rt == NULL) {
+ if (ifp == NULL && nh == NULL) {
/*
* This can happen if the caller did not pass a cached route
* nor any other hints. We treat this case an error.
@@ -814,26 +827,14 @@
IP6STAT_INC(ip6s_noroute);
if (retifp != NULL) {
- *retifp = ifp;
-
- /*
- * Adjust the "outgoing" interface. If we're going to loop
- * the packet back to ourselves, the ifp would be the loopback
- * interface. However, we'd rather know the interface associated
- * to the destination address (which should probably be one of
- * our own addresses.)
- */
- if (rt) {
- if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
- (rt->rt_gateway->sa_family == AF_LINK))
- *retifp =
- ifnet_byindex(((struct sockaddr_dl *)
- rt->rt_gateway)->sdl_index);
- }
+ if (nh != NULL)
+ *retifp = nh->nh_aifp;
+ else
+ *retifp = ifp;
}
- if (retrt != NULL)
- *retrt = rt; /* rt may be NULL */
+ if (retnh != NULL)
+ *retnh = nh; /* nh may be NULL */
return (error);
}
@@ -845,20 +846,20 @@
{
int error;
struct route_in6 sro;
- struct rtentry *rt = NULL;
- int rt_flags;
+ struct nhop_object *nh = NULL;
+ uint16_t nh_flags;
KASSERT(retifp != NULL, ("%s: retifp is NULL", __func__));
bzero(&sro, sizeof(sro));
- rt_flags = 0;
+ nh_flags = 0;
- error = selectroute(dstsock, opts, mopts, &sro, retifp, &rt, 1, fibnum);
+ error = selectroute(dstsock, opts, mopts, &sro, retifp, &nh, 1, fibnum, 0);
- if (rt)
- rt_flags = rt->rt_flags;
- if (rt && rt == sro.ro_rt)
- RTFREE(rt);
+ if (nh != NULL)
+ nh_flags = nh->nh_flags;
+ if (nh != NULL && nh == sro.ro_nh)
+ NH_FREE(nh);
if (error != 0) {
/* Help ND. See oifp comment in in6_selectsrc(). */
@@ -887,8 +888,8 @@
* We thus reject the case here.
*/
- if (rt_flags & (RTF_REJECT | RTF_BLACKHOLE)) {
- error = (rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+ if (nh_flags & (NHF_REJECT | NHF_BLACKHOLE)) {
+ error = (nh_flags & NHF_HOST ? EHOSTUNREACH : ENETUNREACH);
return (error);
}
@@ -899,11 +900,11 @@
int
in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, u_int fibnum)
+ struct ifnet **retifp, struct nhop_object **retnh, u_int fibnum, uint32_t flowid)
{
return (selectroute(dstsock, opts, mopts, ro, retifp,
- retrt, 0, fibnum));
+ retnh, 0, fibnum, flowid));
}
/*
Index: sys/netinet6/ip6_output.c
===================================================================
--- sys/netinet6/ip6_output.c
+++ sys/netinet6/ip6_output.c
@@ -95,6 +95,7 @@
#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/route.h>
+#include <net/route/nhop.h>
#include <net/pfil.h>
#include <net/rss_config.h>
#include <net/vnet.h>
@@ -403,9 +404,9 @@
* This function may modify ver and hlim only.
* The mbuf chain containing the packet will be freed.
* The mbuf opt, if present, will not be freed.
- * If route_in6 ro is present and has ro_rt initialized, route lookup would be
- * skipped and ro->ro_rt would be used. If ro is present but ro->ro_rt is NULL,
- * then result of route lookup is stored in ro->ro_rt.
+ * If route_in6 ro is present and has ro_nh initialized, route lookup would be
+ * skipped and ro->ro_nh would be used. If ro is present but ro->ro_nh is NULL,
+ * then result of route lookup is stored in ro->ro_nh.
*
* Type of "mtu": rt_mtu is u_long, ifnet.ifr_mtu is int, and nd_ifinfo.linkmtu
* is uint32_t. So we use u_long to hold largest one, which is rt_mtu.
@@ -425,7 +426,7 @@
struct mbuf *m = m0;
struct mbuf *mprev;
struct route_in6 *ro_pmtu;
- struct rtentry *rt;
+ struct nhop_object *nh;
struct sockaddr_in6 *dst, sin6, src_sa, dst_sa;
struct in6_addr odst;
u_char *nexthdrp;
@@ -666,7 +667,7 @@
ip6->ip6_hlim = V_ip6_defmcasthlim;
}
- if (ro == NULL || ro->ro_rt == NULL) {
+ if (ro == NULL || ro->ro_nh == NULL) {
bzero(dst, sizeof(*dst));
dst->sin6_family = AF_INET6;
dst->sin6_len = sizeof(*dst);
@@ -676,29 +677,26 @@
* Validate route against routing table changes.
* Make sure that the address family is set in route.
*/
- rt = NULL;
+ nh = NULL;
ifp = NULL;
mtu = 0;
if (ro != NULL) {
- if (ro->ro_rt != NULL && inp != NULL) {
+ if (ro->ro_nh != NULL && inp != NULL) {
ro->ro_dst.sin6_family = AF_INET6; /* XXX KASSERT? */
- RT_VALIDATE((struct route *)ro, &inp->inp_rt_cookie,
+ NH_VALIDATE((struct route *)ro, &inp->inp_rt_cookie,
fibnum);
}
- if (ro->ro_rt != NULL && fwd_tag == NULL &&
- ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- ro->ro_rt->rt_ifp == NULL ||
- !RT_LINK_IS_UP(ro->ro_rt->rt_ifp) ||
+ if (ro->ro_nh != NULL && fwd_tag == NULL &&
+ (!NH_IS_VALID(ro->ro_nh) ||
ro->ro_dst.sin6_family != AF_INET6 ||
!IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)))
RO_INVALIDATE_CACHE(ro);
- if (ro->ro_rt != NULL && fwd_tag == NULL &&
- (ro->ro_rt->rt_flags & RTF_UP) &&
+ if (ro->ro_nh != NULL && fwd_tag == NULL &&
ro->ro_dst.sin6_family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)) {
- rt = ro->ro_rt;
- ifp = ro->ro_rt->rt_ifp;
+ nh = ro->ro_nh;
+ ifp = nh->nh_ifp;
} else {
if (ro->ro_lle)
LLE_FREE(ro->ro_lle); /* zeros ro_lle */
@@ -710,7 +708,7 @@
dst_sa.sin6_addr = ip6->ip6_dst;
}
error = in6_selectroute(&dst_sa, opt, im6o, ro, &ifp,
- &rt, fibnum);
+ &nh, fibnum, m->m_pkthdr.flowid);
if (error != 0) {
IP6STAT_INC(ip6s_noroute);
if (ifp != NULL)
@@ -720,17 +718,17 @@
if (ifp != NULL)
mtu = ifp->if_mtu;
}
- if (rt == NULL) {
+ if (nh == NULL) {
/*
- * If in6_selectroute() does not return a route entry
+ * If in6_selectroute() does not return a nexthop
* dst may not have been updated.
*/
*dst = dst_sa; /* XXX */
} else {
- if (rt->rt_flags & RTF_HOST)
- mtu = rt->rt_mtu;
- ia = (struct in6_ifaddr *)(rt->rt_ifa);
- counter_u64_add(rt->rt_pksent, 1);
+ if (nh->nh_flags & NHF_HOST)
+ mtu = nh->nh_mtu;
+ ia = (struct in6_ifaddr *)(nh->nh_ifa);
+ counter_u64_add(nh->nh_pksent, 1);
}
} else {
struct nhop6_extended nh6;
@@ -781,7 +779,7 @@
;
}
- /* Then rt (for unicast) and ifp must be non-NULL valid values. */
+ /* Then nh (for unicast) and ifp must be non-NULL valid values. */
if ((flags & IPV6_FORWARDING) == 0) {
/* XXX: the FORWARDING flag can be set for mrouting. */
in6_ifstat_inc(ifp, ifs6_out_request);
@@ -852,8 +850,8 @@
}
/* All scope ID checks are successful. */
- if (rt && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
- if (opt && opt->ip6po_nextroute.ro_rt) {
+ if (nh && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
+ if (opt && opt->ip6po_nextroute.ro_nh) {
/*
* The nexthop is explicitly specified by the
* application. We assume the next hop is an IPv6
@@ -861,8 +859,8 @@
*/
dst = (struct sockaddr_in6 *)opt->ip6po_nexthop;
}
- else if ((rt->rt_flags & RTF_GATEWAY))
- dst = (struct sockaddr_in6 *)rt->rt_gateway;
+ else if ((nh->nh_flags & NHF_GATEWAY))
+ dst = &nh->gw6_sa;
}
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
@@ -1517,8 +1515,8 @@
mtu = ro_pmtu->ro_mtu;
}
- if (ro_pmtu != NULL && ro_pmtu->ro_rt != NULL)
- mtu = ro_pmtu->ro_rt->rt_mtu;
+ if (ro_pmtu != NULL && ro_pmtu->ro_nh != NULL)
+ mtu = ro_pmtu->ro_nh->nh_mtu;
return (ip6_calcmtu(ifp, dst, mtu, mtup, alwaysfragp, proto));
}
@@ -2651,9 +2649,9 @@
if (optname == -1 || optname == IPV6_TCLASS)
pktopt->ip6po_tclass = -1;
if (optname == -1 || optname == IPV6_NEXTHOP) {
- if (pktopt->ip6po_nextroute.ro_rt) {
- RTFREE(pktopt->ip6po_nextroute.ro_rt);
- pktopt->ip6po_nextroute.ro_rt = NULL;
+ if (pktopt->ip6po_nextroute.ro_nh) {
+ NH_FREE(pktopt->ip6po_nextroute.ro_nh);
+ pktopt->ip6po_nextroute.ro_nh = NULL;
}
if (pktopt->ip6po_nexthop)
free(pktopt->ip6po_nexthop, M_IP6OPT);
@@ -2673,9 +2671,9 @@
if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT);
pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL;
- if (pktopt->ip6po_route.ro_rt) {
- RTFREE(pktopt->ip6po_route.ro_rt);
- pktopt->ip6po_route.ro_rt = NULL;
+ if (pktopt->ip6po_route.ro_nh) {
+ NH_FREE(pktopt->ip6po_route.ro_nh);
+ pktopt->ip6po_route.ro_nh = NULL;
}
}
if (optname == -1 || optname == IPV6_DSTOPTS) {
Index: sys/netinet6/ip6_var.h
===================================================================
--- sys/netinet6/ip6_var.h
+++ sys/netinet6/ip6_var.h
@@ -416,7 +416,7 @@
uint32_t, struct ifnet *, struct in6_addr *, int *);
int in6_selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, u_int);
+ struct nhop_object **, u_int, uint32_t);
u_int32_t ip6_randomid(void);
u_int32_t ip6_randomflowlabel(void);
void in6_delayed_cksum(struct mbuf *m, uint32_t plen, u_short offset);

File Metadata

Mime Type
text/plain
Expires
Sat, Feb 1, 7:52 AM (20 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16378602
Default Alt Text
D24340.diff (50 KB)

Event Timeline