svn commit: r186624 - user/kmacy/HEAD_fast_net/sys/netinet
Kip Macy
kmacy at FreeBSD.org
Wed Dec 31 03:03:00 UTC 2008
Author: kmacy
Date: Wed Dec 31 03:02:59 2008
New Revision: 186624
URL: http://svn.freebsd.org/changeset/base/186624
Log:
attempt to further streamline ip_output_fast checks_
Modified:
user/kmacy/HEAD_fast_net/sys/netinet/ip_output.c
Modified: user/kmacy/HEAD_fast_net/sys/netinet/ip_output.c
==============================================================================
--- user/kmacy/HEAD_fast_net/sys/netinet/ip_output.c Wed Dec 31 02:27:31 2008 (r186623)
+++ user/kmacy/HEAD_fast_net/sys/netinet/ip_output.c Wed Dec 31 03:02:59 2008 (r186624)
@@ -117,10 +117,6 @@ ip_output_fast(struct mbuf *m, struct ro
ifp = ro->ro_rt->rt_ifp;
ro->ro_rt->rt_rmx.rmx_pksent++;
- if (ro->ro_rt->rt_flags & RTF_GATEWAY)
- bcopy(ro->ro_rt->rt_gateway, &ro->ro_dst,
- sizeof(struct sockaddr));
-
ip = mtod(m, struct ip *);
/*
* If the source address is not specified yet, use the address
@@ -189,7 +185,9 @@ ip_output_fast(struct mbuf *m, struct ro
return ((*ifp->if_output)(ifp, m, ro));
}
-
+
+#define IP_RT_SET 0x1
+#define IP_LLE_SET 0x2
/*
* IP output. The packet in mbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst).
@@ -209,11 +207,12 @@ ip_output(struct mbuf *m, struct mbuf *o
struct mbuf *m0;
struct in_ifaddr *ia = NULL;
int hlen = sizeof (struct ip);
- int mtu;
+ int mtu, flerror = ENOENT;
int len, error = 0;
int neednewroute = 0, neednewlle = 0, nortfree = 0;
struct sockaddr_in *dst = NULL; /* keep compiler happy */
int isbroadcast, sw_csum;
+ int stateflags = 0;
struct route iproute;
struct in_addr odst;
#ifdef IPFIREWALL_FORWARD
@@ -223,7 +222,8 @@ ip_output(struct mbuf *m, struct mbuf *o
if (ro == NULL) {
ro = &iproute;
- bzero(ro, sizeof (*ro));
+ ro->ro_rt = NULL;
+ ro->ro_lle = NULL;
}
if (inp != NULL) {
@@ -261,24 +261,6 @@ ip_output(struct mbuf *m, struct mbuf *o
dst = (struct sockaddr_in *)&ro->ro_dst;
again:
- /*
- * If there is a cached route,
- * check that it is to the same destination
- * and is still up. If not, free it and try again.
- * The address family should also be checked in case of sharing the
- * cache with IPv6.
- */
- if (ro->ro_rt != NULL && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- dst->sin_family != AF_INET ||
- dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
- /*
- * XXX need to check that ro->ro_rt isn't coming from a flow
- * lookup in ip_forward ... perhaps pass in a new flag
- *
- */
- RTFREE(ro->ro_rt);
- ro->ro_rt = NULL;
- }
#ifdef IPFIREWALL_FORWARD
if (ro->ro_rt == NULL && fwd_tag == NULL) {
#else
@@ -289,8 +271,14 @@ again:
dst->sin_len = sizeof(*dst);
dst->sin_addr = ip->ip_dst;
}
- if (ro != &iproute)
+ if (ro != &iproute) {
+ if (ro->ro_rt != NULL && (ro->ro_rt->rt_flags & RTF_UP))
+ stateflags |= IP_RT_SET;
+ if (ro->ro_lle != NULL && (ro->ro_lle->la_flags & LLE_VALID))
+ stateflags |= IP_LLE_SET;
goto skipcachecheck;
+ }
+
if (inp != NULL) {
if (inp->inp_flags & (INP_HW_FLOWID|INP_SW_FLOWID)) {
m->m_pkthdr.flowid = inp->inp_flowid;
@@ -299,54 +287,79 @@ again:
if (inp->inp_vflag & INP_RT_VALID) {
if (inp->inp_rt->rt_flags & RTF_UP) {
ro->ro_rt = inp->inp_rt;
+ stateflags |= IP_RT_SET;
} else
neednewroute = 1;
}
if (inp->inp_flags & INP_LLE_VALID) {
if (inp->inp_lle->la_flags & LLE_VALID) {
ro->ro_lle = inp->inp_lle;
+ stateflags |= IP_LLE_SET;
} else
neednewlle = 1;
}
}
- if ((ro->ro_rt == NULL) && (ro->ro_lle == NULL)) {
- if (flowtable_lookup(ipv4_ft, m, ro) == 0)
+ if ((stateflags & (IP_LLE_SET|IP_RT_SET)) != (IP_LLE_SET|IP_RT_SET)) {
+ if ((flerror = flowtable_lookup(ipv4_ft, m, ro)) == 0) {
nortfree = 1;
+ stateflags |= IP_RT_SET;
+ if (ro->ro_lle != NULL)
+ stateflags |= IP_LLE_SET;
+ }
}
skipcachecheck:
/*
* Check if we can take a huge shortcut
*/
- if (ro->ro_rt != NULL && (ro->ro_rt->rt_flags & RTF_UP) &&
- ro->ro_lle != NULL && (ro->ro_lle->la_flags & LLE_VALID) &&
- (flags & (IP_SENDONES|IP_ROUTETOIF)) == 0 &&
- !PFIL_HOOKED(&inet_pfil_hook) &&
- !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ if ((stateflags & (IP_LLE_SET|IP_RT_SET)) == (IP_LLE_SET|IP_RT_SET)
+ && (flags & (IP_SENDONES|IP_ROUTETOIF)) == 0
+ && !PFIL_HOOKED(&inet_pfil_hook)
+ && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
ifp = ro->ro_rt->rt_ifp;
- if (ro->ro_rt->rt_flags & (RTF_UP|RTF_HOST)) {
+ dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
+ if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+ bcopy(ro->ro_rt->rt_gateway, &ro->ro_dst,
+ sizeof(struct sockaddr));
+
+ if (ro->ro_rt->rt_flags & RTF_HOST) {
if (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)
ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
mtu = ro->ro_rt->rt_rmx.rmx_mtu;
- } else
- mtu = ifp->if_mtu;
-
- if (ro->ro_rt->rt_flags & RTF_GATEWAY)
- dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
- else
- dst = (struct sockaddr_in *)&ro->ro_dst;
- if (ro->ro_rt->rt_flags & RTF_HOST)
isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST);
- else
+ } else {
isbroadcast = in_broadcast(dst->sin_addr, ifp);
-
+ mtu = ifp->if_mtu;
+ }
+
if (!isbroadcast && (ip->ip_len <= mtu ||
(m->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0
|| ((ip->ip_off & IP_DF) == 0
&& (ifp->if_hwassist & CSUM_FRAGMENT))))
return (ip_output_fast(m, ro, flags, hlen, inp));
}
+
+ /*
+ * If there is a cached route,
+ * check that it is to the same destination
+ * and is still up. If not, free it and try again.
+ * The address family should also be checked in case of sharing the
+ * cache with IPv6.
+ */
+ if (ro->ro_rt != NULL && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+ dst->sin_family != AF_INET ||
+ dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+ /*
+ * XXX need to check that ro->ro_rt isn't coming from a flow
+ * lookup in ip_forward ... perhaps pass in a new flag
+ *
+ */
+ if (((inp->inp_vflag & INP_RT_VALID) == 0) &&
+ flerror != 0)
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = NULL;
+ }
/*
* If routing to interface only, short circuit routing lookup.
More information about the svn-src-user
mailing list