Skip to content

Commit c91d810

Browse files
committed
issue: HPCINFRA-3949 distinguish remote addresses
Split the remote address configuration into two separate addresses to properly test different network scenarios: 1. remote_addr (-r): Non-routable address for bind failure tests (e.g., 74.190.183.38 or fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff) Used in tcp_bind.ti_2 and udp_bind.ti_2 to verify EADDRNOTAVAIL 2. remote_routable_addr (-g): Routable address for connect tests (dynamically detected default gateway or manually specified) Used in tcp_event.ti_2, udp_connect.ti_2 to test actual routing Remove the def_gw_exists flag and sys_gateway() C++ function, moving gateway detection to the shell script layer using do_get_gateway(). This bash function mirrors the original C++ logic using route command to detect default gateway for both IPv4 and IPv6. Update gtest.sh to dynamically detect system default, making tests more portable across different network environments. Gateway detection happens at test invocation time rather than during test execution. Remove SKIP_TRUE(def_gw_exists) checks from tests as gateway detection is now handled by the shell script which passes the appropriate address via command-line arguments. Tests requiring routable addresses will receive the actual gateway IP, while bind failure tests continue using non-routable dummy addresses. Changes: - Add remote_routable_addr to gtest_configure_t structure - Add -g/--remote-routable command-line option to gtest - Implement do_get_gateway() bash function in gtest.sh - Update tcp_event and udp_connect tests to use remote_routable_addr - Remove sys_gateway() function from common/sys.cc - Remove def_gw_exists flag from test_base class - Remove gateway detection skip logic from individual tests Signed-off-by: Tomer Cabouly <[email protected]>
1 parent d9d85e9 commit c91d810

File tree

11 files changed

+113
-106
lines changed

11 files changed

+113
-106
lines changed

contrib/jenkins_tests/gtest.sh

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,38 @@ function do_get_addrs()
5858
echo $gtest_ip_list
5959
}
6060

61-
gtest_opt="--addr=$(do_get_addrs 'eth' ${opt2})"
62-
gtest_opt_ipv6="--addr=$(do_get_addrs 'inet6' ${opt2}) -r fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" # Remote - Dummy Address
61+
# Retrieve default gateway address
62+
# $1 - family type: 'inet' for IPv4, 'inet6' for IPv6
63+
# Returns: gateway IP address or empty string if not found
64+
function do_get_gateway()
65+
{
66+
local family=$1
67+
local gateway=""
68+
69+
if [ "$family" = "inet6" ]; then
70+
# IPv6: route -6 -n | grep 'UG[ \t]' | awk '{print $2}' | head -1
71+
gateway=$(route -6 -n 2>/dev/null | grep 'UG[ \t]' | awk '{print $2}' | head -1)
72+
else
73+
# IPv4: route -n | grep 'UG[ \t]' | awk '{print $2}' | head -1
74+
gateway=$(route -n 2>/dev/null | grep 'UG[ \t]' | awk '{print $2}' | head -1)
75+
fi
76+
77+
echo "$gateway"
78+
}
79+
80+
# Detect gateway for IPv4
81+
gateway_ipv4=$(do_get_gateway 'inet')
82+
if [ -z "$gateway_ipv4" ]; then
83+
echo "[FAIL] No IPv4 gateway found. Tests requiring routable address cannot run." >&2
84+
exit 1
85+
fi
86+
gtest_opt="--addr=$(do_get_addrs 'eth' ${opt2}) -r 192.0.2.1 -g $gateway_ipv4" # -r is TEST-NET-1 (RFC 5737) non-routable test address
87+
88+
# Detect gateway for IPv6
89+
gateway_ipv6=$(do_get_gateway 'inet6')
90+
91+
# IpV6 tests don't need a gateway address, so we don't enforce it unlike IPv4.
92+
gtest_opt_ipv6="--addr=$(do_get_addrs 'inet6' ${opt2}) -r fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff ${gateway_ipv6:+-g $gateway_ipv6}" # -r is a dummy address
6393

6494
set +eE
6595

tests/gtest/common/base.cc

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ uint16_t test_base::m_port = 0;
1313
int test_base::m_family = PF_INET;
1414
int test_base::m_break_signal = 0;
1515

