summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeliang Tang <geliangtang@gmail.com>2021-03-13 04:16:17 +0300
committerDavid S. Miller <davem@davemloft.net>2021-03-13 04:47:45 +0300
commit06faa22710342bca5e9c249634199c650799fce6 (patch)
tree9c4a5947223ea8c4e5010838eaf2c11d6b983d9d
parentddd14bb85dd8d26e10a2ce4f9606879b94e81888 (diff)
downloadlinux-06faa22710342bca5e9c249634199c650799fce6.tar.xz
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: Geliang Tang <geliangtang@gmail.com> Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/mptcp/pm_netlink.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 769a05d836da..a5f6ab96a1b4 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -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)) {