Skip to content

Commit 86e39e0

Browse files
Paolo Abenidavem330
Paolo Abeni
authored andcommitted
mptcp: keep track of local endpoint still available for each msk
Include into the path manager status a bitmap tracking the list of local endpoints still available - not yet used - for the relevant mptcp socket. Keep such map updated at endpoint creation/deletion time, so that we can easily skip already used endpoint at local address selection time. The endpoint used by the initial subflow is lazyly accounted at subflow creation time: the usage bitmap is be up2date before endpoint selection and we avoid such unneeded task in some relevant scenarios - e.g. busy servers accepting incoming subflows but not creating any additional ones nor annuncing additional addresses. Overall this allows for fair local endpoints usage in case of subflow failure. As a side effect, this patch also enforces that each endpoint is used at most once for each mptcp connection. Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 71b077e commit 86e39e0

File tree

5 files changed

+91
-55
lines changed

5 files changed

+91
-55
lines changed

net/mptcp/pm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ void mptcp_pm_data_reset(struct mptcp_sock *msk)
370370
WRITE_ONCE(msk->pm.accept_subflow, false);
371371
WRITE_ONCE(msk->pm.remote_deny_join_id0, false);
372372
msk->pm.status = 0;
373+
bitmap_fill(msk->pm.id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
373374

374375
mptcp_pm_nl_data_init(msk);
375376
}

net/mptcp/pm_netlink.c

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ struct mptcp_pm_add_entry {
3838
u8 retrans_times;
3939
};
4040

