From nobody Fri Apr 19 01:05:57 2024 Delivered-To: wpasupplicant.patchew@gmail.com Received: by 2002:a02:1d48:0:0:0:0:0 with SMTP id 69csp2535263jaj; Fri, 17 Sep 2021 16:33:34 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw79WhtMFV5fNOiljUEEdD1G3Vs8kGozc9sYf/Ixs4VnXHCixKyuiM4gZA+swAmQ5cIldnC X-Received: by 2002:aa7:9542:0:b0:434:5a64:bc8 with SMTP id w2-20020aa79542000000b004345a640bc8mr13076803pfq.30.1631921614681; Fri, 17 Sep 2021 16:33:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631921614; cv=none; d=google.com; s=arc-20160816; b=LOk8jMcPaSACq228I35i+aCDvu276DaF8aO5/ToZFa6GsgwiORxNvwffiGwBrKO2h7 p7hNY+jrG43Fh7SF3N8lJ7BANHXk9UPDSeyfbD3t747l5YI3XhqQoF8e6stddnJD/Lo7 ECfA1d97lcGTnoDbmu9+9uc3i5vDJop4q43gIRnZyETq5VkXTwii2AiWjziWuyAqqBYT 6izq4X+Qo0wyky/f8P/N4pMQG4SaFpsba7JM115M9CyKyTISqRsicewsRpu5oJX8XzHC Kc56O64omAF2Y7fVd8f+9amzVxBj2VgR/k7eG1DnzSOBTycxarSOxO+kfUx4obNKmZxm CWkg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=OxHwz4qTAXnsxoXbBNOkcQ5LkOdyHBTdzrW4e/rAlE0=; b=h7B6i8usMVmSMZH2Yu7pG/ssuNkNjBMKYl1wjIkF17M9iqEC9pKLlT7xefA9AUR/wC h6Ho4L1ydOHMFIZ/R1N2aS+ADzB/K40fJjB7v8H3WxHAwwddY7rYilPnxvEMyff/j4ON ndaQhZPiAcDQftlXreXutBXr/zPbmqlPHZixf8QNwcqzaMqkc+ZQKTEHrq4tpvVqBCLA cND/5Cy6Y6Y87xMQVStyehmmRGVUZz6z0atAz2EoW/+7jCygu+ZlVrNhvaGnpn769cfq Ze3mD6528XPqKT0oBgye9h3xGAAIZDuj2wUrYC774c399Ovj27wNxG2n5cu8Bcwm0Frp YjVw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1959-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 2604:1380:1000:8100::1 as permitted sender) smtp.mailfrom="mptcp+bounces-1959-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from sjc.edge.kernel.org (sjc.edge.kernel.org. [2604:1380:1000:8100::1]) by mx.google.com with ESMTPS id q13si9398327plk.433.2021.09.17.16.33.34 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 17 Sep 2021 16:33:34 -0700 (PDT) Received-SPF: pass (google.com: domain of mptcp+bounces-1959-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 2604:1380:1000:8100::1 as permitted sender) client-ip=2604:1380:1000:8100::1; Authentication-Results: mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1959-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 2604:1380:1000:8100::1 as permitted sender) smtp.mailfrom="mptcp+bounces-1959-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sjc.edge.kernel.org (Postfix) with ESMTPS id 428913E10FE for ; Fri, 17 Sep 2021 23:33:34 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 2AAC43FCB; Fri, 17 Sep 2021 23:33:33 +0000 (UTC) X-Original-To: mptcp@lists.linux.dev Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1745A2FB2 for ; Fri, 17 Sep 2021 23:33:32 +0000 (UTC) X-IronPort-AV: E=McAfee;i="6200,9189,10110"; a="209979870" X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="209979870" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:29 -0700 X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="483228556" Received: from mjmartin-desk2.amr.corp.intel.com (HELO mjmartin-desk2.intel.com) ([10.212.205.24]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:29 -0700 From: Mat Martineau To: netdev@vger.kernel.org Cc: Florian Westphal , davem@davemloft.net, kuba@kernel.org, matthieu.baerts@tessares.net, mptcp@lists.linux.dev, Mat Martineau Subject: [PATCH net-next 1/5] mptcp: add new mptcp_fill_diag helper Date: Fri, 17 Sep 2021 16:33:18 -0700 Message-Id: <20210917233322.271789-2-mathew.j.martineau@linux.intel.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210917233322.271789-1-mathew.j.martineau@linux.intel.com> References: <20210917233322.271789-1-mathew.j.martineau@linux.intel.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" From: Florian Westphal Will be re-used from getsockopt path. Since diag can be a module, we can't export the helper from diag, it needs to be moved to core. Signed-off-by: Florian Westphal Signed-off-by: Mat Martineau --- include/net/mptcp.h | 4 ++++ net/mptcp/mptcp_diag.c | 26 +------------------------- net/mptcp/sockopt.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/include/net/mptcp.h b/include/net/mptcp.h index 6026bbefbffd..f83fa48408b3 100644 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@ -12,6 +12,8 @@ #include #include =20 +struct mptcp_info; +struct mptcp_sock; struct seq_file; =20 /* MPTCP sk_buff extension data */ @@ -121,6 +123,8 @@ bool mptcp_incoming_options(struct sock *sk, struct sk_= buff *skb); void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, struct mptcp_out_options *opts); =20 +void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info); + /* move the skb extension owership, with the assumption that 'to' is * newly allocated */ diff --git a/net/mptcp/mptcp_diag.c b/net/mptcp/mptcp_diag.c index f48eb6315bbb..fdf0c1f15a65 100644 --- a/net/mptcp/mptcp_diag.c +++ b/net/mptcp/mptcp_diag.c @@ -113,37 +113,13 @@ static void mptcp_diag_get_info(struct sock *sk, stru= ct inet_diag_msg *r, { struct mptcp_sock *msk =3D mptcp_sk(sk); struct mptcp_info *info =3D _info; - u32 flags =3D 0; - bool slow; - u8 val; =20 r->idiag_rqueue =3D sk_rmem_alloc_get(sk); r->idiag_wqueue =3D sk_wmem_alloc_get(sk); if (!info) return; =20 - slow =3D lock_sock_fast(sk); - info->mptcpi_subflows =3D READ_ONCE(msk->pm.subflows); - info->mptcpi_add_addr_signal =3D READ_ONCE(msk->pm.add_addr_signaled); - info->mptcpi_add_addr_accepted =3D READ_ONCE(msk->pm.add_addr_accepted); - info->mptcpi_local_addr_used =3D READ_ONCE(msk->pm.local_addr_used); - info->mptcpi_subflows_max =3D mptcp_pm_get_subflows_max(msk); - val =3D mptcp_pm_get_add_addr_signal_max(msk); - info->mptcpi_add_addr_signal_max =3D val; - val =3D mptcp_pm_get_add_addr_accept_max(msk); - info->mptcpi_add_addr_accepted_max =3D val; - info->mptcpi_local_addr_max =3D mptcp_pm_get_local_addr_max(msk); - if (test_bit(MPTCP_FALLBACK_DONE, &msk->flags)) - flags |=3D MPTCP_INFO_FLAG_FALLBACK; - if (READ_ONCE(msk->can_ack)) - flags |=3D MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED; - info->mptcpi_flags =3D flags; - info->mptcpi_token =3D READ_ONCE(msk->token); - info->mptcpi_write_seq =3D READ_ONCE(msk->write_seq); - info->mptcpi_snd_una =3D READ_ONCE(msk->snd_una); - info->mptcpi_rcv_nxt =3D READ_ONCE(msk->ack_seq); - info->mptcpi_csum_enabled =3D READ_ONCE(msk->csum_enabled); - unlock_sock_fast(sk, slow); + mptcp_diag_fill_info(msk, info); } =20 static const struct inet_diag_handler mptcp_diag_handler =3D { diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index 8c03afac5ca0..54f0d521a399 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -670,6 +670,38 @@ static int mptcp_getsockopt_first_sf_only(struct mptcp= _sock *msk, int level, int return ret; } =20 +void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info) +{ + struct sock *sk =3D &msk->sk.icsk_inet.sk; + bool slow =3D lock_sock_fast(sk); + u32 flags =3D 0; + u8 val; + + info->mptcpi_subflows =3D READ_ONCE(msk->pm.subflows); + info->mptcpi_add_addr_signal =3D READ_ONCE(msk->pm.add_addr_signaled); + info->mptcpi_add_addr_accepted =3D READ_ONCE(msk->pm.add_addr_accepted); + info->mptcpi_local_addr_used =3D READ_ONCE(msk->pm.local_addr_used); + info->mptcpi_subflows_max =3D mptcp_pm_get_subflows_max(msk); + val =3D mptcp_pm_get_add_addr_signal_max(msk); + info->mptcpi_add_addr_signal_max =3D val; + val =3D mptcp_pm_get_add_addr_accept_max(msk); + info->mptcpi_add_addr_accepted_max =3D val; + info->mptcpi_local_addr_max =3D mptcp_pm_get_local_addr_max(msk); + if (test_bit(MPTCP_FALLBACK_DONE, &msk->flags)) + flags |=3D MPTCP_INFO_FLAG_FALLBACK; + if (READ_ONCE(msk->can_ack)) + flags |=3D MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED; + info->mptcpi_flags =3D flags; + info->mptcpi_token =3D READ_ONCE(msk->token); + info->mptcpi_write_seq =3D READ_ONCE(msk->write_seq); + info->mptcpi_snd_una =3D READ_ONCE(msk->snd_una); + info->mptcpi_rcv_nxt =3D READ_ONCE(msk->ack_seq); + info->mptcpi_csum_enabled =3D READ_ONCE(msk->csum_enabled); + + unlock_sock_fast(sk, slow); +} +EXPORT_SYMBOL_GPL(mptcp_diag_fill_info); + static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname, char __user *optval, int __user *optlen) { --=20 2.33.0 From nobody Fri Apr 19 01:05:57 2024 Delivered-To: wpasupplicant.patchew@gmail.com Received: by 2002:a02:1d48:0:0:0:0:0 with SMTP id 69csp2535271jaj; Fri, 17 Sep 2021 16:33:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz5+4/bmALPzlKrk1U4jVQQSpGruywA6UCblIXdRtqCPzc71XFlSX/nKbQpksGN1SXUYdrB X-Received: by 2002:a05:6214:1430:: with SMTP id o16mr10938477qvx.66.1631921616222; Fri, 17 Sep 2021 16:33:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631921616; cv=none; d=google.com; s=arc-20160816; b=TtyTNcDg0K6+O4ix0FbSHHkk6i3NT55AiT2f0Qrl4npJoqpzm3H/vGe5z8xlgsOY0V sN5sM4oOh9LQNgWl0qh/kQAeuPfnab/fCa7XlSCnfRWWKdn14iLOi4QT+a0GKJfCyWIK puS+zUdMsQXxfCW2Xk9oeqYSusHATjI5qtrvMQYE3ualveJpeJWinioyIHF/kiTMhg0r V9XirBTNn9zCgOQh2STewNqwl6OOUAg959uvHKXH9dV7jIL0TEfjraAn+32k53jBPzHY vxz9DJdAq5e95Gp1poC057OPkH3VazIaTm3hd3W0oool+U7ZqoP5LCRCIKyaaECep0Ac XV/A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=h6hB24b4/LNWijJ7zqidh1EVY+gU8XgLr8V9NkF8oIo=; b=1IlDYvRlhWuto7H8rmtu+mBper1lkQClyiYEMIiukr5veYuuRhCvJb896607EANb+/ fPha4iTKBh1nUigOjDlhWLTS5/i8UlbNy5NeKrJYDXnSgf8HAy27hUtLAc94Yj/BI6uk l4YuBE7n6PuyYW+LhrK5rMIDS94FDUAiobt0c0R6wur3nA8jWhWbHpGAMz+LEenyHy7H SkUR6qFqSrVVBijciua53maUjJT4Z88j63I9oq/xjMEQS0silV2Seca53LVCD1o1v7Yk WgpbrQziw2ehOHez3vCciEmRfJ5X+UWD7AODn8nWPKoZe5Vkj/yl/pnwxKcCT2Zia7HN 5SVA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1960-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) smtp.mailfrom="mptcp+bounces-1960-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from ewr.edge.kernel.org (ewr.edge.kernel.org. [147.75.197.195]) by mx.google.com with ESMTPS id c6si3013406qtg.301.2021.09.17.16.33.36 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 17 Sep 2021 16:33:36 -0700 (PDT) Received-SPF: pass (google.com: domain of mptcp+bounces-1960-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) client-ip=147.75.197.195; Authentication-Results: mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1960-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) smtp.mailfrom="mptcp+bounces-1960-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ewr.edge.kernel.org (Postfix) with ESMTPS id DAE431C0A4B for ; Fri, 17 Sep 2021 23:33:35 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 544613FCE; Fri, 17 Sep 2021 23:33:33 +0000 (UTC) X-Original-To: mptcp@lists.linux.dev Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 324872FB6 for ; Fri, 17 Sep 2021 23:33:32 +0000 (UTC) X-IronPort-AV: E=McAfee;i="6200,9189,10110"; a="209979872" X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="209979872" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:30 -0700 X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="483228557" Received: from mjmartin-desk2.amr.corp.intel.com (HELO mjmartin-desk2.intel.com) ([10.212.205.24]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:29 -0700 From: Mat Martineau To: netdev@vger.kernel.org Cc: Florian Westphal , davem@davemloft.net, kuba@kernel.org, matthieu.baerts@tessares.net, mptcp@lists.linux.dev, Mat Martineau Subject: [PATCH net-next 2/5] mptcp: add MPTCP_INFO getsockopt Date: Fri, 17 Sep 2021 16:33:19 -0700 Message-Id: <20210917233322.271789-3-mathew.j.martineau@linux.intel.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210917233322.271789-1-mathew.j.martineau@linux.intel.com> References: <20210917233322.271789-1-mathew.j.martineau@linux.intel.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" From: Florian Westphal Its not compatible with multipath-tcp.org kernel one. 1. The out-of-tree implementation defines a different 'struct mptcp_info', with embedded __user addresses for additional data such as endpoint addresses. 2. Mat Martineau points out that embedded __user addresses doesn't work with BPF_CGROUP_RUN_PROG_GETSOCKOPT() which assumes that copying in optsize bytes from optval provides all data that got copied to userspace. This provides mptcp_info data for the given mptcp socket. Userspace sets optlen to the size of the structure it expects. The kernel updates it to contain the number of bytes that it copied. This allows to append more information to the structure later. Signed-off-by: Florian Westphal Signed-off-by: Mat Martineau --- include/linux/socket.h | 1 + include/uapi/linux/mptcp.h | 3 +++ net/mptcp/sockopt.c | 40 +++++++++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/linux/socket.h b/include/linux/socket.h index 041d6032a348..7612d760b6a9 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -364,6 +364,7 @@ struct ucred { #define SOL_KCM 281 #define SOL_TLS 282 #define SOL_XDP 283 +#define SOL_MPTCP 284 =20 /* IPX options */ #define IPX_TYPE 1 diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h index f66038b9551f..3e9caeddda7e 100644 --- a/include/uapi/linux/mptcp.h +++ b/include/uapi/linux/mptcp.h @@ -193,4 +193,7 @@ enum mptcp_event_attr { #define MPTCP_RST_EBADPERF 5 #define MPTCP_RST_EMIDDLEBOX 6 =20 +/* MPTCP socket options */ +#define MPTCP_INFO 1 + #endif /* _UAPI_MPTCP_H */ diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index 54f0d521a399..f7683c22911f 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -673,10 +673,14 @@ static int mptcp_getsockopt_first_sf_only(struct mptc= p_sock *msk, int level, int void mptcp_diag_fill_info(struct mptcp_sock *msk, struct mptcp_info *info) { struct sock *sk =3D &msk->sk.icsk_inet.sk; - bool slow =3D lock_sock_fast(sk); u32 flags =3D 0; + bool slow; u8 val; =20 + memset(info, 0, sizeof(*info)); + + slow =3D lock_sock_fast(sk); + info->mptcpi_subflows =3D READ_ONCE(msk->pm.subflows); info->mptcpi_add_addr_signal =3D READ_ONCE(msk->pm.add_addr_signaled); info->mptcpi_add_addr_accepted =3D READ_ONCE(msk->pm.add_addr_accepted); @@ -702,6 +706,27 @@ void mptcp_diag_fill_info(struct mptcp_sock *msk, stru= ct mptcp_info *info) } EXPORT_SYMBOL_GPL(mptcp_diag_fill_info); =20 +static int mptcp_getsockopt_info(struct mptcp_sock *msk, char __user *optv= al, int __user *optlen) +{ + struct mptcp_info m_info; + int len; + + if (get_user(len, optlen)) + return -EFAULT; + + len =3D min_t(unsigned int, len, sizeof(struct mptcp_info)); + + mptcp_diag_fill_info(msk, &m_info); + + if (put_user(len, optlen)) + return -EFAULT; + + if (copy_to_user(optval, &m_info, len)) + return -EFAULT; + + return 0; +} + static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname, char __user *optval, int __user *optlen) { @@ -716,6 +741,17 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock = *msk, int optname, return -EOPNOTSUPP; } =20 +static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock *msk, int optname, + char __user *optval, int __user *optlen) +{ + switch (optname) { + case MPTCP_INFO: + return mptcp_getsockopt_info(msk, optval, optlen); + } + + return -EOPNOTSUPP; +} + int mptcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *option) { @@ -738,6 +774,8 @@ int mptcp_getsockopt(struct sock *sk, int level, int op= tname, =20 if (level =3D=3D SOL_TCP) return mptcp_getsockopt_sol_tcp(msk, optname, optval, option); + if (level =3D=3D SOL_MPTCP) + return mptcp_getsockopt_sol_mptcp(msk, optname, optval, option); return -EOPNOTSUPP; } =20 --=20 2.33.0 From nobody Fri Apr 19 01:05:57 2024 Delivered-To: wpasupplicant.patchew@gmail.com Received: by 2002:a02:1d48:0:0:0:0:0 with SMTP id 69csp2535284jaj; Fri, 17 Sep 2021 16:33:37 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyxVfPMYV9gbaGMl1TjGyG0iRVZm9EzCWiWTbgTcVw5XoSbeE0XiHgVpPB5TweaIYY25Rja X-Received: by 2002:ac8:5912:: with SMTP id 18mr13002482qty.212.1631921617342; Fri, 17 Sep 2021 16:33:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631921617; cv=none; d=google.com; s=arc-20160816; b=W4bjN5hXhJ980mElzhwLKnJ/SgISwrMjt5D4d50DCeuFYIzMGkNiyMwImwHJAWG7o0 dEavJR/VC9tuZp1ig86FI/9M4i6yGdULW+wAPA5qlf33rIYU3/7jisE2/Bm110AT7nza HiN+/ARTN3yMSYL9dpNEIvyQXdVuWJZnVNJTXbwSdp1lvV9P8rdYL3LGszHaQZk+vAUW T40lqYIv2zbOxginRDIOfHV9kCrhmLGNsAsdSTODcC93uerl1bbtetLCkdzNqitpZzBp Vkiu/LSFkl/WO7rrY/7rPWs/k/T82fhXEURRakGYxt8DuqEL1XijnE/UiHU4/mW6PMa6 NanA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=Q76kl/UKr7GWzBqlSwAOOVnYsMmgJcu+bob0lAoe/k8=; b=LEUmf1VL2Iodt/geoQCNgEEyU3715il03HVT5BtOIl+pYbRKysCB9rcyxwKdtYWS4x M4HJi2+WbrioiwOUsDc5zP7yy4C8RksmG27LFmZxDJGPwys9a6x69LHrzglEKjO33xtr Z08u185p5dL/MYVjANgtPd0r3/nUXL4uNHvpuQREnbgm1rOjymIcQ0PEq2/9oasNH4OH tXR/UXWSobOE2Gn4bEUTkxgjpdf7iU1pOaZ9Brwuq6ljXuJGEa6SYeXwdnaqSUOB4A7w cna33Xy5CPa9QU+8ma8Wy1A2KBWpkwnW8zTwnoM6g+aD0sE7JlAAQCSTv/2UMasM2IHp U+KQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1961-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) smtp.mailfrom="mptcp+bounces-1961-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from ewr.edge.kernel.org (ewr.edge.kernel.org. [147.75.197.195]) by mx.google.com with ESMTPS id c6si3013406qtg.301.2021.09.17.16.33.37 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 17 Sep 2021 16:33:37 -0700 (PDT) Received-SPF: pass (google.com: domain of mptcp+bounces-1961-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) client-ip=147.75.197.195; Authentication-Results: mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1961-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) smtp.mailfrom="mptcp+bounces-1961-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ewr.edge.kernel.org (Postfix) with ESMTPS id 158FF1C0F96 for ; Fri, 17 Sep 2021 23:33:37 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5DE763FD4; Fri, 17 Sep 2021 23:33:34 +0000 (UTC) X-Original-To: mptcp@lists.linux.dev Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 236163FC9 for ; Fri, 17 Sep 2021 23:33:33 +0000 (UTC) X-IronPort-AV: E=McAfee;i="6200,9189,10110"; a="209979873" X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="209979873" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:30 -0700 X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="483228559" Received: from mjmartin-desk2.amr.corp.intel.com (HELO mjmartin-desk2.intel.com) ([10.212.205.24]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:30 -0700 From: Mat Martineau To: netdev@vger.kernel.org Cc: Florian Westphal , davem@davemloft.net, kuba@kernel.org, matthieu.baerts@tessares.net, mptcp@lists.linux.dev, Mat Martineau Subject: [PATCH net-next 3/5] mptcp: add MPTCP_TCPINFO getsockopt support Date: Fri, 17 Sep 2021 16:33:20 -0700 Message-Id: <20210917233322.271789-4-mathew.j.martineau@linux.intel.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210917233322.271789-1-mathew.j.martineau@linux.intel.com> References: <20210917233322.271789-1-mathew.j.martineau@linux.intel.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" From: Florian Westphal Allow users to retrieve TCP_INFO data of all subflows. Users need to pre-initialize a meta header that has to be prepended to the data buffer that will be filled with the tcp info data. The meta header looks like this: struct mptcp_subflow_data { __u32 size_subflow_data;/* size of this structure in userspace */ __u32 num_subflows; /* must be 0, set by kernel */ __u32 size_kernel; /* must be 0, set by kernel */ __u32 size_user; /* size of one element in data[] */ } __attribute__((aligned(8))); size_subflow_data has to be set to 'sizeof(struct mptcp_subflow_data)'. This allows to extend mptcp_subflow_data structure later on without breaking backwards compatibility. If the structure is extended later on, kernel knows where the userspace-provided meta header ends, even if userspace uses an older (smaller) version of the structure. num_subflows must be set to 0. If the getsockopt request succeeds (return value is 0), it will be updated to contain the number of active subflows for the given logical connection. size_kernel must be set to 0. If the getsockopt request is successful, it will contain the size of the 'struct tcp_info' as known by the kernel. This is informational only. size_user must be set to 'sizeof(struct tcp_info)'. This allows the kernel to only fill in the space reserved/expected by userspace. Example: struct my_tcp_info { struct mptcp_subflow_data d; struct tcp_info ti[2]; }; struct my_tcp_info ti; socklen_t olen; memset(&ti, 0, sizeof(ti)); ti.d.size_subflow_data =3D sizeof(struct mptcp_subflow_data); ti.d.size_user =3D sizeof(struct tcp_info); olen =3D sizeof(ti); ret =3D getsockopt(fd, SOL_MPTCP, MPTCP_TCPINFO, &ti, &olen); if (ret < 0) die_perror("getsockopt MPTCP_TCPINFO"); mptcp_subflow_data.num_subflows is populated with the number of subflows that exist on the kernel side for the logical mptcp connection. This allows userspace to re-try with a larger tcp_info array if the number of subflows was larger than the available space in the ti[] array. olen has to be set to the number of bytes that userspace has allocated to receive the kernel data. It will be updated to contain the real number bytes that have been copied to by the kernel. In the above example, if the number if subflows was 1, olen is equal to 'sizeof(struct mptcp_subflow_data) + sizeof(struct tcp_info). For 2 or more subflows olen is equal to 'sizeof(struct my_tcp_info)'. If there was more data that could not be copied due to lack of space in the option buffer, userspace can detect this by checking mptcp_subflow_data->num_subflows. Signed-off-by: Florian Westphal Signed-off-by: Mat Martineau --- include/uapi/linux/mptcp.h | 10 +++- net/mptcp/sockopt.c | 115 +++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h index 3e9caeddda7e..3f013a513770 100644 --- a/include/uapi/linux/mptcp.h +++ b/include/uapi/linux/mptcp.h @@ -193,7 +193,15 @@ enum mptcp_event_attr { #define MPTCP_RST_EBADPERF 5 #define MPTCP_RST_EMIDDLEBOX 6 =20 +struct mptcp_subflow_data { + __u32 size_subflow_data; /* size of this structure in userspace */ + __u32 num_subflows; /* must be 0, set by kernel */ + __u32 size_kernel; /* must be 0, set by kernel */ + __u32 size_user; /* size of one element in data[] */ +} __attribute__((aligned(8))); + /* MPTCP socket options */ -#define MPTCP_INFO 1 +#define MPTCP_INFO 1 +#define MPTCP_TCPINFO 2 =20 #endif /* _UAPI_MPTCP_H */ diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index f7683c22911f..eb2905bfa089 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -14,6 +14,8 @@ #include #include "protocol.h" =20 +#define MIN_INFO_OPTLEN_SIZE 16 + static struct sock *__mptcp_tcp_fallback(struct mptcp_sock *msk) { sock_owned_by_me((const struct sock *)msk); @@ -727,6 +729,117 @@ static int mptcp_getsockopt_info(struct mptcp_sock *m= sk, char __user *optval, in return 0; } =20 +static int mptcp_put_subflow_data(struct mptcp_subflow_data *sfd, + char __user *optval, + u32 copied, + int __user *optlen) +{ + u32 copylen =3D min_t(u32, sfd->size_subflow_data, sizeof(*sfd)); + + if (copied) + copied +=3D sfd->size_subflow_data; + else + copied =3D copylen; + + if (put_user(copied, optlen)) + return -EFAULT; + + if (copy_to_user(optval, sfd, copylen)) + return -EFAULT; + + return 0; +} + +static int mptcp_get_subflow_data(struct mptcp_subflow_data *sfd, + char __user *optval, int __user *optlen) +{ + int len, copylen; + + if (get_user(len, optlen)) + return -EFAULT; + + /* if mptcp_subflow_data size is changed, need to adjust + * this function to deal with programs using old version. + */ + BUILD_BUG_ON(sizeof(*sfd) !=3D MIN_INFO_OPTLEN_SIZE); + + if (len < MIN_INFO_OPTLEN_SIZE) + return -EINVAL; + + memset(sfd, 0, sizeof(*sfd)); + + copylen =3D min_t(unsigned int, len, sizeof(*sfd)); + if (copy_from_user(sfd, optval, copylen)) + return -EFAULT; + + /* size_subflow_data is u32, but len is signed */ + if (sfd->size_subflow_data > INT_MAX || + sfd->size_user > INT_MAX) + return -EINVAL; + + if (sfd->size_subflow_data < MIN_INFO_OPTLEN_SIZE || + sfd->size_subflow_data > len) + return -EINVAL; + + if (sfd->num_subflows || sfd->size_kernel) + return -EINVAL; + + return len - sfd->size_subflow_data; +} + +static int mptcp_getsockopt_tcpinfo(struct mptcp_sock *msk, char __user *o= ptval, + int __user *optlen) +{ + struct mptcp_subflow_context *subflow; + struct sock *sk =3D &msk->sk.icsk_inet.sk; + unsigned int sfcount =3D 0, copied =3D 0; + struct mptcp_subflow_data sfd; + char __user *infoptr; + int len; + + len =3D mptcp_get_subflow_data(&sfd, optval, optlen); + if (len < 0) + return len; + + sfd.size_kernel =3D sizeof(struct tcp_info); + sfd.size_user =3D min_t(unsigned int, sfd.size_user, + sizeof(struct tcp_info)); + + infoptr =3D optval + sfd.size_subflow_data; + + lock_sock(sk); + + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + + ++sfcount; + + if (len && len >=3D sfd.size_user) { + struct tcp_info info; + + tcp_get_info(ssk, &info); + + if (copy_to_user(infoptr, &info, sfd.size_user)) { + release_sock(sk); + return -EFAULT; + } + + infoptr +=3D sfd.size_user; + copied +=3D sfd.size_user; + len -=3D sfd.size_user; + } + } + + release_sock(sk); + + sfd.num_subflows =3D sfcount; + + if (mptcp_put_subflow_data(&sfd, optval, copied, optlen)) + return -EFAULT; + + return 0; +} + static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname, char __user *optval, int __user *optlen) { @@ -747,6 +860,8 @@ static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock= *msk, int optname, switch (optname) { case MPTCP_INFO: return mptcp_getsockopt_info(msk, optval, optlen); + case MPTCP_TCPINFO: + return mptcp_getsockopt_tcpinfo(msk, optval, optlen); } =20 return -EOPNOTSUPP; --=20 2.33.0 From nobody Fri Apr 19 01:05:57 2024 Delivered-To: wpasupplicant.patchew@gmail.com Received: by 2002:a02:1d48:0:0:0:0:0 with SMTP id 69csp2535319jaj; Fri, 17 Sep 2021 16:33:40 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyfeuFq9aYNUqG1ZOyU68ednGJTt/7WkUa7tpjW6PVlscvvbuSRjbWN7tsZ+p8ex46hXCaP X-Received: by 2002:a17:902:a9c6:b0:13c:a9b5:2896 with SMTP id b6-20020a170902a9c600b0013ca9b52896mr7595090plr.67.1631921620089; Fri, 17 Sep 2021 16:33:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631921620; cv=none; d=google.com; s=arc-20160816; b=Q0T6xUbIDb328AJ39f0/gSHlMsMTidsYINNZwruoTNZ+OYoGe60fjwLdlEm2R021sk DnDSknoVYEVXI08iLAWvcOOP/Xm+7r+xEvY3tRDWncy6GiY7BoJCcQKb5fhaYlvWUAoP q4UfYapW3drly0lHyxYRu/hha9PKQUq0bkgdcaI0ao8m3+aDL9gY8cp0nQ7DpXAZg96R Qgo/OQylf3NIw228THYasEJzC+bVtxnhV9ufGxJ31iHMi996Sqr23LsTRNP03ChuaL6U wGsgzOP4FNFiADbr3RlCDW5Bk5XnqMxi5bHPWukA4rmEExzYsWK7eeLQGJih4g753Blv QFnQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=3q+el31MklYI3QACrnAve0TI4lYbBbed4NF+9qTtJqE=; b=OEioyl/av0fAmA+VFRFO1H8ZJNP1bnyHN8ihmMCfzP7onJZiZap+5ioVjU0uhrepXd +YpiGfanb93TSnDst6oUmxIR+Vvxj7shsTzbkO29yMS7T4fXj5a3ylZvU5KZxldKeR1Q JoelajMNfoIoJ3VhU12zzpl/iX/pm1TzDZH3WF4ooGD4pUxFmj70dSX6oPHnio7iSx4b ONf33Du2rNhMx2nh6tE1rxSY1kti7SplEB71pxq/cj5UczMr9UjQl8dM2z3VMFs7rdLE teuqJ1U+IPTQN/VD6LKAAgRsKSoFUWdc1ufaJsRQzCnbIExR23PGNpihKD3lLruZdjdQ gdeQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1963-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 2604:1380:1000:8100::1 as permitted sender) smtp.mailfrom="mptcp+bounces-1963-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from sjc.edge.kernel.org (sjc.edge.kernel.org. [2604:1380:1000:8100::1]) by mx.google.com with ESMTPS id o11si15630465pjm.56.2021.09.17.16.33.39 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 17 Sep 2021 16:33:40 -0700 (PDT) Received-SPF: pass (google.com: domain of mptcp+bounces-1963-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 2604:1380:1000:8100::1 as permitted sender) client-ip=2604:1380:1000:8100::1; Authentication-Results: mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1963-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 2604:1380:1000:8100::1 as permitted sender) smtp.mailfrom="mptcp+bounces-1963-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sjc.edge.kernel.org (Postfix) with ESMTPS id 506773E11A4 for ; Fri, 17 Sep 2021 23:33:39 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 88DA53FCB; Fri, 17 Sep 2021 23:33:35 +0000 (UTC) X-Original-To: mptcp@lists.linux.dev Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 38F633FCC for ; Fri, 17 Sep 2021 23:33:33 +0000 (UTC) X-IronPort-AV: E=McAfee;i="6200,9189,10110"; a="209979874" X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="209979874" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:30 -0700 X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="483228560" Received: from mjmartin-desk2.amr.corp.intel.com (HELO mjmartin-desk2.intel.com) ([10.212.205.24]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:30 -0700 From: Mat Martineau To: netdev@vger.kernel.org Cc: Florian Westphal , davem@davemloft.net, kuba@kernel.org, matthieu.baerts@tessares.net, mptcp@lists.linux.dev, Mat Martineau Subject: [PATCH net-next 4/5] mptcp: add MPTCP_SUBFLOW_ADDRS getsockopt support Date: Fri, 17 Sep 2021 16:33:21 -0700 Message-Id: <20210917233322.271789-5-mathew.j.martineau@linux.intel.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210917233322.271789-1-mathew.j.martineau@linux.intel.com> References: <20210917233322.271789-1-mathew.j.martineau@linux.intel.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" From: Florian Westphal This retrieves the address pairs of all subflows currently active for a given mptcp connection. It re-uses the same meta-header as for MPTCP_TCPINFO. A new structure is provided to hold the subflow address data: struct mptcp_subflow_addrs { union { __kernel_sa_family_t sa_family; struct sockaddr sa_local; struct sockaddr_in sin_local; struct sockaddr_in6 sin6_local; struct sockaddr_storage ss_local; }; union { struct sockaddr sa_remote; struct sockaddr_in sin_remote; struct sockaddr_in6 sin6_remote; struct sockaddr_storage ss_remote; }; }; Usage of the new getsockopt is very similar to MPTCP_TCPINFO one. Userspace allocates a 'struct mptcp_subflow_data', followed by one or more 'struct mptcp_subflow_addrs', then inits the mptcp_subflow_data structure as follows: struct mptcp_subflow_addrs *sf_addr; struct mptcp_subflow_data *addr; socklen_t olen =3D sizeof(*addr) + (8 * sizeof(*sf_addr)); addr =3D malloc(olen); addr->size_subflow_data =3D sizeof(*addr); addr->num_subflows =3D 0; addr->size_kernel =3D 0; addr->size_user =3D sizeof(struct mptcp_subflow_addrs); sf_addr =3D (struct mptcp_subflow_addrs *)(addr + 1); and then retrieves the endpoint addresses via: ret =3D getsockopt(fd, SOL_MPTCP, MPTCP_SUBFLOW_ADDRS, addr, &olen); If the call succeeds, kernel will have added up to 8 endpoint addresses after the 'mptcp_subflow_data' header. Userspace needs to re-check 'olen' value to detect how many bytes have been filled in by the kernel. Userspace can check addr->num_subflows to discover when there were more subflows that available data space. Co-developed-by: Matthieu Baerts Signed-off-by: Matthieu Baerts Signed-off-by: Florian Westphal Signed-off-by: Mat Martineau --- include/uapi/linux/mptcp.h | 24 ++++++++++ net/mptcp/sockopt.c | 91 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h index 3f013a513770..c8cc46f80a16 100644 --- a/include/uapi/linux/mptcp.h +++ b/include/uapi/linux/mptcp.h @@ -4,6 +4,13 @@ =20 #include #include +#include /* for sockaddr_in */ +#include /* for sockaddr_in6 */ +#include /* for sockaddr_storage and sa_family */ + +#ifndef __KERNEL__ +#include /* for struct sockaddr */ +#endif =20 #define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) #define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) @@ -200,8 +207,25 @@ struct mptcp_subflow_data { __u32 size_user; /* size of one element in data[] */ } __attribute__((aligned(8))); =20 +struct mptcp_subflow_addrs { + union { + __kernel_sa_family_t sa_family; + struct sockaddr sa_local; + struct sockaddr_in sin_local; + struct sockaddr_in6 sin6_local; + struct __kernel_sockaddr_storage ss_local; + }; + union { + struct sockaddr sa_remote; + struct sockaddr_in sin_remote; + struct sockaddr_in6 sin6_remote; + struct __kernel_sockaddr_storage ss_remote; + }; +}; + /* MPTCP socket options */ #define MPTCP_INFO 1 #define MPTCP_TCPINFO 2 +#define MPTCP_SUBFLOW_ADDRS 3 =20 #endif /* _UAPI_MPTCP_H */ diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index eb2905bfa089..8137cc3a4296 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -840,6 +840,95 @@ static int mptcp_getsockopt_tcpinfo(struct mptcp_sock = *msk, char __user *optval, return 0; } =20 +static void mptcp_get_sub_addrs(const struct sock *sk, struct mptcp_subflo= w_addrs *a) +{ + struct inet_sock *inet =3D inet_sk(sk); + + memset(a, 0, sizeof(*a)); + + if (sk->sk_family =3D=3D AF_INET) { + a->sin_local.sin_family =3D AF_INET; + a->sin_local.sin_port =3D inet->inet_sport; + a->sin_local.sin_addr.s_addr =3D inet->inet_rcv_saddr; + + if (!a->sin_local.sin_addr.s_addr) + a->sin_local.sin_addr.s_addr =3D inet->inet_saddr; + + a->sin_remote.sin_family =3D AF_INET; + a->sin_remote.sin_port =3D inet->inet_dport; + a->sin_remote.sin_addr.s_addr =3D inet->inet_daddr; +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family =3D=3D AF_INET6) { + const struct ipv6_pinfo *np =3D inet6_sk(sk); + + a->sin6_local.sin6_family =3D AF_INET6; + a->sin6_local.sin6_port =3D inet->inet_sport; + + if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) + a->sin6_local.sin6_addr =3D np->saddr; + else + a->sin6_local.sin6_addr =3D sk->sk_v6_rcv_saddr; + + a->sin6_remote.sin6_family =3D AF_INET6; + a->sin6_remote.sin6_port =3D inet->inet_dport; + a->sin6_remote.sin6_addr =3D sk->sk_v6_daddr; +#endif + } +} + +static int mptcp_getsockopt_subflow_addrs(struct mptcp_sock *msk, char __u= ser *optval, + int __user *optlen) +{ + struct sock *sk =3D &msk->sk.icsk_inet.sk; + struct mptcp_subflow_context *subflow; + unsigned int sfcount =3D 0, copied =3D 0; + struct mptcp_subflow_data sfd; + char __user *addrptr; + int len; + + len =3D mptcp_get_subflow_data(&sfd, optval, optlen); + if (len < 0) + return len; + + sfd.size_kernel =3D sizeof(struct mptcp_subflow_addrs); + sfd.size_user =3D min_t(unsigned int, sfd.size_user, + sizeof(struct mptcp_subflow_addrs)); + + addrptr =3D optval + sfd.size_subflow_data; + + lock_sock(sk); + + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk =3D mptcp_subflow_tcp_sock(subflow); + + ++sfcount; + + if (len && len >=3D sfd.size_user) { + struct mptcp_subflow_addrs a; + + mptcp_get_sub_addrs(ssk, &a); + + if (copy_to_user(addrptr, &a, sfd.size_user)) { + release_sock(sk); + return -EFAULT; + } + + addrptr +=3D sfd.size_user; + copied +=3D sfd.size_user; + len -=3D sfd.size_user; + } + } + + release_sock(sk); + + sfd.num_subflows =3D sfcount; + + if (mptcp_put_subflow_data(&sfd, optval, copied, optlen)) + return -EFAULT; + + return 0; +} + static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname, char __user *optval, int __user *optlen) { @@ -862,6 +951,8 @@ static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock= *msk, int optname, return mptcp_getsockopt_info(msk, optval, optlen); case MPTCP_TCPINFO: return mptcp_getsockopt_tcpinfo(msk, optval, optlen); + case MPTCP_SUBFLOW_ADDRS: + return mptcp_getsockopt_subflow_addrs(msk, optval, optlen); } =20 return -EOPNOTSUPP; --=20 2.33.0 From nobody Fri Apr 19 01:05:57 2024 Delivered-To: wpasupplicant.patchew@gmail.com Received: by 2002:a02:1d48:0:0:0:0:0 with SMTP id 69csp2535305jaj; Fri, 17 Sep 2021 16:33:38 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxfjf5FkSJUlFq7pEICevluo7q0UbDcAYhYcrEw1r2Xe/Mq8g1OvuoAEjCMT0X1pzHti9Ei X-Received: by 2002:a05:620a:13bb:: with SMTP id m27mr10020975qki.430.1631921618672; Fri, 17 Sep 2021 16:33:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631921618; cv=none; d=google.com; s=arc-20160816; b=0YgPlcbKXuyKsjfqpUcenZlahL82W+UuRkHpLXOo5RLPFAmAaSTzCu7AI5nNUHVExY nbRjw6A0r94iznXvelw+XlWvmnIRDhb3KezjcnunH9dlvuqvYJEFlL6NLuDaAuCdHCTu jSsdOyNA1BvNMLg8sS4jP19CvG8NtU/4WEKSuFrCxz04bdZ9e8+1z0J9B91xiFxVcFeM omzwPrVu0My9lVRETTOgmFgtbMKE0F8InTbD3xJ8rnA8SYcH2hXZx+bGNxOYCT/CFSMs gW46V87Qh0RkAowrdYASa2b8bN91S1Vp6SFzuYTxzd/dtXNDXFWgwCizdqzvBGeYj5ns Z06A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from; bh=q8xV5IpQhHdcYQzgaQdXhxcAZSYRnYTr+prz1TgsAks=; b=CEQVTXnstFTWhe02S8lFW08pKcuZ/UNSTlN0vAINa4ksWk8Ga3KnVe2WIYQs+gTa0Q jt7nK1Ly3vUtpQQrvBdAnFe10Mv1UlTtCSlecgRaXAsprI3at0ChJz1reFJRa9QdFlN3 gRitcIu1TXjYDyLVd7XMODkIEVUVPyUSXp4ln10KhmyIN1Ic/n8k4Q0fFXbbb6MgxaQO 48yZxdHcHN9D21Mpf9DNkvrEIfyOK/cYCOwqzz4JBm0XY/MVUApBjFlkNH1pbGsp+YiG 5SiztqWfCSwVY+ebLOx+gU91qmG+ZDgX8E1C5yDhWJufuypY10yiKRWLzTFI1AcCy49h 5Xuw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1962-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) smtp.mailfrom="mptcp+bounces-1962-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from ewr.edge.kernel.org (ewr.edge.kernel.org. [147.75.197.195]) by mx.google.com with ESMTPS id c7si4047692qth.431.2021.09.17.16.33.38 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 17 Sep 2021 16:33:38 -0700 (PDT) Received-SPF: pass (google.com: domain of mptcp+bounces-1962-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) client-ip=147.75.197.195; Authentication-Results: mx.google.com; spf=pass (google.com: domain of mptcp+bounces-1962-wpasupplicant.patchew=gmail.com@lists.linux.dev designates 147.75.197.195 as permitted sender) smtp.mailfrom="mptcp+bounces-1962-wpasupplicant.patchew=gmail.com@lists.linux.dev"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ewr.edge.kernel.org (Postfix) with ESMTPS id 50F6D1C0F41 for ; Fri, 17 Sep 2021 23:33:38 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 029D43FC9; Fri, 17 Sep 2021 23:33:35 +0000 (UTC) X-Original-To: mptcp@lists.linux.dev Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5756A3FCF for ; Fri, 17 Sep 2021 23:33:33 +0000 (UTC) X-IronPort-AV: E=McAfee;i="6200,9189,10110"; a="209979875" X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="209979875" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:30 -0700 X-IronPort-AV: E=Sophos;i="5.85,302,1624345200"; d="scan'208";a="483228561" Received: from mjmartin-desk2.amr.corp.intel.com (HELO mjmartin-desk2.intel.com) ([10.212.205.24]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Sep 2021 16:33:30 -0700 From: Mat Martineau To: netdev@vger.kernel.org Cc: Florian Westphal , davem@davemloft.net, kuba@kernel.org, matthieu.baerts@tessares.net, mptcp@lists.linux.dev, Mat Martineau Subject: [PATCH net-next 5/5] selftests: mptcp: add mptcp getsockopt test cases Date: Fri, 17 Sep 2021 16:33:22 -0700 Message-Id: <20210917233322.271789-6-mathew.j.martineau@linux.intel.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210917233322.271789-1-mathew.j.martineau@linux.intel.com> References: <20210917233322.271789-1-mathew.j.martineau@linux.intel.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" From: Florian Westphal Add a test program that retrieves the three info types: 1. mptcp meta information 2. tcp info for subflow 3. subflow endpoint addresses For all three rudimentary checks are added. 1. Meta information checks that the logical mptcp sequence numbers advance as expected, based on the bytes read (init seq + bytes_received/sent) and the connection state (after close, we should exect 1 extra byte due to FIN). 2. TCP info checks the number of bytes sent/received vs. sums of read/write syscall return values. 3. Subflow endpoint addresses are checked vs. getsockname/getpeername result. Tests for forward compatibility (0-initialisation of output-only fields in mptcp_subflow_data structure) are added as well. Co-developed-by: Matthieu Baerts Signed-off-by: Matthieu Baerts Signed-off-by: Florian Westphal Signed-off-by: Mat Martineau --- tools/testing/selftests/net/mptcp/.gitignore | 1 + tools/testing/selftests/net/mptcp/Makefile | 2 +- .../selftests/net/mptcp/mptcp_sockopt.c | 683 ++++++++++++++++++ .../selftests/net/mptcp/mptcp_sockopt.sh | 31 +- 4 files changed, 714 insertions(+), 3 deletions(-) create mode 100644 tools/testing/selftests/net/mptcp/mptcp_sockopt.c diff --git a/tools/testing/selftests/net/mptcp/.gitignore b/tools/testing/s= elftests/net/mptcp/.gitignore index 260336d5f0b1..7569d892967a 100644 --- a/tools/testing/selftests/net/mptcp/.gitignore +++ b/tools/testing/selftests/net/mptcp/.gitignore @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only mptcp_connect +mptcp_sockopt pm_nl_ctl *.pcap diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/sel= ftests/net/mptcp/Makefile index f1464f09b080..bbf4e448bad9 100644 --- a/tools/testing/selftests/net/mptcp/Makefile +++ b/tools/testing/selftests/net/mptcp/Makefile @@ -8,7 +8,7 @@ CFLAGS =3D -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir= )/usr/include TEST_PROGS :=3D mptcp_connect.sh pm_netlink.sh mptcp_join.sh diag.sh \ simult_flows.sh mptcp_sockopt.sh =20 -TEST_GEN_FILES =3D mptcp_connect pm_nl_ctl +TEST_GEN_FILES =3D mptcp_connect pm_nl_ctl mptcp_sockopt =20 TEST_FILES :=3D settings =20 diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/test= ing/selftests/net/mptcp/mptcp_sockopt.c new file mode 100644 index 000000000000..417b11cafafe --- /dev/null +++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c @@ -0,0 +1,683 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +static int pf =3D AF_INET; + +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP 262 +#endif +#ifndef SOL_MPTCP +#define SOL_MPTCP 284 +#endif + +#ifndef MPTCP_INFO +struct mptcp_info { + __u8 mptcpi_subflows; + __u8 mptcpi_add_addr_signal; + __u8 mptcpi_add_addr_accepted; + __u8 mptcpi_subflows_max; + __u8 mptcpi_add_addr_signal_max; + __u8 mptcpi_add_addr_accepted_max; + __u32 mptcpi_flags; + __u32 mptcpi_token; + __u64 mptcpi_write_seq; + __u64 mptcpi_snd_una; + __u64 mptcpi_rcv_nxt; + __u8 mptcpi_local_addr_used; + __u8 mptcpi_local_addr_max; + __u8 mptcpi_csum_enabled; +}; + +struct mptcp_subflow_data { + __u32 size_subflow_data; /* size of this structure in userspace */ + __u32 num_subflows; /* must be 0, set by kernel */ + __u32 size_kernel; /* must be 0, set by kernel */ + __u32 size_user; /* size of one element in data[] */ +} __attribute__((aligned(8))); + +struct mptcp_subflow_addrs { + union { + __kernel_sa_family_t sa_family; + struct sockaddr sa_local; + struct sockaddr_in sin_local; + struct sockaddr_in6 sin6_local; + struct __kernel_sockaddr_storage ss_local; + }; + union { + struct sockaddr sa_remote; + struct sockaddr_in sin_remote; + struct sockaddr_in6 sin6_remote; + struct __kernel_sockaddr_storage ss_remote; + }; +}; + +#define MPTCP_INFO 1 +#define MPTCP_TCPINFO 2 +#define MPTCP_SUBFLOW_ADDRS 3 +#endif + +struct so_state { + struct mptcp_info mi; + uint64_t mptcpi_rcv_delta; + uint64_t tcpi_rcv_delta; +}; + +static void die_perror(const char *msg) +{ + perror(msg); + exit(1); +} + +static void die_usage(int r) +{ + fprintf(stderr, "Usage: mptcp_sockopt [-6]\n"); + exit(r); +} + +static void xerror(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); + exit(1); +} + +static const char *getxinfo_strerr(int err) +{ + if (err =3D=3D EAI_SYSTEM) + return strerror(errno); + + return gai_strerror(err); +} + +static void xgetaddrinfo(const char *node, const char *service, + const struct addrinfo *hints, + struct addrinfo **res) +{ + int err =3D getaddrinfo(node, service, hints, res); + + if (err) { + const char *errstr =3D getxinfo_strerr(err); + + fprintf(stderr, "Fatal: getaddrinfo(%s:%s): %s\n", + node ? node : "", service ? service : "", errstr); + exit(1); + } +} + +static int sock_listen_mptcp(const char * const listenaddr, + const char * const port) +{ + int sock; + struct addrinfo hints =3D { + .ai_protocol =3D IPPROTO_TCP, + .ai_socktype =3D SOCK_STREAM, + .ai_flags =3D AI_PASSIVE | AI_NUMERICHOST + }; + + hints.ai_family =3D pf; + + struct addrinfo *a, *addr; + int one =3D 1; + + xgetaddrinfo(listenaddr, port, &hints, &addr); + hints.ai_family =3D pf; + + for (a =3D addr; a; a =3D a->ai_next) { + sock =3D socket(a->ai_family, a->ai_socktype, IPPROTO_MPTCP); + if (sock < 0) + continue; + + if (-1 =3D=3D setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, + sizeof(one))) + perror("setsockopt"); + + if (bind(sock, a->ai_addr, a->ai_addrlen) =3D=3D 0) + break; /* success */ + + perror("bind"); + close(sock); + sock =3D -1; + } + + freeaddrinfo(addr); + + if (sock < 0) + xerror("could not create listen socket"); + + if (listen(sock, 20)) + die_perror("listen"); + + return sock; +} + +static int sock_connect_mptcp(const char * const remoteaddr, + const char * const port, int proto) +{ + struct addrinfo hints =3D { + .ai_protocol =3D IPPROTO_TCP, + .ai_socktype =3D SOCK_STREAM, + }; + struct addrinfo *a, *addr; + int sock =3D -1; + + hints.ai_family =3D pf; + + xgetaddrinfo(remoteaddr, port, &hints, &addr); + for (a =3D addr; a; a =3D a->ai_next) { + sock =3D socket(a->ai_family, a->ai_socktype, proto); + if (sock < 0) + continue; + + if (connect(sock, a->ai_addr, a->ai_addrlen) =3D=3D 0) + break; /* success */ + + die_perror("connect"); + } + + if (sock < 0) + xerror("could not create connect socket"); + + freeaddrinfo(addr); + return sock; +} + +static void parse_opts(int argc, char **argv) +{ + int c; + + while ((c =3D getopt(argc, argv, "h6")) !=3D -1) { + switch (c) { + case 'h': + die_usage(0); + break; + case '6': + pf =3D AF_INET6; + break; + default: + die_usage(1); + break; + } + } +} + +static void do_getsockopt_bogus_sf_data(int fd, int optname) +{ + struct mptcp_subflow_data good_data; + struct bogus_data { + struct mptcp_subflow_data d; + char buf[2]; + } bd; + socklen_t olen, _olen; + int ret; + + memset(&bd, 0, sizeof(bd)); + memset(&good_data, 0, sizeof(good_data)); + + olen =3D sizeof(good_data); + good_data.size_subflow_data =3D olen; + + ret =3D getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); + assert(ret < 0); /* 0 size_subflow_data */ + assert(olen =3D=3D sizeof(good_data)); + + bd.d =3D good_data; + + ret =3D getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); + assert(ret =3D=3D 0); + assert(olen =3D=3D sizeof(good_data)); + assert(bd.d.num_subflows =3D=3D 1); + assert(bd.d.size_kernel > 0); + assert(bd.d.size_user =3D=3D 0); + + bd.d =3D good_data; + _olen =3D rand() % olen; + olen =3D _olen; + ret =3D getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); + assert(ret < 0); /* bogus olen */ + assert(olen =3D=3D _olen); /* must be unchanged */ + + bd.d =3D good_data; + olen =3D sizeof(good_data); + bd.d.size_kernel =3D 1; + ret =3D getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); + assert(ret < 0); /* size_kernel not 0 */ + + bd.d =3D good_data; + olen =3D sizeof(good_data); + bd.d.num_subflows =3D 1; + ret =3D getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); + assert(ret < 0); /* num_subflows not 0 */ + + /* forward compat check: larger struct mptcp_subflow_data on 'old' kernel= */ + bd.d =3D good_data; + olen =3D sizeof(bd); + bd.d.size_subflow_data =3D sizeof(bd); + + ret =3D getsockopt(fd, SOL_MPTCP, optname, &bd, &olen); + assert(ret =3D=3D 0); + + /* olen must be truncated to real data size filled by kernel: */ + assert(olen =3D=3D sizeof(good_data)); + + assert(bd.d.size_subflow_data =3D=3D sizeof(bd)); + + bd.d =3D good_data; + bd.d.size_subflow_data +=3D 1; + bd.d.size_user =3D 1; + olen =3D bd.d.size_subflow_data + 1; + _olen =3D olen; + + ret =3D getsockopt(fd, SOL_MPTCP, optname, &bd, &_olen); + assert(ret =3D=3D 0); + + /* no truncation, kernel should have filled 1 byte of optname payload in = buf[1]: */ + assert(olen =3D=3D _olen); + + assert(bd.d.size_subflow_data =3D=3D sizeof(good_data) + 1); + assert(bd.buf[0] =3D=3D 0); +} + +static void do_getsockopt_mptcp_info(struct so_state *s, int fd, size_t w) +{ + struct mptcp_info i; + socklen_t olen; + int ret; + + olen =3D sizeof(i); + ret =3D getsockopt(fd, SOL_MPTCP, MPTCP_INFO, &i, &olen); + + if (ret < 0) + die_perror("getsockopt MPTCP_INFO"); + + assert(olen =3D=3D sizeof(i)); + + if (s->mi.mptcpi_write_seq =3D=3D 0) + s->mi =3D i; + + assert(s->mi.mptcpi_write_seq + w =3D=3D i.mptcpi_write_seq); + + s->mptcpi_rcv_delta =3D i.mptcpi_rcv_nxt - s->mi.mptcpi_rcv_nxt; +} + +static void do_getsockopt_tcp_info(struct so_state *s, int fd, size_t r, s= ize_t w) +{ + struct my_tcp_info { + struct mptcp_subflow_data d; + struct tcp_info ti[2]; + } ti; + int ret, tries =3D 5; + socklen_t olen; + + do { + memset(&ti, 0, sizeof(ti)); + + ti.d.size_subflow_data =3D sizeof(struct mptcp_subflow_data); + ti.d.size_user =3D sizeof(struct tcp_info); + olen =3D sizeof(ti); + + ret =3D getsockopt(fd, SOL_MPTCP, MPTCP_TCPINFO, &ti, &olen); + if (ret < 0) + xerror("getsockopt MPTCP_TCPINFO (tries %d, %m)"); + + assert(olen <=3D sizeof(ti)); + assert(ti.d.size_user =3D=3D ti.d.size_kernel); + assert(ti.d.size_user =3D=3D sizeof(struct tcp_info)); + assert(ti.d.num_subflows =3D=3D 1); + + assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data)); + olen -=3D sizeof(struct mptcp_subflow_data); + assert(olen =3D=3D sizeof(struct tcp_info)); + + if (ti.ti[0].tcpi_bytes_sent =3D=3D w && + ti.ti[0].tcpi_bytes_received =3D=3D r) + goto done; + + if (r =3D=3D 0 && ti.ti[0].tcpi_bytes_sent =3D=3D w && + ti.ti[0].tcpi_bytes_received) { + s->tcpi_rcv_delta =3D ti.ti[0].tcpi_bytes_received; + goto done; + } + + /* wait and repeat, might be that tx is still ongoing */ + sleep(1); + } while (tries-- > 0); + + xerror("tcpi_bytes_sent %" PRIu64 ", want %zu. tcpi_bytes_received %" PRI= u64 ", want %zu", + ti.ti[0].tcpi_bytes_sent, w, ti.ti[0].tcpi_bytes_received, r); + +done: + do_getsockopt_bogus_sf_data(fd, MPTCP_TCPINFO); +} + +static void do_getsockopt_subflow_addrs(int fd) +{ + struct sockaddr_storage remote, local; + socklen_t olen, rlen, llen; + int ret; + struct my_addrs { + struct mptcp_subflow_data d; + struct mptcp_subflow_addrs addr[2]; + } addrs; + + memset(&addrs, 0, sizeof(addrs)); + memset(&local, 0, sizeof(local)); + memset(&remote, 0, sizeof(remote)); + + addrs.d.size_subflow_data =3D sizeof(struct mptcp_subflow_data); + addrs.d.size_user =3D sizeof(struct mptcp_subflow_addrs); + olen =3D sizeof(addrs); + + ret =3D getsockopt(fd, SOL_MPTCP, MPTCP_SUBFLOW_ADDRS, &addrs, &olen); + if (ret < 0) + die_perror("getsockopt MPTCP_SUBFLOW_ADDRS"); + + assert(olen <=3D sizeof(addrs)); + assert(addrs.d.size_user =3D=3D addrs.d.size_kernel); + assert(addrs.d.size_user =3D=3D sizeof(struct mptcp_subflow_addrs)); + assert(addrs.d.num_subflows =3D=3D 1); + + assert(olen > (socklen_t)sizeof(struct mptcp_subflow_data)); + olen -=3D sizeof(struct mptcp_subflow_data); + assert(olen =3D=3D sizeof(struct mptcp_subflow_addrs)); + + llen =3D sizeof(local); + ret =3D getsockname(fd, (struct sockaddr *)&local, &llen); + if (ret < 0) + die_perror("getsockname"); + rlen =3D sizeof(remote); + ret =3D getpeername(fd, (struct sockaddr *)&remote, &rlen); + if (ret < 0) + die_perror("getpeername"); + + assert(rlen > 0); + assert(rlen =3D=3D llen); + + assert(remote.ss_family =3D=3D local.ss_family); + + assert(memcmp(&local, &addrs.addr[0].ss_local, sizeof(local)) =3D=3D 0); + assert(memcmp(&remote, &addrs.addr[0].ss_remote, sizeof(remote)) =3D=3D 0= ); + + memset(&addrs, 0, sizeof(addrs)); + + addrs.d.size_subflow_data =3D sizeof(struct mptcp_subflow_data); + addrs.d.size_user =3D sizeof(sa_family_t); + olen =3D sizeof(addrs.d) + sizeof(sa_family_t); + + ret =3D getsockopt(fd, SOL_MPTCP, MPTCP_SUBFLOW_ADDRS, &addrs, &olen); + assert(ret =3D=3D 0); + assert(olen =3D=3D sizeof(addrs.d) + sizeof(sa_family_t)); + + assert(addrs.addr[0].sa_family =3D=3D pf); + assert(addrs.addr[0].sa_family =3D=3D local.ss_family); + + assert(memcmp(&local, &addrs.addr[0].ss_local, sizeof(local)) !=3D 0); + assert(memcmp(&remote, &addrs.addr[0].ss_remote, sizeof(remote)) !=3D 0); + + do_getsockopt_bogus_sf_data(fd, MPTCP_SUBFLOW_ADDRS); +} + +static void do_getsockopts(struct so_state *s, int fd, size_t r, size_t w) +{ + do_getsockopt_mptcp_info(s, fd, w); + + do_getsockopt_tcp_info(s, fd, r, w); + + do_getsockopt_subflow_addrs(fd); +} + +static void connect_one_server(int fd, int pipefd) +{ + char buf[4096], buf2[4096]; + size_t len, i, total; + struct so_state s; + bool eof =3D false; + ssize_t ret; + + memset(&s, 0, sizeof(s)); + + len =3D rand() % (sizeof(buf) - 1); + + if (len < 128) + len =3D 128; + + for (i =3D 0; i < len ; i++) { + buf[i] =3D rand() % 26; + buf[i] +=3D 'A'; + } + + buf[i] =3D '\n'; + + do_getsockopts(&s, fd, 0, 0); + + /* un-block server */ + ret =3D read(pipefd, buf2, 4); + assert(ret =3D=3D 4); + close(pipefd); + + assert(strncmp(buf2, "xmit", 4) =3D=3D 0); + + ret =3D write(fd, buf, len); + if (ret < 0) + die_perror("write"); + + if (ret !=3D (ssize_t)len) + xerror("short write"); + + total =3D 0; + do { + ret =3D read(fd, buf2 + total, sizeof(buf2) - total); + if (ret < 0) + die_perror("read"); + if (ret =3D=3D 0) { + eof =3D true; + break; + } + + total +=3D ret; + } while (total < len); + + if (total !=3D len) + xerror("total %lu, len %lu eof %d\n", total, len, eof); + + if (memcmp(buf, buf2, len)) + xerror("data corruption"); + + if (s.tcpi_rcv_delta) + assert(s.tcpi_rcv_delta <=3D total); + + do_getsockopts(&s, fd, ret, ret); + + if (eof) + total +=3D 1; /* sequence advances due to FIN */ + + assert(s.mptcpi_rcv_delta =3D=3D (uint64_t)total); + close(fd); +} + +static void process_one_client(int fd, int pipefd) +{ + ssize_t ret, ret2, ret3; + struct so_state s; + char buf[4096]; + + memset(&s, 0, sizeof(s)); + do_getsockopts(&s, fd, 0, 0); + + ret =3D write(pipefd, "xmit", 4); + assert(ret =3D=3D 4); + + ret =3D read(fd, buf, sizeof(buf)); + if (ret < 0) + die_perror("read"); + + assert(s.mptcpi_rcv_delta <=3D (uint64_t)ret); + + if (s.tcpi_rcv_delta) + assert(s.tcpi_rcv_delta =3D=3D (uint64_t)ret); + + ret2 =3D write(fd, buf, ret); + if (ret2 < 0) + die_perror("write"); + + /* wait for hangup */ + ret3 =3D read(fd, buf, 1); + if (ret3 !=3D 0) + xerror("expected EOF, got %lu", ret3); + + do_getsockopts(&s, fd, ret, ret2); + if (s.mptcpi_rcv_delta !=3D (uint64_t)ret + 1) + xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64, s.mptcpi_rcv_del= ta, ret + 1, s.mptcpi_rcv_delta - ret); + close(fd); +} + +static int xaccept(int s) +{ + int fd =3D accept(s, NULL, 0); + + if (fd < 0) + die_perror("accept"); + + return fd; +} + +static int server(int pipefd) +{ + int fd =3D -1, r; + + switch (pf) { + case AF_INET: + fd =3D sock_listen_mptcp("127.0.0.1", "15432"); + break; + case AF_INET6: + fd =3D sock_listen_mptcp("::1", "15432"); + break; + default: + xerror("Unknown pf %d\n", pf); + break; + } + + r =3D write(pipefd, "conn", 4); + assert(r =3D=3D 4); + + alarm(15); + r =3D xaccept(fd); + + process_one_client(r, pipefd); + + return 0; +} + +static int client(int pipefd) +{ + int fd =3D -1; + + alarm(15); + + switch (pf) { + case AF_INET: + fd =3D sock_connect_mptcp("127.0.0.1", "15432", IPPROTO_MPTCP); + break; + case AF_INET6: + fd =3D sock_connect_mptcp("::1", "15432", IPPROTO_MPTCP); + break; + default: + xerror("Unknown pf %d\n", pf); + } + + connect_one_server(fd, pipefd); + + return 0; +} + +static pid_t xfork(void) +{ + pid_t p =3D fork(); + + if (p < 0) + die_perror("fork"); + + return p; +} + +static int rcheck(int wstatus, const char *what) +{ + if (WIFEXITED(wstatus)) { + if (WEXITSTATUS(wstatus) =3D=3D 0) + return 0; + fprintf(stderr, "%s exited, status=3D%d\n", what, WEXITSTATUS(wstatus)); + return WEXITSTATUS(wstatus); + } else if (WIFSIGNALED(wstatus)) { + xerror("%s killed by signal %d\n", what, WTERMSIG(wstatus)); + } else if (WIFSTOPPED(wstatus)) { + xerror("%s stopped by signal %d\n", what, WSTOPSIG(wstatus)); + } + + return 111; +} + +int main(int argc, char *argv[]) +{ + int e1, e2, wstatus; + pid_t s, c, ret; + int pipefds[2]; + + parse_opts(argc, argv); + + e1 =3D pipe(pipefds); + if (e1 < 0) + die_perror("pipe"); + + s =3D xfork(); + if (s =3D=3D 0) + return server(pipefds[1]); + + close(pipefds[1]); + + /* wait until server bound a socket */ + e1 =3D read(pipefds[0], &e1, 4); + assert(e1 =3D=3D 4); + + c =3D xfork(); + if (c =3D=3D 0) + return client(pipefds[0]); + + close(pipefds[0]); + + ret =3D waitpid(s, &wstatus, 0); + if (ret =3D=3D -1) + die_perror("waitpid"); + e1 =3D rcheck(wstatus, "server"); + ret =3D waitpid(c, &wstatus, 0); + if (ret =3D=3D -1) + die_perror("waitpid"); + e2 =3D rcheck(wstatus, "client"); + + return e1 ? e1 : e2; +} diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh b/tools/tes= ting/selftests/net/mptcp/mptcp_sockopt.sh index 1579e471a5e7..41de643788b8 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.sh @@ -239,12 +239,35 @@ make_file() echo "Created $name (size $size KB) containing data sent by $who" } =20 +do_mptcp_sockopt_tests() +{ + local lret=3D0 + + ./mptcp_sockopt + lret=3D$? + + if [ $lret -ne 0 ]; then + echo "FAIL: SOL_MPTCP getsockopt" 1>&2 + ret=3D$lret + return + fi + + ./mptcp_sockopt -6 + lret=3D$? + + if [ $lret -ne 0 ]; then + echo "FAIL: SOL_MPTCP getsockopt (ipv6)" 1>&2 + ret=3D$lret + return + fi +} + run_tests() { listener_ns=3D"$1" connector_ns=3D"$2" connect_addr=3D"$3" - lret=3D0 + local lret=3D0 =20 do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP ${connect_addr} =20 @@ -268,9 +291,13 @@ trap cleanup EXIT run_tests $ns1 $ns2 10.0.1.1 run_tests $ns1 $ns2 dead:beef:1::1 =20 - if [ $ret -eq 0 ];then echo "PASS: all packets had packet mark set" fi =20 +do_mptcp_sockopt_tests +if [ $ret -eq 0 ];then + echo "PASS: SOL_MPTCP getsockopt has expected information" +fi + exit $ret --=20 2.33.0