From owner-svn-src-user@FreeBSD.ORG Thu Feb 4 00:11:34 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B1C9B106566C; Thu, 4 Feb 2010 00:11:34 +0000 (UTC) (envelope-from kmacy@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 9FA168FC0C; Thu, 4 Feb 2010 00:11:34 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o140BYLk049630; Thu, 4 Feb 2010 00:11:34 GMT (envelope-from kmacy@svn.freebsd.org) Received: (from kmacy@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o140BYtJ049626; Thu, 4 Feb 2010 00:11:34 GMT (envelope-from kmacy@svn.freebsd.org) Message-Id: <201002040011.o140BYtJ049626@svn.freebsd.org> From: Kip Macy Date: Thu, 4 Feb 2010 00:11:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r203462 - in user/kmacy/head_flowtable_v6/sys: net netinet X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Feb 2010 00:11:34 -0000 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 __FBSDID("$FreeBSD$"); @@ -63,6 +65,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef INET6 +#include +#endif #include #include #include @@ -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 }