16+
static void convert_and_copy_address(const sockaddr_store_t &source, sockaddr_store_t &dest,
17+
sa_family_t target_family)
18+
{
19+
if (((struct sockaddr *)&source)->sa_family != target_family) {
20+
memset(&dest, 0, sizeof(dest));
21+
((struct sockaddr *)&dest)->sa_family = target_family;
22+
sys_ipv4_to_ipv6(&((struct sockaddr_in *)&source)->sin_addr,
23+
&((struct sockaddr_in6 *)&dest)->sin6_addr);
24+
sys_set_port((struct sockaddr *)&dest, sys_get_port((struct sockaddr *)&source));
25+
} else {
26+
memcpy(&dest, &source, sizeof(dest));
27+
}
28+
}
29+
1630
test_base::test_base()
1731
{
1832
m_port = gtest_conf.port;
@@ -23,38 +37,10 @@ test_base::test_base()
2337
m_family = PF_INET6;
2438
}
2539

26-
if (((struct sockaddr *)&gtest_conf.client_addr)->sa_family != m_family) {
27-
memset(&client_addr, 0, sizeof(client_addr));
28-
((struct sockaddr *)&client_addr)->sa_family = m_family;
29-
sys_ipv4_to_ipv6(&((struct sockaddr_in *)&gtest_conf.client_addr)->sin_addr,
30-
&((struct sockaddr_in6 *)&client_addr)->sin6_addr);
31-
sys_set_port((struct sockaddr *)&client_addr,
32-
sys_get_port((struct sockaddr *)&gtest_conf.client_addr));
33-
} else {
34-
memcpy(&client_addr, &gtest_conf.client_addr, sizeof(client_addr));
35-
}
36-
37-
if (((struct sockaddr *)&gtest_conf.server_addr)->sa_family != m_family) {
38-
memset(&server_addr, 0, sizeof(server_addr));
39-
((struct sockaddr *)&server_addr)->sa_family = m_family;
40-
sys_ipv4_to_ipv6(&((struct sockaddr_in *)&gtest_conf.server_addr)->sin_addr,
41-
&((struct sockaddr_in6 *)&server_addr)->sin6_addr);
42-
sys_set_port((struct sockaddr *)&server_addr,
43-
sys_get_port((struct sockaddr *)&gtest_conf.server_addr));
44-
} else {
45-
memcpy(&server_addr, &gtest_conf.server_addr, sizeof(server_addr));
46-
}
47-
48-
if (((struct sockaddr *)&gtest_conf.remote_addr)->sa_family != m_family) {
49-
memset(&remote_addr, 0, sizeof(remote_addr));
50-
((struct sockaddr *)&remote_addr)->sa_family = m_family;
51-
sys_ipv4_to_ipv6(&((struct sockaddr_in *)&gtest_conf.remote_addr)->sin_addr,
52-
&((struct sockaddr_in6 *)&remote_addr)->sin6_addr);
53-
sys_set_port((struct sockaddr *)&remote_addr,
54-
sys_get_port((struct sockaddr *)&gtest_conf.remote_addr));
55-
} else {
56-
memcpy(&remote_addr, &gtest_conf.remote_addr, sizeof(remote_addr));
57-
}
40+
convert_and_copy_address(gtest_conf.client_addr, client_addr, m_family);
41+
convert_and_copy_address(gtest_conf.server_addr, server_addr, m_family);
42+
convert_and_copy_address(gtest_conf.remote_addr, remote_addr, m_family);
43+
convert_and_copy_address(gtest_conf.remote_routable_addr, remote_routable_addr, m_family);
5844

5945
memset(&bogus_addr, 0, sizeof(bogus_addr));
6046
((struct sockaddr *)&bogus_addr)->sa_family = m_family;
@@ -67,8 +53,6 @@ test_base::test_base()
6753
&(((struct sockaddr_in6 *)&bogus_addr)->sin6_addr));
6854
}
6955

70-
def_gw_exists = gtest_conf.def_gw_exists;
71-
7256
m_efd_signal = 0;
7357
m_efd = eventfd(m_efd_signal, 0);
7458

