aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/route.h1
-rw-r--r--sys/netinet/in_fib.c122
-rw-r--r--sys/netinet/in_fib.h5
-rw-r--r--sys/netinet6/in6_fib.c126
-rw-r--r--sys/netinet6/in6_fib.h5
5 files changed, 169 insertions, 90 deletions
diff --git a/sys/net/route.h b/sys/net/route.h
index c1f9bf560517..5a623d3a35f0 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -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.
diff --git a/sys/netinet/in_fib.c b/sys/netinet/in_fib.c
index 031277add777..ee54d524c3e2 100644
--- a/sys/netinet/in_fib.c
+++ b/sys/netinet/in_fib.c
@@ -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, uint32_t scopeid,
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, uint32_t scopeid,
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;
-
- nh = NULL;
- /* unlocked lookup */
+ struct sockaddr_in sin4 = {
+ .sin_family = AF_INET,
+ .sin_len = sizeof(struct sockaddr_in),
+ .sin_addr = dst,
+ };
+
+ 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);
diff --git a/sys/netinet/in_fib.h b/sys/netinet/in_fib.h
index 0d93086bc116..7b31e09e82fc 100644
--- a/sys/netinet/in_fib.h
+++ b/sys/netinet/in_fib.h
@@ -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,
diff --git a/sys/netinet6/in6_fib.c b/sys/netinet6/in6_fib.c
index a3fd20f8ba25..8aaf23ad374b 100644
--- a/sys/netinet6/in6_fib.c
+++ b/sys/netinet6/in6_fib.c
@@ -119,19 +119,16 @@ fib6_lookup(uint32_t fibnum, const struct in6_addr *dst6,
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);
diff --git a/sys/netinet6/in6_fib.h b/sys/netinet6/in6_fib.h
index 78edb5e5b776..2b260811ca36 100644
--- a/sys/netinet6/in6_fib.h
+++ b/sys/netinet6/in6_fib.h
@@ -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,