From db36d948fa63ce950d94a5e8e9ebc37956543661 Mon Sep 17 00:00:00 2001 From: Bhasker Hariharan Date: Fri, 9 Oct 2020 18:59:48 -0700 Subject: TCP Receive window advertisement fixes. The fix in commit 028e045da93b7c1c26417e80e4b4e388b86a713d was incorrect as it can cause the right edge of the window to shrink when we announce a zero window due to receive buffer being full as its done before the check for seeing if the window is being shrunk because of the selected window. Further the window was calculated purely on available space but in cases where we are getting full sized segments it makes more sense to use the actual bytes being held. This CL changes to use the lower of the total available space vs the available space in the maximal window we could advertise minus the actual payload bytes being held. This change also cleans up the code so that the window selection logic is not duplicated between getSendParams() and windowCrossedACKThresholdLocked. PiperOrigin-RevId: 336404827 --- test/syscalls/linux/tcp_socket.cc | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'test/syscalls/linux') diff --git a/test/syscalls/linux/tcp_socket.cc b/test/syscalls/linux/tcp_socket.cc index e0981e28a..9f522f833 100644 --- a/test/syscalls/linux/tcp_socket.cc +++ b/test/syscalls/linux/tcp_socket.cc @@ -903,6 +903,58 @@ TEST_P(SimpleTcpSocketTest, NonBlockingConnectNoListener) { EXPECT_EQ(err, ECONNREFUSED); } +TEST_P(SimpleTcpSocketTest, SelfConnectSendRecv_NoRandomSave) { + // Initialize address to the loopback one. + sockaddr_storage addr = + ASSERT_NO_ERRNO_AND_VALUE(InetLoopbackAddr(GetParam())); + socklen_t addrlen = sizeof(addr); + + const FileDescriptor s = + ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_STREAM, IPPROTO_TCP)); + + ASSERT_THAT( + (bind)(s.get(), reinterpret_cast(&addr), addrlen), + SyscallSucceeds()); + // Get the bound port. + ASSERT_THAT( + getsockname(s.get(), reinterpret_cast(&addr), &addrlen), + SyscallSucceeds()); + ASSERT_THAT(RetryEINTR(connect)( + s.get(), reinterpret_cast(&addr), addrlen), + SyscallSucceeds()); + + constexpr int kBufSz = 1 << 20; // 1 MiB + std::vector writebuf(kBufSz); + + // Start reading the response in a loop. + int read_bytes = 0; + ScopedThread t([&s, &read_bytes]() { + // Too many syscalls. + const DisableSave ds; + + char readbuf[2500] = {}; + int n = -1; + while (n != 0) { + ASSERT_THAT(n = RetryEINTR(read)(s.get(), &readbuf, sizeof(readbuf)), + SyscallSucceeds()); + read_bytes += n; + } + }); + + // Try to send the whole thing. + int n; + ASSERT_THAT(n = SendFd(s.get(), writebuf.data(), kBufSz, 0), + SyscallSucceeds()); + + // We should have written the whole thing. + EXPECT_EQ(n, kBufSz); + EXPECT_THAT(shutdown(s.get(), SHUT_WR), SyscallSucceedsWithValue(0)); + t.Join(); + + // We should have read the whole thing. + EXPECT_EQ(read_bytes, kBufSz); +} + TEST_P(SimpleTcpSocketTest, NonBlockingConnect) { const FileDescriptor listener = ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_STREAM, IPPROTO_TCP)); -- cgit v1.2.3