diff mbox series

[mptcp-next,v5,2/4] mptcp: pm nl: support IPv4 mapped in v6 addresses

Message ID 20210113175453.1945886-3-matthieu.baerts@tessares.net
State Superseded, archived
Headers show
Series add IPv4-mapped address support | expand

Commit Message

Matthieu Baerts Jan. 13, 2021, 5:54 p.m. UTC
On one side, we can allow the creation of subflows between v4 mapped in
v6 and v4 addresses. For that we look for v4mapped addresses between the
local address we want to select and the remote one.

On the other side, we also properly deal with received v4mapped
addresses, either announced ones or set via Netlink.

Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/122
Suggested-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
---

Notes:
    v4 -> v5:
    - select_local_address(): extract info from sk again instead of using
      remote
    - also add explicit braces in select_local_address to avoid confusions
    - move the declaration of 'remote' to reduce the scope and to do it only
      when needed.
    - add missing Mat' suggesting-by tag (sorry, I forgot that earlier)

 net/mptcp/pm_netlink.c | 39 +++++++++++++++++++++++++++------------
 1 file changed, 27 insertions(+), 12 deletions(-)

Comments

Geliang Tang Jan. 14, 2021, 3:31 a.m. UTC | #1
Hi Matt,

Matthieu Baerts <matthieu.baerts@tessares.net> 于2021年1月14日周四 上午1:55写道:
>
> On one side, we can allow the creation of subflows between v4 mapped in
> v6 and v4 addresses. For that we look for v4mapped addresses between the
> local address we want to select and the remote one.
>
> On the other side, we also properly deal with received v4mapped
> addresses, either announced ones or set via Netlink.
>
> Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
> Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/122
> Suggested-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
> Co-developed-by: Geliang Tang <geliangtang@gmail.com>
> Signed-off-by: Geliang Tang <geliangtang@gmail.com>
> Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
> ---
>
> Notes:
>     v4 -> v5:
>     - select_local_address(): extract info from sk again instead of using
>       remote
>     - also add explicit braces in select_local_address to avoid confusions
>     - move the declaration of 'remote' to reduce the scope and to do it only
>       when needed.
>     - add missing Mat' suggesting-by tag (sorry, I forgot that earlier)
>
>  net/mptcp/pm_netlink.c | 39 +++++++++++++++++++++++++++------------
>  1 file changed, 27 insertions(+), 12 deletions(-)
>
> diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
> index 9b1f6298bbdb..83976b9ee99b 100644
> --- a/net/mptcp/pm_netlink.c
> +++ b/net/mptcp/pm_netlink.c
> @@ -60,15 +60,20 @@ static bool addresses_equal(const struct mptcp_addr_info *a,
>  {
>         bool addr_equals = false;
>
> -       if (a->family != b->family)
> -               return false;
> -
> -       if (a->family == AF_INET)
> -               addr_equals = a->addr.s_addr == b->addr.s_addr;
> +       if (a->family == b->family) {
> +               if (a->family == AF_INET)
> +                       addr_equals = a->addr.s_addr == b->addr.s_addr;
>  #if IS_ENABLED(CONFIG_MPTCP_IPV6)
> -       else
> -               addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
> +               else
> +                       addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
> +       } else if (a->family == AF_INET) {
> +               if (ipv6_addr_v4mapped(&b->addr6))
> +                       addr_equals = a->addr.s_addr == b->addr6.s6_addr32[3];
> +       } else if (b->family == AF_INET) {
> +               if (ipv6_addr_v4mapped(&a->addr6))
> +                       addr_equals = a->addr6.s6_addr32[3] == b->addr.s_addr;
>  #endif
> +       }
>
>         if (!addr_equals)
>                 return false;
> @@ -137,6 +142,7 @@ select_local_address(const struct pm_nl_pernet *pernet,
>                      struct mptcp_sock *msk)
>  {
>         struct mptcp_pm_addr_entry *entry, *ret = NULL;
> +       struct sock *sk = (struct sock *)msk;
>
>         rcu_read_lock();
>         __mptcp_flush_join_list(msk);
> @@ -144,11 +150,20 @@ select_local_address(const struct pm_nl_pernet *pernet,
>                 if (!(entry->addr.flags & MPTCP_PM_ADDR_FLAG_SUBFLOW))
>                         continue;
>
> +               if (entry->addr.family != sk->sk_family) {
> +#if IS_ENABLED(CONFIG_MPTCP_IPV6)
> +                       if ((entry->addr.family == AF_INET &&
> +                            !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) ||
> +                           (sk->sk_family == AF_INET &&
> +                            !ipv6_addr_v4mapped(&entry->addr.addr6)))
> +#endif
> +                               continue;
> +               }
> +
>                 /* avoid any address already in use by subflows and
>                  * pending join
>                  */
> -               if (entry->addr.family == ((struct sock *)msk)->sk_family &&
> -                   !lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
> +               if (!lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
>                         ret = entry;
>                         break;
>                 }
> @@ -310,7 +325,6 @@ void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
>

This patch looks good to me. But the following cleanup in
mptcp_pm_create_subflow_or_signal_addr is not related with ipv4mapped
address, could we split it into a new patch when merging this patchset?
Do you think it's necessary to do this?

Thanks.

-Geliang

>  static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
>  {
> -       struct mptcp_addr_info remote = { 0 };
>         struct sock *sk = (struct sock *)msk;
>         struct mptcp_pm_addr_entry *local;
>         struct pm_nl_pernet *pernet;
> @@ -344,13 +358,14 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
>         /* check if should create a new subflow */
>         if (msk->pm.local_addr_used < msk->pm.local_addr_max &&
>             msk->pm.subflows < msk->pm.subflows_max) {
> -               remote_address((struct sock_common *)sk, &remote);
> -
>                 local = select_local_address(pernet, msk);
>                 if (local) {
> +                       struct mptcp_addr_info remote = { 0 };
> +
>                         msk->pm.local_addr_used++;
>                         msk->pm.subflows++;
>                         check_work_pending(msk);
> +                       remote_address((struct sock_common *)sk, &remote);
>                         spin_unlock_bh(&msk->pm.lock);
>                         __mptcp_subflow_connect(sk, &local->addr, &remote);
>                         spin_lock_bh(&msk->pm.lock);
> --
> 2.29.2
>
diff mbox series

Patch

diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 9b1f6298bbdb..83976b9ee99b 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -60,15 +60,20 @@  static bool addresses_equal(const struct mptcp_addr_info *a,
 {
 	bool addr_equals = false;
 
-	if (a->family != b->family)
-		return false;
-
-	if (a->family == AF_INET)
-		addr_equals = a->addr.s_addr == b->addr.s_addr;
+	if (a->family == b->family) {
+		if (a->family == AF_INET)
+			addr_equals = a->addr.s_addr == b->addr.s_addr;
 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
-	else
-		addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
+		else
+			addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
+	} else if (a->family == AF_INET) {
+		if (ipv6_addr_v4mapped(&b->addr6))
+			addr_equals = a->addr.s_addr == b->addr6.s6_addr32[3];
+	} else if (b->family == AF_INET) {
+		if (ipv6_addr_v4mapped(&a->addr6))
+			addr_equals = a->addr6.s6_addr32[3] == b->addr.s_addr;
 #endif
+	}
 
 	if (!addr_equals)
 		return false;
@@ -137,6 +142,7 @@  select_local_address(const struct pm_nl_pernet *pernet,
 		     struct mptcp_sock *msk)
 {
 	struct mptcp_pm_addr_entry *entry, *ret = NULL;
+	struct sock *sk = (struct sock *)msk;
 
 	rcu_read_lock();
 	__mptcp_flush_join_list(msk);
@@ -144,11 +150,20 @@  select_local_address(const struct pm_nl_pernet *pernet,
 		if (!(entry->addr.flags & MPTCP_PM_ADDR_FLAG_SUBFLOW))
 			continue;
 
+		if (entry->addr.family != sk->sk_family) {
+#if IS_ENABLED(CONFIG_MPTCP_IPV6)
+			if ((entry->addr.family == AF_INET &&
+			     !ipv6_addr_v4mapped(&sk->sk_v6_daddr)) ||
+			    (sk->sk_family == AF_INET &&
+			     !ipv6_addr_v4mapped(&entry->addr.addr6)))
+#endif
+				continue;
+		}
+
 		/* avoid any address already in use by subflows and
 		 * pending join
 		 */
-		if (entry->addr.family == ((struct sock *)msk)->sk_family &&
-		    !lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
+		if (!lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
 			ret = entry;
 			break;
 		}
@@ -310,7 +325,6 @@  void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
 
 static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
 {
-	struct mptcp_addr_info remote = { 0 };
 	struct sock *sk = (struct sock *)msk;
 	struct mptcp_pm_addr_entry *local;
 	struct pm_nl_pernet *pernet;
@@ -344,13 +358,14 @@  static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
 	/* check if should create a new subflow */
 	if (msk->pm.local_addr_used < msk->pm.local_addr_max &&
 	    msk->pm.subflows < msk->pm.subflows_max) {
-		remote_address((struct sock_common *)sk, &remote);
-
 		local = select_local_address(pernet, msk);
 		if (local) {
+			struct mptcp_addr_info remote = { 0 };
+
 			msk->pm.local_addr_used++;
 			msk->pm.subflows++;
 			check_work_pending(msk);
+			remote_address((struct sock_common *)sk, &remote);
 			spin_unlock_bh(&msk->pm.lock);
 			__mptcp_subflow_connect(sk, &local->addr, &remote);
 			spin_lock_bh(&msk->pm.lock);