From nobody Fri May 3 07:27:16 2024 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 AA7D6A497 for ; Fri, 23 Dec 2022 19:00:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1671822024; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ULqKTqz06NnyraDBeKRoaACwrjiY+WsUXPOEZwey9Dk=; b=FXCIdnhc01FvZWfepgPXSNTbNX3+MPwkYQueV30EEVSc4zBfzT6RAe6rjiqDmPJCF6jb7d 3wJf4n1DT+Ey3KAijdwmjvlH7xaag4XxZkeKTzPPZoNuWtzWnM0ARTAOL1RIlonCWA4oYn iUVAOOgoydeN9jyTs18yWF7DGhmse60= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-324-7b2VtL0SNoaNX-teuKoeYg-1; Fri, 23 Dec 2022 14:00:23 -0500 X-MC-Unique: 7b2VtL0SNoaNX-teuKoeYg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 35B761C05122 for ; Fri, 23 Dec 2022 19:00:23 +0000 (UTC) Received: from gerbillo.redhat.com (unknown [10.39.192.156]) by smtp.corp.redhat.com (Postfix) with ESMTP id B51C540C945A for ; Fri, 23 Dec 2022 19:00:22 +0000 (UTC) From: Paolo Abeni To: mptcp@lists.linux.dev Subject: [PATCH v2 mptcp-next 1/3] mptcp: explicitly specify sock family at subflow creation time Date: Fri, 23 Dec 2022 20:00:12 +0100 Message-Id: <7d3aae6493caa1563d1aaadc79d299c01077f28a.1671821017.git.pabeni@redhat.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8"; x-default="true" Let the caller specify the to-be-created subflow family. No functional change intended, will be leveraged by the next patch. Signed-off-by: Paolo Abeni --- net/mptcp/protocol.c | 2 +- net/mptcp/protocol.h | 3 ++- net/mptcp/subflow.c | 9 +++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 5e813580c394..f08ef9ca242a 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -98,7 +98,7 @@ static int __mptcp_socket_create(struct mptcp_sock *msk) struct socket *ssock; int err; =20 - err =3D mptcp_subflow_create_socket(sk, &ssock); + err =3D mptcp_subflow_create_socket(sk, sk->sk_family, &ssock); if (err) return err; =20 diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 3cd3270407b0..fcce8f03c1b5 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -643,7 +643,8 @@ bool mptcp_addresses_equal(const struct mptcp_addr_info= *a, /* called with sk socket lock held */ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info = *loc, const struct mptcp_addr_info *remote); -int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock); +int mptcp_subflow_create_socket(struct sock *sk, unsigned short family, + struct socket **new_sock); void mptcp_info2sockaddr(const struct mptcp_addr_info *info, struct sockaddr_storage *addr, unsigned short family); diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index bd387d4b5a38..ec54413fb31f 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -1547,7 +1547,7 @@ int __mptcp_subflow_connect(struct sock *sk, const st= ruct mptcp_addr_info *loc, if (!mptcp_is_fully_established(sk)) goto err_out; =20 - err =3D mptcp_subflow_create_socket(sk, &sf); + err =3D mptcp_subflow_create_socket(sk, loc->family, &sf); if (err) goto err_out; =20 @@ -1660,7 +1660,9 @@ static void mptcp_subflow_ops_undo_override(struct so= ck *ssk) #endif ssk->sk_prot =3D &tcp_prot; } -int mptcp_subflow_create_socket(struct sock *sk, struct socket **new_sock) + +int mptcp_subflow_create_socket(struct sock *sk, unsigned short family, + struct socket **new_sock) { struct mptcp_subflow_context *subflow; struct net *net =3D sock_net(sk); @@ -1673,8 +1675,7 @@ int mptcp_subflow_create_socket(struct sock *sk, stru= ct socket **new_sock) if (unlikely(!sk->sk_socket)) return -EINVAL; =20 - err =3D sock_create_kern(net, sk->sk_family, SOCK_STREAM, IPPROTO_TCP, - &sf); + err =3D sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP, &sf); if (err) return err; =20 --=20 2.38.1 From nobody Fri May 3 07:27:16 2024 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 ED297A498 for ; Fri, 23 Dec 2022 19:00:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1671822025; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ghBJVfFZFDXwXCBFFoN6ZIlCCxpPV7mON6nb9Zh0YPM=; b=fyjWjuDu2gPHKbpUQR/CxFNaFUqHnNK0/9ue2V+B2qmfbexM6iML1b1Mgb5HKlg0QZMdzS A6XPAkfKBqWs2FC60wzCGuZHdnqcnxBWNITzZJ6xxoPX9kdsrbFq+AQWBGBRKJFeZdHEiM 3iBmBdcR/c22Nqggkxv/ZXbCExkkWj4= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-45-mIluhuabP8a6S15PtNlqoA-1; Fri, 23 Dec 2022 14:00:24 -0500 X-MC-Unique: mIluhuabP8a6S15PtNlqoA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 21FB23832783 for ; Fri, 23 Dec 2022 19:00:24 +0000 (UTC) Received: from gerbillo.redhat.com (unknown [10.39.192.156]) by smtp.corp.redhat.com (Postfix) with ESMTP id 888F740C945A for ; Fri, 23 Dec 2022 19:00:23 +0000 (UTC) From: Paolo Abeni To: mptcp@lists.linux.dev Subject: [PATCH v2 mptcp-next 2/3] mptcp: let the in kernel PM use mixed ipv4 and ipv6 addresses Date: Fri, 23 Dec 2022 20:00:13 +0100 Message-Id: <61ebbe1bdb47f74d856b3edee06112999da50f07.1671821017.git.pabeni@redhat.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8"; x-default="true" Currently the in kernel PM arbitrary enforces that created subflow's family must match the main MPTCP socket. The RFC allow instead for mixing IPv4 and IPv6 subflows. This patch changes the in kernel PM logic to create subflows matching the currently selected source (or destination) address. IPv4 sockets can pick only IPv4 addresses, while IPv6 sockets not restricted to V6ONLY can pick either IPv4 and IPv6 addresses, effectively allowing the creation of IPv4 and IPv6 subflows under the same msk. While at that, factor out a new helper for address family matching, taking care of ipv4 vs ipv4-mapped-ipv6. Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/269 Signed-off-by: Paolo Abeni --- net/mptcp/pm_netlink.c | 68 ++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c index f2a43e13bacd..23c4e74312f7 100644 --- a/net/mptcp/pm_netlink.c +++ b/net/mptcp/pm_netlink.c @@ -152,7 +152,6 @@ static struct mptcp_pm_addr_entry * select_local_address(const struct pm_nl_pernet *pernet, const struct mptcp_sock *msk) { - const struct sock *sk =3D (const struct sock *)msk; struct mptcp_pm_addr_entry *entry, *ret =3D NULL; =20 msk_owned_by_me(msk); @@ -165,16 +164,6 @@ select_local_address(const struct pm_nl_pernet *pernet, if (!test_bit(entry->addr.id, msk->pm.id_avail_bitmap)) continue; =20 - if (entry->addr.family !=3D sk->sk_family) { -#if IS_ENABLED(CONFIG_MPTCP_IPV6) - if ((entry->addr.family =3D=3D AF_INET && - !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) || - (sk->sk_family =3D=3D AF_INET && - !ipv6_addr_v4mapped(&entry->addr.addr6))) -#endif - continue; - } - ret =3D entry; break; } @@ -420,10 +409,34 @@ static bool lookup_address_in_vec(const struct mptcp_= addr_info *addrs, unsigned return false; } =20 +/* if sk is ipv4 or ipv6_only allows only same-family local and remote add= resses, + * otherwise allow any matching local/remote pair + */ +static bool addr_families_match(const struct sock *sk, + const struct mptcp_addr_info *loc, + const struct mptcp_addr_info *remote) +{ + if (sk->sk_family =3D=3D loc->family && sk->sk_family =3D=3D remote->fami= ly) + return true; + +#if IS_ENABLED(CONFIG_MPTCP_IPV6) + if (sk->sk_family =3D=3D AF_INET || sk->sk_ipv6only) + return false; + + if (loc->family =3D=3D remote->family || + (loc->family =3D=3D AF_INET && ipv6_addr_v4mapped(&remote->addr6)) || + (remote->family =3D=3D AF_INET && ipv6_addr_v4mapped(&loc->addr6))) + return true; +#endif + return false; +} + /* Fill all the remote addresses into the array addrs[], * and return the array size. */ -static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk, bool= fullmesh, +static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk, + struct mptcp_addr_info *local, + bool fullmesh, struct mptcp_addr_info *addrs) { bool deny_id0 =3D READ_ONCE(msk->pm.remote_deny_join_id0); @@ -443,6 +456,9 @@ static unsigned int fill_remote_addresses_vec(struct mp= tcp_sock *msk, bool fullm if (deny_id0) return 0; =20 + if (!addr_families_match(sk, local, &remote)) + return 0; + msk->pm.subflows++; addrs[i++] =3D remote; } else { @@ -453,6 +469,9 @@ static unsigned int fill_remote_addresses_vec(struct mp= tcp_sock *msk, bool fullm if (deny_id0 && !addrs[i].id) continue; =20 + if (!addr_families_match(sk, local, &addrs[i])) + continue; + if (!lookup_address_in_vec(addrs, i, &addrs[i]) && msk->pm.subflows < subflows_max) { msk->pm.subflows++; @@ -600,10 +619,10 @@ static void mptcp_pm_create_subflow_or_signal_addr(st= ruct mptcp_sock *msk) fullmesh =3D !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH); =20 msk->pm.local_addr_used++; - nr =3D fill_remote_addresses_vec(msk, fullmesh, addrs); - if (nr) - __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); + nr =3D fill_remote_addresses_vec(msk, &local->addr, fullmesh, addrs); + __clear_bit(local->addr.id, msk->pm.id_avail_bitmap); spin_unlock_bh(&msk->pm.lock); + for (i =3D 0; i < nr; i++) __mptcp_subflow_connect(sk, &local->addr, &addrs[i]); spin_lock_bh(&msk->pm.lock); @@ -625,6 +644,7 @@ static void mptcp_pm_nl_subflow_established(struct mptc= p_sock *msk) * and return the array size. */ static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk, + struct mptcp_addr_info *remote, struct mptcp_addr_info *addrs) { struct sock *sk =3D (struct sock *)msk; @@ -642,15 +662,8 @@ static unsigned int fill_local_addresses_vec(struct mp= tcp_sock *msk, if (!(entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH)) continue; =20 - if (entry->addr.family !=3D sk->sk_family) { -#if IS_ENABLED(CONFIG_MPTCP_IPV6) - if ((entry->addr.family =3D=3D AF_INET && - !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) || - (sk->sk_family =3D=3D AF_INET && - !ipv6_addr_v4mapped(&entry->addr.addr6))) -#endif - continue; - } + if (!addr_families_match(sk, &entry->addr, remote)) + continue; =20 if (msk->pm.subflows < subflows_max) { msk->pm.subflows++; @@ -664,7 +677,10 @@ static unsigned int fill_local_addresses_vec(struct mp= tcp_sock *msk, */ if (!i) { memset(&local, 0, sizeof(local)); - local.family =3D msk->pm.remote.family; + local.family =3D remote->family; + + if (!addr_families_match(sk, &local, remote)) + return 0; =20 msk->pm.subflows++; addrs[i++] =3D local; @@ -703,7 +719,7 @@ static void mptcp_pm_nl_add_addr_received(struct mptcp_= sock *msk) /* connect to the specified remote address, using whatever * local address the routing configuration will pick. */ - nr =3D fill_local_addresses_vec(msk, addrs); + nr =3D fill_local_addresses_vec(msk, &remote, addrs); =20 msk->pm.add_addr_accepted++; if (msk->pm.add_addr_accepted >=3D add_addr_accept_max || --=20 2.38.1 From nobody Fri May 3 07:27:16 2024 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 413ACA499 for ; Fri, 23 Dec 2022 19:00:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1671822027; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=q002Cx6H7J6GsTMmS8yYrnNQymIZc5XPTwuQcylTC5U=; b=bl9a294ZdwNgPCcS7Ddsccbo9KBBpDS0OuiT66lftO4uiQli8Oq0moGlvNnRI/v23On5B+ VVtD/wZ2v+x/ynPRuflT2GTInW5BiAtudCl/tHOPwI1w5eNH+2OB8goFwu8KiBSdpYxjvZ tAZLvJ2Q+qTdyohInsMVJtPNk/2CWPE= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-158-o522248eM9SQcIPr9CMEGA-1; Fri, 23 Dec 2022 14:00:25 -0500 X-MC-Unique: o522248eM9SQcIPr9CMEGA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 25FB83C0DDCD for ; Fri, 23 Dec 2022 19:00:25 +0000 (UTC) Received: from gerbillo.redhat.com (unknown [10.39.192.156]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7E36A40C945A for ; Fri, 23 Dec 2022 19:00:24 +0000 (UTC) From: Paolo Abeni To: mptcp@lists.linux.dev Subject: [PATCH v2 mptcp-next 3/3] selftests: mptcp: add test-cases for mixed v4/v6 subflows Date: Fri, 23 Dec 2022 20:00:14 +0100 Message-Id: In-Reply-To: References: Precedence: bulk X-Mailing-List: mptcp@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8"; x-default="true" Note that we can't guess anymore the listener family based on the client target address; use always IPv6. Signed-off-by: Paolo Abeni --- .../testing/selftests/net/mptcp/mptcp_join.sh | 53 +++++++++++++++---- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testin= g/selftests/net/mptcp/mptcp_join.sh index d11d3d566608..387abdcec011 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_join.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh @@ -774,24 +774,17 @@ do_transfer() addr_nr_ns2=3D${addr_nr_ns2:9} fi =20 - local local_addr - if is_v6 "${connect_addr}"; then - local_addr=3D"::" - else - local_addr=3D"0.0.0.0" - fi - extra_srv_args=3D"$extra_args $extra_srv_args" if [ "$test_link_fail" -gt 1 ];then timeout ${timeout_test} \ ip netns exec ${listener_ns} \ ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ - $extra_srv_args ${local_addr} < "$sinfail" > "$sout" & + $extra_srv_args "::" < "$sinfail" > "$sout" & else timeout ${timeout_test} \ ip netns exec ${listener_ns} \ ./mptcp_connect -t ${timeout_poll} -l -p $port -s ${srv_proto} \ - $extra_srv_args ${local_addr} < "$sin" > "$sout" & + $extra_srv_args "::" < "$sin" > "$sout" & fi local spid=3D$! =20 @@ -2448,6 +2441,47 @@ v4mapped_tests() fi } =20 +mixed_tests() +{ + if reset "IPv4 sockets do not use IPv6 addresses"; then + pm_nl_set_limits $ns1 0 1 + pm_nl_set_limits $ns2 1 1 + pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal + run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow + chk_join_nr 0 0 0 + fi + + # Need an IPv6 mptcp socket to allow subflows of both families + if reset "simult IPv4 and IPv6 subflows"; then + pm_nl_set_limits $ns1 0 1 + pm_nl_set_limits $ns2 1 1 + pm_nl_add_endpoint $ns1 10.0.1.1 flags signal + run_tests $ns1 $ns2 dead:beef:2::1 0 0 0 slow + chk_join_nr 1 1 1 + fi + + # cross families subflows will not be created even in fullmesh mode + if reset "simult IPv4 and IPv6 subflows, fullmesh 1x1"; then + pm_nl_set_limits $ns1 0 4 + pm_nl_set_limits $ns2 1 4 + pm_nl_add_endpoint $ns2 dead:beef:2::2 flags subflow,fullmesh + pm_nl_add_endpoint $ns1 10.0.1.1 flags signal + run_tests $ns1 $ns2 dead:beef:2::1 0 0 0 slow + chk_join_nr 1 1 1 + fi + + # fullmesh still tries to create all the possibly subflows with + # matching family + if reset "simult IPv4 and IPv6 subflows, fullmesh 2x2"; then + pm_nl_set_limits $ns1 0 4 + pm_nl_set_limits $ns2 2 4 + pm_nl_add_endpoint $ns1 10.0.2.1 flags signal + pm_nl_add_endpoint $ns1 dead:beef:2::1 flags signal + run_tests $ns1 $ns2 dead:beef:1::1 0 0 fullmesh_1 slow + chk_join_nr 4 4 4 + fi +} + backup_tests() { # single subflow, backup @@ -3120,6 +3154,7 @@ all_tests_sorted=3D( a@add_tests 6@ipv6_tests 4@v4mapped_tests + M@mixed_tests b@backup_tests p@add_addr_ports_tests k@syncookies_tests --=20 2.38.1