svn commit: r186625 - user/kmacy/HEAD_fast_net/sys/net

Kip Macy kmacy at FreeBSD.org
Wed Dec 31 03:13:06 UTC 2008


Author: kmacy
Date: Wed Dec 31 03:13:05 2008
New Revision: 186625
URL: http://svn.freebsd.org/changeset/base/186625

Log:
  import kernel support for route shutdown

Modified:
  user/kmacy/HEAD_fast_net/sys/net/radix_mpath.c
  user/kmacy/HEAD_fast_net/sys/net/route.c
  user/kmacy/HEAD_fast_net/sys/net/route.h

Modified: user/kmacy/HEAD_fast_net/sys/net/radix_mpath.c
==============================================================================
--- user/kmacy/HEAD_fast_net/sys/net/radix_mpath.c	Wed Dec 31 03:02:59 2008	(r186624)
+++ user/kmacy/HEAD_fast_net/sys/net/radix_mpath.c	Wed Dec 31 03:13:05 2008	(r186625)
@@ -81,11 +81,15 @@ u_int32_t
 rn_mpath_count(struct radix_node *rn)
 {
 	u_int32_t i;
-
+	struct rtentry *rt;
+	
 	i = 1;
-	while ((rn = rn_mpath_next(rn)) != NULL)
-		i++;
-	return i;
+	while ((rn = rn_mpath_next(rn)) != NULL) {
+		rt = (struct rtentry *)rn;
+		if ((rt->rt_flags & RTF_SHUTDOWN) == 0)
+			i++;
+	}
+	return (i);
 }
 
 struct rtentry *
@@ -260,7 +264,8 @@ rtalloc_mpath_fib(struct route *ro, u_in
 {
 	struct radix_node *rn0, *rn;
 	u_int32_t n;
-
+	struct rtentry *rt;
+	
 	/*
 	 * XXX we don't attempt to lookup cached route again; what should
 	 * be done for sendto(3) case?
@@ -285,6 +290,11 @@ rtalloc_mpath_fib(struct route *ro, u_in
 	hash += hashjitter;
 	hash %= n;
 	while (hash-- > 0 && rn) {
+		rt = (struct rtentry *)rn;
+		if (rt->rt_flags & RTF_SHUTDOWN) {
+			hash++;
+			continue;
+		}
 		/* stay within the multipath routes */
 		if (rn->rn_dupedkey && rn->rn_mask != rn->rn_dupedkey->rn_mask)
 			break;

Modified: user/kmacy/HEAD_fast_net/sys/net/route.c
==============================================================================
--- user/kmacy/HEAD_fast_net/sys/net/route.c	Wed Dec 31 03:02:59 2008	(r186624)
+++ user/kmacy/HEAD_fast_net/sys/net/route.c	Wed Dec 31 03:13:05 2008	(r186625)
@@ -803,6 +803,98 @@ bad:
 	return (error);
 }
 
+#ifdef RADIX_MPATH
+static int
+rn_mpath_delete(int req, struct rt_addrinfo *info,
+    struct radix_node_head *rnh, struct rtentry **ret_nrt)
+{
+	/*
+	 * if we got multipath routes, we require users to specify
+	 * a matching RTAX_GATEWAY.
+	 */
+	struct rtentry *rto = NULL;
+	int error = 0;
+
+	rn = rnh->rnh_matchaddr(dst, rnh);
+	if (rn == NULL)
+		return (ESRCH);
+	rto = rt = RNTORT(rn);
+	rt = rt_mpath_matchgate(rt, gateway);
+	if (!rt)
+		return (ESRCH);
+	/*
+	 * this is the first entry in the chain
+	 */
+	if (rto == rt) {
+		rn = rn_mpath_next((struct radix_node *)rt);
+		/*
+		 * there is another entry, now it's active
+		 */
+		if (rn) {
+			rto = RNTORT(rn);
+			RT_LOCK(rto);
+			rto->rt_flags |= RTF_UP;
+			RT_UNLOCK(rto);
+		} else if (rt->rt_flags & RTF_GATEWAY) {
+			/*
+			 * For gateway routes, we need to 
+			 * make sure that we we are deleting
+			 * the correct gateway. 
+			 * rt_mpath_matchgate() does not 
+			 * check the case when there is only
+			 * one route in the chain.  
+			 */
+			if (gateway &&
+			    (rt->rt_gateway->sa_len != gateway->sa_len ||
+				memcmp(rt->rt_gateway, gateway, gateway->sa_len)))
+				error = ESRCH;
+			goto done;
+		}
+		/*
+		 * use the normal delete code to remove
+		 * the first entry
+		 */
+		error = ENOENT;
+		goto done;
+	}
+		
+	/*
+	 * if the entry is 2nd and on up
+	 */
+	if ((req == RTM_DELETE) && !rt_mpath_deldup(rto, rt))
+		panic ("rtrequest1: rt_mpath_deldup");
+	RT_LOCK(rt);
+	RT_ADDREF(rt);
+	if (req == RTM_DELETE) {
+		rt->rt_flags &= ~RTF_UP;
+		/*
+		 * One more rtentry floating around that is not
+		 * linked to the routing table. rttrash will be decremented
+		 * when RTFREE(rt) is eventually called.
+		 */
+		V_rttrash++;
+		
+	} else if (req == RTM_SHUTDOWN)
+		rt->rt_flags |= RTF_SHUTDOWN;
+	else
+		panic("unrecognized request %d", req);
+	
+
+	/*
+	 * If the caller wants it, then it can have it,
+	 * but it's up to it to free the rtentry as we won't be
+	 * doing it.
+	 */
+	if (ret_nrt) {
+		*ret_nrt = rt;
+		RT_UNLOCK(rt);
+	} else
+		RTFREE_LOCKED(rt);
+done:
+	return (error);
+}
+#endif
+
 int
 rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
 				u_int fibnum)
