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: Yumei Huang <yuhuang@redhat.com>, passt-dev@passt.top
Subject: Re: [PATCH v7 4/5] tcp: Update data retransmission timeout
Date: Wed, 5 Nov 2025 15:19:22 +1100	[thread overview]
Message-ID: <aQrQSsfEP-PlVrhf@zatzit> (raw)
In-Reply-To: <20251104054225.2b2a5a8c@elisabeth>

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

On Tue, Nov 04, 2025 at 05:42:25AM +0100, Stefano Brivio wrote:
> On Mon, 3 Nov 2025 20:32:14 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
> 
> > On Mon, Nov 03, 2025 at 10:57:27AM +0800, Yumei Huang wrote:
> > > On Mon, Nov 3, 2025 at 9:38 AM David Gibson <david@gibson.dropbear.id.au> wrote:  
> > > >
> > > > On Fri, Oct 31, 2025 at 01:42:41PM +0800, Yumei Huang wrote:
[snip]
> > > > > @@ -589,12 +585,10 @@ static void tcp_timer_ctl(const struct ctx *c, struct tcp_tap_conn *conn)
> > > > >       if (conn->flags & ACK_TO_TAP_DUE) {
> > > > >               it.it_value.tv_nsec = (long)ACK_INTERVAL * 1000 * 1000;
> > > > >       } else if (conn->flags & ACK_FROM_TAP_DUE) {
> > > > > -             if (!(conn->events & ESTABLISHED)) {
> > > > > -                     int exp = conn->retries - c->tcp.syn_linear_timeouts;  
> > > >
> > > > I didn't spot it in the previous patch, but this is (theoretically)
> > > > buggy.  conn->retries is unsigned, so the subtraction will be
> > > > performed unsigned and only then cast to signed.  I think that will
> > > > probably do the right thing in practice, but I don't think that's
> > > > guaranteed by the C standard (and might even be UB).  
> > > 
> > > I'm not sure, but I just googled it. IIUC, the uint8_t (conn->retries
> > > and c->tcp.syn_linear_timeouts) will go through integer promotion
> > > before subtraction. So the line is like:
> > > 
> > >     int exp = (int) conn->retries - (int) c->tcp.syn_linear_timeouts;
> > > 
> > > Please correct me if I'm wrong.  
> > 
> > Huh, I thought it would only be promoted if one of the operands was an
> > int.
> 
> I thought and I think so too, yes.
> 
> > But C promotion rules are really confusing, so I could well be wrong.
> 
> Some references linked at:
> 
>   https://archives.passt.top/passt-dev/20240103080834.24fa0a7a@elisabeth/
> 
> and here, it's about paragraph 6.3.1.8, "Usual arithmetic conversions"
> of C11 (that's what passt uses right now).
> 
> No double or float here, so this is the relevant text:
> 
>     Otherwise, the integer promotions are performed on both operands.
>     Then the following rules are applied to the promoted operands:
> 
>         If both operands have the same type, then no further conversion
>         is needed
> 
> now, are they really the same type? The standard doesn't define uint8_t.
> If we see it as an unsigned int, with storage limited to 8 bits, then I
> would call them the same type.

So, I was a bit confused in the first place - I had thought both
operands were literally uint8_t typed.  But that's not the case,
'retries' is an unsigned int that's bit limited.

> If we see c->tcp.syn_linear_timeouts as a character type instead
> (6.3.1.1, "Boolean, characters, and integers"), then the integer
> conversion rank of unsigned int (conn->retries) is greater than the rank
> of char, and the same text applies (promotion of char to unsigned int).
> 
> But I'm fairly sure that's not the case. We used uint8_t, not short,
> and not char.
> 
> All in all I don't think there's any possibility of promotion to a
> signed int: for that, you would need one of the operands to be signed.
> Or two unsigned chars/shorts (see examples below).

Right.  I'm fairly confident the arguments will be promoted to
unsigned int, not signed.

> If the operation is performed unsigned, and that's what gcc appears to
> do here, promoting both operands to unsigned int (32-bit):
> 
> ---
> $ cat pro_uh_oh_motion.c
> #include <stdio.h>
> #include <stdint.h>
> 
> int main()
> {
> 	uint8_t a = 0;
> 	struct { unsigned b:3; } x = { 7 };
> 
> 	printf("%u %i\n", a - x.b, a - x.b);
> }
> $ gcc -o pro_uh_oh_motion{,.c}
> $ ./pro_uh_oh_motion
> 4294967289 -7
> ---
> 
> ...do we really have a problem with that? To me it looks like the
> behaviour is defined, and it's what we want.

So, this is a second step, where we cast the result of the subtraction
into a signed int of the same size.  I'm not sure if that behaviour is
defined for values outside the positive range the signed type can
represent.  In practice the obvious result on a two's complement
machine will do what we need, but I'm not sure that C guarantees that.

> 
> These pages:
> 
>   https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules
>   https://wiki.sei.cmu.edu/confluence/display/c/EXP14-C.+Beware+of+integer+promotion+when+performing+bitwise+operations+on+integer+types+smaller+than+int
> 
> show some problematic examples. This one is close to our case:
> 
>   unsigned short x = 45000, y = 50000;
>   unsigned int z = x * y;
> 
> but there we have implicit promotion of the unsigned shorts to
> int, which doesn't happen in our case, because we already have an
> unsigned int.

Also multiplication which is a whole other thing.

> See also the examples with two unsigned shorts from:
> 
>   https://cryptoservices.github.io/fde/2018/11/30/undefined-behavior.html
> 
> and there the operation would be performed as signed int.
> 
> On top of that, you have the fact that the original types can't store
> the result of the operation. Here it's not the case.

They can't though - the result is negative which can't be stored in an
unsigned type.  Now, wraparound / mod 2^n behaviour *is* defined for
unsigned (but not signed) integer types.  The second part where we
assign an unsigned "negative" value into a signed variable might not
be.

-- 
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-05  4:24 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-31  5:42 [PATCH v7 0/5] Retry SYNs for inbound connections Yumei Huang
2025-10-31  5:42 ` [PATCH v7 1/5] tcp: Rename "retrans" to "retries" Yumei Huang
2025-10-31  5:42 ` [PATCH v7 2/5] util: Introduce read_file() and read_file_integer() function Yumei Huang
2025-11-03  0:53   ` David Gibson
2025-10-31  5:42 ` [PATCH v7 3/5] tcp: Resend SYN for inbound connections Yumei Huang
2025-11-03  1:09   ` David Gibson
2025-11-03  2:31     ` Yumei Huang
2025-11-03  9:01       ` David Gibson
2025-11-04  4:42         ` Stefano Brivio
2025-11-04  4:42   ` Stefano Brivio
2025-11-05  4:24     ` David Gibson
2025-11-05  7:00       ` Stefano Brivio
2025-11-07  9:56         ` Yumei Huang
2025-11-07 10:05           ` Stefano Brivio
2025-11-10  2:52             ` Yumei Huang
2025-11-10  4:25               ` David Gibson
2025-10-31  5:42 ` [PATCH v7 4/5] tcp: Update data retransmission timeout Yumei Huang
2025-10-31  5:56   ` Yumei Huang
2025-10-31  8:04     ` Stefano Brivio
2025-11-03  1:18   ` David Gibson
2025-11-03  2:57     ` Yumei Huang
2025-11-03  9:32       ` David Gibson
2025-11-04  4:42         ` Stefano Brivio
2025-11-05  4:19           ` David Gibson [this message]
2025-10-31  5:42 ` [PATCH v7 5/5] tcp: Clamp the retry timeout Yumei Huang
2025-10-31  8:38   ` Stefano Brivio
2025-11-03  3:11     ` Yumei Huang
2025-11-03  9:37       ` David Gibson
2025-11-03 10:55       ` Stefano Brivio
2025-11-03  1:37   ` David Gibson
2025-11-03  4:06     ` Yumei Huang
2025-11-03 10:38     ` Stefano Brivio
2025-11-05  4:22       ` David Gibson
2025-11-04  4:42   ` Stefano Brivio

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=aQrQSsfEP-PlVrhf@zatzit \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    --cc=yuhuang@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).