Skip to content

Commit efd5a4c

Browse files
geliangtangkuba-moo
authored andcommitted
mptcp: add the address ID assignment bitmap
Currently the address ID set by the netlink PM from user-space is overridden by the kernel. This patch added the address ID assignment bitmap to allow user-space to set the address ID. Use a per netns bitmask id_bitmap (256 bits) to keep track of in-use IDs. And use next_id to keep track of the highest ID currently in use. If the user-space provides an ID at endpoint creation time, try to use it. If already in use, endpoint creation fails. Otherwise pick the first ID available after the highest currently in use, with wrap-around. Signed-off-by: Geliang Tang <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 43b3983 commit efd5a4c

File tree

1 file changed

+54
-18
lines changed

1 file changed

+54
-18
lines changed

net/mptcp/pm_netlink.c

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ struct mptcp_pm_add_entry {
3636
u8 retrans_times;
3737
};
3838

39+
#define MAX_ADDR_ID 255
40+
#define BITMAP_SZ DIV_ROUND_UP(MAX_ADDR_ID + 1, BITS_PER_LONG)
41+
3942
struct pm_nl_pernet {
4043
/* protects pernet updates */
4144
spinlock_t lock;
@@ -46,6 +49,7 @@ struct pm_nl_pernet {
4649
unsigned int local_addr_max;
4750
unsigned int subflows_max;
4851
unsigned int next_id;
52+
unsigned long id_bitmap[BITMAP_SZ];
4953
};
5054

5155
#define MPTCP_PM_ADDR_MAX 8
@@ -524,10 +528,12 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
524528
/* to keep the code simple, don't do IDR-like allocation for address ID,
525529
* just bail when we exceed limits
526530
*/
527-
if (pernet->next_id > 255)
528-
goto out;
531+
if (pernet->next_id == MAX_ADDR_ID)
532+
pernet->next_id = 1;
529533
if (pernet->addrs >= MPTCP_PM_ADDR_MAX)
530534
goto out;
535+
if (test_bit(entry->addr.id, pernet->id_bitmap))
536+
goto out;
531537

532538
/* do not insert duplicate address, differentiate on port only
533539
* singled addresses
@@ -539,12 +545,30 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
539545
goto out;
540546
}
541547

548+
if (!entry->addr.id) {
549+
find_next:
550+
entry->addr.id = find_next_zero_bit(pernet->id_bitmap,
551+
MAX_ADDR_ID + 1,
552+
pernet->next_id);
553+
if ((!entry->addr.id || entry->addr.id > MAX_ADDR_ID) &&
554+
pernet->next_id != 1) {
555+
pernet->next_id = 1;
556+
goto find_next;
557+
}
558+
}
559+
560+
if (!entry->addr.id || entry->addr.id > MAX_ADDR_ID)
561+
goto out;
562+
563+
__set_bit(entry->addr.id, pernet->id_bitmap);
564+
if (entry->addr.id > pernet->next_id)
565+
pernet->next_id = entry->addr.id;
566+
542567
if (entry->addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)
543568
pernet->add_addr_signal_max++;
544569
if (entry->addr.flags & MPTCP_PM_ADDR_FLAG_SUBFLOW)
545570
pernet->local_addr_max++;
546571

547-
entry->addr.id = pernet->next_id++;
548572
pernet->addrs++;
549573
list_add_tail_rcu(&entry->list, &pernet->local_addr_list);
550574
ret = entry->addr.id;
@@ -597,6 +621,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
597621
entry->addr = skc_local;
598622
entry->addr.ifindex = 0;
599623
entry->addr.flags = 0;
624+
entry->addr.id = 0;
600625
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
601626
if (ret < 0)
602627
kfree(entry);
@@ -857,6 +882,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
857882

858883
pernet->addrs--;
859884
list_del_rcu(&entry->list);
885+
__clear_bit(entry->addr.id, pernet->id_bitmap);
860886
spin_unlock_bh(&pernet->lock);
861887

862888
mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
@@ -894,6 +920,8 @@ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
894920
spin_lock_bh(&pernet->lock);
895921
list_splice_init(&pernet->local_addr_list, &free_list);
896922
__reset_counters(pernet);
923+
pernet->next_id = 1;
924+
bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
897925
spin_unlock_bh(&pernet->lock);
898926
__flush_addrs(sock_net(skb->sk), &free_list);
899927
return 0;
@@ -994,27 +1022,34 @@ static int mptcp_nl_cmd_dump_addrs(struct sk_buff *msg,
9941022
struct pm_nl_pernet *pernet;
9951023
int id = cb->args[0];
9961024
void *hdr;
1025+
int i;
9971026

9981027
pernet = net_generic(net, pm_nl_pernet_id);
9991028

10001029
spin_lock_bh(&pernet->lock);
1001-
list_for_each_entry(entry, &pernet->local_addr_list, list) {
1002-
if (entry->addr.id <= id)
1003-
continue;
1004-
1005-
hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
1006-
cb->nlh->nlmsg_seq, &mptcp_genl_family,
1007-
NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
1008-
if (!hdr)
1009-
break;
1030+
for (i = id; i < MAX_ADDR_ID + 1; i++) {
1031+
if (test_bit(i, pernet->id_bitmap)) {
1032+
entry = __lookup_addr_by_id(pernet, i);
1033+
if (!entry)
1034+
break;
1035+
1036+
if (entry->addr.id <= id)
1037+
continue;
1038+
1039+
hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
1040+
cb->nlh->nlmsg_seq, &mptcp_genl_family,
1041+
NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
1042+
if (!hdr)
1043+
break;
1044+
1045+
if (mptcp_nl_fill_addr(msg, entry) < 0) {
1046+
genlmsg_cancel(msg, hdr);
1047+
break;
1048+
}
10101049

1011-
if (mptcp_nl_fill_addr(msg, entry) < 0) {
1012-
genlmsg_cancel(msg, hdr);
1013-
break;
1050+
id = entry->addr.id;
1051+
genlmsg_end(msg, hdr);
10141052
}
1015-
1016-
id = entry->addr.id;
1017-
genlmsg_end(msg, hdr);
10181053
}
10191054
spin_unlock_bh(&pernet->lock);
10201055

@@ -1148,6 +1183,7 @@ static int __net_init pm_nl_init_net(struct net *net)
11481183
INIT_LIST_HEAD_RCU(&pernet->local_addr_list);
11491184
__reset_counters(pernet);
11501185
pernet->next_id = 1;
1186+
bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
11511187
spin_lock_init(&pernet->lock);
11521188
return 0;
11531189
}

0 commit comments

Comments
 (0)