Message ID | 20210113175453.1945886-3-matthieu.baerts@tessares.net |
---|---|
State | Superseded, archived |
Headers | show |
Series | add IPv4-mapped address support | expand |
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 --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);