Refactor rib iterator functions.

* Make rib_walk() order of arguments consistent with the rest of RIB api
* Add rib_walk_ext() allowing to exec callback before/after iteration.
* Rename rt_foreach_fib_walk_del -> rib_foreach_table_walk_del
* Rename rt_forach_fib_walk -> rib_foreach_table_walk
* Move rib_foreach_table_walk{_del} to route/route_helpers.c
* Slightly refactor rib_foreach_table_walk{_del} to make the implementation
 consistent and prepare for upcoming iterator optimizations.

Differential Revision:	https://reviews.freebsd.org/D27219
This commit is contained in:
Alexander V. Chernikov 2020-11-22 20:21:10 +00:00
parent 5e38d9e483
commit 7511a63825
7 changed files with 103 additions and 93 deletions

View File

@ -457,81 +457,6 @@ rib_free_info(struct rt_addrinfo *info)
if_rele(info->rti_ifp);
}
/*
* Iterates over all existing fibs in system calling
* @setwa_f function prior to traversing each fib.
* Calls @wa_f function for each element in current fib.
* If af is not AF_UNSPEC, iterates over fibs in particular
* address family.
*/
void
rt_foreach_fib_walk(int af, rt_setwarg_t *setwa_f, rt_walktree_f_t *wa_f,
void *arg)
{
struct rib_head *rnh;
uint32_t fibnum;
int i;
for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
/* Do we want some specific family? */
if (af != AF_UNSPEC) {
rnh = rt_tables_get_rnh(fibnum, af);
if (rnh == NULL)
continue;
if (setwa_f != NULL)
setwa_f(rnh, fibnum, af, arg);
RIB_WLOCK(rnh);
rnh->rnh_walktree(&rnh->head, (walktree_f_t *)wa_f,arg);
RIB_WUNLOCK(rnh);
continue;
}
for (i = 1; i <= AF_MAX; i++) {
rnh = rt_tables_get_rnh(fibnum, i);
if (rnh == NULL)
continue;
if (setwa_f != NULL)
setwa_f(rnh, fibnum, i, arg);
RIB_WLOCK(rnh);
rnh->rnh_walktree(&rnh->head, (walktree_f_t *)wa_f,arg);
RIB_WUNLOCK(rnh);
}
}
}
/*
* Iterates over all existing fibs in system and deletes each element
* for which @filter_f function returns non-zero value.
* If @family is not AF_UNSPEC, iterates over fibs in particular
* address family.
*/
void
rt_foreach_fib_walk_del(int family, rt_filter_f_t *filter_f, void *arg)
{
u_int fibnum;
int i, start, end;
for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
/* Do we want some specific family? */
if (family != AF_UNSPEC) {
start = family;
end = family;
} else {
start = 1;
end = AF_MAX;
}
for (i = start; i <= end; i++) {
if (rt_tables_get_rnh(fibnum, i) == NULL)
continue;
rib_walk_del(fibnum, i, filter_f, arg, 0);
}
}
}
/*
* Delete Routes for a Network Interface
*
@ -577,14 +502,14 @@ rt_flushifroutes_af(struct ifnet *ifp, int af)
KASSERT((af >= 1 && af <= AF_MAX), ("%s: af %d not >= 1 and <= %d",
__func__, af, AF_MAX));
rt_foreach_fib_walk_del(af, rt_ifdelroute, ifp);
rib_foreach_table_walk_del(af, rt_ifdelroute, ifp);
}
void
rt_flushifroutes(struct ifnet *ifp)
{
rt_foreach_fib_walk_del(AF_UNSPEC, rt_ifdelroute, ifp);
rib_foreach_table_walk_del(AF_UNSPEC, rt_ifdelroute, ifp);
}
/*

View File

@ -342,7 +342,7 @@ struct rt_msghdr {
struct rtentry;
struct nhop_object;
typedef int rt_filter_f_t(const struct rtentry *, const struct nhop_object *,
typedef int rib_filter_f_t(const struct rtentry *, const struct nhop_object *,
void *);
struct rt_addrinfo {
@ -351,7 +351,7 @@ struct rt_addrinfo {
struct sockaddr *rti_info[RTAX_MAX]; /* Sockaddr data */
struct ifaddr *rti_ifa; /* value of rt_ifa addr */
struct ifnet *rti_ifp; /* route interface */
rt_filter_f_t *rti_filter; /* filter function */
rib_filter_f_t *rti_filter; /* filter function */
void *rti_filterdata; /* filter paramenters */
u_long rti_mflags; /* metrics RTV_ flags */
u_long rti_spare; /* Will be used for fib */

View File

