Message ID | 20211028093902.8685-3-fw@strlen.de (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
Series | mptcp: add freebind & transparent sockopt | expand |
Context | Check | Description |
---|---|---|
matttbe/build | success | Build and static analysis OK |
matttbe/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 195 lines checked |
On Thu, 28 Oct 2021, Florian Westphal wrote: > 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. > > v2: update mptcp/config (Mat Martineau) > > Signed-off-by: Florian Westphal <fw@strlen.de> > --- > tools/testing/selftests/net/mptcp/config | 7 +- > .../selftests/net/mptcp/mptcp_connect.c | 51 +++++++++++- > .../selftests/net/mptcp/mptcp_connect.sh | 80 +++++++++++++++++++ > 3 files changed, 135 insertions(+), 3 deletions(-) > ... > diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh > index 559173a8e387..205e9f0c4296 100755 > --- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh > +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh > @@ -671,6 +671,82 @@ run_tests() > run_tests_lo $1 $2 $3 0 > } > > +run_test_transparent() > +{ > + local connect_addr="$1" > + local msg="$2" > + > + local connector_ns="$ns1" > + local listener_ns="$ns2" > + local lret=0 > + local r6flag="" > + > + # skip if we don't want v6 > + if ! $ipv6 && is_v6 "${connect_addr}"; then > + return 0 > + fi > + > +ip netns exec "$listener_ns" nft -f /dev/stdin <<"EOF" > +flush ruleset > +table inet mangle { > + chain divert { > + type filter hook prerouting priority -150; > + > + meta l4proto tcp socket transparent 1 meta mark set 1 accept > + tcp dport 20000 tproxy to :20000 meta mark set 1 accept > + } > +} > +EOF > + if [ $? -ne 0 ]; then > + echo "SKIP: $msg" > + return > + fi > + > + local local_addr > + if is_v6 "${connect_addr}"; then > + local_addr="::" > + r6flag="-6" > + else > + local_addr="0.0.0.0" > + fi > + > + ip -net "$listener_ns" $r6flag rule add fwmark 1 lookup 100 Something's still missing from the kernel config - this works with ipv4 but with ipv6 I get: Error: Rule family not supported. I experimented with a couple of extra CONFIG_IP6_NF* options but didn't find the right ones, here are the ipv6/netfilter options I tried unsuccessfully: # # IPv6: Netfilter Configuration # CONFIG_NF_SOCKET_IPV6=y CONFIG_NF_TPROXY_IPV6=y CONFIG_NF_TABLES_IPV6=y # CONFIG_NFT_DUP_IPV6 is not set # CONFIG_NFT_FIB_IPV6 is not set # CONFIG_NF_DUP_IPV6 is not set CONFIG_NF_REJECT_IPV6=y CONFIG_NF_LOG_IPV6=m CONFIG_IP6_NF_IPTABLES=y # CONFIG_IP6_NF_MATCH_AH is not set # CONFIG_IP6_NF_MATCH_EUI64 is not set # CONFIG_IP6_NF_MATCH_FRAG is not set # CONFIG_IP6_NF_MATCH_OPTS is not set # CONFIG_IP6_NF_MATCH_HL is not set # CONFIG_IP6_NF_MATCH_IPV6HEADER is not set # CONFIG_IP6_NF_MATCH_MH is not set # CONFIG_IP6_NF_MATCH_RPFILTER is not set # CONFIG_IP6_NF_MATCH_RT is not set # CONFIG_IP6_NF_MATCH_SRH is not set # CONFIG_IP6_NF_TARGET_HL is not set CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y # CONFIG_IP6_NF_TARGET_SYNPROXY is not set CONFIG_IP6_NF_MANGLE=y # CONFIG_IP6_NF_RAW is not set # CONFIG_IP6_NF_SECURITY is not set CONFIG_IP6_NF_NAT=y # CONFIG_IP6_NF_TARGET_MASQUERADE is not set # CONFIG_IP6_NF_TARGET_NPT is not set # end of IPv6: Netfilter Configuration I generate the config for my MPTCP tests with: make defconfig make kvm_guest.config ... and then the options in the selftest config file plus some extra debug features like KASAN and such. I'm attaching the full config in case you want to reference that. -- Mat Martineau Intel
Mat Martineau <mathew.j.martineau@linux.intel.com> wrote: > > + ip -net "$listener_ns" $r6flag rule add fwmark 1 lookup 100 > > Something's still missing from the kernel config - this works with ipv4 but > with ipv6 I get: > > Error: Rule family not supported. Yep, ip -6 rule fails. > I experimented with a couple of extra CONFIG_IP6_NF* options but didn't find > the right ones, here are the ipv6/netfilter options I tried unsuccessfully: Thanks for providing your .config, this helped a lot. CONFIG_IPV6_MULTIPLE_TABLES is missing. I'll send a v3 once I've confirmed your config works with this option enabled, I'll also make the SKIP message a bit more verbose.
diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config index 0faaccd21447..8a45ee6b54e8 100644 --- a/tools/testing/selftests/net/mptcp/config +++ b/tools/testing/selftests/net/mptcp/config @@ -13,5 +13,8 @@ CONFIG_NFT_COUNTER=m CONFIG_NFT_COMPAT=m CONFIG_NETFILTER_XTABLES=m CONFIG_NETFILTER_XT_MATCH_BPF=m -CONFIG_NF_TABLES_IPV4=y -CONFIG_NF_TABLES_IPV6=y +CONFIG_NF_TABLES_INET=y +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SOCKET=m +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.c b/tools/testing/selftests/net/mptcp/mptcp_connect.c index 95e81d557b08..ada9b80774d4 100644 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.c +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.c @@ -75,7 +75,12 @@ struct cfg_cmsg_types { unsigned int timestampns:1; }; +struct cfg_sockopt_types { + unsigned int transparent:1; +}; + static struct cfg_cmsg_types cfg_cmsg_types; +static struct cfg_sockopt_types cfg_sockopt_types; static void die_usage(void) { @@ -93,6 +98,7 @@ static void die_usage(void) fprintf(stderr, "\t-u -- check mptcp ulp\n"); fprintf(stderr, "\t-w num -- wait num sec before closing the socket\n"); fprintf(stderr, "\t-c cmsg -- test cmsg type <cmsg>\n"); + fprintf(stderr, "\t-o option -- test sockopt <option>\n"); fprintf(stderr, "\t-P [saveWithPeek|saveAfterPeek] -- save data with/after MSG_PEEK form tcp socket\n"); exit(1); @@ -185,6 +191,22 @@ static void set_mark(int fd, uint32_t mark) } } +static void set_transparent(int fd, int pf) +{ + int one = 1; + + switch (pf) { + case AF_INET: + if (-1 == setsockopt(fd, SOL_IP, IP_TRANSPARENT, &one, sizeof(one))) + perror("IP_TRANSPARENT"); + break; + case AF_INET6: + if (-1 == setsockopt(fd, IPPROTO_IPV6, IPV6_TRANSPARENT, &one, sizeof(one))) + perror("IPV6_TRANSPARENT"); + break; + } +} + static int sock_listen_mptcp(const char * const listenaddr, const char * const port) { @@ -212,6 +234,9 @@ static int sock_listen_mptcp(const char * const listenaddr, sizeof(one))) perror("setsockopt"); + if (cfg_sockopt_types.transparent) + set_transparent(sock, pf); + if (bind(sock, a->ai_addr, a->ai_addrlen) == 0) break; /* success */ @@ -944,6 +969,27 @@ static void parse_cmsg_types(const char *type) exit(1); } +static void parse_setsock_options(const char *name) +{ + char *next = strchr(name, ','); + unsigned int len = 0; + + if (next) { + parse_setsock_options(next + 1); + len = next - name; + } else { + len = strlen(name); + } + + if (strncmp(name, "TRANSPARENT", len) == 0) { + cfg_sockopt_types.transparent = 1; + return; + } + + fprintf(stderr, "Unrecognized setsockopt option %s\n", name); + exit(1); +} + int main_loop(void) { int fd; @@ -1047,7 +1093,7 @@ static void parse_opts(int argc, char **argv) { int c; - while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:")) != -1) { + while ((c = getopt(argc, argv, "6jr:lp:s:hut:T:m:S:R:w:M:P:c:o:")) != -1) { switch (c) { case 'j': cfg_join = true; @@ -1108,6 +1154,9 @@ static void parse_opts(int argc, char **argv) case 'c': parse_cmsg_types(optarg); break; + case 'o': + parse_setsock_options(optarg); + break; } } diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh index 559173a8e387..205e9f0c4296 100755 --- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh +++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh @@ -671,6 +671,82 @@ run_tests() run_tests_lo $1 $2 $3 0 } +run_test_transparent() +{ + local connect_addr="$1" + local msg="$2" + + local connector_ns="$ns1" + local listener_ns="$ns2" + local lret=0 + local r6flag="" + + # skip if we don't want v6 + if ! $ipv6 && is_v6 "${connect_addr}"; then + return 0 + fi + +ip netns exec "$listener_ns" nft -f /dev/stdin <<"EOF" +flush ruleset +table inet mangle { + chain divert { + type filter hook prerouting priority -150; + + meta l4proto tcp socket transparent 1 meta mark set 1 accept + tcp dport 20000 tproxy to :20000 meta mark set 1 accept + } +} +EOF + if [ $? -ne 0 ]; then + echo "SKIP: $msg" + return + fi + + local local_addr + if is_v6 "${connect_addr}"; then + local_addr="::" + r6flag="-6" + else + local_addr="0.0.0.0" + fi + + ip -net "$listener_ns" $r6flag rule add fwmark 1 lookup 100 + if [ $? -ne 0 ]; then + ip netns exec "$listener_ns" nft flush ruleset + echo "SKIP: $msg" + return + fi + + ip -net "$listener_ns" route add local $local_addr/0 dev lo table 100 + if [ $? -ne 0 ]; then + ip netns exec "$listener_ns" nft flush ruleset + ip -net "$listener_ns" $r6flag rule del fwmark 1 lookup 100 + echo "SKIP: $msg" + return + fi + + echo "INFO: test $msg" + + TEST_COUNT=10000 + local extra_args="-o TRANSPARENT" + do_transfer ${listener_ns} ${connector_ns} MPTCP MPTCP \ + ${connect_addr} ${local_addr} "${extra_args}" + lret=$? + + ip netns exec "$listener_ns" nft flush ruleset + ip -net "$listener_ns" $r6flag rule del fwmark 1 lookup 100 + ip -net "$listener_ns" route del local $local_addr/0 dev lo table 100 + + if [ $lret -ne 0 ]; then + echo "FAIL: $msg" 1>&2 + ret=$lret + return 1 + fi + + echo "PASS: $msg" + return 0 +} + run_tests_peekmode() { local peekmode="$1" @@ -794,5 +870,9 @@ run_tests_peekmode "saveWithPeek" run_tests_peekmode "saveAfterPeek" stop_if_error "Tests with peek mode have failed" +# connect to ns4 ip address, ns2 should intercept/proxy +run_test_transparent 10.0.3.1 "tproxy ipv4" +run_test_transparent dead:beef:3::1 "tproxy ipv6" + display_time exit $ret
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. v2: update mptcp/config (Mat Martineau) Signed-off-by: Florian Westphal <fw@strlen.de> --- tools/testing/selftests/net/mptcp/config | 7 +- .../selftests/net/mptcp/mptcp_connect.c | 51 +++++++++++- .../selftests/net/mptcp/mptcp_connect.sh | 80 +++++++++++++++++++ 3 files changed, 135 insertions(+), 3 deletions(-)