diff options
author | Stanislav Fomichev <sdf@google.com> | 2019-04-22 11:55:45 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2019-04-23 12:36:34 -0400 |
commit | 7b8a1304323b35bbf060e0d29691031056836b73 (patch) | |
tree | 19d54fc05d3c50660c9c7277e11ebda3665e12cf /net/bpf | |
parent | 089b19a9204fc090793d389a265f54124eacb05d (diff) |
bpf: when doing BPF_PROG_TEST_RUN for flow dissector use no-skb mode
Now that we have bpf_flow_dissect which can work on raw data,
use it when doing BPF_PROG_TEST_RUN for flow dissector.
Simplifies bpf_prog_test_run_flow_dissector and allows us to
test no-skb mode.
Note, that previously, with bpf_flow_dissect_skb we used to call
eth_type_trans which pulled L2 (ETH_HLEN) header and we explicitly called
skb_reset_network_header. That means flow_keys->nhoff would be
initialized to 0 (skb_network_offset) in init_flow_keys.
Now we call bpf_flow_dissect with nhoff set to ETH_HLEN and need
to undo it once the dissection is done to preserve the existing behavior.
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'net/bpf')
-rw-r--r-- | net/bpf/test_run.c | 47 |
1 files changed, 17 insertions, 30 deletions
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 006ad865f7fb..db2ec88ab129 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c | |||
@@ -379,12 +379,12 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, | |||
379 | union bpf_attr __user *uattr) | 379 | union bpf_attr __user *uattr) |
380 | { | 380 | { |
381 | u32 size = kattr->test.data_size_in; | 381 | u32 size = kattr->test.data_size_in; |
382 | struct bpf_flow_dissector ctx = {}; | ||
382 | u32 repeat = kattr->test.repeat; | 383 | u32 repeat = kattr->test.repeat; |
383 | struct bpf_flow_keys flow_keys; | 384 | struct bpf_flow_keys flow_keys; |
384 | u64 time_start, time_spent = 0; | 385 | u64 time_start, time_spent = 0; |
386 | const struct ethhdr *eth; | ||
385 | u32 retval, duration; | 387 | u32 retval, duration; |
386 | struct sk_buff *skb; | ||
387 | struct sock *sk; | ||
388 | void *data; | 388 | void *data; |
389 | int ret; | 389 | int ret; |
390 | u32 i; | 390 | u32 i; |
@@ -395,43 +395,31 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, | |||
395 | if (kattr->test.ctx_in || kattr->test.ctx_out) | 395 | if (kattr->test.ctx_in || kattr->test.ctx_out) |
396 | return -EINVAL; | 396 | return -EINVAL; |
397 | 397 | ||
398 | data = bpf_test_init(kattr, size, NET_SKB_PAD + NET_IP_ALIGN, | 398 | if (size < ETH_HLEN) |
399 | SKB_DATA_ALIGN(sizeof(struct skb_shared_info))); | 399 | return -EINVAL; |
400 | |||
401 | data = bpf_test_init(kattr, size, 0, 0); | ||
400 | if (IS_ERR(data)) | 402 | if (IS_ERR(data)) |
401 | return PTR_ERR(data); | 403 | return PTR_ERR(data); |
402 | 404 | ||
403 | sk = kzalloc(sizeof(*sk), GFP_USER); | 405 | eth = (struct ethhdr *)data; |
404 | if (!sk) { | ||
405 | kfree(data); | ||
406 | return -ENOMEM; | ||
407 | } | ||
408 | sock_net_set(sk, current->nsproxy->net_ns); | ||
409 | sock_init_data(NULL, sk); | ||
410 | |||
411 | skb = build_skb(data, 0); | ||
412 | if (!skb) { | ||
413 | kfree(data); | ||
414 | kfree(sk); | ||
415 | return -ENOMEM; | ||
416 | } | ||
417 | skb->sk = sk; | ||
418 | |||
419 | skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); | ||
420 | __skb_put(skb, size); | ||
421 | skb->protocol = eth_type_trans(skb, | ||
422 | current->nsproxy->net_ns->loopback_dev); | ||
423 | skb_reset_network_header(skb); | ||
424 | 406 | ||
425 | if (!repeat) | 407 | if (!repeat) |
426 | repeat = 1; | 408 | repeat = 1; |
427 | 409 | ||
410 | ctx.flow_keys = &flow_keys; | ||
411 | ctx.data = data; | ||
412 | ctx.data_end = (__u8 *)data + size; | ||
413 | |||
428 | rcu_read_lock(); | 414 | rcu_read_lock(); |
429 | preempt_disable(); | 415 | preempt_disable(); |
430 | time_start = ktime_get_ns(); | 416 | time_start = ktime_get_ns(); |
431 | for (i = 0; i < repeat; i++) { | 417 | for (i = 0; i < repeat; i++) { |
432 | retval = __skb_flow_bpf_dissect(prog, skb, | 418 | retval = bpf_flow_dissect(prog, &ctx, eth->h_proto, ETH_HLEN, |
433 | &flow_keys_dissector, | 419 | size); |
434 | &flow_keys); | 420 | |
421 | flow_keys.nhoff -= ETH_HLEN; | ||
422 | flow_keys.thoff -= ETH_HLEN; | ||
435 | 423 | ||
436 | if (signal_pending(current)) { | 424 | if (signal_pending(current)) { |
437 | preempt_enable(); | 425 | preempt_enable(); |
@@ -464,7 +452,6 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog, | |||
464 | retval, duration); | 452 | retval, duration); |
465 | 453 | ||
466 | out: | 454 | out: |
467 | kfree_skb(skb); | 455 | kfree(data); |
468 | kfree(sk); | ||
469 | return ret; | 456 | return ret; |
470 | } | 457 | } |