On Sun, Feb 22, 2026 at 12:44:34PM -0500, Jon Maloy wrote: > Add the for_each_addr() macro to iterate over addresses in the unified > array. The macro supports an address family filter parameter (AF_INET, > AF_INET6, or 0 for all) using a _next_addr_idx() helper function to > skip non-matching entries. > > Signed-off-by: Jon Maloy > > --- > v1: - Broke out as separate commit > - I kept the third argument, despite David's comment, since I still > find it practical. If we want to iterate the list without filter Eh, ok. I'm kind of hoping it will go away eventually, once more of the v4 and v6 paths are unified. > we can just use AF_UNSPEC (== 0) > --- > passt.h | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/passt.h b/passt.h > index 1aa71f0..bb56998 100644 > --- a/passt.h > +++ b/passt.h > @@ -344,6 +344,40 @@ static inline int inany_prefix4(const struct inany_addr_entry *e) > return e->prefix_len - 96; > } > > +/** > + * _next_addr_idx() - Find next address index matching family filter > + * @c: Pointer to struct ctx > + * @i: Starting index > + * @af: Address family filter: AF_INET, AF_INET6, or 0 for all > + * > + * Return: next matching index, or addr_count if none found > + */ > +static inline int _next_addr_idx(const struct ctx *c, int i, sa_family_t af) > +{ > + for (; i < c->addr_count; i++) { > + sa_family_t entry_af; > + > + entry_af = inany_v4(&c->addrs[i].addr) ? AF_INET : AF_INET6; > + > + if (!af || af == entry_af) I'd prefer an explicit (af == AF_UNSPEC), rather than subtly relying on AF_UNSPEC having value 0. > + return i; > + } > + return i; > +} > + > +/** > + * for_each_addr() - Iterate over addresses in unified array > + * @e: Pointer variable for current entry (struct inany_addr_entry *) > + * @c: Pointer to struct ctx > + * @af: Address family filter: AF_INET, AF_INET6, or 0 for all > + * > + * Note: @_i is the internal loop counter, uses _next_addr_idx() helper > + */ > +#define for_each_addr(e, c, af) \ > + for (int _i = _next_addr_idx((c), 0, (af)); \ Huh. We haven't really used declarations within for previously, but we do require C11 which allows them. There might be some other foreach macros that can be improved by using this. > + _i < (c)->addr_count && ((e) = &(c)->addrs[_i], true); \ > + _i = _next_addr_idx((c), _i + 1, (af))) > + > void proto_update_l2_buf(const unsigned char *eth_d); > > #endif /* PASST_H */ > -- > 2.52.0 > -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson