PERFORCE change 126352 for review

Kip Macy kmacy at FreeBSD.org
Wed Sep 12 18:38:07 PDT 2007


http://perforce.freebsd.org/chv.cgi?CH=126352

Change 126352 by kmacy at kmacy_home:ethng on 2007/09/13 01:37:50

	add rtalloc2 which does the same work as rtalloc1 but: 
	- internally locks the route shared except when bumping the refcount
	- returns the route unlocked
	plug locking holes introduced in previous revision of rtalloc1

Affected files ...

.. //depot/projects/ethng/src/sys/net/route.c#5 edit

Differences ...

==== //depot/projects/ethng/src/sys/net/route.c#5 (text+ko) ====

@@ -114,9 +114,7 @@
 		RTFREE(rt);
 		ro->ro_rt = NULL;
 	}
-	ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore);
-	if (ro->ro_rt)
-		RT_UNLOCK(ro->ro_rt);
+	ro->ro_rt = rtalloc2(&ro->ro_dst, 1, ignore);
 }
 
 /*
@@ -153,8 +151,121 @@
 		 */
 		newrt = rt = RNTORT(rn);
 		nflags = rt->rt_flags & ~ignflags;
+		if (report && (nflags & RTF_CLONING)) {
+			RADIX_NODE_HEAD_UNLOCK_SHARED(rnh);
+			RADIX_NODE_HEAD_LOCK(rnh);
+			/*
+			 * We are apparently adding (report = 0 in delete).
+			 * If it requires that it be cloned, do so.
+			 * (This implies it wasn't a HOST route.)
+			 */
+			err = rtrequest(RTM_RESOLVE, dst, NULL,
+					      NULL, 0, &newrt);
+			if (err) {
+				if (!((rn = rnh->rnh_matchaddr(dst, rnh)) &&
+					(rn->rn_flags & RNF_ROOT) == 0)) {
+					RADIX_NODE_HEAD_UNLOCK(rnh);
+					goto miss2;
+				}
+				/*
+				 * If the cloning didn't succeed, maybe
+				 * what we have will do. Return that.
+				 */
+				newrt = rt;		/* existing route */
+				RT_LOCK(newrt);
+				RADIX_NODE_HEAD_UNLOCK(rnh);
+				RT_ADDREF(newrt);
+				goto miss2;
+			}
+			KASSERT(newrt, ("no route and no error"));
+			RT_LOCK(newrt);
+			RADIX_NODE_HEAD_UNLOCK(rnh);
+			if (newrt->rt_flags & RTF_XRESOLVE) {
+				/*
+				 * If the new route specifies it be
+				 * externally resolved, then go do that.
+				 */
+				msgtype = RTM_RESOLVE;
+				goto miss2;
+			}
+			/* Inform listeners of the new route. */
+			bzero(&info, sizeof(info));
+			info.rti_info[RTAX_DST] = rt_key(newrt);
+			info.rti_info[RTAX_NETMASK] = rt_mask(newrt);
+			info.rti_info[RTAX_GATEWAY] = newrt->rt_gateway;
+			if (newrt->rt_ifp != NULL) {
+				info.rti_info[RTAX_IFP] =
+				    newrt->rt_ifp->if_addr->ifa_addr;
+				info.rti_info[RTAX_IFA] = newrt->rt_ifa->ifa_addr;
+			}
+			rt_missmsg(RTM_ADD, &info, newrt->rt_flags, 0);
+		} else {
+			KASSERT(rt == newrt, ("locking wrong route"));
+			RT_LOCK(newrt);
+			RADIX_NODE_HEAD_UNLOCK_SHARED(rnh);
+			RT_ADDREF(newrt);
+		}
+	} else {
+		/*
+		 * Either we hit the root or couldn't find any match,
+		 * Which basically means
+		 * "caint get there frm here"
+		 */
+		rtstat.rts_unreach++;
 		RADIX_NODE_HEAD_UNLOCK_SHARED(rnh);
+	miss2:	if (report) {
+			/*
+			 * If required, report the failure to the supervising
+			 * Authorities.
+			 * For a delete, this is not an error. (report == 0)
+			 */
+			bzero(&info, sizeof(info));
+			info.rti_info[RTAX_DST] = dst;
+			rt_missmsg(msgtype, &info, 0, err);
+		}
+	}
+	if (newrt)
+		RT_LOCK_ASSERT(newrt);
+	return (newrt);
+}
+
+/*
+ * Look up the route that matches the address given
+ * Or, at least try.. Create a cloned route if needed.
+ *
+ * The returned route, if any, is locked.
+ */
+struct rtentry *
+rtalloc2(struct sockaddr *dst, int report, u_long ignflags)
+{
+	struct radix_node_head *rnh = rt_tables[dst->sa_family];
+	struct rtentry *rt;
+	struct radix_node *rn;
+	struct rtentry *newrt;
+	struct rt_addrinfo info;
+	u_long nflags;
+	int err = 0, msgtype = RTM_MISS;
+
+	newrt = NULL;
+	/*
+	 * Look up the address in the table for that Address Family
+	 */
+	if (rnh == NULL) {
+		rtstat.rts_unreach++;
+		goto miss2;
+	}
+	RADIX_NODE_HEAD_LOCK_SHARED(rnh);
+	if ((rn = rnh->rnh_matchaddr(dst, rnh)) &&
+	    (rn->rn_flags & RNF_ROOT) == 0) {
+		/*
+		 * If we find it and it's not the root node, then
+		 * get a reference on the rtentry associated.
+		 */
+		newrt = rt = RNTORT(rn);
+		nflags = rt->rt_flags & ~ignflags;
 		if (report && (nflags & RTF_CLONING)) {
+			RADIX_NODE_HEAD_UNLOCK_SHARED(rnh);
+			RADIX_NODE_HEAD_LOCK(rnh);
 			/*
 			 * We are apparently adding (report = 0 in delete).
 			 * If it requires that it be cloned, do so.
@@ -163,29 +274,32 @@
 			err = rtrequest(RTM_RESOLVE, dst, NULL,
 					      NULL, 0, &newrt);
 			if (err) {
-				RADIX_NODE_HEAD_LOCK_SHARED(rnh);
 				if (!((rn = rnh->rnh_matchaddr(dst, rnh)) &&
-					(rn->rn_flags & RNF_ROOT) == 0)) 
-					goto miss;
+					(rn->rn_flags & RNF_ROOT) == 0)) {
+					RADIX_NODE_HEAD_UNLOCK(rnh);
+					goto miss2;
+				}
 				/*
 				 * If the cloning didn't succeed, maybe
 				 * what we have will do. Return that.
 				 */
 				newrt = rt;		/* existing route */
 				RT_LOCK(newrt);
-				RADIX_NODE_HEAD_UNLOCK_SHARED(rnh);
+				RADIX_NODE_HEAD_UNLOCK(rnh);
 				RT_ADDREF(newrt);
-				goto miss;
+				RT_LOCK_DOWNGRADE(newrt);
+				goto miss2;
 			}
+			RT_LOCK_SHARED(newrt);
+			RADIX_NODE_HEAD_UNLOCK(rnh);
 			KASSERT(newrt, ("no route and no error"));
-			RT_LOCK(newrt);
 			if (newrt->rt_flags & RTF_XRESOLVE) {
 				/*
 				 * If the new route specifies it be
 				 * externally resolved, then go do that.
 				 */
 				msgtype = RTM_RESOLVE;
-				goto miss;
+				goto miss2;
 			}
 			/* Inform listeners of the new route. */
 			bzero(&info, sizeof(info));
@@ -201,7 +315,9 @@
 		} else {
 			KASSERT(rt == newrt, ("locking wrong route"));
 			RT_LOCK(newrt);
+			RADIX_NODE_HEAD_UNLOCK_SHARED(rnh);
 			RT_ADDREF(newrt);
+			RT_LOCK_DOWNGRADE(newrt);
 		}
 	} else {
 		/*
@@ -210,7 +326,6 @@
 		 * "caint get there frm here"
 		 */
 		rtstat.rts_unreach++;
-	miss:
 		RADIX_NODE_HEAD_UNLOCK_SHARED(rnh);
 	miss2:	if (report) {
 			/*
@@ -225,6 +340,9 @@
 	}
 	if (newrt)
 		RT_LOCK_ASSERT(newrt);
+
+	RT_UNLOCK_SHARED(newrt);
+
 	return (newrt);
 }
 


More information about the p4-projects mailing list