Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Oct 2009 20:32:29 +0000 (UTC)
From:      Qing Li <qingli@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r197687 - head/sys/net
Message-ID:  <200910012032.n91KWTOa064111@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: qingli
Date: Thu Oct  1 20:32:29 2009
New Revision: 197687
URL: http://svn.freebsd.org/changeset/base/197687

Log:
  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.
  
  Submitted by:	simon, phk
  Reviewed by:	bz, kmacy
  MFC after:	3 days

Modified:
  head/sys/net/flowtable.c
  head/sys/net/flowtable.h
  head/sys/net/route.c

Modified: head/sys/net/flowtable.c
==============================================================================
--- head/sys/net/flowtable.c	Thu Oct  1 20:11:42 2009	(r197686)
+++ head/sys/net/flowtable.c	Thu Oct  1 20:32:29 2009	(r197687)
@@ -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: head/sys/net/flowtable.h
==============================================================================
--- head/sys/net/flowtable.h	Thu Oct  1 20:11:42 2009	(r197686)
+++ head/sys/net/flowtable.h	Thu Oct  1 20:32:29 2009	(r197687)
@@ -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: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c	Thu Oct  1 20:11:42 2009	(r197686)
+++ head/sys/net/route.c	Thu Oct  1 20:32:29 2009	(r197687)
@@ -56,6 +56,7 @@
 #include <net/if_dl.h>
 #include <net/route.h>
 #include <net/vnet.h>
+#include <net/flowtable.h>
 
 #ifdef RADIX_MPATH
 #include <net/radix_mpath.h>
@@ -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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910012032.n91KWTOa064111>