svn commit: r195254 - user/kmacy/head_ppacket/sys/netinet
Kip Macy
kmacy at FreeBSD.org
Wed Jul 1 19:55:08 UTC 2009
Author: kmacy
Date: Wed Jul 1 19:55:07 2009
New Revision: 195254
URL: http://svn.freebsd.org/changeset/base/195254
Log:
Cache rtentry and llentry in the inpcb
Modified:
user/kmacy/head_ppacket/sys/netinet/in_pcb.c
user/kmacy/head_ppacket/sys/netinet/in_pcb.h
user/kmacy/head_ppacket/sys/netinet/ip_output.c
user/kmacy/head_ppacket/sys/netinet/tcp_usrreq.c
Modified: user/kmacy/head_ppacket/sys/netinet/in_pcb.c
==============================================================================
--- user/kmacy/head_ppacket/sys/netinet/in_pcb.c Wed Jul 1 19:46:53 2009 (r195253)
+++ user/kmacy/head_ppacket/sys/netinet/in_pcb.c Wed Jul 1 19:55:07 2009 (r195254)
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -494,6 +495,76 @@ in_pcbbind_setup(struct inpcb *inp, stru
return (0);
}
+void
+in_pcbrtalloc(struct inpcb *inp, in_addr_t faddr, struct route *sro)
+{
+ struct sockaddr_in *sin;
+ struct sockaddr *dst;
+ struct llentry *la;
+ struct rtentry *rt;
+ struct ifnet *ifp;
+ int flags = LLE_EXCLUSIVE;
+ struct route iproute;
+
+ INP_WLOCK_ASSERT(inp);
+ if (sro == NULL)
+ sro = &iproute;
+
+ bzero(sro, sizeof(*sro));
+ sin = (struct sockaddr_in *)&sro->ro_dst;
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(struct sockaddr_in);
+ sin->sin_addr.s_addr = faddr;
+ /*
+ * If route is known our src addr is taken from the i/f,
+ * else punt.
+ *
+ * Find out route to destination.
+ */
+ if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0) {
+#ifdef RADIX_MPATH
+ rtalloc_mpath_fib(sro, ntohl(faddr->s_addr),
+ inp->inp_inc.inc_fibnum);
+#else
+ in_rtalloc_ign(sro, 0, inp->inp_inc.inc_fibnum);
+#endif
+ }
+
+ rt = sro->ro_rt;
+ if (rt == NULL)
+ return;
+
+ inp->inp_rt = rt;
+ inp->inp_flags2 |= INP_RT_VALID;
+
+ if (rt->rt_ifp == NULL)
+ return;
+
+ ifp = rt->rt_ifp;
+ dst = &sro->ro_dst;
+ if (rt->rt_flags & RTF_GATEWAY)
+ dst = rt->rt_gateway;
+
+ IF_AFDATA_RLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), flags, dst);
+ IF_AFDATA_RUNLOCK(ifp);
+ if ((la == NULL) &&
+ (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
+ flags |= (LLE_CREATE | LLE_EXCLUSIVE);
+ IF_AFDATA_WLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), flags, dst);
+ IF_AFDATA_WUNLOCK(ifp);
+ }
+ if (la == NULL)
+ return;
+
+ LLE_ADDREF(la);
+ LLE_WUNLOCK(la);
+
+ inp->inp_lle = la;
+ inp->inp_flags2 |= INP_LLE_VALID;
+}
+
/*
* Connect from a socket to a specified address.
* Both address and port must be specified in argument sin.
@@ -529,6 +600,7 @@ in_pcbconnect(struct inpcb *inp, struct
}
}
+ in_pcbrtalloc(inp, faddr, NULL);
/* Commit the remaining changes. */
inp->inp_lport = lport;
inp->inp_laddr.s_addr = laddr;
@@ -888,6 +960,17 @@ in_pcbdisconnect(struct inpcb *inp)
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
+ if (inp->inp_flags2 & INP_RT_VALID) {
+ inp->inp_flags2 &= ~INP_RT_VALID;
+ RTFREE(inp->inp_rt);
+ inp->inp_rt = NULL;
+ }
+ if (inp->inp_flags2 & INP_LLE_VALID) {
+ inp->inp_flags2 &= ~INP_LLE_VALID;
+ LLE_FREE(inp->inp_lle);
+ inp->inp_lle = NULL;
+ }
+
inp->inp_faddr.s_addr = INADDR_ANY;
inp->inp_fport = 0;
in_pcbrehash(inp);
@@ -925,6 +1008,17 @@ in_pcbfree_internal(struct inpcb *inp)
INP_INFO_WLOCK_ASSERT(ipi);
INP_WLOCK_ASSERT(inp);
+ if (inp->inp_flags2 & INP_RT_VALID) {
+ inp->inp_flags2 &= ~INP_RT_VALID;
+ RTFREE(inp->inp_rt);
+ inp->inp_rt = NULL;
+ }
+ if (inp->inp_flags2 & INP_LLE_VALID) {
+ inp->inp_flags2 &= ~INP_LLE_VALID;
+ LLE_FREE(inp->inp_lle);
+ inp->inp_lle = NULL;
+ }
+
#ifdef IPSEC
if (inp->inp_sp != NULL)
ipsec_delete_pcbpolicy(inp);
Modified: user/kmacy/head_ppacket/sys/netinet/in_pcb.h
==============================================================================
--- user/kmacy/head_ppacket/sys/netinet/in_pcb.h Wed Jul 1 19:46:53 2009 (r195253)
+++ user/kmacy/head_ppacket/sys/netinet/in_pcb.h Wed Jul 1 19:55:07 2009 (r195254)
@@ -46,6 +46,7 @@
#define in6pcb inpcb /* for KAME src sync over BSD*'s */
#define in6p_sp inp_sp /* for KAME src sync over BSD*'s */
struct inpcbpolicy;
+struct route;
/*
* struct inpcb is the common protocol control block structure used in most
@@ -481,6 +482,7 @@ void in_pcbdisconnect(struct inpcb *);
void in_pcbdrop(struct inpcb *);
void in_pcbfree(struct inpcb *);
int in_pcbinshash(struct inpcb *);
+void in_pcbrtalloc(struct inpcb *inp, in_addr_t faddr, struct route *sro);
struct inpcb *
in_pcblookup_local(struct inpcbinfo *,
struct in_addr, u_short, int, struct ucred *);
Modified: user/kmacy/head_ppacket/sys/netinet/ip_output.c
==============================================================================
--- user/kmacy/head_ppacket/sys/netinet/ip_output.c Wed Jul 1 19:46:53 2009 (r195253)
+++ user/kmacy/head_ppacket/sys/netinet/ip_output.c Wed Jul 1 19:55:07 2009 (r195254)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/pfil.h>
#include <net/route.h>
@@ -129,11 +130,13 @@ ip_output(struct mbuf *m, struct mbuf *o
int mtu;
int len, error = 0;
int nortfree = 0;
+ int neednewroute = 0, neednewlle = 0;
struct sockaddr_in *dst = NULL; /* keep compiler happy */
struct in_ifaddr *ia = NULL;
int isbroadcast, sw_csum;
struct route iproute;
struct in_addr odst;
+ struct sockaddr_in *sin;
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag = NULL;
#endif
@@ -207,7 +210,7 @@ again:
if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
dst->sin_family != AF_INET ||
dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
- if (!nortfree)
+ if (!nortfree && (inp == NULL || (ro->ro_rt != inp->inp_rt)))
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)NULL;
}
@@ -422,6 +425,22 @@ again:
if (ia != NULL) {
ip->ip_src = IA_SIN(ia)->sin_addr;
}
+ if ((ro == &iproute) && (inp->inp_flags2 & INP_RT_VALID)) {
+ if (inp->inp_rt->rt_flags & RTF_UP) {
+ 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;
+ } else
+ neednewroute = 1;
+ }
+ if ((ro == &iproute) && (inp->inp_flags2 & INP_LLE_VALID)) {
+ if (inp->inp_lle->la_flags & LLE_VALID) {
+ ro->ro_lle = inp->inp_lle;
+ } else
+ neednewlle = 1;
+ }
}
/*
@@ -666,7 +685,45 @@ passout:
done:
if (ro == &iproute && ro->ro_rt && !nortfree) {
- RTFREE(ro->ro_rt);
+ int wlocked = 0;
+ struct llentry *la;
+
+ if (neednewlle || neednewroute) {
+ wlocked = INP_WLOCKED(inp);
+ if (!wlocked && INP_TRY_UPGRADE(inp) == 0)
+ return (error);
+ }
+
+ if ((nortfree == 0) &&
+ (inp == NULL || (inp->inp_vflag & INP_RT_VALID) == 0))
+ RTFREE(ro->ro_rt);
+ else if (neednewroute && ro->ro_rt != inp->inp_rt) {
+ RTFREE(inp->inp_rt);
+ inp->inp_rt = ro->ro_rt;
+ }
+ if (neednewlle) {
+ IF_AFDATA_RLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE,
+ (struct sockaddr *)dst);
+ IF_AFDATA_RUNLOCK(ifp);
+ if ((la == NULL) &&
+ (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
+ IF_AFDATA_WLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp),
+ (LLE_CREATE | LLE_EXCLUSIVE),
+ (struct sockaddr *)dst);
+ IF_AFDATA_WUNLOCK(ifp);
+ }
+ if (la != NULL && (inp->inp_lle != la)) {
+ LLE_FREE(inp->inp_lle);
+ LLE_ADDREF(la);
+ LLE_WUNLOCK(la);
+ inp->inp_lle = la;
+ } else if (la != NULL)
+ LLE_WUNLOCK(la);
+ }
+ if ((neednewlle || neednewroute) && !wlocked)
+ INP_DOWNGRADE(inp);
}
if (ia != NULL)
ifa_free(&ia->ia_ifa);
Modified: user/kmacy/head_ppacket/sys/netinet/tcp_usrreq.c
==============================================================================
--- user/kmacy/head_ppacket/sys/netinet/tcp_usrreq.c Wed Jul 1 19:46:53 2009 (r195253)
+++ user/kmacy/head_ppacket/sys/netinet/tcp_usrreq.c Wed Jul 1 19:55:07 2009 (r195254)
@@ -1109,6 +1109,7 @@ tcp_connect(struct tcpcb *tp, struct soc
inp->inp_laddr = laddr;
in_pcbrehash(inp);
+ in_pcbrtalloc(inp, inp->inp_faddr.s_addr, NULL);
/*
* Compute window scaling to request:
* Scale to fit into sweet spot. See tcp_syncache.c.
More information about the svn-src-user
mailing list