bpf: test_sockmap, add options for msg_pop_data() helper

Similar to msg_pull_data and msg_push_data add a set of options to
have msg_pop_data() exercised.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:
John Fastabend 2018-11-26 14:16:19 -08:00 committed by Daniel Borkmann
parent d913a2273a
commit 1ade9abadf
2 changed files with 180 additions and 17 deletions

View File

@ -79,6 +79,8 @@ int txmsg_start;
int txmsg_end;
int txmsg_start_push;
int txmsg_end_push;
int txmsg_start_pop;
int txmsg_pop;
int txmsg_ingress;
int txmsg_skb;
int ktls;
@ -104,6 +106,8 @@ static const struct option long_options[] = {
{"txmsg_end", required_argument, NULL, 'e'},
{"txmsg_start_push", required_argument, NULL, 'p'},
{"txmsg_end_push", required_argument, NULL, 'q'},
{"txmsg_start_pop", required_argument, NULL, 'w'},
{"txmsg_pop", required_argument, NULL, 'x'},
{"txmsg_ingress", no_argument, &txmsg_ingress, 1 },
{"txmsg_skb", no_argument, &txmsg_skb, 1 },
{"ktls", no_argument, &ktls, 1 },
@ -473,13 +477,27 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
clock_gettime(CLOCK_MONOTONIC, &s->end);
} else {
int slct, recvp = 0, recv, max_fd = fd;
float total_bytes, txmsg_pop_total;
int fd_flags = O_NONBLOCK;
struct timeval timeout;
float total_bytes;
fd_set w;
fcntl(fd, fd_flags);
/* Account for pop bytes noting each iteration of apply will
* call msg_pop_data helper so we need to account for this
* by calculating the number of apply iterations. Note user
* of the tool can create cases where no data is sent by
* manipulating pop/push/pull/etc. For example txmsg_apply 1
* with txmsg_pop 1 will try to apply 1B at a time but each
* iteration will then pop 1B so no data will ever be sent.
* This is really only useful for testing edge cases in code
* paths.
*/
total_bytes = (float)iov_count * (float)iov_length * (float)cnt;
txmsg_pop_total = txmsg_pop;
if (txmsg_apply)
txmsg_pop_total *= (total_bytes / txmsg_apply);
total_bytes -= txmsg_pop_total;
err = clock_gettime(CLOCK_MONOTONIC, &s->start);
if (err < 0)
perror("recv start time: ");
@ -488,7 +506,7 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
timeout.tv_sec = 0;
timeout.tv_usec = 300000;
} else {
timeout.tv_sec = 1;
timeout.tv_sec = 3;
timeout.tv_usec = 0;
}
@ -503,7 +521,7 @@ static int msg_loop(int fd, int iov_count, int iov_length, int cnt,
goto out_errno;
} else if (!slct) {
if (opt->verbose)
fprintf(stderr, "unexpected timeout\n");
fprintf(stderr, "unexpected timeout: recved %zu/%f pop_total %f\n", s->bytes_recvd, total_bytes, txmsg_pop_total);
errno = -EIO;
clock_gettime(CLOCK_MONOTONIC, &s->end);
goto out_errno;
@ -619,7 +637,7 @@ static int sendmsg_test(struct sockmap_options *opt)
iov_count = 1;
err = msg_loop(rx_fd, iov_count, iov_buf,
cnt, &s, false, opt);
if (err && opt->verbose)
if (opt->verbose)
fprintf(stderr,
"msg_loop_rx: iov_count %i iov_buf %i cnt %i err %i\n",
iov_count, iov_buf, cnt, err);
@ -931,6 +949,39 @@ run:
}
}
if (txmsg_start_pop) {
i = 4;
err = bpf_map_update_elem(map_fd[5],
&i, &txmsg_start_pop, BPF_ANY);
if (err) {
fprintf(stderr,
"ERROR: bpf_map_update_elem %i@%i (txmsg_start_pop): %d (%s)\n",
txmsg_start_pop, i, err, strerror(errno));
goto out;
}
} else {
i = 4;
bpf_map_update_elem(map_fd[5],
&i, &txmsg_start_pop, BPF_ANY);
}
if (txmsg_pop) {
i = 5;
err = bpf_map_update_elem(map_fd[5],
&i, &txmsg_pop, BPF_ANY);
if (err) {
fprintf(stderr,
"ERROR: bpf_map_update_elem %i@%i (txmsg_pop): %d (%s)\n",
txmsg_pop, i, err, strerror(errno));
goto out;
}
} else {
i = 5;
bpf_map_update_elem(map_fd[5],
&i, &txmsg_pop, BPF_ANY);
}
if (txmsg_ingress) {
int in = BPF_F_INGRESS;
@ -1082,6 +1133,11 @@ static void test_options(char *options)
snprintf(tstr, OPTSTRING, "end %d,", txmsg_end);
strncat(options, tstr, OPTSTRING);
}
if (txmsg_start_pop) {
snprintf(tstr, OPTSTRING, "pop (%d,%d),",
txmsg_start_pop, txmsg_start_pop + txmsg_pop);
strncat(options, tstr, OPTSTRING);
}
if (txmsg_ingress)
strncat(options, "ingress,", OPTSTRING);
if (txmsg_skb)
@ -1264,6 +1320,7 @@ static int test_mixed(int cgrp)
txmsg_apply = txmsg_cork = 0;
txmsg_start = txmsg_end = 0;
txmsg_start_push = txmsg_end_push = 0;
txmsg_start_pop = txmsg_pop = 0;
/* Test small and large iov_count values with pass/redir/apply/cork */
txmsg_pass = 1;
@ -1383,6 +1440,19 @@ static int test_start_end(int cgrp)
txmsg_end = 2;
txmsg_start_push = 1;
txmsg_end_push = 2;
txmsg_start_pop = 1;
txmsg_pop = 1;
err = test_txmsg(cgrp);
if (err)
goto out;
/* Cut a byte of pushed data but leave reamining in place */
txmsg_start = 1;
txmsg_end = 2;
txmsg_start_push = 1;
txmsg_end_push = 3;
txmsg_start_pop = 1;
txmsg_pop = 1;
err = test_txmsg(cgrp);
if (err)
goto out;
@ -1393,6 +1463,9 @@ static int test_start_end(int cgrp)
opt.iov_length = 100;
txmsg_cork = 1600;
txmsg_start_pop = 0;
txmsg_pop = 0;
for (i = 99; i <= 1600; i += 500) {
txmsg_start = 0;
txmsg_end = i;
@ -1403,6 +1476,17 @@ static int test_start_end(int cgrp)
goto out;
}
/* Test pop data in middle of cork */
for (i = 99; i <= 1600; i += 500) {
txmsg_start_pop = 10;
txmsg_pop = i;
err = test_exec(cgrp, &opt);
if (err)
goto out;
}
txmsg_start_pop = 0;
txmsg_pop = 0;
/* Test start/end with cork but pull data in middle */
for (i = 199; i <= 1600; i += 500) {
txmsg_start = 100;
@ -1423,6 +1507,15 @@ static int test_start_end(int cgrp)
if (err)
goto out;
/* Test pop with cork pulling last sg entry */
txmsg_start_pop = 1500;
txmsg_pop = 1600;
err = test_exec(cgrp, &opt);
if (err)
goto out;
txmsg_start_pop = 0;
txmsg_pop = 0;
/* Test start/end pull of single byte in last page */
txmsg_start = 1111;
txmsg_end = 1112;
@ -1432,6 +1525,13 @@ static int test_start_end(int cgrp)
if (err)
goto out;
/* Test pop of single byte in last page */
txmsg_start_pop = 1111;
txmsg_pop = 1112;
err = test_exec(cgrp, &opt);
if (err)
goto out;
/* Test start/end with end < start */
txmsg_start = 1111;
txmsg_end = 0;
@ -1456,7 +1556,20 @@ static int test_start_end(int cgrp)
txmsg_start_push = 1601;
txmsg_end_push = 1600;
err = test_exec(cgrp, &opt);
if (err)
goto out;
/* Test pop with start > data */
txmsg_start_pop = 1601;
txmsg_pop = 1;
err = test_exec(cgrp, &opt);
if (err)
goto out;
/* Test pop with pop range > data */
txmsg_start_pop = 1599;
txmsg_pop = 10;
err = test_exec(cgrp, &opt);
out:
txmsg_start = 0;
txmsg_end = 0;
@ -1641,6 +1754,12 @@ int main(int argc, char **argv)
case 'q':
txmsg_end_push = atoi(optarg);
break;
case 'w':
txmsg_start_pop = atoi(optarg);
break;
case 'x':
txmsg_pop = atoi(optarg);
break;
case 'a':
txmsg_apply = atoi(optarg);
break;

View File

@ -74,7 +74,7 @@ struct bpf_map_def SEC("maps") sock_bytes = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(int),
.max_entries = 4
.max_entries = 6
};
struct bpf_map_def SEC("maps") sock_redir_flags = {
@ -181,8 +181,8 @@ int bpf_sockmap(struct bpf_sock_ops *skops)
SEC("sk_msg1")
int bpf_prog4(struct sk_msg_md *msg)
{
int *bytes, zero = 0, one = 1, two = 2, three = 3;
int *start, *end, *start_push, *end_push;
int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
int *start, *end, *start_push, *end_push, *start_pop, *pop;
bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
if (bytes)
@ -198,15 +198,19 @@ int bpf_prog4(struct sk_msg_md *msg)
end_push = bpf_map_lookup_elem(&sock_bytes, &three);
if (start_push && end_push)
bpf_msg_push_data(msg, *start_push, *end_push, 0);
start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
pop = bpf_map_lookup_elem(&sock_bytes, &five);
if (start_pop && pop)
bpf_msg_pop_data(msg, *start_pop, *pop, 0);
return SK_PASS;
}
SEC("sk_msg2")
int bpf_prog5(struct sk_msg_md *msg)
{
int zero = 0, one = 1, two = 2, three = 3;
int *start, *end, *start_push, *end_push;
int *bytes, len1, len2 = 0, len3;
int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
int *start, *end, *start_push, *end_push, *start_pop, *pop;
int *bytes, len1, len2 = 0, len3, len4;
int err1 = -1, err2 = -1;
bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
@ -247,6 +251,20 @@ int bpf_prog5(struct sk_msg_md *msg)
bpf_printk("sk_msg2: length push_update %i->%i\n",
len2 ? len2 : len1, len3);
}
start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
pop = bpf_map_lookup_elem(&sock_bytes, &five);
if (start_pop && pop) {
int err;
bpf_printk("sk_msg2: pop(%i@%i)\n",
start_pop, pop);
err = bpf_msg_pop_data(msg, *start_pop, *pop, 0);
if (err)
bpf_printk("sk_msg2: pop_data err %i\n", err);
len4 = (__u64)msg->data_end - (__u64)msg->data;
bpf_printk("sk_msg2: length pop_data %i->%i\n",
len1 ? len1 : 0, len4);
}
bpf_printk("sk_msg2: data length %i err1 %i err2 %i\n",
len1, err1, err2);
@ -256,8 +274,8 @@ int bpf_prog5(struct sk_msg_md *msg)
SEC("sk_msg3")
int bpf_prog6(struct sk_msg_md *msg)
{
int *bytes, *start, *end, *start_push, *end_push, *f;
int zero = 0, one = 1, two = 2, three = 3, key = 0;
int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;
int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
__u64 flags = 0;
bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
@ -277,6 +295,11 @@ int bpf_prog6(struct sk_msg_md *msg)
if (start_push && end_push)
bpf_msg_push_data(msg, *start_push, *end_push, 0);
start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
pop = bpf_map_lookup_elem(&sock_bytes, &five);
if (start_pop && pop)
bpf_msg_pop_data(msg, *start_pop, *pop, 0);
f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
if (f && *f) {
key = 2;
@ -292,8 +315,9 @@ int bpf_prog6(struct sk_msg_md *msg)
SEC("sk_msg4")
int bpf_prog7(struct sk_msg_md *msg)
{
int zero = 0, one = 1, two = 2, three = 3, len1, len2 = 0, len3;
int *bytes, *start, *end, *start_push, *end_push, *f;
int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
int len1, len2 = 0, len3, len4;
int err1 = 0, err2 = 0, key = 0;
__u64 flags = 0;
@ -335,6 +359,22 @@ int bpf_prog7(struct sk_msg_md *msg)
len2 ? len2 : len1, len3);
}
start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
pop = bpf_map_lookup_elem(&sock_bytes, &five);
if (start_pop && pop) {
int err;
bpf_printk("sk_msg4: pop(%i@%i)\n",
start_pop, pop);
err = bpf_msg_pop_data(msg, *start_pop, *pop, 0);
if (err)
bpf_printk("sk_msg4: pop_data err %i\n", err);
len4 = (__u64)msg->data_end - (__u64)msg->data;
bpf_printk("sk_msg4: length pop_data %i->%i\n",
len1 ? len1 : 0, len4);
}
f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
if (f && *f) {
key = 2;
@ -389,8 +429,8 @@ int bpf_prog9(struct sk_msg_md *msg)
SEC("sk_msg7")
int bpf_prog10(struct sk_msg_md *msg)
{
int *bytes, *start, *end, *start_push, *end_push;
int zero = 0, one = 1, two = 2, three = 3;
int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;
int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
if (bytes)
@ -406,7 +446,11 @@ int bpf_prog10(struct sk_msg_md *msg)
end_push = bpf_map_lookup_elem(&sock_bytes, &three);
if (start_push && end_push)
bpf_msg_push_data(msg, *start_push, *end_push, 0);
start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
pop = bpf_map_lookup_elem(&sock_bytes, &five);
if (start_pop && pop)
bpf_msg_pop_data(msg, *start_pop, *pop, 0);
bpf_printk("return sk drop\n");
return SK_DROP;
}