svn commit: r368147 - in head/sys: net netinet netinet6

Alexander V. Chernikov melifaro at FreeBSD.org
Sun Nov 29 13:41:51 UTC 2020


Author: melifaro
Date: Sun Nov 29 13:41:49 2020
New Revision: 368147
URL: https://svnweb.freebsd.org/changeset/base/368147

Log:
  Refactor fib4/fib6 functions.
  
  No functional changes.
  
  * Make lookup path of fib<4|6>_lookup_debugnet() separate functions
   (fib<46>_lookup_rt()). These will be used in the control plane code
   requiring unlocked radix operations and actual prefix pointer.
  * Make lookup part of fib<4|6>_check_urpf() separate functions.
   This change simplifies the switch to alternative lookup implementations,
   which helps algorithmic lookups introduction.
  * While here, use static initializers for IPv4/IPv6 keys
  
  Differential Revision:	https://reviews.freebsd.org/D27405

Modified:
  head/sys/net/route.h
  head/sys/netinet/in_fib.c
  head/sys/netinet/in_fib.h
  head/sys/netinet6/in6_fib.c
  head/sys/netinet6/in6_fib.h

Modified: head/sys/net/route.h
==============================================================================
--- head/sys/net/route.h	Sun Nov 29 13:27:24 2020	(r368146)
+++ head/sys/net/route.h	Sun Nov 29 13:41:49 2020	(r368147)
@@ -230,6 +230,7 @@ VNET_DECLARE(u_int, fib_hash_outbound);
 
 /* Control plane route request flags */
 #define	NHR_COPY		0x100	/* Copy rte data */
+#define	NHR_UNLOCKED		0x200	/* Do not lock table */
 
 /*
  * Routing statistics.

Modified: head/sys/netinet/in_fib.c
==============================================================================
--- head/sys/netinet/in_fib.c	Sun Nov 29 13:27:24 2020	(r368146)
+++ head/sys/netinet/in_fib.c	Sun Nov 29 13:41:49 2020	(r368147)
@@ -75,7 +75,6 @@ struct _hash_5tuple_ipv4 {
 _Static_assert(sizeof(struct _hash_5tuple_ipv4) == 16,
     "_hash_5tuple_ipv4 size is wrong");
 
-
 uint32_t
 fib4_calc_software_hash(struct in_addr src, struct in_addr dst,
     unsigned short src_port, unsigned short dst_port, char proto,
@@ -119,11 +118,11 @@ fib4_lookup(uint32_t fibnum, struct in_addr dst, uint3
 		return (NULL);
 
 	/* Prepare lookup key */
-	struct sockaddr_in sin4;
-	memset(&sin4, 0, sizeof(sin4));
-	sin4.sin_family = AF_INET;
-	sin4.sin_len = sizeof(struct sockaddr_in);
-	sin4.sin_addr = dst;
+	struct sockaddr_in sin4 = {
+		.sin_family = AF_INET,
+		.sin_len = sizeof(struct sockaddr_in),
+		.sin_addr = dst,
+	};
 
 	nh = NULL;
 	RIB_RLOCK(rh);
@@ -181,28 +180,18 @@ check_urpf(struct nhop_object *nh, uint32_t flags,
 		return (check_urpf_nhop(nh, flags, src_if));
 }
 
-/*
- * Performs reverse path forwarding lookup.
- * If @src_if is non-zero, verifies that at least 1 path goes via
- *   this interface.
- * If @src_if is zero, verifies that route exist.
- * if @flags contains NHR_NOTDEFAULT, do not consider default route.
- *
- * Returns 1 if route matching conditions is found, 0 otherwise.
- */
-int
-fib4_check_urpf(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
-  uint32_t flags, const struct ifnet *src_if)
+static struct nhop_object *
+lookup_nhop(uint32_t fibnum, struct in_addr dst, uint32_t scopeid)
 {
 	RIB_RLOCK_TRACKER;
 	struct rib_head *rh;
 	struct radix_node *rn;
-	int ret;
+	struct nhop_object *nh;
 
 	KASSERT((fibnum < rt_numfibs), ("fib4_check_urpf: bad fibnum"));
 	rh = rt_tables_get_rnh(fibnum, AF_INET);
 	if (rh == NULL)
-		return (0);
+		return (NULL);
 
 	/* Prepare lookup key */
 	struct sockaddr_in sin4;
@@ -210,49 +199,96 @@ fib4_check_urpf(uint32_t fibnum, struct in_addr dst, u
 	sin4.sin_len = sizeof(struct sockaddr_in);
 	sin4.sin_addr = dst;
 
+	nh = NULL;
 	RIB_RLOCK(rh);
 	rn = rh->rnh_matchaddr((void *)&sin4, &rh->head);
-	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
-		ret = check_urpf(RNTORT(rn)->rt_nhop, flags, src_if);
-		RIB_RUNLOCK(rh);
-		return (ret);
-	}
+	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0))
+		nh = RNTORT(rn)->rt_nhop;
 	RIB_RUNLOCK(rh);
 
