selftests: fcnal: Test SO_DONTROUTE socket option.
Subsystems (3)
cover selftests: fcnal: Test SO_DONTROUTE socket option.
The objective is to cover kernel paths that use the RTO_ONLINK flag in .flowi4_tos. This way we'll be able to safely remove this flag in the future by properly setting .flowi4_scope instead. With these selftests in place, we can make sure this won't introduce regressions.
For more context, the final objective is to convert .flowi4_tos to dscp_t, to ensure that ECN bits don't influence route and fib-rule lookups (see commit a410a0cf9885 ("ipv6: Define dscp_t and stop taking ECN bits into account in fib6-rules")).
These selftests only cover IPv4, as SO_DONTROUTE has no effect on IPv6 sockets.
Guillaume Nault (4):
selftests: Add SO_DONTROUTE option to nettest.
selftests: fcnal: Test SO_DONTROUTE on TCP sockets.
selftests: fcnal: Test SO_DONTROUTE on UDP sockets.
selftests: fcnal: Test SO_DONTROUTE on raw and ping sockets.
tools/testing/selftests/net/fcnal-test.sh | 105 ++++++++++++++++++++++ tools/testing/selftests/net/nettest.c | 32 ++++++- 2 files changed, 135 insertions(+), 2 deletions(-)
Signature · 1 line
2.30.2
PATCH 1/4 selftests: Add SO_DONTROUTE option to nettest.
Add -G option to nettest. It allows to set the SO_DONTROUTE option to the created sockets. This will be used by the following patches to test the SO_DONTROUTE behaviour with TCP and UDP.
--- tools/testing/selftests/net/nettest.c | 32 +++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-)
tools/testing/selftests/net/nettest.c +30 -2
@@ -76,7 +76,8 @@ struct sock_args { has_grp:1, has_expected_laddr:1, has_expected_raddr:1, - bind_test_only:1; + bind_test_only:1, + dontroute:1;unsigned short port;
@@ -611,6 +612,18 @@ static int set_dsfield(int sd, int version, int dsfield)return 0 ; } +static int set_dontroute (int sd) +{ +unsigned int one =1 ; + +if (setsockopt (sd,SOL_SOCKET ,SO_DONTROUTE , &one,sizeof (one)) <0 ) { +log_err_errno ("setsockopt(SO_DONTROUTE)" ); +return -1 ; + } + +return 0 ; +} +static int str_to_uint (const char *str,int min,int max,unsigned int *value) {int number;
@@ -1351,6 +1364,9 @@ static int msock_init(struct sock_args *args, int server)if (set_dsfield (sd,AF_INET , args->dsfield) !=0 ) goto out_err; +if (args->dontroute &&set_dontroute (sd) !=0 ) + goto out_err; +if (args->dev &&bind_to_device (sd, args->dev) !=0 ) goto out_err; else if (args->use_setsockopt &&
@@ -1482,6 +1498,9 @@ static int lsock_init(struct sock_args *args)if (set_dsfield (sd, args->version, args->dsfield) !=0 ) goto err; +if (args->dontroute &&set_dontroute (sd) !=0 ) + goto err; +if (args->dev &&bind_to_device (sd, args->dev) !=0 ) goto err; else if (args->use_setsockopt &&
@@ -1698,6 +1717,9 @@ static int connectsock(void *addr, socklen_t alen, struct sock_args *args)if (set_dsfield (sd, args->version, args->dsfield) !=0 ) goto err; +if (args->dontroute &&set_dontroute (sd) !=0 ) + goto err; +if (args->dev &&bind_to_device (sd, args->dev) !=0 ) goto err; else if (args->use_setsockopt &&
@@ -1902,7 +1924,7 @@ static int ipc_parent(int cpid, int fd, struct sock_args *args)return client_status; } -#define GETOPT_STR "sr:l:c:Q:p:t:g:P:DRn:M:X:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf" +#define GETOPT_STR "sr:l:c:Q:Gp:t:g:P:DRn:M:X:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf"#define OPT_FORCE_BIND_KEY_IFINDEX 1001#define OPT_NO_BIND_KEY_IFINDEX 1002
@@ -1935,6 +1957,9 @@ static void print_usage(char *prog)" -c addr local address to bind to in client mode\n" " -Q dsfield DS Field value of the socket (the IP_TOS or\n" " IPV6_TCLASS socket option)\n" +" -G don't use gateways: send packets only if\n" +" destination is on link (see SO_DONTROUTE in\n" +" socket(7))\n" " -x configure XFRM policy on socket\n" "\n" " -d dev bind socket to given device name\n"
@@ -2020,6 +2045,9 @@ int main(int argc, char *argv[]) } args.dsfield = tmp;break ; +case 'G' : + args.dontroute =1 ; +break ;case 'p' :if (str_to_uint (optarg,1 ,65535 , &tmp) !=0 ) {fprintf (stderr,"Invalid port\n" );
Signature · 1 line
2.30.2
Re: [PATCH net-next 1/4] selftests: Add SO_DONTROUTE option to nettest.
Quoted 9 lines · Guillaume Nault
Add -G option to nettest. It allows to set the
SO_DONTROUTEoption to the created sockets. This will be used by the following patches to test theSO_DONTROUTEbehaviour with TCP and UDP.Signed-off-by Guillaume Nault <[email protected]>--- tools/testing/selftests/net/nettest.c | 32 +++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-)
PATCH 2/4 selftests: fcnal: Test SO_DONTROUTE on TCP sockets.
In reply to Guillaume NaultUse nettest -G to test the kernel behaviour with TCP sockets having the SO_DONTROUTE option. Sending packets to a neighbour (on link) host, should work. When the host is behind a router, sending should fail.
Client and server sockets are tested independently, so that we can cover different TCP kernel paths.
SO_DONTROUTE also affects the syncookies path. So ipv4_tcp_dontroute() is made to work with or without syncookies, to cover both paths.
--- tools/testing/selftests/net/fcnal-test.sh | 70 +++++++++++++++++++++++ 1 file changed, 70 insertions(+)
tools/testing/selftests/net/fcnal-test.sh +70 -0
@@ -1098,6 +1098,73 @@ test_ipv4_md5_vrf__global_server__bind_ifindex0() set_sysctl net.ipv4.tcp_l3mdev_accept="$old_tcp_l3mdev_accept" } +ipv4_tcp_dontroute() +{ + local syncookies=$1 + local nsa_syncookies + local nsb_syncookies + local a + + # + # Link local connection tests (SO_DONTROUTE). + # Connections should succeed only when the remote IP address is + # on link (doesn't need to be routed through a gateway). + # + + nsa_syncookies=$(ip netns exec "${NSA}" sysctl -n net.ipv4.tcp_syncookies) + nsb_syncookies=$(ip netns exec "${NSB}" sysctl -n net.ipv4.tcp_syncookies) + ip netns exec "${NSA}" sysctl -wq net.ipv4.tcp_syncookies=${syncookies} + ip netns exec "${NSB}" sysctl -wq net.ipv4.tcp_syncookies=${syncookies} + + # Test with eth1 address (on link). + + a=${NSB_IP} + log_start + run_cmd_nsb nettest -s & + sleep 1 + run_cmd nettest -r ${a} -G + log_test_addr ${a} $? 0 "SO_DONTROUTE client, syncookies=${syncookies}" + + a=${NSB_IP} + log_start + # Ensure previous nettest server exited, so that it won't respond (we + # really want to test the -G option on the server). + wait + run_cmd_nsb nettest -s -G & + sleep 1 + run_cmd nettest -r ${a} + log_test_addr ${a} $? 0 "SO_DONTROUTE server, syncookies=${syncookies}" + + # Test with loopback address (routed). + # + # The client would use the eth1 address as source IP by default. + # Therefore, we need to use the -c option here, to force the use of the + # routed (loopback) address as source IP (so that the server will try + # to respond to a routed address and not a link local one). + + a=${NSB_LO_IP} + log_start + show_hint "Should fail 'Network is unreachable' since server is not on link" + run_cmd_nsb nettest -s & + sleep 1 + run_cmd nettest -c ${NSA_LO_IP} -r ${a} -G + log_test_addr ${a} $? 1 "SO_DONTROUTE client, syncookies=${syncookies}" + + a=${NSB_LO_IP} + log_start + show_hint "Should timeout since server cannot respond (client is not on link)" + # Ensure previous nettest server exited, so that it won't respond (we + # really want to test the -G option on the server). + wait + run_cmd_nsb nettest -s -G & + sleep 1 + run_cmd nettest -c ${NSA_LO_IP} -r ${a} + log_test_addr ${a} $? 2 "SO_DONTROUTE server, syncookies=${syncookies}" + + ip netns exec "${NSB}" sysctl -wq net.ipv4.tcp_syncookies=${nsb_syncookies} + ip netns exec "${NSA}" sysctl -wq net.ipv4.tcp_syncookies=${nsa_syncookies} +} + ipv4_tcp_novrf() { local a
@@ -1217,6 +1284,9 @@ ipv4_tcp_novrf() log_test_addr ${a} $? 1 "No server, device client, local conn" ipv4_tcp_md5_novrf + + ipv4_tcp_dontroute 0 + ipv4_tcp_dontroute 2 } ipv4_tcp_vrf()
Signature · 1 line
2.30.2
Re: [PATCH net-next 2/4] selftests: fcnal: Test SO_DONTROUTE on TCP sockets.
Quoted 22 lines · Guillaume Nault
tools/testing/selftests/net/fcnal-test.sh +14
-0@@ -1098,6 +1098,73 @@ test_ipv4_md5_vrf__global_server__bind_ifindex0() set_sysctl net.ipv4.tcp_l3mdev_accept="$old_tcp_l3mdev_accept" } +ipv4_tcp_dontroute() +{ + local syncookies=$1 + local nsa_syncookies + local nsb_syncookies + local a + + # + # Link local connection tests (SO_DONTROUTE). + # Connections should succeed only when the remote IP address is + # on link (doesn't need to be routed through a gateway). + # + + nsa_syncookies=$(ip netns exec "${NSA}" sysctl -n net.ipv4.tcp_syncookies)
tools/testing/selftests/net/fcnal-test.sh test_ipv4_md5_vrf__global_server__bind_ifindex0() · line 1124
Quoted 10 lines
tools/testing/selftests/net/fcnal-test.sh +10
-0+ nsb_syncookies=$(ip netns exec "${NSB}" sysctl -n net.ipv4.tcp_syncookies) + ip netns exec "${NSA}" sysctl -wq net.ipv4.tcp_syncookies=${syncookies} + ip netns exec "${NSB}" sysctl -wq net.ipv4.tcp_syncookies=${syncookies} + + # Test with eth1 address (on link). + + a=${NSB_IP} + log_start + run_cmd_nsb nettest -s & + sleep 1
rather than propagate the sleep for new tests, you try adding these tests using a single nettest instance that takes both server and client arguments and does the netns switch internally.
Re: [PATCH net-next 2/4] selftests: fcnal: Test SO_DONTROUTE on TCP sockets.
Quoted 29 lines · David Ahern
Quoted 28 lines · Guillaume Nault
tools/testing/selftests/net/fcnal-test.sh +20
-0@@ -1098,6 +1098,73 @@ test_ipv4_md5_vrf__global_server__bind_ifindex0() set_sysctl net.ipv4.tcp_l3mdev_accept="$old_tcp_l3mdev_accept" } +ipv4_tcp_dontroute() +{ + local syncookies=$1 + local nsa_syncookies + local nsb_syncookies + local a + + # + # Link local connection tests (SO_DONTROUTE). + # Connections should succeed only when the remote IP address is + # on link (doesn't need to be routed through a gateway). + # + + nsa_syncookies=$(ip netns exec "${NSA}" sysctl -n net.ipv4.tcp_syncookies) + nsb_syncookies=$(ip netns exec "${NSB}" sysctl -n net.ipv4.tcp_syncookies) + ip netns exec "${NSA}" sysctl -wq net.ipv4.tcp_syncookies=${syncookies} + ip netns exec "${NSB}" sysctl -wq net.ipv4.tcp_syncookies=${syncookies} + + # Test with eth1 address (on link). +
Quoted 8 lines
tools/testing/selftests/net/fcnal-test.sh test_ipv4_md5_vrf__global_server__bind_ifindex0() · line 1124
Quoted 4 lines
tools/testing/selftests/net/fcnal-test.sh +4
-0+ a=${NSB_IP} + log_start + run_cmd_nsb nettest -s & + sleep 1rather than propagate the sleep for new tests, you try adding these tests using a single nettest instance that takes both server and client arguments and does the netns switch internally.
Okay. That also means adding more options to nettest, to independently set SO_DONTROUTE on the server or on the client. We're getting short of one letter options, so I'll probably use long ones.
PATCH 3/4 selftests: fcnal: Test SO_DONTROUTE on UDP sockets.
In reply to Guillaume NaultUse nettest -G to test the kernel behaviour with UDP sockets having the SO_DONTROUTE option. Sending packets to a neighbour (on link) host, should work. When the host is behind a router, sending should fail.
--- tools/testing/selftests/net/fcnal-test.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
tools/testing/selftests/net/fcnal-test.sh +21 -0
@@ -1655,6 +1655,27 @@ ipv4_udp_novrf() log_start run_cmd nettest -D -d ${NSA_DEV} -r ${a} log_test_addr ${a} $? 2 "No server, device client, local conn" + + # + # Link local connection tests (SO_DONTROUTE). + # Connections should succeed only when the remote IP address is + # on link (doesn't need to be routed through a gateway). + # + + a=${NSB_IP} + log_start + run_cmd_nsb nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -G + log_test_addr ${a} $? 0 "SO_DONTROUTE client" + + a=${NSB_LO_IP} + log_start + show_hint "Should fail 'Network is unreachable' since server is not on link" + run_cmd_nsb nettest -D -s & + sleep 1 + run_cmd nettest -D -r ${a} -G + log_test_addr ${a} $? 1 "SO_DONTROUTE client" } ipv4_udp_vrf()
Signature · 1 line
2.30.2
PATCH 4/4 selftests: fcnal: Test SO_DONTROUTE on raw and ping sockets.
In reply to Guillaume NaultUse ping -r to test the kernel behaviour with raw and ping sockets having the SO_DONTROUTE option.
Since ipv4_ping_novrf() is called with different values of net.ipv4.ping_group_range, then it tests both raw and ping sockets (ping uses ping sockets if its user ID belongs to ping_group_range and raw sockets otherwise).
With both socket types, sending packets to a neighbour (on link) host, should work. When the host is behind a router, sending should fail.
--- tools/testing/selftests/net/fcnal-test.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
tools/testing/selftests/net/fcnal-test.sh +14 -0
@@ -584,6 +584,20 @@ ipv4_ping_novrf() log_test_addr ${a} $? 0 "ping out, address bind" done + # + # out, but don't use gateway if peer is not on link + # + a=${NSB_IP} + log_start + run_cmd ping -c 1 -w 1 -r ${a} + log_test_addr ${a} $? 0 "ping out (don't route), peer on link" + + a=${NSB_LO_IP} + log_start + show_hint "Fails since peer is not on link" + run_cmd ping -c 1 -w 1 -r ${a} + log_test_addr ${a} $? 1 "ping out (don't route), peer not on link" + # # in #
Signature · 1 line
2.30.2