Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Dec 2020 22:23:57 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r368317 - head/sys/net/route
Message-ID:  <202012032223.0B3MNvcc009440@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Thu Dec  3 22:23:57 2020
New Revision: 368317
URL: https://svnweb.freebsd.org/changeset/base/368317

Log:
  Add IPv4/IPv6 rtentry prefix accessors.
  
  Multiple consumers like ipfw, netflow or new route lookup algorithms
   need to get the prefix data out of struct rtentry.
  Instead of providing direct access to the rtentry, create IPv4/IPv6
   accessors to abstract struct rtentry internals and avoid including
   internal routing headers for external consumers.
  
  While here, move struct route_nhop_data to the public header, so external
   customers can actually use lookup functions returning rt&nhop data.
  
  Differential Revision:	https://reviews.freebsd.org/D27416

Modified:
  head/sys/net/route/route_ctl.c
  head/sys/net/route/route_ctl.h
  head/sys/net/route/route_var.h

Modified: head/sys/net/route/route_ctl.c
==============================================================================
--- head/sys/net/route/route_ctl.c	Thu Dec  3 22:06:08 2020	(r368316)
+++ head/sys/net/route/route_ctl.c	Thu Dec  3 22:23:57 2020	(r368317)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include <net/route/nhop.h>
 #include <net/route/nhop_var.h>
 #include <netinet/in.h>
+#include <netinet6/scope6_var.h>
 
 #include <vm/uma.h>
 
@@ -235,6 +236,132 @@ get_info_weight(const struct rt_addrinfo *info, uint32
 
 	return (weight);
 }
+
+bool
+rt_is_host(const struct rtentry *rt)
+{
+
+	return (rt->rte_flags & RTF_HOST);
+}
+
+/*
+ * Returns pointer to nexthop or nexthop group
+ * associated with @rt
+ */
+struct nhop_object *
+rt_get_raw_nhop(const struct rtentry *rt)
+{
+
+	return (rt->rt_nhop);
+}
+
+#ifdef INET
+/*
+ * Stores IPv4 address and prefix length of @rt inside
+ *  @paddr and @plen.
+ * @pscopeid is currently always set to 0.
+ */
+void
+rt_get_inet_prefix_plen(const struct rtentry *rt, struct in_addr *paddr,
+    int *plen, uint32_t *pscopeid)
+{
+	const struct sockaddr_in *dst;
+
+	dst = (const struct sockaddr_in *)rt_key_const(rt);
+	KASSERT((dst->sin_family == AF_INET),
+	    ("rt family is %d, not inet", dst->sin_family));
+	*paddr = dst->sin_addr;
+	dst = (const struct sockaddr_in *)rt_mask_const(rt);
+	if (dst == NULL)
+		*plen = 32;
+	else
+		*plen = bitcount32(dst->sin_addr.s_addr);
+	*pscopeid = 0;
+}
+
+/*
+ * Stores IPv4 address and prefix mask of @rt inside
+ *  @paddr and @pmask. Sets mask to INADDR_ANY for host routes.
+ * @pscopeid is currently always set to 0.
+ */
+void
+rt_get_inet_prefix_pmask(const struct rtentry *rt, struct in_addr *paddr,
+    struct in_addr *pmask, uint32_t *pscopeid)
+{
+	const struct sockaddr_in *dst;
+
+	dst = (const struct sockaddr_in *)rt_key_const(rt);
+	KASSERT((dst->sin_family == AF_INET),
+	    ("rt family is %d, not inet", dst->sin_family));
+	*paddr = dst->sin_addr;
+	dst = (const struct sockaddr_in *)rt_mask_const(rt);
+	if (dst == NULL)
+		pmask->s_addr = INADDR_BROADCAST;
+	else
+		*pmask = dst->sin_addr;
+	*pscopeid = 0;
+}
+#endif
+
+#ifdef INET6
+static int
+inet6_get_plen(const struct in6_addr *addr)
+{
+
+	return (bitcount32(addr->s6_addr32[0]) + bitcount32(addr->s6_addr32[1]) +
+	    bitcount32(addr->s6_addr32[2]) + bitcount32(addr->s6_addr32[3]));
+}
+
+/*
+ * Stores IPv6 address and prefix length of @rt inside
+ *  @paddr and @plen. Addresses are returned in de-embedded form.
+ * Scopeid is set to 0 for non-LL addresses.
+ */
+void
+rt_get_inet6_prefix_plen(const struct rtentry *rt, struct in6_addr *paddr,
+    int *plen, uint32_t *pscopeid)
+{
+	const struct sockaddr_in6 *dst;
+
+	dst = (const struct sockaddr_in6 *)rt_key_const(rt);
+	KASSERT((dst->sin6_family == AF_INET6),
+	    ("rt family is %d, not inet6", dst->sin6_family));
+	if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr))
+		in6_splitscope(&dst->sin6_addr, paddr, pscopeid);
+	else
+		*paddr = dst->sin6_addr;
+	dst = (const struct sockaddr_in6 *)rt_mask_const(rt);
+	if (dst == NULL)
+		*plen = 128;
+	else
+		*plen = inet6_get_plen(&dst->sin6_addr);
+}
+
+/*
+ * Stores IPv6 address and prefix mask of @rt inside
+ *  @paddr and @pmask. Addresses are returned in de-embedded form.
+ * Scopeid is set to 0 for non-LL addresses.
+ */
+void
+rt_get_inet6_prefix_pmask(const struct rtentry *rt, struct in6_addr *paddr,
+    struct in6_addr *pmask, uint32_t *pscopeid)
+{
+	const struct sockaddr_in6 *dst;
+
+	dst = (const struct sockaddr_in6 *)rt_key_const(rt);
+	KASSERT((dst->sin6_family == AF_INET6),
+	    ("rt family is %d, not inet", dst->sin6_family));
+	if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr))
+		in6_splitscope(&dst->sin6_addr, paddr, pscopeid);
+	else
+		*paddr = dst->sin6_addr;
+	dst = (const struct sockaddr_in6 *)rt_mask_const(rt);
+	if (dst == NULL)
+		memset(pmask, 0xFF, sizeof(struct in6_addr));
+	else
+		*pmask = dst->sin6_addr;
+}
+#endif
 
 static void
 rt_set_expire_info(struct rtentry *rt, const struct rt_addrinfo *info)

