Skip to content

Commit b6c0838

Browse files
geliangtangdavem330
authored andcommitted
mptcp: remove addr and subflow in PM netlink
This patch implements the remove announced addr and subflow logic in PM netlink. When the PM netlink removes an address, we traverse all the existing msk sockets to find the relevant sockets. We add a new list named anno_list in mptcp_pm_data, to record all the announced addrs. In the traversing, we check if it has been recorded. If it has been, we trigger the RM_ADDR signal. We also check if this address is in conn_list. If it is, we remove the subflow which using this local address. Since we call mptcp_pm_free_anno_list in mptcp_destroy, we need to move __mptcp_init_sock before the mptcp_is_enabled check in mptcp_init_sock. Suggested-by: Matthieu Baerts <[email protected]> Suggested-by: Paolo Abeni <[email protected]> Suggested-by: Mat Martineau <[email protected]> Acked-by: Paolo Abeni <[email protected]> Signed-off-by: Geliang Tang <[email protected]> Reviewed-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f58f065 commit b6c0838

File tree

5 files changed

+130
-11
lines changed

5 files changed

+130
-11
lines changed

net/mptcp/pm.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
2626

2727
int mptcp_pm_remove_addr(struct mptcp_sock *msk, u8 local_id)
2828
{
29-
return -ENOTSUPP;
29+
pr_debug("msk=%p, local_id=%d", msk, local_id);
30+
31+
msk->pm.rm_id = local_id;
32+
WRITE_ONCE(msk->pm.rm_addr_signal, true);
33+
return 0;
3034
}
3135

3236
int mptcp_pm_remove_subflow(struct mptcp_sock *msk, u8 remote_id)
@@ -231,6 +235,7 @@ void mptcp_pm_data_init(struct mptcp_sock *msk)
231235
msk->pm.status = 0;
232236

233237
spin_lock_init(&msk->pm.lock);
238+
INIT_LIST_HEAD(&msk->pm.anno_list);
234239

235240
mptcp_pm_nl_data_init(msk);
236241
}

net/mptcp/pm_netlink.c

+116-6
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,50 @@ static void check_work_pending(struct mptcp_sock *msk)
177177
WRITE_ONCE(msk->pm.work_pending, false);
178178
}
179179

180+
static bool lookup_anno_list_by_saddr(struct mptcp_sock *msk,
181+
struct mptcp_addr_info *addr)
182+
{
183+
struct mptcp_pm_addr_entry *entry;
184+
185+
list_for_each_entry(entry, &msk->pm.anno_list, list) {
186+
if (addresses_equal(&entry->addr, addr, false))
187+
return true;
188+
}
189+
190+
return false;
191+
}
192+
193+
static bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
194+
struct mptcp_pm_addr_entry *entry)
195+
{
196+
struct mptcp_pm_addr_entry *clone = NULL;
197+
198+
if (lookup_anno_list_by_saddr(msk, &entry->addr))
199+
return false;
200+
201+
clone = kmemdup(entry, sizeof(*entry), GFP_ATOMIC);
202+
if (!clone)
203+
return false;
204+
205+
list_add(&clone->list, &msk->pm.anno_list);
206+
207+
return true;
208+
}
209+
210+
void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
211+
{
212+
struct mptcp_pm_addr_entry *entry, *tmp;
213+
214+
pr_debug("msk=%p", msk);
215+
216+
spin_lock_bh(&msk->pm.lock);
217+
list_for_each_entry_safe(entry, tmp, &msk->pm.anno_list, list) {
218+
list_del(&entry->list);
219+
kfree(entry);
220+
}
221+
spin_unlock_bh(&msk->pm.lock);
222+
}
223+
180224
static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
181225
{
182226
struct mptcp_addr_info remote = { 0 };
@@ -197,8 +241,10 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
197241
msk->pm.add_addr_signaled);
198242

199243
if (local) {
200-
msk->pm.add_addr_signaled++;
201-
mptcp_pm_announce_addr(msk, &local->addr, false);
244+
if (mptcp_pm_alloc_anno_list(msk, local)) {
245+
msk->pm.add_addr_signaled++;
246+
mptcp_pm_announce_addr(msk, &local->addr, false);
247+
}
202248
} else {
203249
/* pick failed, avoid fourther attempts later */
204250
msk->pm.local_addr_used = msk->pm.add_addr_signal_max;
@@ -567,6 +613,68 @@ __lookup_addr_by_id(struct pm_nl_pernet *pernet, unsigned int id)
567613
return NULL;
568614
}
569615

