svn commit: r203462 - in user/kmacy/head_flowtable_v6/sys: net
netinet
Kip Macy
kmacy at FreeBSD.org
Thu Feb 4 00:11:34 UTC 2010
Author: kmacy
Date: Thu Feb 4 00:11:34 2010
New Revision: 203462
URL: http://svn.freebsd.org/changeset/base/203462
Log:
add IPv6 support to flowtable
Modified:
user/kmacy/head_flowtable_v6/sys/net/flowtable.c
user/kmacy/head_flowtable_v6/sys/net/flowtable.h
user/kmacy/head_flowtable_v6/sys/netinet/ip_output.c
Modified: user/kmacy/head_flowtable_v6/sys/net/flowtable.c
==============================================================================
--- user/kmacy/head_flowtable_v6/sys/net/flowtable.c Wed Feb 3 23:59:52 2010 (r203461)
+++ user/kmacy/head_flowtable_v6/sys/net/flowtable.c Thu Feb 4 00:11:34 2010 (r203462)
@@ -30,6 +30,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "opt_route.h"
#include "opt_mpath.h"
#include "opt_ddb.h"
+#include "opt_inet.h"
+#include "opt_inet6.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -63,6 +65,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/sctp.h>
@@ -342,45 +347,123 @@ flowtable_pcpu_unlock(struct flowtable *
#define FL_ENTRY_LOCK(table, hash) (table)->ft_lock((table), (hash))
#define FL_ENTRY_UNLOCK(table, hash) (table)->ft_unlock((table), (hash))
-#define FL_STALE (1<<8)
-#define FL_IPV6 (1<<9)
+#define FL_STALE (1<<8)
+#define FL_IPV6 (1<<9)
+#define FL_OVERWRITE (1<<10)
+#define FL_TCP (1<<11)
+#define FL_SCTP (1<<12)
+#define FL_UDP (1<<13)
-static uint32_t
-ipv4_flow_lookup_hash_internal(struct mbuf *m, struct route *ro,
- uint32_t *key, uint16_t *flags, uint8_t *protop)
+void
+flow_invalidate(struct flentry *fle)
{
- uint16_t sport = 0, dport = 0;
- struct ip *ip = NULL;
- uint8_t proto = 0;
- int iphlen;
- uint32_t hash;
- struct sockaddr_in *sin;
- struct tcphdr *th;
- struct udphdr *uh;
- struct sctphdr *sh;
- if ((V_flowtable_enable == 0) || (V_flowtable_ready == 0))
- return (0);
+ fle->f_flags |= FL_STALE;
+}
+
+static __inline int
+proto_to_flags(uint8_t proto)
+{
+ int flag;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ flag = FL_TCP;
+ break;
+ case IPPROTO_SCTP:
+ flag = FL_SCTP;
+ break;
+ case IPPROTO_UDP:
+ flag = FL_UDP;
+ break;
+ default:
+ flag = 0;
+ break;
+ }
+
+ return (flag);
+}
+
+static __inline int
+flags_to_proto(int flags)
+{
+ int proto, protoflags;
+
+ protoflags = flags & (FL_TCP|FL_SCTP|FL_UDP);
+ switch (protoflags) {
+ case FL_TCP:
+ proto = IPPROTO_TCP;
+ break;
+ case FL_SCTP:
+ proto = IPPROTO_SCTP;
+ break;
+ case FL_UDP:
+ proto = IPPROTO_UDP;
+ break;
+ default:
+ proto = 0;
+ break;
+ }
+ return (proto);
+}
+
+void
+flow_to_route(struct flentry *fle, struct route *ro)
+{
+ struct sockaddr_in *sin = NULL;
+ struct sockaddr_in6 *sin6 = NULL;
+ uint32_t *hashkey;
+
+#ifdef INET6
+ if (fle->f_flags & FL_IPV6) {
+ sin6 = (struct sockaddr_in6 *)&ro->ro_dst;
+
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin);
+ hashkey = ((struct flentry_v6 *)fle)->fl_flow.ipf_key;
+ memcpy(&sin6->sin6_addr, &hashkey[1], sizeof (struct in6_addr));
+ } else
+#endif
+#ifdef INET
+ {
+ sin = (struct sockaddr_in *)&ro->ro_dst;
- key[1] = key[0] = 0;
- sin = (struct sockaddr_in *)&ro->ro_dst;
- if (m != NULL) {
- ip = mtod(m, struct ip *);
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
- sin->sin_addr = ip->ip_dst;
- } else
- *flags &= ~FL_HASH_PORTS;
+ hashkey = ((struct flentry_v4 *)fle)->fl_flow.ipf_key;
+ sin->sin_addr.s_addr = hashkey[1];
+ }
+#endif
+ ; /* terminate INET6 else if no INET4 */
+ ro->ro_rt = __DEVOLATILE(struct rtentry *, fle->f_rt);
+ ro->ro_lle = __DEVOLATILE(struct llentry *, fle->f_lle);
+}
- key[2] = sin->sin_addr.s_addr;
+#ifdef INET
+static int
+ipv4_mbuf_demarshal(struct mbuf *m, struct sockaddr_in *ssin,
+ struct sockaddr_in *dsin, uint16_t *flags)
+{
+ struct ip *ip;
+ uint8_t proto;
+ int iphlen;
+ struct tcphdr *th;
+ struct udphdr *uh;
+ struct sctphdr *sh;
+ uint16_t sport, dport;
- if ((*flags & FL_HASH_PORTS) == 0)
- goto skipports;
+ sport = dport = 0;
+ ip = mtod(m, struct ip *);
+ dsin->sin_family = AF_INET;
+ dsin->sin_len = sizeof(*dsin);
+ dsin->sin_addr = ip->ip_dst;
+ ssin->sin_family = AF_INET;
+ ssin->sin_len = sizeof(*dsin);
+ ssin->sin_addr = ip->ip_dst;
proto = ip->ip_p;
iphlen = ip->ip_hl << 2; /* XXX options? */
- key[1] = ip->ip_src.s_addr;
-
+
switch (proto) {
case IPPROTO_TCP:
th = (struct tcphdr *)((caddr_t)ip + iphlen);
@@ -401,38 +484,244 @@ ipv4_flow_lookup_hash_internal(struct mb
dport = sh->dest_port;
break;
default:
- if (*flags & FL_HASH_PORTS)
- goto noop;
+ return (ENOTSUP);
/* no port - hence not a protocol we care about */
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;
+ *flags |= proto_to_flags(proto);
+ ssin->sin_port = sport;
+ dsin->sin_port = dport;
+ return (0);
+}
- ((uint16_t *)key)[0] = sport;
- ((uint16_t *)key)[1] = dport;
+static uint32_t
+ipv4_flow_lookup_hash_internal(
+ struct sockaddr_in *ssin, struct sockaddr_in *dsin,
+ uint32_t *key, uint16_t flags)
+{
+ uint16_t sport, dport;
+ uint8_t proto;
-skipports:
- hash = jenkins_hashword(key, 3, V_flow_hashjitter + proto);
- if (m != NULL && (m->m_flags & M_FLOWID) == 0) {
- m->m_flags |= M_FLOWID;
- m->m_pkthdr.flowid = hash;
+ if ((V_flowtable_enable == 0) || (V_flowtable_ready == 0))
+ return (0);
+
+ proto = flags_to_proto(flags);
+ sport = dport = key[2] = key[1] = key[0] = 0;
+ if (dsin != NULL) {
+ key[1] = dsin->sin_addr.s_addr;
+ dport = dsin->sin_port;
+ }
+ if ((ssin != NULL) && (flags & FL_HASH_ALL)) {
+ key[2] = ssin->sin_addr.s_addr;
+ sport = ssin->sin_port;
+ }
+ if (flags & FL_HASH_ALL) {
+ ((uint16_t *)key)[0] = sport;
+ ((uint16_t *)key)[1] = dport;
+ }
+
+ return (jenkins_hashword(key, 3, V_flow_hashjitter + proto));
+}
+
+static struct flentry *
+flowtable_lookup_mbuf4(struct flowtable *ft, struct mbuf *m)
+{
+ struct sockaddr ssa, dsa;
+ uint16_t flags;
+ struct sockaddr_in *dsin, *ssin;
+
+ dsin = (struct sockaddr_in *)&dsa;
+ ssin = (struct sockaddr_in *)&ssa;
+ flags = 0;
+ if (ipv4_mbuf_demarshal(m, ssin, dsin, &flags) != 0)
+ return (NULL);
+
+ return (flowtable_lookup(ft, &ssa, &dsa, M_GETFIB(m), flags));
+}
+#endif /* INET */
+
+#ifdef INET6
+/*
+ * PULLUP_TO(len, p, T) makes sure that len + sizeof(T) is contiguous,
+ * then it sets p to point at the offset "len" in the mbuf. WARNING: the
+ * pointer might become stale after other pullups (but we never use it
+ * this way).
+ */
+#define PULLUP_TO(_len, p, T) \
+do { \
+ int x = (_len) + sizeof(T); \
+ if ((m)->m_len < x) { \
+ goto receive_failed; \
+ } \
+ p = (mtod(m, char *) + (_len)); \
+} while (0)
+
+#define TCP(p) ((struct tcphdr *)(p))
+#define SCTP(p) ((struct sctphdr *)(p))
+#define UDP(p) ((struct udphdr *)(p))
+
+static int
+ipv6_mbuf_demarshal(struct mbuf *m, struct sockaddr_in6 *ssin6,
+ struct sockaddr_in6 *dsin6, uint16_t *flags)
+{
+ struct ip6_hdr *ip6;
+ uint8_t proto;
+ int hlen;
+ uint16_t src_port, dst_port;
+ u_short offset;
+ void *ulp;
+
+ offset = hlen = src_port = dst_port = 0;
+ ulp = NULL;
+ ip6 = mtod(m, struct ip6_hdr *);
+ hlen = sizeof(struct ip6_hdr);
+ proto = ip6->ip6_nxt;
+
+ while (ulp == NULL) {
+ switch (proto) {
+ case IPPROTO_ICMPV6:
+ case IPPROTO_OSPFIGP:
+ case IPPROTO_PIM:
+ case IPPROTO_CARP:
+ case IPPROTO_ESP:
+ case IPPROTO_NONE:
+ ulp = ip6;
+ break;
+ case IPPROTO_TCP:
+ PULLUP_TO(hlen, ulp, struct tcphdr);
+ dst_port = TCP(ulp)->th_dport;
+ src_port = TCP(ulp)->th_sport;
+ *flags = TCP(ulp)->th_flags;
+ if (*flags & (TH_RST|TH_FIN))
+ *flags |= FL_STALE;
+ break;
+ case IPPROTO_SCTP:
+ PULLUP_TO(hlen, ulp, struct sctphdr);
+ src_port = SCTP(ulp)->src_port;
+ dst_port = SCTP(ulp)->dest_port;
+ break;
+ case IPPROTO_UDP:
+ PULLUP_TO(hlen, ulp, struct udphdr);
+ dst_port = UDP(ulp)->uh_dport;
+ src_port = UDP(ulp)->uh_sport;
+ break;
+ case IPPROTO_HOPOPTS: /* RFC 2460 */
+ PULLUP_TO(hlen, ulp, struct ip6_hbh);
+ hlen += (((struct ip6_hbh *)ulp)->ip6h_len + 1) << 3;
+ proto = ((struct ip6_hbh *)ulp)->ip6h_nxt;
+ ulp = NULL;
+ break;
+ case IPPROTO_ROUTING: /* RFC 2460 */
+ PULLUP_TO(hlen, ulp, struct ip6_rthdr);
+ hlen += (((struct ip6_rthdr *)ulp)->ip6r_len + 1) << 3;
+ proto = ((struct ip6_rthdr *)ulp)->ip6r_nxt;
+ ulp = NULL;
+ break;
+ case IPPROTO_FRAGMENT: /* RFC 2460 */
+ PULLUP_TO(hlen, ulp, struct ip6_frag);
+ hlen += sizeof (struct ip6_frag);
+ proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
+ offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
+ IP6F_OFF_MASK;
+ ulp = NULL;
+ break;
+ case IPPROTO_DSTOPTS: /* RFC 2460 */
+ PULLUP_TO(hlen, ulp, struct ip6_hbh);
+ hlen += (((struct ip6_hbh *)ulp)->ip6h_len + 1) << 3;
+ proto = ((struct ip6_hbh *)ulp)->ip6h_nxt;
+ ulp = NULL;
+ break;
+ case IPPROTO_AH: /* RFC 2402 */
+ PULLUP_TO(hlen, ulp, struct ip6_ext);
+ hlen += (((struct ip6_ext *)ulp)->ip6e_len + 2) << 2;
+ proto = ((struct ip6_ext *)ulp)->ip6e_nxt;
+ ulp = NULL;
+ break;
+ default:
+ PULLUP_TO(hlen, ulp, struct ip6_ext);
+ break;
+ }
}
- return (hash);
-noop:
- *protop = proto;
+ if (src_port == 0) {
+ receive_failed:
+ return (ENOTSUP);
+ }
+
+ dsin6->sin6_family = AF_INET6;
+ dsin6->sin6_len = sizeof(*dsin6);
+ memcpy(&dsin6->sin6_addr, &ip6->ip6_dst, sizeof(struct in6_addr));
+
+ ssin6->sin6_family = AF_INET6;
+ ssin6->sin6_len = sizeof(*ssin6);
+ memcpy(&ssin6->sin6_addr, &ip6->ip6_src, sizeof(struct in6_addr));
+ *flags |= proto_to_flags(proto);
+
return (0);
}
+#define zero_key(key) \
+do { \
+ key[0] = 0; \
+ key[1] = 0; \
+ key[2] = 0; \
+ key[3] = 0; \
+ key[4] = 0; \
+ key[5] = 0; \
+ key[6] = 0; \
+ key[7] = 0; \
+ key[8] = 0; \
+} while (0)
+
+static uint32_t
+ipv6_flow_lookup_hash_internal(
+ struct sockaddr_in6 *ssin6, struct sockaddr_in6 *dsin6,
+ uint32_t *key, uint16_t flags)
+{
+ uint16_t sport, dport;
+ uint8_t proto;
+
+ if ((V_flowtable_enable == 0) || (V_flowtable_ready == 0))
+ return (0);
+
+ proto = flags_to_proto(flags);
+ zero_key(key);
+ sport = dport = 0;
+ if (dsin6 != NULL) {
+ memcpy(&key[1], &dsin6->sin6_addr, sizeof(struct in6_addr));
+ dport = dsin6->sin6_port;
+ }
+ if ((ssin6 != NULL) && (flags & FL_HASH_ALL)) {
+ memcpy(&key[5], &ssin6->sin6_addr, sizeof(struct in6_addr));
+ sport = ssin6->sin6_port;
+ }
+ if (flags & FL_HASH_ALL) {
+ ((uint16_t *)key)[0] = sport;
+ ((uint16_t *)key)[1] = dport;
+ }
+
+ return (jenkins_hashword(key, 9, V_flow_hashjitter + proto));
+}
+
+static struct flentry *
+flowtable_lookup_mbuf6(struct flowtable *ft, struct mbuf *m)
+{
+ struct sockaddr ssa, dsa;
+ struct sockaddr_in6 *dsin6, *ssin6;
+ uint16_t flags;
+
+ dsin6 = (struct sockaddr_in6 *)&dsa;
+ ssin6 = (struct sockaddr_in6 *)&ssa;
+ flags = 0;
+ if (ipv6_mbuf_demarshal(m, ssin6, dsin6, &flags) != 0)
+ return (NULL);
+
+ return (flowtable_lookup(ft, &ssa, &dsa, M_GETFIB(m), flags));
+}
+#endif /* INET6 */
+
static bitstr_t *
flowtable_mask(struct flowtable *ft)
{
@@ -553,6 +842,9 @@ flowtable_insert(struct flowtable *ft, u
FL_ENTRY_UNLOCK(ft, hash);
uma_zfree((newfle->f_flags & FL_IPV6) ?
V_flow_ipv6_zone : V_flow_ipv4_zone, newfle);
+
+ if (flags & FL_OVERWRITE)
+ goto skip;
return (EEXIST);
}
/*
@@ -582,6 +874,21 @@ skip:
return (0);
}
+int
+kern_flowtable_insert(struct flowtable *ft, struct sockaddr *ssa,
+ struct sockaddr *dsa, struct route *ro, uint32_t fibnum, int flags,
+ uint8_t proto)
+{
+ uint32_t key[9], hash;
+
+ flags = (ft->ft_flags | flags | FL_OVERWRITE);
+
+ hash = ipv4_flow_lookup_hash_internal((struct sockaddr_in *)ssa,
+ (struct sockaddr_in *)dsa, key, flags);
+
+ return (flowtable_insert(ft, hash, key, proto, fibnum, ro, flags));
+}
+
static int
flowtable_key_equal(struct flentry *fle, uint32_t *key)
{
@@ -603,42 +910,74 @@ flowtable_key_equal(struct flentry *fle,
return (1);
}
-int
-flowtable_lookup(struct flowtable *ft, struct mbuf *m, struct route *ro, uint32_t fibnum)
+struct flentry *
+flowtable_lookup_mbuf(struct flowtable *ft, struct mbuf *m, int af)
+{
+ struct flentry *fle = NULL;
+
+#ifdef INET
+ if (af == AF_INET)
+ fle = flowtable_lookup_mbuf4(ft, m);
+#endif
+#ifdef INET6
+ if (af == AF_INET6)
+ fle = flowtable_lookup_mbuf6(ft, m);
+#endif
+ if (fle != NULL && m != NULL && (m->m_flags & M_FLOWID) == 0) {
+ m->m_flags |= M_FLOWID;
+ m->m_pkthdr.flowid = fle->f_fhash;
+ }
+ return (fle);
+}
+
+struct flentry *
+flowtable_lookup(struct flowtable *ft, struct sockaddr *ssa,
+ struct sockaddr *dsa, uint32_t fibnum, int flags)
{
uint32_t key[9], hash;
struct flentry *fle;
- uint16_t flags;
uint8_t proto = 0;
int error = 0;
struct rtentry *rt;
struct llentry *lle;
+ struct route sro, *ro;
- flags = ft->ft_flags;
+ ro = &sro;
ro->ro_rt = NULL;
ro->ro_lle = NULL;
+ hash = 0;
+ flags |= ft->ft_flags;
+#ifdef INET
+ if (ssa->sa_family == AF_INET) {
+ struct sockaddr_in *ssin, *dsin;
- /*
- * The internal hash lookup is the only IPv4 specific bit
- * remaining
- *
- * XXX BZ: to add IPv6 support just add a check for the
- * address type in m and ro and an equivalent ipv6 lookup
- * function - the rest of the code should automatically
- * handle an ipv6 flow (note that m can be NULL in which
- * case ro will be set)
- */
- hash = ipv4_flow_lookup_hash_internal(m, ro, key,
- &flags, &proto);
+ dsin = (struct sockaddr_in *)dsa;
+ ssin = (struct sockaddr_in *)ssa;
+
+ hash = ipv4_flow_lookup_hash_internal(ssin, dsin, key, flags);
+ }
+#endif
+#ifdef INET6
+ if (ssa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *ssin6, *dsin6;
+
+ dsin6 = (struct sockaddr_in6 *)dsa;
+ ssin6 = (struct sockaddr_in6 *)ssa;
+
+ hash = ipv6_flow_lookup_hash_internal(ssin6, dsin6, key, flags);
+ }
+#endif
+ if (hash == 0)
+ return (NULL);
/*
* Ports are zero and this isn't a transmit cache
* - thus not a protocol for which we need to keep
* state
- * FL_HASH_PORTS => key[0] != 0 for TCP || UDP || SCTP
+ * FL_HASH_ALL => key[0] != 0 for TCP || UDP || SCTP
*/
- if (hash == 0 || (key[0] == 0 && (ft->ft_flags & FL_HASH_PORTS)))
- return (ENOENT);
+ if (hash == 0 || (key[0] == 0 && (ft->ft_flags & FL_HASH_ALL)))
+ return (NULL);
V_flowtable_lookups++;
FL_ENTRY_LOCK(ft, hash);
@@ -647,6 +986,7 @@ flowtable_lookup(struct flowtable *ft, s
goto uncached;
}
keycheck:
+ proto = flags_to_proto(flags);
rt = __DEVOLATILE(struct rtentry *, fle->f_rt);
lle = __DEVOLATILE(struct llentry *, fle->f_lle);
if ((rt != NULL)
@@ -659,16 +999,15 @@ keycheck:
V_flowtable_hits++;
fle->f_uptime = time_uptime;
fle->f_flags |= flags;
- ro->ro_rt = rt;
- ro->ro_lle = lle;
FL_ENTRY_UNLOCK(ft, hash);
- return (0);
+ return (fle);
} else if (fle->f_next != NULL) {
fle = fle->f_next;
goto keycheck;
}
FL_ENTRY_UNLOCK(ft, hash);
-
+ if (flags & FL_NOAUTO)
+ return (NULL);
uncached:
V_flowtable_misses++;
/*
@@ -695,9 +1034,8 @@ uncached:
if (ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) {
RTFREE(rt);
ro->ro_rt = NULL;
- return (ENOENT);
+ return (NULL);
}
-
if (rt->rt_flags & RTF_GATEWAY)
l3addr = rt->rt_gateway;
else
@@ -708,7 +1046,7 @@ uncached:
if (lle == NULL) {
RTFREE(rt);
ro->ro_rt = NULL;
- return (ENOENT);
+ return (NULL);
}
error = flowtable_insert(ft, hash, key, proto, fibnum,
ro, flags);
@@ -721,7 +1059,7 @@ uncached:
}
}
- return (error);
+ return ((error) ? NULL : fle);
}
/*
@@ -783,7 +1121,7 @@ flowtable_alloc(int nentry, int flags)
* just a cache - so everything is eligible for
* replacement after 5s of non-use
*/
- if (flags & FL_HASH_PORTS) {
+ if (flags & FL_HASH_ALL) {
ft->ft_udp_idle = V_flowtable_udp_expire;
ft->ft_syn_idle = V_flowtable_syn_expire;
ft->ft_fin_wait_idle = V_flowtable_fin_wait_expire;
Modified: user/kmacy/head_flowtable_v6/sys/net/flowtable.h
==============================================================================
--- user/kmacy/head_flowtable_v6/sys/net/flowtable.h Wed Feb 3 23:59:52 2010 (r203461)
+++ user/kmacy/head_flowtable_v6/sys/net/flowtable.h Thu Feb 4 00:11:34 2010 (r203462)
@@ -34,10 +34,13 @@ $FreeBSD$
#ifdef _KERNEL
-#define FL_HASH_PORTS (1<<0) /* hash 4-tuple + protocol */
+#define FL_HASH_ALL (1<<0) /* hash 4-tuple + protocol */
#define FL_PCPU (1<<1) /* pcpu cache */
+#define FL_NOAUTO (1<<2) /* don't automatically add flentry on miss */
struct flowtable;
+struct flentry;
+
VNET_DECLARE(struct flowtable *, ip_ft);
#define V_ip_ft VNET(ip_ft)
@@ -48,8 +51,18 @@ struct flowtable *flowtable_alloc(int ne
* return it in the route.
*
*/
-int flowtable_lookup(struct flowtable *ft, struct mbuf *m,
- struct route *ro, uint32_t fibnum);
+struct flentry *flowtable_lookup_mbuf(struct flowtable *ft, struct mbuf *m, int af);
+
+struct flentry *flowtable_lookup(struct flowtable *ft, struct sockaddr *ssa,
+ struct sockaddr *dsa, uint32_t fibnum, int flags);
+
+int kern_flowtable_insert(struct flowtable *ft, struct sockaddr *ssa,
+ struct sockaddr *dsa, struct route *ro, uint32_t fibnum, int flags,
+ uint8_t proto);
+
+void flow_invalidate(struct flentry *fl);
+
+void flow_to_route(struct flentry *fl, struct route *ro);
void flowtable_route_flush(struct flowtable *ft, struct rtentry *rt);
Modified: user/kmacy/head_flowtable_v6/sys/netinet/ip_output.c
==============================================================================
--- user/kmacy/head_flowtable_v6/sys/netinet/ip_output.c Wed Feb 3 23:59:52 2010 (r203461)
+++ user/kmacy/head_flowtable_v6/sys/netinet/ip_output.c Thu Feb 4 00:11:34 2010 (r203462)
@@ -148,14 +148,20 @@ ip_output(struct mbuf *m, struct mbuf *o
bzero(ro, sizeof (*ro));
#ifdef FLOWTABLE
- /*
- * The flow table returns route entries valid for up to 30
- * seconds; we rely on the remainder of ip_output() taking no
- * longer than that long for the stability of ro_rt. The
- * flow ID assignment must have happened before this point.
- */
- if (flowtable_lookup(V_ip_ft, m, ro, M_GETFIB(m)) == 0)
- nortfree = 1;
+ {
+ struct flentry *fle;
+
+ /*
+ * The flow table returns route entries valid for up to 30
+ * seconds; we rely on the remainder of ip_output() taking no
+ * longer than that long for the stability of ro_rt. The
+ * flow ID assignment must have happened before this point.
+ */
+ if ((fle = flowtable_lookup_mbuf(V_ip_ft, m, AF_INET)) != NULL)
+ flow_to_route(fle, ro);
+ else
+ nortfree = 1;
+ }
#endif
}
More information about the svn-src-user
mailing list