tests/gtest/common/base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ class test_base {
8080
sockaddr_store_t client_addr;
8181
sockaddr_store_t server_addr;
8282
sockaddr_store_t remote_addr;
83+
sockaddr_store_t remote_routable_addr;
8384
sockaddr_store_t bogus_addr;
84-
bool def_gw_exists;
8585
static uint16_t m_port;
8686
static int m_family;
8787

tests/gtest/common/def.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ struct gtest_configure_t {
105105
sockaddr_store_t client_addr;
106106
sockaddr_store_t server_addr;
107107
sockaddr_store_t remote_addr;
108+
sockaddr_store_t remote_routable_addr;
108109
uint16_t port;
109-
bool def_gw_exists;
110110
};
111111

112112
#endif /* TESTS_GTEST_COMMON_DEF_H_ */

tests/gtest/common/sys.cc

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -157,39 +157,6 @@ int sys_dev2addr(const char *dev, struct sockaddr *addr)
157157
return rc;
158158
}
159159

160-
bool sys_gateway(struct sockaddr *addr, sa_family_t family)
161-
{
162-
sockaddr_store_t temp_addr;
163-
bool found = false;
164-
char line[256];
165-
const char cmd4[] = "route -n | grep 'UG[ \t]' | awk '{print $2}'";
166-
const char cmd6[] = "route -6 -n | grep 'UG[ \t]' | awk '{print $2}'";
167-
const char *cmd_ptr = (family == AF_INET ? cmd4 : cmd6);
168-
169-
FILE *file = popen(cmd_ptr, "r");
170-
if (!file) {
171-
log_warn("Unable to execute '%s'.\n", cmd_ptr);
172-
return false;
173-
}
174-
175-
while (fgets(line, sizeof(line), file) != NULL && !found) {
176-
size_t len = strlen(line);
177-
if (line[len - 1] == '\n' || line[len - 1] == '\r') {
178-
line[len - 1] = 0;
179-
}
180-
sys_str2addr(line, &temp_addr.addr, false);
181-
found = (temp_addr.addr.sa_family == family);
182-
if (found) {
183-
sys_str2addr(line, addr, false);
184-
log_trace("%s found gateway ip: %s\n", line, sys_addr2str(addr));
185-
}
186-
}
187-
188-
pclose(file);
189-
190-
return found;
191-
}
192-
193160
// Converts address to sockaddr structure. On an error, addr->sa_family is AF_UNSPEC.
194161
void sys_str2addr(const char *buf, struct sockaddr *addr, bool port)
195162
{

tests/gtest/common/sys.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ char *sys_addr2dev(const struct sockaddr *addr, char *buf, size_t size);
111111

112112
int sys_dev2addr(const char *dev, struct sockaddr *addr);
113113

114-
bool sys_gateway(struct sockaddr *addr, sa_family_t family);
115-
116114
void sys_str2addr(const char *buf, struct sockaddr *addr, bool port = true);
117115

118116
static INLINE char *sys_addr2str(const struct sockaddr *addr, bool port = true)

tests/gtest/main.cc

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -52,40 +52,57 @@ static int _def_config(void)
5252

5353
sys_str2addr("0.0.0.0[0]", (struct sockaddr *)&gtest_conf.client_addr, true);
5454
sys_str2addr("0.0.0.0[0]", (struct sockaddr *)&gtest_conf.server_addr, true);
55-
sys_str2addr("0.0.0.0[8888]", (struct sockaddr *)&gtest_conf.remote_addr, true);
55+
sys_str2addr("192.0.2.1[8888]", (struct sockaddr *)&gtest_conf.remote_addr, true);
56+
sys_str2addr("127.0.0.1[8888]", (struct sockaddr *)&gtest_conf.remote_routable_addr, true);
5657

5758
gtest_conf.port = 55555;
5859

5960
return rc;
6061
}
6162

