This patch adds call_again flag in struct mptcp_sched_ops, init it as
true. Set it to false when the scheduler set call_again = true over
MPTCP_SUBFLOWS_MAX times to avoid infinite loops.
Signed-off-by: Geliang Tang <geliang.tang@suse.com>
---
include/net/mptcp.h | 1 +
net/mptcp/protocol.c | 21 +++++++++++++++------
net/mptcp/sched.c | 1 +
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index d48c66de8466..8c9991ef591a 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -112,6 +112,7 @@ struct mptcp_sched_ops {
char name[MPTCP_SCHED_NAME_MAX];
struct module *owner;
struct list_head list;
+ bool call_again;
void (*init)(const struct mptcp_sock *msk);
void (*release)(const struct mptcp_sock *msk);
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 1105c8ad670f..9c1ebd7a507e 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1560,6 +1560,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
int len, copied = 0;
bool call_again;
int max = 0;
+ int nr = 0;
while ((dfrag = mptcp_send_head(sk))) {
info.sent = dfrag->already_sent;
@@ -1587,7 +1588,7 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
lock_sock(ssk);
ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
- if (ret <= 0 && !call_again) {
+ if (ret <= 0 && (!call_again || !msk->sched->call_again)) {
mptcp_push_release(ssk, &info);
goto out;
}
@@ -1595,16 +1596,20 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
if (ret > max)
max = ret;
- if (!call_again) {
+ if (!call_again || !msk->sched->call_again) {
info.sent += max;
copied += max;
len -= max;
mptcp_update_post_push(msk, dfrag, max);
max = 0;
+ } else if (nr++ >= MPTCP_SUBFLOWS_MAX) {
+ mptcp_push_release(ssk, &info);
+ WRITE_ONCE(msk->sched->call_again, false);
+ goto out;
}
}
- if (!call_again)
+ if (!call_again || !msk->sched->call_again)
WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
}
@@ -1632,6 +1637,7 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
int len, copied = 0;
bool first = true;
int max = 0;
+ int nr = 0;
info.flags = 0;
while ((dfrag = mptcp_send_head(sk))) {
@@ -1655,23 +1661,26 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk)
}
ret = mptcp_sendmsg_frag(sk, ssk, dfrag, &info);
- if (ret <= 0 && !call_again)
+ if (ret <= 0 && (!call_again || !msk->sched->call_again))
goto out;
if (ret > max)
max = ret;
first = false;
- if (!call_again) {
+ if (!call_again || !msk->sched->call_again) {
info.sent += max;
copied += max;
len -= max;
mptcp_update_post_push(msk, dfrag, max);
max = 0;
+ } else if (nr++ >= MPTCP_SUBFLOWS_MAX) {
+ WRITE_ONCE(msk->sched->call_again, false);
+ goto out;
}
}
- if (!call_again)
+ if (!call_again || !msk->sched->call_again)
WRITE_ONCE(msk->first_pending, mptcp_send_next(sk));
}
diff --git a/net/mptcp/sched.c b/net/mptcp/sched.c
index 0d5fc96a2ce0..10736c334ab0 100644
--- a/net/mptcp/sched.c
+++ b/net/mptcp/sched.c
@@ -67,6 +67,7 @@ int mptcp_init_sched(struct mptcp_sock *msk,
msk->sched = sched;
if (msk->sched->init)
msk->sched->init(msk);
+ WRITE_ONCE(msk->sched->call_again, true);
pr_debug("sched=%s", msk->sched->name);
--
2.34.1