66#include <netinet/in.h>
77#include <test_progs.h>
88#include <unistd.h>
9+ #include <error.h>
910#include "cgroup_helpers.h"
1011#include "network_helpers.h"
12+ #include "socket_helpers.h"
1113#include "mptcp_sock.skel.h"
1214#include "mptcpify.skel.h"
1315#include "mptcp_subflow.skel.h"
16+ #include "mptcp_sockmap.skel.h"
1417
1518#define NS_TEST "mptcp_ns"
1619#define ADDR_1 "10.0.1.1"
@@ -436,6 +439,142 @@ static void test_subflow(void)
436439 close (cgroup_fd );
437440}
438441
442+ /* Test sockmap on MPTCP server handling non-mp-capable clients. */
443+ static void test_sockmap_with_mptcp_fallback (struct mptcp_sockmap * skel )
444+ {
445+ int listen_fd = -1 , client_fd1 = -1 , client_fd2 = -1 ;
446+ int server_fd1 = -1 , server_fd2 = -1 , sent , recvd ;
447+ char snd [9 ] = "123456789" ;
448+ char rcv [10 ];
449+
450+ /* start server with MPTCP enabled */
451+ listen_fd = start_mptcp_server (AF_INET , NULL , 0 , 0 );
452+ if (!ASSERT_OK_FD (listen_fd , "sockmap-fb:start_mptcp_server" ))
453+ return ;
454+
455+ skel -> bss -> trace_port = ntohs (get_socket_local_port (listen_fd ));
456+ skel -> bss -> sk_index = 0 ;
457+ /* create client without MPTCP enabled */
458+ client_fd1 = connect_to_fd_opts (listen_fd , NULL );
459+ if (!ASSERT_OK_FD (client_fd1 , "sockmap-fb:connect_to_fd" ))
460+ goto end ;
461+
462+ server_fd1 = xaccept_nonblock (listen_fd , NULL , NULL );
463+ skel -> bss -> sk_index = 1 ;
464+ client_fd2 = connect_to_fd_opts (listen_fd , NULL );
465+ if (!ASSERT_OK_FD (client_fd2 , "sockmap-fb:connect_to_fd" ))
466+ goto end ;
467+
468+ server_fd2 = xaccept_nonblock (listen_fd , NULL , NULL );
469+ /* test normal redirect behavior: data sent by client_fd1 can be
470+ * received by client_fd2
471+ */
472+ skel -> bss -> redirect_idx = 1 ;
473+ sent = xsend (client_fd1 , snd , sizeof (snd ), 0 );
474+ if (!ASSERT_EQ (sent , sizeof (snd ), "sockmap-fb:xsend(client_fd1)" ))
475+ goto end ;
476+
477+ /* try to recv more bytes to avoid truncation check */
478+ recvd = recv_timeout (client_fd2 , rcv , sizeof (rcv ), MSG_DONTWAIT , 2 );
479+ if (!ASSERT_EQ (recvd , sizeof (snd ), "sockmap-fb:recv(client_fd2)" ))
480+ goto end ;
481+
482+ end :
483+ if (client_fd1 >= 0 )
484+ close (client_fd1 );
485+ if (client_fd2 >= 0 )
486+ close (client_fd2 );
487+ if (server_fd1 >= 0 )
488+ close (server_fd1 );
489+ if (server_fd2 >= 0 )
490+ close (server_fd2 );
491+ close (listen_fd );
492+ }
493+
494+ /* Test sockmap rejection of MPTCP sockets - both server and client sides. */
495+ static void test_sockmap_reject_mptcp (struct mptcp_sockmap * skel )
496+ {
497+ int listen_fd = -1 , server_fd = -1 , client_fd1 = -1 ;
498+ int err , zero = 0 ;
499+
500+ /* start server with MPTCP enabled */
501+ listen_fd = start_mptcp_server (AF_INET , NULL , 0 , 0 );
502+ if (!ASSERT_OK_FD (listen_fd , "start_mptcp_server" ))
503+ return ;
504+
505+ skel -> bss -> trace_port = ntohs (get_socket_local_port (listen_fd ));
506+ skel -> bss -> sk_index = 0 ;
507+ /* create client with MPTCP enabled */
508+ client_fd1 = connect_to_fd (listen_fd , 0 );
509+ if (!ASSERT_OK_FD (client_fd1 , "connect_to_fd client_fd1" ))
510+ goto end ;
511+
512+ /* bpf_sock_map_update() called from sockops should reject MPTCP sk */
513+ if (!ASSERT_EQ (skel -> bss -> helper_ret , - EOPNOTSUPP , "should reject" ))
514+ goto end ;
515+
516+ server_fd = xaccept_nonblock (listen_fd , NULL , NULL );
517+ err = bpf_map_update_elem (bpf_map__fd (skel -> maps .sock_map ),
518+ & zero , & server_fd , BPF_NOEXIST );
519+ if (!ASSERT_EQ (err , - EOPNOTSUPP , "server should be disallowed" ))
520+ goto end ;
521+
522+ /* MPTCP client should also be disallowed */
523+ err = bpf_map_update_elem (bpf_map__fd (skel -> maps .sock_map ),
524+ & zero , & client_fd1 , BPF_NOEXIST );
525+ if (!ASSERT_EQ (err , - EOPNOTSUPP , "client should be disallowed" ))
526+ goto end ;
527+ end :
528+ if (client_fd1 >= 0 )
529+ close (client_fd1 );
530+ if (server_fd >= 0 )
531+ close (server_fd );
532+ close (listen_fd );
533+ }
534+
535+ static void test_mptcp_sockmap (void )
536+ {
537+ struct mptcp_sockmap * skel ;
538+ struct netns_obj * netns ;
539+ int cgroup_fd , err ;
540+
541+ cgroup_fd = test__join_cgroup ("/mptcp_sockmap" );
542+ if (!ASSERT_OK_FD (cgroup_fd , "join_cgroup: mptcp_sockmap" ))
543+ return ;
544+
545+ skel = mptcp_sockmap__open_and_load ();
546+ if (!ASSERT_OK_PTR (skel , "skel_open_load: mptcp_sockmap" ))
547+ goto close_cgroup ;
548+
549+ skel -> links .mptcp_sockmap_inject =
550+ bpf_program__attach_cgroup (skel -> progs .mptcp_sockmap_inject , cgroup_fd );
551+ if (!ASSERT_OK_PTR (skel -> links .mptcp_sockmap_inject , "attach sockmap" ))
552+ goto skel_destroy ;
553+
554+ err = bpf_prog_attach (bpf_program__fd (skel -> progs .mptcp_sockmap_redirect ),
555+ bpf_map__fd (skel -> maps .sock_map ),
556+ BPF_SK_SKB_STREAM_VERDICT , 0 );
557+ if (!ASSERT_OK (err , "bpf_prog_attach stream verdict" ))
558+ goto skel_destroy ;
559+
560+ netns = netns_new (NS_TEST , true);
561+ if (!ASSERT_OK_PTR (netns , "netns_new: mptcp_sockmap" ))
562+ goto skel_destroy ;
563+
564+ if (endpoint_init ("subflow" ) < 0 )
565+ goto close_netns ;
566+
567+ test_sockmap_with_mptcp_fallback (skel );
568+ test_sockmap_reject_mptcp (skel );
569+
570+ close_netns :
571+ netns_free (netns );
572+ skel_destroy :
573+ mptcp_sockmap__destroy (skel );
574+ close_cgroup :
575+ close (cgroup_fd );
576+ }
577+
439578void test_mptcp (void )
440579{
441580 if (test__start_subtest ("base" ))
@@ -444,4 +583,6 @@ void test_mptcp(void)
444583 test_mptcpify ();
445584 if (test__start_subtest ("subflow" ))
446585 test_subflow ();
586+ if (test__start_subtest ("sockmap" ))
587+ test_mptcp_sockmap ();
447588}
0 commit comments