+	return (nh);
+}
+
+/*
+ * Performs reverse path forwarding lookup.
+ * If @src_if is non-zero, verifies that at least 1 path goes via
+ *   this interface.
+ * If @src_if is zero, verifies that route exist.
+ * if @flags contains NHR_NOTDEFAULT, do not consider default route.
+ *
+ * Returns 1 if route matching conditions is found, 0 otherwise.
+ */
+int
+fib4_check_urpf(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
+  uint32_t flags, const struct ifnet *src_if)
+{
+	struct nhop_object *nh;
+
+	nh = lookup_nhop(fibnum, dst, scopeid);
+	if (nh != NULL)
+		return (check_urpf(nh, flags, src_if));
+
 	return (0);
 }
 
-struct nhop_object *
-fib4_lookup_debugnet(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
-    uint32_t flags)
+/*
+ * Function returning prefix match data along with the nexthop data.
+ * Intended to be used by the control plane code.
+ * Supported flags:
+ *  NHR_UNLOCKED: do not lock radix during lookup.
+ * Returns pointer to rtentry and raw nexthop in @rnd. Both rtentry
+ *  and nexthop are safe to use within current epoch. Note:
+ * Note: rnd_nhop can actually be the nexthop group.
+ */
+struct rtentry *
+fib4_lookup_rt(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
+    uint32_t flags, struct route_nhop_data *rnd)
 {
+	RIB_RLOCK_TRACKER;
 	struct rib_head *rh;
 	struct radix_node *rn;
-	struct nhop_object *nh;
+	struct rtentry *rt;
 
-	KASSERT((fibnum < rt_numfibs), ("fib4_lookup_debugnet: bad fibnum"));
+	KASSERT((fibnum < rt_numfibs), ("fib4_lookup_rt: bad fibnum"));
 	rh = rt_tables_get_rnh(fibnum, AF_INET);
 	if (rh == NULL)
 		return (NULL);
 
 	/* Prepare lookup key */
-	struct sockaddr_in sin4;
-	memset(&sin4, 0, sizeof(sin4));
-	sin4.sin_family = AF_INET;
-	sin4.sin_len = sizeof(struct sockaddr_in);
-	sin4.sin_addr = dst;
+	struct sockaddr_in sin4 = {
+		.sin_family = AF_INET,
+		.sin_len = sizeof(struct sockaddr_in),
+		.sin_addr = dst,
+	};
 
-	nh = NULL;
-	/* unlocked lookup */
+	rt = NULL;
+	if (!(flags & NHR_UNLOCKED))
+		RIB_RLOCK(rh);
 	rn = rh->rnh_matchaddr((void *)&sin4, &rh->head);
 	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
-		nh = nhop_select((RNTORT(rn))->rt_nhop, 0);
+		rt = (struct rtentry *)rn;
+		rnd->rnd_nhop = rt->rt_nhop;
+		rnd->rnd_weight = rt->rt_weight;
+	}
+	if (!(flags & NHR_UNLOCKED))
+		RIB_RUNLOCK(rh);
+
+	return (rt);
+}
+
+struct nhop_object *
+fib4_lookup_debugnet(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
+    uint32_t flags)
+{
+	struct rtentry *rt;
+	struct route_nhop_data rnd;
+
+	rt = fib4_lookup_rt(fibnum, dst, scopeid, NHR_UNLOCKED, &rnd);
+	if (rt != NULL) {
+		struct nhop_object *nh = nhop_select(rnd.rnd_nhop, 0);
 		/* Ensure route & ifp is UP */
-		if (RT_LINK_IS_UP(nh->nh_ifp)) {
-			if (flags & NHR_REF)
-				nhop_ref_object(nh);
+		if (RT_LINK_IS_UP(nh->nh_ifp))
 			return (nh);
-		}
 	}
 
 	return (NULL);

Modified: head/sys/netinet/in_fib.h
==============================================================================
--- head/sys/netinet/in_fib.h	Sun Nov 29 13:27:24 2020	(r368146)
+++ head/sys/netinet/in_fib.h	Sun Nov 29 13:41:49 2020	(r368147)
@@ -45,10 +45,15 @@ struct route_in {
 	struct sockaddr_in ro_dst4;
 };
 
+struct rtentry;
+struct route_nhop_data;
+
 struct nhop_object *fib4_lookup(uint32_t fibnum, struct in_addr dst,
     uint32_t scopeid, uint32_t flags, uint32_t flowid);
 int fib4_check_urpf(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
     uint32_t flags, const struct ifnet *src_if);
+struct rtentry *fib4_lookup_rt(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
+    uint32_t flags, struct route_nhop_data *nrd);
 struct nhop_object *fib4_lookup_debugnet(uint32_t fibnum, struct in_addr dst,
     uint32_t scopeid, uint32_t flags);
 uint32_t fib4_calc_software_hash(struct in_addr src, struct in_addr dst,

Modified: head/sys/netinet6/in6_fib.c
==============================================================================
--- head/sys/netinet6/in6_fib.c	Sun Nov 29 13:27:24 2020	(r368146)
+++ head/sys/netinet6/in6_fib.c	Sun Nov 29 13:41:49 2020	(r368147)
@@ -119,19 +119,16 @@ fib6_lookup(uint32_t fibnum, const struct in6_addr *ds
 	struct rib_head *rh;
 	struct radix_node *rn;
 	struct nhop_object *nh;
-	struct sockaddr_in6 sin6;
 
 	KASSERT((fibnum < rt_numfibs), ("fib6_lookup: bad fibnum"));
 	rh = rt_tables_get_rnh(fibnum, AF_INET6);
 	if (rh == NULL)
 		return (NULL);
 
-	/* TODO: radix changes */
-	//addr = *dst6;
-	/* Prepare lookup key */
-	memset(&sin6, 0, sizeof(sin6));
-	sin6.sin6_len = sizeof(struct sockaddr_in6);
-	sin6.sin6_addr = *dst6;
+	struct sockaddr_in6 sin6 = {
+		.sin6_len = sizeof(struct sockaddr_in6),
+		.sin6_addr = *dst6,
+	};
 
 	/* Assume scopeid is valid and embed it directly */
 	if (IN6_IS_SCOPE_LINKLOCAL(dst6))
@@ -192,86 +189,121 @@ check_urpf(struct nhop_object *nh, uint32_t flags,
 		return (check_urpf_nhop(nh, flags, src_if));
 }
 
-/*
- * Performs reverse path forwarding lookup.
- * If @src_if is non-zero, verifies that at least 1 path goes via
- *   this interface.
- * If @src_if is zero, verifies that route exist.
- * if @flags contains NHR_NOTDEFAULT, do not consider default route.
- *
- * Returns 1 if route matching conditions is found, 0 otherwise.
- */
-int
-fib6_check_urpf(uint32_t fibnum, const struct in6_addr *dst6,
-    uint32_t scopeid, uint32_t flags, const struct ifnet *src_if)
+static struct nhop_object *
+lookup_nhop(uint32_t fibnum, const struct in6_addr *dst6,
+    uint32_t scopeid)
 {
 	RIB_RLOCK_TRACKER;
 	struct rib_head *rh;
 	struct radix_node *rn;
-	struct sockaddr_in6 sin6;
-	int ret;
+	struct nhop_object *nh;
 
 	KASSERT((fibnum < rt_numfibs), ("fib6_check_urpf: bad fibnum"));
 	rh = rt_tables_get_rnh(fibnum, AF_INET6);
 	if (rh == NULL)
-		return (0);
+		return (NULL);
 
-	/* TODO: radix changes */
 	/* Prepare lookup key */
-	memset(&sin6, 0, sizeof(sin6));
-	sin6.sin6_len = sizeof(struct sockaddr_in6);
-	sin6.sin6_addr = *dst6;
+	struct sockaddr_in6 sin6 = {
+		.sin6_len = sizeof(struct sockaddr_in6),
+		.sin6_addr = *dst6,
+	};
 
 	/* Assume scopeid is valid and embed it directly */
 	if (IN6_IS_SCOPE_LINKLOCAL(dst6))
 		sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
 
+	nh = NULL;
 	RIB_RLOCK(rh);
 	rn = rh->rnh_matchaddr((void *)&sin6, &rh->head);
-	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
-		ret = check_urpf(RNTORT(rn)->rt_nhop, flags, src_if);
-		RIB_RUNLOCK(rh);
-		return (ret);
-	}
+	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0))
+		nh = RNTORT(rn)->rt_nhop;
 	RIB_RUNLOCK(rh);
 
+	return (nh);
+}
+
+/*
+ * Performs reverse path forwarding lookup.
+ * If @src_if is non-zero, verifies that at least 1 path goes via
+ *   this interface.
+ * If @src_if is zero, verifies that route exist.
+ * if @flags contains NHR_NOTDEFAULT, do not consider default route.
+ *
+ * Returns 1 if route matching conditions is found, 0 otherwise.
+ */
+int
+fib6_check_urpf(uint32_t fibnum, const struct in6_addr *dst6,
+    uint32_t scopeid, uint32_t flags, const struct ifnet *src_if)
+{
+	struct nhop_object *nh;
+
+	nh = lookup_nhop(fibnum, dst6, scopeid);
+	if (nh != NULL)
+		return (check_urpf(nh, flags, src_if));
 	return (0);
 }
 
