svn commit: r186994 - user/kmacy/HEAD_fast_net/sys/net
Kip Macy
kmacy at FreeBSD.org
Fri Jan 9 18:32:57 PST 2009
Author: kmacy
Date: Sat Jan 10 02:32:56 2009
New Revision: 186994
URL: http://svn.freebsd.org/changeset/base/186994
Log:
- add kernel support for "sticky" routes - all connections from a given
source ip will be routed to the same dst ip
Modified:
user/kmacy/HEAD_fast_net/sys/net/flowtable.c
user/kmacy/HEAD_fast_net/sys/net/route.h
Modified: user/kmacy/HEAD_fast_net/sys/net/flowtable.c
==============================================================================
--- user/kmacy/HEAD_fast_net/sys/net/flowtable.c Sat Jan 10 01:47:15 2009 (r186993)
+++ user/kmacy/HEAD_fast_net/sys/net/flowtable.c Sat Jan 10 02:32:56 2009 (r186994)
@@ -330,13 +330,14 @@ flowtable_pcpu_unlock(struct flowtable *
static uint32_t
ipv4_flow_lookup_hash_internal(struct mbuf *m, struct route *ro,
- uint32_t *key, uint16_t *flags, uint8_t *protop)
+ uint32_t *key, uint16_t *flags, uint8_t *protop, uint32_t *hash,
+ uint32_t *hash_noports)
{
uint16_t sport = 0, dport = 0;
struct ip *ip;
uint8_t proto = 0;
int iphlen;
- uint32_t hash;
+ uint32_t rh;
struct sockaddr_in *sin;
struct tcphdr *th;
struct udphdr *uh;
@@ -352,14 +353,16 @@ ipv4_flow_lookup_hash_internal(struct mb
key[1] = 0;
key[2] = sin->sin_addr.s_addr;
- if (m == NULL || (*flags & FL_HASH_PORTS) == 0)
+ if (m == NULL)
goto skipports;
-
ip = mtod(m, struct ip *);
proto = ip->ip_p;
iphlen = ip->ip_hl << 2; /* XXX options? */
key[1] = ip->ip_src.s_addr;
-
+
+ if ((*flags & FL_HASH_PORTS) == 0)
+ goto skipports;
+
switch (proto) {
case IPPROTO_TCP:
th = (struct tcphdr *)((caddr_t)ip + iphlen);
@@ -386,30 +389,27 @@ ipv4_flow_lookup_hash_internal(struct mb
break;;
}
- *protop = proto;
-
- /*
- * If this is a transmit route cache then
- * hash all flows to a given destination to
- * the same bucket
- */
- if ((*flags & FL_HASH_PORTS) == 0)
- proto = sport = dport = 0;
-
- ((uint16_t *)key)[0] = sport;
- ((uint16_t *)key)[1] = dport;
skipports:
- hash = hashword(key, 3, hashjitter + proto);
+ rh = hashword(key, 3, hashjitter + proto);
+ *hash_noports = rh;
+ *hash = 0;
+ if ((*flags & FL_HASH_PORTS) && sport) {
+ ((uint16_t *)key)[0] = sport;
+ ((uint16_t *)key)[1] = dport;
+ rh = hashword(key, 3, hashjitter + proto);
+ *hash = rh;
+ }
if (m != NULL && (m->m_flags & M_FLOWID) == 0)
- m->m_pkthdr.flowid = hash;
-
- CTR5(KTR_SPARE3, "proto=%d hash=%x key[0]=%x sport=%d dport=%d\n", proto, hash, key[0], sport, dport);
-
- return (hash);
+ m->m_pkthdr.flowid = rh;
+
+ CTR5(KTR_SPARE3, "proto=%d hash=%x key[0]=%x sport=%d dport=%d\n",
+ proto, *hash, key[0], sport, dport);
+
+ return (0);
noop:
*protop = proto;
- return (0);
+ return (ENOENT);
}
static bitstr_t *
@@ -566,7 +566,7 @@ flowtable_key_equal(struct flentry *fle,
int
flowtable_lookup(struct flowtable *ft, struct mbuf *m, struct route *ro)
{
- uint32_t key[9], hash;
+ uint32_t key[9], hash, hash_noports;
struct flentry *fle;
uint16_t flags;
uint8_t proto = 0;
@@ -577,13 +577,14 @@ flowtable_lookup(struct flowtable *ft, s
flags = ft ? ft->ft_flags : 0;
ro->ro_rt = NULL;
ro->ro_lle = NULL;
-
+ hash = hash_noports = 0;
+
/*
* The internal hash lookup is the only IPv4 specific bit
* remaining
*/
- hash = ipv4_flow_lookup_hash_internal(m, ro, key,
- &flags, &proto);
+ error = ipv4_flow_lookup_hash_internal(m, ro, key,
+ &flags, &proto, &hash, &hash_noports);
/*
* Ports are zero and this isn't a transmit cache
@@ -591,10 +592,13 @@ flowtable_lookup(struct flowtable *ft, s
* statex
* FL_HASH_PORTS => key[0] != 0 for TCP || UDP || SCTP
*/
- if (hash == 0 || (key[0] == 0 && (ft->ft_flags & FL_HASH_PORTS))) {
+ if (error == ENOENT || (key[0] == 0 && (ft->ft_flags & FL_HASH_PORTS))) {
cache = 0;
goto uncached;
}
+ if ((ft->ft_flags & FL_HASH_PORTS) == 0)
+ goto skipports;
+
FL_ENTRY_LOCK(ft, hash);
fle = FL_ENTRY(ft, hash);
rt = __DEVOLATILE(struct rtentry *, fle->f_rt);
@@ -614,6 +618,27 @@ flowtable_lookup(struct flowtable *ft, s
}
FL_ENTRY_UNLOCK(ft, hash);
+skipports:
+ key[0] = 0;
+ FL_ENTRY_LOCK(ft, hash_noports);
+ fle = FL_ENTRY(ft, hash_noports);
+ rt = __DEVOLATILE(struct rtentry *, fle->f_rt);
+ lle = __DEVOLATILE(struct llentry *, fle->f_lle);
+ if ((rt != NULL)
+ && fle->f_fhash == hash_noports
+ && flowtable_key_equal(fle, key, flags)
+ && (proto == fle->f_proto)
+ && (rt->rt_flags & RTF_UP)
+ && (rt->rt_ifp != NULL)) {
+ fle->f_uptime = time_uptime;
+ fle->f_flags |= flags;
+ ro->ro_rt = rt;
+ ro->ro_lle = lle;
+ FL_ENTRY_UNLOCK(ft, hash_noports);
+ return (0);
+ }
+ FL_ENTRY_UNLOCK(ft, hash_noports);
+
uncached:
/*
* This bit of code ends up locking the
@@ -639,6 +664,18 @@ uncached:
struct rtentry *rt = ro->ro_rt;
struct ifnet *ifp = rt->rt_ifp;
+ if (rt->rt_flags & RTF_STICKY) {
+ RTFREE(rt);
+ hash = hash_noports;
+ ft->ft_rtalloc(ro, hash, fib);
+ if (ro->ro_rt == NULL) {
+ error = ENETUNREACH;
+ goto done;
+ }
+ rt = ro->ro_rt;
+ ifp = rt->rt_ifp;
+ }
+
if (rt->rt_flags & RTF_GATEWAY)
l3addr = rt->rt_gateway;
else
@@ -670,7 +707,7 @@ uncached:
}
error = 0;
}
-
+done:
return (error);
}
@@ -719,7 +756,7 @@ flowtable_alloc(int nentry, int flags)
ft->ft_masks[i] = bit_alloc(nentry);
}
} else {
- ft->ft_lock_count = 2*(powerof2(mp_ncpus) ? mp_ncpus :
+ ft->ft_lock_count = 8*(powerof2(mp_ncpus) ? mp_ncpus :
(fls(mp_ncpus) << 1));
ft->ft_lock = flowtable_global_lock;
Modified: user/kmacy/HEAD_fast_net/sys/net/route.h
==============================================================================
--- user/kmacy/HEAD_fast_net/sys/net/route.h Sat Jan 10 01:47:15 2009 (r186993)
+++ user/kmacy/HEAD_fast_net/sys/net/route.h Sat Jan 10 02:32:56 2009 (r186994)
@@ -196,9 +196,10 @@ struct ortentry {
#define RTF_LOCAL 0x200000 /* route represents a local address */
#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
- /* 0x1000000 and up unassigned */
+ /* 0x8000000 and up unassigned */
+#define RTF_STICKY 0x10000000 /* always route dst->src */
#define RTF_SHUTDOWN 0x20000000 /* no new connections */
-#define RTF_RNH_LOCKED 0x40000000
+#define RTF_RNH_LOCKED 0x40000000
/* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */
#define RTF_FMASK \
More information about the svn-src-user
mailing list