@@ -841,65 +933,16 @@ rtrequest1_fib(int req, struct rt_addrin
 	switch (req) {
 	case RTM_DELETE:
 #ifdef RADIX_MPATH
-		/*
-		 * if we got multipath routes, we require users to specify
-		 * a matching RTAX_GATEWAY.
-		 */
+	case RTM_SHUTDOWN:		
 		if (rn_mpath_capable(rnh)) {
-			struct rtentry *rto = NULL;
-
-			rn = rnh->rnh_matchaddr(dst, rnh);
-			if (rn == NULL)
-				senderr(ESRCH);
- 			rto = rt = RNTORT(rn);
-			rt = rt_mpath_matchgate(rt, gateway);
-			if (!rt)
-				senderr(ESRCH);
-			/*
-			 * this is the first entry in the chain
-			 */
-			if (rto == rt) {
-				rn = rn_mpath_next((struct radix_node *)rt);
-				/*
-				 * there is another entry, now it's active
-				 */
-				if (rn) {
-					rto = RNTORT(rn);
-					RT_LOCK(rto);
-					rto->rt_flags |= RTF_UP;
-					RT_UNLOCK(rto);
-				} else if (rt->rt_flags & RTF_GATEWAY) {
-					/*
-					 * For gateway routes, we need to 
-					 * make sure that we we are deleting
-					 * the correct gateway. 
-					 * rt_mpath_matchgate() does not 
-					 * check the case when there is only
-					 * one route in the chain.  
-					 */
-					if (gateway &&
-					    (rt->rt_gateway->sa_len != gateway->sa_len ||
-					    memcmp(rt->rt_gateway, gateway, gateway->sa_len)))
-						senderr(ESRCH);
-				}
-				/*
-				 * use the normal delete code to remove
-				 * the first entry
-				 */
-				goto normal_rtdel;
-			}
+			error = rn_mpath_delete(req, info, rnh, ret_nrt);
 			/*
-			 * if the entry is 2nd and on up
+			 * "bad" holds true for the success case
+			 * as well
 			 */
-			if (!rt_mpath_deldup(rto, rt))
-				panic ("rtrequest1: rt_mpath_deldup");
-			RT_LOCK(rt);
-			RT_ADDREF(rt);
-			rt->rt_flags &= ~RTF_UP;
-			goto deldone;  /* done with the RTM_DELETE command */
+			if (error != ENOENT)
+				goto bad;
 		}
-
-normal_rtdel:
 #endif
 		/*
 		 * Remove the item from the tree and return it.
@@ -921,9 +964,6 @@ normal_rtdel:
 		if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
 			ifa->ifa_rtrequest(RTM_DELETE, rt, info);
 
-#ifdef RADIX_MPATH
-deldone:
-#endif
 		/*
 		 * One more rtentry floating around that is not
 		 * linked to the routing table. rttrash will be decremented

Modified: user/kmacy/HEAD_fast_net/sys/net/route.h
==============================================================================
--- user/kmacy/HEAD_fast_net/sys/net/route.h	Wed Dec 31 03:02:59 2008	(r186624)
+++ user/kmacy/HEAD_fast_net/sys/net/route.h	Wed Dec 31 03:13:05 2008	(r186625)
@@ -195,7 +195,8 @@ struct ortentry {
 #define	RTF_BROADCAST	0x400000	/* route represents a bcast address */
 #define	RTF_MULTICAST	0x800000	/* route represents a mcast address */
 					/* 0x1000000 and up unassigned */
-#define	RTF_RNH_LOCKED	 0x40000000	/* radix node head locked by caller */
+#define	RTF_SHUTDOWN	 0x20000000	/* no new connections */
+#define	RTF_RNH_LOCKED	 0x40000000	
 
 /* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */
 #define RTF_FMASK	\
@@ -254,6 +255,7 @@ struct rt_msghdr {
 #define	RTM_DELMADDR	0x10	/* mcast group membership being deleted */
 #define	RTM_IFANNOUNCE	0x11	/* iface arrival/departure */
 #define	RTM_IEEE80211	0x12	/* IEEE80211 wireless event */
+#define	RTM_SHUTDOWN	0x13	/* don't use for new connections */
 
 /*
  * Bitmask values for rtm_inits and rmx_locks.


More information about the svn-src-user mailing list