From nobody Tue May 5 11:27:26 2026 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (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 659B028643A for ; Tue, 21 Apr 2026 22:33:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776810826; cv=none; b=gMMQE7Yne7XXTXrwuQ1Ek8ZUWWIjKlvG7gSlpBp8v3lJc0NZ5INL/NYDCt4Mlk/uNDXgi60H3ZmxjPMN/V0gFegTWmrlXrLRwCH17MsJNga58tzKySoWoFm8MI9v03tj0websyF/JQEoIHWI/xQBryUrW27d9oo0GnW9xylpVWA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776810826; c=relaxed/simple; bh=gP3xPc2+iFOqL5Q+LRb6XPRPMrGN4TgqPKGtHGkGx6k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tN13IeBombrQXdNNbUDYwrnMrHkSrq/3RXLBiMhYPzrwLMDN8FZydzf6w/mp2HgWng0m/XTJQOdErSi27UTdvP5ZRVY19WSXw6pdjKZdiD3AHXq1WwZIj5NReJJdXESBt/9C8ljdaXllriADo0tCLCSkzAIYSamw6bpyOeaJeOI= 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=WmHpLMC0; arc=none smtp.client-ip=209.85.128.54 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="WmHpLMC0" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-488ad135063so40873995e9.0 for ; Tue, 21 Apr 2026 15:33:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776810823; x=1777415623; darn=lists.linux.dev; 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=xYNaU+7FMxSTwZANJDmlLzMBd40D//blvKqYMGhS5nM=; b=WmHpLMC0PaMFLfNerQncuPuj94XaDw6gA/8ssSBP6fYRav9bc8/3Li83RsRZruaJSl 0Y9qeA25IDaDrqLQ4F5O/0Wg6g34C8IDuq8XxYRuWwf3Asc0r3Rl120kw6WiqYsV27lA FtpsQhlKYzWUljA95G7kY9q/eAuVlXwvVsG4k14IHoszPLiwwxoacfTe3mTHghwSCE/+ up0XzN9sX0c2RON+F9473ZUrZqn0IfcjQkBBP2m7eDByK6vPJerLnPV8vnx/Frdii3h1 4aQAzZQgK2J5xFXJXmuUkjxPsJ8DzNwAE9e2CNZEhI8Y/PJgzReZata1fTB8eddbYIyr DENg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776810823; x=1777415623; 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=xYNaU+7FMxSTwZANJDmlLzMBd40D//blvKqYMGhS5nM=; b=IewnMdwoiVQaMNDxDVd5kfrSqCDWjGnJhPykddt6KCIyG9dEsn20G3oUXMHizg/avG EErfT6mT5atWSe+DPsxWpeVsRu2lF4EulEnRVJjxOzZAEpr7gFQa0+Y9UpdxaaAC4uDC 1e20eoAx4rodakVLDwVCDVdw95S2uaU2YSx0RjFQJSmSUJYiXuW3+WLIic37fzn+D+Hx Fvp5Zdge0wVPnDuzB+nNlZ4LKkVUd+kJb7LPtVPLr1XFj1KbaELjenfn7Rsqop0hXFGv wnD0xLClJtit/ntCvJEHuwUSt+lE8cg194phkJ2D15n4q0etLdNkU+9NBj71jcY0Ln6D ltzw== X-Gm-Message-State: AOJu0Yy55maH4m2YprRs5ZMyFLYwCQNdF2baZ5S1Ee2cHg68xU55dlsO vHotXu7wejKCmMhCfetfhkUifrg3sKebH6AK5zCRynDaUgiafw1fIbrwwJ/j79Kv X-Gm-Gg: AeBDiesMduH1gQTOoW9IxCDdZV6llM5DQxUPrKDyivrqd3KWJBBkl0pJzBpAY8i+DxW lHYv6bx5V4zrl7/JS+/lQCPfPYTdHCB9v5ZZ0ruH6hgAVrQ4CyKy65c8n4KADCNyvhEjQQw/72A jo+O3YBpen+fD9xB4Yae2yRP0VGavbBpj0DKtPgE1uuAO+MpJ41ZykgA0G3DqW4XGGbpu5fRwAR u/BSaShaytkU/fp6PIrYVrHS1gEjaVfQXYL+H8UZ5krVEbmbc7RYwKdoxGRa5KVb0xhwFdFbmhi jwMhNVLFHhttd2FJcarjNU4MEUxcmqW+AQg5zWA9D22VJ1n3hGTAcdjR7zQdomhxvcpb9RFK/cY kjTHtGnrp94lEJgRxCPirqsa9ZPHhW+Dp8Xo3nPutiEsGU1+8aq5hU1fvO0zPW3OY2EbDw8L1bG tXDhU/9U8FcUB6fnq222K4k4BGU7Zz20aLk3JT47M9zlF7jx7EWkI1wM1CHETnwmtMXEB7dFQnP Sl6LhlXOhZXu57fXwzXWQ== X-Received: by 2002:a05:600c:a30b:b0:487:2671:fb8f with SMTP id 5b1f17b1804b1-488fb74dfe5mr195605825e9.8.1776810823459; Tue, 21 Apr 2026 15:33:43 -0700 (PDT) Received: from dohko.chello.ie (188-141-5-72.dynamic.upc.ie. [188.141.5.72]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488fc1c01cfsm413350505e9.10.2026.04.21.15.33.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 15:33:42 -0700 (PDT) From: David Carlier To: mptcp@lists.linux.dev Cc: Matthieu Baerts , Mat Martineau , Geliang Tang , David Carlier Subject: [PATCH mptcp-next v3 1/3] mptcp: propagate RECVERR sockopts to subflows Date: Tue, 21 Apr 2026 23:33:36 +0100 Message-ID: <20260421223338.52743-2-devnexen@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260421223338.52743-1-devnexen@gmail.com> References: <20260421223338.52743-1-devnexen@gmail.com> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Propagate IP_RECVERR/IP_RECVERR_RFC4884 and IPV6_RECVERR/IPV6_RECVERR_RFC4884 from the MPTCP socket to existing and future subflows. Apply the matching sockopt according to the subflow family so mixed- family subflows stay aligned with the parent socket configuration, including disable-time errqueue purge semantics. Signed-off-by: David Carlier Assisted-by: Codex:gpt-5 Signed-off-by: David Carlier --- net/mptcp/sockopt.c | 129 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index 79db15903e7a..acb0ca330e44 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -8,6 +8,8 @@ =20 #include #include +#include +#include #include #include #include @@ -384,6 +386,72 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_so= ck *msk, int optname, return -EOPNOTSUPP; } =20 +static bool mptcp_recverr_enabled(const struct sock *sk, bool rfc4884) +{ + bool enabled; + + enabled =3D rfc4884 ? inet_test_bit(RECVERR_RFC4884, sk) : + inet_test_bit(RECVERR, sk); + +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family =3D=3D AF_INET6) + enabled |=3D rfc4884 ? inet6_test_bit(RECVERR6_RFC4884, sk) : + inet6_test_bit(RECVERR6, sk); +#endif + + return enabled; +} + +static int mptcp_subflow_set_recverr(struct sock *sk, struct sock *ssk, + bool rfc4884) +{ + int level, optname, val; + +#if IS_ENABLED(CONFIG_IPV6) + if (ssk->sk_family =3D=3D AF_INET6) { + level =3D SOL_IPV6; + optname =3D rfc4884 ? IPV6_RECVERR_RFC4884 : IPV6_RECVERR; + } else +#endif + { + level =3D SOL_IP; + optname =3D rfc4884 ? IP_RECVERR_RFC4884 : IP_RECVERR; + } + + val =3D mptcp_recverr_enabled(sk, rfc4884); + return tcp_setsockopt(ssk, level, optname, KERNEL_SOCKPTR(&val), + sizeof(val)); +} + +#if IS_ENABLED(CONFIG_IPV6) +static int mptcp_setsockopt_v6_recverr(struct mptcp_sock *msk, int optname, + sockptr_t optval, unsigned int optlen) +{ + struct mptcp_subflow_context *subflow; + struct sock *sk =3D (struct sock *)msk; + int ret; + + ret =3D ipv6_setsockopt(sk, SOL_IPV6, optname, optval, optlen); + if (ret) + return ret; + + lock_sock(sk); + sockopt_seq_inc(msk); + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + bool rfc4884 =3D optname =3D=3D IPV6_RECVERR_RFC4884; + + ret =3D mptcp_subflow_set_recverr(sk, ssk, rfc4884); + if (ret) + break; + subflow->setsockopt_seq =3D msk->setsockopt_seq; + } + release_sock(sk); + + return ret; +} +#endif + static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname, sockptr_t optval, unsigned int optlen) { @@ -426,6 +494,12 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk,= int optname, =20 release_sock(sk); break; +#if IS_ENABLED(CONFIG_IPV6) + case IPV6_RECVERR: + case IPV6_RECVERR_RFC4884: + ret =3D mptcp_setsockopt_v6_recverr(msk, optname, optval, optlen); + break; +#endif } =20 return ret; @@ -760,6 +834,33 @@ static int mptcp_setsockopt_v4_set_tos(struct mptcp_so= ck *msk, int optname, return 0; } =20 +static int mptcp_setsockopt_v4_recverr(struct mptcp_sock *msk, int optname, + sockptr_t optval, unsigned int optlen) +{ + struct mptcp_subflow_context *subflow; + struct sock *sk =3D (struct sock *)msk; + int err; + + err =3D ip_setsockopt(sk, SOL_IP, optname, optval, optlen); + if (err) + return err; + + lock_sock(sk); + sockopt_seq_inc(msk); + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + bool rfc4884 =3D optname =3D=3D IP_RECVERR_RFC4884; + + err =3D mptcp_subflow_set_recverr(sk, ssk, rfc4884); + if (err) + break; + subflow->setsockopt_seq =3D msk->setsockopt_seq; + } + release_sock(sk); + + return err; +} + static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname, sockptr_t optval, unsigned int optlen) { @@ -771,6 +872,9 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, = int optname, return mptcp_setsockopt_sol_ip_set(msk, optname, optval, optlen); case IP_TOS: return mptcp_setsockopt_v4_set_tos(msk, optname, optval, optlen); + case IP_RECVERR: + case IP_RECVERR_RFC4884: + return mptcp_setsockopt_v4_recverr(msk, optname, optval, optlen); } =20 return -EOPNOTSUPP; @@ -1459,6 +1563,12 @@ static int mptcp_getsockopt_v4(struct mptcp_sock *ms= k, int optname, case IP_LOCAL_PORT_RANGE: return mptcp_put_int_option(msk, optval, optlen, READ_ONCE(inet_sk(sk)->local_port_range)); + case IP_RECVERR: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(RECVERR, sk)); + case IP_RECVERR_RFC4884: + return mptcp_put_int_option(msk, optval, optlen, + inet_test_bit(RECVERR_RFC4884, sk)); } =20 return -EOPNOTSUPP; @@ -1479,6 +1589,12 @@ static int mptcp_getsockopt_v6(struct mptcp_sock *ms= k, int optname, case IPV6_FREEBIND: return mptcp_put_int_option(msk, optval, optlen, inet_test_bit(FREEBIND, sk)); + case IPV6_RECVERR: + return mptcp_put_int_option(msk, optval, optlen, + inet6_test_bit(RECVERR6, sk)); + case IPV6_RECVERR_RFC4884: + return mptcp_put_int_option(msk, optval, optlen, + inet6_test_bit(RECVERR6_RFC4884, sk)); } =20 return -EOPNOTSUPP; @@ -1536,6 +1652,7 @@ static void sync_socket_options(struct mptcp_sock *ms= k, struct sock *ssk) { static const unsigned int tx_rx_locks =3D SOCK_RCVBUF_LOCK | SOCK_SNDBUF_= LOCK; struct sock *sk =3D (struct sock *)msk; + bool recverr, recverr_rfc4884; bool keep_open; =20 keep_open =3D sock_flag(sk, SOCK_KEEPOPEN); @@ -1586,6 +1703,18 @@ static void sync_socket_options(struct mptcp_sock *m= sk, struct sock *ssk) inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk)); inet_assign_bit(BIND_ADDRESS_NO_PORT, ssk, inet_test_bit(BIND_ADDRESS_NO_= PORT, sk)); WRITE_ONCE(inet_sk(ssk)->local_port_range, READ_ONCE(inet_sk(sk)->local_p= ort_range)); + recverr =3D mptcp_recverr_enabled(sk, false); + recverr_rfc4884 =3D mptcp_recverr_enabled(sk, true); +#if IS_ENABLED(CONFIG_IPV6) + if (ssk->sk_family =3D=3D AF_INET6) { + inet6_assign_bit(RECVERR6, ssk, recverr); + inet6_assign_bit(RECVERR6_RFC4884, ssk, recverr_rfc4884); + } else +#endif + { + inet_assign_bit(RECVERR, ssk, recverr); + inet_assign_bit(RECVERR_RFC4884, ssk, recverr_rfc4884); + } } =20 void mptcp_sockopt_sync_locked(struct mptcp_sock *msk, struct sock *ssk) --=20 2.53.0 From nobody Tue May 5 11:27:26 2026 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (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 9B5C126B2DA for ; Tue, 21 Apr 2026 22:33:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776810828; cv=none; b=pKpu5taySrp747NkXThD++iVqwFzp5YerzAuxIMGnTewCTIQholN7ugU2kkK96aQivF7sq6eIWSQXuoVhi1M+bS5vreiAbelX8cCJVjHYnke0g9z91wrVFbAF989iF5h6ZI9BV2qlazpiyWXtFXMYwxoN9SeUAwfIOG19NchmP0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776810828; c=relaxed/simple; bh=rmMCLSiNjQ0zi5Szgu6JuMRht5SNmzPSWgxY3yu8q74=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GTC6J8wR192yxPddIstUrHVCAof1wm+BmCQAoHQ8EgP+z/dqo11MuQlV76frqrn73v/xOOQsPYgBiLBCewNZ8m6o+13SQ21AvEOXPZU23e+nTegMITf9/BofilZWrqWrq4IwtBASyssfv2WHhGMaN05Vu6obgLhqe7iht6NkIDc= 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=dzi7eZqc; arc=none smtp.client-ip=209.85.128.54 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="dzi7eZqc" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-488d2079582so55643645e9.2 for ; Tue, 21 Apr 2026 15:33:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776810825; x=1777415625; darn=lists.linux.dev; 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=wpzd8+9DwlWwfdYBazdVMlZ0wJBEABxjwUprlU8+dHM=; b=dzi7eZqcdhaAYnB1LiYRL66cExajQfw5AL+h5rnxaD1XVQxOZ9mCI3Vx5nsw1cE/Sw FGdEWUZwiQguSJVxVnRernqzhgFWn5ahdKrFt4O0rH+yWdlE+7rvxAh8mcEMJyvHApbM 2T0MQ2jDnrDUcW2r9ZIvr0eoHqrIRS0+w1mz268w3eOdF+qktf5dAYkqTqJx20YbRJoy vsi3FVyhVpAEev2kxpJ9AgtpKPdweNFCULXk3UCc1IdHLP1p3ATrNwnrfn1Zh3QlSI+m 7Be918xEyfVkce3Y7GA/iH8tWl8SruoY7QxUQyerJ4l3juj0Y5QF6kwFE6n8w317SwLC BWKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776810825; x=1777415625; 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=wpzd8+9DwlWwfdYBazdVMlZ0wJBEABxjwUprlU8+dHM=; b=YSzrsw3GWTawRpWfXZDNFSaZw40E8MhSS/iQ8w9m4XT+C9kUMPVDtR0a+2yHolZ7og KNaM6rtJgLxMbDWSz2PzLzZXL4oXGnRHR8P82ifJXGqyWzyAkogso2ZAQB2FdXmmRoDJ /FzAvlEhhbMxH1jqQt39IL16BWeao0mUN4OebOsgBQ0m2Tjj05h5/KKC/9DOn0b3BkK4 cOfjuqvum6CxMrOt4ql9kYVEmF31wWc6uS6sw6lJK3VE5fbkqIxU3FVSixgVcaPvNyrE tYgoFkxxpl+l+m2TBfalcesXSXqPUG7e/lmZy4OyXf0XcafI9CHFOUi8kY31kosNIzeW VeQQ== X-Gm-Message-State: AOJu0YzlXSEfu35jGnaNe6pxlwYLJCMmHork4FXIKKFRF/B/ac8bbP47 6WhS5OCnwVtTE8u0Y/Vo9OKjwMrpNnXMOucJt1Wx6vN8mueRBUp7W5jI7Sd372W8 X-Gm-Gg: AeBDieu86fMCr6GSjIh9nsjHisZ0cgFsPwSSbCQGLanYcpOLaAZNjEpmkhkl3j3kpnk YhO6ZUxdXjq17VygJZuBOd0KHQ1Z5s4UQAENp4SonG4flu6zVkXAFcf62nm9YS7j8xYBi1wKX3G zQpowD0VQC+Bb6yvZqeTDuFLXzBR5pM6HQ6raCvZXASHPZwDFkb8jPew0SaiHn5a3lPVVyJLxtg uuhLn/9czmz1OlSvpTZmml6aqW3p8USSVchbzEfwn0uyGbtzesN3/Un9tCgIXFqRIRl3SAvMMhr TELrlB/CrTdLL7LyNF3joR2MnUSO9UHz27ReilKbS4qAOlxjSoeXo5q7c7A8jZtkJLOZ+2+755S MmrvCSXAG8ZZ+4S6UGQ84P3wGm34qjF9cXJzvdhINJ/QP94D7+J1bAcgQGEAYKCKVNLIWe+56z5 Qu3dC4fuaDAz9K3kdp9to/0hQILz8/a58TIQqeqcxBINqqBXKQuziMdZQIYLc0YGnUnpezDJc31 5qcevW20603A+ujywrThQ== X-Received: by 2002:a05:600c:444a:b0:487:1520:d107 with SMTP id 5b1f17b1804b1-488fb793580mr262347415e9.31.1776810824537; Tue, 21 Apr 2026 15:33:44 -0700 (PDT) Received: from dohko.chello.ie (188-141-5-72.dynamic.upc.ie. [188.141.5.72]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488fc1c01cfsm413350505e9.10.2026.04.21.15.33.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 15:33:43 -0700 (PDT) From: David Carlier To: mptcp@lists.linux.dev Cc: Matthieu Baerts , Mat Martineau , Geliang Tang , David Carlier Subject: [PATCH mptcp-next v3 2/3] mptcp: support MSG_ERRQUEUE on the parent socket Date: Tue, 21 Apr 2026 23:33:37 +0100 Message-ID: <20260421223338.52743-3-devnexen@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260421223338.52743-1-devnexen@gmail.com> References: <20260421223338.52743-1-devnexen@gmail.com> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Handle MSG_ERRQUEUE on the MPTCP socket by selecting a subflow with pending errqueue data, moving one error skb to the parent socket, and consuming it through the parent socket ABI. This surfaces subflow errqueue activity through poll(), keeps the userspace ABI tied to the socket being used, and restores the skb to the subflow errqueue if requeueing to the parent fails under rmem pressure. Signed-off-by: David Carlier Assisted-by: Codex:gpt-5 Signed-off-by: David Carlier --- net/mptcp/protocol.c | 123 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 103 insertions(+), 20 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 6b486fc94c16..87871216bab2 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -818,28 +818,29 @@ static bool __mptcp_ofo_queue(struct mptcp_sock *msk) static bool __mptcp_subflow_error_report(struct sock *sk, struct sock *ssk) { int ssk_state; - int err; + int err =3D 0; + bool has_errqueue; + + has_errqueue =3D !skb_queue_empty_lockless(&ssk->sk_error_queue); =20 - /* only propagate errors on fallen-back sockets or - * on MPC connect + /* Only fallback sockets and the MPC connect path inherit TCP's sk_err + * semantics; consume ssk->sk_err only on those paths so steady-state + * MPTCP doesn't silently drop TCP's one-shot errors. */ - if (sk->sk_state !=3D TCP_SYN_SENT && !__mptcp_check_fallback(mptcp_sk(sk= ))) - return false; + if (sk->sk_state =3D=3D TCP_SYN_SENT || + __mptcp_check_fallback(mptcp_sk(sk))) { + err =3D sock_error(ssk); + if (err) { + ssk_state =3D inet_sk_state_load(ssk); + if (ssk_state =3D=3D TCP_CLOSE && !sock_flag(sk, SOCK_DEAD)) + mptcp_set_state(sk, ssk_state); + WRITE_ONCE(sk->sk_err, -err); + } + } =20 - err =3D sock_error(ssk); - if (!err) + if (!err && !has_errqueue) return false; =20 - /* We need to propagate only transition to CLOSE state. - * Orphaned socket will see such state change via - * subflow_sched_work_if_closed() and that path will properly - * destroy the msk as needed. - */ - ssk_state =3D inet_sk_state_load(ssk); - if (ssk_state =3D=3D TCP_CLOSE && !sock_flag(sk, SOCK_DEAD)) - mptcp_set_state(sk, ssk_state); - WRITE_ONCE(sk->sk_err, -err); - /* This barrier is coupled with smp_rmb() in mptcp_poll() */ smp_wmb(); sk_error_report(sk); @@ -2286,6 +2287,68 @@ static unsigned int mptcp_inq_hint(const struct sock= *sk) return 0; } =20 +static struct sock *mptcp_pick_errqueue_subflow(struct sock *sk) +{ + struct mptcp_subflow_context *subflow; + struct sock *ssk =3D NULL; + + lock_sock(sk); + mptcp_for_each_subflow(mptcp_sk(sk), subflow) { + struct sock *subflow_sk =3D mptcp_subflow_tcp_sock(subflow); + + if (skb_queue_empty_lockless(&subflow_sk->sk_error_queue)) + continue; + + if (!refcount_inc_not_zero(&subflow_sk->sk_refcnt)) + continue; + + ssk =3D subflow_sk; + break; + } + release_sock(sk); + + return ssk; +} + +static bool mptcp_has_error_queue(const struct sock *sk) +{ + return !skb_queue_empty_lockless(&sk->sk_error_queue); +} + +static int mptcp_recv_error(struct sock *sk, struct msghdr *msg, int len) +{ + struct sk_buff *skb; + struct sock *ssk; + int ret, ret2; + + if (READ_ONCE(sk->sk_err) || mptcp_has_error_queue(sk)) + return inet_recv_error(sk, msg, len); + + ssk =3D mptcp_pick_errqueue_subflow(sk); + if (!ssk) + return -EAGAIN; + + skb =3D sock_dequeue_err_skb(ssk); + if (!skb) + goto put_ssk; + + ret =3D sock_queue_err_skb(sk, skb); + if (ret) { + ret2 =3D sock_queue_err_skb(ssk, skb); + sock_put(ssk); + if (ret2) + kfree_skb(skb); + return ret; + } + + sock_put(ssk); + return inet_recv_error(sk, msg, len); + +put_ssk: + sock_put(ssk); + return -EAGAIN; +} + static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags) { @@ -2295,9 +2358,8 @@ static int mptcp_recvmsg(struct sock *sk, struct msgh= dr *msg, size_t len, int target; long timeo; =20 - /* MSG_ERRQUEUE is really a no-op till we support IP_RECVERR */ if (unlikely(flags & MSG_ERRQUEUE)) - return inet_recv_error(sk, msg, len); + return mptcp_recv_error(sk, msg, len); =20 lock_sock(sk); if (unlikely(sk->sk_state =3D=3D TCP_LISTEN)) { @@ -4296,6 +4358,26 @@ static __poll_t mptcp_check_writeable(struct mptcp_s= ock *msk) return 0; } =20 +static bool mptcp_subflow_has_error(struct sock *sk) +{ + struct mptcp_subflow_context *subflow; + bool has_error =3D false; + + mptcp_data_lock(sk); + mptcp_for_each_subflow(mptcp_sk(sk), subflow) { + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + + if (READ_ONCE(ssk->sk_err) || + !skb_queue_empty_lockless(&ssk->sk_error_queue)) { + has_error =3D true; + break; + } + } + mptcp_data_unlock(sk); + + return has_error; +} + static __poll_t mptcp_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait) { @@ -4339,7 +4421,8 @@ static __poll_t mptcp_poll(struct file *file, struct = socket *sock, =20 /* This barrier is coupled with smp_wmb() in __mptcp_error_report() */ smp_rmb(); - if (READ_ONCE(sk->sk_err)) + if (READ_ONCE(sk->sk_err) || mptcp_has_error_queue(sk) || + mptcp_subflow_has_error(sk)) mask |=3D EPOLLERR; =20 return mask; --=20 2.53.0 From nobody Tue May 5 11:27:26 2026 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (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 D4FEF28643A for ; Tue, 21 Apr 2026 22:33:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776810829; cv=none; b=Vefx6D0pSPXz/cbsyG1j4iiSrhg/7Te0LnIhrn11OXKM37Miipzy3cmhOv0zZyRdWDXpPWEKw1uu1yZR0hY2TxLN6sgtP86rsSbFx4TNhwakxVey8Zi8G2Bw286bWbxmHJ2RlkyH3q3BPHya7PDaRPfK/F1whucT1dAtk5AgWWg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776810829; c=relaxed/simple; bh=QcNVzrHJDmzDhVBtHzMTu8HUGMD/QTYlMSpRK5EIoOU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WUNzAF6GCYQj02qwrcPJfZVavoDi172mnRhyrt8OEXZoAbiQYSzXNtuiYH8OaBbvvFhcfhFB37E3ynvIguTFgPGlHet84W5lnFVSSo+uqI9B/8bJUAGBNUGaUEnIlF3rMxTG/0VEwcdBJpkBwsLGUORLJbRfT4VXLd62eQgKo40= 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=cPQEnwSZ; arc=none smtp.client-ip=209.85.128.41 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="cPQEnwSZ" Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-488b8bc6bc9so33604675e9.3 for ; Tue, 21 Apr 2026 15:33:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776810826; x=1777415626; darn=lists.linux.dev; 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=+lXcg061bbhFrI0v23H2NQAB6iGsZBPcokYpsEnhLcE=; b=cPQEnwSZhFlB9JpsNHgf1uzLVuHKCpLgDMH28QKmZVxZjs+fOOq1qzx14E8hPzRZx3 FpjJmcF1s1MwMlC2kv+kscawijffRX5JnetNVvRaxgtNj29nEmfuAN7dvuRoNtRTfPPo AgieZETg6F8i4sU57n7DDyFoSVRcRCxu2ryeUeY6uHK7JdQSMSkX+7CtGEaZMnqEU6UT 6uPPWzaKcH5zg3W+iksHKjHa24gqlSrp1cL/ia9/xJ3/05V4YoU338Q9EiEGfoxr16PX OD2/FiOYe+PJceVQUzGeH+KMm+1p+QLnztVJvIPPArnUlaee7+WJpolwG86E4ZQVp9/X Kefg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776810826; x=1777415626; 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=+lXcg061bbhFrI0v23H2NQAB6iGsZBPcokYpsEnhLcE=; b=MFlCGAOPZoE4Y3npz/cvnCTICnIO2JoZljkSuqqV0i4PAO3YVPTeH+2IZrC8TIKUCD pgWJAKhiPPa1YstK7ufku8SpwHRtoq99ZBLU1sn0DC02O422+15i7+EOcejsJSphRz/X F2AGO11PmJnqOwLwNBJqxolwJw+OLx8mVABHjnHj5h8bonhXY/AIMoxg135m1K38VjBv 6sVPOjTp0v4wGhcS9ROFkWdq0jqnWD5LOyhZaCk9C2EzY8B+/8OUollBjd7A8PTqGdGW vo/ez51KD/xN0gC9nWqeA2KOqQEhh20r1N4ppYQtrgs2wvRIA3ozwZWJFaVOmtMN3Q+2 w+JQ== X-Gm-Message-State: AOJu0Yz2nIKF8B158b704lfNjWCAUPRD/wifZROX7d2PalpzzG4iLXr3 8/0pdln4UWYUagFBXilnaWABR+ELbojOdvmKILZ39FcZ51hwOls/vP78CH2hVsGB X-Gm-Gg: AeBDiesYlC1u6sXL+mKRzbO+0FvLPRx/qObnBWyg/fdC842dc4Dy8tZqOu0CHBJHtzW g4/Z+sjNVnU+JFdYjeDbFj3yBt92n9+vqqY8XMCRgNCzyJkAQLGdqpvEi8nfYos31CLuSZN5lmR JJf9tr/SeImeOBsuzPYwR9iuvnjmDpI9XpaaIoEAHKiakWPbibzhiPt4CBuVklAfERFqA/xc5+d d9cZzOsXrE9p/bUBsWei88RyTB7oLrbvXjsF6XH49FKtqZ9zMMXSv65BXz1cVqEaIMzwBCsAW4A h73gPVAiyNCTV3mCAKn89sWk4Fhzl6xlOlStPLD3VISqQUcN2XOPBJO2E8abOv0R5dN46D/9Bzx 1OA6UJa3VLHT0ki8nX4VmxFaidxqm8x+2gX5aA59VoWlhr14P/m2yHiQd3F+iWwr7lEOnsfSpiB wvO+p8020km6w7TMT8peFM7a7rOy8w2TBi2GyOho1N0gmpAsHNCt+LkCqWaJ0ZStiuHTkhyrTg1 UV0m/ADLnwDc2iM1TrV6g== X-Received: by 2002:a05:600c:42cc:b0:488:ffb1:494c with SMTP id 5b1f17b1804b1-488ffb14a0cmr134853055e9.12.1776810825879; Tue, 21 Apr 2026 15:33:45 -0700 (PDT) Received: from dohko.chello.ie (188-141-5-72.dynamic.upc.ie. [188.141.5.72]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-488fc1c01cfsm413350505e9.10.2026.04.21.15.33.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Apr 2026 15:33:45 -0700 (PDT) From: David Carlier To: mptcp@lists.linux.dev Cc: Matthieu Baerts , Mat Martineau , Geliang Tang , David Carlier Subject: [PATCH mptcp-next v3 3/3] selftests: mptcp: cover IP_RECVERR sockopt propagation Date: Tue, 21 Apr 2026 23:33:38 +0100 Message-ID: <20260421223338.52743-4-devnexen@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260421223338.52743-1-devnexen@gmail.com> References: <20260421223338.52743-1-devnexen@gmail.com> Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Exercise setsockopt/getsockopt of IP_RECVERR and IPV6_RECVERR on the MPTCP parent socket, including the empty-errqueue EAGAIN contract on MSG_ERRQUEUE|MSG_DONTWAIT. End-to-end errqueue delivery (ICMP, TX timestamps, zerocopy) depends on subflow-side producers that are out of scope for this series and will be covered by follow-up work. Assisted-by: Codex:gpt-5 Signed-off-by: David Carlier --- .../selftests/net/mptcp/mptcp_sockopt.c | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/test= ing/selftests/net/mptcp/mptcp_sockopt.c index b6e58d936ebe..95bb2cc8e2ff 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c +++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c @@ -769,6 +769,60 @@ static void test_ip_tos_sockopt(int fd) xerror("expect socklen_t =3D=3D -1"); } =20 +static void test_ip_recverr_sockopt(int fd) +{ + struct iovec iov =3D { + .iov_base =3D &(char){ 0 }, + .iov_len =3D 1, + }; + struct msghdr msg =3D { + .msg_iov =3D &iov, + .msg_iovlen =3D 1, + }; + int one =3D 1, zero =3D 0, val =3D -1; + socklen_t s =3D sizeof(val); + int level, optname, r; + + switch (pf) { + case AF_INET: + level =3D SOL_IP; + optname =3D IP_RECVERR; + break; + case AF_INET6: + level =3D SOL_IPV6; + optname =3D IPV6_RECVERR; + break; + default: + xerror("Unknown pf %d\n", pf); + } + + r =3D setsockopt(fd, level, optname, &one, sizeof(one)); + if (r) + die_perror("setsockopt recverr on"); + + r =3D getsockopt(fd, level, optname, &val, &s); + if (r) + die_perror("getsockopt recverr on"); + if (s !=3D sizeof(val) || val !=3D one) + xerror("recverr on mismatch val=3D%d len=3D%u", val, s); + + r =3D recvmsg(fd, &msg, MSG_ERRQUEUE | MSG_DONTWAIT); + if (r !=3D -1 || errno !=3D EAGAIN) + xerror("expected empty errqueue to return EAGAIN, ret=3D%d errno=3D%d", = r, errno); + + r =3D setsockopt(fd, level, optname, &zero, sizeof(zero)); + if (r) + die_perror("setsockopt recverr off"); + + val =3D -1; + s =3D sizeof(val); + r =3D getsockopt(fd, level, optname, &val, &s); + if (r) + die_perror("getsockopt recverr off"); + if (s !=3D sizeof(val) || val !=3D zero) + xerror("recverr off mismatch val=3D%d len=3D%u", val, s); +} + static int client(int pipefd) { int fd =3D -1; @@ -787,6 +841,7 @@ static int client(int pipefd) } =20 test_ip_tos_sockopt(fd); + test_ip_recverr_sockopt(fd); =20 connect_one_server(fd, pipefd); =20 --=20 2.53.0