Skip to content

Commit d4c0a8e

Browse files
mrpreKernel Patches Daemon
authored andcommitted
selftests/bpf: Add mptcp test with sockmap
Add test cases to verify that when MPTCP falls back to plain TCP sockets, they can properly work with sockmap. Additionally, add test cases to ensure that sockmap correctly rejects MPTCP sockets as expected. Signed-off-by: Jiayuan Chen <[email protected]> Acked-by: Matthieu Baerts (NGI0) <[email protected]>
1 parent a24af86 commit d4c0a8e

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed

tools/testing/selftests/bpf/prog_tests/mptcp.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
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+
439578
void 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
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include "bpf_tracing_net.h"
4+
5+
char _license[] SEC("license") = "GPL";
6+
7+
int sk_index;
8+
int redirect_idx;
9+
int trace_port;
10+
int helper_ret;
11+
struct {
12+
__uint(type, BPF_MAP_TYPE_SOCKMAP);
13+
__uint(key_size, sizeof(__u32));
14+
__uint(value_size, sizeof(__u32));
15+
__uint(max_entries, 100);
16+
} sock_map SEC(".maps");
17+
18+
SEC("sockops")
19+
int mptcp_sockmap_inject(struct bpf_sock_ops *skops)
20+
{
21+
struct bpf_sock *sk;
22+
23+
/* only accept specified connection */
24+
if (skops->local_port != trace_port ||
25+
skops->op != BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB)
26+
return 1;
27+
28+
sk = skops->sk;
29+
if (!sk)
30+
return 1;
31+
32+
/* update sk handler */
33+
helper_ret = bpf_sock_map_update(skops, &sock_map, &sk_index, BPF_NOEXIST);
34+
35+
return 1;
36+
}
37+
38+
SEC("sk_skb/stream_verdict")
39+
int mptcp_sockmap_redirect(struct __sk_buff *skb)
40+
{
41+
/* redirect skb to the sk under sock_map[redirect_idx] */
42+
return bpf_sk_redirect_map(skb, &sock_map, redirect_idx, 0);
43+
}

0 commit comments

Comments
 (0)