Skip to content

Commit 5fb62e9

Browse files
Florian Westphaldavem330
authored andcommitted
selftests: mptcp: add tproxy test case
No hard dependencies here, just skip if test environ lacks nft binary or the needed kernel config options. The test case spawns listener in ns2 but ns1 will connect to the ip address of ns4. policy routing + tproxy rule will redirect packets to ns2 instead of forward. v3: - update mptcp/config (Mat Martineau) - more verbose SKIP messages in mptcp_connect.sh Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c9406a2 commit 5fb62e9

File tree

3 files changed

+136
-3
lines changed

3 files changed

+136
-3
lines changed

tools/testing/selftests/net/mptcp/config

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,9 @@ CONFIG_NFT_COUNTER=m
1313
CONFIG_NFT_COMPAT=m
1414
CONFIG_NETFILTER_XTABLES=m
1515
CONFIG_NETFILTER_XT_MATCH_BPF=m
16-
CONFIG_NF_TABLES_IPV4=y
17-
CONFIG_NF_TABLES_IPV6=y
16+
CONFIG_NF_TABLES_INET=y
17+
CONFIG_NFT_TPROXY=m
18+
CONFIG_NFT_SOCKET=m
19+
CONFIG_IP_ADVANCED_ROUTER=y
20+
CONFIG_IP_MULTIPLE_TABLES=y
21+
CONFIG_IPV6_MULTIPLE_TABLES=y

tools/testing/selftests/net/mptcp/mptcp_connect.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,12 @@ struct cfg_cmsg_types {
7575
unsigned int timestampns:1;
7676
};
7777

78+
struct cfg_sockopt_types {
79+
unsigned int transparent:1;
80+
};
81+
7882
static struct cfg_cmsg_types cfg_cmsg_types;
83+
static struct cfg_sockopt_types cfg_sockopt_types;
7984

8085
static void die_usage(void)
8186
{
@@ -93,6 +98,7 @@ static void die_usage(void)
9398
fprintf(stderr, "\t-u -- check mptcp ulp\n");
9499
fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n");
95100
fprintf(stderr, "\t-c cmsg -- test cmsg type <cmsg>\n");
101+
fprintf(stderr, "\t-o option -- test sockopt <option>\n");
96102
fprintf(stderr,
97103
"\t-P [saveWithPeek|saveAfterPeek] -- save data with/after MSG_PEEK form tcp socket\n");
98104
exit(1);
@@ -185,6 +191,22 @@ static void set_mark(int fd, uint32_t mark)
185191
}
186192
}
187193

194+
static void set_transparent(int fd, int pf)
195+
{
196+
int one = 1;
197+
198+
switch (pf) {
199+
case AF_INET:
200+
if (-1 == setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)))
201+
perror("IP_TRANSPARENT");
202+
break;
203+
case AF_INET6:
204+
if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_TRANSPARENT, &one, sizeof(one)))
205+
perror("IPV6_TRANSPARENT");
206+
break;
207+
}
208+
}
209+
188210
static int sock_listen_mptcp(const char * const listenaddr,
189211
const char * const port)
190212
{
@@ -212,6 +234,9 @@ static int sock_listen_mptcp(const char * const listenaddr,
212234
sizeof(one)))
213235
perror("setsockopt");
214236

237+
if (cfg_sockopt_types.transparent)
238+
set_transparent(sock, pf);
239+
215240
if (bind(sock, a->ai_addr, a->ai_addrlen) == 0)
216241
break; /* success */
217242

@@ -944,6 +969,27 @@ static void parse_cmsg_types(const char *type)
944969
exit(1);
945970
}
946971

