1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include <network_helpers.h>
4
test_xdp_update_frags(void)5 static void test_xdp_update_frags(void)
6 {
7 const char *file = "./test_xdp_update_frags.bpf.o";
8 int err, prog_fd, max_skb_frags, buf_size, num;
9 struct bpf_program *prog;
10 struct bpf_object *obj;
11 __u32 *offset;
12 __u8 *buf;
13 FILE *f;
14 LIBBPF_OPTS(bpf_test_run_opts, topts);
15
16 obj = bpf_object__open(file);
17 if (libbpf_get_error(obj))
18 return;
19
20 prog = bpf_object__next_program(obj, NULL);
21 if (bpf_object__load(obj))
22 return;
23
24 prog_fd = bpf_program__fd(prog);
25
26 buf = malloc(128);
27 if (!ASSERT_OK_PTR(buf, "alloc buf 128b"))
28 goto out;
29
30 memset(buf, 0, 128);
31 offset = (__u32 *)buf;
32 *offset = 16;
33 buf[*offset] = 0xaa; /* marker at offset 16 (head) */
34 buf[*offset + 15] = 0xaa; /* marker at offset 31 (head) */
35
36 topts.data_in = buf;
37 topts.data_out = buf;
38 topts.data_size_in = 128;
39 topts.data_size_out = 128;
40
41 err = bpf_prog_test_run_opts(prog_fd, &topts);
42
43 /* test_xdp_update_frags: buf[16,31]: 0xaa -> 0xbb */
44 ASSERT_OK(err, "xdp_update_frag");
45 ASSERT_EQ(topts.retval, XDP_PASS, "xdp_update_frag retval");
46 ASSERT_EQ(buf[16], 0xbb, "xdp_update_frag buf[16]");
47 ASSERT_EQ(buf[31], 0xbb, "xdp_update_frag buf[31]");
48
49 free(buf);
50
51 buf = malloc(9000);
52 if (!ASSERT_OK_PTR(buf, "alloc buf 9Kb"))
53 goto out;
54
55 memset(buf, 0, 9000);
56 offset = (__u32 *)buf;
57 *offset = 5000;
58 buf[*offset] = 0xaa; /* marker at offset 5000 (frag0) */
59 buf[*offset + 15] = 0xaa; /* marker at offset 5015 (frag0) */
60
61 topts.data_in = buf;
62 topts.data_out = buf;
63 topts.data_size_in = 9000;
64 topts.data_size_out = 9000;
65
66 err = bpf_prog_test_run_opts(prog_fd, &topts);
67
68 /* test_xdp_update_frags: buf[5000,5015]: 0xaa -> 0xbb */
69 ASSERT_OK(err, "xdp_update_frag");
70 ASSERT_EQ(topts.retval, XDP_PASS, "xdp_update_frag retval");
71 ASSERT_EQ(buf[5000], 0xbb, "xdp_update_frag buf[5000]");
72 ASSERT_EQ(buf[5015], 0xbb, "xdp_update_frag buf[5015]");
73
74 memset(buf, 0, 9000);
75 offset = (__u32 *)buf;
76 *offset = 3510;
77 buf[*offset] = 0xaa; /* marker at offset 3510 (head) */
78 buf[*offset + 15] = 0xaa; /* marker at offset 3525 (frag0) */
79
80 err = bpf_prog_test_run_opts(prog_fd, &topts);
81
82 /* test_xdp_update_frags: buf[3510,3525]: 0xaa -> 0xbb */
83 ASSERT_OK(err, "xdp_update_frag");
84 ASSERT_EQ(topts.retval, XDP_PASS, "xdp_update_frag retval");
85 ASSERT_EQ(buf[3510], 0xbb, "xdp_update_frag buf[3510]");
86 ASSERT_EQ(buf[3525], 0xbb, "xdp_update_frag buf[3525]");
87
88 memset(buf, 0, 9000);
89 offset = (__u32 *)buf;
90 *offset = 7606;
91 buf[*offset] = 0xaa; /* marker at offset 7606 (frag0) */
92 buf[*offset + 15] = 0xaa; /* marker at offset 7621 (frag1) */
93
94 err = bpf_prog_test_run_opts(prog_fd, &topts);
95
96 /* test_xdp_update_frags: buf[7606,7621]: 0xaa -> 0xbb */
97 ASSERT_OK(err, "xdp_update_frag");
98 ASSERT_EQ(topts.retval, XDP_PASS, "xdp_update_frag retval");
99 ASSERT_EQ(buf[7606], 0xbb, "xdp_update_frag buf[7606]");
100 ASSERT_EQ(buf[7621], 0xbb, "xdp_update_frag buf[7621]");
101
102 free(buf);
103
104 /* test_xdp_update_frags: unsupported buffer size */
105 f = fopen("/proc/sys/net/core/max_skb_frags", "r");
106 if (!ASSERT_OK_PTR(f, "max_skb_frag file pointer"))
107 goto out;
108
109 num = fscanf(f, "%d", &max_skb_frags);
110 fclose(f);
111
112 if (!ASSERT_EQ(num, 1, "max_skb_frags read failed"))
113 goto out;
114
115 /* xdp_buff linear area size is always set to 4096 in the
116 * bpf_prog_test_run_xdp routine.
117 */
118 buf_size = 4096 + (max_skb_frags + 1) * sysconf(_SC_PAGE_SIZE);
119 buf = malloc(buf_size);
120 if (!ASSERT_OK_PTR(buf, "alloc buf"))
121 goto out;
122
123 memset(buf, 0, buf_size);
124 offset = (__u32 *)buf;
125 *offset = 16;
126 buf[*offset] = 0xaa;
127 buf[*offset + 15] = 0xaa;
128
129 topts.data_in = buf;
130 topts.data_out = buf;
131 topts.data_size_in = buf_size;
132 topts.data_size_out = buf_size;
133
134 err = bpf_prog_test_run_opts(prog_fd, &topts);
135 ASSERT_EQ(err, -ENOMEM,
136 "unsupported buf size, possible non-default /proc/sys/net/core/max_skb_flags?");
137 free(buf);
138 out:
139 bpf_object__close(obj);
140 }
141
test_xdp_adjust_frags(void)142 void test_xdp_adjust_frags(void)
143 {
144 if (test__start_subtest("xdp_adjust_frags"))
145 test_xdp_update_frags();
146 }
147