[PATCH v6 tip 6/8] samples: bpf: counting example for kfree_skb and write syscall

2015-03-10 Thread Alexei Starovoitov
this example has two probes in one C file that attach to different kprove events
and use two different maps.

1st probe is x64 specific equivalent of dropmon. It attaches to kfree_skb,
retrevies 'ip' address of kfree_skb() caller and counts number of packet drops
at that 'ip' address. User space prints 'location - count' map every second.

2nd probe attaches to kprobe:sys_write and computes a histogram of different
write sizes

Usage:
$ sudo tracex2
location 0x81695995 count 1
location 0x816d0da9 count 2

location 0x81695995 count 2
location 0x816d0da9 count 2

location 0x81695995 count 3
location 0x816d0da9 count 2

557145+0 records in
557145+0 records out
285258240 bytes (285 MB) copied, 1.02379 s, 279 MB/s
   syscall write() stats
 byte_size   : count distribution
   1 -> 1: 3|  |
   2 -> 3: 0|  |
   4 -> 7: 0|  |
   8 -> 15   : 0|  |
  16 -> 31   : 2|  |
  32 -> 63   : 3|  |
  64 -> 127  : 1|  |
 128 -> 255  : 1|  |
 256 -> 511  : 0|  |
 512 -> 1023 : 1118968  |* |

Ctrl-C at any time. Kernel will auto cleanup maps and programs

$ addr2line -ape ./bld_x64/vmlinux 0x81695995 0x816d0da9
0x81695995: ./bld_x64/../net/ipv4/icmp.c:1038
0x816d0da9: ./bld_x64/../net/unix/af_unix.c:1231

Signed-off-by: Alexei Starovoitov 
---
 samples/bpf/Makefile   |4 ++
 samples/bpf/tracex2_kern.c |   86 +++
 samples/bpf/tracex2_user.c |   95 
 3 files changed, 185 insertions(+)
 create mode 100644 samples/bpf/tracex2_kern.c
 create mode 100644 samples/bpf/tracex2_user.c

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 51f6f01e5a3a..6dd272143733 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -7,6 +7,7 @@ hostprogs-y += sock_example
 hostprogs-y += sockex1
 hostprogs-y += sockex2
 hostprogs-y += tracex1
+hostprogs-y += tracex2
 
 test_verifier-objs := test_verifier.o libbpf.o
 test_maps-objs := test_maps.o libbpf.o
@@ -14,12 +15,14 @@ sock_example-objs := sock_example.o libbpf.o
 sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
 sockex2-objs := bpf_load.o libbpf.o sockex2_user.o
 tracex1-objs := bpf_load.o libbpf.o tracex1_user.o
+tracex2-objs := bpf_load.o libbpf.o tracex2_user.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
 always += sockex1_kern.o
 always += sockex2_kern.o
 always += tracex1_kern.o
+always += tracex2_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 
@@ -27,6 +30,7 @@ HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include 
-Wno-unused-variable
 HOSTLOADLIBES_sockex1 += -lelf
 HOSTLOADLIBES_sockex2 += -lelf
 HOSTLOADLIBES_tracex1 += -lelf
+HOSTLOADLIBES_tracex2 += -lelf
 
 # point this to your LLVM backend with bpf support
 LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc
