aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/in_fib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/in_fib.c')
-rw-r--r--sys/netinet/in_fib.c122
1 files changed, 79 insertions, 43 deletions
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);