Skip to content

Commit 463bac5

Browse files
jrfastabAlexei Starovoitov
authored andcommitted
bpf, selftests: Add test for ktls with skb bpf ingress policy
This adds a test for bpf ingress policy. To ensure data writes happen as expected with extra TLS headers we run these tests with data verification enabled by default. This will test receive packets have "PASS" stamped into the front of the payload. Signed-off-by: John Fastabend <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/159079363965.5745.3390806911628980210.stgit@john-Precision-5820-Tower Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent e91de6a commit 463bac5

File tree

2 files changed

+187
-22
lines changed

2 files changed

+187
-22
lines changed

tools/testing/selftests/bpf/progs/test_sockmap_kern.h

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,18 @@ struct {
7979

8080
struct {
8181
__uint(type, BPF_MAP_TYPE_ARRAY);
82-
__uint(max_entries, 1);
82+
__uint(max_entries, 2);
8383
__type(key, int);
8484
__type(value, int);
8585
} sock_skb_opts SEC(".maps");
8686

87+
struct {
88+
__uint(type, TEST_MAP_TYPE);
89+
__uint(max_entries, 20);
90+
__uint(key_size, sizeof(int));
91+
__uint(value_size, sizeof(int));
92+
} tls_sock_map SEC(".maps");
93+
8794
SEC("sk_skb1")
8895
int bpf_prog1(struct __sk_buff *skb)
8996
{
@@ -118,6 +125,43 @@ int bpf_prog2(struct __sk_buff *skb)
118125

119126
}
120127

128+
SEC("sk_skb3")
129+
int bpf_prog3(struct __sk_buff *skb)
130+
{
131+
const int one = 1;
132+
int err, *f, ret = SK_PASS;
133+
void *data_end;
134+
char *c;
135+
136+
err = bpf_skb_pull_data(skb, 19);
137+
if (err)
138+
goto tls_out;
139+
140+
c = (char *)(long)skb->data;
141+
data_end = (void *)(long)skb->data_end;
142+
143+
if (c + 18 < data_end)
144+
memcpy(&c[13], "PASS", 4);
145+
f = bpf_map_lookup_elem(&sock_skb_opts, &one);
146+
if (f && *f) {
147+
__u64 flags = 0;
148+
149+
ret = 0;
150+
flags = *f;
151+
#ifdef SOCKMAP
152+
return bpf_sk_redirect_map(skb, &tls_sock_map, ret, flags);
153+
#else
154+
return bpf_sk_redirect_hash(skb, &tls_sock_map, &ret, flags);
155+
#endif
156+
}
157+
158+
f = bpf_map_lookup_elem(&sock_skb_opts, &one);
159+
if (f && *f)
160+
ret = SK_DROP;
161+
tls_out:
162+
return ret;
163+
}
164+
121165
SEC("sockops")
122166
int bpf_sockmap(struct bpf_sock_ops *skops)
123167
{

tools/testing/selftests/bpf/test_sockmap.c

Lines changed: 142 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ int s1, s2, c1, c2, p1, p2;
6363
int test_cnt;
6464
int passed;
6565
int failed;
66-
int map_fd[8];
67-
struct bpf_map *maps[8];
66+
int map_fd[9];
67+
struct bpf_map *maps[9];
6868
int prog_fd[11];
6969

7070
int txmsg_pass;
@@ -79,7 +79,10 @@ int txmsg_end_push;
7979
int txmsg_start_pop;
8080
int txmsg_pop;
8181
int txmsg_ingress;
82-
int txmsg_skb;
82+
int txmsg_redir_skb;
83+
int txmsg_ktls_skb;
84+
int txmsg_ktls_skb_drop;
85+
int txmsg_ktls_skb_redir;
8386
int ktls;
8487
int peek_flag;
8588

@@ -104,7 +107,7 @@ static const struct option long_options[] = {
104107
{"txmsg_start_pop", required_argument, NULL, 'w'},
105108
{"txmsg_pop", required_argument, NULL, 'x'},
106109
{"txmsg_ingress", no_argument, &txmsg_ingress, 1 },
107-
{"txmsg_skb", no_argument, &txmsg_skb, 1 },
110+
{"txmsg_redir_skb", no_argument, &txmsg_redir_skb, 1 },
108111
{"ktls", no_argument, &ktls, 1 },
109112
{"peek", no_argument, &peek_flag, 1 },
110113
{"whitelist", required_argument, NULL, 'n' },
@@ -169,7 +172,8 @@ static void test_reset(void)
169172
txmsg_start_push = txmsg_end_push = 0;
170173
txmsg_pass = txmsg_drop = txmsg_redir = 0;
171174
txmsg_apply = txmsg_cork = 0;
172-
txmsg_ingress = txmsg_skb = 0;
175+
txmsg_ingress = txmsg_redir_skb = 0;
176+
txmsg_ktls_skb = txmsg_ktls_skb_drop = txmsg_ktls_skb_redir = 0;
173177
}
174178

175179
static int test_start_subtest(const struct _test *t, struct sockmap_options *o)
@@ -502,14 +506,41 @@ static int msg_alloc_iov(struct msghdr *msg,
502506

503507
static int msg_verify_data(struct msghdr *msg, int size, int chunk_sz)
504508
{
505-
int i, j, bytes_cnt = 0;
509+
int i, j = 0, bytes_cnt = 0;
506510
unsigned char k = 0;
507511

508512
for (i = 0; i < msg->msg_iovlen; i++) {
509513
unsigned char *d = msg->msg_iov[i].iov_base;
510514

511-
for (j = 0;
512-
j < msg->msg_iov[i].iov_len && size; j++) {
515+
/* Special case test for skb ingress + ktls */
516+
if (i == 0 && txmsg_ktls_skb) {
517+
if (msg->msg_iov[i].iov_len < 4)
518+
return -EIO;
519+
if (txmsg_ktls_skb_redir) {
520+
if (memcmp(&d[13], "PASS", 4) != 0) {
521+
fprintf(stderr,
522+
"detected redirect ktls_skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n", i, 0, d[13], d[14], d[15], d[16]);
523+
return -EIO;
524+
}
525+
d[13] = 0;
526+
d[14] = 1;
527+
d[15] = 2;
528+
d[16] = 3;
529+
j = 13;
530+
} else if (txmsg_ktls_skb) {
531+
if (memcmp(d, "PASS", 4) != 0) {
532+
fprintf(stderr,
533+
"detected ktls_skb data error with skb ingress update @iov[%i]:%i \"%02x %02x %02x %02x\" != \"PASS\"\n", i, 0, d[0], d[1], d[2], d[3]);
534+
return -EIO;
535+
}
536+
d[0] = 0;
537+
d[1] = 1;
538+
d[2] = 2;
539+
d[3] = 3;
540+
}
541+
}
542+
543+
for (; j < msg->msg_iov[i].iov_len && size; j++) {
513544
if (d[j] != k++) {
514545
fprintf(stderr,
515546
"detected data corruption @iov[%i]:%i %02x != %02x, %02x ?= %02x\n",
@@ -724,7 +755,7 @@ static int sendmsg_test(struct sockmap_options *opt)
724755
rxpid = fork();
725756
if (rxpid == 0) {
726757
iov_buf -= (txmsg_pop - txmsg_start_pop + 1);
727-
if (opt->drop_expected)
758+
if (opt->drop_expected || txmsg_ktls_skb_drop)
728759
_exit(0);
729760

730761
if (!iov_buf) /* zero bytes sent case */
@@ -911,8 +942,28 @@ static int run_options(struct sockmap_options *options, int cg_fd, int test)
911942
return err;
912943
}
913944

945+
/* Attach programs to TLS sockmap */
946+
if (txmsg_ktls_skb) {
947+
err = bpf_prog_attach(prog_fd[0], map_fd[8],
948+
BPF_SK_SKB_STREAM_PARSER, 0);
949+
if (err) {
950+
fprintf(stderr,
951+
"ERROR: bpf_prog_attach (TLS sockmap %i->%i): %d (%s)\n",
952+
prog_fd[0], map_fd[8], err, strerror(errno));
953+
return err;
954+
}
955+
956+
err = bpf_prog_attach(prog_fd[2], map_fd[8],
957+
BPF_SK_SKB_STREAM_VERDICT, 0);
958+
if (err) {
959+
fprintf(stderr, "ERROR: bpf_prog_attach (TLS sockmap): %d (%s)\n",
960+
err, strerror(errno));
961+
return err;
962+
}
963+
}
964+
914965
/* Attach to cgroups */
915-
err = bpf_prog_attach(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS, 0);
966+
err = bpf_prog_attach(prog_fd[3], cg_fd, BPF_CGROUP_SOCK_OPS, 0);
916967
if (err) {
917968
fprintf(stderr, "ERROR: bpf_prog_attach (groups): %d (%s)\n",
918969
err, strerror(errno));
@@ -928,15 +979,15 @@ static int run_options(struct sockmap_options *options, int cg_fd, int test)
928979

929980
/* Attach txmsg program to sockmap */
930981
if (txmsg_pass)
931-
tx_prog_fd = prog_fd[3];
932-
else if (txmsg_redir)
933982
tx_prog_fd = prog_fd[4];
934-
else if (txmsg_apply)
983+
else if (txmsg_redir)
935984
tx_prog_fd = prog_fd[5];
936-
else if (txmsg_cork)
985+
else if (txmsg_apply)
937986
tx_prog_fd = prog_fd[6];
938-
else if (txmsg_drop)
987+
else if (txmsg_cork)
939988
tx_prog_fd = prog_fd[7];
989+
else if (txmsg_drop)
990+
tx_prog_fd = prog_fd[8];
940991
else
941992
tx_prog_fd = 0;
942993

@@ -1108,7 +1159,35 @@ static int run_options(struct sockmap_options *options, int cg_fd, int test)
11081159
}
11091160
}
11101161

1111-
if (txmsg_skb) {
1162+
if (txmsg_ktls_skb) {
1163+
int ingress = BPF_F_INGRESS;
1164+
1165+
i = 0;
1166+
err = bpf_map_update_elem(map_fd[8], &i, &p2, BPF_ANY);
1167+
if (err) {
1168+
fprintf(stderr,
1169+
"ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
1170+
err, strerror(errno));
1171+
}
1172+
1173+
if (txmsg_ktls_skb_redir) {
1174+
i = 1;
1175+
err = bpf_map_update_elem(map_fd[7],
1176+
&i, &ingress, BPF_ANY);
1177+
if (err) {
1178+
fprintf(stderr,
1179+
"ERROR: bpf_map_update_elem (txmsg_ingress): %d (%s)\n",
1180+
err, strerror(errno));
1181+
}
1182+
}
1183+
1184+
if (txmsg_ktls_skb_drop) {
1185+
i = 1;
1186+
err = bpf_map_update_elem(map_fd[7], &i, &i, BPF_ANY);
1187+
}
1188+
}
1189+
1190+
if (txmsg_redir_skb) {
11121191
int skb_fd = (test == SENDMSG || test == SENDPAGE) ?
11131192
p2 : p1;
11141193
int ingress = BPF_F_INGRESS;
@@ -1123,8 +1202,7 @@ static int run_options(struct sockmap_options *options, int cg_fd, int test)
11231202
}
11241203

11251204
i = 3;
1126-
err = bpf_map_update_elem(map_fd[0],
1127-
&i, &skb_fd, BPF_ANY);
1205+
err = bpf_map_update_elem(map_fd[0], &i, &skb_fd, BPF_ANY);
11281206
if (err) {
11291207
fprintf(stderr,
11301208
"ERROR: bpf_map_update_elem (c1 sockmap): %d (%s)\n",
@@ -1158,9 +1236,12 @@ static int run_options(struct sockmap_options *options, int cg_fd, int test)
11581236
fprintf(stderr, "unknown test\n");
11591237
out:
11601238
/* Detatch and zero all the maps */
1161-
bpf_prog_detach2(prog_fd[2], cg_fd, BPF_CGROUP_SOCK_OPS);
1239+
bpf_prog_detach2(prog_fd[3], cg_fd, BPF_CGROUP_SOCK_OPS);
11621240
bpf_prog_detach2(prog_fd[0], map_fd[0], BPF_SK_SKB_STREAM_PARSER);
11631241
bpf_prog_detach2(prog_fd[1], map_fd[0], BPF_SK_SKB_STREAM_VERDICT);
1242+
bpf_prog_detach2(prog_fd[0], map_fd[8], BPF_SK_SKB_STREAM_PARSER);
1243+
bpf_prog_detach2(prog_fd[2], map_fd[8], BPF_SK_SKB_STREAM_VERDICT);
1244+
11641245
if (tx_prog_fd >= 0)
11651246
bpf_prog_detach2(tx_prog_fd, map_fd[1], BPF_SK_MSG_VERDICT);
11661247

@@ -1229,8 +1310,10 @@ static void test_options(char *options)
12291310
}
12301311
if (txmsg_ingress)
12311312
strncat(options, "ingress,", OPTSTRING);
1232-
if (txmsg_skb)
1233-
strncat(options, "skb,", OPTSTRING);
1313+
if (txmsg_redir_skb)
1314+
strncat(options, "redir_skb,", OPTSTRING);
1315+
if (txmsg_ktls_skb)
1316+
strncat(options, "ktls_skb,", OPTSTRING);
12341317
if (ktls)
12351318
strncat(options, "ktls,", OPTSTRING);
12361319
if (peek_flag)
@@ -1362,6 +1445,40 @@ static void test_txmsg_ingress_redir(int cgrp, struct sockmap_options *opt)
13621445
test_send(opt, cgrp);
13631446
}
13641447

1448+
static void test_txmsg_skb(int cgrp, struct sockmap_options *opt)
1449+
{
1450+
bool data = opt->data_test;
1451+
int k = ktls;
1452+
1453+
opt->data_test = true;
1454+
ktls = 1;
1455+
1456+
txmsg_pass = txmsg_drop = 0;
1457+
txmsg_ingress = txmsg_redir = 0;
1458+
txmsg_ktls_skb = 1;
1459+
txmsg_pass = 1;
1460+
1461+
/* Using data verification so ensure iov layout is
1462+
* expected from test receiver side. e.g. has enough
1463+
* bytes to write test code.
1464+
*/
1465+
opt->iov_length = 100;
1466+
opt->iov_count = 1;
1467+
opt->rate = 1;
1468+
test_exec(cgrp, opt);
1469+
1470+
txmsg_ktls_skb_drop = 1;
1471+
test_exec(cgrp, opt);
1472+
1473+
txmsg_ktls_skb_drop = 0;
1474+
txmsg_ktls_skb_redir = 1;
1475+
test_exec(cgrp, opt);
1476+
1477+
opt->data_test = data;
1478+
ktls = k;
1479+
}
1480+
1481+
13651482
/* Test cork with hung data. This tests poor usage patterns where
13661483
* cork can leave data on the ring if user program is buggy and
13671484
* doesn't flush them somehow. They do take some time however
@@ -1542,11 +1659,13 @@ char *map_names[] = {
15421659
"sock_bytes",
15431660
"sock_redir_flags",
15441661
"sock_skb_opts",
1662+
"tls_sock_map",
15451663
};
15461664

15471665
int prog_attach_type[] = {
15481666
BPF_SK_SKB_STREAM_PARSER,
15491667
BPF_SK_SKB_STREAM_VERDICT,
1668+
BPF_SK_SKB_STREAM_VERDICT,
15501669
BPF_CGROUP_SOCK_OPS,
15511670
BPF_SK_MSG_VERDICT,
15521671
BPF_SK_MSG_VERDICT,
@@ -1558,6 +1677,7 @@ int prog_attach_type[] = {
15581677
};
15591678

15601679
int prog_type[] = {
1680+
BPF_PROG_TYPE_SK_SKB,
15611681
BPF_PROG_TYPE_SK_SKB,
15621682
BPF_PROG_TYPE_SK_SKB,
15631683
BPF_PROG_TYPE_SOCK_OPS,
@@ -1620,6 +1740,7 @@ struct _test test[] = {
16201740
{"txmsg test redirect", test_txmsg_redir},
16211741
{"txmsg test drop", test_txmsg_drop},
16221742
{"txmsg test ingress redirect", test_txmsg_ingress_redir},
1743+
{"txmsg test skb", test_txmsg_skb},
16231744
{"txmsg test apply", test_txmsg_apply},
16241745
{"txmsg test cork", test_txmsg_cork},
16251746
{"txmsg test hanging corks", test_txmsg_cork_hangs},

0 commit comments

Comments
 (0)