Skip to content

Commit a4b7193

Browse files
Xu KuohaiMartin KaFai Lau
authored andcommitted
selftests/bpf: Add sockmap test for redirecting partial skb data
Add a test case to check whether sockmap redirection works correctly when data length returned by stream_parser is less than skb->len. In addition, this test checks whether strp_done is called correctly. The reason is that we returns skb->len - 1 from the stream_parser, so the last byte in the skb will be held by strp->skb_head. Therefore, if strp_done is not called to free strp->skb_head, we'll get a memleak warning. Signed-off-by: Xu Kuohai <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Martin KaFai Lau <[email protected]>
1 parent 90f0074 commit a4b7193

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

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

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,77 @@ static void test_msg_redir_to_listening(struct test_sockmap_listen *skel,
869869
xbpf_prog_detach2(verdict, sock_map, BPF_SK_MSG_VERDICT);
870870
}
871871

872+
static void redir_partial(int family, int sotype, int sock_map, int parser_map)
873+
{
874+
int s, c0, c1, p0, p1;
875+
int err, n, key, value;
876+
char buf[] = "abc";
877+
878+
key = 0;
879+
value = sizeof(buf) - 1;
880+
err = xbpf_map_update_elem(parser_map, &key, &value, 0);
881+
if (err)
882+
return;
883+
884+
s = socket_loopback(family, sotype | SOCK_NONBLOCK);
885+
if (s < 0)
886+
goto clean_parser_map;
887+
888+
err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1);
889+
if (err)
890+
goto close_srv;
891+
892+
err = add_to_sockmap(sock_map, p0, p1);
893+
if (err)
894+
goto close;
895+
896+
n = xsend(c1, buf, sizeof(buf), 0);
897+
if (n < sizeof(buf))
898+
FAIL("incomplete write");
899+
900+
n = xrecv_nonblock(c0, buf, sizeof(buf), 0);
901+
if (n != sizeof(buf) - 1)
902+
FAIL("expect %zu, received %d", sizeof(buf) - 1, n);
903+
904+
close:
905+
xclose(c0);
906+
xclose(p0);
907+
xclose(c1);
908+
xclose(p1);
909+
close_srv:
910+
xclose(s);
911+
912+
clean_parser_map:
913+
key = 0;
914+
value = 0;
915+
xbpf_map_update_elem(parser_map, &key, &value, 0);
916+
}
917+
918+
static void test_skb_redir_partial(struct test_sockmap_listen *skel,
919+
struct bpf_map *inner_map, int family,
920+
int sotype)
921+
{
922+
int verdict = bpf_program__fd(skel->progs.prog_stream_verdict);
923+
int parser = bpf_program__fd(skel->progs.prog_stream_parser);
924+
int parser_map = bpf_map__fd(skel->maps.parser_map);
925+
int sock_map = bpf_map__fd(inner_map);
926+
int err;
927+
928+
err = xbpf_prog_attach(parser, sock_map, BPF_SK_SKB_STREAM_PARSER, 0);
929+
if (err)
930+
return;
931+
932+
err = xbpf_prog_attach(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT, 0);
933+
if (err)
934+
goto detach;
935+
936+
redir_partial(family, sotype, sock_map, parser_map);
937+
938+
xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_STREAM_VERDICT);
939+
detach:
940+
xbpf_prog_detach2(parser, sock_map, BPF_SK_SKB_STREAM_PARSER);
941+
}
942+
872943
static void test_reuseport_select_listening(int family, int sotype,
873944
int sock_map, int verd_map,
874945
int reuseport_prog)
@@ -1243,6 +1314,7 @@ static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map,
12431314
} tests[] = {
12441315
TEST(test_skb_redir_to_connected),
12451316
TEST(test_skb_redir_to_listening),
1317+
TEST(test_skb_redir_partial),
12461318
TEST(test_msg_redir_to_connected),
12471319
TEST(test_msg_redir_to_listening),
12481320
};

tools/testing/selftests/bpf/progs/test_sockmap_listen.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,26 @@ struct {
2828
__type(value, unsigned int);
2929
} verdict_map SEC(".maps");
3030

31+
struct {
32+
__uint(type, BPF_MAP_TYPE_ARRAY);
33+
__uint(max_entries, 1);
34+
__type(key, int);
35+
__type(value, int);
36+
} parser_map SEC(".maps");
37+
3138
bool test_sockmap = false; /* toggled by user-space */
3239
bool test_ingress = false; /* toggled by user-space */
3340

3441
SEC("sk_skb/stream_parser")
3542
int prog_stream_parser(struct __sk_buff *skb)
3643
{
44+
int *value;
45+
__u32 key = 0;
46+
47+
value = bpf_map_lookup_elem(&parser_map, &key);
48+
if (value && *value)
49+
return *value;
50+
3751
return skb->len;
3852
}
3953

0 commit comments

Comments
 (0)