Skip to content

Commit 9ee0c7b

Browse files
Cong Wangborkmann
authored andcommitted
selftests/bpf: Add a BPF selftest for bpf_skb_change_tail()
As requested by Daniel, we need to add a selftest to cover bpf_skb_change_tail() cases in skb_verdict. Here we test trimming, growing and error cases, and validate its expected return values and the expected sizes of the payload. Signed-off-by: Cong Wang <cong.wang@bytedance.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20241213034057.246437-3-xiyou.wangcong@gmail.com
1 parent 9ecc4d8 commit 9ee0c7b

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "test_sockmap_progs_query.skel.h"
1313
#include "test_sockmap_pass_prog.skel.h"
1414
#include "test_sockmap_drop_prog.skel.h"
15+
#include "test_sockmap_change_tail.skel.h"
1516
#include "bpf_iter_sockmap.skel.h"
1617

1718
#include "sockmap_helpers.h"
@@ -643,6 +644,54 @@ static void test_sockmap_skb_verdict_fionread(bool pass_prog)
643644
test_sockmap_drop_prog__destroy(drop);
644645
}
645646

647+
static void test_sockmap_skb_verdict_change_tail(void)
648+
{
649+
struct test_sockmap_change_tail *skel;
650+
int err, map, verdict;
651+
int c1, p1, sent, recvd;
652+
int zero = 0;
653+
char buf[2];
654+
655+
skel = test_sockmap_change_tail__open_and_load();
656+
if (!ASSERT_OK_PTR(skel, "open_and_load"))
657+
return;
658+
verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
659+
map = bpf_map__fd(skel->maps.sock_map_rx);
660+
661+
err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0);
662+
if (!ASSERT_OK(err, "bpf_prog_attach"))
663+
goto out;
664+
err = create_pair(AF_INET, SOCK_STREAM, &c1, &p1);
665+
if (!ASSERT_OK(err, "create_pair()"))
666+
goto out;
667+
err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
668+
if (!ASSERT_OK(err, "bpf_map_update_elem(c1)"))
669+
goto out_close;
670+
sent = xsend(p1, "Tr", 2, 0);
671+
ASSERT_EQ(sent, 2, "xsend(p1)");
672+
recvd = recv(c1, buf, 2, 0);
673+
ASSERT_EQ(recvd, 1, "recv(c1)");
674+
ASSERT_EQ(skel->data->change_tail_ret, 0, "change_tail_ret");
675+
676+
sent = xsend(p1, "G", 1, 0);
677+
ASSERT_EQ(sent, 1, "xsend(p1)");
678+
recvd = recv(c1, buf, 2, 0);
679+
ASSERT_EQ(recvd, 2, "recv(c1)");
680+
ASSERT_EQ(skel->data->change_tail_ret, 0, "change_tail_ret");
681+
682+
sent = xsend(p1, "E", 1, 0);
683+
ASSERT_EQ(sent, 1, "xsend(p1)");
684+
recvd = recv(c1, buf, 1, 0);
685+
ASSERT_EQ(recvd, 1, "recv(c1)");
686+
ASSERT_EQ(skel->data->change_tail_ret, -EINVAL, "change_tail_ret");
687+
688+
out_close:
689+
close(c1);
690+
close(p1);
691+
out:
692+
test_sockmap_change_tail__destroy(skel);
693+
}
694+
646695
static void test_sockmap_skb_verdict_peek_helper(int map)
647696
{
648697
int err, c1, p1, zero = 0, sent, recvd, avail;
@@ -1058,6 +1107,8 @@ void test_sockmap_basic(void)
10581107
test_sockmap_skb_verdict_fionread(true);
10591108
if (test__start_subtest("sockmap skb_verdict fionread on drop"))
10601109
test_sockmap_skb_verdict_fionread(false);
1110+
if (test__start_subtest("sockmap skb_verdict change tail"))
1111+
test_sockmap_skb_verdict_change_tail();
10611112
if (test__start_subtest("sockmap skb_verdict msg_f_peek"))
10621113
test_sockmap_skb_verdict_peek();
10631114
if (test__start_subtest("sockmap skb_verdict msg_f_peek with link"))
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2024 ByteDance */
3+
#include <linux/bpf.h>
4+
#include <bpf/bpf_helpers.h>
5+
6+
struct {
7+
__uint(type, BPF_MAP_TYPE_SOCKMAP);
8+
__uint(max_entries, 1);
9+
__type(key, int);
10+
__type(value, int);
11+
} sock_map_rx SEC(".maps");
12+
13+
long change_tail_ret = 1;
14+
15+
SEC("sk_skb")
16+
int prog_skb_verdict(struct __sk_buff *skb)
17+
{
18+
char *data, *data_end;
19+
20+
bpf_skb_pull_data(skb, 1);
21+
data = (char *)(unsigned long)skb->data;
22+
data_end = (char *)(unsigned long)skb->data_end;
23+
24+
if (data + 1 > data_end)
25+
return SK_PASS;
26+
27+
if (data[0] == 'T') { /* Trim the packet */
28+
change_tail_ret = bpf_skb_change_tail(skb, skb->len - 1, 0);
29+
return SK_PASS;
30+
} else if (data[0] == 'G') { /* Grow the packet */
31+
change_tail_ret = bpf_skb_change_tail(skb, skb->len + 1, 0);
32+
return SK_PASS;
33+
} else if (data[0] == 'E') { /* Error */
34+
change_tail_ret = bpf_skb_change_tail(skb, 65535, 0);
35+
return SK_PASS;
36+
}
37+
return SK_PASS;
38+
}
39+
40+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)