All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt
@ 2021-10-29 11:09 Florian Westphal
  2021-10-29 11:09 ` [PATCH mptcp-next v3 1/2] mptcp: sockopt: add SOL_IP freebind & transparent options Florian Westphal
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Florian Westphal @ 2021-10-29 11:09 UTC (permalink / raw)
  To: mptcp; +Cc: Florian Westphal

First patch adds ipv4/ipv6 TRANSPARENT and FREEBIND, second
patch adds a selftest to mptcp_connect.sh.

Only change is in patch 2 which has more verbose SKIP messages
and an updated mptcp/config to account for IPV6_MULTIPLE_TABLES
and other toggles required for the tproxy test case.

Florian Westphal (2):
  mptcp: sockopt: add SOL_IP freebind & transparent options
  selftests: mptcp: add tproxy test case

 net/mptcp/sockopt.c                           | 66 ++++++++++++++-
 net/mptcp/subflow.c                           |  3 +-
 .../selftests/net/mptcp/config                |  7 ++-
 .../selftests/net/mptcp/mptcp_connect.c       | 51 +++++++++++-
 .../selftests/net/mptcp/mptcp_connect.sh      | 80 +++++++++++++++++++
 5 files changed, 202 insertions(+), 5 deletions(-)
-- 
2.32.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH mptcp-next v3 1/2] mptcp: sockopt: add SOL_IP freebind & transparent options
  2021-10-29 11:09 [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt Florian Westphal
@ 2021-10-29 11:09 ` Florian Westphal
  2021-10-29 11:09 ` [PATCH mptcp-next v3 2/2] selftests: mptcp: add tproxy test case Florian Westphal
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2021-10-29 11:09 UTC (permalink / raw)
  To: mptcp; +Cc: Florian Westphal

These options also need to be set before bind, so do the sync of msk to
new ssk socket a bit earlier.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 no changes
 net/mptcp/sockopt.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-
 net/mptcp/subflow.c |  3 ++-
 2 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
index b452571e8d9b..b818e91f2e09 100644
--- a/net/mptcp/sockopt.c
+++ b/net/mptcp/sockopt.c
@@ -390,6 +390,8 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
 
 	switch (optname) {
 	case IPV6_V6ONLY:
+	case IPV6_TRANSPARENT:
+	case IPV6_FREEBIND:
 		lock_sock(sk);
 		ssock = __mptcp_nmpc_socket(msk);
 		if (!ssock) {
@@ -398,8 +400,24 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
 		}
 
 		ret = tcp_setsockopt(ssock->sk, SOL_IPV6, optname, optval, optlen);
-		if (ret == 0)
+		if (ret != 0) {
+			release_sock(sk);
+			return ret;
+		}
+
+		sockopt_seq_inc(msk);
+
+		switch (optname) {
+		case IPV6_V6ONLY:
 			sk->sk_ipv6only = ssock->sk->sk_ipv6only;
+			break;
+		case IPV6_TRANSPARENT:
+			inet_sk(sk)->transparent = inet_sk(ssock->sk)->transparent;
+			break;
+		case IPV6_FREEBIND:
+			inet_sk(sk)->freebind = inet_sk(ssock->sk)->freebind;
+			break;
+		}
 
 		release_sock(sk);
 		break;
@@ -598,6 +616,46 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t
 	return ret;
 }
 
+static int mptcp_setsockopt_sol_ip_set_transparent(struct mptcp_sock *msk, int optname,
+						   sockptr_t optval, unsigned int optlen)
+{
+	struct sock *sk = (struct sock *)msk;
+	struct inet_sock *issk;
+	struct socket *ssock;
+	int ret, err;
+
+	err = ip_setsockopt(sk, SOL_IP, optname, optval, optlen);
+	if (err != 0)
+		return err;
+
+	lock_sock(sk);
+
+	ssock = __mptcp_nmpc_socket(msk);
+	if (!ssock) {
+		release_sock(sk);
+		return -EINVAL;
+	}
+
+	issk = inet_sk(ssock->sk);
+
+	switch (optname) {
+	case IP_FREEBIND:
+		issk->freebind = inet_sk(sk)->freebind;
+		break;
+	case IP_TRANSPARENT:
+		issk->transparent = inet_sk(sk)->transparent;
+		break;
+	default:
+		release_sock(sk);
+		WARN_ON_ONCE(1);
+		return -EOPNOTSUPP;
+	}
+
+	sockopt_seq_inc(msk);
+	release_sock(sk);
+	return ret;
+}
+
 static int mptcp_setsockopt_v4_set_tos(struct mptcp_sock *msk, int optname,
 				       sockptr_t optval, unsigned int optlen)
 {
@@ -627,6 +685,9 @@ static int mptcp_setsockopt_v4(struct mptcp_sock *msk, int optname,
 			       sockptr_t optval, unsigned int optlen)
 {
 	switch (optname) {
+	case IP_FREEBIND:
+	case IP_TRANSPARENT:
+		return mptcp_setsockopt_sol_ip_set_transparent(msk, optname, optval, optlen);
 	case IP_TOS:
 		return mptcp_setsockopt_v4_set_tos(msk, optname, optval, optlen);
 	}
@@ -1068,6 +1129,9 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
 
 	if (inet_csk(sk)->icsk_ca_ops != inet_csk(ssk)->icsk_ca_ops)
 		tcp_set_congestion_control(ssk, msk->ca_name, false, true);
+
+	inet_sk(ssk)->transparent = inet_sk(sk)->transparent;
+	inet_sk(ssk)->freebind = inet_sk(sk)->freebind;
 }
 
 static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
index 6172f380dfb7..72ccbd85941b 100644
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1425,6 +1425,8 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
 	if (addr.ss_family == AF_INET6)
 		addrlen = sizeof(struct sockaddr_in6);
 #endif
+	mptcp_sockopt_sync(msk, ssk);
+
 	ssk->sk_bound_dev_if = ifindex;
 	err = kernel_bind(sf, (struct sockaddr *)&addr, addrlen);
 	if (err)
@@ -1441,7 +1443,6 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
 	mptcp_info2sockaddr(remote, &addr, ssk->sk_family);
 
 	mptcp_add_pending_subflow(msk, subflow);
-	mptcp_sockopt_sync(msk, ssk);
 	err = kernel_connect(sf, (struct sockaddr *)&addr, addrlen, O_NONBLOCK);
 	if (err && err != -EINPROGRESS)
 		goto failed_unlink;
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH mptcp-next v3 2/2] selftests: mptcp: add tproxy test case
  2021-10-29 11:09 [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt Florian Westphal
  2021-10-29 11:09 ` [PATCH mptcp-next v3 1/2] mptcp: sockopt: add SOL_IP freebind & transparent options Florian Westphal
