Add tests for SO_REUSEADDR and SO_REUSEPORT.

* Basic tests for the SO_REUSEADDR and SO_REUSEPORT options.
* SO_REUSEADDR functional tests for TCP and UDP.
* SO_REUSEADDR and SO_REUSEPORT interaction tests for UDP.
* Stubbed support for UDP getsockopt(SO_REUSEADDR).

PiperOrigin-RevId: 280049265
This commit is contained in:
Ian Gudger
2019-11-12 14:04:14 -08:00
committed by gVisor bot
parent 548d65b2b6
commit 57a2a5ea33
7 changed files with 789 additions and 480 deletions
+4
View File
@@ -732,6 +732,10 @@ func (e *endpoint) GetSockOpt(opt interface{}) *tcpip.Error {
*o = tcpip.MulticastLoopOption(v)
return nil
case *tcpip.ReuseAddressOption:
*o = 0
return nil
case *tcpip.ReusePortOption:
e.mu.RLock()
v := e.reusePort
+1
View File
@@ -2234,6 +2234,7 @@ cc_library(
":ip_socket_test_util",
":socket_test_util",
"//test/util:test_util",
"@com_google_absl//absl/memory",
"@com_google_googletest//:gtest",
],
alwayslink = 1,
+118 -10
View File
@@ -35,7 +35,7 @@ TEST_P(UDPSocketPairTest, MulticastTTLDefault) {
int get = -1;
socklen_t get_len = sizeof(get);
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -52,7 +52,7 @@ TEST_P(UDPSocketPairTest, SetUDPMulticastTTLMin) {
int get = -1;
socklen_t get_len = sizeof(get);
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -69,7 +69,7 @@ TEST_P(UDPSocketPairTest, SetUDPMulticastTTLMax) {
int get = -1;
socklen_t get_len = sizeof(get);
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -91,7 +91,7 @@ TEST_P(UDPSocketPairTest, SetUDPMulticastTTLNegativeOne) {
int get = -1;
socklen_t get_len = sizeof(get);
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -126,7 +126,7 @@ TEST_P(UDPSocketPairTest, SetUDPMulticastTTLChar) {
int get = -1;
socklen_t get_len = sizeof(get);
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_TTL,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -147,7 +147,7 @@ TEST_P(UDPSocketPairTest, MulticastLoopDefault) {
int get = -1;
socklen_t get_len = sizeof(get);
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -163,7 +163,7 @@ TEST_P(UDPSocketPairTest, SetMulticastLoop) {
int get = -1;
socklen_t get_len = sizeof(get);
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -173,7 +173,7 @@ TEST_P(UDPSocketPairTest, SetMulticastLoop) {
&kSockOptOn, sizeof(kSockOptOn)),
SyscallSucceeds());
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -192,7 +192,7 @@ TEST_P(UDPSocketPairTest, SetMulticastLoopChar) {
int get = -1;
socklen_t get_len = sizeof(get);
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
@@ -202,12 +202,120 @@ TEST_P(UDPSocketPairTest, SetMulticastLoopChar) {
&kSockOptOnChar, sizeof(kSockOptOnChar)),
SyscallSucceeds());
EXPECT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
ASSERT_THAT(getsockopt(sockets->first_fd(), IPPROTO_IP, IP_MULTICAST_LOOP,
&get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOn);
}
TEST_P(UDPSocketPairTest, ReuseAddrDefault) {
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
int get = -1;
socklen_t get_len = sizeof(get);
ASSERT_THAT(
getsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEADDR, &get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOff);
}
TEST_P(UDPSocketPairTest, SetReuseAddr) {
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
// FIXME(b/129164367): Support SO_REUSEADDR on UDP sockets.
SKIP_IF(IsRunningOnGvisor());
ASSERT_THAT(setsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEADDR,
&kSockOptOn, sizeof(kSockOptOn)),
SyscallSucceeds());
int get = -1;
socklen_t get_len = sizeof(get);
ASSERT_THAT(
getsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEADDR, &get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOn);
ASSERT_THAT(setsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEADDR,
&kSockOptOff, sizeof(kSockOptOff)),
SyscallSucceeds());
ASSERT_THAT(
getsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEADDR, &get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOff);
}
TEST_P(UDPSocketPairTest, ReusePortDefault) {
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
int get = -1;
socklen_t get_len = sizeof(get);
ASSERT_THAT(
getsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEPORT, &get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOff);
}
TEST_P(UDPSocketPairTest, SetReusePort) {
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
ASSERT_THAT(setsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEPORT,
&kSockOptOn, sizeof(kSockOptOn)),
SyscallSucceeds());
int get = -1;
socklen_t get_len = sizeof(get);
ASSERT_THAT(
getsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEPORT, &get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOn);
ASSERT_THAT(setsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEPORT,
&kSockOptOff, sizeof(kSockOptOff)),
SyscallSucceeds());
ASSERT_THAT(
getsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEPORT, &get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOff);
}
TEST_P(UDPSocketPairTest, SetReuseAddrReusePort) {
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
// FIXME(b/129164367): Support SO_REUSEADDR on UDP sockets.
SKIP_IF(IsRunningOnGvisor());
ASSERT_THAT(setsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEADDR,
&kSockOptOn, sizeof(kSockOptOn)),
SyscallSucceeds());
ASSERT_THAT(setsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEPORT,
&kSockOptOn, sizeof(kSockOptOn)),
SyscallSucceeds());
int get = -1;
socklen_t get_len = sizeof(get);
ASSERT_THAT(
getsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEADDR, &get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOn);
ASSERT_THAT(
getsockopt(sockets->first_fd(), SOL_SOCKET, SO_REUSEPORT, &get, &get_len),
SyscallSucceedsWithValue(0));
EXPECT_EQ(get_len, sizeof(get));
EXPECT_EQ(get, kSockOptOn);
}
} // namespace testing
} // namespace gvisor
File diff suppressed because it is too large Load Diff
@@ -20,8 +20,8 @@
namespace gvisor {
namespace testing {
// Test fixture for tests that apply to pairs of IPv4 UDP sockets.
using IPv4UDPUnboundSocketPairTest = SocketPairTest;
// Test fixture for tests that apply to IPv4 UDP sockets.
using IPv4UDPUnboundSocketTest = SimpleSocketTest;
} // namespace testing
} // namespace gvisor
@@ -22,14 +22,11 @@
namespace gvisor {
namespace testing {
std::vector<SocketPairKind> GetSocketPairs() {
return ApplyVec<SocketPairKind>(
IPv4UDPUnboundSocketPair,
AllBitwiseCombinations(List<int>{0, SOCK_NONBLOCK}));
}
INSTANTIATE_TEST_SUITE_P(IPv4UDPSockets, IPv4UDPUnboundSocketPairTest,
::testing::ValuesIn(GetSocketPairs()));
INSTANTIATE_TEST_SUITE_P(
IPv4UDPSockets, IPv4UDPUnboundSocketTest,
::testing::ValuesIn(ApplyVec<SocketKind>(IPv4UDPUnboundSocket,
AllBitwiseCombinations(List<int>{
0, SOCK_NONBLOCK}))));
} // namespace testing
} // namespace gvisor
+3
View File
@@ -114,6 +114,9 @@ class FDSocketPair : public SocketPair {
public:
FDSocketPair(int first_fd, int second_fd)
: first_(first_fd), second_(second_fd) {}
FDSocketPair(std::unique_ptr<FileDescriptor> first_fd,
std::unique_ptr<FileDescriptor> second_fd)
: first_(first_fd->release()), second_(second_fd->release()) {}
int first_fd() const override { return first_.get(); }
int second_fd() const override { return second_.get(); }