Add rib_lookup() sockaddr lookup wrapper and make ifa_ifwithroute use it.

Create rib_lookup() wrapper around per-af dataplane lookup functions.
This will help in the cases of having control plane af-agnostic code.

Switch ifa_ifwithroute() to use this function instead of rtalloc1().

Reviewed by:	ae
Differential Revision:	https://reviews.freebsd.org/D24731
This commit is contained in:
Alexander V. Chernikov 2020-05-07 08:11:36 +00:00
parent a1da7a46f6
commit 682b902daf
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=360773
3 changed files with 60 additions and 25 deletions

View File

@ -683,7 +683,6 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst, struct sockaddr *gateway,
u_int fibnum)
{
struct ifaddr *ifa;
int not_found = 0;
NET_EPOCH_ASSERT();
if ((flags & RTF_GATEWAY) == 0) {
@ -710,34 +709,17 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst, struct sockaddr *gateway,
if (ifa == NULL)
ifa = ifa_ifwithnet(gateway, 0, fibnum);
if (ifa == NULL) {
struct rtentry *rt;
struct nhop_object *nh;
nh = rib_lookup(fibnum, gateway, NHR_NONE, 0);
rt = rtalloc1_fib(gateway, 0, flags, fibnum);
if (rt == NULL)
goto out;
/*
* dismiss a gateway that is reachable only
* through the default router
*/
switch (gateway->sa_family) {
case AF_INET:
if (satosin(rt_key(rt))->sin_addr.s_addr == INADDR_ANY)
not_found = 1;
break;
case AF_INET6:
if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(rt_key(rt))->sin6_addr))
not_found = 1;
break;
default:
break;
}
if (!not_found && rt->rt_nhop->nh_ifa != NULL) {
ifa = rt->rt_nhop->nh_ifa;
}
RT_REMREF(rt);
RT_UNLOCK(rt);
if (not_found || ifa == NULL)
goto out;
if ((nh == NULL) || (nh->nh_flags & NHF_DEFAULT))
return (NULL);
ifa = nh->nh_ifa;
}
if (ifa->ifa_addr->sa_family != dst->sa_family) {
struct ifaddr *oifa = ifa;
@ -745,7 +727,7 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst, struct sockaddr *gateway,
if (ifa == NULL)
ifa = oifa;
}
out:
return (ifa);
}

View File

@ -436,6 +436,8 @@ int rib_add_redirect(u_int fibnum, struct sockaddr *dst,
/* New API */
void rib_walk(int af, u_int fibnum, rt_walktree_f_t *wa_f, void *arg);
struct nhop_object *rib_lookup(uint32_t fibnum, const struct sockaddr *dst,
uint32_t flags, uint32_t flowid);
#endif
#endif

View File

@ -55,6 +55,12 @@ __FBSDID("$FreeBSD$");
#include <net/route/nhop.h>
#include <net/route/nhop_var.h>
#include <net/route/shared.h>
#ifdef INET
#include <netinet/in_fib.h>
#endif
#ifdef INET6
#include <netinet6/in6_fib.h>
#endif
#include <net/vnet.h>
/*
@ -81,3 +87,48 @@ rib_walk(int af, u_int fibnum, rt_walktree_f_t *wa_f, void *arg)
RIB_RUNLOCK(rnh);
}
/*
* Wrapper for the control plane functions for performing af-agnostic
* lookups.
* @fibnum: fib to perform the lookup.
* @dst: sockaddr with family and addr filled in. IPv6 addresses needs to be in
* deembedded from.
* @flags: fib(9) flags.
* @flowid: flow id for path selection in multipath use case.
*
* Returns nhop_object or NULL.
*
* Requires NET_EPOCH.
*
*/
struct nhop_object *
rib_lookup(uint32_t fibnum, const struct sockaddr *dst, uint32_t flags,
uint32_t flowid)
{
struct nhop_object *nh;
nh = NULL;
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
{
const struct sockaddr_in *a = (const struct sockaddr_in *)dst;
nh = fib4_lookup(fibnum, a->sin_addr, 0, flags, flowid);
break;
}
#endif
#ifdef INET6
case AF_INET6:
{
const struct sockaddr_in6 *a = (const struct sockaddr_in6*)dst;
nh = fib6_lookup(fibnum, &a->sin6_addr, a->sin6_scope_id,
flags, flowid);
break;
}
#endif
}
return (nh);
}