svn commit: r197339 - user/kmacy/releng_8_fcs/sys/netinet
Kip Macy
kmacy at FreeBSD.org
Sun Sep 20 05:06:42 UTC 2009
Author: kmacy
Date: Sun Sep 20 05:06:42 2009
New Revision: 197339
URL: http://svn.freebsd.org/changeset/base/197339
Log:
cache lle and rtentry in connected sockets
Modified:
user/kmacy/releng_8_fcs/sys/netinet/in_pcb.c
user/kmacy/releng_8_fcs/sys/netinet/in_pcb.h
user/kmacy/releng_8_fcs/sys/netinet/ip_output.c
user/kmacy/releng_8_fcs/sys/netinet/tcp_usrreq.c
Modified: user/kmacy/releng_8_fcs/sys/netinet/in_pcb.c
==============================================================================
--- user/kmacy/releng_8_fcs/sys/netinet/in_pcb.c Sun Sep 20 05:04:23 2009 (r197338)
+++ user/kmacy/releng_8_fcs/sys/netinet/in_pcb.c Sun Sep 20 05:06:42 2009 (r197339)
@@ -59,6 +59,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>
@@ -203,6 +205,7 @@ in_pcballoc(struct socket *so, struct in
inp->inp_socket = so;
inp->inp_cred = crhold(so->so_cred);
inp->inp_inc.inc_fibnum = so->so_fibnum;
+ inp->inp_flowid = arc4random();
#ifdef MAC
error = mac_inpcb_init(inp, M_NOWAIT);
if (error != 0)
@@ -489,6 +492,80 @@ 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;
+ /*
+ * Don't cache route in pcb if this is a per-packet
+ * route
+ */
+ 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.
@@ -524,6 +601,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;
@@ -884,6 +962,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);
@@ -921,6 +1010,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/releng_8_fcs/sys/netinet/in_pcb.h
==============================================================================
--- user/kmacy/releng_8_fcs/sys/netinet/in_pcb.h Sun Sep 20 05:04:23 2009 (r197338)
+++ user/kmacy/releng_8_fcs/sys/netinet/in_pcb.h Sun Sep 20 05:06:42 2009 (r197339)
@@ -452,6 +452,8 @@ void inp_4tuple_get(struct inpcb *inp,
#define INP_CHECK_SOCKAF(so, af) (INP_SOCKAF(so) == af)
#ifdef _KERNEL
+struct route;
+
VNET_DECLARE(int, ipport_reservedhigh);
VNET_DECLARE(int, ipport_reservedlow);
VNET_DECLARE(int, ipport_lowfirstauto);
@@ -496,6 +498,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/releng_8_fcs/sys/netinet/ip_output.c
==============================================================================
--- user/kmacy/releng_8_fcs/sys/netinet/ip_output.c Sun Sep 20 05:04:23 2009 (r197338)
+++ user/kmacy/releng_8_fcs/sys/netinet/ip_output.c Sun Sep 20 05:06:42 2009 (r197339)
@@ -124,11 +124,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
@@ -202,7 +204,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;
ro->ro_lle = (struct llentry *)NULL;
@@ -236,13 +238,17 @@ again:
ip->ip_ttl = 1;
isbroadcast = 1;
} else if (flags & IP_ROUTETOIF) {
- if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL &&
+ if (!nortfree &&
+ (ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL &&
(ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == NULL) {
IPSTAT_INC(ips_noroute);
error = ENETUNREACH;
goto bad;
}
- ifp = ia->ia_ifp;
+ if (nortfree)
+ ifp = ro->ro_rt->rt_ifp;
+ else
+ ifp = ia->ia_ifp;
ip->ip_ttl = 1;
isbroadcast = in_broadcast(dst->sin_addr, ifp);
} else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
@@ -418,6 +424,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;
+ }
}
/*
@@ -662,7 +684,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/releng_8_fcs/sys/netinet/tcp_usrreq.c
==============================================================================
--- user/kmacy/releng_8_fcs/sys/netinet/tcp_usrreq.c Sun Sep 20 05:04:23 2009 (r197338)
+++ user/kmacy/releng_8_fcs/sys/netinet/tcp_usrreq.c Sun Sep 20 05:06:42 2009 (r197339)
@@ -1091,6 +1091,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