Skip to content

Commit 9de1280

Browse files
committed
Merge branch 'mptcp-fixes-for-connect-selftest-flakes'
Matthieu Baerts says: ==================== mptcp: fixes for connect selftest flakes Last week, Jakub reported [1] that the MPTCP Connect selftest was unstable. It looked like it started after the introduction of some fixes [2]. After analysis from Paolo, these patches revealed existing bugs, that should be fixed by the following patches. - Patch 1: Make sure ACK are sent when MPTCP-level window re-opens. In some corner cases, the other peer was not notified when more data could be sent. A fix for v5.11, but depending on a feature introduced in v5.19. - Patch 2: Fix spurious wake-up under memory pressure. In this situation, the userspace could be invited to read data not being there yet. A fix for v6.7. - Patch 3: Fix a false positive error when running the MPTCP Connect selftest with the "disconnect" cases. The userspace could disconnect the socket too soon, which would reset (MP_FASTCLOSE) the connection, interpreted as an error by the test. A fix for v5.17. Link: https://lore.kernel.org/[email protected] [1] Link: https://lore.kernel.org/[email protected] [2] ==================== Link: https://patch.msgid.link/20250113-net-mptcp-connect-st-flakes-v1-0-0d986ee7b1b6@kernel.org Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 665bcfc + 218cc16 commit 9de1280

File tree

3 files changed

+43
-15
lines changed

3 files changed

+43
-15
lines changed

net/mptcp/options.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,6 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
607607
}
608608
opts->ext_copy.use_ack = 1;
609609
opts->suboptions = OPTION_MPTCP_DSS;
610-
WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk));
611610

612611
/* Add kind/length/subtype/flag overhead if mapping is not populated */
613612
if (dss_size == 0)
@@ -1288,7 +1287,7 @@ static void mptcp_set_rwin(struct tcp_sock *tp, struct tcphdr *th)
12881287
}
12891288
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDCONFLICT);
12901289
}
1291-
return;
1290+
goto update_wspace;
12921291
}
12931292

12941293
if (rcv_wnd_new != rcv_wnd_old) {
@@ -1313,6 +1312,9 @@ static void mptcp_set_rwin(struct tcp_sock *tp, struct tcphdr *th)
13131312
th->window = htons(new_win);
13141313
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_RCVWNDSHARED);
13151314
}
1315+
1316+
update_wspace:
1317+
WRITE_ONCE(msk->old_wspace, tp->rcv_wnd);
13161318
}
13171319

13181320
__sum16 __mptcp_make_csum(u64 data_seq, u32 subflow_seq, u16 data_len, __wsum sum)

net/mptcp/protocol.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -760,10 +760,15 @@ static inline u64 mptcp_data_avail(const struct mptcp_sock *msk)
760760

761761
static inline bool mptcp_epollin_ready(const struct sock *sk)
762762
{
763+
u64 data_avail = mptcp_data_avail(mptcp_sk(sk));
764+
765+
if (!data_avail)
766+
return false;
767+
763768
/* mptcp doesn't have to deal with small skbs in the receive queue,
764-
* at it can always coalesce them
769+
* as it can always coalesce them
765770
*/
766-
return (mptcp_data_avail(mptcp_sk(sk)) >= sk->sk_rcvlowat) ||
771+
return (data_avail >= sk->sk_rcvlowat) ||
767772
(mem_cgroup_sockets_enabled && sk->sk_memcg &&
768773
mem_cgroup_under_socket_pressure(sk->sk_memcg)) ||
769774
READ_ONCE(tcp_memory_pressure);

tools/testing/selftests/net/mptcp/mptcp_connect.c

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include <sys/types.h>
2626
#include <sys/mman.h>
2727

28+
#include <arpa/inet.h>
29+
2830
#include <netdb.h>
2931
#include <netinet/in.h>
3032

@@ -1211,23 +1213,42 @@ static void parse_setsock_options(const char *name)
12111213
exit(1);
12121214
}
12131215

1214-
void xdisconnect(int fd, int addrlen)
1216+
void xdisconnect(int fd)
12151217
{
1216-
struct sockaddr_storage empty;
1218+
socklen_t addrlen = sizeof(struct sockaddr_storage);
1219+
struct sockaddr_storage addr, empty;
12171220
int msec_sleep = 10;
1218-
int queued = 1;
1219-
int i;
1221+
void *raw_addr;
1222+
int i, cmdlen;
1223+
char cmd[128];
1224+
1225+
/* get the local address and convert it to string */
1226+
if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) < 0)
1227+
xerror("getsockname");
1228+
1229+
if (addr.ss_family == AF_INET)
1230+
raw_addr = &(((struct sockaddr_in *)&addr)->sin_addr);
1231+
else if (addr.ss_family == AF_INET6)
1232+
raw_addr = &(((struct sockaddr_in6 *)&addr)->sin6_addr);
1233+
else
1234+
xerror("bad family");
1235+
1236+
strcpy(cmd, "ss -M | grep -q ");
1237+
cmdlen = strlen(cmd);
1238+
if (!inet_ntop(addr.ss_family, raw_addr, &cmd[cmdlen],
1239+
sizeof(cmd) - cmdlen))
1240+
xerror("inet_ntop");
12201241

12211242
shutdown(fd, SHUT_WR);
12221243

1223-
/* while until the pending data is completely flushed, the later
1244+
/*
1245+
* wait until the pending data is completely flushed and all
1246+
* the MPTCP sockets reached the closed status.
12241247
* disconnect will bypass/ignore/drop any pending data.
12251248
*/
12261249
for (i = 0; ; i += msec_sleep) {
1227-
if (ioctl(fd, SIOCOUTQ, &queued) < 0)
1228-
xerror("can't query out socket queue: %d", errno);
1229-
1230-
if (!queued)
1250+
/* closed socket are not listed by 'ss' */
1251+
if (system(cmd) != 0)
12311252
break;
12321253

12331254
if (i > poll_timeout)
@@ -1281,9 +1302,9 @@ int main_loop(void)
12811302
return ret;
12821303

12831304
if (cfg_truncate > 0) {
1284-
xdisconnect(fd, peer->ai_addrlen);
1305+
xdisconnect(fd);
12851306
} else if (--cfg_repeat > 0) {
1286-
xdisconnect(fd, peer->ai_addrlen);
1307+
xdisconnect(fd);
12871308

12881309
/* the socket could be unblocking at this point, we need the
12891310
* connect to be blocking

0 commit comments

Comments
 (0)