Index: head/sys/net/route.h =================================================================== --- head/sys/net/route.h +++ head/sys/net/route.h @@ -342,7 +342,7 @@ 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 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 */ Index: head/sys/net/route.c =================================================================== --- head/sys/net/route.c +++ head/sys/net/route.c @@ -458,81 +458,6 @@ } /* - * 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 * * Called for each routing entry via the rnh->rnh_walktree() call above @@ -577,14 +502,14 @@ 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); } /* Index: head/sys/net/route/route_ctl.h =================================================================== --- head/sys/net/route/route_ctl.h +++ head/sys/net/route/route_ctl.h @@ -61,14 +61,24 @@ 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, Index: head/sys/net/route/route_ctl.c =================================================================== --- head/sys/net/route/route_ctl.c +++ head/sys/net/route/route_ctl.c @@ -1143,7 +1143,7 @@ * @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; Index: head/sys/net/route/route_helpers.c =================================================================== --- head/sys/net/route/route_helpers.c +++ head/sys/net/route/route_helpers.c @@ -71,21 +71,96 @@ * 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 Index: head/sys/netinet/in_rmx.c =================================================================== --- head/sys/netinet/in_rmx.c +++ head/sys/netinet/in_rmx.c @@ -178,6 +178,6 @@ 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? */ } Index: head/sys/netinet6/nd6_rtr.c =================================================================== --- head/sys/netinet6/nd6_rtr.c +++ head/sys/netinet6/nd6_rtr.c @@ -2460,7 +2460,7 @@ 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