svn commit: r235341 - in projects/rtentry_cache/sys: net netinet
netinet6
Kip Macy
kmacy at FreeBSD.org
Sat May 12 16:10:57 UTC 2012
Author: kmacy
Date: Sat May 12 16:10:56 2012
New Revision: 235341
URL: http://svn.freebsd.org/changeset/base/235341
Log:
Commit current state of rtentry patch.
Modified:
projects/rtentry_cache/sys/net/if_ethersubr.c
projects/rtentry_cache/sys/net/route.c
projects/rtentry_cache/sys/netinet/in_pcb.c
projects/rtentry_cache/sys/netinet/in_pcb.h
projects/rtentry_cache/sys/netinet/ip_output.c
projects/rtentry_cache/sys/netinet/tcp_output.c
projects/rtentry_cache/sys/netinet/tcp_usrreq.c
projects/rtentry_cache/sys/netinet6/in6_src.c
projects/rtentry_cache/sys/netinet6/ip6_forward.c
projects/rtentry_cache/sys/netinet6/ip6_output.c
projects/rtentry_cache/sys/netinet6/nd6.c
projects/rtentry_cache/sys/netinet6/nd6.h
Modified: projects/rtentry_cache/sys/net/if_ethersubr.c
==============================================================================
--- projects/rtentry_cache/sys/net/if_ethersubr.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/net/if_ethersubr.c Sat May 12 16:10:56 2012 (r235341)
@@ -146,9 +146,30 @@ int
ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared);
static VNET_DEFINE(int, ether_ipfw);
#define V_ether_ipfw VNET(ether_ipfw)
-#endif
+static __inline void
+update_cached_lle(struct route *ro, struct llentry *lle, struct ifnet *ifp,
+ struct sockaddr *dst)
+{
+
+ if (lle == ro->ro_lle ||
+ (ro->ro_flags & RT_CACHING_CONTEXT) == 0)
+ return;
+
+ IF_AFDATA_RLOCK(ifp);
+ lle = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
+ IF_AFDATA_RUNLOCK(ifp);
+ if (lle != NULL) {
+ LLE_ADDREF(lle);
+ LLE_WUNLOCK(lle);
+ if (ro->ro_lle != NULL)
+ LLE_FREE(ro->ro_lle);
+ ro->ro_lle = lle;
+ }
+}
+#endif
+
/*
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
@@ -198,6 +219,8 @@ ether_output(struct ifnet *ifp, struct m
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
+ if (ro != NULL)
+ update_cached_lle(ro, lle, ifp, dst);
break;
case AF_ARP:
{
@@ -236,6 +259,8 @@ ether_output(struct ifnet *ifp, struct m
if (error)
return error;
type = htons(ETHERTYPE_IPV6);
+ if (ro != NULL)
+ update_cached_lle(ro, lle, ifp, dst);
break;
#endif
#ifdef IPX
Modified: projects/rtentry_cache/sys/net/route.c
==============================================================================
--- projects/rtentry_cache/sys/net/route.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/net/route.c Sat May 12 16:10:56 2012 (r235341)
@@ -99,6 +99,11 @@ SYSCTL_UINT(_net, OID_AUTO, fibs, CTLFLA
*/
TUNABLE_INT("net.fibs", &rt_numfibs);
+u_int inpcb_rt_cache_enable = 0;
+SYSCTL_UINT(_net, OID_AUTO, conn_rt_cache, CTLFLAG_RW|CTLFLAG_TUN, &inpcb_rt_cache_enable, 0, "");
+TUNABLE_INT("net.conn_rt_cache", &inpcb_rt_cache_enable);
+
+
/*
* By default add routes to all fibs for new interfaces.
* Once this is set to 0 then only allocate routes on interface
@@ -905,6 +910,7 @@ rtexpunge(struct rtentry *rt)
* but when callers invoke us blindly it may not (sigh).
*/
rn = rnh->rnh_deladdr(rt_key(rt), rt_mask(rt), rnh);
+ atomic_add_int(&rnh->rnh_gen, 1);
if (rn == NULL) {
error = ESRCH;
goto bad;
@@ -994,6 +1000,7 @@ rn_mpath_update(int req, struct rt_addri
* to the caller
*/
rn = rnh->rnh_deladdr(dst, netmask, rnh);
+ atomic_add_int(&rnh->rnh_gen, 1);
KASSERT(rt == RNTORT(rn), ("radix node disappeared"));
goto gwdelete;
}
@@ -1117,6 +1124,7 @@ rtrequest1_fib(int req, struct rt_addrin
* Complain if it is not there and do no more processing.
*/
rn = rnh->rnh_deladdr(dst, netmask, rnh);
+ atomic_add_int(&rnh->rnh_gen, 1);
if (rn == NULL)
senderr(ESRCH);
if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
@@ -1278,6 +1286,7 @@ rtrequest1_fib(int req, struct rt_addrin
/* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes);
+ atomic_add_int(&rnh->rnh_gen, 1);
/*
* If it still failed to go into the tree,
* then un-make it (this should be a function)
Modified: projects/rtentry_cache/sys/netinet/in_pcb.c
==============================================================================
--- projects/rtentry_cache/sys/netinet/in_pcb.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet/in_pcb.c Sat May 12 16:10:56 2012 (r235341)
@@ -67,6 +67,8 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <net/vnet.h>
@@ -128,6 +130,8 @@ static VNET_DEFINE(int, ipport_tcplastco
#define V_ipport_tcplastcount VNET(ipport_tcplastcount)
+extern u_int inpcb_rt_cache_enable;
+
static void in_pcbremlists(struct inpcb *inp);
#ifdef INET
static struct inpcb *in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo,
@@ -466,6 +470,180 @@ in_pcb_lport(struct inpcb *inp, struct i
return (0);
}
+
+/*
+ * in_rt_valid() both checks for, and attempts to ensure, that a cached route
+ * is present on a socket. It will call in_pcbrtalloc() if conditions are
+ * right (i.e. routing is enabled on the socket) and required (no route cached
+ * already or the cached rout is no longer valid). A route can only be
+ * installed if the caller passes the inp with a write lock, but the route may
+ * be used if a read lock is held.
+ */
+
+int
+in_rt_valid(struct inpcb *inp)
+{
+ struct radix_node_head *rnh;
+
+ INP_WLOCK_ASSERT(inp);
+
+ if (inpcb_rt_cache_enable == 0)
+ return (0);
+ if (inp->inp_socket == NULL)
+ return (0);
+ if (inp->inp_socket->so_options & SO_DONTROUTE)
+ return (0);
+ if (inp->inp_vflag & INP_IPV6PROTO)
+ rnh = rt_tables_get_rnh(0, AF_INET6);
+ else
+ rnh = rt_tables_get_rnh(inp->inp_inc.inc_fibnum, AF_INET);
+ if (inp->inp_rt != NULL &&
+ (inp->inp_rt->rt_flags & RTF_UP) &&
+ inp->inp_rt_gen == rnh->rnh_gen)
+ return (1);
+ /*
+ * This will handle selectively replacing one field or the other or
+ * merely updating the inpcb's routing generation count.
+ */
+ in_pcbrtalloc(inp);
+ return (inp->inp_rt != NULL && inp->inp_rt->rt_ifp != NULL);
+}
+
+/*
+ * in_pcbrtalloc will install or update a cached route on an inpcb.
+ */
+
+void
+in_pcbrtalloc(struct inpcb *inp)
+{
+ struct rtentry *rt;
+ struct radix_node_head *rnh = NULL;
+ int gen;
+ struct route_in6 iproute;
+#ifdef INET6
+ struct route_in6 *sro6 = NULL;
+ struct sockaddr_in6 *sin6 = NULL;
+#endif
+#ifdef INET
+ struct sockaddr_in *sin = NULL;
+ struct route *sro = NULL;
+ struct in_ifaddr *ia;
+#endif
+
+ INP_WLOCK_ASSERT(inp);
+
+ if (inpcb_rt_cache_enable == 0)
+ return;
+
+ if (inp->inp_socket->so_options & SO_DONTROUTE)
+ return;
+
+ if (inp->inp_vflag & INP_IPV6PROTO) {
+#ifdef INET6
+ sro6 = &iproute;
+ bzero(sro6, sizeof(*sro6));
+ rnh = rt_tables_get_rnh(0, AF_INET6);
+ sin6 = (struct sockaddr_in6 *)&sro6->ro_dst;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+ sin6->sin6_addr = inp->in6p_faddr;
+#endif
+ } else {
+#ifdef INET
+ sro = (struct route *)&iproute;
+ bzero(sro, sizeof(*sro));
+ rnh = rt_tables_get_rnh(inp->inp_inc.inc_fibnum, AF_INET);
+ sin = (struct sockaddr_in *)&sro->ro_dst;
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(struct sockaddr_in);
+ sin->sin_addr.s_addr = inp->inp_faddr.s_addr;
+#endif
+
+ }
+ if (inp->inp_rt != NULL &&
+ inp->inp_rt_gen == rnh->rnh_gen) {
+ KASSERT(inp->inp_rt->rt_flags & RTF_UP,
+ ("gen count unchanged but route invalid"));
+ rt = inp->inp_rt;
+ return;
+ }
+resolve:
+
+ gen = rnh->rnh_gen;
+
+ if (inp->inp_vflag & INP_IPV6PROTO) {
+#ifdef INET6
+#ifdef RADIX_MPATH
+ rtalloc_mpath((struct route *)ro,
+ ntohl(sin6->sin6_addr.s6_addr32[3]));
+#else
+ sro6->ro_rt = rtalloc1(&((struct route *)sro6)
+ ->ro_dst, 0, 0UL);
+ if (sro6->ro_rt)
+ RT_UNLOCK(sro6->ro_rt);
+#endif
+ rt = sro6->ro_rt;
+#endif
+ } else {
+#ifdef INET
+#ifdef RADIX_MPATH
+ rtalloc_mpath_fib(sro, ntohl(faddr->s_addr),
+ inp->inp_inc.inc_fibnum);
+#else
+ rtalloc_ign_fib(sro, 0, inp->inp_inc.inc_fibnum);
+#endif
+ rt = sro->ro_rt;
+#endif
+ }
+
+ if (inp->inp_rt != NULL) {
+ if (rt == inp->inp_rt) {
+ /* The route is unchanged so we drop the added
+ * reference and update reference count.
+ */
+ RTFREE(rt);
+ inp->inp_rt_gen = gen;
+
+ /* The route has been validated and the generation
+ * count updated so we're done here.
+ */
+ return;
+ }
+#ifdef INET
+ /* Drop our reference to the old route */
+ ia = ifatoia(inp->inp_rt->rt_ifa);
+ ifa_free(&ia->ia_ifa);
+ inp->inp_ifaddr = NULL;
+#endif
+ RTFREE(inp->inp_rt);
+ inp->inp_rt = NULL;
+ }
+
+ if (inp->inp_lle != NULL) {
+ LLE_FREE(inp->inp_lle);
+ inp->inp_lle = NULL;
+ }
+ if (rt == NULL)
+ return;
+
+ if (gen != rnh->rnh_gen) {
+ /*
+ * The routing tree was updated some time after we read its
+ * generation counter.
+ */
+ RTFREE(rt);
+ goto resolve;
+ }
+
+ inp->inp_rt = rt;
+#ifdef INET
+ ia = ifatoia(rt->rt_ifa);
+ ifa_ref(&ia->ia_ifa);
+ inp->inp_ifaddr = ia;
+#endif
+ inp->inp_rt_gen = gen;
+}
+
#endif /* INET || INET6 */
#ifdef INET
@@ -662,6 +840,7 @@ in_pcbconnect_mbuf(struct inpcb *inp, st
inp->inp_laddr.s_addr = laddr;
inp->inp_faddr.s_addr = faddr;
inp->inp_fport = fport;
+
in_pcbrehash_mbuf(inp, m);
if (anonport)
@@ -714,7 +893,7 @@ in_pcbladdr(struct inpcb *inp, struct in
* Find out route to destination.
*/
if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0)
- in_rtalloc_ign(&sro, 0, inp->inp_inc.inc_fibnum);
+ rtalloc_ign_fib(&sro, 0, inp->inp_inc.inc_fibnum);
/*
* If we found a route, use the address corresponding to
@@ -1034,6 +1213,19 @@ in_pcbdisconnect(struct inpcb *inp)
INP_WLOCK_ASSERT(inp);
INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
+ if (inp->inp_rt != NULL) {
+ RTFREE(inp->inp_rt);
+ inp->inp_rt = NULL;
+ }
+ if (inp->inp_ifaddr != NULL) {
+ ifa_free(&inp->inp_ifaddr->ia_ifa);
+ inp->inp_ifaddr = NULL;
+ }
+ if (inp->inp_lle != NULL) {
+ LLE_FREE(inp->inp_lle);
+ inp->inp_lle = NULL;
+ }
+
inp->inp_faddr.s_addr = INADDR_ANY;
inp->inp_fport = 0;
in_pcbrehash(inp);
@@ -1165,6 +1357,20 @@ in_pcbfree(struct inpcb *inp)
INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_WLOCK_ASSERT(inp);
+ if (inp->inp_rt != NULL) {
+ RTFREE(inp->inp_rt);
+ inp->inp_rt = NULL;
+#ifdef INET
+ KASSERT(inp->inp_ifaddr != NULL, ("route valid but ifaddr not set"));
+ ifa_free(&inp->inp_ifaddr->ia_ifa);
+ inp->inp_ifaddr = NULL;
+#endif
+ }
+ if (inp->inp_lle != NULL) {
+ LLE_FREE(inp->inp_lle);
+ inp->inp_lle = NULL;
+ }
+
/* XXXRW: Do as much as possible here. */
#ifdef IPSEC
if (inp->inp_sp != NULL)
Modified: projects/rtentry_cache/sys/netinet/in_pcb.h
==============================================================================
--- projects/rtentry_cache/sys/netinet/in_pcb.h Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet/in_pcb.h Sat May 12 16:10:56 2012 (r235341)
@@ -141,6 +141,7 @@ struct icmp6_filter;
* these fields that write locks be held on both the inpcb and global locks.
*
* Key:
+ * (a) - Atomically incremented
* (c) - Constant after initialization
* (g) - Protected by the pcbgroup lock
* (i) - Protected by the inpcb lock
@@ -179,6 +180,8 @@ struct inpcb {
u_char inp_ip_minttl; /* (i) minimum TTL or drop */
uint32_t inp_flowid; /* (x) flow id / queue id */
u_int inp_refcount; /* (i) refcount */
+ struct in_ifaddr *inp_ifaddr; /* (i) reference to the local ifaddr */
+ u_int inp_rt_gen; /* (a) generation count of routing entry */
void *inp_pspare[5]; /* (x) route caching / general use */
u_int inp_ispare[6]; /* (x) route caching / user cookie /
* general use */
@@ -537,8 +540,6 @@ void inp_4tuple_get(struct inpcb *inp,
/*
* Flags for inp_flags2.
*/
-#define INP_LLE_VALID 0x00000001 /* cached lle is valid */
-#define INP_RT_VALID 0x00000002 /* cached rtentry is valid */
#define INP_PCBGROUPWILD 0x00000004 /* in pcbgroup wildcard list */
#define INP_REUSEPORT 0x00000008 /* SO_REUSEPORT option is set */
@@ -632,6 +633,8 @@ void in_pcbdrop(struct inpcb *);
void in_pcbfree(struct inpcb *);
int in_pcbinshash(struct inpcb *);
int in_pcbinshash_nopcbgroup(struct inpcb *);
+void in_pcbrtalloc(struct inpcb *inp);
+int in_rt_valid(struct inpcb *inp);
struct inpcb *
in_pcblookup_local(struct inpcbinfo *,
struct in_addr, u_short, int, struct ucred *);
Modified: projects/rtentry_cache/sys/netinet/ip_output.c
==============================================================================
--- projects/rtentry_cache/sys/netinet/ip_output.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet/ip_output.c Sat May 12 16:10:56 2012 (r235341)
@@ -146,7 +146,6 @@ ip_output(struct mbuf *m, struct mbuf *o
if (ro == NULL) {
ro = &iproute;
bzero(ro, sizeof (*ro));
-
#ifdef FLOWTABLE
{
struct flentry *fle;
@@ -163,6 +162,9 @@ ip_output(struct mbuf *m, struct mbuf *o
}
}
#endif
+ } else {
+ nortfree = 1;
+ ia = ro->ro_ia;
}
if (opt) {
@@ -277,6 +279,7 @@ again:
inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m));
#endif
rte = ro->ro_rt;
+ nortfree = 0;
}
if (rte == NULL ||
rte->rt_ifp == NULL ||
@@ -672,9 +675,11 @@ passout:
IPSTAT_INC(ips_fragmented);
done:
- if (ro == &iproute && ro->ro_rt && !nortfree) {
+ if (nortfree)
+ return (error);
+
+ if (ro->ro_rt)
RTFREE(ro->ro_rt);
- }
if (ia != NULL)
ifa_free(&ia->ia_ifa);
return (error);
Modified: projects/rtentry_cache/sys/netinet/tcp_output.c
==============================================================================
--- projects/rtentry_cache/sys/netinet/tcp_output.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet/tcp_output.c Sat May 12 16:10:56 2012 (r235341)
@@ -169,6 +169,15 @@ tcp_output(struct tcpcb *tp)
struct ip *ip = NULL;
struct ipovly *ipov = NULL;
struct tcphdr *th;
+#ifdef INET
+ struct sockaddr_in *sin;
+ struct route iproute, *ro = NULL;
+#endif
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+ struct route_in6 iproute6, *ro6 = NULL;
+#endif
+ struct inpcb *inp;
u_char opt[TCP_MAXOLEN];
unsigned ipoptlen, optlen, hdrlen;
#ifdef IPSEC
@@ -189,7 +198,8 @@ tcp_output(struct tcpcb *tp)
isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0;
#endif
- INP_WLOCK_ASSERT(tp->t_inpcb);
+ inp = tp->t_inpcb;
+ INP_WLOCK_ASSERT(inp);
/*
* Determine length of data that should be transmitted,
@@ -1203,11 +1213,27 @@ timer:
*/
ip6->ip6_hlim = in6_selecthlim(tp->t_inpcb, NULL);
+ if (in_rt_valid(inp)) {
+ ro6 = &iproute6;
+ sin6 = (struct sockaddr_in6 *)&ro6->ro_dst;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&sin6->sin6_addr.s6_addr, &inp->in6p_faddr.s6_addr, 16);
+ ro6->ro_rt = inp->inp_rt;
+ ro6->ro_lle = inp->inp_lle;
+ ro6->ro_flags |= RT_CACHING_CONTEXT;
+ } else
+ ro6 = NULL;
+
/* TODO: IPv6 IP6TOS_ECT bit on */
error = ip6_output(m,
- tp->t_inpcb->in6p_outputopts, NULL,
+ tp->t_inpcb->in6p_outputopts, ro6,
((so->so_options & SO_DONTROUTE) ?
IP_ROUTETOIF : 0), NULL, NULL, tp->t_inpcb);
+ if (ro6 != NULL && ro6->ro_lle != NULL &&
+ inp->inp_lle != ro6->ro_lle)
+ inp->inp_lle = ro6->ro_lle;
+
}
#endif /* INET6 */
#if defined(INET) && defined(INET6)
@@ -1231,9 +1257,25 @@ timer:
if (V_path_mtu_discovery && tp->t_maxopd > V_tcp_minmss)
ip->ip_off |= IP_DF;
- error = ip_output(m, tp->t_inpcb->inp_options, NULL,
+ if (in_rt_valid(inp)) {
+ ro = &iproute;
+ sin = (struct sockaddr_in *)&ro->ro_dst;
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(struct sockaddr_in);
+ sin->sin_addr.s_addr = inp->inp_faddr.s_addr;
+ ro->ro_rt = inp->inp_rt;
+ ro->ro_lle = inp->inp_lle;
+ ro->ro_ia = inp->inp_ifaddr;
+ ro->ro_flags |= RT_CACHING_CONTEXT;
+ } else
+ ro = NULL;
+
+ error = ip_output(m, tp->t_inpcb->inp_options, ro,
((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0,
tp->t_inpcb);
+ if (ro != NULL && ro->ro_lle != NULL && inp->inp_lle != ro->ro_lle)
+ inp->inp_lle = ro->ro_lle;
+
}
#endif /* INET */
if (error) {
Modified: projects/rtentry_cache/sys/netinet/tcp_usrreq.c
==============================================================================
--- projects/rtentry_cache/sys/netinet/tcp_usrreq.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet/tcp_usrreq.c Sat May 12 16:10:56 2012 (r235341)
@@ -1104,6 +1104,7 @@ tcp_connect(struct tcpcb *tp, struct soc
goto out;
}
inp->inp_laddr = laddr;
+ in_pcbrtalloc(inp);
in_pcbrehash(inp);
INP_HASH_WUNLOCK(&V_tcbinfo);
Modified: projects/rtentry_cache/sys/netinet6/in6_src.c
==============================================================================
--- projects/rtentry_cache/sys/netinet6/in6_src.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet6/in6_src.c Sat May 12 16:10:56 2012 (r235341)
@@ -662,7 +662,9 @@ selectroute(struct sockaddr_in6 *dstsock
((struct sockaddr *)(&ro->ro_dst))->sa_family != AF_INET6 ||
!IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr,
dst))) {
- RTFREE(ro->ro_rt);
+
+ if (!(ro->ro_flags & RT_CACHING_CONTEXT))
+ RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)NULL;
}
if (ro->ro_rt == (struct rtentry *)NULL) {
@@ -696,7 +698,8 @@ selectroute(struct sockaddr_in6 *dstsock
ifp = ro->ro_rt->rt_ifp;
if (ifp == NULL) { /* can this really happen? */
- RTFREE(ro->ro_rt);
+ if (!(ro->ro_flags & RT_CACHING_CONTEXT))
+ RTFREE(ro->ro_rt);
ro->ro_rt = NULL;
}
}
Modified: projects/rtentry_cache/sys/netinet6/ip6_forward.c
==============================================================================
--- projects/rtentry_cache/sys/netinet6/ip6_forward.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet6/ip6_forward.c Sat May 12 16:10:56 2012 (r235341)
@@ -627,7 +627,7 @@ skip_routing:
#endif /* IPFIREWALL_FORWARD */
pass:
- error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
+ error = nd6_output(rt->rt_ifp, origifp, m, dst, &rin6);
if (error) {
in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
V_ip6stat.ip6s_cantforward++;
Modified: projects/rtentry_cache/sys/netinet6/ip6_output.c
==============================================================================
--- projects/rtentry_cache/sys/netinet6/ip6_output.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet6/ip6_output.c Sat May 12 16:10:56 2012 (r235341)
@@ -981,7 +981,7 @@ passout:
ia6->ia_ifa.if_obytes += m->m_pkthdr.len;
ifa_free(&ia6->ia_ifa);
}
- error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
+ error = nd6_output(ifp, origifp, m, dst, ro);
goto done;
}
@@ -1120,7 +1120,7 @@ sendorfree:
ia->ia_ifa.if_opackets++;
ia->ia_ifa.if_obytes += m->m_pkthdr.len;
}
- error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
+ error = nd6_output(ifp, origifp, m, dst, ro);
} else
m_freem(m);
}
Modified: projects/rtentry_cache/sys/netinet6/nd6.c
==============================================================================
--- projects/rtentry_cache/sys/netinet6/nd6.c Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet6/nd6.c Sat May 12 16:10:56 2012 (r235341)
@@ -1822,10 +1822,10 @@ nd6_slowtimo(void *arg)
int
nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
- struct sockaddr_in6 *dst, struct rtentry *rt0)
+ struct sockaddr_in6 *dst, struct route_in6 *ro)
{
- return (nd6_output_lle(ifp, origifp, m0, dst, rt0, NULL, NULL));
+ return (nd6_output_lle(ifp, origifp, m0, dst, ro->ro_rt, ro->ro_lle, NULL));
}
@@ -1851,6 +1851,7 @@ nd6_output_lle(struct ifnet *ifp, struct
int error = 0;
int flags = 0;
int ip6len;
+ struct route ro;
#ifdef INVARIANTS
if (lle != NULL) {
@@ -2078,7 +2079,9 @@ nd6_output_lle(struct ifnet *ifp, struct
return ((*ifp->if_output)(origifp, m, (struct sockaddr *)dst,
NULL));
}
- error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, NULL);
+ ro.ro_rt = rt0;
+ ro.ro_lle = ln;
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, &ro);
return (error);
bad:
Modified: projects/rtentry_cache/sys/netinet6/nd6.h
==============================================================================
--- projects/rtentry_cache/sys/netinet6/nd6.h Sat May 12 16:08:05 2012 (r235340)
+++ projects/rtentry_cache/sys/netinet6/nd6.h Sat May 12 16:10:56 2012 (r235341)
@@ -408,7 +408,7 @@ int nd6_ioctl __P((u_long, caddr_t, stru
struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
- struct sockaddr_in6 *, struct rtentry *));
+ struct sockaddr_in6 *, struct route_in6 *));
int nd6_output_lle __P((struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *, struct rtentry *, struct llentry *,
struct mbuf **));
More information about the svn-src-projects
mailing list