Skip to content

Commit a88c9e4

Browse files
Paolo Abenidavem330
Paolo Abeni
authored andcommitted
mptcp: do not block subflows creation on errors
If the MPTCP configuration allows for multiple subflows creation, and the first additional subflows never reach the fully established status - e.g. due to packets drop or reset - the in kernel path manager do not move to the next subflow. This patch introduces a new PM helper to cope with MPJ subflow creation failure and delay and hook it where appropriate. Such helper triggers additional subflow creation, as needed and updates the PM subflow counter, if the current one is closing. Additionally start all the needed additional subflows as soon as the MPTCP socket is fully established, so we don't have to cope with slow MPJ handshake blocking the next subflow creation. Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 86e39e0 commit a88c9e4

File tree

4 files changed

+71
-31
lines changed

4 files changed

+71
-31
lines changed

net/mptcp/pm.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,28 @@ void mptcp_pm_subflow_established(struct mptcp_sock *msk)
172172
spin_unlock_bh(&pm->lock);
173173
}
174174

175-
void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id)
175+
void mptcp_pm_subflow_check_next(struct mptcp_sock *msk, const struct sock *ssk,
176+
const struct mptcp_subflow_context *subflow)
176177
{
177-
pr_debug("msk=%p", msk);
178+
struct mptcp_pm_data *pm = &msk->pm;
179+
bool update_subflows;
180+
181+
update_subflows = (ssk->sk_state == TCP_CLOSE) &&
182+
(subflow->request_join || subflow->mp_join);
183+
if (!READ_ONCE(pm->work_pending) && !update_subflows)
184+
return;
185+
186+
spin_lock_bh(&pm->lock);
187+
if (update_subflows)
188+
pm->subflows--;
189+
190+
/* Even if this subflow is not really established, tell the PM to try
191+
* to pick the next ones, if possible.
192+
*/
193+
if (mptcp_pm_nl_check_work_pending(msk))
194+
mptcp_pm_schedule_work(msk, MPTCP_PM_SUBFLOW_ESTABLISHED);
195+
196+
spin_unlock_bh(&pm->lock);
178197
}
179198

180199
void mptcp_pm_add_addr_received(struct mptcp_sock *msk,

net/mptcp/pm_netlink.c

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,17 @@ unsigned int mptcp_pm_get_local_addr_max(struct mptcp_sock *msk)
251251
}
252252
EXPORT_SYMBOL_GPL(mptcp_pm_get_local_addr_max);
253253

254-
static void check_work_pending(struct mptcp_sock *msk)
254+
bool mptcp_pm_nl_check_work_pending(struct mptcp_sock *msk)
255255
{
256256
struct pm_nl_pernet *pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
257257

258258
if (msk->pm.subflows == mptcp_pm_get_subflows_max(msk) ||
259259
(find_next_and_bit(pernet->id_bitmap, msk->pm.id_avail_bitmap,
260-
MPTCP_PM_MAX_ADDR_ID + 1, 0) == MPTCP_PM_MAX_ADDR_ID + 1))
260+
MPTCP_PM_MAX_ADDR_ID + 1, 0) == MPTCP_PM_MAX_ADDR_ID + 1)) {
261261
WRITE_ONCE(msk->pm.work_pending, false);
262+
return false;
263+
}
264+
return true;
262265
}
263266

