From: Geliang Tang <tanggeliang@kylinos.cn>
The helper mptcp_pm_is_userspace() is used to distinguish userspace PM
operations from in-kernel PM in mptcp_pm_add_addr_received(). It seems
reasonable to add a mandatory .add_addr_echo interface for struct
mptcp_pm_ops.
Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
---
include/net/mptcp.h | 2 ++
net/mptcp/pm.c | 36 ++++++++++++++++++------------------
net/mptcp/pm_kernel.c | 7 +++++++
net/mptcp/pm_userspace.c | 12 ++++++++++++
net/mptcp/protocol.h | 2 ++
5 files changed, 41 insertions(+), 18 deletions(-)
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index 5f2d94b2f97f..1f4d0d3988c1 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -128,6 +128,8 @@ struct mptcp_pm_ops {
bool (*accept_new_subflow)(const struct mptcp_sock *msk);
void (*subflow_check_next)(struct mptcp_sock *msk,
const struct mptcp_subflow_context *subflow);
+ void (*add_addr_echo)(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr);
char name[MPTCP_PM_NAME_MAX];
struct module *owner;
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index d8a5c2c06500..dc7ab696c24b 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -529,6 +529,22 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,
msk->pm.ops->subflow_check_next(msk, subflow);
}
+void mptcp_pm_add_addr_echo(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr)
+{
+ struct mptcp_pm_data *pm = &msk->pm;
+
+ if ((addr->id == 0 && !mptcp_pm_is_init_remote_addr(msk, addr)) ||
+ (addr->id > 0 && !READ_ONCE(pm->accept_addr))) {
+ mptcp_pm_announce_addr(msk, addr, true);
+ mptcp_pm_add_addr_send_ack(msk);
+ } else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {
+ pm->remote = *addr;
+ } else {
+ __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
+ }
+}
+
void mptcp_pm_add_addr_received(const struct sock *ssk,
const struct mptcp_addr_info *addr)
{
@@ -543,23 +559,7 @@ void mptcp_pm_add_addr_received(const struct sock *ssk,
spin_lock_bh(&pm->lock);
- if (mptcp_pm_is_userspace(msk)) {
- if (mptcp_userspace_pm_active(msk)) {
- mptcp_pm_announce_addr(msk, addr, true);
- mptcp_pm_add_addr_send_ack(msk);
- } else {
- __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
- }
- /* id0 should not have a different address */
- } else if ((addr->id == 0 && !mptcp_pm_is_init_remote_addr(msk, addr)) ||
- (addr->id > 0 && !READ_ONCE(pm->accept_addr))) {
- mptcp_pm_announce_addr(msk, addr, true);
- mptcp_pm_add_addr_send_ack(msk);
- } else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) {
- pm->remote = *addr;
- } else {
- __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
- }
+ pm->ops->add_addr_echo(msk, addr);
spin_unlock_bh(&pm->lock);
}
@@ -992,7 +992,7 @@ int mptcp_pm_validate(struct mptcp_pm_ops *pm_ops)
{
if (!pm_ops->get_local_id || !pm_ops->get_priority ||
!pm_ops->allow_new_subflow || !pm_ops->accept_new_subflow ||
- !pm_ops->subflow_check_next) {
+ !pm_ops->subflow_check_next || !pm_ops->add_addr_echo) {
pr_err("%s does not implement required ops\n", pm_ops->name);
return -EINVAL;
}
diff --git a/net/mptcp/pm_kernel.c b/net/mptcp/pm_kernel.c
index b40d39232f70..d5002236fe6e 100644
--- a/net/mptcp/pm_kernel.c
+++ b/net/mptcp/pm_kernel.c
@@ -1449,6 +1449,12 @@ static void mptcp_pm_kernel_subflow_check_next(struct mptcp_sock *msk,
mptcp_pm_subflow_established(msk);
}
+static void mptcp_pm_kernel_add_addr_echo(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr)
+{
+ mptcp_pm_add_addr_echo(msk, addr);
+}
+
static void mptcp_pm_kernel_init(struct mptcp_sock *msk)
{
bool subflows_allowed = !!mptcp_pm_get_subflows_max(msk);
@@ -1475,6 +1481,7 @@ struct mptcp_pm_ops mptcp_pm_kernel = {
.allow_new_subflow = mptcp_pm_kernel_allow_new_subflow,
.accept_new_subflow = mptcp_pm_kernel_accept_new_subflow,
.subflow_check_next = mptcp_pm_kernel_subflow_check_next,
+ .add_addr_echo = mptcp_pm_kernel_add_addr_echo,
.init = mptcp_pm_kernel_init,
.name = "kernel",
.owner = THIS_MODULE,
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index 68247ec4cdaa..848102bd0f4b 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -715,6 +715,17 @@ static void mptcp_pm_userspace_subflow_check_next(struct mptcp_sock *msk,
}
}
+static void mptcp_pm_userspace_add_addr_echo(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr)
+{
+ if (mptcp_userspace_pm_active(msk)) {
+ mptcp_pm_announce_addr(msk, addr, true);
+ mptcp_pm_add_addr_send_ack(msk);
+ } else {
+ __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP);
+ }
+}
+
static void mptcp_pm_userspace_release(struct mptcp_sock *msk)
{
mptcp_userspace_pm_free_local_addr_list(msk);
@@ -726,6 +737,7 @@ static struct mptcp_pm_ops mptcp_pm_userspace = {
.allow_new_subflow = mptcp_pm_userspace_allow_new_subflow,
.accept_new_subflow = mptcp_pm_userspace_accept_new_subflow,
.subflow_check_next = mptcp_pm_userspace_subflow_check_next,
+ .add_addr_echo = mptcp_pm_userspace_add_addr_echo,
.release = mptcp_pm_userspace_release,
.name = "userspace",
.owner = THIS_MODULE,
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index d9ca3a19a218..8ca8eea1795b 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -1013,6 +1013,8 @@ void mptcp_pm_subflow_established(struct mptcp_sock *msk);
bool mptcp_pm_nl_check_work_pending(struct mptcp_sock *msk);
void mptcp_pm_subflow_check_next(struct mptcp_sock *msk,
const struct mptcp_subflow_context *subflow);
+void mptcp_pm_add_addr_echo(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr);
void mptcp_pm_add_addr_received(const struct sock *ssk,
const struct mptcp_addr_info *addr);
void mptcp_pm_add_addr_echoed(struct mptcp_sock *msk,
--
2.43.0
Hi Geliang, On 11/03/2025 10:32, Geliang Tang wrote: > From: Geliang Tang <tanggeliang@kylinos.cn> > > The helper mptcp_pm_is_userspace() is used to distinguish userspace PM > operations from in-kernel PM in mptcp_pm_add_addr_received(). It seems > reasonable to add a mandatory .add_addr_echo interface for struct > mptcp_pm_ops. > > Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn> > --- > include/net/mptcp.h | 2 ++ > net/mptcp/pm.c | 36 ++++++++++++++++++------------------ > net/mptcp/pm_kernel.c | 7 +++++++ > net/mptcp/pm_userspace.c | 12 ++++++++++++ > net/mptcp/protocol.h | 2 ++ > 5 files changed, 41 insertions(+), 18 deletions(-) > > diff --git a/include/net/mptcp.h b/include/net/mptcp.h > index 5f2d94b2f97f..1f4d0d3988c1 100644 > --- a/include/net/mptcp.h > +++ b/include/net/mptcp.h > @@ -128,6 +128,8 @@ struct mptcp_pm_ops { > bool (*accept_new_subflow)(const struct mptcp_sock *msk); > void (*subflow_check_next)(struct mptcp_sock *msk, > const struct mptcp_subflow_context *subflow); > + void (*add_addr_echo)(struct mptcp_sock *msk, add_addr_received instead? > + const struct mptcp_addr_info *addr); > > char name[MPTCP_PM_NAME_MAX]; > struct module *owner; > diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c > index d8a5c2c06500..dc7ab696c24b 100644 > --- a/net/mptcp/pm.c > +++ b/net/mptcp/pm.c > @@ -529,6 +529,22 @@ void mptcp_pm_subflow_check_next(struct mptcp_sock *msk, > msk->pm.ops->subflow_check_next(msk, subflow); > } > > +void mptcp_pm_add_addr_echo(struct mptcp_sock *msk, > + const struct mptcp_addr_info *addr) Why is this here if it is only used by the kernel PM? > +{ > + struct mptcp_pm_data *pm = &msk->pm; > + > + if ((addr->id == 0 && !mptcp_pm_is_init_remote_addr(msk, addr)) || > + (addr->id > 0 && !READ_ONCE(pm->accept_addr))) { > + mptcp_pm_announce_addr(msk, addr, true); > + mptcp_pm_add_addr_send_ack(msk); > + } else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) { > + pm->remote = *addr; > + } else { > + __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP); > + } > +} > + > void mptcp_pm_add_addr_received(const struct sock *ssk, > const struct mptcp_addr_info *addr) > { > @@ -543,23 +559,7 @@ void mptcp_pm_add_addr_received(const struct sock *ssk, > > spin_lock_bh(&pm->lock); > > - if (mptcp_pm_is_userspace(msk)) { > - if (mptcp_userspace_pm_active(msk)) { > - mptcp_pm_announce_addr(msk, addr, true); > - mptcp_pm_add_addr_send_ack(msk); > - } else { > - __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP); > - } > - /* id0 should not have a different address */ > - } else if ((addr->id == 0 && !mptcp_pm_is_init_remote_addr(msk, addr)) || > - (addr->id > 0 && !READ_ONCE(pm->accept_addr))) { > - mptcp_pm_announce_addr(msk, addr, true); > - mptcp_pm_add_addr_send_ack(msk); > - } else if (mptcp_pm_schedule_work(msk, MPTCP_PM_ADD_ADDR_RECEIVED)) { Here as well, I think the worker scheduling should be done from pm.c if an optional callback is set, and this callback should be called from the worker. Maybe we need 2 callbacks here? One to know if there is a need to be called from a worker, then add_addr_received? Or: can we not always send the ADD_ADDR echo here, and schedule the worker if there is a need to? So we would drop the "if (mptcp_userspace_pm_active(msk))" condition above, but maybe that's OK? (We would need a dedicate patch for that) > - pm->remote = *addr; > - } else { > - __MPTCP_INC_STATS(sock_net((struct sock *)msk), MPTCP_MIB_ADDADDRDROP); I think this MIB counter should be incremented from here, not from each PM. Cheers, Matt -- Sponsored by the NGI0 Core fund.
© 2016 - 2025 Red Hat, Inc.