From nobody Sun Mar 22 09:32:16 2026 Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 550573BBA1A for ; Wed, 11 Mar 2026 07:56:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773215801; cv=none; b=Jg8Q3m7qzYZ8DxhVogA4eW/9xKmdE7RNRn7aFodQHAE2r+Ow4f4t+HSc+02Vb4uGnU4rRSvCnKYSEih8S40mVCESfrWY+LEl05HUpcxZ1hBV88M7F39Sf38Bk34YbPXxSI6nuOrmhi/qyer7KvuNkBvkt43BUj2ZW6uxfXGaY2Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773215801; c=relaxed/simple; bh=FWYsgoyKVIUupg0joGsjXBrmnww52mswGSTqsNgSq3U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=VS46AlyGU1HHjqGSPZIk1dmJWFVxuqxdJJ8wzV9IDdw2i2TTvHzs3adfhWYXBPjdPoON2gZXzGyoi8ZZjwzkQrFtNpySLRt1muTSTYI8s3WHepgsaPnAGTXyoUMj/Kx4BqHQLWkkarT1uzey3Jre5xGvC8frSVEPKkKRPixr1Lc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=H/2YPI1C; arc=none smtp.client-ip=209.85.210.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="H/2YPI1C" Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-7d75d698ee6so878356a34.3 for ; Wed, 11 Mar 2026 00:56:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773215795; x=1773820595; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DWRaO2kk43skP87kgk2P1rc0roOMtr/hXw08wzU1czs=; b=H/2YPI1Cgww1qLF8X73k6RMOlAtgpK/tDCvVe+qwTWtv1lCqP/9Fz45QU3JjxC8vrb KrI/fsEV4RvZpfe88/9Cwo/YMKi35uyvLHUFKDak3gowGawOrR3bOjUjQ3v6IgOmR/9L FYLTBlILCke4UkUMknw1uBgIO5NQE+pfMPuzCDz+CnIWsyP7Hkf22Ya8+euYwzq9rU4Y +bIc4n7aEXDhyF8zB00n5LgY89TGa4cFLqoLjmdsa67XhchiL3Zu+1D7GOGzgbGmzERY 0igkVYqDe1yoW9f/vGObwMv1JwybRSSMh3KeQl5KIPum6s8beGt543tmJSEwsJMkvkWu AR+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1773215795; x=1773820595; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=DWRaO2kk43skP87kgk2P1rc0roOMtr/hXw08wzU1czs=; b=t54ocVeXNG1nwnwDsgErwUxppTMsLY1A4rsIddL19oteW690/40rGCyI1bAJl4gwiD gqyLCPGqQtjbC7tzjBc0ORME1TR+Nakda0WfjHgy3yly783DpXMX3TSQvrgKFUTVgvGy mJ+uQ2ugEM5qCbt6z0GbJrbkRjOPMaDmlctlkCIhHNMYOg+pwbzB4cP1rzulEvaNfYrU 1b5nW0weqBfjVy6EQUePMyt8CN+O7r4QIaCpqBdaVjH6L1QGQffNyz7woX2bKiucS0/o w/mJbhhzwevk6yVIfxK9xmzw7oeKsyCfrnwBkw1Mk6nIwGophY80y4wDVjm3UZkxy+KG kZIg== X-Forwarded-Encrypted: i=1; AJvYcCWpMQRQfhRBe8YvP+kaOqxB9u4fTp+lOkpckzo5t5R+ckeLVnAvsOxRNbWaoCro5gJot0aejwt0gcYT4go=@vger.kernel.org X-Gm-Message-State: AOJu0YyNNuXwHJYX7ebNj/VY0TWtJ8AOqgNpew59I2quZYame2NfSSG7 Htjr1nxu2le2ukaCiu6dAItG4HLFh4jwHfQ9MCD03t4OUbSjGTLADg+d X-Gm-Gg: ATEYQzwUSEs1Hywfz5a44UIIedUuMureJv68+p4/tcEiJBsmMcsPlFm4zeT0BH7Au+5 5byaqBq9kMtuE+dPFE9s3z0nFAuo/Ph9FKd+gDkRqlOzQqlK4EGOWB5dp6K0ED98ghptwHQpC34 kM8ZsaYvMXDoU9GI2tawKVv6mSQmeANPvwFcp74wMy4H6CpbMuXzI9C8rW7nvKbSF0EAZMaHINz K9Rca3zMuoMHT7aIt/9puhvopwlTGgghprc6HYNexnUcHio75fUSwFOpTjvHwd46AflikD22mmr fsybxDxwzR9q1kJazfSsu24DiUd+fqrYdest+TNI9I9fzfHF/vIT4R2gpWoU5AVtzoeA6QBZMjI Dc5mudyueoE1pgX5fq9vPUy3cIx0LnBZmYgB+8p2PkYX2pg6X8Xk0MHatttNPPg01yFBlcyywr1 pj9aMHrsplSYqiAatQCz6cin+eqpmSACJa36NjQks88Fvs2+EfGrtVG/wtCag88s0Vatnep1dh5 Ih3i2lAdTchPhcDE4htMl6cJnoIU2lOq6tthMthCTIrcXL3 X-Received: by 2002:a05:6820:4deb:b0:679:e889:dde1 with SMTP id 006d021491bc7-67bc8877e83mr927920eaf.6.1773215795085; Wed, 11 Mar 2026 00:56:35 -0700 (PDT) Received: from localhost.localdomain (108-212-132-20.lightspeed.irvnca.sbcglobal.net. [108.212.132.20]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-4177e6ae0e3sm1568938fac.16.2026.03.11.00.56.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Mar 2026 00:56:34 -0700 (PDT) From: Wesley Atwell To: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com, edumazet@google.com, ncardwell@google.com, dsahern@kernel.org, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, mptcp@lists.linux.dev Cc: kuniyu@google.com, horms@kernel.org, geliang@kernel.org, corbet@lwn.net, skhan@linuxfoundation.org, rostedt@goodmis.org, mhiramat@kernel.org, mathieu.desnoyers@efficios.com, 0x7f454c46@gmail.com, linux-doc@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, atwellwea@gmail.com Subject: [PATCH net 4/7] tcp: extend TCP_REPAIR_WINDOW with receive-window scaling snapshot Date: Wed, 11 Mar 2026 01:55:57 -0600 Message-Id: <20260311075600.948413-5-atwellwea@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260311075600.948413-1-atwellwea@gmail.com> References: <20260311075600.948413-1-atwellwea@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The paired receive-window state is now part of the live TCP socket semantics, so repair and restore need a way to preserve it. Extend TCP_REPAIR_WINDOW with the advertise-time scaling snapshot while keeping old userspace working. The kernel now accepts exactly the legacy layout and the extended layout. Legacy restore leaves the snapshot unknown so the socket falls back safely until a fresh local window advertisement refreshes the pair, while the extended layout restores the exact snapshot. Signed-off-by: Wesley Atwell --- include/uapi/linux/tcp.h | 1 + net/ipv4/tcp.c | 34 ++++++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h index 03772dd4d399..3a799f4c0e1e 100644 --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h @@ -159,6 +159,7 @@ struct tcp_repair_window { =20 __u32 rcv_wnd; __u32 rcv_wup; + __u32 rcv_wnd_scaling_ratio; /* 0 means advertise-time basis unknown */ }; =20 enum { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index cec9ae1bf875..dd2b4fe61bd8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3551,17 +3551,25 @@ static inline bool tcp_can_repair_sock(const struct= sock *sk) (sk->sk_state !=3D TCP_LISTEN); } =20 +/* Keep accepting the pre-extension TCP_REPAIR_WINDOW layout so legacy + * userspace can restore sockets without fabricating a snapshot basis. + */ +static inline int tcp_repair_window_legacy_size(void) +{ + return offsetof(struct tcp_repair_window, rcv_wnd_scaling_ratio); +} + static int tcp_repair_set_window(struct tcp_sock *tp, sockptr_t optbuf, in= t len) { - struct tcp_repair_window opt; + struct tcp_repair_window opt =3D {}; =20 if (!tp->repair) return -EPERM; =20 - if (len !=3D sizeof(opt)) + if (len !=3D tcp_repair_window_legacy_size() && len !=3D sizeof(opt)) return -EINVAL; =20 - if (copy_from_sockptr(&opt, optbuf, sizeof(opt))) + if (copy_from_sockptr(&opt, optbuf, len)) return -EFAULT; =20 if (opt.max_window < opt.snd_wnd) @@ -3577,7 +3585,20 @@ static int tcp_repair_set_window(struct tcp_sock *tp= , sockptr_t optbuf, int len) tp->snd_wnd =3D opt.snd_wnd; tp->max_window =3D opt.max_window; =20 - tp->rcv_wnd =3D opt.rcv_wnd; + if (len =3D=3D tcp_repair_window_legacy_size()) { + /* Legacy repair UAPI has no advertise-time basis for tp->rcv_wnd. + * Mark the snapshot unknown until a fresh local advertisement + * re-establishes the pair. + */ + tcp_set_rcv_wnd_unknown(tp, opt.rcv_wnd); + tp->rcv_wup =3D opt.rcv_wup; + return 0; + } + + if (opt.rcv_wnd_scaling_ratio > U8_MAX) + return -EINVAL; + + tcp_set_rcv_wnd_snapshot(tp, opt.rcv_wnd, opt.rcv_wnd_scaling_ratio); tp->rcv_wup =3D opt.rcv_wup; =20 return 0; @@ -4667,12 +4688,12 @@ int do_tcp_getsockopt(struct sock *sk, int level, break; =20 case TCP_REPAIR_WINDOW: { - struct tcp_repair_window opt; + struct tcp_repair_window opt =3D {}; =20 if (copy_from_sockptr(&len, optlen, sizeof(int))) return -EFAULT; =20 - if (len !=3D sizeof(opt)) + if (len !=3D tcp_repair_window_legacy_size() && len !=3D sizeof(opt)) return -EINVAL; =20 if (!tp->repair) @@ -4683,6 +4704,7 @@ int do_tcp_getsockopt(struct sock *sk, int level, opt.max_window =3D tp->max_window; opt.rcv_wnd =3D tp->rcv_wnd; opt.rcv_wup =3D tp->rcv_wup; + opt.rcv_wnd_scaling_ratio =3D tp->rcv_wnd_scaling_ratio; =20 if (copy_to_sockptr(optval, &opt, len)) return -EFAULT; --=20 2.34.1