Return user_mss if user_mss is set and socket is unconnected.

Has the same effect as Linux commit 34dfde4ad87b ("tcp: Return user_mss for
TCP_MAXSEG in CLOSE/LISTEN state if user_mss set").

Updated test to accept both values (default and user set) so test works on
newer and older kernels.

PiperOrigin-RevId: 563844012
This commit is contained in:
Ayush Ranjan
2023-09-08 13:57:42 -07:00
committed by gVisor bot
parent ad275a100e
commit 717539fbd7
2 changed files with 19 additions and 9 deletions
+9 -4
View File
@@ -2059,11 +2059,16 @@ func (e *endpoint) GetSockOptInt(opt tcpip.SockOptInt) (int, tcpip.Error) {
return v, nil
case tcpip.MaxSegOption:
// This is just stubbed out. Linux never returns the user_mss
// value as it either returns the defaultMSS or returns the
// actual current MSS. Netstack just returns the defaultMSS
// always for now.
// Linux only returns user_mss value if user_mss is set and the socket is
// unconnected. Otherwise Linux returns the actual current MSS. Netstack
// mimics the user_mss behavior, but otherwise just returns the defaultMSS
// for now.
v := header.TCPDefaultMSS
e.LockUser()
if state := e.EndpointState(); e.userMSS > 0 && (state.internal() || state == StateClose || state == StateListen) {
v = int(e.userMSS)
}
e.UnlockUser()
return v, nil
case tcpip.MTUDiscoverOption:
+10 -5
View File
@@ -28,6 +28,7 @@
#include <limits>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/status/statusor.h"
#include "absl/time/clock.h"
@@ -38,6 +39,8 @@
#include "test/util/test_util.h"
#include "test/util/thread_util.h"
using ::testing::AnyOf;
namespace gvisor {
namespace testing {
@@ -1857,17 +1860,19 @@ TEST_P(SimpleTcpSocketTest, SetMaxSeg) {
sizeof(kTCPMaxSeg)),
SyscallSucceedsWithValue(0));
// Linux actually never returns the user_mss value. It will always return the
// default MSS value defined above for an unconnected socket and always return
// the actual current MSS for a connected one.
int optval;
socklen_t optlen = sizeof(optval);
ASSERT_THAT(getsockopt(s.get(), IPPROTO_TCP, TCP_MAXSEG, &optval, &optlen),
SyscallSucceedsWithValue(0));
ASSERT_EQ(optlen, sizeof(optval));
EXPECT_EQ(kDefaultMSS, optval);
EXPECT_EQ(sizeof(optval), optlen);
// In older Linux versions, user_mss value was never actually returned. Linux
// would always return the default MSS value for an unconnected socket and
// always return the actual current MSS for a connected one. However, the
// behavior changed since 34dfde4ad87b ("tcp: Return user_mss for TCP_MAXSEG
// in CLOSE/LISTEN state if user_mss set"). With this change, user_mss is
// returned if set for unconnected sockets. So allow both.
EXPECT_THAT(optval, AnyOf(kDefaultMSS, kTCPMaxSeg));
}
TEST_P(SimpleTcpSocketTest, SetMaxSegFailsForInvalidMSSValues) {