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