972+
static void parse_setsock_options(const char *name)
973+
{
974+
char *next = strchr(name, ',');
975+
unsigned int len = 0;
976+
977+
if (next) {
978+
parse_setsock_options(next + 1);
979+
len = next - name;
980+
} else {
981+
len = strlen(name);
982+
}
983+
984+
if (strncmp(name, "TRANSPARENT", len) == 0) {
985+
cfg_sockopt_types.transparent = 1;
986+
return;
987+
}
988+
989+
fprintf(stderr, "Unrecognized setsockopt option %s\n", name);
990+
exit(1);
991+
}
992+
947993
int main_loop(void)
948994
{
949995
int fd;
@@ -1047,7 +1093,7 @@ static void parse_opts(int argc, char **argv)
10471093
{
10481094
int c;
10491095

1050-
while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:")) != -1) {
1096+
while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:o:")) != -1) {
10511097
switch (c) {
10521098
case 'j':
10531099
cfg_join = true;
@@ -1108,6 +1154,9 @@ static void parse_opts(int argc, char **argv)
11081154
case 'c':
11091155
parse_cmsg_types(optarg);
11101156
break;
1157+
case 'o':
1158+
parse_setsock_options(optarg);
1159+
break;
11111160
}
11121161
}
11131162

tools/testing/selftests/net/mptcp/mptcp_connect.sh

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,82 @@ run_tests()
671671
run_tests_lo $1 $2 $3 0
672672
}
673673

674+
run_test_transparent()
675+
{
676+
local connect_addr="$1"
677+
local msg="$2"
678+
679+
local connector_ns="$ns1"
680+
local listener_ns="$ns2"
681+
local lret=0
682+
local r6flag=""
683+
684+
# skip if we don't want v6
685+
if ! $ipv6 && is_v6 "${connect_addr}"; then
686+
return 0
687+
fi
688+
689+
ip netns exec "$listener_ns" nft -f /dev/stdin <<"EOF"
690+
flush ruleset
691+
table inet mangle {
692+
chain divert {
693+
type filter hook prerouting priority -150;
694+
695+
meta l4proto tcp socket transparent 1 meta mark set 1 accept
696+
tcp dport 20000 tproxy to :20000 meta mark set 1 accept
697+
}
698+
}
699+
EOF
700+
if [ $? -ne 0 ]; then
701+
echo "SKIP: $msg, could not load nft ruleset"
702+
return
703+
fi
704+
705+
local local_addr
706+
if is_v6 "${connect_addr}"; then
707+
local_addr="::"
708+
r6flag="-6"
709+
else
710+
local_addr="0.0.0.0"
711+
fi
712+
713+
ip -net "$listener_ns" $r6flag rule add fwmark 1 lookup 100
714+
if [ $? -ne 0 ]; then
715+
ip netns exec "$listener_ns" nft flush ruleset
716+
echo "SKIP: $msg, ip $r6flag rule failed"
717+
return
718+
fi
719+
720+
ip -net "$listener_ns" route add local $local_addr/0 dev lo table 100
721+
if [ $? -ne 0 ]; then
722+
ip netns exec "$listener_ns" nft flush ruleset
723+
ip -net "$listener_ns" $r6flag rule del fwmark 1 lookup 100
724+
echo "SKIP: $msg, ip route add local $local_addr failed"
725+
return
726+
fi
727+
728+
echo "INFO: test $msg"
729+
730+
TEST_COUNT=10000
731+
local extra_args="-o TRANSPARENT"
732+
do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP \
733+
${connect_addr} ${local_addr} "${extra_args}"
734+
lret=$?
735+
736+
ip netns exec "$listener_ns" nft flush ruleset
737+
ip -net "$listener_ns" $r6flag rule del fwmark 1 lookup 100
738+
ip -net "$listener_ns" route del local $local_addr/0 dev lo table 100
739+
740+
if [ $lret -ne 0 ]; then
741+
echo "FAIL: $msg, mptcp connection error" 1>&2
742+
ret=$lret
743+
return 1
744+
fi
745+
746+
echo "PASS: $msg"
747+
return 0
748+
}
749+
674750
run_tests_peekmode()
675751
{
676752
local peekmode="$1"
@@ -794,5 +870,9 @@ run_tests_peekmode "saveWithPeek"
794870
run_tests_peekmode "saveAfterPeek"
795871
stop_if_error "Tests with peek mode have failed"
796872

873+
# connect to ns4 ip address, ns2 should intercept/proxy
874+
run_test_transparent 10.0.3.1 "tproxy ipv4"
875+
run_test_transparent dead:beef:3::1 "tproxy ipv6"
876+
797877
display_time
798878
exit $ret

0 commit comments

Comments
 (0)