On Wed, Jul 10, 2024 at 11:32:01PM +0200, Stefano Brivio wrote: > On Fri, 5 Jul 2024 12:07:12 +1000 > David Gibson wrote: > > > We have upcoming use cases where it's useful to create new bound socket > > based on information from the flow table. Add flowside_sock_l4() to do > > this for either PIF_HOST or PIF_SPLICE sockets. > > > > Signed-off-by: David Gibson > > --- > > flow.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > flow.h | 3 ++ > > util.c | 6 ++-- > > util.h | 3 ++ > > 4 files changed, 101 insertions(+), 3 deletions(-) > > > > diff --git a/flow.c b/flow.c > > index 6f09781a..2d0a8a32 100644 > > --- a/flow.c > > +++ b/flow.c > > @@ -5,9 +5,11 @@ > > * Tracking for logical "flows" of packets. > > */ > > > > +#include > > #include > > #include > > #include > > +#include > > #include > > > > #include "util.h" > > @@ -143,6 +145,96 @@ static void flowside_from_af(struct flowside *fside, sa_family_t af, > > fside->eport = eport; > > } > > > > +/** > > + * struct flowside_sock_args - Parameters for flowside_sock_splice() > > + * @c: Execution context > > + * @fd: Filled in with new socket fd > > + * @err: Filled in with errno if something failed > > + * @type: Socket epoll type > > + * @sa: Socket address > > + * @sl: Length of @sa > > + * @data: epoll reference data > > + */ > > +struct flowside_sock_args { > > + const struct ctx *c; > > + int fd; > > + int err; > > + enum epoll_type type; > > + const struct sockaddr *sa; > > + socklen_t sl; > > + const char *path; > > + uint32_t data; > > +}; > > + > > +/** flowside_sock_splice() - Create and bind socket for PIF_SPLICE based on flowside > > + * @arg: Argument as a struct flowside_sock_args > > + * > > + * Return: 0 > > + */ > > +static int flowside_sock_splice(void *arg) > > +{ > > + struct flowside_sock_args *a = arg; > > + > > + ns_enter(a->c); > > + > > + a->fd = sock_l4_sa(a->c, a->type, a->sa, a->sl, NULL, > > Nit: assuming you wanted the extra whitespace here to align the > assignment with the one of a->err below, I'd rather write this > (at least for consistency) as "a->fd = ...". Actually, I think it was just a boring old typo. > > > + a->sa->sa_family == AF_INET6, a->data); > > + a->err = errno; > > > > + > > + return 0; > > +} > > + > > +/** flowside_sock_l4() - Create and bind socket based on flowside > > + * @c: Execution context > > + * @type: Socket epoll type > > + * @pif: Interface for this socket > > + * @tgt: Target flowside > > + * @data: epoll reference portion for protocol handlers > > + * > > + * Return: socket fd of protocol @proto bound to the forwarding address and port > > + * from @tgt (if specified). > > + */ > > +/* cppcheck-suppress unusedFunction */ > > +int flowside_sock_l4(const struct ctx *c, enum epoll_type type, uint8_t pif, > > + const struct flowside *tgt, uint32_t data) > > +{ > > + const char *ifname = NULL; > > + union sockaddr_inany sa; > > + socklen_t sl; > > + > > + ASSERT(pif_is_socket(pif)); > > + > > + pif_sockaddr(c, &sa, &sl, pif, &tgt->faddr, tgt->fport); > > + > > + switch (pif) { > > + case PIF_HOST: > > + if (inany_is_loopback(&tgt->faddr)) > > + ifname = NULL; > > + else if (sa.sa_family == AF_INET) > > + ifname = c->ip4.ifname_out; > > + else if (sa.sa_family == AF_INET6) > > + ifname = c->ip6.ifname_out; > > + > > + return sock_l4_sa(c, type, &sa, sl, ifname, > > + sa.sa_family == AF_INET6, data); > > + > > + case PIF_SPLICE: { > > + struct flowside_sock_args args = { > > + .c = c, .type = type, > > + .sa = &sa.sa, .sl = sl, .data = data, > > + }; > > + NS_CALL(flowside_sock_splice, &args); > > + errno = args.err; > > + return args.fd; > > + } > > + > > + default: > > + /* If we add new socket pifs, they'll need to be implemented > > + * here */ > > For consistency: > > /* If we add new socket pifs, they'll need to be implemented > * here > */ Done. > > there are a few occurrences in the next patches, not so important I > guess, I can also do a pass later at some point. > > > + ASSERT(0); > > + } > > +} > > + > > /** flow_log_ - Log flow-related message > > * @f: flow the message is related to > > * @pri: Log priority > > diff --git a/flow.h b/flow.h > > index c3a15ca6..e27f99be 100644 > > --- a/flow.h > > +++ b/flow.h > > @@ -164,6 +164,9 @@ static inline bool flowside_eq(const struct flowside *left, > > left->fport == right->fport; > > } > > > > +int flowside_sock_l4(const struct ctx *c, enum epoll_type type, uint8_t pif, > > + const struct flowside *tgt, uint32_t data); > > + > > /** > > * struct flow_common - Common fields for packet flows > > * @state: State of the flow table entry > > diff --git a/util.c b/util.c > > index 9a73fbb9..f2994a79 100644 > > --- a/util.c > > +++ b/util.c > > @@ -44,9 +44,9 @@ > > * > > * Return: newly created socket, negative error code on failure > > */ > > -static int sock_l4_sa(const struct ctx *c, enum epoll_type type, > > - const void *sa, socklen_t sl, > > - const char *ifname, bool v6only, uint32_t data) > > +int sock_l4_sa(const struct ctx *c, enum epoll_type type, > > + const void *sa, socklen_t sl, > > + const char *ifname, bool v6only, uint32_t data) > > { > > sa_family_t af = ((const struct sockaddr *)sa)->sa_family; > > union epoll_ref ref = { .type = type, .data = data }; > > diff --git a/util.h b/util.h > > index d0150396..f2e4f8cf 100644 > > --- a/util.h > > +++ b/util.h > > @@ -144,6 +144,9 @@ struct ctx; > > > > /* cppcheck-suppress funcArgNamesDifferent */ > > __attribute__ ((weak)) int ffsl(long int i) { return __builtin_ffsl(i); } > > +int sock_l4_sa(const struct ctx *c, enum epoll_type type, > > + const void *sa, socklen_t sl, > > + const char *ifname, bool v6only, uint32_t data); > > int sock_l4(const struct ctx *c, sa_family_t af, enum epoll_type type, > > const void *bind_addr, const char *ifname, uint16_t port, > > uint32_t data); > -- 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