[PATCH 0/3] mptcp: just another recvmsg refactor
by Paolo Abeni
This start constructing the instrucutre to support pulling data from
multiple subflow. At the current stage uses a very simply approach, dropping
any out-of-order data and reading from any subflow with valid data.
The above should work quite nicely in active backup scenario and possibly
even with multiple subflows sending data concurrently - with a low bwidth and
a huge number of retransmissions.
Note that this rewrite completely the recvmsg() main loop to mirror more closely
the TCP recvmsg() main loop, likely fixing some bug in respect to signal and
error condition handling.
I think this 3 patches should be squashed into
"mptcp: Implement MPTCP receive path", but the resulting one will be likely
too huge; possibly splitting the resulting code in 2 different patches would
be nicer. Additionally "mptcp: Implement MPTCP receive path" has some chunks
that should be likely moved to some other patches (e.g. ULP RCU fixes).
What if - after the eventuall accept - I publish the resulting code of the
above squashing somewhere?
RFC -> v1
- address Mat's comment on patch 2/3, see individual changelog for the details
Paolo Abeni (3):
mptcp: move some helper into the header file
mptcp: flush duplicate data at data_ready() time
mptcp: recvmsg() can drain data from multiple subflows
net/mptcp/protocol.c | 360 +++++++++++++------------------------------
net/mptcp/protocol.h | 31 +++-
net/mptcp/subflow.c | 289 +++++++++++++++++++++++++++++++++-
3 files changed, 422 insertions(+), 258 deletions(-)
--
2.21.0
2 years, 7 months
[PATCH] mptcp:pm: use mptcp_pm_init
by Matthieu Baerts
Since e3c637f02e45 (mptcp: Minor changes to path manager interface),
mptcp_pm_init() is no longer declared in protocol.h but still declared
as non static in pm.c. I would propose here to continue to use it but
declare mptcp_basic_init() in mptcp_pm_init() to limit the modified .c
files for 'basic' features to pm.c only.
Signed-off-by: Matthieu Baerts <matthieu.baerts(a)tessares.net>
---
Notes:
to be squashed in "mptcp: Add path manager interface"
net/mptcp/protocol.c | 1 +
net/mptcp/protocol.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 3cef22193035..00ab1e7674eb 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1033,6 +1033,7 @@ void __init mptcp_init(void)
mptcp_stream_ops.shutdown = mptcp_shutdown;
mptcp_subflow_init();
+ mptcp_pm_init();
if (proto_register(&mptcp_prot, 1) != 0)
panic("Failed to register MPTCP proto.\n");
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index b3cb54efe724..b0ee4010c0c0 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -203,6 +203,7 @@ static inline void mptcp_crypto_key_gen_sha1(u64 *key, u32 *token, u64 *idsn)
void mptcp_crypto_hmac_sha1(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
u32 *hash_out);
+void mptcp_pm_init(void);
void mptcp_pm_new_connection(struct mptcp_sock *msk, int server_side);
void mptcp_pm_fully_established(struct mptcp_sock *msk);
void mptcp_pm_connection_closed(struct mptcp_sock *msk);
--
2.20.1
2 years, 7 months
[PATCH] mptcp:pm: limit changes for basic in pm.c
by Matthieu Baerts
Seems better to use mptcp_pm_init() and remove specifc changes for
'basic' PM in protocol.c.
Signed-off-by: Matthieu Baerts <matthieu.baerts(a)tessares.net>
---
Notes:
to be squashed in "mptcp: Implement basic path manager"
net/mptcp/pm.c | 1 +
net/mptcp/protocol.c | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index 9c1e3e631ade..d2b56fb8b47f 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -198,4 +198,5 @@ int mptcp_pm_get_local_id(struct request_sock *req, struct sock *sk,
void mptcp_pm_init(void)
{
+ mptcp_basic_init();
}
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 9f89095ac438..df5455c3719a 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1447,7 +1447,6 @@ void mptcp_proto_init(void)
mptcp_subflow_init();
mptcp_pm_init();
- mptcp_basic_init();
if (proto_register(&mptcp_prot, 1) != 0)
panic("Failed to register MPTCP proto.\n");
--
2.20.1
2 years, 7 months
[PATCH] mptcp:pm: remove duplicated RM addr
by Matthieu Baerts
We already have mptcp_pm_remove_addr() and this one is implemented.
Signed-off-by: Matthieu Baerts <matthieu.baerts(a)tessares.net>
---
Notes:
to be squashed in "mptcp: Implement basic path manager"
net/mptcp/pm.c | 5 -----
net/mptcp/protocol.h | 1 -
2 files changed, 6 deletions(-)
diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c
index d2b56fb8b47f..f20377c869ad 100644
--- a/net/mptcp/pm.c
+++ b/net/mptcp/pm.c
@@ -154,11 +154,6 @@ void mptcp_pm_add_addr6(struct mptcp_sock *msk, const struct in6_addr *addr,
pr_debug("msk=%p", msk);
}
-void mptcp_pm_rm_addr(struct mptcp_sock *msk, u8 id)
-{
- pr_debug("msk=%p", msk);
-}
-
/* path manager helpers */
int mptcp_pm_addr_signal(struct mptcp_sock *msk, u8 *id,
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 245833f438ee..d81d6bf18a65 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -297,7 +297,6 @@ void mptcp_pm_add_addr(struct mptcp_sock *msk, const struct in_addr *addr,
u8 id);
void mptcp_pm_add_addr6(struct mptcp_sock *msk, const struct in6_addr *addr,
u8 id);
-void mptcp_pm_rm_addr(struct mptcp_sock *msk, u8 id);
int mptcp_pm_announce_addr(u32 token, u8 local_id, sa_family_t family,
struct in_addr *addr);
int mptcp_pm_create_subflow(u32 token, u8 remote_id, sa_family_t family,
--
2.20.1
2 years, 7 months
[RFC PATCH 0/3] mptcp: just another recvmsg refactor
by Paolo Abeni
This start constructing the instrucutre to support pulling data from
multiple subflow. At the current stage uses a very simply approach, dropping
any out-of-order data and reading from any subflow with valid data.
The above should work quite nicely in active backup scenario and possibly
even with multiple subflows sending data concurrently - with a low bwidth and
a huge number of retransmissions.
This is a not_so_early draft, shared as it may pave some ground and/or
partially overlap with DATA_FIN support effort
Note that this rewrite completely the recvmsg() main loop to mirror more closely
the TCP recvmsg() main loop, likely fixing some bug in respect to signal and
error condition handling.
Paolo Abeni (3):
mptcp: move some helper into the header file
mptcp: flush duplicate data at data_ready() time
mptcp: recvmsg() can drain data from multiple subflows
net/mptcp/protocol.c | 360 +++++++++++++------------------------------
net/mptcp/protocol.h | 31 +++-
net/mptcp/subflow.c | 270 +++++++++++++++++++++++++++++++-
3 files changed, 403 insertions(+), 258 deletions(-)
--
2.21.0
2 years, 7 months
[PATCH] selftests: allow compilation on older systems
by Florian Westphal
squashto: mptcp: add basic kselftest for mptcp
An older VM image i was using lacks TCP_ULP define, add a workaround.
Signed-off-by: Florian Westphal <fw(a)strlen.de>
---
tools/testing/selftests/net/mptcp/mptcp_connect.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c
index a472e056fae6..987a8411756e 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_connect.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c
@@ -26,6 +26,9 @@ extern int optind;
#ifndef IPPROTO_MPTCP
#define IPPROTO_MPTCP 262
#endif
+#ifndef TCP_ULP
+#define TCP_ULP 31
+#endif
static bool listen_mode;
static int poll_timeout;
--
2.21.0
2 years, 7 months
[PATCH v2 0/2] Interim Path Manager
by Peter Krystad
Patchset includes the interim path manager plus sysctl setting of
the announce address and binding local address when creating subflows.
I also split the path manager into a seperate file.
v2:
rename to 'basic' path manager
remove pm_init definition
Peter Krystad (2):
mptcp: Minor changes to path manager interface
mptcp: Implement basic path manager
net/mptcp/Makefile | 2 +-
net/mptcp/basic.c | 247 +++++++++++++++++++++++++++++++++++++++++++
net/mptcp/pm.c | 38 +++++--
net/mptcp/protocol.c | 2 +-
net/mptcp/protocol.h | 14 ++-
5 files changed, 290 insertions(+), 13 deletions(-)
create mode 100644 net/mptcp/basic.c
--
2.17.2
2 years, 7 months
[RFC PATCH] mptcp: Add DATA_FIN transmission and handling
by Mat Martineau
Send and process received DATA_FIN options. This requires addition of a
state machine to the MPTCP socket to handle the closing process.
This is still a work in progress, including these areas:
* DATA_FIN requires a special DSS mapping when sent without a regular
data mapping. This is causing self test failures (as noted in
mptcp_established_options_dss()).
* Need to finish handling of DSS_ACKs for the state machine.
* Need to double-check whether it's correct to bypass inet_shutdown
as the current code does.
* A DATA_FIN that arrives on a packet without data payload (unless it's
a TCP FIN) are discarded by tcp_data_queue() and not propagated to
the MPTCP socket. This is detected in mptcp_incoming_options() but
not yet handled. The skb with the DATA_FIN could be cloned and
placed in the subflow error queue, or a workqueue could handle it.
Signed-off-by: Mat Martineau <mathew.j.martineau(a)linux.intel.com>
---
net/mptcp/options.c | 45 +++++++++++++--
net/mptcp/protocol.c | 134 ++++++++++++++++++++++++++++++++++++-------
net/mptcp/protocol.h | 4 +-
3 files changed, 156 insertions(+), 27 deletions(-)
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 4bb3766fce5e..0a104b3ee185 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -388,13 +388,15 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
unsigned int remaining,
struct mptcp_out_options *opts)
{
+ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
unsigned int dss_size = 0;
struct mptcp_ext *mpext;
unsigned int ack_size;
mpext = skb ? mptcp_get_ext(skb) : NULL;
- if (!skb || (mpext && mpext->use_map)) {
+ if (!skb || (mpext && mpext->use_map) ||
+ (subflow->send_data_fin && subflow->conn)) {
unsigned int map_size;
map_size = TCPOLEN_MPTCP_DSS_BASE + TCPOLEN_MPTCP_DSS_MAP64;
@@ -404,6 +406,21 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
dss_size = map_size;
if (mpext)
opts->ext_copy = *mpext;
+
+ /* This creates self test failures, still tracking
+ * down the root cause */
+ if (subflow->send_data_fin && !opts->ext_copy.use_map &&
+ subflow->conn) {
+ struct mptcp_sock *msk;
+
+ /* Required for DATA_FIN without data payload */
+ msk = mptcp_sk(subflow->conn);
+ opts->ext_copy.use_map = 1;
+ opts->ext_copy.dsn64 = 1;
+ opts->ext_copy.data_seq = msk->write_seq;
+ opts->ext_copy.subflow_seq = 0;
+ opts->ext_copy.data_len = 1;
+ }
} else {
opts->ext_copy.use_map = 0;
WARN_ONCE(1, "MPTCP: Map dropped");
@@ -421,7 +438,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
dss_size += ack_size;
- msk = mptcp_sk(mptcp_subflow_ctx(sk)->conn);
+ msk = mptcp_sk(subflow->conn);
if (msk) {
opts->ext_copy.data_ack = msk->ack_seq;
} else {
@@ -440,6 +457,13 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
if (!dss_size)
return false;
+ if (subflow->send_data_fin) {
+ opts->ext_copy.data_fin = 1;
+ /* Only clear the flag if this affects a real skb */
+ if (skb)
+ subflow->send_data_fin = 0;
+ }
+
*size = ALIGN(dss_size, 4);
return true;
}
@@ -617,6 +641,18 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb,
mpext->data_fin = mp_opt->data_fin;
+ if (mp_opt->data_fin &&
+ TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq) {
+ /* The DATA_FIN is on a packet that will be discarded by
+ * tcp_data_queue() and will not get propagated to the MPTCP
+ * socket.
+ *
+ * Use workqueue or subflow error queue?
+ */
+ pr_warn("Ignored DATA_FIN");
+ }
+
+
if (msk)
mptcp_pm_fully_established(msk);
}
@@ -712,10 +748,11 @@ void mptcp_write_options(__be32 *ptr, struct mptcp_out_options *opts)
* support for optional 32-bit mappings later.
*/
flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64;
- if (mpext->data_fin)
- flags |= MPTCP_DSS_DATA_FIN;
}
+ if (mpext->data_fin)
+ flags |= MPTCP_DSS_DATA_FIN;
+
*ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags);
if (mpext->use_ack) {
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index df5455c3719a..4507b259ca3e 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -360,6 +360,13 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
lock_sock(ssk);
mptcp_clean_una(sk);
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
+
+ if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
+ ret = sk_stream_wait_connect(sk, &timeo);
+ if (ret != 0)
+ goto put_out_subflow;
+ }
+
while (msg_data_left(msg)) {
ret = mptcp_sendmsg_frag(sk, ssk, msg, NULL, &timeo, &mss_now,
&size_goal);
@@ -380,6 +387,7 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
mptcp_reset_timer(sk);
}
+put_out_subflow:
release_sock(ssk);
out:
@@ -445,14 +453,14 @@ enum mapping_status {
MAPPING_ADDED,
MAPPING_MISSING,
MAPPING_EMPTY,
- MAPPING_DATA_FIN
+ MAPPING_BARE_DATA_FIN
};
static enum mapping_status mptcp_get_mapping(struct sock *ssk)
{
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
struct mptcp_ext *mpext;
- enum mapping_status ret;
+ enum mapping_status ret = MAPPING_ADDED;
struct sk_buff *skb;
u64 map_seq;
@@ -482,11 +490,15 @@ static enum mapping_status mptcp_get_mapping(struct sock *ssk)
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX);
ret = MAPPING_MISSING;
goto del_out;
- } else if (mpext->subflow_seq == 0 &&
- mpext->data_fin == 1) {
- pr_debug("DATA_FIN with no payload");
- ret = MAPPING_DATA_FIN;
- goto del_out;
+ }
+
+ if (mpext->data_fin) {
+ if (mpext->subflow_seq == 0 && mpext->data_len == 1) {
+ ret = MAPPING_BARE_DATA_FIN;
+ goto del_out;
+ }
+
+ subflow->incoming_data_fin = 1;
}
if (!mpext->dsn64) {
@@ -503,7 +515,8 @@ static enum mapping_status mptcp_get_mapping(struct sock *ssk)
*/
if (subflow->map_seq != map_seq ||
subflow->map_subflow_seq != mpext->subflow_seq ||
- subflow->map_data_len != mpext->data_len) {
+ subflow->map_data_len != mpext->data_len ||
+ subflow->incoming_data_fin != mpext->data_fin) {
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSNOMATCH);
pr_warn("Replaced mapping before it was done");
}
@@ -513,7 +526,6 @@ static enum mapping_status mptcp_get_mapping(struct sock *ssk)
subflow->map_subflow_seq = mpext->subflow_seq;
subflow->map_data_len = mpext->data_len;
subflow->map_valid = 1;
- ret = MAPPING_ADDED;
pr_debug("new map seq=%llu subflow_seq=%u data_len=%u",
subflow->map_seq, subflow->map_subflow_seq,
subflow->map_data_len);
@@ -554,6 +566,41 @@ static void warn_bad_map(struct mptcp_subflow_context *subflow, u32 ssn)
ssn, subflow->map_subflow_seq, subflow->map_data_len);
}
+static int mptcp_close_state(int oldstate, bool fin, bool ack)
+{
+ switch (oldstate) {
+ case TCP_FIN_WAIT1:
+ if (fin && ack)
+ return TCP_TIME_WAIT;
+ else if (fin)
+ return TCP_FIN_WAIT2;
+ else
+ return TCP_CLOSING;
+ case TCP_FIN_WAIT2:
+ if (fin)
+ return TCP_TIME_WAIT;
+ else
+ return oldstate;
+ case TCP_CLOSING:
+ if (ack)
+ return TCP_TIME_WAIT;
+ else
+ return oldstate;
+ case TCP_TIME_WAIT:
+ return TCP_CLOSE;
+ case TCP_LAST_ACK:
+ if (ack)
+ return TCP_CLOSE;
+ else
+ return oldstate;
+ case TCP_ESTABLISHED:
+ return TCP_CLOSE_WAIT;
+ default:
+ pr_debug("Unexpected state with DATA_FIN: %d", oldstate);
+ return oldstate;
+ }
+}
+
static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len)
{
@@ -636,12 +683,16 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
}
} else if (status == MAPPING_EMPTY) {
goto wait_for_data;
- } else if (status == MAPPING_DATA_FIN) {
- /* TODO: Handle according to RFC 6824 */
- if (!copied) {
- pr_err("Can't read after DATA_FIN");
- copied = -ENOTCONN;
+ } else if (status == MAPPING_BARE_DATA_FIN) {
+ int newstate = mptcp_close_state(sk->sk_state, true,
+ false);
+
+ if (subflow->map_seq == msk->ack_seq) {
+ msk->ack_seq++;
+ inet_sk_state_store(sk, newstate);
+ tcp_send_ack(ssk);
}
+ /* else fallback to TCP? */
break;
}
@@ -697,9 +748,25 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
if (!before(tcp_sk(ssk)->copied_seq - subflow->ssn_offset,
subflow->map_subflow_seq + subflow->map_data_len)) {
subflow->map_valid = 0;
- pr_debug("Done with mapping: seq=%u data_len=%u",
+
+ if (subflow->incoming_data_fin) {
+ int newstate;
+
+ if (subflow->map_seq == msk->ack_seq) {
+ newstate = mptcp_close_state(
+ sk->sk_state, false, true);
+
+ msk->ack_seq++;
+ inet_sk_state_store(sk, newstate);
+ tcp_send_ack(ssk);
+ }
+ /* else fallback to TCP? */
+ }
+
+ pr_debug("Done with mapping: seq=%u data_len=%u data_fin=%u",
subflow->map_subflow_seq,
- subflow->map_data_len);
+ subflow->map_data_len,
+ subflow->incoming_data_fin);
}
if (arg.msg)
@@ -897,11 +964,11 @@ static void mptcp_close(struct sock *sk, long timeout)
struct mptcp_sock *msk = mptcp_sk(sk);
struct socket *ssk = NULL;
- mptcp_token_destroy(msk->token);
- inet_sk_state_store(sk, TCP_CLOSE);
-
lock_sock(sk);
+ inet_sk_state_store(sk, TCP_CLOSE);
+ mptcp_token_destroy(msk->token);
+
if (msk->subflow) {
ssk = msk->subflow;
msk->subflow = NULL;
@@ -914,6 +981,7 @@ static void mptcp_close(struct sock *sk, long timeout)
list_for_each_entry_safe(subflow, tmp, &msk->conn_list, node) {
pr_debug("conn_list->subflow=%p", subflow);
+ subflow->send_data_fin = 1;
sock_release(mptcp_subflow_tcp_socket(subflow));
}
@@ -1071,6 +1139,11 @@ static int mptcp_getsockopt(struct sock *sk, int level, int optname,
return -EOPNOTSUPP;
}
+static void mptcp_shutdown(struct sock *sock, int how)
+{
+ pr_err("Unexpected MPTCP shutdown call sock=%p how=%d", sock, how);
+}
+
#define MPTCP_DEFERRED_ALL TCPF_WRITE_TIMER_DEFERRED
/* this is very alike tcp_release_cb() but we must handle differently a
@@ -1195,7 +1268,7 @@ static struct proto mptcp_prot = {
.accept = mptcp_accept,
.setsockopt = mptcp_setsockopt,
.getsockopt = mptcp_getsockopt,
- .shutdown = tcp_shutdown,
+ .shutdown = mptcp_shutdown,
.destroy = mptcp_destroy,
.sendmsg = mptcp_sendmsg,
.recvmsg = mptcp_recvmsg,
@@ -1338,6 +1411,10 @@ static int mptcp_listen(struct socket *sock, int backlog)
err = inet_listen(ssock, backlog);
sock_put(ssock->sk);
+
+ if (!err)
+ inet_sk_state_store(sock->sk, TCP_LISTEN);
+
return err;
}
@@ -1389,7 +1466,7 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
return ret;
}
-static int mptcp_shutdown(struct socket *sock, int how)
+static int mptcp_stream_shutdown(struct socket *sock, int how)
{
struct mptcp_sock *msk = mptcp_sk(sock->sk);
struct mptcp_subflow_context *subflow;
@@ -1399,6 +1476,18 @@ static int mptcp_shutdown(struct socket *sock, int how)
pr_debug("sk=%p, how=%d", msk, how);
lock_sock(sock->sk);
+
+ if (sock->sk->sk_state == TCP_ESTABLISHED) {
+ inet_sk_state_store(sock->sk, TCP_FIN_WAIT1);
+ } else if (sock->sk->sk_state == TCP_CLOSE_WAIT) {
+ inet_sk_state_store(sock->sk, TCP_LAST_ACK);
+ } else if (sock->sk->sk_state != TCP_CLOSE) {
+ pr_warn("Shutdown from unexpected state %d",
+ sock->sk->sk_state);
+ release_sock(sock->sk);
+ return -EALREADY;
+ }
+
ssock = __mptcp_fallback_get_ref(msk);
if (ssock) {
release_sock(sock->sk);
@@ -1413,6 +1502,7 @@ static int mptcp_shutdown(struct socket *sock, int how)
tcp_socket = mptcp_subflow_tcp_socket(subflow);
pr_debug("conn_list->subflow=%p", subflow);
+ subflow->send_data_fin = 1;
ret = kernel_sock_shutdown(tcp_socket, how);
}
release_sock(sock->sk);
@@ -1440,7 +1530,7 @@ void mptcp_proto_init(void)
mptcp_stream_ops.accept = mptcp_stream_accept;
mptcp_stream_ops.getname = mptcp_getname;
mptcp_stream_ops.listen = mptcp_listen;
- mptcp_stream_ops.shutdown = mptcp_shutdown;
+ mptcp_stream_ops.shutdown = mptcp_stream_shutdown;
if (percpu_counter_init(&mptcp_sockets_allocated, 0, GFP_KERNEL))
panic("Failed to allocate MPTCP pcpu counter\n");
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index 3c66f69a734d..3f185db7da36 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -214,7 +214,9 @@ struct mptcp_subflow_context {
fourth_ack : 1, /* send initial DSS */
conn_finished : 1,
map_valid : 1,
- backup : 1;
+ backup : 1,
+ incoming_data_fin : 1,
+ send_data_fin : 1;
u32 remote_nonce;
u64 thmac;
u32 local_nonce;
--
2.23.0
2 years, 7 months
[PATCH v2] selftests: fixes and improvements
by Florian Westphal
First a couple of resends, rebased on top of current export
branch. All commits may be squashed at your discretion.
The last two are new and were not included before.
The commits build on one-another so its possible to take
the resends and defer or drop the last ones.
1. increase tc delay variation to cover more scenarios.
3. check accept/getpeername provide expected sockaddr info.
3. add ipv6 support (disabled via ipv6=false in script)
4. randomly disable any combination of gro/tso/gso.
5. allow to run multiple instances of mptcp_connect.sh in parallel.
6. Fix a possible deadlock in the test program where both ends block in
write(mptcp_sk, ..).
Comments welcome.
These patches are currently queued in
https://git.breakpoint.cc/cgit/fw/mptcp-next.git/log/?h=sendmsg_refactor_12
and can be fetched via
git://git.breakpoint.cc/fw/mptcp-next.git sendmsg_refactor_12
Beware, it contains further changes -- you will need to toss the
extra baggage.
2 years, 7 months