From owner-svn-src-all@FreeBSD.ORG Tue Oct 6 18:47:03 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0285C106566B; Tue, 6 Oct 2009 18:47:03 +0000 (UTC) (envelope-from qingli@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E32AC8FC18; Tue, 6 Oct 2009 18:47:02 +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 n96Il2Ll060979; Tue, 6 Oct 2009 18:47:02 GMT (envelope-from qingli@svn.freebsd.org) Received: (from qingli@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n96Il2Dm060975; Tue, 6 Oct 2009 18:47:02 GMT (envelope-from qingli@svn.freebsd.org) Message-Id: <200910061847.n96Il2Dm060975@svn.freebsd.org> From: Qing Li Date: Tue, 6 Oct 2009 18:47:02 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r197810 - in stable/8/sys: . amd64/include/xen cddl/contrib/opensolaris contrib/dev/acpica contrib/pf dev/xen/xenpci net X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Oct 2009 18:47:03 -0000 Author: qingli Date: Tue Oct 6 18:47:02 2009 New Revision: 197810 URL: http://svn.freebsd.org/changeset/base/197810 Log: MFC r197687 The flow-table associates TCP/UDP flows and IP destinations with specific routes. When the routing table changes, for example, when a new route with a more specific prefix is inserted into the routing table, the flow-table is not updated to reflect that change. As such existing connections cannot take advantage of the new path. In some cases the path is broken. This patch will update the affected flow-table entries when a more specific route is added. The route entry is properly marked when a route is deleted from the table. In this case, when the flow-table performs a search, the stale entry is updated automatically. Therefore this patch is not necessary for route deletion. Reviewed by: bz, kmacy Approved by: re Modified: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/xen/xenpci/ (props changed) stable/8/sys/net/flowtable.c stable/8/sys/net/flowtable.h stable/8/sys/net/route.c Modified: stable/8/sys/net/flowtable.c ============================================================================== --- stable/8/sys/net/flowtable.c Tue Oct 6 17:33:00 2009 (r197809) +++ stable/8/sys/net/flowtable.c Tue Oct 6 18:47:02 2009 (r197810) @@ -830,7 +830,7 @@ fle_free(struct flentry *fle) } static void -flowtable_free_stale(struct flowtable *ft) +flowtable_free_stale(struct flowtable *ft, struct rtentry *rt) { int curbit = 0, count; struct flentry *fle, **flehead, *fleprev; @@ -866,8 +866,14 @@ flowtable_free_stale(struct flowtable *f curbit); } #endif - while (fle != NULL) { - if (!flow_stale(ft, fle)) { + while (fle != NULL) { + if (rt != NULL) { + if (__DEVOLATILE(struct rtentry *, fle->f_rt) != rt) { + fleprev = fle; + fle = fle->f_next; + continue; + } + } else if (!flow_stale(ft, fle)) { fleprev = fle; fle = fle->f_next; continue; @@ -916,6 +922,30 @@ flowtable_free_stale(struct flowtable *f log(LOG_DEBUG, "freed %d flow entries\n", count); } +void +flowtable_route_flush(struct flowtable *ft, struct rtentry *rt) +{ + int i; + if (ft->ft_flags & FL_PCPU) { + for (i = 0; i <= mp_maxid; i++) { + if (CPU_ABSENT(i)) + continue; + + thread_lock(curthread); + sched_bind(curthread, i); + thread_unlock(curthread); + + flowtable_free_stale(ft, rt); + + thread_lock(curthread); + sched_unbind(curthread); + thread_unlock(curthread); + } + } else { + flowtable_free_stale(ft, rt); + } +} + static void flowtable_clean_vnet(void) { @@ -933,14 +963,14 @@ flowtable_clean_vnet(void) sched_bind(curthread, i); thread_unlock(curthread); - flowtable_free_stale(ft); + flowtable_free_stale(ft, NULL); thread_lock(curthread); sched_unbind(curthread); thread_unlock(curthread); } } else { - flowtable_free_stale(ft); + flowtable_free_stale(ft, NULL); } ft = ft->ft_next; } Modified: stable/8/sys/net/flowtable.h ============================================================================== --- stable/8/sys/net/flowtable.h Tue Oct 6 17:33:00 2009 (r197809) +++ stable/8/sys/net/flowtable.h Tue Oct 6 18:47:02 2009 (r197810) @@ -51,5 +51,7 @@ struct flowtable *flowtable_alloc(int ne int flowtable_lookup(struct flowtable *ft, struct mbuf *m, struct route *ro, uint32_t fibnum); +void flowtable_route_flush(struct flowtable *ft, struct rtentry *rt); + #endif /* _KERNEL */ #endif Modified: stable/8/sys/net/route.c ============================================================================== --- stable/8/sys/net/route.c Tue Oct 6 17:33:00 2009 (r197809) +++ stable/8/sys/net/route.c Tue Oct 6 18:47:02 2009 (r197810) @@ -56,6 +56,7 @@ #include #include #include +#include #ifdef RADIX_MPATH #include @@ -996,6 +997,9 @@ rtrequest1_fib(int req, struct rt_addrin { int error = 0, needlock = 0; register struct rtentry *rt; +#ifdef FLOWTABLE + register struct rtentry *rt0; +#endif register struct radix_node *rn; register struct radix_node_head *rnh; struct ifaddr *ifa; @@ -1153,6 +1157,53 @@ rtrequest1_fib(int req, struct rt_addrin } #endif +#ifdef FLOWTABLE + rt0 = NULL; + /* XXX + * "flow-table" only support IPv4 at the moment. + */ + if (dst->sa_family == AF_INET) { + rn = rnh->rnh_matchaddr(dst, rnh); + if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) { + struct sockaddr *mask; + u_char *m, *n; + int len; + + /* + * compare mask to see if the new route is + * more specific than the existing one + */ + rt0 = RNTORT(rn); + RT_LOCK(rt0); + RT_ADDREF(rt0); + RT_UNLOCK(rt0); + /* + * A host route is already present, so + * leave the flow-table entries as is. + */ + if (rt0->rt_flags & RTF_HOST) { + RTFREE(rt0); + rt0 = NULL; + } else if (!(flags & RTF_HOST) && netmask) { + mask = rt_mask(rt0); + len = mask->sa_len; + m = (u_char *)mask; + n = (u_char *)netmask; + while (len-- > 0) { + if (*n != *m) + break; + n++; + m++; + } + if (len == 0 || (*n < *m)) { + RTFREE(rt0); + rt0 = NULL; + } + } + } + } +#endif + /* XXX mtu manipulation will be done in rnh_addaddr -- itojun */ rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes); /* @@ -1165,8 +1216,18 @@ rtrequest1_fib(int req, struct rt_addrin Free(rt_key(rt)); RT_LOCK_DESTROY(rt); uma_zfree(V_rtzone, rt); +#ifdef FLOWTABLE + if (rt0 != NULL) + RTFREE(rt0); +#endif senderr(EEXIST); + } +#ifdef FLOWTABLE + else if (rt0 != NULL) { + flowtable_route_flush(V_ip_ft, rt0); + RTFREE(rt0); } +#endif /* * If this protocol has something to add to this then