This change updates struct mptcp_pm_addr_entry to store a
listening socket (lsk) reference, i.e. a pointer to a reference
counted structure containing the lsk (struct socket *) instead
of the lsk itself. Code blocks that previously operated on
the lsk in struct mptcp_pm_addr_entry have been updated to work
with the lsk ref instead, utilizing new helper functions.
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
---
v2: fixed formatting
v3: added helper lsk_list_find_or_create(), updated
mptcp_pm_nl_create_listen_socket() to take struct net* as param
v4: call lsk_list_find() after a failed lsk_list_find_or_create()
for a chance to retrieve a recently created lsk by a simultaneous
call
v5: fixed implicit declaration error
---
net/mptcp/pm_netlink.c | 83 +++++++++++++++++++++++++++++++-----------
1 file changed, 62 insertions(+), 21 deletions(-)
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 3d6251baef26..a4fb9acbba51 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -35,7 +35,7 @@ struct mptcp_pm_addr_entry {
struct mptcp_addr_info addr;
u8 flags;
int ifindex;
- struct socket *lsk;
+ struct mptcp_local_lsk *lsk_ref;
};
struct mptcp_pm_add_entry {
@@ -66,6 +66,10 @@ struct pm_nl_pernet {
#define MPTCP_PM_ADDR_MAX 8
#define ADD_ADDR_RETRANS_MAX 3
+static int mptcp_pm_nl_create_listen_socket(struct net *net,
+ struct mptcp_pm_addr_entry *entry,
+ struct socket **lsk);
+
static bool addresses_equal(const struct mptcp_addr_info *a,
const struct mptcp_addr_info *b, bool use_port)
{
@@ -157,6 +161,33 @@ static void lsk_list_release(struct pm_nl_pernet *pernet,
}
}
+static struct mptcp_local_lsk *lsk_list_find_or_create(struct net *net,
+ struct pm_nl_pernet *pernet,
+ struct mptcp_pm_addr_entry *entry,
+ int *createlsk_err)
+{
+ struct mptcp_local_lsk *lsk_ref;
+ struct socket *lsk;
+ int err;
+
+ lsk_ref = lsk_list_find(pernet, &entry->addr);
+
+ if (!lsk_ref) {
+ err = mptcp_pm_nl_create_listen_socket(net, entry, &lsk);
+
+ if (createlsk_err)
+ *createlsk_err = err;
+
+ if (lsk)
+ lsk_ref = lsk_list_add(pernet, &entry->addr, lsk);
+
+ if (lsk && !lsk_ref)
+ sock_release(lsk);
+ }
+
+ return lsk_ref;
+}
+
static bool address_zero(const struct mptcp_addr_info *addr)
{
struct mptcp_addr_info zero;
@@ -999,8 +1030,9 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
return ret;
}
-static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
- struct mptcp_pm_addr_entry *entry)
+static int mptcp_pm_nl_create_listen_socket(struct net *net,
+ struct mptcp_pm_addr_entry *entry,
+ struct socket **lsk)
{
int addrlen = sizeof(struct sockaddr_in);
struct sockaddr_storage addr;
@@ -1009,12 +1041,12 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
int backlog = 1024;
int err;
- err = sock_create_kern(sock_net(sk), entry->addr.family,
- SOCK_STREAM, IPPROTO_MPTCP, &entry->lsk);
+ err = sock_create_kern(net, entry->addr.family,
+ SOCK_STREAM, IPPROTO_MPTCP, lsk);
if (err)
return err;
- msk = mptcp_sk(entry->lsk->sk);
+ msk = mptcp_sk((*lsk)->sk);
if (!msk) {
err = -EINVAL;
goto out;
@@ -1046,7 +1078,8 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
return 0;
out:
- sock_release(entry->lsk);
+ sock_release(*lsk);
+ *lsk = NULL;
return err;
}
@@ -1095,7 +1128,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
entry->addr.port = 0;
entry->ifindex = 0;
entry->flags = 0;
- entry->lsk = NULL;
+ entry->lsk_ref = NULL;
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
if (ret < 0)
kfree(entry);
@@ -1304,18 +1337,25 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
*entry = addr;
if (entry->addr.port) {
- ret = mptcp_pm_nl_create_listen_socket(skb->sk, entry);
- if (ret) {
- GENL_SET_ERR_MSG(info, "create listen socket error");
+ entry->lsk_ref = lsk_list_find_or_create(sock_net(skb->sk), pernet, entry, &ret);
+
+ if (!entry->lsk_ref)
+ entry->lsk_ref = lsk_list_find(pernet, &entry->addr);
+
+ if (!entry->lsk_ref) {
+ GENL_SET_ERR_MSG(info, "can't create/allocate lsk");
kfree(entry);
+ ret = (ret == 0) ? -ENOMEM : ret;
return ret;
}
}
+
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
+
if (ret < 0) {
GENL_SET_ERR_MSG(info, "too many addresses or duplicate one");
- if (entry->lsk)
- sock_release(entry->lsk);
+ if (entry->lsk_ref)
+ lsk_list_release(pernet, entry->lsk_ref);
kfree(entry);
return ret;
}
@@ -1418,10 +1458,11 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
}
/* caller must ensure the RCU grace period is already elapsed */
-static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
+static void __mptcp_pm_release_addr_entry(struct pm_nl_pernet *pernet,
+ struct mptcp_pm_addr_entry *entry)
{
- if (entry->lsk)
- sock_release(entry->lsk);
+ if (entry->lsk_ref)
+ lsk_list_release(pernet, entry->lsk_ref);
kfree(entry);
}
@@ -1503,7 +1544,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
synchronize_rcu();
- __mptcp_pm_release_addr_entry(entry);
+ __mptcp_pm_release_addr_entry(pernet, entry);
return ret;
}
@@ -1559,7 +1600,7 @@ static void mptcp_nl_remove_addrs_list(struct net *net,
}
/* caller must ensure the RCU grace period is already elapsed */
-static void __flush_addrs(struct list_head *list)
+static void __flush_addrs(struct pm_nl_pernet *pernet, struct list_head *list)
{
while (!list_empty(list)) {
struct mptcp_pm_addr_entry *cur;
@@ -1567,7 +1608,7 @@ static void __flush_addrs(struct list_head *list)
cur = list_entry(list->next,
struct mptcp_pm_addr_entry, list);
list_del_rcu(&cur->list);
- __mptcp_pm_release_addr_entry(cur);
+ __mptcp_pm_release_addr_entry(pernet, cur);
}
}
@@ -1592,7 +1633,7 @@ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
spin_unlock_bh(&pernet->lock);
mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
synchronize_rcu();
- __flush_addrs(&free_list);
+ __flush_addrs(pernet, &free_list);
return 0;
}
@@ -2242,7 +2283,7 @@ static void __net_exit pm_nl_exit_net(struct list_head *net_list)
* other modifiers, also netns core already waited for a
* RCU grace period.
*/
- __flush_addrs(&pernet->local_addr_list);
+ __flush_addrs(pernet, &pernet->local_addr_list);
}
}
--
2.31.1
Hi Kishen,
Kishen Maloor <kishen.maloor@intel.com> 于2022年2月3日周四 15:25写道:
>
> This change updates struct mptcp_pm_addr_entry to store a
> listening socket (lsk) reference, i.e. a pointer to a reference
> counted structure containing the lsk (struct socket *) instead
> of the lsk itself. Code blocks that previously operated on
> the lsk in struct mptcp_pm_addr_entry have been updated to work
> with the lsk ref instead, utilizing new helper functions.
>
> Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
> ---
> v2: fixed formatting
> v3: added helper lsk_list_find_or_create(), updated
> mptcp_pm_nl_create_listen_socket() to take struct net* as param
> v4: call lsk_list_find() after a failed lsk_list_find_or_create()
> for a chance to retrieve a recently created lsk by a simultaneous
> call
> v5: fixed implicit declaration error
> ---
> net/mptcp/pm_netlink.c | 83 +++++++++++++++++++++++++++++++-----------
> 1 file changed, 62 insertions(+), 21 deletions(-)
>
> diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
> index 3d6251baef26..a4fb9acbba51 100644
> --- a/net/mptcp/pm_netlink.c
> +++ b/net/mptcp/pm_netlink.c
> @@ -35,7 +35,7 @@ struct mptcp_pm_addr_entry {
> struct mptcp_addr_info addr;
> u8 flags;
> int ifindex;
> - struct socket *lsk;
> + struct mptcp_local_lsk *lsk_ref;
> };
>
> struct mptcp_pm_add_entry {
> @@ -66,6 +66,10 @@ struct pm_nl_pernet {
> #define MPTCP_PM_ADDR_MAX 8
> #define ADD_ADDR_RETRANS_MAX 3
>
> +static int mptcp_pm_nl_create_listen_socket(struct net *net,
> + struct mptcp_pm_addr_entry *entry,
> + struct socket **lsk);
> +
> static bool addresses_equal(const struct mptcp_addr_info *a,
> const struct mptcp_addr_info *b, bool use_port)
> {
> @@ -157,6 +161,33 @@ static void lsk_list_release(struct pm_nl_pernet *pernet,
> }
> }
>
> +static struct mptcp_local_lsk *lsk_list_find_or_create(struct net *net,
> + struct pm_nl_pernet *pernet,
> + struct mptcp_pm_addr_entry *entry,
> + int *createlsk_err)
> +{
> + struct mptcp_local_lsk *lsk_ref;
> + struct socket *lsk;
> + int err;
> +
> + lsk_ref = lsk_list_find(pernet, &entry->addr);
> +
> + if (!lsk_ref) {
> + err = mptcp_pm_nl_create_listen_socket(net, entry, &lsk);
> +
> + if (createlsk_err)
> + *createlsk_err = err;
> +
> + if (lsk)
> + lsk_ref = lsk_list_add(pernet, &entry->addr, lsk);
> +
> + if (lsk && !lsk_ref)
> + sock_release(lsk);
> + }
> +
> + return lsk_ref;
> +}
> +
> static bool address_zero(const struct mptcp_addr_info *addr)
> {
> struct mptcp_addr_info zero;
> @@ -999,8 +1030,9 @@ static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
> return ret;
> }
>
> -static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
> - struct mptcp_pm_addr_entry *entry)
> +static int mptcp_pm_nl_create_listen_socket(struct net *net,
> + struct mptcp_pm_addr_entry *entry,
> + struct socket **lsk)
> {
> int addrlen = sizeof(struct sockaddr_in);
> struct sockaddr_storage addr;
> @@ -1009,12 +1041,12 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
> int backlog = 1024;
> int err;
>
> - err = sock_create_kern(sock_net(sk), entry->addr.family,
> - SOCK_STREAM, IPPROTO_MPTCP, &entry->lsk);
> + err = sock_create_kern(net, entry->addr.family,
> + SOCK_STREAM, IPPROTO_MPTCP, lsk);
> if (err)
> return err;
>
> - msk = mptcp_sk(entry->lsk->sk);
> + msk = mptcp_sk((*lsk)->sk);
> if (!msk) {
> err = -EINVAL;
> goto out;
> @@ -1046,7 +1078,8 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
> return 0;
>
> out:
> - sock_release(entry->lsk);
> + sock_release(*lsk);
> + *lsk = NULL;
> return err;
> }
>
> @@ -1095,7 +1128,7 @@ int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc)
> entry->addr.port = 0;
> entry->ifindex = 0;
> entry->flags = 0;
> - entry->lsk = NULL;
> + entry->lsk_ref = NULL;
> ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
> if (ret < 0)
> kfree(entry);
> @@ -1304,18 +1337,25 @@ static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
>
> *entry = addr;
> if (entry->addr.port) {
> - ret = mptcp_pm_nl_create_listen_socket(skb->sk, entry);
> - if (ret) {
> - GENL_SET_ERR_MSG(info, "create listen socket error");
> + entry->lsk_ref = lsk_list_find_or_create(sock_net(skb->sk), pernet, entry, &ret);
> +
> + if (!entry->lsk_ref)
> + entry->lsk_ref = lsk_list_find(pernet, &entry->addr);
> +
> + if (!entry->lsk_ref) {
> + GENL_SET_ERR_MSG(info, "can't create/allocate lsk");
> kfree(entry);
> + ret = (ret == 0) ? -ENOMEM : ret;
> return ret;
> }
> }
> +
Blank lines aren't necessary here,
> ret = mptcp_pm_nl_append_new_local_addr(pernet, entry);
> +
and here.
Thanks,
Geliang
SUSE
> if (ret < 0) {
> GENL_SET_ERR_MSG(info, "too many addresses or duplicate one");
> - if (entry->lsk)
> - sock_release(entry->lsk);
> + if (entry->lsk_ref)
> + lsk_list_release(pernet, entry->lsk_ref);
> kfree(entry);
> return ret;
> }
> @@ -1418,10 +1458,11 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
> }
>
> /* caller must ensure the RCU grace period is already elapsed */
> -static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
> +static void __mptcp_pm_release_addr_entry(struct pm_nl_pernet *pernet,
> + struct mptcp_pm_addr_entry *entry)
> {
> - if (entry->lsk)
> - sock_release(entry->lsk);
> + if (entry->lsk_ref)
> + lsk_list_release(pernet, entry->lsk_ref);
> kfree(entry);
> }
>
> @@ -1503,7 +1544,7 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
>
> mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
> synchronize_rcu();
> - __mptcp_pm_release_addr_entry(entry);
> + __mptcp_pm_release_addr_entry(pernet, entry);
>
> return ret;
> }
> @@ -1559,7 +1600,7 @@ static void mptcp_nl_remove_addrs_list(struct net *net,
> }
>
> /* caller must ensure the RCU grace period is already elapsed */
> -static void __flush_addrs(struct list_head *list)
> +static void __flush_addrs(struct pm_nl_pernet *pernet, struct list_head *list)
> {
> while (!list_empty(list)) {
> struct mptcp_pm_addr_entry *cur;
> @@ -1567,7 +1608,7 @@ static void __flush_addrs(struct list_head *list)
> cur = list_entry(list->next,
> struct mptcp_pm_addr_entry, list);
> list_del_rcu(&cur->list);
> - __mptcp_pm_release_addr_entry(cur);
> + __mptcp_pm_release_addr_entry(pernet, cur);
> }
> }
>
> @@ -1592,7 +1633,7 @@ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
> spin_unlock_bh(&pernet->lock);
> mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
> synchronize_rcu();
> - __flush_addrs(&free_list);
> + __flush_addrs(pernet, &free_list);
> return 0;
> }
>
> @@ -2242,7 +2283,7 @@ static void __net_exit pm_nl_exit_net(struct list_head *net_list)
> * other modifiers, also netns core already waited for a
> * RCU grace period.
> */
> - __flush_addrs(&pernet->local_addr_list);
> + __flush_addrs(pernet, &pernet->local_addr_list);
> }
> }
>
> --
> 2.31.1
>
>
© 2016 - 2026 Red Hat, Inc.