summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux
diff options
context:
space:
mode:
authorBhasker Hariharan <bhaskerh@google.com>2020-10-09 18:59:48 -0700
committergVisor bot <gvisor-bot@google.com>2020-10-09 19:02:03 -0700
commitdb36d948fa63ce950d94a5e8e9ebc37956543661 (patch)
tree123b5ab20650dbb5f79300a4d68d2d98e4c79cfe /test/syscalls/linux
parentd75fe7660a61a454ece9472658eac609b3bf61e6 (diff)
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
Diffstat (limited to 'test/syscalls/linux')
-rw-r--r--test/syscalls/linux/tcp_socket.cc52
1 files changed, 52 insertions, 0 deletions
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<struct sockaddr*>(&addr), addrlen),
+ SyscallSucceeds());
+ // Get the bound port.
+ ASSERT_THAT(
+ getsockname(s.get(), reinterpret_cast<struct sockaddr*>(&addr), &addrlen),
+ SyscallSucceeds());
+ ASSERT_THAT(RetryEINTR(connect)(
+ s.get(), reinterpret_cast<struct sockaddr*>(&addr), addrlen),
+ SyscallSucceeds());
+
+ constexpr int kBufSz = 1 << 20; // 1 MiB
+ std::vector<char> 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));