Skip to content

Commit 965bffd

Browse files
committed
Merge branch 'mptcp-fixes'
Matthieu Baerts says: ==================== mptcp: fixes for v6.2 Patch 1 clears resources earlier if there is no more reasons to keep MPTCP sockets alive. Patches 2 and 3 fix some locking issues visible in some rare corner cases: the linked issues should be quite hard to reproduce. Patch 4 makes sure subflows are correctly cleaned after the end of a connection. Patch 5 and 6 improve the selftests stability when running in a slow environment by transfering data for a longer period on one hand and by stopping the tests when all expected events have been observed on the other hand. All these patches fix issues introduced before v6.2. ==================== Signed-off-by: Matthieu Baerts <[email protected]> Signed-off-by: David S. Miller <[email protected]>
2 parents 1a3245f + 070d6da commit 965bffd

File tree

5 files changed

+51
-13
lines changed

5 files changed

+51
-13
lines changed

net/mptcp/pm_netlink.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -998,8 +998,8 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
998998
{
999999
int addrlen = sizeof(struct sockaddr_in);
10001000
struct sockaddr_storage addr;
1001-
struct mptcp_sock *msk;
10021001
struct socket *ssock;
1002+
struct sock *newsk;
10031003
int backlog = 1024;
10041004
int err;
10051005

@@ -1008,11 +1008,13 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
10081008
if (err)
10091009
return err;
10101010

1011-
msk = mptcp_sk(entry->lsk->sk);
1012-
if (!msk)
1011+
newsk = entry->lsk->sk;
1012+
if (!newsk)
10131013
return -EINVAL;
10141014

1015-
ssock = __mptcp_nmpc_socket(msk);
1015+
lock_sock(newsk);
1016+
ssock = __mptcp_nmpc_socket(mptcp_sk(newsk));
1017+
release_sock(newsk);
10161018
if (!ssock)
10171019
return -EINVAL;
10181020

net/mptcp/protocol.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,6 +2897,7 @@ bool __mptcp_close(struct sock *sk, long timeout)
28972897
struct mptcp_subflow_context *subflow;
28982898
struct mptcp_sock *msk = mptcp_sk(sk);
28992899
bool do_cancel_work = false;
2900+
int subflows_alive = 0;
29002901

29012902
sk->sk_shutdown = SHUTDOWN_MASK;
29022903

@@ -2922,6 +2923,8 @@ bool __mptcp_close(struct sock *sk, long timeout)
29222923
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
29232924
bool slow = lock_sock_fast_nested(ssk);
29242925

2926+
subflows_alive += ssk->sk_state != TCP_CLOSE;
2927+
29252928
/* since the close timeout takes precedence on the fail one,
29262929
* cancel the latter
29272930
*/
@@ -2937,6 +2940,12 @@ bool __mptcp_close(struct sock *sk, long timeout)
29372940
}
29382941
sock_orphan(sk);
29392942

2943+
/* all the subflows are closed, only timeout can change the msk
2944+
* state, let's not keep resources busy for no reasons
2945+
*/
2946+
if (subflows_alive == 0)
2947+
inet_sk_state_store(sk, TCP_CLOSE);
2948+
29402949
sock_hold(sk);
29412950
pr_debug("msk=%p state=%d", sk, sk->sk_state);
29422951
if (msk->token)

net/mptcp/sockopt.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -760,14 +760,21 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname,
760760
static int mptcp_setsockopt_first_sf_only(struct mptcp_sock *msk, int level, int optname,
761761
sockptr_t optval, unsigned int optlen)
762762
{
763+
struct sock *sk = (struct sock *)msk;
763764
struct socket *sock;
765+
int ret = -EINVAL;
764766

765767
/* Limit to first subflow, before the connection establishment */
768+
lock_sock(sk);
766769
sock = __mptcp_nmpc_socket(msk);
767770
if (!sock)
768-
return -EINVAL;
771+
goto unlock;
769772

770-
return tcp_setsockopt(sock->sk, level, optname, optval, optlen);
773+
ret = tcp_setsockopt(sock->sk, level, optname, optval, optlen);
774+
775+
unlock:
776+
release_sock(sk);
777+
return ret;
771778
}
772779

773780
static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,