41-
/* max value of mptcp_addr_info.id */
42-
#define MAX_ADDR_ID U8_MAX
43-
#define BITMAP_SZ DIV_ROUND_UP(MAX_ADDR_ID + 1, BITS_PER_LONG)
44-
4541
struct pm_nl_pernet {
4642
/* protects pernet updates */
4743
spinlock_t lock;
@@ -53,14 +49,14 @@ struct pm_nl_pernet {
5349
unsigned int local_addr_max;
5450
unsigned int subflows_max;
5551
unsigned int next_id;
56-
unsigned long id_bitmap[BITMAP_SZ];
52+
DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
5753
};
5854

5955
#define MPTCP_PM_ADDR_MAX 8
6056
#define ADD_ADDR_RETRANS_MAX 3
6157

6258
static bool addresses_equal(const struct mptcp_addr_info *a,
63-
struct mptcp_addr_info *b, bool use_port)
59+
const struct mptcp_addr_info *b, bool use_port)
6460
{
6561
bool addr_equals = false;
6662

@@ -174,6 +170,9 @@ select_local_address(const struct pm_nl_pernet *pernet,
174170
if (!(entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW))
175171
continue;
176172

173+
if (!test_bit(entry->addr.id, msk->pm.id_avail_bitmap))
174+
continue;
175+
177176
if (entry->addr.family != sk->sk_family) {
178177
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
179178
if ((entry->addr.family == AF_INET &&
@@ -184,23 +183,17 @@ select_local_address(const struct pm_nl_pernet *pernet,
184183
continue;
185184
}
186185

187-
/* avoid any address already in use by subflows and
188-
* pending join
189-
*/
190-
if (!lookup_subflow_by_saddr(&msk->conn_list, &entry->addr)) {
191-
ret = entry;
192-
break;
193-
}
186+
ret = entry;
187+
break;
194188
}
195189
rcu_read_unlock();
196190
return ret;
197191
}
198192

199193
static struct mptcp_pm_addr_entry *
200-
select_signal_address(struct pm_nl_pernet *pernet, unsigned int pos)
194+
select_signal_address(struct pm_nl_pernet *pernet, struct mptcp_sock *msk)
201195
{
202196
struct mptcp_pm_addr_entry *entry, *ret = NULL;
203-
int i = 0;
204197

205198
rcu_read_lock();
206199
/* do not keep any additional per socket state, just signal
@@ -209,12 +202,14 @@ select_signal_address(struct pm_nl_pernet *pernet, unsigned int pos)
209202
* can lead to additional addresses not being announced.
210203
*/
211204
list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
205+
if (!test_bit(entry->addr.id, msk->pm.id_avail_bitmap))
206+
continue;
207+
212208
if (!(entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
213209
continue;
214-
if (i++ == pos) {
215-
ret = entry;
216-
break;
217-
}
210+
211+
ret = entry;
212+
break;
218213
}
219214
rcu_read_unlock();
220215
return ret;
@@ -258,9 +253,11 @@ EXPORT_SYMBOL_GPL(mptcp_pm_get_local_addr_max);
258253

259254
static void check_work_pending(struct mptcp_sock *msk)
260255
{
261-
if (msk->pm.add_addr_signaled == mptcp_pm_get_add_addr_signal_max(msk) &&
262-
(msk->pm.local_addr_used == mptcp_pm_get_local_addr_max(msk) ||
263-
msk->pm.subflows == mptcp_pm_get_subflows_max(msk)))
256+
struct pm_nl_pernet *pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
257+
258+
if (msk->pm.subflows == mptcp_pm_get_subflows_max(msk) ||
259+
(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))
264261
WRITE_ONCE(msk->pm.work_pending, false);
265262
}
266263

@@ -460,6 +457,35 @@ static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk, bool fullm
460457
return i;
461458
}
462459

460+
static struct mptcp_pm_addr_entry *
461+
__lookup_addr_by_id(struct pm_nl_pernet *pernet, unsigned int id)
462+
{
463+
struct mptcp_pm_addr_entry *entry;
464+
465+
list_for_each_entry(entry, &pernet->local_addr_list, list) {
466+
if (entry->addr.id == id)
467+
return entry;
468+
}
469+
return NULL;
470+
}
471+
472+
static int
473+
lookup_id_by_addr(struct pm_nl_pernet *pernet, const struct mptcp_addr_info *addr)
474+
{
475+
struct mptcp_pm_addr_entry *entry;
476+
int ret = -1;
477+
478+
rcu_read_lock();
479+
list_for_each_entry(entry, &pernet->local_addr_list, list) {
480+
if (addresses_equal(&entry->addr, addr, entry->addr.port)) {
481+
ret = entry->addr.id;
482+
break;
483+
}
484+
}
485+
rcu_read_unlock();
486+
return ret;
487+
}
488+
463489
static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
464490
{
465491
struct sock *sk = (struct sock *)msk;
@@ -475,28 +501,36 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
475501
local_addr_max = mptcp_pm_get_local_addr_max(msk);
476502
subflows_max = mptcp_pm_get_subflows_max(msk);
477503

504+
/* do lazy endpoint usage accounting for the MPC subflows */
505+
if (unlikely(!(msk->pm.status & BIT(MPTCP_PM_MPC_ENDPOINT_ACCOUNTED))) && msk->first) {
506+
struct mptcp_addr_info local;
507+
int mpc_id;
508+
509+
local_address((struct sock_common *)msk->first, &local);
510+
mpc_id = lookup_id_by_addr(pernet, &local);
511+
if (mpc_id < 0)
512+
__clear_bit(mpc_id, msk->pm.id_avail_bitmap);
513+
514+
msk->pm.status |= BIT(MPTCP_PM_MPC_ENDPOINT_ACCOUNTED);
515+
}
516+
478517
pr_debug("local %d:%d signal %d:%d subflows %d:%d\n",
479518
msk->pm.local_addr_used, local_addr_max,
480519
msk->pm.add_addr_signaled, add_addr_signal_max,
481520
msk->pm.subflows, subflows_max);
482521

483522
/* check first for announce */
484523
if (msk->pm.add_addr_signaled < add_addr_signal_max) {
485-
local = select_signal_address(pernet,
486-
msk->pm.add_addr_signaled);
524+
local = select_signal_address(pernet, msk);
487525

488526
if (local) {
489527
if (mptcp_pm_alloc_anno_list(msk, local)) {
528+
__clear_bit(local->addr.id, msk->pm.id_avail_bitmap);
490529
msk->pm.add_addr_signaled++;
491530
mptcp_pm_announce_addr(msk, &local->addr, false);
492531
mptcp_pm_nl_addr_send_ack(msk);
493532
}
494-
} else {
495-
/* pick failed, avoid fourther attempts later */
496-
msk->pm.local_addr_used = add_addr_signal_max;
497533
}
498-
499-
check_work_pending(msk);
500534
}
501535

502536
/* check if should create a new subflow */
@@ -510,19 +544,16 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
510544
int i, nr;
511545

512546
msk->pm.local_addr_used++;
513-
check_work_pending(msk);
514547
nr = fill_remote_addresses_vec(msk, fullmesh, addrs);
548+
if (nr)
549+
__clear_bit(local->addr.id, msk->pm.id_avail_bitmap);
515550
spin_unlock_bh(&msk->pm.lock);
516551
for (i = 0; i < nr; i++)
517552
__mptcp_subflow_connect(sk, &local->addr, &addrs[i]);
518553
spin_lock_bh(&msk->pm.lock);
519-
return;
520554
}
521-
522-
/* lookup failed, avoid fourther attempts later */
523-
msk->pm.local_addr_used = local_addr_max;
524-
check_work_pending(msk);
525555
}
556+
check_work_pending(msk);
526557
}
527558

528559
static void mptcp_pm_nl_fully_established(struct mptcp_sock *msk)
@@ -736,6 +767,7 @@ static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
736767
msk->pm.subflows--;
737768
__MPTCP_INC_STATS(sock_net(sk), rm_type);
738769
}
770+
__set_bit(rm_list->ids[1], msk->pm.id_avail_bitmap);
739771
if (!removed)
740772
continue;
741773

@@ -765,6 +797,9 @@ void mptcp_pm_nl_work(struct mptcp_sock *msk)
765797

766798
msk_owned_by_me(msk);
767799

800+
if (!(pm->status & MPTCP_PM_WORK_MASK))
801+
return;
802+
768803
spin_lock_bh(&msk->pm.lock);
769804

770805
pr_debug("msk=%p status=%x", msk, pm->status);
@@ -810,7 +845,7 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
810845
/* to keep the code simple, don't do IDR-like allocation for address ID,
811846
* just bail when we exceed limits
812847
*/
813-
if (pernet->next_id == MAX_ADDR_ID)
848+
if (pernet->next_id == MPTCP_PM_MAX_ADDR_ID)
814849
pernet->next_id = 1;
815850
if (pernet->addrs >= MPTCP_PM_ADDR_MAX)
816851
goto out;
@@ -830,7 +865,7 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
830865
if (!entry->addr.id) {
831866
find_next:
832867
entry->addr.id = find_next_zero_bit(pernet->id_bitmap,
833-
MAX_ADDR_ID + 1,
868+
MPTCP_PM_MAX_ADDR_ID + 1,
834869
pernet->next_id);
835870
if (!entry->addr.id && pernet->next_id != 1) {
836871
pernet->next_id = 1;
@@ -1197,18 +1232,6 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
11971232
return 0;
11981233
}
11991234

1200-
static struct mptcp_pm_addr_entry *
1201-
__lookup_addr_by_id(struct pm_nl_pernet *pernet, unsigned int id)
1202-
{
1203-
struct mptcp_pm_addr_entry *entry;
1204-
1205-
list_for_each_entry(entry, &pernet->local_addr_list, list) {
1206-
if (entry->addr.id == id)
1207-
return entry;
1208-
}
1209-
return NULL;
1210-
}
1211-
12121235
int mptcp_pm_get_flags_and_ifindex_by_id(struct net *net, unsigned int id,
12131236
u8 *flags, int *ifindex)
12141237
{
@@ -1467,7 +1490,7 @@ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
14671490
list_splice_init(&pernet->local_addr_list, &free_list);
14681491
__reset_counters(pernet);
14691492
pernet->next_id = 1;
1470-
bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
1493+
bitmap_zero(pernet->id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
14711494
spin_unlock_bh(&pernet->lock);
14721495
mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
14731496
synchronize_rcu();
@@ -1577,7 +1600,7 @@ static int mptcp_nl_cmd_dump_addrs(struct sk_buff *msg,
15771600
pernet = net_generic(net, pm_nl_pernet_id);
15781601

15791602
spin_lock_bh(&pernet->lock);
1580-
for (i = id; i < MAX_ADDR_ID + 1; i++) {
1603+
for (i = id; i < MPTCP_PM_MAX_ADDR_ID + 1; i++) {
15811604
if (test_bit(i, pernet->id_bitmap)) {
15821605
entry = __lookup_addr_by_id(pernet, i);
15831606
if (!entry)

net/mptcp/protocol.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,8 +2488,7 @@ static void mptcp_worker(struct work_struct *work)
24882488

24892489
mptcp_check_fastclose(msk);
24902490

2491-
if (msk->pm.status)
2492-
mptcp_pm_nl_work(msk);
2491+
mptcp_pm_nl_work(msk);
24932492

24942493
if (test_and_clear_bit(MPTCP_WORK_EOF, &msk->flags))
24952494
mptcp_check_for_eof(msk);

net/mptcp/protocol.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,25 @@ enum mptcp_pm_status {
173173
MPTCP_PM_ADD_ADDR_SEND_ACK,
174174
MPTCP_PM_RM_ADDR_RECEIVED,
175175
MPTCP_PM_ESTABLISHED,
176-
MPTCP_PM_ALREADY_ESTABLISHED, /* persistent status, set after ESTABLISHED event */
177176
MPTCP_PM_SUBFLOW_ESTABLISHED,
177+
MPTCP_PM_ALREADY_ESTABLISHED, /* persistent status, set after ESTABLISHED event */
178+
MPTCP_PM_MPC_ENDPOINT_ACCOUNTED /* persistent status, set after MPC local address is
179+
* accounted int id_avail_bitmap
180+
*/
178181
};
179182

183+
/* Status bits below MPTCP_PM_ALREADY_ESTABLISHED need pm worker actions */
184+
#define MPTCP_PM_WORK_MASK ((1 << MPTCP_PM_ALREADY_ESTABLISHED) - 1)
185+
180186
enum mptcp_addr_signal_status {
181187
MPTCP_ADD_ADDR_SIGNAL,
182188
MPTCP_ADD_ADDR_ECHO,
183189
MPTCP_RM_ADDR_SIGNAL,
184190
};
185191

192+
/* max value of mptcp_addr_info.id */
193+
#define MPTCP_PM_MAX_ADDR_ID U8_MAX
194+
186195
struct mptcp_pm_data {
187196
struct mptcp_addr_info local;
188197
struct mptcp_addr_info remote;
@@ -201,6 +210,7 @@ struct mptcp_pm_data {
201210
u8 local_addr_used;
202211
u8 subflows;
203212
u8 status;
213+
DECLARE_BITMAP(id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
204214
struct mptcp_rm_list rm_list_tx;
205215
struct mptcp_rm_list rm_list_rx;
206216
};

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,10 @@ signal_address_tests()
10711071
ip netns exec $ns2 ./pm_nl_ctl add 10.0.3.2 flags signal
10721072
ip netns exec $ns2 ./pm_nl_ctl add 10.0.4.2 flags signal
10731073
run_tests $ns1 $ns2 10.0.1.1
1074-
chk_add_nr 4 4
1074+
1075+
# the server will not signal the address terminating
1076+
# the MPC subflow
1077+
chk_add_nr 3 3
10751078
}
10761079

10771080
link_failure_tests()

0 commit comments

Comments
 (0)