Date: Wed, 1 Jul 2009 19:55:07 +0000 (UTC) From: Kip Macy <kmacy@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r195254 - user/kmacy/head_ppacket/sys/netinet Message-ID: <200907011955.n61Jt7MP022265@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907011955.n61Jt7MP022265>