IfAPI: Add iterator to complement if_foreach()

Summary:
Sometimes an if_foreach() callback can be trivial, or need a lot of
outer context.  In this case a regular `for` loop makes more sense.  To
keep things hidden in the new API, use an opaque `if_iter` structure
that can still be instantiated on the stack.  The current implementation
uses just a single pointer out of the 4 alotted to the opaque context,
and the cleanup does nothing, but may be used in the future.

Reviewed by:	melifaro
Sponsored by:	Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D39138
This commit is contained in:
Justin Hibbits 2023-03-16 16:24:56 -04:00
parent 2af158ae83
commit e2427c6917
2 changed files with 45 additions and 0 deletions

View File

@ -4600,6 +4600,42 @@ if_foreach_sleep(if_foreach_match_t match_cb, void *match_arg, if_foreach_cb_t c
return (error);
}
/*
* Uses just 1 pointer of the 4 available in the public struct.
*/
if_t
if_iter_start(struct if_iter *iter)
{
if_t ifp;
NET_EPOCH_ASSERT();
bzero(iter, sizeof(*iter));
ifp = CK_STAILQ_FIRST(&V_ifnet);
if (ifp != NULL)
iter->context[0] = CK_STAILQ_NEXT(ifp, if_link);
else
iter->context[0] = NULL;
return (ifp);
}
if_t
if_iter_next(struct if_iter *iter)
{
if_t cur_ifp = iter->context[0];
if (cur_ifp != NULL)
iter->context[0] = CK_STAILQ_NEXT(cur_ifp, if_link);
return (cur_ifp);
}
void
if_iter_finish(struct if_iter *iter)
{
/* Nothing to do here for now. */
}
u_int
if_foreach_lladdr(if_t ifp, iflladdr_cb_t cb, void *cb_arg)
{

View File

@ -684,6 +684,15 @@ typedef bool (*if_foreach_match_t)(if_t, void *);
int if_foreach(if_foreach_cb_t, void *);
int if_foreach_sleep(if_foreach_match_t, void *, if_foreach_cb_t, void *);
/* Opaque iterator structure for iterating over interfaces. */
struct if_iter {
void *context[4];
};
if_t if_iter_start(struct if_iter *);
if_t if_iter_next(struct if_iter *);
void if_iter_finish(struct if_iter *);
/* Functions */
void if_setinitfn(if_t ifp, if_init_fn_t);
void if_setinputfn(if_t ifp, if_input_fn_t);