264267
struct mptcp_pm_add_entry *
@@ -427,29 +430,36 @@ static bool lookup_address_in_vec(struct mptcp_addr_info *addrs, unsigned int nr
427430
static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk, bool fullmesh,
428431
struct mptcp_addr_info *addrs)
429432
{
433+
bool deny_id0 = READ_ONCE(msk->pm.remote_deny_join_id0);
430434
struct sock *sk = (struct sock *)msk, *ssk;
431435
struct mptcp_subflow_context *subflow;
432436
struct mptcp_addr_info remote = { 0 };
433437
unsigned int subflows_max;
434438
int i = 0;
435439

436440
subflows_max = mptcp_pm_get_subflows_max(msk);
441+
remote_address((struct sock_common *)sk, &remote);
437442

438443
/* Non-fullmesh endpoint, fill in the single entry
439444
* corresponding to the primary MPC subflow remote address
440445
*/
441446
if (!fullmesh) {
442-
remote_address((struct sock_common *)sk, &remote);
447+
if (deny_id0)
448+
return 0;
449+
443450
msk->pm.subflows++;
444451
addrs[i++] = remote;
445452
} else {
446453
mptcp_for_each_subflow(msk, subflow) {
447454
ssk = mptcp_subflow_tcp_sock(subflow);
448-
remote_address((struct sock_common *)ssk, &remote);
449-
if (!lookup_address_in_vec(addrs, i, &remote) &&
455+
remote_address((struct sock_common *)ssk, &addrs[i]);
456+
if (deny_id0 && addresses_equal(&addrs[i], &remote, false))
457+
continue;
458+
459+
if (!lookup_address_in_vec(addrs, i, &addrs[i]) &&
450460
msk->pm.subflows < subflows_max) {
451461
msk->pm.subflows++;
452-
addrs[i++] = remote;
462+
i++;
453463
}
454464
}
455465
}
@@ -503,12 +513,12 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
503513

504514
/* do lazy endpoint usage accounting for the MPC subflows */
505515
if (unlikely(!(msk->pm.status & BIT(MPTCP_PM_MPC_ENDPOINT_ACCOUNTED))) && msk->first) {
506-
struct mptcp_addr_info local;
516+
struct mptcp_addr_info mpc_addr;
507517
int mpc_id;
508518

509-
local_address((struct sock_common *)msk->first, &local);
510-
mpc_id = lookup_id_by_addr(pernet, &local);
511-
if (mpc_id < 0)
519+
local_address((struct sock_common *)msk->first, &mpc_addr);
520+
mpc_id = lookup_id_by_addr(pernet, &mpc_addr);
521+
if (mpc_id >= 0)
512522
__clear_bit(mpc_id, msk->pm.id_avail_bitmap);
513523

514524
msk->pm.status |= BIT(MPTCP_PM_MPC_ENDPOINT_ACCOUNTED);
@@ -534,26 +544,28 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
534544
}
535545

536546
/* check if should create a new subflow */
537-
if (msk->pm.local_addr_used < local_addr_max &&
538-
msk->pm.subflows < subflows_max &&
539-
!READ_ONCE(msk->pm.remote_deny_join_id0)) {
547+
while (msk->pm.local_addr_used < local_addr_max &&
548+
msk->pm.subflows < subflows_max) {
549+
struct mptcp_addr_info addrs[MPTCP_PM_ADDR_MAX];
550+
bool fullmesh;
551+
int i, nr;
552+
540553
local = select_local_address(pernet, msk);
541-
if (local) {
542-
bool fullmesh = !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH);
543-
struct mptcp_addr_info addrs[MPTCP_PM_ADDR_MAX];
544-
int i, nr;
554+
if (!local)
555+
break;
545556

546-
msk->pm.local_addr_used++;
547-
nr = fill_remote_addresses_vec(msk, fullmesh, addrs);
548-
if (nr)
549-
__clear_bit(local->addr.id, msk->pm.id_avail_bitmap);
550-
spin_unlock_bh(&msk->pm.lock);
551-
for (i = 0; i < nr; i++)
552-
__mptcp_subflow_connect(sk, &local->addr, &addrs[i]);
553-
spin_lock_bh(&msk->pm.lock);
554-
}
557+
fullmesh = !!(local->flags & MPTCP_PM_ADDR_FLAG_FULLMESH);
558+
559+
msk->pm.local_addr_used++;
560+
nr = fill_remote_addresses_vec(msk, fullmesh, addrs);
561+
if (nr)
562+
__clear_bit(local->addr.id, msk->pm.id_avail_bitmap);
563+
spin_unlock_bh(&msk->pm.lock);
564+
for (i = 0; i < nr; i++)
565+
__mptcp_subflow_connect(sk, &local->addr, &addrs[i]);
566+
spin_lock_bh(&msk->pm.lock);
555567
}
556-
check_work_pending(msk);
568+
mptcp_pm_nl_check_work_pending(msk);
557569
}
558570

559571
static void mptcp_pm_nl_fully_established(struct mptcp_sock *msk)
@@ -760,11 +772,12 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
760772
i, rm_list->ids[i], subflow->local_id, subflow->remote_id);
761773
spin_unlock_bh(&msk->pm.lock);
762774
mptcp_subflow_shutdown(sk, ssk, how);
775+
776+
/* the following takes care of updating the subflows counter */
763777
mptcp_close_ssk(sk, ssk, subflow);
764778
spin_lock_bh(&msk->pm.lock);
765779

766780
removed = true;
767-
msk->pm.subflows--;
768781
__MPTCP_INC_STATS(sock_net(sk), rm_type);
769782
}
770783
__set_bit(rm_list->ids[1], msk->pm.id_avail_bitmap);

net/mptcp/protocol.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,6 +2332,12 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
23322332
{
23332333
if (sk->sk_state == TCP_ESTABLISHED)
23342334
mptcp_event(MPTCP_EVENT_SUB_CLOSED, mptcp_sk(sk), ssk, GFP_KERNEL);
2335+
2336+
/* subflow aborted before reaching the fully_established status
2337+
* attempt the creation of the next subflow
2338+
*/
2339+
mptcp_pm_subflow_check_next(mptcp_sk(sk), ssk, subflow);
2340+
23352341
__mptcp_close_ssk(sk, ssk, subflow, MPTCP_CF_PUSH);
23362342
}
23372343

net/mptcp/protocol.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,9 @@ void mptcp_pm_fully_established(struct mptcp_sock *msk, const struct sock *ssk,
743743
bool mptcp_pm_allow_new_subflow(struct mptcp_sock *msk);
744744
void mptcp_pm_connection_closed(struct mptcp_sock *msk);
745745
void mptcp_pm_subflow_established(struct mptcp_sock *msk);
746-
void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id);
746+
bool mptcp_pm_nl_check_work_pending(struct mptcp_sock *msk);
747+
void mptcp_pm_subflow_check_next(struct mptcp_sock *msk, const struct sock *ssk,
748+
const struct mptcp_subflow_context *subflow);
747749
void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
748750
const struct mptcp_addr_info *addr);
749751
void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,

0 commit comments

Comments
 (0)