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,
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to