Brenden Blanco | 561dafc | 2015-06-29 11:09:00 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # Copyright (c) PLUMgrid, Inc. |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License") |
| 4 | |
Brenden Blanco | c35989d | 2015-09-02 18:04:07 -0700 | [diff] [blame] | 5 | from bcc import BPF |
Brenden Blanco | 561dafc | 2015-06-29 11:09:00 -0700 | [diff] [blame] | 6 | from unittest import main, TestCase |
| 7 | |
| 8 | class TestClang(TestCase): |
| 9 | def test_complex(self): |
| 10 | b = BPF(src_file="test_clang_complex.c", debug=0) |
| 11 | fn = b.load_func("handle_packet", BPF.SCHED_CLS) |
| 12 | def test_printk(self): |
| 13 | text = """ |
| 14 | #include <bcc/proto.h> |
| 15 | int handle_packet(void *ctx) { |
Brenden Blanco | 6ec65e4 | 2015-07-02 10:02:04 -0700 | [diff] [blame] | 16 | u8 *cursor = 0; |
| 17 | struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); |
| 18 | bpf_trace_printk("ethernet->dst = %llx, ethernet->src = %llx\\n", |
| 19 | ethernet->dst, ethernet->src); |
Brenden Blanco | 561dafc | 2015-06-29 11:09:00 -0700 | [diff] [blame] | 20 | return 0; |
| 21 | } |
| 22 | """ |
| 23 | b = BPF(text=text, debug=0) |
| 24 | fn = b.load_func("handle_packet", BPF.SCHED_CLS) |
| 25 | |
Brenden Blanco | b711d45 | 2015-07-01 15:23:18 -0700 | [diff] [blame] | 26 | def test_probe_read1(self): |
| 27 | text = """ |
| 28 | #include <linux/sched.h> |
| 29 | #include <uapi/linux/ptrace.h> |
| 30 | int count_sched(struct pt_regs *ctx, struct task_struct *prev) { |
| 31 | pid_t p = prev->pid; |
| 32 | return (p != -1); |
| 33 | } |
| 34 | """ |
| 35 | b = BPF(text=text, debug=0) |
| 36 | fn = b.load_func("count_sched", BPF.KPROBE) |
| 37 | |
| 38 | def test_probe_read2(self): |
| 39 | text = """ |
| 40 | #include <linux/sched.h> |
| 41 | #include <uapi/linux/ptrace.h> |
| 42 | int count_foo(struct pt_regs *ctx, unsigned long a, unsigned long b) { |
| 43 | return (a != b); |
| 44 | } |
| 45 | """ |
| 46 | b = BPF(text=text, debug=0) |
| 47 | fn = b.load_func("count_foo", BPF.KPROBE) |
| 48 | |
Brenden Blanco | 3c4a29c | 2015-09-08 22:16:10 -0700 | [diff] [blame] | 49 | def test_probe_read_keys(self): |
| 50 | text = """ |
| 51 | #include <uapi/linux/ptrace.h> |
| 52 | #include <linux/blkdev.h> |
| 53 | BPF_HASH(start, struct request *); |
| 54 | int do_request(struct pt_regs *ctx, struct request *req) { |
| 55 | u64 ts = bpf_ktime_get_ns(); |
| 56 | start.update(&req, &ts); |
| 57 | return 0; |
| 58 | } |
| 59 | |
| 60 | int do_completion(struct pt_regs *ctx, struct request *req) { |
| 61 | u64 *tsp = start.lookup(&req); |
| 62 | if (tsp != 0) { |
| 63 | start.delete(&req); |
| 64 | } |
| 65 | return 0; |
| 66 | } |
| 67 | """ |
| 68 | b = BPF(text=text, debug=0) |
| 69 | fns = b.load_funcs(BPF.KPROBE) |
| 70 | |
Brenden Blanco | 00ee4fe | 2015-08-07 21:04:35 -0700 | [diff] [blame] | 71 | def test_sscanf(self): |
Brenden Blanco | 52b0a90 | 2015-08-07 08:28:02 -0700 | [diff] [blame] | 72 | text = """ |
Brenden Blanco | 985adf6 | 2015-08-08 21:00:59 -0700 | [diff] [blame] | 73 | BPF_TABLE("hash", int, struct { u64 a; u64 b; u64 c:36; u64 d:28; struct { u32 a; u32 b; } s; }, stats, 10); |
Brenden Blanco | 52b0a90 | 2015-08-07 08:28:02 -0700 | [diff] [blame] | 74 | int foo(void *ctx) { |
| 75 | return 0; |
| 76 | } |
| 77 | """ |
| 78 | b = BPF(text=text, debug=0) |
| 79 | fn = b.load_func("foo", BPF.KPROBE) |
Brenden Blanco | 985adf6 | 2015-08-08 21:00:59 -0700 | [diff] [blame] | 80 | t = b.get_table("stats") |
Brenden Blanco | 2582ecf | 2015-08-12 12:08:00 -0700 | [diff] [blame] | 81 | s1 = t.key_sprintf(t.Key(2)) |
| 82 | self.assertEqual(s1, b"0x2") |
| 83 | s2 = t.leaf_sprintf(t.Leaf(2, 3, 4, 1, (5, 6))) |
| 84 | l = t.leaf_scanf(s2) |
Brenden Blanco | 985adf6 | 2015-08-08 21:00:59 -0700 | [diff] [blame] | 85 | self.assertEqual(l.a, 2) |
| 86 | self.assertEqual(l.b, 3) |
| 87 | self.assertEqual(l.c, 4) |
| 88 | self.assertEqual(l.d, 1) |
| 89 | self.assertEqual(l.s.a, 5) |
| 90 | self.assertEqual(l.s.b, 6) |
Brenden Blanco | 52b0a90 | 2015-08-07 08:28:02 -0700 | [diff] [blame] | 91 | |
Brenden Blanco | dfcdf0a | 2015-08-11 12:45:00 -0700 | [diff] [blame] | 92 | def test_iosnoop(self): |
| 93 | text = """ |
| 94 | #include <linux/blkdev.h> |
| 95 | #include <uapi/linux/ptrace.h> |
| 96 | |
| 97 | struct key_t { |
| 98 | struct request *req; |
| 99 | }; |
| 100 | |
| 101 | BPF_TABLE("hash", struct key_t, u64, start, 1024); |
| 102 | int do_request(struct pt_regs *ctx, struct request *req) { |
| 103 | struct key_t key = {}; |
| 104 | |
| 105 | bpf_trace_printk("traced start %d\\n", req->__data_len); |
| 106 | |
| 107 | return 0; |
| 108 | } |
| 109 | """ |
| 110 | b = BPF(text=text, debug=0) |
| 111 | fn = b.load_func("do_request", BPF.KPROBE) |
| 112 | |
Brenden Blanco | a328d23 | 2015-08-11 18:33:49 -0700 | [diff] [blame] | 113 | def test_blk_start_request(self): |
| 114 | text = """ |
| 115 | #include <linux/blkdev.h> |
| 116 | #include <uapi/linux/ptrace.h> |
| 117 | int do_request(struct pt_regs *ctx, int req) { |
| 118 | bpf_trace_printk("req ptr: 0x%x\\n", req); |
| 119 | return 0; |
| 120 | } |
| 121 | """ |
| 122 | b = BPF(text=text, debug=0) |
| 123 | fn = b.load_func("do_request", BPF.KPROBE) |
| 124 | |
Brenden Blanco | 7b9e5f1 | 2015-09-05 21:54:59 -0700 | [diff] [blame] | 125 | def test_bpf_hash(self): |
| 126 | text = """ |
| 127 | BPF_HASH(table1); |
| 128 | BPF_HASH(table2, u32); |
| 129 | BPF_HASH(table3, u32, int); |
| 130 | """ |
| 131 | b = BPF(text=text, debug=0) |
| 132 | |
Brenden Blanco | 70fa0a1 | 2015-09-15 15:46:26 -0700 | [diff] [blame] | 133 | def test_consecutive_probe_read(self): |
| 134 | text = """ |
| 135 | #include <linux/fs.h> |
| 136 | #include <linux/mount.h> |
| 137 | BPF_HASH(table1, struct super_block *); |
| 138 | int trace_entry(struct pt_regs *ctx, struct file *file) { |
| 139 | if (!file) return 0; |
| 140 | struct vfsmount *mnt = file->f_path.mnt; |
| 141 | if (mnt) { |
| 142 | struct super_block *k = mnt->mnt_sb; |
| 143 | u64 zero = 0; |
| 144 | table1.update(&k, &zero); |
| 145 | k = mnt->mnt_sb; |
| 146 | table1.update(&k, &zero); |
| 147 | } |
| 148 | |
| 149 | return 0; |
| 150 | } |
| 151 | """ |
| 152 | b = BPF(text=text, debug=0) |
| 153 | fn = b.load_func("trace_entry", BPF.KPROBE) |
| 154 | |
| 155 | def test_nested_probe_read(self): |
| 156 | text = """ |
| 157 | #include <linux/fs.h> |
| 158 | int trace_entry(struct pt_regs *ctx, struct file *file) { |
| 159 | if (!file) return 0; |
| 160 | const char *name = file->f_path.dentry->d_name.name; |
| 161 | bpf_trace_printk("%s\\n", name); |
| 162 | return 0; |
| 163 | } |
| 164 | """ |
| 165 | b = BPF(text=text, debug=0) |
| 166 | fn = b.load_func("trace_entry", BPF.KPROBE) |
| 167 | |
Brenden Blanco | 9518e74 | 2015-09-16 14:06:06 -0700 | [diff] [blame^] | 168 | def test_char_array_probe(self): |
| 169 | BPF(text="""#include <linux/blkdev.h> |
| 170 | int kprobe__blk_update_request(struct pt_regs *ctx, struct request *req) { |
| 171 | bpf_trace_printk("%s\\n", req->rq_disk->disk_name); |
| 172 | return 0; |
| 173 | }""") |
| 174 | |
Brenden Blanco | 561dafc | 2015-06-29 11:09:00 -0700 | [diff] [blame] | 175 | if __name__ == "__main__": |
| 176 | main() |