aboutsummaryrefslogtreecommitdiffstats
path: root/samples
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@plumgrid.com>2015-03-13 14:57:43 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-15 22:02:28 -0400
commit614cd3bd3758a806cea497d493b584e6157561f7 (patch)
tree3c294086671617614f672aeb0d14bd2496fdb23c /samples
parent9bac3d6d548e5cc925570b263f35b70a00a00ffd (diff)
samples: bpf: add skb->field examples and tests
- modify sockex1 example to count number of bytes in outgoing packets - modify sockex2 example to count number of bytes and packets per flow - add 4 stress tests that exercise 'skb->field' code path of verifier Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples')
-rw-r--r--samples/bpf/sockex1_kern.c8
-rw-r--r--samples/bpf/sockex1_user.c2
-rw-r--r--samples/bpf/sockex2_kern.c26
-rw-r--r--samples/bpf/sockex2_user.c11
-rw-r--r--samples/bpf/test_verifier.c70
5 files changed, 101 insertions, 16 deletions
diff --git a/samples/bpf/sockex1_kern.c b/samples/bpf/sockex1_kern.c
index 066892662915..ed18e9a4909c 100644
--- a/samples/bpf/sockex1_kern.c
+++ b/samples/bpf/sockex1_kern.c
@@ -1,5 +1,6 @@
1#include <uapi/linux/bpf.h> 1#include <uapi/linux/bpf.h>
2#include <uapi/linux/if_ether.h> 2#include <uapi/linux/if_ether.h>
3#include <uapi/linux/if_packet.h>
3#include <uapi/linux/ip.h> 4#include <uapi/linux/ip.h>
4#include "bpf_helpers.h" 5#include "bpf_helpers.h"
5 6
@@ -11,14 +12,17 @@ struct bpf_map_def SEC("maps") my_map = {
11}; 12};
12 13
13SEC("socket1") 14SEC("socket1")
14int bpf_prog1(struct sk_buff *skb) 15int bpf_prog1(struct __sk_buff *skb)
15{ 16{
16 int index = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol)); 17 int index = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol));
17 long *value; 18 long *value;
18 19
20 if (skb->pkt_type != PACKET_OUTGOING)
21 return 0;
22
19 value = bpf_map_lookup_elem(&my_map, &index); 23 value = bpf_map_lookup_elem(&my_map, &index);
20 if (value) 24 if (value)
21 __sync_fetch_and_add(value, 1); 25 __sync_fetch_and_add(value, skb->len);
22 26
23 return 0; 27 return 0;
24} 28}
diff --git a/samples/bpf/sockex1_user.c b/samples/bpf/sockex1_user.c
index 34a443ff3831..678ce4693551 100644
--- a/samples/bpf/sockex1_user.c
+++ b/samples/bpf/sockex1_user.c
@@ -40,7 +40,7 @@ int main(int ac, char **argv)
40 key = IPPROTO_ICMP; 40 key = IPPROTO_ICMP;
41 assert(bpf_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0); 41 assert(bpf_lookup_elem(map_fd[0], &key, &icmp_cnt) == 0);
42 42
43 printf("TCP %lld UDP %lld ICMP %lld packets\n", 43 printf("TCP %lld UDP %lld ICMP %lld bytes\n",
44 tcp_cnt, udp_cnt, icmp_cnt); 44 tcp_cnt, udp_cnt, icmp_cnt);
45 sleep(1); 45 sleep(1);
46 } 46 }
diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c
index 6f0135f0f217..ba0e177ff561 100644
--- a/samples/bpf/sockex2_kern.c
+++ b/samples/bpf/sockex2_kern.c
@@ -42,13 +42,13 @@ static inline int proto_ports_offset(__u64 proto)
42 } 42 }
43} 43}
44 44
45static inline int ip_is_fragment(struct sk_buff *ctx, __u64 nhoff) 45static inline int ip_is_fragment(struct __sk_buff *ctx, __u64 nhoff)
46{ 46{
47 return load_half(ctx, nhoff + offsetof(struct iphdr, frag_off)) 47 return load_half(ctx, nhoff + offsetof(struct iphdr, frag_off))
48 & (IP_MF | IP_OFFSET); 48 & (IP_MF | IP_OFFSET);
49} 49}
50 50
51static inline __u32 ipv6_addr_hash(struct sk_buff *ctx, __u64 off) 51static inline __u32 ipv6_addr_hash(struct __sk_buff *ctx, __u64 off)
52{ 52{
53 __u64 w0 = load_word(ctx, off); 53 __u64 w0 = load_word(ctx, off);
54 __u64 w1 = load_word(ctx, off + 4); 54 __u64 w1 = load_word(ctx, off + 4);
@@ -58,7 +58,7 @@ static inline __u32 ipv6_addr_hash(struct sk_buff *ctx, __u64 off)
58 return (__u32)(w0 ^ w1 ^ w2 ^ w3); 58 return (__u32)(w0 ^ w1 ^ w2 ^ w3);
59} 59}
60 60
61static inline __u64 parse_ip(struct sk_buff *skb, __u64 nhoff, __u64 *ip_proto, 61static inline __u64 parse_ip(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto,
62 struct flow_keys *flow) 62 struct flow_keys *flow)
63{ 63{
64 __u64 verlen; 64 __u64 verlen;
@@ -82,7 +82,7 @@ static inline __u64 parse_ip(struct sk_buff *skb, __u64 nhoff, __u64 *ip_proto,
82 return nhoff; 82 return nhoff;
83} 83}
84 84
85static inline __u64 parse_ipv6(struct sk_buff *skb, __u64 nhoff, __u64 *ip_proto, 85static inline __u64 parse_ipv6(struct __sk_buff *skb, __u64 nhoff, __u64 *ip_proto,
86 struct flow_keys *flow) 86 struct flow_keys *flow)
87{ 87{
88 *ip_proto = load_byte(skb, 88 *ip_proto = load_byte(skb,
@@ -96,7 +96,7 @@ static inline __u64 parse_ipv6(struct sk_buff *skb, __u64 nhoff, __u64 *ip_proto
96 return nhoff; 96 return nhoff;
97} 97}
98 98
99static inline bool flow_dissector(struct sk_buff *skb, struct flow_keys *flow) 99static inline bool flow_dissector(struct __sk_buff *skb, struct flow_keys *flow)
100{ 100{
101 __u64 nhoff = ETH_HLEN; 101 __u64 nhoff = ETH_HLEN;
102 __u64 ip_proto; 102 __u64 ip_proto;
@@ -183,18 +183,23 @@ static inline bool flow_dissector(struct sk_buff *skb, struct flow_keys *flow)
183 return true; 183 return true;
184} 184}
185 185
186struct pair {
187 long packets;
188 long bytes;
189};
190
186struct bpf_map_def SEC("maps") hash_map = { 191struct bpf_map_def SEC("maps") hash_map = {
187 .type = BPF_MAP_TYPE_HASH, 192 .type = BPF_MAP_TYPE_HASH,
188 .key_size = sizeof(__be32), 193 .key_size = sizeof(__be32),
189 .value_size = sizeof(long), 194 .value_size = sizeof(struct pair),
190 .max_entries = 1024, 195 .max_entries = 1024,
191}; 196};
192 197
193SEC("socket2") 198SEC("socket2")
194int bpf_prog2(struct sk_buff *skb) 199int bpf_prog2(struct __sk_buff *skb)
195{ 200{
196 struct flow_keys flow; 201 struct flow_keys flow;
197 long *value; 202 struct pair *value;
198 u32 key; 203 u32 key;
199 204
200 if (!flow_dissector(skb, &flow)) 205 if (!flow_dissector(skb, &flow))
@@ -203,9 +208,10 @@ int bpf_prog2(struct sk_buff *skb)
203 key = flow.dst; 208 key = flow.dst;
204 value = bpf_map_lookup_elem(&hash_map, &key); 209 value = bpf_map_lookup_elem(&hash_map, &key);
205 if (value) { 210 if (value) {
206 __sync_fetch_and_add(value, 1); 211 __sync_fetch_and_add(&value->packets, 1);
212 __sync_fetch_and_add(&value->bytes, skb->len);
207 } else { 213 } else {
208 long val = 1; 214 struct pair val = {1, skb->len};
209 215
210 bpf_map_update_elem(&hash_map, &key, &val, BPF_ANY); 216 bpf_map_update_elem(&hash_map, &key, &val, BPF_ANY);
211 } 217 }
diff --git a/samples/bpf/sockex2_user.c b/samples/bpf/sockex2_user.c
index d2d5f5a790d3..29a276d766fc 100644
--- a/samples/bpf/sockex2_user.c
+++ b/samples/bpf/sockex2_user.c
@@ -6,6 +6,11 @@
6#include <unistd.h> 6#include <unistd.h>
7#include <arpa/inet.h> 7#include <arpa/inet.h>
8 8
9struct pair {
10 __u64 packets;
11 __u64 bytes;
12};
13
9int main(int ac, char **argv) 14int main(int ac, char **argv)
10{ 15{
11 char filename[256]; 16 char filename[256];
@@ -29,13 +34,13 @@ int main(int ac, char **argv)
29 34
30 for (i = 0; i < 5; i++) { 35 for (i = 0; i < 5; i++) {
31 int key = 0, next_key; 36 int key = 0, next_key;
32 long long value; 37 struct pair value;
33 38
34 while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) { 39 while (bpf_get_next_key(map_fd[0], &key, &next_key) == 0) {
35 bpf_lookup_elem(map_fd[0], &next_key, &value); 40 bpf_lookup_elem(map_fd[0], &next_key, &value);
36 printf("ip %s count %lld\n", 41 printf("ip %s bytes %lld packets %lld\n",
37 inet_ntoa((struct in_addr){htonl(next_key)}), 42 inet_ntoa((struct in_addr){htonl(next_key)}),
38 value); 43 value.bytes, value.packets);
39 key = next_key; 44 key = next_key;
40 } 45 }
41 sleep(1); 46 sleep(1);
diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c
index 7b56b59fad8e..df6dbb6576f6 100644
--- a/samples/bpf/test_verifier.c
+++ b/samples/bpf/test_verifier.c
@@ -14,6 +14,7 @@
14#include <linux/unistd.h> 14#include <linux/unistd.h>
15#include <string.h> 15#include <string.h>
16#include <linux/filter.h> 16#include <linux/filter.h>
17#include <stddef.h>
17#include "libbpf.h" 18#include "libbpf.h"
18 19
19#define MAX_INSNS 512 20#define MAX_INSNS 512
@@ -642,6 +643,75 @@ static struct bpf_test tests[] = {
642 }, 643 },
643 .result = ACCEPT, 644 .result = ACCEPT,
644 }, 645 },
646 {
647 "access skb fields ok",
648 .insns = {
649 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
650 offsetof(struct __sk_buff, len)),
651 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
652 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
653 offsetof(struct __sk_buff, mark)),
654 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
655 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
656 offsetof(struct __sk_buff, pkt_type)),
657 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
658 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
659 offsetof(struct __sk_buff, queue_mapping)),
660 BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 0),
661 BPF_EXIT_INSN(),
662 },
663 .result = ACCEPT,
664 },
665 {
666 "access skb fields bad1",
667 .insns = {
668 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, -4),
669 BPF_EXIT_INSN(),
670 },
671 .errstr = "invalid bpf_context access",
672 .result = REJECT,
673 },
674 {
675 "access skb fields bad2",
676 .insns = {
677 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 9),
678 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
679 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
680 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
681 BPF_LD_MAP_FD(BPF_REG_1, 0),
682 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
683 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
684 BPF_EXIT_INSN(),
685 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
686 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
687 offsetof(struct __sk_buff, pkt_type)),
688 BPF_EXIT_INSN(),
689 },
690 .fixup = {4},
691 .errstr = "different pointers",
692 .result = REJECT,
693 },
694 {
695 "access skb fields bad3",
696 .insns = {
697 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0, 2),
698 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
699 offsetof(struct __sk_buff, pkt_type)),
700 BPF_EXIT_INSN(),
701 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
702 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
703 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
704 BPF_LD_MAP_FD(BPF_REG_1, 0),
705 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
706 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
707 BPF_EXIT_INSN(),
708 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
709 BPF_JMP_IMM(BPF_JA, 0, 0, -12),
710 },
711 .fixup = {6},
712 .errstr = "different pointers",
713 .result = REJECT,
714 },
645}; 715};
646 716
647static int probe_filter_length(struct bpf_insn *fp) 717static int probe_filter_length(struct bpf_insn *fp)