616+
static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
617+
struct mptcp_addr_info *addr)
618+
{
619+
struct mptcp_pm_addr_entry *entry, *tmp;
620+
621+
list_for_each_entry_safe(entry, tmp, &msk->pm.anno_list, list) {
622+
if (addresses_equal(&entry->addr, addr, false)) {
623+
list_del(&entry->list);
624+
kfree(entry);
625+
return true;
626+
}
627+
}
628+
629+
return false;
630+
}
631+
632+
static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
633+
struct mptcp_addr_info *addr,
634+
bool force)
635+
{
636+
bool ret;
637+
638+
spin_lock_bh(&msk->pm.lock);
639+
ret = remove_anno_list_by_saddr(msk, addr);
640+
if (ret || force)
641+
mptcp_pm_remove_addr(msk, addr->id);
642+
spin_unlock_bh(&msk->pm.lock);
643+
return ret;
644+
}
645+
646+
static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
647+
struct mptcp_addr_info *addr)
648+
{
649+
struct mptcp_sock *msk;
650+
long s_slot = 0, s_num = 0;
651+
652+
pr_debug("remove_id=%d", addr->id);
653+
654+
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
655+
struct sock *sk = (struct sock *)msk;
656+
bool remove_subflow;
657+
658+
if (list_empty(&msk->conn_list)) {
659+
mptcp_pm_remove_anno_addr(msk, addr, false);
660+
goto next;
661+
}
662+
663+
lock_sock(sk);
664+
remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
665+
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow);
666+
if (remove_subflow)
667+
mptcp_pm_remove_subflow(msk, addr->id);
668+
release_sock(sk);
669+
670+
next:
671+
sock_put(sk);
672+
cond_resched();
673+
}
674+
675+
return 0;
676+
}
677+
570678
static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
571679
{
572680
struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
@@ -582,8 +690,8 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
582690
entry = __lookup_addr_by_id(pernet, addr.addr.id);
583691
if (!entry) {
584692
GENL_SET_ERR_MSG(info, "address not found");
585-
ret = -EINVAL;
586-
goto out;
693+
spin_unlock_bh(&pernet->lock);
694+
return -EINVAL;
587695
}
588696
if (entry->addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)
589697
pernet->add_addr_signal_max--;
@@ -592,9 +700,11 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
592700

593701
pernet->addrs--;
594702
list_del_rcu(&entry->list);
595-
kfree_rcu(entry, rcu);
596-
out:
597703
spin_unlock_bh(&pernet->lock);
704+
705+
mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
706+
kfree_rcu(entry, rcu);
707+
598708
return ret;
599709
}
600710

net/mptcp/protocol.c

+5-4
Original file line numberDiff line numberDiff line change
@@ -1810,16 +1810,16 @@ static int mptcp_init_sock(struct sock *sk)
18101810
struct net *net = sock_net(sk);
18111811
int ret;
18121812

1813+
ret = __mptcp_init_sock(sk);
1814+
if (ret)
1815+
return ret;
1816+
18131817
if (!mptcp_is_enabled(net))
18141818
return -ENOPROTOOPT;
18151819

18161820
if (unlikely(!net->mib.mptcp_statistics) && !mptcp_mib_alloc(net))
18171821
return -ENOMEM;
18181822

1819-
ret = __mptcp_init_sock(sk);
1820-
if (ret)
1821-
return ret;
1822-
18231823
ret = __mptcp_socket_create(mptcp_sk(sk));
18241824
if (ret)
18251825
return ret;
@@ -2137,6 +2137,7 @@ static void mptcp_destroy(struct sock *sk)
21372137
if (msk->cached_ext)
21382138
__skb_ext_put(msk->cached_ext);
21392139

2140+
mptcp_pm_free_anno_list(msk);
21402141
sk_sockets_allocated_dec(sk);
21412142
}
21422143

net/mptcp/protocol.h

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ enum mptcp_pm_status {
160160
struct mptcp_pm_data {
161161
struct mptcp_addr_info local;
162162
struct mptcp_addr_info remote;
163+
struct list_head anno_list;
163164

164165
spinlock_t lock; /*protects the whole PM data */
165166

@@ -441,6 +442,7 @@ void mptcp_pm_subflow_closed(struct mptcp_sock *msk, u8 id);
441442
void mptcp_pm_add_addr_received(struct mptcp_sock *msk,
442443
const struct mptcp_addr_info *addr);
443444
void mptcp_pm_rm_addr_received(struct mptcp_sock *msk, u8 rm_id);
445+
void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
444446

445447
int mptcp_pm_announce_addr(struct mptcp_sock *msk,
446448
const struct mptcp_addr_info *addr,

net/mptcp/subflow.c

+1
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ static void mptcp_sock_destruct(struct sock *sk)
437437

438438
skb_rbtree_purge(&mptcp_sk(sk)->out_of_order_queue);
439439
mptcp_token_destroy(mptcp_sk(sk));
440+
mptcp_pm_free_anno_list(mptcp_sk(sk));
440441
inet_sock_destruct(sk);
441442
}
442443

0 commit comments

Comments
 (0)