This patch adds userspace PM address entry refcont. Add a new refcont
filed in struct mptcp_pm_addr_entry, inited to 1, and another filed
subflows, inited to 0, to store how many subflows have been established
on this address entry.
Increase both values in mptcp_nl_cmd_sf_create(), and decrease refcont
in mptcp_userspace_pm_delete_local_addr() according the subflows value.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
net/mptcp/pm_userspace.c | 27 +++++++++++++++++++++------
net/mptcp/protocol.h | 3 +++
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 359ecc65fc73..091f299db010 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -70,6 +70,8 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
1);
list_add_tail_rcu(&e->list, &msk->pm.userspace_pm_local_addr_list);
msk->pm.local_addr_used++;
+ e->subflows = 0;
+ refcount_set(&e->refcnt, 1);
ret = e->addr.id;
} else if (match) {
ret = entry->addr.id;
@@ -102,14 +104,20 @@ static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk,
struct mptcp_pm_addr_entry *addr)
{
struct mptcp_pm_addr_entry *entry;
+ int i;
entry = mptcp_userspace_pm_get_entry(msk, &addr->addr);
if (!entry)
return -EINVAL;
- /* TODO: a refcount is needed because the entry can
- * be used multiple times (e.g. fullmesh mode).
- */
+ for (i = 0; i < entry->subflows; i++) {
+ if (!refcount_dec_not_one(&entry->refcnt)) {
+ pr_debug("userspace refcount error: refcnt=%d, subflows=%d",
+ refcount_read(&entry->refcnt), entry->subflows);
+ return -EINVAL;
+ }
+ }
+
list_del_rcu(&entry->list);
kfree(entry);
msk->pm.local_addr_used--;
@@ -380,10 +388,17 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info)
release_sock(sk);
spin_lock_bh(&msk->pm.lock);
- if (err)
+ if (err) {
mptcp_userspace_pm_delete_local_addr(msk, &local);
- else
- msk->pm.subflows++;
+ } else {
+ struct mptcp_pm_addr_entry *entry;
+
+ entry = mptcp_userspace_pm_get_entry(msk, &addr_l);
+ if (entry && refcount_inc_not_zero(&entry->refcnt)) {
+ msk->pm.subflows++;
+ entry->subflows++;
+ }
+ }
spin_unlock_bh(&msk->pm.lock);
create_err:
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 15c85be21fd9..06465c8c21e4 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -8,6 +8,7 @@
#define __MPTCP_PROTOCOL_H
#include <linux/random.h>
+#include <linux/refcount.h>
#include <net/tcp.h>
#include <net/inet_connection_sock.h>
#include <uapi/linux/mptcp.h>
@@ -241,6 +242,8 @@ struct mptcp_pm_addr_entry {
u8 flags;
int ifindex;
struct socket *lsk;
+ u8 subflows;
+ refcount_t refcnt;
};
struct mptcp_data_frag {
--
2.35.3