public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>
Cc: passt-dev@passt.top
Subject: Re: [PATCH v3 1/8] inany: Let length of sockaddr_inany be implicit from the family
Date: Fri, 14 Nov 2025 09:53:10 +1100	[thread overview]
Message-ID: <aRZhVjJ7lo4k3A4U@zatzit> (raw)
In-Reply-To: <20251113073304.56859bae@elisabeth>

[-- Attachment #1: Type: text/plain, Size: 6890 bytes --]

On Thu, Nov 13, 2025 at 07:33:04AM +0100, Stefano Brivio wrote:
> Apologies for the very substantial delay. I have to admit I
> procrastinated around 3/8 and 4/8 quite a bit as they look scary (but
> much needed, of course).
> 
> Nits only, here:
> 
> On Wed, 29 Oct 2025 17:26:21 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > sockaddr_inany can contain either an IPv4 or IPv6 socket address, so the
> > relevant length for bind() or connect() can vary.  In pif_sockaddr() we
> > return that length, and in sock_l4_sa() we take it as an extra parameter.
> > 
> > However, sockaddr_inany always contains exactly a sockaddr_in or a
> > sockaddr_in6 each with a fixed size.  Therefore we can derive the relevant
> > length from the family, and don't need to pass it around separately.
> > 
> > Make a tiny helper to get the relevant address length, and update all
> > interfaces to use that approach instead.
> > 
> > In the process, fix a buglet in tcp_flow_repair_bind(): we passed
> > sizeof(union sockaddr_inany) to bind() instead of the specific length for
> > the address family.  Since the sizeof() is always longer than the specific
> > length, this is probably fine, but not theoretically correct.
> 
> (Whoops.)
>  
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > ---
> >  flow.c       | 17 +++++++----------
> >  icmp.c       |  3 ++-
> >  inany.h      | 18 ++++++++++++++++++
> >  pif.c        | 14 ++++----------
> >  pif.h        |  2 +-
> >  tcp.c        | 20 +++++++++-----------
> >  tcp_splice.c |  5 ++---
> >  udp.c        |  8 +++-----
> >  util.c       |  9 ++++-----
> >  util.h       |  5 +++--
> >  10 files changed, 53 insertions(+), 48 deletions(-)
> > 
> > diff --git a/flow.c b/flow.c
> > index feefda3c..9926f408 100644
> > --- a/flow.c
> > +++ b/flow.c
> > @@ -170,8 +170,7 @@ struct flowside_sock_args {
> >  	int fd;
> >  	int err;
> >  	enum epoll_type type;
> > -	const struct sockaddr *sa;
> > -	socklen_t sl;
> 
> This should be dropped from the struct documentation.

Good point, done.

> > +	const union sockaddr_inany *sa;
> >  	const char *path;
> >  	uint32_t data;
> 
> Note: you'll get a trivial conflict here with "util: Move epoll
> registration out of sock_l4_sa()" if you rebase.

Actually, there are a heap of conflicts with that patch.  I'll
definitely respin for that reason if no other.

> 
> >  };
> > @@ -187,7 +186,7 @@ static int flowside_sock_splice(void *arg)
> >  
> >  	ns_enter(a->c);
> >  
> > -	a->fd = sock_l4_sa(a->c, a->type, a->sa, a->sl, NULL,
> > +	a->fd = sock_l4_sa(a->c, a->type, a->sa, NULL,
> >  	                   a->sa->sa_family == AF_INET6, a->data);
> >  	a->err = errno;
> >  
> > @@ -209,11 +208,10 @@ int flowside_sock_l4(const struct ctx *c, enum epoll_type type, uint8_t pif,
> >  {
> >  	const char *ifname = NULL;
> >  	union sockaddr_inany sa;
> > -	socklen_t sl;
> >  
> >  	ASSERT(pif_is_socket(pif));
> >  
> > -	pif_sockaddr(c, &sa, &sl, pif, &tgt->oaddr, tgt->oport);
> > +	pif_sockaddr(c, &sa, pif, &tgt->oaddr, tgt->oport);
> >  
> >  	switch (pif) {
> >  	case PIF_HOST:
> > @@ -224,13 +222,13 @@ int flowside_sock_l4(const struct ctx *c, enum epoll_type type, uint8_t pif,
> >  		else if (sa.sa_family == AF_INET6)
> >  			ifname = c->ip6.ifname_out;
> >  
> > -		return sock_l4_sa(c, type, &sa, sl, ifname,
> > +		return sock_l4_sa(c, type, &sa, 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,
> > +			.sa = &sa, .data = data,
> >  		};
> >  		NS_CALL(flowside_sock_splice, &args);
> >  		errno = args.err;
> > @@ -259,10 +257,9 @@ int flowside_connect(const struct ctx *c, int s,
> >  		     uint8_t pif, const struct flowside *tgt)
> >  {
> >  	union sockaddr_inany sa;
> > -	socklen_t sl;
> >  
> > -	pif_sockaddr(c, &sa, &sl, pif, &tgt->eaddr, tgt->eport);
> > -	return connect(s, &sa.sa, sl);
> > +	pif_sockaddr(c, &sa, pif, &tgt->eaddr, tgt->eport);
> > +	return connect(s, &sa.sa, socklen_inany(&sa));
> >  }
> >  
> >  /** flow_log_ - Log flow-related message
> > diff --git a/icmp.c b/icmp.c
> > index 6dffafb0..62b3bed8 100644
> > --- a/icmp.c
> > +++ b/icmp.c
> > @@ -301,8 +301,9 @@ int icmp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
> >  	ASSERT(flow_proto[pingf->f.type] == proto);
> >  	pingf->ts = now->tv_sec;
> >  
> > -	pif_sockaddr(c, &sa, &msh.msg_namelen, PIF_HOST, &tgt->eaddr, 0);
> > +	pif_sockaddr(c, &sa, PIF_HOST, &tgt->eaddr, 0);
> >  	msh.msg_name = &sa;
> > +	msh.msg_namelen = socklen_inany(&sa);
> >  	msh.msg_iov = iov;
> >  	msh.msg_iovlen = cnt;
> >  	msh.msg_control = NULL;
> > diff --git a/inany.h b/inany.h
> > index 7ca5cbd3..e3cae2a8 100644
> > --- a/inany.h
> > +++ b/inany.h
> > @@ -67,6 +67,24 @@ union sockaddr_inany {
> >  	struct sockaddr_in6	sa6;
> >  };
> >  
> > +/** socklen_inany() - Return relevant size of an sockaddr_inany
> 
> 'of a'
> 
> ...but the fact that it returns that sounds kind of pleonastic. What
> about:
> 
> /** socklen_inany() - Get relevant address length for sockaddr_inany address

Good idea, done.

> 
> > + * @sa:		sockaddr_iany socket address
> 
> sockaddr_inany

Fixed.

> > + *
> > + * Returns the correct socket address length to pass to bind() or connect() with
> > + * @sa, based on whether it is an IPv4 or IPv6 address.
> 
> Same here, I guess we obviously want it to be correct, and we have a
> somewhat standard syntax for return values in documentation, what about:
> 
>  * Return: socket address length for bind() or connect(), from IP family in @sa
> 
> ?

Again, good idea, done.

> 
> > + */
> > +static inline socklen_t socklen_inany(const union sockaddr_inany *sa)
> > +{
> > +	switch (sa->sa_family) {
> > +	case AF_INET:
> > +		return sizeof(sa->sa4);
> 
> Wouldn't it be more obvious to return sizeof(struct sockaddr_in), and
> sizeof(struct sockaddr_in6) below, instead? I actually had to check that
> sa->sa4 matched that (I didn't remember if that was a union).

Eh, maybe?

> Not a strong preference from my side, both are obviously correct
> anyway.

I usually prefer to use sizeof() on variables not types when possible
- it means things tend to either work or break more obviously if the
types of the variables get changed.  Leaving this one for now.

> 
> > +	case AF_INET6:
> > +		return sizeof(sa->sa6);
> > +	default:
> > +		ASSERT(0);
> > +	}
> > +}
> 
> -- 
> Stefano
> 

-- 
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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2025-11-14  0:26 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-29  6:26 [PATCH v3 0/8] Reduce differences between inbound and outbound socket binding David Gibson
2025-10-29  6:26 ` [PATCH v3 1/8] inany: Let length of sockaddr_inany be implicit from the family David Gibson
2025-11-13  6:33   ` Stefano Brivio
2025-11-13 22:53     ` David Gibson [this message]
2025-10-29  6:26 ` [PATCH v3 2/8] util, flow, pif: Simplify sock_l4_sa() interface David Gibson
2025-11-13  6:33   ` Stefano Brivio
2025-11-13 23:21     ` David Gibson
2025-11-18  0:19       ` Stefano Brivio
2025-11-18  3:34         ` David Gibson
2025-11-19 11:42           ` Stefano Brivio
2025-11-20  0:05             ` David Gibson
2025-11-20  2:22               ` David Gibson
2025-10-29  6:26 ` [PATCH v3 3/8] tcp: Merge tcp_ns_sock_init[46]() into tcp_sock_init_one() David Gibson
2025-10-29  6:26 ` [PATCH v3 4/8] udp: Unify some more inbound/outbound parts of udp_sock_init() David Gibson
2025-11-13  6:33   ` Stefano Brivio
2025-11-13 23:33     ` David Gibson
2025-10-29  6:26 ` [PATCH v3 5/8] udp: Move udp_sock_init() special case to its caller David Gibson
2025-10-29  6:26 ` [PATCH v3 6/8] util: Fix setting of IPV6_V6ONLY socket option David Gibson
2025-11-13  6:33   ` Stefano Brivio
2025-11-14  0:24     ` David Gibson
2025-11-18  0:19       ` Stefano Brivio
2025-10-29  6:26 ` [PATCH v3 7/8] tcp, udp: Remove fallback if creating dual stack socket fails David Gibson
2025-10-29  6:26 ` [PATCH v3 8/8] [RFC, DO NOT APPLY] tcp, udp: Bind outbound listening sockets by interface instead of address David Gibson
2025-10-30  3:58 ` [PATCH v3 0/8] Reduce differences between inbound and outbound socket binding David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aRZhVjJ7lo4k3A4U@zatzit \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).