diff --git a/samples/bpf/tracex2_kern.c b/samples/bpf/tracex2_kern.c
new file mode 100644
index ..334348335795
--- /dev/null
+++ b/samples/bpf/tracex2_kern.c
@@ -0,0 +1,86 @@
+/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include 
+#include 
+#include 
+#include 
+#include "bpf_helpers.h"
+
+struct bpf_map_def SEC("maps") my_map = {
+   .type = BPF_MAP_TYPE_HASH,
+   .key_size = sizeof(long),
+   .value_size = sizeof(long),
+   .max_entries = 1024,
+};
+
+/* kprobe is NOT a stable ABI
+ * This bpf+kprobe example can stop working any time.
+ */
+SEC("kprobe/kfree_skb")
+int bpf_prog2(struct pt_regs *ctx)
+{
+   long loc = 0;
+   long init_val = 1;
+   long *value;
+
+   /* x64 specific: read ip of kfree_skb caller.
+* non-portable version of __builtin_return_address(0)
+*/
+   bpf_probe_read(, sizeof(loc), (void *)ctx->sp);
+
+   value = bpf_map_lookup_elem(_map, );
+   if (value)
+   *value += 1;
+   else
+   bpf_map_update_elem(_map, , _val, BPF_ANY);
+   return 0;
+}
+
+static unsigned int log2(unsigned int v)
+{
+   unsigned int r;
+   unsigned int shift;
+
+   r = (v > 0x) << 4; v >>= r;
+   shift = (v > 0xFF) << 3; v >>= shift; r |= shift;
+   shift = (v > 0xF) << 2; v >>= shift; r |= shift;
+   shift = (v > 0x3) << 1; v >>= shift; r 

[PATCH v6 tip 6/8] samples: bpf: counting example for kfree_skb and write syscall

2015-03-10 Thread Alexei Starovoitov
this example has two probes in one C file that attach to different kprove events
and use two different maps.

1st probe is x64 specific equivalent of dropmon. It attaches to kfree_skb,
retrevies 'ip' address of kfree_skb() caller and counts number of packet drops
at that 'ip' address. User space prints 'location - count' map every second.

2nd probe attaches to kprobe:sys_write and computes a histogram of different
write sizes

Usage:
$ sudo tracex2
location 0x81695995 count 1
location 0x816d0da9 count 2

location 0x81695995 count 2
location 0x816d0da9 count 2

location 0x81695995 count 3
location 0x816d0da9 count 2

557145+0 records in
557145+0 records out
285258240 bytes (285 MB) copied, 1.02379 s, 279 MB/s
   syscall write() stats
 byte_size   : count distribution
   1 - 1: 3|  |
   2 - 3: 0|  |
   4 - 7: 0|  |
   8 - 15   : 0|  |
  16 - 31   : 2|  |
  32 - 63   : 3|  |
  64 - 127  : 1|  |
 128 - 255  : 1|  |
 256 - 511  : 0|  |
 512 - 1023 : 1118968  |* |

Ctrl-C at any time. Kernel will auto cleanup maps and programs

$ addr2line -ape ./bld_x64/vmlinux 0x81695995 0x816d0da9
0x81695995: ./bld_x64/../net/ipv4/icmp.c:1038
0x816d0da9: ./bld_x64/../net/unix/af_unix.c:1231

Signed-off-by: Alexei Starovoitov a...@plumgrid.com
---
 samples/bpf/Makefile   |4 ++
 samples/bpf/tracex2_kern.c |   86 +++
 samples/bpf/tracex2_user.c |   95 
 3 files changed, 185 insertions(+)
 create mode 100644 samples/bpf/tracex2_kern.c
 create mode 100644 samples/bpf/tracex2_user.c

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 51f6f01e5a3a..6dd272143733 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -7,6 +7,7 @@ hostprogs-y += sock_example
 hostprogs-y += sockex1
 hostprogs-y += sockex2
 hostprogs-y += tracex1
+hostprogs-y += tracex2
 
 test_verifier-objs := test_verifier.o libbpf.o
 test_maps-objs := test_maps.o libbpf.o
@@ -14,12 +15,14 @@ sock_example-objs := sock_example.o libbpf.o
 sockex1-objs := bpf_load.o libbpf.o sockex1_user.o
 sockex2-objs := bpf_load.o libbpf.o sockex2_user.o
 tracex1-objs := bpf_load.o libbpf.o tracex1_user.o
+tracex2-objs := bpf_load.o libbpf.o tracex2_user.o
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
 always += sockex1_kern.o
 always += sockex2_kern.o
 always += tracex1_kern.o
+always += tracex2_kern.o
 
 HOSTCFLAGS += -I$(objtree)/usr/include
 
@@ -27,6 +30,7 @@ HOSTCFLAGS_bpf_load.o += -I$(objtree)/usr/include 
-Wno-unused-variable
 HOSTLOADLIBES_sockex1 += -lelf
 HOSTLOADLIBES_sockex2 += -lelf
 HOSTLOADLIBES_tracex1 += -lelf
+HOSTLOADLIBES_tracex2 += -lelf
 
 # point this to your LLVM backend with bpf support
 LLC=$(srctree)/tools/bpf/llvm/bld/Debug+Asserts/bin/llc
diff --git a/samples/bpf/tracex2_kern.c b/samples/bpf/tracex2_kern.c
new file mode 100644
index ..334348335795
--- /dev/null
+++ b/samples/bpf/tracex2_kern.c
@@ -0,0 +1,86 @@
+/* Copyright (c) 2013-2015 PLUMgrid, http://plumgrid.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ */
+#include linux/skbuff.h
+#include linux/netdevice.h
+#include linux/version.h
+#include uapi/linux/bpf.h
+#include bpf_helpers.h
+
+struct bpf_map_def SEC(maps) my_map = {
+   .type = BPF_MAP_TYPE_HASH,
+   .key_size = sizeof(long),
+   .value_size = sizeof(long),
+   .max_entries = 1024,
+};
+
+/* kprobe is NOT a stable ABI
+ * This bpf+kprobe example can stop working any time.
+ */
+SEC(kprobe/kfree_skb)
+int bpf_prog2(struct pt_regs *ctx)
+{
+   long loc = 0;
+   long init_val = 1;
+   long *value;
+
+   /* x64 specific: read ip of kfree_skb caller.
+* non-portable version of __builtin_return_address(0)
+*/
+   bpf_probe_read(loc, sizeof(loc), (void *)ctx-sp);
+
+   value = bpf_map_lookup_elem(my_map, loc);
+   if (value)
+   *value += 1;
+   else
+   bpf_map_update_elem(my_map, loc, init_val, BPF_ANY);
+   return 0;
+}
+
+static unsigned int log2(unsigned int v)
+{
+   unsigned int r;
+   unsigned int shift;
+
+   r = (v  0x)  4; v = r;
+   shift = (v  0xFF)  3; v = shift; r |= shift;
+   shift = (v  0xF)  2; v =