@ -1143,7 +1143,7 @@ rt_checkdelroute(struct radix_node *rn, void *arg)
* @report: true if rtsock notification is needed.
*/
void
rib_walk_del(u_int fibnum, int family, rt_filter_f_t *filter_f, void *arg, bool report)
rib_walk_del(u_int fibnum, int family, rib_filter_f_t *filter_f, void *arg, bool report)
{
struct rib_head *rnh;
struct rt_delinfo di;

View File

@ -61,14 +61,24 @@ int rib_add_redirect(u_int fibnum, struct sockaddr *dst,
struct sockaddr *gateway, struct sockaddr *author, struct ifnet *ifp,
int flags, int expire_sec);
typedef int rt_walktree_f_t(struct rtentry *, void *);
void rib_walk(int af, u_int fibnum, rt_walktree_f_t *wa_f, void *arg);
void rib_walk_del(u_int fibnum, int family, rt_filter_f_t *filter_f,
enum rib_walk_hook {
RIB_WALK_HOOK_PRE, /* Hook is called before iteration */
RIB_WALK_HOOK_POST, /* Hook is called after iteration */
};
typedef int rib_walktree_f_t(struct rtentry *, void *);
typedef void rib_walk_hook_f_t(struct rib_head *rnh, enum rib_walk_hook stage,
void *arg);
void rib_walk(uint32_t fibnum, int af, bool wlock, rib_walktree_f_t *wa_f,
void *arg);
void rib_walk_ext(uint32_t fibnum, int af, bool wlock, rib_walktree_f_t *wa_f,
rib_walk_hook_f_t *hook_f, void *arg);
void rib_walk_del(u_int fibnum, int family, rib_filter_f_t *filter_f,
void *arg, bool report);
typedef void rt_setwarg_t(struct rib_head *, uint32_t, int, void *);
void rt_foreach_fib_walk(int af, rt_setwarg_t *, rt_walktree_f_t *, void *);
void rt_foreach_fib_walk_del(int af, rt_filter_f_t *filter_f, void *arg);
void rib_foreach_table_walk(int family, bool wlock, rib_walktree_f_t *wa_f,
rib_walk_hook_f_t *hook_f, void *arg);
void rib_foreach_table_walk_del(int family, rib_filter_f_t *filter_f, void *arg);
struct route_nhop_data;
const struct rtentry *rib_lookup_prefix(uint32_t fibnum, int family,

View File

@ -71,22 +71,97 @@ __FBSDID("$FreeBSD$");
* Calls @wa_f with @arg for each entry in the table specified by
* @af and @fibnum.
*
* Table is traversed under read lock.
* @ss_t callback is called before and after the tree traversal
* while holding table lock.
*
* Table is traversed under read lock unless @wlock is set.
*/
void
rib_walk(int af, u_int fibnum, rt_walktree_f_t *wa_f, void *arg)
rib_walk_ext(uint32_t fibnum, int family, bool wlock, rib_walktree_f_t *wa_f,
rib_walk_hook_f_t *hook_f, void *arg)
{
RIB_RLOCK_TRACKER;
struct rib_head *rnh;
if ((rnh = rt_tables_get_rnh(fibnum, af)) == NULL)
if ((rnh = rt_tables_get_rnh(fibnum, family)) == NULL)
return;
RIB_RLOCK(rnh);
if (wlock)
RIB_WLOCK(rnh);
else
RIB_RLOCK(rnh);
if (hook_f != NULL)
hook_f(rnh, RIB_WALK_HOOK_PRE, arg);
rnh->rnh_walktree(&rnh->head, (walktree_f_t *)wa_f, arg);
RIB_RUNLOCK(rnh);
if (hook_f != NULL)
hook_f(rnh, RIB_WALK_HOOK_POST, arg);
if (wlock)
RIB_WUNLOCK(rnh);
else
RIB_RUNLOCK(rnh);
}
/*
* Calls @wa_f with @arg for each entry in the table specified by
* @af and @fibnum.
*
* Table is traversed under read lock unless @wlock is set.
*/
void
rib_walk(uint32_t fibnum, int family, bool wlock, rib_walktree_f_t *wa_f,
void *arg)
{
rib_walk_ext(fibnum, family, wlock, wa_f, NULL, arg);
}
/*
* Iterates over all existing fibs in system calling
* @hook_f function before/after traversing each fib.
* Calls @wa_f function for each element in current fib.
* If af is not AF_UNSPEC, iterates over fibs in particular
* address family.
*/
void
rib_foreach_table_walk(int family, bool wlock, rib_walktree_f_t *wa_f,
rib_walk_hook_f_t *hook_f, void *arg)
{
for (uint32_t fibnum = 0; fibnum < rt_numfibs; fibnum++) {
/* Do we want some specific family? */
if (family != AF_UNSPEC) {
rib_walk_ext(fibnum, family, wlock, wa_f, hook_f, arg);
continue;
}
for (int i = 1; i <= AF_MAX; i++)
rib_walk_ext(fibnum, i, wlock, wa_f, hook_f, arg);
}
}
/*
* Iterates over all existing fibs in system and deletes each element
* for which @filter_f function returns non-zero value.
* If @family is not AF_UNSPEC, iterates over fibs in particular
* address family.
*/
void
rib_foreach_table_walk_del(int family, rib_filter_f_t *filter_f, void *arg)
{
for (uint32_t fibnum = 0; fibnum < rt_numfibs; fibnum++) {
/* Do we want some specific family? */
if (family != AF_UNSPEC) {
rib_walk_del(fibnum, family, filter_f, arg, 0);
continue;
}
for (int i = 1; i <= AF_MAX; i++)
rib_walk_del(fibnum, i, filter_f, arg, 0);
}
}
/*
* Wrapper for the control plane functions for performing af-agnostic
* lookups.

View File

@ -178,6 +178,6 @@ in_ifadown(struct ifaddr *ifa, int delete)
arg.ifa = ifa;
arg.del = delete;
rt_foreach_fib_walk_del(AF_INET, in_ifadownkill, &arg);
rib_foreach_table_walk_del(AF_INET, in_ifadownkill, &arg);
ifa->ifa_flags &= ~IFA_ROUTE; /* XXXlocking? */
}

View File

@ -2460,7 +2460,7 @@ rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
return;
/* XXX Do we really need to walk any but the default FIB? */
rt_foreach_fib_walk_del(AF_INET6, rt6_deleteroute, (void *)gateway);
rib_foreach_table_walk_del(AF_INET6, rt6_deleteroute, (void *)gateway);
}
int