summaryrefslogtreecommitdiffstats
path: root/net/bpf
diff options
context:
space:
mode:
authorStanislav Fomichev <sdf@google.com>2019-04-22 11:55:45 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2019-04-23 12:36:34 -0400
commit7b8a1304323b35bbf060e0d29691031056836b73 (patch)
tree19d54fc05d3c50660c9c7277e11ebda3665e12cf /net/bpf
parent089b19a9204fc090793d389a265f54124eacb05d (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.c47
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
466out: 454out:
467 kfree_skb(skb); 455 kfree(data);
468 kfree(sk);
469 return ret; 456 return ret;
470} 457}