Modified: head/sys/net/route/route_ctl.h
==============================================================================
--- head/sys/net/route/route_ctl.h	Thu Dec  3 22:06:08 2020	(r368316)
+++ head/sys/net/route/route_ctl.h	Thu Dec  3 22:23:57 2020	(r368317)
@@ -82,18 +82,44 @@ void rib_foreach_table_walk(int family, bool wlock, ri
     rib_walk_hook_f_t *hook_f, void *arg);
 void rib_foreach_table_walk_del(int family, rib_filter_f_t *filter_f, void *arg);
 
-struct route_nhop_data;
+struct nhop_object;
+struct nhgrp_object;
+struct route_nhop_data {
+	union {
+		struct nhop_object *rnd_nhop;
+		struct nhgrp_object *rnd_nhgrp;
+	};
+	uint32_t rnd_weight;
+};
+
 const struct rtentry *rib_lookup_prefix(uint32_t fibnum, int family,
     const struct sockaddr *dst, const struct sockaddr *netmask,
     struct route_nhop_data *rnd);
 const struct rtentry *rib_lookup_lpm(uint32_t fibnum, int family,
     const struct sockaddr *dst, struct route_nhop_data *rnd);
 
+/* rtentry accessors */
+bool rt_is_host(const struct rtentry *rt);
+struct nhop_object *rt_get_raw_nhop(const struct rtentry *rt);
+#ifdef INET
+struct in_addr;
+void rt_get_inet_prefix_plen(const struct rtentry *rt, struct in_addr *paddr,
+    int *plen, uint32_t *pscopeid);
+void rt_get_inet_prefix_pmask(const struct rtentry *rt, struct in_addr *paddr,
+    struct in_addr *pmask, uint32_t *pscopeid);
+#endif
+#ifdef INET6
+struct in6_addr;
+void rt_get_inet6_prefix_plen(const struct rtentry *rt, struct in6_addr *paddr,
+    int *plen, uint32_t *pscopeid);
+void rt_get_inet6_prefix_pmask(const struct rtentry *rt, struct in6_addr *paddr,
+    struct in6_addr *pmask, uint32_t *pscopeid);
+#endif
+
 /* Nexthops */
 uint32_t nhops_get_count(struct rib_head *rh);
 
 /* Multipath */
-struct nhgrp_object;
 struct weightened_nhop;
 
 struct weightened_nhop *nhgrp_get_nhops(struct nhgrp_object *nhg,

Modified: head/sys/net/route/route_var.h
==============================================================================
--- head/sys/net/route/route_var.h	Thu Dec  3 22:06:08 2020	(r368316)
+++ head/sys/net/route/route_var.h	Thu Dec  3 22:23:57 2020	(r368317)
@@ -205,14 +205,7 @@ void tmproutes_init(struct rib_head *rh);
 void tmproutes_destroy(struct rib_head *rh);
 
 /* route_ctl.c */
-struct route_nhop_data {
-	union {
-		struct nhop_object *rnd_nhop;
-		struct nhgrp_object *rnd_nhgrp;
-	};
-	uint32_t rnd_weight;
-};
-
+struct route_nhop_data;
 int change_route_nhop(struct rib_head *rnh, struct rtentry *rt,
     struct rt_addrinfo *info, struct route_nhop_data *rnd,
     struct rib_cmd_info *rc);



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