-struct nhop_object *
-fib6_lookup_debugnet(uint32_t fibnum, const struct in6_addr *dst6,
-    uint32_t scopeid, uint32_t flags)
+/*
+ * Function returning prefix match data along with the nexthop data.
+ * Intended to be used by the control plane code.
+ * Supported flags:
+ *  NHR_UNLOCKED: do not lock radix during lookup.
+ * Returns pointer to rtentry and raw nexthop in @rnd. Both rtentry
+ *  and nexthop are safe to use within current epoch. Note:
+ * Note: rnd_nhop can actually be the nexthop group.
+ */
+struct rtentry *
+fib6_lookup_rt(uint32_t fibnum, const struct in6_addr *dst6,
+    uint32_t scopeid, uint32_t flags, struct route_nhop_data *rnd)
 {
+	RIB_RLOCK_TRACKER;
 	struct rib_head *rh;
 	struct radix_node *rn;
-	struct nhop_object *nh;
-	struct sockaddr_in6 sin6;
+	struct rtentry *rt;
 
 	KASSERT((fibnum < rt_numfibs), ("fib6_lookup: bad fibnum"));
 	rh = rt_tables_get_rnh(fibnum, AF_INET6);
 	if (rh == NULL)
 		return (NULL);
 
-	/* TODO: radix changes */
-	//addr = *dst6;
-	/* Prepare lookup key */
-	memset(&sin6, 0, sizeof(sin6));
-	sin6.sin6_len = sizeof(struct sockaddr_in6);
-	sin6.sin6_addr = *dst6;
+	struct sockaddr_in6 sin6 = {
+		.sin6_len = sizeof(struct sockaddr_in6),
+		.sin6_addr = *dst6,
+	};
 
 	/* Assume scopeid is valid and embed it directly */
 	if (IN6_IS_SCOPE_LINKLOCAL(dst6))
 		sin6.sin6_addr.s6_addr16[1] = htons(scopeid & 0xffff);
 
+	rt = NULL;
+	if (!(flags & NHR_UNLOCKED))
+		RIB_RLOCK(rh);
 	rn = rh->rnh_matchaddr((void *)&sin6, &rh->head);
 	if (rn != NULL && ((rn->rn_flags & RNF_ROOT) == 0)) {
-		nh = nhop_select((RNTORT(rn))->rt_nhop, 0);
+		rt = (struct rtentry *)rn;
+		rnd->rnd_nhop = rt->rt_nhop;
+		rnd->rnd_weight = rt->rt_weight;
+	}
+	if (!(flags & NHR_UNLOCKED))
+		RIB_RUNLOCK(rh);
+
+	return (rt);
+}
+
+struct nhop_object *
+fib6_lookup_debugnet(uint32_t fibnum, const struct in6_addr *dst6,
+    uint32_t scopeid, uint32_t flags)
+{
+	struct rtentry *rt;
+	struct route_nhop_data rnd;
+
+	rt = fib6_lookup_rt(fibnum, dst6, scopeid, NHR_UNLOCKED, &rnd);
+	if (rt != NULL) {
+		struct nhop_object *nh = nhop_select(rnd.rnd_nhop, 0);
 		/* Ensure route & ifp is UP */
-		if (RT_LINK_IS_UP(nh->nh_ifp)) {
-			if (flags & NHR_REF)
-				nhop_ref_object(nh);
+		if (RT_LINK_IS_UP(nh->nh_ifp))
 			return (nh);
-		}
 	}
 
 	return (NULL);

Modified: head/sys/netinet6/in6_fib.h
==============================================================================
--- head/sys/netinet6/in6_fib.h	Sun Nov 29 13:27:24 2020	(r368146)
+++ head/sys/netinet6/in6_fib.h	Sun Nov 29 13:41:49 2020	(r368147)
@@ -32,11 +32,16 @@
 #ifndef _NETINET6_IN6_FIB_H_
 #define	_NETINET6_IN6_FIB_H_
 
+struct rtentry;
+struct route_nhop_data;
+
 struct nhop_object *fib6_lookup(uint32_t fibnum,
     const struct in6_addr *dst6, uint32_t scopeid, uint32_t flags,
     uint32_t flowid);
 int fib6_check_urpf(uint32_t fibnum, const struct in6_addr *dst6,
     uint32_t scopeid, uint32_t flags, const struct ifnet *src_if);
+struct rtentry *fib6_lookup_rt(uint32_t fibnum, const struct in6_addr *dst6,
+    uint32_t scopeid, uint32_t flags, struct route_nhop_data *rnd);
 struct nhop_object *fib6_lookup_debugnet(uint32_t fibnum,
     const struct in6_addr *dst6, uint32_t scopeid, uint32_t flags);
 uint32_t fib6_calc_software_hash(const struct in6_addr *src,


More information about the svn-src-all mailing list