diff --git a/sys/net/route/route_ctl.h b/sys/net/route/route_ctl.h --- a/sys/net/route/route_ctl.h +++ b/sys/net/route/route_ctl.h @@ -62,6 +62,10 @@ struct sockaddr *gateway, struct sockaddr *author, struct ifnet *ifp, int flags, int expire_sec); +/* common flags for the functions below */ +#define RIB_FLAG_WLOCK 0x01 /* Need exclusive rnh lock */ +#define RIB_FLAG_LOCKED 0x02 /* Do not explicitly acquire rnh lock */ + enum rib_walk_hook { RIB_WALK_HOOK_PRE, /* Hook is called before iteration */ RIB_WALK_HOOK_POST, /* Hook is called after iteration */ @@ -77,6 +81,8 @@ rib_walktree_f_t *wa_f, rib_walk_hook_f_t *hook_f, void *arg); void rib_walk_ext_locked(struct rib_head *rnh, rib_walktree_f_t *wa_f, rib_walk_hook_f_t *hook_f, void *arg); +void rib_walk_from(uint32_t fibnum, int family, uint32_t flags, struct sockaddr *prefix, + struct sockaddr *mask, rib_walktree_f_t *wa_f, void *arg); void rib_walk_del(u_int fibnum, int family, rib_filter_f_t *filter_f, void *arg, bool report); diff --git a/sys/net/route/route_helpers.c b/sys/net/route/route_helpers.c --- a/sys/net/route/route_helpers.c +++ b/sys/net/route/route_helpers.c @@ -128,6 +128,38 @@ rib_walk_ext(fibnum, family, wlock, wa_f, NULL, arg); } +/* + * Calls @wa_f with @arg for each entry in the table matching @prefix/@mask. + * + * The following flags are supported: + * RIB_FLAG_WLOCK: acquire exclusive lock + * RIB_FLAG_LOCKED: Assumes the table is already locked & skip locking + * + * By default, table is traversed under read lock. + */ +void +rib_walk_from(uint32_t fibnum, int family, uint32_t flags, struct sockaddr *prefix, + struct sockaddr *mask, rib_walktree_f_t *wa_f, void *arg) +{ + RIB_RLOCK_TRACKER; + struct rib_head *rnh = rt_tables_get_rnh(fibnum, family); + + if (rnh == NULL) + return; + + if (flags & RIB_FLAG_WLOCK) + RIB_WLOCK(rnh); + else if (!(flags & RIB_FLAG_LOCKED)) + RIB_RLOCK(rnh); + + rnh->rnh_walktree_from(&rnh->head, prefix, mask, (walktree_f_t *)wa_f, arg); + + if (flags & RIB_FLAG_WLOCK) + RIB_WUNLOCK(rnh); + else if (!(flags & RIB_FLAG_LOCKED)) + RIB_RUNLOCK(rnh); +} + /* * Iterates over all existing fibs in system calling * @hook_f function before/after traversing each fib.