net/mptcp/subflow.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,7 @@ void __mptcp_error_report(struct sock *sk)
13991399
mptcp_for_each_subflow(msk, subflow) {
14001400
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
14011401
int err = sock_error(ssk);
1402+
int ssk_state;
14021403

14031404
if (!err)
14041405
continue;
@@ -1409,7 +1410,14 @@ void __mptcp_error_report(struct sock *sk)
14091410
if (sk->sk_state != TCP_SYN_SENT && !__mptcp_check_fallback(msk))
14101411
continue;
14111412

1412-
inet_sk_state_store(sk, inet_sk_state_load(ssk));
1413+
/* We need to propagate only transition to CLOSE state.
1414+
* Orphaned socket will see such state change via
1415+
* subflow_sched_work_if_closed() and that path will properly
1416+
* destroy the msk as needed.
1417+
*/
1418+
ssk_state = inet_sk_state_load(ssk);
1419+
if (ssk_state == TCP_CLOSE && !sock_flag(sk, SOCK_DEAD))
1420+
inet_sk_state_store(sk, ssk_state);
14131421
sk->sk_err = -err;
14141422

14151423
/* This barrier is coupled with smp_rmb() in mptcp_poll() */
@@ -1679,7 +1687,7 @@ int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
16791687
if (err)
16801688
return err;
16811689

1682-
lock_sock(sf->sk);
1690+
lock_sock_nested(sf->sk, SINGLE_DEPTH_NESTING);
16831691

16841692
/* the newly created socket has to be in the same cgroup as its parent */
16851693
mptcp_attach_cgroup(sk, sf->sk);

tools/testing/selftests/net/mptcp/mptcp_join.sh

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,12 @@ kill_events_pids()
498498
kill_wait $evts_ns2_pid
499499
}
500500

501+
kill_tests_wait()
502+
{
503+
kill -SIGUSR1 $(ip netns pids $ns2) $(ip netns pids $ns1)
504+
wait
505+
}
506+
501507
pm_nl_set_limits()
502508
{
503509
local ns=$1
@@ -1694,6 +1700,7 @@ chk_subflow_nr()
16941700
local subflow_nr=$3
16951701
local cnt1
16961702
local cnt2
1703+
local dump_stats
16971704

16981705
if [ -n "${need_title}" ]; then
16991706
printf "%03u %-36s %s" "${TEST_COUNT}" "${TEST_NAME}" "${msg}"
@@ -1711,7 +1718,12 @@ chk_subflow_nr()
17111718
echo "[ ok ]"
17121719
fi
17131720

1714-
[ "${dump_stats}" = 1 ] && ( ss -N $ns1 -tOni ; ss -N $ns1 -tOni | grep token; ip -n $ns1 mptcp endpoint )
1721+
if [ "${dump_stats}" = 1 ]; then
1722+
ss -N $ns1 -tOni
1723+
ss -N $ns1 -tOni | grep token
1724+
ip -n $ns1 mptcp endpoint
1725+
dump_stats
1726+
fi
17151727
}
17161728

17171729
chk_link_usage()
@@ -3049,7 +3061,7 @@ endpoint_tests()
30493061
pm_nl_set_limits $ns1 2 2
30503062
pm_nl_set_limits $ns2 2 2
30513063
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
3052-
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow &
3064+
run_tests $ns1 $ns2 10.0.1.1 0 0 0 slow 2>/dev/null &
30533065

30543066
wait_mpj $ns1
30553067
pm_nl_check_endpoint 1 "creation" \
@@ -3062,14 +3074,14 @@ endpoint_tests()
30623074
pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
30633075
pm_nl_check_endpoint 0 "modif is allowed" \
30643076
$ns2 10.0.2.2 id 1 flags signal
3065-
wait
3077+
kill_tests_wait
30663078
fi
30673079

30683080
if reset "delete and re-add"; then
30693081
pm_nl_set_limits $ns1 1 1
30703082
pm_nl_set_limits $ns2 1 1
30713083
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
3072-
run_tests $ns1 $ns2 10.0.1.1 4 0 0 slow &
3084+
run_tests $ns1 $ns2 10.0.1.1 4 0 0 speed_20 2>/dev/null &
30733085

30743086
wait_mpj $ns2
30753087
pm_nl_del_endpoint $ns2 2 10.0.2.2
@@ -3079,7 +3091,7 @@ endpoint_tests()
30793091
pm_nl_add_endpoint $ns2 10.0.2.2 dev ns2eth2 flags subflow
30803092
wait_mpj $ns2
30813093
chk_subflow_nr "" "after re-add" 2
3082-
wait
3094+
kill_tests_wait
30833095
fi
30843096
}
30853097

0 commit comments

Comments
 (0)