Commit 06faa227 authored by Geliang Tang's avatar Geliang Tang Committed by David S. Miller
Browse files

mptcp: remove multi addresses and subflows in PM



This patch implemented the function to remove a list of addresses and
subflows, named mptcp_nl_remove_addrs_list, which had a input parameter
rm_list as the removing addresses list.

In mptcp_nl_remove_addrs_list, traverse all the existing msk sockets to
invoke mptcp_pm_remove_addrs_and_subflows to remove a list of addresses
for each msk socket.

In mptcp_pm_remove_addrs_and_subflows, traverse all the addresses in the
removing addresses list, to find whether this address is in the conn_list
or anno_list. If it is, put the address ID into the removing address list
or the removing subflow list, and pass the two lists to
mptcp_pm_remove_addr and mptcp_pm_remove_subflow.

Signed-off-by: default avatarGeliang Tang <geliangtang@gmail.com>
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ddd14bb8
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -1200,6 +1200,54 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
	return ret;
}

static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
					       struct list_head *rm_list)
{
	struct mptcp_rm_list alist = { .nr = 0 }, slist = { .nr = 0 };
	struct mptcp_pm_addr_entry *entry;

	list_for_each_entry(entry, rm_list, list) {
		if (lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) &&
		    alist.nr < MPTCP_RM_IDS_MAX &&
		    slist.nr < MPTCP_RM_IDS_MAX) {
			alist.ids[alist.nr++] = entry->addr.id;
			slist.ids[slist.nr++] = entry->addr.id;
		} else if (remove_anno_list_by_saddr(msk, &entry->addr) &&
			 alist.nr < MPTCP_RM_IDS_MAX) {
			alist.ids[alist.nr++] = entry->addr.id;
		}
	}

	if (alist.nr) {
		spin_lock_bh(&msk->pm.lock);
		mptcp_pm_remove_addr(msk, &alist);
		spin_unlock_bh(&msk->pm.lock);
	}
	if (slist.nr)
		mptcp_pm_remove_subflow(msk, &slist);
}

static void mptcp_nl_remove_addrs_list(struct net *net,
				       struct list_head *rm_list)
{
	long s_slot = 0, s_num = 0;
	struct mptcp_sock *msk;

	if (list_empty(rm_list))
		return;

	while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
		struct sock *sk = (struct sock *)msk;

		lock_sock(sk);
		mptcp_pm_remove_addrs_and_subflows(msk, rm_list);
		release_sock(sk);

		sock_put(sk);
		cond_resched();
	}
}

static void __flush_addrs(struct net *net, struct list_head *list)
{
	while (!list_empty(list)) {