@ 2021-10-29 11:09 ` Florian Westphal
  2021-10-29 20:15 ` [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt Mat Martineau
  2021-11-02  9:44 ` Matthieu Baerts
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2021-10-29 11:09 UTC (permalink / raw)
  To: mptcp; +Cc: Florian Westphal

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 <fw@strlen.de>
---
 tools/testing/selftests/net/mptcp/config      |  8 +-
 .../selftests/net/mptcp/mptcp_connect.c       | 51 +++++++++++-
 .../selftests/net/mptcp/mptcp_connect.sh      | 80 +++++++++++++++++++
 3 files changed, 136 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/net/mptcp/config b/tools/testing/selftests/net/mptcp/config
index 0faaccd21447..419e71560fd1 100644
--- a/tools/testing/selftests/net/mptcp/config
+++ b/tools/testing/selftests/net/mptcp/config
@@ -13,5 +13,9 @@ 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
+CONFIG_IPV6_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..a4226b608c68 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, could not load nft ruleset"
+		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, ip $r6flag rule failed"
+		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, ip route add local $local_addr failed"
+		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, mptcp connection error" 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
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt
  2021-10-29 11:09 [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt Florian Westphal
  2021-10-29 11:09 ` [PATCH mptcp-next v3 1/2] mptcp: sockopt: add SOL_IP freebind & transparent options Florian Westphal
  2021-10-29 11:09 ` [PATCH mptcp-next v3 2/2] selftests: mptcp: add tproxy test case Florian Westphal
@ 2021-10-29 20:15 ` Mat Martineau
  2021-11-02  9:44 ` Matthieu Baerts
  3 siblings, 0 replies; 5+ messages in thread
From: Mat Martineau @ 2021-10-29 20:15 UTC (permalink / raw)
  To: Florian Westphal; +Cc: mptcp

On Fri, 29 Oct 2021, Florian Westphal wrote:

> First patch adds ipv4/ipv6 TRANSPARENT and FREEBIND, second
> patch adds a selftest to mptcp_connect.sh.
>
> Only change is in patch 2 which has more verbose SKIP messages
> and an updated mptcp/config to account for IPV6_MULTIPLE_TABLES
> and other toggles required for the tproxy test case.
>
> Florian Westphal (2):
>  mptcp: sockopt: add SOL_IP freebind & transparent options
>  selftests: mptcp: add tproxy test case
>
> net/mptcp/sockopt.c                           | 66 ++++++++++++++-
> net/mptcp/subflow.c                           |  3 +-
> .../selftests/net/mptcp/config                |  7 ++-
> .../selftests/net/mptcp/mptcp_connect.c       | 51 +++++++++++-
> .../selftests/net/mptcp/mptcp_connect.sh      | 80 +++++++++++++++++++
> 5 files changed, 202 insertions(+), 5 deletions(-)
> -- 
> 2.32.0

Looks good to me, thanks for tracking down the missing config.

It seemed a little odd at first that sync_socket_options() copies the 
transparent/freebind values without considering whether the protocol (v4 
or v6) used in the setsockopt matches the subflow being synced, but the IP 
code doesn't really care for historical reasons. Looks like ipv6 used to 
just use the SOL_IP options for these anyway, until someone noticed it 
didn't work on AF_INET6 SOCK_RAW sockets.

Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>

--
Mat Martineau
Intel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt
  2021-10-29 11:09 [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt Florian Westphal
                   ` (2 preceding siblings ...)
  2021-10-29 20:15 ` [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt Mat Martineau
@ 2021-11-02  9:44 ` Matthieu Baerts
  3 siblings, 0 replies; 5+ messages in thread
From: Matthieu Baerts @ 2021-11-02  9:44 UTC (permalink / raw)
  To: Florian Westphal, Mat Martineau; +Cc: mptcp

Hi Florian, Mat,

On 29/10/2021 13:09, Florian Westphal wrote:
> First patch adds ipv4/ipv6 TRANSPARENT and FREEBIND, second
> patch adds a selftest to mptcp_connect.sh.
> 
> Only change is in patch 2 which has more verbose SKIP messages
> and an updated mptcp/config to account for IPV6_MULTIPLE_TABLES
> and other toggles required for the tproxy test case.

Thank you for these patches and reviews!

Applied in our tree (features for net-next) with Mat's RvB tags:

- 509d313fffc4: mptcp: sockopt: add SOL_IP freebind & transparent options
- fe37d7b3122b: selftests: mptcp: add tproxy test case
- Results: d271a2e8d559..4538021f6a78

Builds and tests are now in progress:

https://cirrus-ci.com/github/multipath-tcp/mptcp_net-next/export/20211102T094419
https://github.com/multipath-tcp/mptcp_net-next/actions/workflows/build-validation.yml?query=branch:export

Cheers,
Matt
-- 
Tessares | Belgium | Hybrid Access Solutions
www.tessares.net

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-11-02  9:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-29 11:09 [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt Florian Westphal
2021-10-29 11:09 ` [PATCH mptcp-next v3 1/2] mptcp: sockopt: add SOL_IP freebind & transparent options Florian Westphal
2021-10-29 11:09 ` [PATCH mptcp-next v3 2/2] selftests: mptcp: add tproxy test case Florian Westphal
2021-10-29 20:15 ` [PATCH mptcp-next v3 0/2] mptcp: add freebind & transparent sockopt Mat Martineau
2021-11-02  9:44 ` Matthieu Baerts

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.