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
This commit is contained in:
parent
98d5c4e5c8
commit
b712e3e343
@ -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.
|
||||
|
@ -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,6 +180,35 @@ check_urpf(struct nhop_object *nh, uint32_t flags,
|
||||
return (check_urpf_nhop(nh, flags, 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;
|
||||
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 (NULL);
|
||||
|
||||
/* Prepare lookup key */
|
||||
struct sockaddr_in sin4;
|
||||
memset(&sin4, 0, sizeof(sin4));
|
||||
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))
|
||||
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
|
||||
@ -193,66 +221,74 @@ check_urpf(struct nhop_object *nh, uint32_t flags,
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
int ret;
|
||||
struct rtentry *rt;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_check_urpf: bad fibnum"));
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_rt: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET);
|
||||
if (rh == NULL)
|
||||
return (0);
|
||||
return (NULL);
|
||||
|
||||
/* Prepare lookup key */
|
||||
struct sockaddr_in sin4;
|
||||
memset(&sin4, 0, sizeof(sin4));
|
||||
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,
|
||||
};
|
||||
|
||||
RIB_RLOCK(rh);
|
||||
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)) {
|
||||
ret = check_urpf(RNTORT(rn)->rt_nhop, flags, src_if);
|
||||
RIB_RUNLOCK(rh);
|
||||
return (ret);
|
||||
rt = (struct rtentry *)rn;
|
||||
rnd->rnd_nhop = rt->rt_nhop;
|
||||
rnd->rnd_weight = rt->rt_weight;
|
||||
}
|
||||
RIB_RUNLOCK(rh);
|
||||
if (!(flags & NHR_UNLOCKED))
|
||||
RIB_RUNLOCK(rh);
|
||||
|
||||
return (0);
|
||||
return (rt);
|
||||
}
|
||||
|
||||
struct nhop_object *
|
||||
fib4_lookup_debugnet(uint32_t fibnum, struct in_addr dst, uint32_t scopeid,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct rib_head *rh;
|
||||
struct radix_node *rn;
|
||||
struct nhop_object *nh;
|
||||
struct rtentry *rt;
|
||||
struct route_nhop_data rnd;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib4_lookup_debugnet: 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 */
|
||||
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 = 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);
|
||||
|
@ -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,
|
||||
|
@ -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,6 +189,40 @@ check_urpf(struct nhop_object *nh, uint32_t flags,
|
||||
return (check_urpf_nhop(nh, flags, 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 nhop_object *nh;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib6_check_urpf: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET6);
|
||||
if (rh == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* Prepare lookup key */
|
||||
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))
|
||||
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
|
||||
@ -205,73 +236,74 @@ int
|
||||
fib6_check_urpf(uint32_t fibnum, const struct in6_addr *dst6,
|
||||
uint32_t scopeid, uint32_t flags, const struct ifnet *src_if)
|
||||
{
|
||||
RIB_RLOCK_TRACKER;
|
||||
struct rib_head *rh;
|
||||
struct radix_node *rn;
|
||||
struct sockaddr_in6 sin6;
|
||||
int ret;
|
||||
|
||||
KASSERT((fibnum < rt_numfibs), ("fib6_check_urpf: bad fibnum"));
|
||||
rh = rt_tables_get_rnh(fibnum, AF_INET6);
|
||||
if (rh == NULL)
|
||||
return (0);
|
||||
|
||||
/* TODO: radix changes */
|
||||
/* Prepare lookup key */
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.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);
|
||||
|
||||
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);
|
||||
}
|
||||
RIB_RUNLOCK(rh);
|
||||
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);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user