62-
static void set_def_remote_address()
63+
static void set_def_remote_address(bool user_defined_routable, bool user_defined_remote)
6364
{
64-
gtest_conf.def_gw_exists = sys_gateway((struct sockaddr *)&gtest_conf.remote_addr,
65-
gtest_conf.server_addr.addr.sa_family);
6665
if (gtest_conf.server_addr.addr.sa_family == AF_INET6) {
67-
if (!gtest_conf.def_gw_exists) {
68-
sys_str2addr("::[8888]", (struct sockaddr *)&gtest_conf.remote_addr, true);
66+
if (!user_defined_remote) {
67+
// Replace IPv4 non-routable default with IPv6 non-routable address
68+
sys_str2addr("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff[8888]",
69+
(struct sockaddr *)&gtest_conf.remote_addr, true);
6970
} else {
71+
// User provided -r, just ensure port is set
7072
gtest_conf.remote_addr.addr6.sin6_port = htons(8888);
7173
}
74+
if (!user_defined_routable) {
75+
// User didn't provide -g, use IPv6 localhost as default
76+
sys_str2addr("::1[8888]", (struct sockaddr *)&gtest_conf.remote_routable_addr, true);
77+
} else {
78+
// User provided -g, just ensure port is set
79+
gtest_conf.remote_routable_addr.addr6.sin6_port = htons(8888);
80+
}
81+
} else if (gtest_conf.server_addr.addr.sa_family == AF_INET) {
82+
gtest_conf.remote_addr.addr4.sin_port = htons(8888);
83+
gtest_conf.remote_routable_addr.addr4.sin_port = htons(8888);
7284
}
7385
}
7486

7587
static int _set_config(int argc, char **argv)
7688
{
7789
int rc = 0;
7890
static struct option long_options[] = {
79-
{"addr", required_argument, 0, 'a'}, {"if", required_argument, 0, 'i'},
80-
{"remote", required_argument, 0, 'r'}, {"port", required_argument, 0, 'p'},
81-
{"random", required_argument, 0, 's'}, {"debug", required_argument, 0, 'd'},
91+
{"addr", required_argument, 0, 'a'},
92+
{"if", required_argument, 0, 'i'},
93+
{"remote-non-routable", required_argument, 0, 'r'},
94+
{"remote-routable", required_argument, 0, 'g'},
95+
{"port", required_argument, 0, 'p'},
96+
{"random", required_argument, 0, 's'},
97+
{"debug", required_argument, 0, 'd'},
8298
{"help", no_argument, 0, 'h'},
8399
};
84100
int op;
85101
int option_index;
86102
bool user_defined_remote = false;
103+
bool user_defined_routable = false;
87104

88-
while ((op = getopt_long(argc, argv, "a:i:r:p:d:h", long_options, &option_index)) != -1) {
105+
while ((op = getopt_long(argc, argv, "a:i:r:g:p:d:h", long_options, &option_index)) != -1) {
89106
switch (op) {
90107
case 'a': {
91108
char *token1 = NULL;
@@ -155,6 +172,15 @@ static int _set_config(int argc, char **argv)
155172
user_defined_remote = true;
156173
}
157174
} break;
175+
case 'g': {
176+
rc = sys_get_addr(optarg, (struct sockaddr *)&gtest_conf.remote_routable_addr);
177+
if (rc < 0) {
178+
rc = -EINVAL;
179+
log_fatal("Failed to resolve ip address %s\n", optarg);
180+
} else {
181+
user_defined_routable = true;
182+
}
183+
} break;
158184
case 'p':
159185
errno = 0;
160186
gtest_conf.port = strtol(optarg, NULL, 0);
@@ -195,16 +221,16 @@ static int _set_config(int argc, char **argv)
195221
srand(gtest_conf.random_seed);
196222
sys_set_port((struct sockaddr *)&gtest_conf.server_addr, gtest_conf.port);
197223

198-
if (!user_defined_remote) {
199-
set_def_remote_address();
200-
}
224+
set_def_remote_address(user_defined_routable, user_defined_remote);
201225

202226
log_info("CONFIGURATION:\n");
203227
log_info("log level: %d\n", gtest_conf.log_level);
204228
log_info("seed: %d\n", gtest_conf.random_seed);
205229
log_info("client ip: %s\n", sys_addr2str((struct sockaddr *)&gtest_conf.client_addr));
206230
log_info("server ip: %s\n", sys_addr2str((struct sockaddr *)&gtest_conf.server_addr));
207231
log_info("remote ip: %s\n", sys_addr2str((struct sockaddr *)&gtest_conf.remote_addr));
232+
log_info("remote routable ip: %s\n",
233+
sys_addr2str((struct sockaddr *)&gtest_conf.remote_routable_addr));
208234
log_info("port: %d\n", gtest_conf.port);
209235
}
210236

@@ -214,13 +240,14 @@ static int _set_config(int argc, char **argv)
214240
static void _usage(void)
215241
{
216242
printf("Usage: gtest [options]\n"
217-
"\t--addr,-a <ip,ip> IP address client,server\n"
218-
"\t--if,-i <ip,ip> Interface client,server\n"
219-
"\t--remote,-r <ip> IP address remote\n"
220-
"\t--port,-p <num> Listen/connect to port <num> (default %d).\n"
221-
"\t--random,-s <count> Seed (default %d).\n"
222-
"\t--debug,-d <level> Output verbose level (default: %d).\n"
223-
"\t--help,-h Print help and exit\n",
243+
"\t--addr,-a <ip,ip> IP address client,server\n"
244+
"\t--if,-i <ip,ip> Interface client,server\n"
245+
"\t--remote-non-routable,-r <ip> IP address not reachable\n"
246+
"\t--remote-routable,-g <ip> IP address reachable\n"
247+
"\t--port,-p <num> Listen/connect to port <num> (default %d).\n"
248+
"\t--random,-s <count> Seed (default %d).\n"
249+
"\t--debug,-d <level> Output verbose level (default: %d).\n"
250+
"\t--help,-h Print help and exit\n",
224251

225252
gtest_conf.port, gtest_conf.random_seed, gtest_conf.log_level);
226253
exit(0);

tests/gtest/tcp/tcp_bind.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ TEST_F(tcp_bind, ti_2)
115115
int rc = EOK;
116116
int fd;
117117

118-
SKIP_TRUE(def_gw_exists, "No Default Gateway");
119-
120118
fd = tcp_base::sock_create();
121119
ASSERT_LE(0, fd);
122120

tests/gtest/tcp/tcp_event.cc

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,25 @@ TEST_F(tcp_event, DISABLED_ti_1)
3838

3939
TEST_F(tcp_event, ti_2)
4040
{
41+
// Skip if running with default localhost address - test requires real gateway via -g
42+
if (remote_routable_addr.addr.sa_family == AF_INET) {
43+
if (remote_routable_addr.addr4.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
44+
GTEST_SKIP() << "Test requires real gateway address via -g flag (not localhost)";
45+
}
46+
} else if (remote_routable_addr.addr.sa_family == AF_INET6) {
47+
if (IN6_IS_ADDR_LOOPBACK(&remote_routable_addr.addr6.sin6_addr)) {
48+
GTEST_SKIP() << "Test requires real gateway address via -g flag (not localhost)";
49+
}
50+
}
51+
4152
int rc = EOK;
4253
int fd;
4354
struct epoll_event event;
4455

45-
SKIP_TRUE(def_gw_exists, "No Default Gateway");
46-
4756
fd = tcp_base::sock_create_nb();
4857
ASSERT_LE(0, fd);
4958

50-
rc = connect(fd, (struct sockaddr *)&remote_addr, sizeof(remote_addr));
59+
rc = connect(fd, (struct sockaddr *)&remote_routable_addr, sizeof(remote_routable_addr));
5160
ASSERT_EQ(EINPROGRESS, errno);
5261
ASSERT_EQ((-1), rc);
5362

@@ -92,7 +101,7 @@ TEST_F(tcp_event, DISABLED_ti_4)
92101
fd = tcp_base::sock_create_nb();
93102
ASSERT_LE(0, fd);
94103

95-
rc = connect(fd, (struct sockaddr *)&remote_addr, sizeof(remote_addr));
104+
rc = connect(fd, (struct sockaddr *)&remote_routable_addr, sizeof(remote_routable_addr));
96105
ASSERT_EQ(EINPROGRESS, errno);
97106
ASSERT_EQ((-1), rc);
98107

tests/gtest/udp/udp_bind.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,6 @@ TEST_F(udp_bind, ti_2)
110110
int rc = EOK;
111111
int fd;
112112

113-
SKIP_TRUE(def_gw_exists, "No Default Gateway");
114-
115113
fd = udp_base::sock_create();
116114
ASSERT_LE(0, fd);
117115

0 commit comments

Comments
 (0)