diff options
Diffstat (limited to 'samples')
29 files changed, 1260 insertions, 155 deletions
diff --git a/samples/Kconfig b/samples/Kconfig index ccc50beaf17b..85c405fcccb0 100644 --- a/samples/Kconfig +++ b/samples/Kconfig | |||
@@ -11,6 +11,13 @@ config SAMPLE_TRACE_EVENTS | |||
11 | help | 11 | help |
12 | This build trace event example modules. | 12 | This build trace event example modules. |
13 | 13 | ||
14 | config SAMPLE_TRACE_PRINTK | ||
15 | tristate "Build trace_printk module - tests various trace_printk formats" | ||
16 | depends on EVENT_TRACING && m | ||
17 | help | ||
18 | This builds a module that calls trace_printk() and can be used to | ||
19 | test various trace_printk() calls from a module. | ||
20 | |||
14 | config SAMPLE_KOBJECT | 21 | config SAMPLE_KOBJECT |
15 | tristate "Build kobject examples -- loadable modules only" | 22 | tristate "Build kobject examples -- loadable modules only" |
16 | depends on m | 23 | depends on m |
diff --git a/samples/Makefile b/samples/Makefile index 2e3b523d7097..1a20169d85ac 100644 --- a/samples/Makefile +++ b/samples/Makefile | |||
@@ -2,4 +2,4 @@ | |||
2 | 2 | ||
3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ | 3 | obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \ |
4 | hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ | 4 | hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \ |
5 | configfs/ connector/ v4l/ | 5 | configfs/ connector/ v4l/ trace_printk/ |
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 0bf2478cb7df..90ebf7d35c07 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile | |||
@@ -14,12 +14,16 @@ hostprogs-y += tracex3 | |||
14 | hostprogs-y += tracex4 | 14 | hostprogs-y += tracex4 |
15 | hostprogs-y += tracex5 | 15 | hostprogs-y += tracex5 |
16 | hostprogs-y += tracex6 | 16 | hostprogs-y += tracex6 |
17 | hostprogs-y += test_probe_write_user | ||
17 | hostprogs-y += trace_output | 18 | hostprogs-y += trace_output |
18 | hostprogs-y += lathist | 19 | hostprogs-y += lathist |
19 | hostprogs-y += offwaketime | 20 | hostprogs-y += offwaketime |
20 | hostprogs-y += spintest | 21 | hostprogs-y += spintest |
21 | hostprogs-y += map_perf_test | 22 | hostprogs-y += map_perf_test |
22 | hostprogs-y += test_overhead | 23 | hostprogs-y += test_overhead |
24 | hostprogs-y += test_cgrp2_array_pin | ||
25 | hostprogs-y += xdp1 | ||
26 | hostprogs-y += xdp2 | ||
23 | 27 | ||
24 | test_verifier-objs := test_verifier.o libbpf.o | 28 | test_verifier-objs := test_verifier.o libbpf.o |
25 | test_maps-objs := test_maps.o libbpf.o | 29 | test_maps-objs := test_maps.o libbpf.o |
@@ -34,12 +38,17 @@ tracex3-objs := bpf_load.o libbpf.o tracex3_user.o | |||
34 | tracex4-objs := bpf_load.o libbpf.o tracex4_user.o | 38 | tracex4-objs := bpf_load.o libbpf.o tracex4_user.o |
35 | tracex5-objs := bpf_load.o libbpf.o tracex5_user.o | 39 | tracex5-objs := bpf_load.o libbpf.o tracex5_user.o |
36 | tracex6-objs := bpf_load.o libbpf.o tracex6_user.o | 40 | tracex6-objs := bpf_load.o libbpf.o tracex6_user.o |
41 | test_probe_write_user-objs := bpf_load.o libbpf.o test_probe_write_user_user.o | ||
37 | trace_output-objs := bpf_load.o libbpf.o trace_output_user.o | 42 | trace_output-objs := bpf_load.o libbpf.o trace_output_user.o |
38 | lathist-objs := bpf_load.o libbpf.o lathist_user.o | 43 | lathist-objs := bpf_load.o libbpf.o lathist_user.o |
39 | offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o | 44 | offwaketime-objs := bpf_load.o libbpf.o offwaketime_user.o |
40 | spintest-objs := bpf_load.o libbpf.o spintest_user.o | 45 | spintest-objs := bpf_load.o libbpf.o spintest_user.o |
41 | map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o | 46 | map_perf_test-objs := bpf_load.o libbpf.o map_perf_test_user.o |
42 | test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o | 47 | test_overhead-objs := bpf_load.o libbpf.o test_overhead_user.o |
48 | test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o | ||
49 | xdp1-objs := bpf_load.o libbpf.o xdp1_user.o | ||
50 | # reuse xdp1 source intentionally | ||
51 | xdp2-objs := bpf_load.o libbpf.o xdp1_user.o | ||
43 | 52 | ||
44 | # Tell kbuild to always build the programs | 53 | # Tell kbuild to always build the programs |
45 | always := $(hostprogs-y) | 54 | always := $(hostprogs-y) |
@@ -52,6 +61,7 @@ always += tracex3_kern.o | |||
52 | always += tracex4_kern.o | 61 | always += tracex4_kern.o |
53 | always += tracex5_kern.o | 62 | always += tracex5_kern.o |
54 | always += tracex6_kern.o | 63 | always += tracex6_kern.o |
64 | always += test_probe_write_user_kern.o | ||
55 | always += trace_output_kern.o | 65 | always += trace_output_kern.o |
56 | always += tcbpf1_kern.o | 66 | always += tcbpf1_kern.o |
57 | always += lathist_kern.o | 67 | always += lathist_kern.o |
@@ -61,6 +71,9 @@ always += map_perf_test_kern.o | |||
61 | always += test_overhead_tp_kern.o | 71 | always += test_overhead_tp_kern.o |
62 | always += test_overhead_kprobe_kern.o | 72 | always += test_overhead_kprobe_kern.o |
63 | always += parse_varlen.o parse_simple.o parse_ldabs.o | 73 | always += parse_varlen.o parse_simple.o parse_ldabs.o |
74 | always += test_cgrp2_tc_kern.o | ||
75 | always += xdp1_kern.o | ||
76 | always += xdp2_kern.o | ||
64 | 77 | ||
65 | HOSTCFLAGS += -I$(objtree)/usr/include | 78 | HOSTCFLAGS += -I$(objtree)/usr/include |
66 | 79 | ||
@@ -75,12 +88,15 @@ HOSTLOADLIBES_tracex3 += -lelf | |||
75 | HOSTLOADLIBES_tracex4 += -lelf -lrt | 88 | HOSTLOADLIBES_tracex4 += -lelf -lrt |
76 | HOSTLOADLIBES_tracex5 += -lelf | 89 | HOSTLOADLIBES_tracex5 += -lelf |
77 | HOSTLOADLIBES_tracex6 += -lelf | 90 | HOSTLOADLIBES_tracex6 += -lelf |
91 | HOSTLOADLIBES_test_probe_write_user += -lelf | ||
78 | HOSTLOADLIBES_trace_output += -lelf -lrt | 92 | HOSTLOADLIBES_trace_output += -lelf -lrt |
79 | HOSTLOADLIBES_lathist += -lelf | 93 | HOSTLOADLIBES_lathist += -lelf |
80 | HOSTLOADLIBES_offwaketime += -lelf | 94 | HOSTLOADLIBES_offwaketime += -lelf |
81 | HOSTLOADLIBES_spintest += -lelf | 95 | HOSTLOADLIBES_spintest += -lelf |
82 | HOSTLOADLIBES_map_perf_test += -lelf -lrt | 96 | HOSTLOADLIBES_map_perf_test += -lelf -lrt |
83 | HOSTLOADLIBES_test_overhead += -lelf -lrt | 97 | HOSTLOADLIBES_test_overhead += -lelf -lrt |
98 | HOSTLOADLIBES_xdp1 += -lelf | ||
99 | HOSTLOADLIBES_xdp2 += -lelf | ||
84 | 100 | ||
85 | # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: | 101 | # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: |
86 | # make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang | 102 | # make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang |
diff --git a/samples/bpf/bpf_helpers.h b/samples/bpf/bpf_helpers.h index 7904a2a493de..217c8d507f2e 100644 --- a/samples/bpf/bpf_helpers.h +++ b/samples/bpf/bpf_helpers.h | |||
@@ -41,6 +41,8 @@ static int (*bpf_perf_event_output)(void *ctx, void *map, int index, void *data, | |||
41 | (void *) BPF_FUNC_perf_event_output; | 41 | (void *) BPF_FUNC_perf_event_output; |
42 | static int (*bpf_get_stackid)(void *ctx, void *map, int flags) = | 42 | static int (*bpf_get_stackid)(void *ctx, void *map, int flags) = |
43 | (void *) BPF_FUNC_get_stackid; | 43 | (void *) BPF_FUNC_get_stackid; |
44 | static int (*bpf_probe_write_user)(void *dst, void *src, int size) = | ||
45 | (void *) BPF_FUNC_probe_write_user; | ||
44 | 46 | ||
45 | /* llvm builtin functions that eBPF C program may use to | 47 | /* llvm builtin functions that eBPF C program may use to |
46 | * emit BPF_LD_ABS and BPF_LD_IND instructions | 48 | * emit BPF_LD_ABS and BPF_LD_IND instructions |
@@ -70,6 +72,8 @@ static int (*bpf_l3_csum_replace)(void *ctx, int off, int from, int to, int flag | |||
70 | (void *) BPF_FUNC_l3_csum_replace; | 72 | (void *) BPF_FUNC_l3_csum_replace; |
71 | static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flags) = | 73 | static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flags) = |
72 | (void *) BPF_FUNC_l4_csum_replace; | 74 | (void *) BPF_FUNC_l4_csum_replace; |
75 | static int (*bpf_skb_in_cgroup)(void *ctx, void *map, int index) = | ||
76 | (void *) BPF_FUNC_skb_in_cgroup; | ||
73 | 77 | ||
74 | #if defined(__x86_64__) | 78 | #if defined(__x86_64__) |
75 | 79 | ||
diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c index 022af71c2bb5..0cfda2320320 100644 --- a/samples/bpf/bpf_load.c +++ b/samples/bpf/bpf_load.c | |||
@@ -50,6 +50,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) | |||
50 | bool is_kprobe = strncmp(event, "kprobe/", 7) == 0; | 50 | bool is_kprobe = strncmp(event, "kprobe/", 7) == 0; |
51 | bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0; | 51 | bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0; |
52 | bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0; | 52 | bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0; |
53 | bool is_xdp = strncmp(event, "xdp", 3) == 0; | ||
53 | enum bpf_prog_type prog_type; | 54 | enum bpf_prog_type prog_type; |
54 | char buf[256]; | 55 | char buf[256]; |
55 | int fd, efd, err, id; | 56 | int fd, efd, err, id; |
@@ -66,6 +67,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) | |||
66 | prog_type = BPF_PROG_TYPE_KPROBE; | 67 | prog_type = BPF_PROG_TYPE_KPROBE; |
67 | } else if (is_tracepoint) { | 68 | } else if (is_tracepoint) { |
68 | prog_type = BPF_PROG_TYPE_TRACEPOINT; | 69 | prog_type = BPF_PROG_TYPE_TRACEPOINT; |
70 | } else if (is_xdp) { | ||
71 | prog_type = BPF_PROG_TYPE_XDP; | ||
69 | } else { | 72 | } else { |
70 | printf("Unknown event '%s'\n", event); | 73 | printf("Unknown event '%s'\n", event); |
71 | return -1; | 74 | return -1; |
@@ -79,6 +82,9 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) | |||
79 | 82 | ||
80 | prog_fd[prog_cnt++] = fd; | 83 | prog_fd[prog_cnt++] = fd; |
81 | 84 | ||
85 | if (is_xdp) | ||
86 | return 0; | ||
87 | |||
82 | if (is_socket) { | 88 | if (is_socket) { |
83 | event += 6; | 89 | event += 6; |
84 | if (*event != '/') | 90 | if (*event != '/') |
@@ -319,6 +325,7 @@ int load_bpf_file(char *path) | |||
319 | if (memcmp(shname_prog, "kprobe/", 7) == 0 || | 325 | if (memcmp(shname_prog, "kprobe/", 7) == 0 || |
320 | memcmp(shname_prog, "kretprobe/", 10) == 0 || | 326 | memcmp(shname_prog, "kretprobe/", 10) == 0 || |
321 | memcmp(shname_prog, "tracepoint/", 11) == 0 || | 327 | memcmp(shname_prog, "tracepoint/", 11) == 0 || |
328 | memcmp(shname_prog, "xdp", 3) == 0 || | ||
322 | memcmp(shname_prog, "socket", 6) == 0) | 329 | memcmp(shname_prog, "socket", 6) == 0) |
323 | load_and_attach(shname_prog, insns, data_prog->d_size); | 330 | load_and_attach(shname_prog, insns, data_prog->d_size); |
324 | } | 331 | } |
@@ -336,6 +343,7 @@ int load_bpf_file(char *path) | |||
336 | if (memcmp(shname, "kprobe/", 7) == 0 || | 343 | if (memcmp(shname, "kprobe/", 7) == 0 || |
337 | memcmp(shname, "kretprobe/", 10) == 0 || | 344 | memcmp(shname, "kretprobe/", 10) == 0 || |
338 | memcmp(shname, "tracepoint/", 11) == 0 || | 345 | memcmp(shname, "tracepoint/", 11) == 0 || |
346 | memcmp(shname, "xdp", 3) == 0 || | ||
339 | memcmp(shname, "socket", 6) == 0) | 347 | memcmp(shname, "socket", 6) == 0) |
340 | load_and_attach(shname, data->d_buf, data->d_size); | 348 | load_and_attach(shname, data->d_buf, data->d_size); |
341 | } | 349 | } |
diff --git a/samples/bpf/sockex2_user.c b/samples/bpf/sockex2_user.c index 29a276d766fc..8a4085c2d117 100644 --- a/samples/bpf/sockex2_user.c +++ b/samples/bpf/sockex2_user.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "bpf_load.h" | 5 | #include "bpf_load.h" |
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <arpa/inet.h> | 7 | #include <arpa/inet.h> |
8 | #include <sys/resource.h> | ||
8 | 9 | ||
9 | struct pair { | 10 | struct pair { |
10 | __u64 packets; | 11 | __u64 packets; |
@@ -13,11 +14,13 @@ struct pair { | |||
13 | 14 | ||
14 | int main(int ac, char **argv) | 15 | int main(int ac, char **argv) |
15 | { | 16 | { |
17 | struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; | ||
16 | char filename[256]; | 18 | char filename[256]; |
17 | FILE *f; | 19 | FILE *f; |
18 | int i, sock; | 20 | int i, sock; |
19 | 21 | ||
20 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); | 22 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); |
23 | setrlimit(RLIMIT_MEMLOCK, &r); | ||
21 | 24 | ||
22 | if (load_bpf_file(filename)) { | 25 | if (load_bpf_file(filename)) { |
23 | printf("%s", bpf_log_buf); | 26 | printf("%s", bpf_log_buf); |
diff --git a/samples/bpf/sockex3_user.c b/samples/bpf/sockex3_user.c index 2617772d060d..d4184ab5f3ac 100644 --- a/samples/bpf/sockex3_user.c +++ b/samples/bpf/sockex3_user.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "bpf_load.h" | 5 | #include "bpf_load.h" |
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | #include <arpa/inet.h> | 7 | #include <arpa/inet.h> |
8 | #include <sys/resource.h> | ||
8 | 9 | ||
9 | struct flow_keys { | 10 | struct flow_keys { |
10 | __be32 src; | 11 | __be32 src; |
@@ -23,11 +24,13 @@ struct pair { | |||
23 | 24 | ||
24 | int main(int argc, char **argv) | 25 | int main(int argc, char **argv) |
25 | { | 26 | { |
27 | struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; | ||
26 | char filename[256]; | 28 | char filename[256]; |
27 | FILE *f; | 29 | FILE *f; |
28 | int i, sock; | 30 | int i, sock; |
29 | 31 | ||
30 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); | 32 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); |
33 | setrlimit(RLIMIT_MEMLOCK, &r); | ||
31 | 34 | ||
32 | if (load_bpf_file(filename)) { | 35 | if (load_bpf_file(filename)) { |
33 | printf("%s", bpf_log_buf); | 36 | printf("%s", bpf_log_buf); |
diff --git a/samples/bpf/test_cgrp2_array_pin.c b/samples/bpf/test_cgrp2_array_pin.c new file mode 100644 index 000000000000..70e86f7be69d --- /dev/null +++ b/samples/bpf/test_cgrp2_array_pin.c | |||
@@ -0,0 +1,109 @@ | |||
1 | /* Copyright (c) 2016 Facebook | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of version 2 of the GNU General Public | ||
5 | * License as published by the Free Software Foundation. | ||
6 | */ | ||
7 | #include <linux/unistd.h> | ||
8 | #include <linux/bpf.h> | ||
9 | |||
10 | #include <stdio.h> | ||
11 | #include <stdint.h> | ||
12 | #include <unistd.h> | ||
13 | #include <string.h> | ||
14 | #include <errno.h> | ||
15 | #include <fcntl.h> | ||
16 | |||
17 | #include "libbpf.h" | ||
18 | |||
19 | static void usage(void) | ||
20 | { | ||
21 | printf("Usage: test_cgrp2_array_pin [...]\n"); | ||
22 | printf(" -F <file> File to pin an BPF cgroup array\n"); | ||
23 | printf(" -U <file> Update an already pinned BPF cgroup array\n"); | ||
24 | printf(" -v <value> Full path of the cgroup2\n"); | ||
25 | printf(" -h Display this help\n"); | ||
26 | } | ||
27 | |||
28 | int main(int argc, char **argv) | ||
29 | { | ||
30 | const char *pinned_file = NULL, *cg2 = NULL; | ||
31 | int create_array = 1; | ||
32 | int array_key = 0; | ||
33 | int array_fd = -1; | ||
34 | int cg2_fd = -1; | ||
35 | int ret = -1; | ||
36 | int opt; | ||
37 | |||
38 | while ((opt = getopt(argc, argv, "F:U:v:")) != -1) { | ||
39 | switch (opt) { | ||
40 | /* General args */ | ||
41 | case 'F': | ||
42 | pinned_file = optarg; | ||
43 | break; | ||
44 | case 'U': | ||
45 | pinned_file = optarg; | ||
46 | create_array = 0; | ||
47 | break; | ||
48 | case 'v': | ||
49 | cg2 = optarg; | ||
50 | break; | ||
51 | default: | ||
52 | usage(); | ||
53 | goto out; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | if (!cg2 || !pinned_file) { | ||
58 | usage(); | ||
59 | goto out; | ||
60 | } | ||
61 | |||
62 | cg2_fd = open(cg2, O_RDONLY); | ||
63 | if (cg2_fd < 0) { | ||
64 | fprintf(stderr, "open(%s,...): %s(%d)\n", | ||
65 | cg2, strerror(errno), errno); | ||
66 | goto out; | ||
67 | } | ||
68 | |||
69 | if (create_array) { | ||
70 | array_fd = bpf_create_map(BPF_MAP_TYPE_CGROUP_ARRAY, | ||
71 | sizeof(uint32_t), sizeof(uint32_t), | ||
72 | 1, 0); | ||
73 | if (array_fd < 0) { | ||
74 | fprintf(stderr, | ||
75 | "bpf_create_map(BPF_MAP_TYPE_CGROUP_ARRAY,...): %s(%d)\n", | ||
76 | strerror(errno), errno); | ||
77 | goto out; | ||
78 | } | ||
79 | } else { | ||
80 | array_fd = bpf_obj_get(pinned_file); | ||
81 | if (array_fd < 0) { | ||
82 | fprintf(stderr, "bpf_obj_get(%s): %s(%d)\n", | ||
83 | pinned_file, strerror(errno), errno); | ||
84 | goto out; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | ret = bpf_update_elem(array_fd, &array_key, &cg2_fd, 0); | ||
89 | if (ret) { | ||
90 | perror("bpf_update_elem"); | ||
91 | goto out; | ||
92 | } | ||
93 | |||
94 | if (create_array) { | ||
95 | ret = bpf_obj_pin(array_fd, pinned_file); | ||
96 | if (ret) { | ||
97 | fprintf(stderr, "bpf_obj_pin(..., %s): %s(%d)\n", | ||
98 | pinned_file, strerror(errno), errno); | ||
99 | goto out; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | out: | ||
104 | if (array_fd != -1) | ||
105 | close(array_fd); | ||
106 | if (cg2_fd != -1) | ||
107 | close(cg2_fd); | ||
108 | return ret; | ||
109 | } | ||
diff --git a/samples/bpf/test_cgrp2_tc.sh b/samples/bpf/test_cgrp2_tc.sh new file mode 100755 index 000000000000..0b119eeaf85c --- /dev/null +++ b/samples/bpf/test_cgrp2_tc.sh | |||
@@ -0,0 +1,184 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | MY_DIR=$(dirname $0) | ||
4 | # Details on the bpf prog | ||
5 | BPF_CGRP2_ARRAY_NAME='test_cgrp2_array_pin' | ||
6 | BPF_PROG="$MY_DIR/test_cgrp2_tc_kern.o" | ||
7 | BPF_SECTION='filter' | ||
8 | |||
9 | [ -z "$TC" ] && TC='tc' | ||
10 | [ -z "$IP" ] && IP='ip' | ||
11 | |||
12 | # Names of the veth interface, net namespace...etc. | ||
13 | HOST_IFC='ve' | ||
14 | NS_IFC='vens' | ||
15 | NS='ns' | ||
16 | |||
17 | find_mnt() { | ||
18 | cat /proc/mounts | \ | ||
19 | awk '{ if ($3 == "'$1'" && mnt == "") { mnt = $2 }} END { print mnt }' | ||
20 | } | ||
21 | |||
22 | # Init cgroup2 vars | ||
23 | init_cgrp2_vars() { | ||
24 | CGRP2_ROOT=$(find_mnt cgroup2) | ||
25 | if [ -z "$CGRP2_ROOT" ] | ||
26 | then | ||
27 | CGRP2_ROOT='/mnt/cgroup2' | ||
28 | MOUNT_CGRP2="yes" | ||
29 | fi | ||
30 | CGRP2_TC="$CGRP2_ROOT/tc" | ||
31 | CGRP2_TC_LEAF="$CGRP2_TC/leaf" | ||
32 | } | ||
33 | |||
34 | # Init bpf fs vars | ||
35 | init_bpf_fs_vars() { | ||
36 | local bpf_fs_root=$(find_mnt bpf) | ||
37 | [ -n "$bpf_fs_root" ] || return -1 | ||
38 | BPF_FS_TC_SHARE="$bpf_fs_root/tc/globals" | ||
39 | } | ||
40 | |||
41 | setup_cgrp2() { | ||
42 | case $1 in | ||
43 | start) | ||
44 | if [ "$MOUNT_CGRP2" == 'yes' ] | ||
45 | then | ||
46 | [ -d $CGRP2_ROOT ] || mkdir -p $CGRP2_ROOT | ||
47 | mount -t cgroup2 none $CGRP2_ROOT || return $? | ||
48 | fi | ||
49 | mkdir -p $CGRP2_TC_LEAF | ||
50 | ;; | ||
51 | *) | ||
52 | rmdir $CGRP2_TC_LEAF && rmdir $CGRP2_TC | ||
53 | [ "$MOUNT_CGRP2" == 'yes' ] && umount $CGRP2_ROOT | ||
54 | ;; | ||
55 | esac | ||
56 | } | ||
57 | |||
58 | setup_bpf_cgrp2_array() { | ||
59 | local bpf_cgrp2_array="$BPF_FS_TC_SHARE/$BPF_CGRP2_ARRAY_NAME" | ||
60 | case $1 in | ||
61 | start) | ||
62 | $MY_DIR/test_cgrp2_array_pin -U $bpf_cgrp2_array -v $CGRP2_TC | ||
63 | ;; | ||
64 | *) | ||
65 | [ -d "$BPF_FS_TC_SHARE" ] && rm -f $bpf_cgrp2_array | ||
66 | ;; | ||
67 | esac | ||
68 | } | ||
69 | |||
70 | setup_net() { | ||
71 | case $1 in | ||
72 | start) | ||
73 | $IP link add $HOST_IFC type veth peer name $NS_IFC || return $? | ||
74 | $IP link set dev $HOST_IFC up || return $? | ||
75 | sysctl -q net.ipv6.conf.$HOST_IFC.accept_dad=0 | ||
76 | |||
77 | $IP netns add ns || return $? | ||
78 | $IP link set dev $NS_IFC netns ns || return $? | ||
79 | $IP -n $NS link set dev $NS_IFC up || return $? | ||
80 | $IP netns exec $NS sysctl -q net.ipv6.conf.$NS_IFC.accept_dad=0 | ||
81 | $TC qdisc add dev $HOST_IFC clsact || return $? | ||
82 | $TC filter add dev $HOST_IFC egress bpf da obj $BPF_PROG sec $BPF_SECTION || return $? | ||
83 | ;; | ||
84 | *) | ||
85 | $IP netns del $NS | ||
86 | $IP link del $HOST_IFC | ||
87 | ;; | ||
88 | esac | ||
89 | } | ||
90 | |||
91 | run_in_cgrp() { | ||
92 | # Fork another bash and move it under the specified cgroup. | ||
93 | # It makes the cgroup cleanup easier at the end of the test. | ||
94 | cmd='echo $$ > ' | ||
95 | cmd="$cmd $1/cgroup.procs; exec $2" | ||
96 | bash -c "$cmd" | ||
97 | } | ||
98 | |||
99 | do_test() { | ||
100 | run_in_cgrp $CGRP2_TC_LEAF "ping -6 -c3 ff02::1%$HOST_IFC >& /dev/null" | ||
101 | local dropped=$($TC -s qdisc show dev $HOST_IFC | tail -3 | \ | ||
102 | awk '/drop/{print substr($7, 0, index($7, ",")-1)}') | ||
103 | if [[ $dropped -eq 0 ]] | ||
104 | then | ||
105 | echo "FAIL" | ||
106 | return 1 | ||
107 | else | ||
108 | echo "Successfully filtered $dropped packets" | ||
109 | return 0 | ||
110 | fi | ||
111 | } | ||
112 | |||
113 | do_exit() { | ||
114 | if [ "$DEBUG" == "yes" ] && [ "$MODE" != 'cleanuponly' ] | ||
115 | then | ||
116 | echo "------ DEBUG ------" | ||
117 | echo "mount: "; mount | egrep '(cgroup2|bpf)'; echo | ||
118 | echo "$CGRP2_TC_LEAF: "; ls -l $CGRP2_TC_LEAF; echo | ||
119 | if [ -d "$BPF_FS_TC_SHARE" ] | ||
120 | then | ||
121 | echo "$BPF_FS_TC_SHARE: "; ls -l $BPF_FS_TC_SHARE; echo | ||
122 | fi | ||
123 | echo "Host net:" | ||
124 | $IP netns | ||
125 | $IP link show dev $HOST_IFC | ||
126 | $IP -6 a show dev $HOST_IFC | ||
127 | $TC -s qdisc show dev $HOST_IFC | ||
128 | echo | ||
129 | echo "$NS net:" | ||
130 | $IP -n $NS link show dev $NS_IFC | ||
131 | $IP -n $NS -6 link show dev $NS_IFC | ||
132 | echo "------ DEBUG ------" | ||
133 | echo | ||
134 | fi | ||
135 | |||
136 | if [ "$MODE" != 'nocleanup' ] | ||
137 | then | ||
138 | setup_net stop | ||
139 | setup_bpf_cgrp2_array stop | ||
140 | setup_cgrp2 stop | ||
141 | fi | ||
142 | } | ||
143 | |||
144 | init_cgrp2_vars | ||
145 | init_bpf_fs_vars | ||
146 | |||
147 | while [[ $# -ge 1 ]] | ||
148 | do | ||
149 | a="$1" | ||
150 | case $a in | ||
151 | debug) | ||
152 | DEBUG='yes' | ||
153 | shift 1 | ||
154 | ;; | ||
155 | cleanup-only) | ||
156 | MODE='cleanuponly' | ||
157 | shift 1 | ||
158 | ;; | ||
159 | no-cleanup) | ||
160 | MODE='nocleanup' | ||
161 | shift 1 | ||
162 | ;; | ||
163 | *) | ||
164 | echo "test_cgrp2_tc [debug] [cleanup-only | no-cleanup]" | ||
165 | echo " debug: Print cgrp and network setup details at the end of the test" | ||
166 | echo " cleanup-only: Try to cleanup things from last test. No test will be run" | ||
167 | echo " no-cleanup: Run the test but don't do cleanup at the end" | ||
168 | echo "[Note: If no arg is given, it will run the test and do cleanup at the end]" | ||
169 | echo | ||
170 | exit -1 | ||
171 | ;; | ||
172 | esac | ||
173 | done | ||
174 | |||
175 | trap do_exit 0 | ||
176 | |||
177 | [ "$MODE" == 'cleanuponly' ] && exit | ||
178 | |||
179 | setup_cgrp2 start || exit $? | ||
180 | setup_net start || exit $? | ||
181 | init_bpf_fs_vars || exit $? | ||
182 | setup_bpf_cgrp2_array start || exit $? | ||
183 | do_test | ||
184 | echo | ||
diff --git a/samples/bpf/test_cgrp2_tc_kern.c b/samples/bpf/test_cgrp2_tc_kern.c new file mode 100644 index 000000000000..2732c37c8d5b --- /dev/null +++ b/samples/bpf/test_cgrp2_tc_kern.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* Copyright (c) 2016 Facebook | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of version 2 of the GNU General Public | ||
5 | * License as published by the Free Software Foundation. | ||
6 | */ | ||
7 | #include <uapi/linux/if_ether.h> | ||
8 | #include <uapi/linux/in6.h> | ||
9 | #include <uapi/linux/ipv6.h> | ||
10 | #include <uapi/linux/pkt_cls.h> | ||
11 | #include <uapi/linux/bpf.h> | ||
12 | #include "bpf_helpers.h" | ||
13 | |||
14 | /* copy of 'struct ethhdr' without __packed */ | ||
15 | struct eth_hdr { | ||
16 | unsigned char h_dest[ETH_ALEN]; | ||
17 | unsigned char h_source[ETH_ALEN]; | ||
18 | unsigned short h_proto; | ||
19 | }; | ||
20 | |||
21 | #define PIN_GLOBAL_NS 2 | ||
22 | struct bpf_elf_map { | ||
23 | __u32 type; | ||
24 | __u32 size_key; | ||
25 | __u32 size_value; | ||
26 | __u32 max_elem; | ||
27 | __u32 flags; | ||
28 | __u32 id; | ||
29 | __u32 pinning; | ||
30 | }; | ||
31 | |||
32 | struct bpf_elf_map SEC("maps") test_cgrp2_array_pin = { | ||
33 | .type = BPF_MAP_TYPE_CGROUP_ARRAY, | ||
34 | .size_key = sizeof(uint32_t), | ||
35 | .size_value = sizeof(uint32_t), | ||
36 | .pinning = PIN_GLOBAL_NS, | ||
37 | .max_elem = 1, | ||
38 | }; | ||
39 | |||
40 | SEC("filter") | ||
41 | int handle_egress(struct __sk_buff *skb) | ||
42 | { | ||
43 | void *data = (void *)(long)skb->data; | ||
44 | struct eth_hdr *eth = data; | ||
45 | struct ipv6hdr *ip6h = data + sizeof(*eth); | ||
46 | void *data_end = (void *)(long)skb->data_end; | ||
47 | char dont_care_msg[] = "dont care %04x %d\n"; | ||
48 | char pass_msg[] = "pass\n"; | ||
49 | char reject_msg[] = "reject\n"; | ||
50 | |||
51 | /* single length check */ | ||
52 | if (data + sizeof(*eth) + sizeof(*ip6h) > data_end) | ||
53 | return TC_ACT_OK; | ||
54 | |||
55 | if (eth->h_proto != htons(ETH_P_IPV6) || | ||
56 | ip6h->nexthdr != IPPROTO_ICMPV6) { | ||
57 | bpf_trace_printk(dont_care_msg, sizeof(dont_care_msg), | ||
58 | eth->h_proto, ip6h->nexthdr); | ||
59 | return TC_ACT_OK; | ||
60 | } else if (bpf_skb_in_cgroup(skb, &test_cgrp2_array_pin, 0) != 1) { | ||
61 | bpf_trace_printk(pass_msg, sizeof(pass_msg)); | ||
62 | return TC_ACT_OK; | ||
63 | } else { | ||
64 | bpf_trace_printk(reject_msg, sizeof(reject_msg)); | ||
65 | return TC_ACT_SHOT; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | char _license[] SEC("license") = "GPL"; | ||
diff --git a/samples/bpf/test_probe_write_user_kern.c b/samples/bpf/test_probe_write_user_kern.c new file mode 100644 index 000000000000..3a677c807044 --- /dev/null +++ b/samples/bpf/test_probe_write_user_kern.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* Copyright (c) 2016 Sargun Dhillon <sargun@sargun.me> | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of version 2 of the GNU General Public | ||
5 | * License as published by the Free Software Foundation. | ||
6 | */ | ||
7 | #include <linux/skbuff.h> | ||
8 | #include <linux/netdevice.h> | ||
9 | #include <uapi/linux/bpf.h> | ||
10 | #include <linux/version.h> | ||
11 | #include "bpf_helpers.h" | ||
12 | |||
13 | struct bpf_map_def SEC("maps") dnat_map = { | ||
14 | .type = BPF_MAP_TYPE_HASH, | ||
15 | .key_size = sizeof(struct sockaddr_in), | ||
16 | .value_size = sizeof(struct sockaddr_in), | ||
17 | .max_entries = 256, | ||
18 | }; | ||
19 | |||
20 | /* kprobe is NOT a stable ABI | ||
21 | * kernel functions can be removed, renamed or completely change semantics. | ||
22 | * Number of arguments and their positions can change, etc. | ||
23 | * In such case this bpf+kprobe example will no longer be meaningful | ||
24 | * | ||
25 | * This example sits on a syscall, and the syscall ABI is relatively stable | ||
26 | * of course, across platforms, and over time, the ABI may change. | ||
27 | */ | ||
28 | SEC("kprobe/sys_connect") | ||
29 | int bpf_prog1(struct pt_regs *ctx) | ||
30 | { | ||
31 | struct sockaddr_in new_addr, orig_addr = {}; | ||
32 | struct sockaddr_in *mapped_addr; | ||
33 | void *sockaddr_arg = (void *)PT_REGS_PARM2(ctx); | ||
34 | int sockaddr_len = (int)PT_REGS_PARM3(ctx); | ||
35 | |||
36 | if (sockaddr_len > sizeof(orig_addr)) | ||
37 | return 0; | ||
38 | |||
39 | if (bpf_probe_read(&orig_addr, sizeof(orig_addr), sockaddr_arg) != 0) | ||
40 | return 0; | ||
41 | |||
42 | mapped_addr = bpf_map_lookup_elem(&dnat_map, &orig_addr); | ||
43 | if (mapped_addr != NULL) { | ||
44 | memcpy(&new_addr, mapped_addr, sizeof(new_addr)); | ||
45 | bpf_probe_write_user(sockaddr_arg, &new_addr, | ||
46 | sizeof(new_addr)); | ||
47 | } | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | char _license[] SEC("license") = "GPL"; | ||
52 | u32 _version SEC("version") = LINUX_VERSION_CODE; | ||
diff --git a/samples/bpf/test_probe_write_user_user.c b/samples/bpf/test_probe_write_user_user.c new file mode 100644 index 000000000000..a44bf347bedd --- /dev/null +++ b/samples/bpf/test_probe_write_user_user.c | |||
@@ -0,0 +1,78 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <assert.h> | ||
3 | #include <linux/bpf.h> | ||
4 | #include <unistd.h> | ||
5 | #include "libbpf.h" | ||
6 | #include "bpf_load.h" | ||
7 | #include <sys/socket.h> | ||
8 | #include <string.h> | ||
9 | #include <netinet/in.h> | ||
10 | #include <arpa/inet.h> | ||
11 | |||
12 | int main(int ac, char **argv) | ||
13 | { | ||
14 | int serverfd, serverconnfd, clientfd; | ||
15 | socklen_t sockaddr_len; | ||
16 | struct sockaddr serv_addr, mapped_addr, tmp_addr; | ||
17 | struct sockaddr_in *serv_addr_in, *mapped_addr_in, *tmp_addr_in; | ||
18 | char filename[256]; | ||
19 | char *ip; | ||
20 | |||
21 | serv_addr_in = (struct sockaddr_in *)&serv_addr; | ||
22 | mapped_addr_in = (struct sockaddr_in *)&mapped_addr; | ||
23 | tmp_addr_in = (struct sockaddr_in *)&tmp_addr; | ||
24 | |||
25 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); | ||
26 | |||
27 | if (load_bpf_file(filename)) { | ||
28 | printf("%s", bpf_log_buf); | ||
29 | return 1; | ||
30 | } | ||
31 | |||
32 | assert((serverfd = socket(AF_INET, SOCK_STREAM, 0)) > 0); | ||
33 | assert((clientfd = socket(AF_INET, SOCK_STREAM, 0)) > 0); | ||
34 | |||
35 | /* Bind server to ephemeral port on lo */ | ||
36 | memset(&serv_addr, 0, sizeof(serv_addr)); | ||
37 | serv_addr_in->sin_family = AF_INET; | ||
38 | serv_addr_in->sin_port = 0; | ||
39 | serv_addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK); | ||
40 | |||
41 | assert(bind(serverfd, &serv_addr, sizeof(serv_addr)) == 0); | ||
42 | |||
43 | sockaddr_len = sizeof(serv_addr); | ||
44 | assert(getsockname(serverfd, &serv_addr, &sockaddr_len) == 0); | ||
45 | ip = inet_ntoa(serv_addr_in->sin_addr); | ||
46 | printf("Server bound to: %s:%d\n", ip, ntohs(serv_addr_in->sin_port)); | ||
47 | |||
48 | memset(&mapped_addr, 0, sizeof(mapped_addr)); | ||
49 | mapped_addr_in->sin_family = AF_INET; | ||
50 | mapped_addr_in->sin_port = htons(5555); | ||
51 | mapped_addr_in->sin_addr.s_addr = inet_addr("255.255.255.255"); | ||
52 | |||
53 | assert(!bpf_update_elem(map_fd[0], &mapped_addr, &serv_addr, BPF_ANY)); | ||
54 | |||
55 | assert(listen(serverfd, 5) == 0); | ||
56 | |||
57 | ip = inet_ntoa(mapped_addr_in->sin_addr); | ||
58 | printf("Client connecting to: %s:%d\n", | ||
59 | ip, ntohs(mapped_addr_in->sin_port)); | ||
60 | assert(connect(clientfd, &mapped_addr, sizeof(mapped_addr)) == 0); | ||
61 | |||
62 | sockaddr_len = sizeof(tmp_addr); | ||
63 | ip = inet_ntoa(tmp_addr_in->sin_addr); | ||
64 | assert((serverconnfd = accept(serverfd, &tmp_addr, &sockaddr_len)) > 0); | ||
65 | printf("Server received connection from: %s:%d\n", | ||
66 | ip, ntohs(tmp_addr_in->sin_port)); | ||
67 | |||
68 | sockaddr_len = sizeof(tmp_addr); | ||
69 | assert(getpeername(clientfd, &tmp_addr, &sockaddr_len) == 0); | ||
70 | ip = inet_ntoa(tmp_addr_in->sin_addr); | ||
71 | printf("Client's peer address: %s:%d\n", | ||
72 | ip, ntohs(tmp_addr_in->sin_port)); | ||
73 | |||
74 | /* Is the server's getsockname = the socket getpeername */ | ||
75 | assert(memcmp(&serv_addr, &tmp_addr, sizeof(struct sockaddr_in)) == 0); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
diff --git a/samples/bpf/xdp1_kern.c b/samples/bpf/xdp1_kern.c new file mode 100644 index 000000000000..219742106bfd --- /dev/null +++ b/samples/bpf/xdp1_kern.c | |||
@@ -0,0 +1,93 @@ | |||
1 | /* Copyright (c) 2016 PLUMgrid | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of version 2 of the GNU General Public | ||
5 | * License as published by the Free Software Foundation. | ||
6 | */ | ||
7 | #define KBUILD_MODNAME "foo" | ||
8 | #include <uapi/linux/bpf.h> | ||
9 | #include <linux/in.h> | ||
10 | #include <linux/if_ether.h> | ||
11 | #include <linux/if_packet.h> | ||
12 | #include <linux/if_vlan.h> | ||
13 | #include <linux/ip.h> | ||
14 | #include <linux/ipv6.h> | ||
15 | #include "bpf_helpers.h" | ||
16 | |||
17 | struct bpf_map_def SEC("maps") rxcnt = { | ||
18 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, | ||
19 | .key_size = sizeof(u32), | ||
20 | .value_size = sizeof(long), | ||
21 | .max_entries = 256, | ||
22 | }; | ||
23 | |||
24 | static int parse_ipv4(void *data, u64 nh_off, void *data_end) | ||
25 | { | ||
26 | struct iphdr *iph = data + nh_off; | ||
27 | |||
28 | if (iph + 1 > data_end) | ||
29 | return 0; | ||
30 | return iph->protocol; | ||
31 | } | ||
32 | |||
33 | static int parse_ipv6(void *data, u64 nh_off, void *data_end) | ||
34 | { | ||
35 | struct ipv6hdr *ip6h = data + nh_off; | ||
36 | |||
37 | if (ip6h + 1 > data_end) | ||
38 | return 0; | ||
39 | return ip6h->nexthdr; | ||
40 | } | ||
41 | |||
42 | SEC("xdp1") | ||
43 | int xdp_prog1(struct xdp_md *ctx) | ||
44 | { | ||
45 | void *data_end = (void *)(long)ctx->data_end; | ||
46 | void *data = (void *)(long)ctx->data; | ||
47 | struct ethhdr *eth = data; | ||
48 | int rc = XDP_DROP; | ||
49 | long *value; | ||
50 | u16 h_proto; | ||
51 | u64 nh_off; | ||
52 | u32 ipproto; | ||
53 | |||
54 | nh_off = sizeof(*eth); | ||
55 | if (data + nh_off > data_end) | ||
56 | return rc; | ||
57 | |||
58 | h_proto = eth->h_proto; | ||
59 | |||
60 | if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { | ||
61 | struct vlan_hdr *vhdr; | ||
62 | |||
63 | vhdr = data + nh_off; | ||
64 | nh_off += sizeof(struct vlan_hdr); | ||
65 | if (data + nh_off > data_end) | ||
66 | return rc; | ||
67 | h_proto = vhdr->h_vlan_encapsulated_proto; | ||
68 | } | ||
69 | if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { | ||
70 | struct vlan_hdr *vhdr; | ||
71 | |||
72 | vhdr = data + nh_off; | ||
73 | nh_off += sizeof(struct vlan_hdr); | ||
74 | if (data + nh_off > data_end) | ||
75 | return rc; | ||
76 | h_proto = vhdr->h_vlan_encapsulated_proto; | ||
77 | } | ||
78 | |||
79 | if (h_proto == htons(ETH_P_IP)) | ||
80 | ipproto = parse_ipv4(data, nh_off, data_end); | ||
81 | else if (h_proto == htons(ETH_P_IPV6)) | ||
82 | ipproto = parse_ipv6(data, nh_off, data_end); | ||
83 | else | ||
84 | ipproto = 0; | ||
85 | |||
86 | value = bpf_map_lookup_elem(&rxcnt, &ipproto); | ||
87 | if (value) | ||
88 | *value += 1; | ||
89 | |||
90 | return rc; | ||
91 | } | ||
92 | |||
93 | char _license[] SEC("license") = "GPL"; | ||
diff --git a/samples/bpf/xdp1_user.c b/samples/bpf/xdp1_user.c new file mode 100644 index 000000000000..a5e109e398a1 --- /dev/null +++ b/samples/bpf/xdp1_user.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* Copyright (c) 2016 PLUMgrid | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of version 2 of the GNU General Public | ||
5 | * License as published by the Free Software Foundation. | ||
6 | */ | ||
7 | #include <linux/bpf.h> | ||
8 | #include <linux/netlink.h> | ||
9 | #include <linux/rtnetlink.h> | ||
10 | #include <assert.h> | ||
11 | #include <errno.h> | ||
12 | #include <signal.h> | ||
13 | #include <stdio.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <string.h> | ||
16 | #include <sys/socket.h> | ||
17 | #include <unistd.h> | ||
18 | #include "bpf_load.h" | ||
19 | #include "libbpf.h" | ||
20 | |||
21 | static int set_link_xdp_fd(int ifindex, int fd) | ||
22 | { | ||
23 | struct sockaddr_nl sa; | ||
24 | int sock, seq = 0, len, ret = -1; | ||
25 | char buf[4096]; | ||
26 | struct nlattr *nla, *nla_xdp; | ||
27 | struct { | ||
28 | struct nlmsghdr nh; | ||
29 | struct ifinfomsg ifinfo; | ||
30 | char attrbuf[64]; | ||
31 | } req; | ||
32 | struct nlmsghdr *nh; | ||
33 | struct nlmsgerr *err; | ||
34 | |||
35 | memset(&sa, 0, sizeof(sa)); | ||
36 | sa.nl_family = AF_NETLINK; | ||
37 | |||
38 | sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); | ||
39 | if (sock < 0) { | ||
40 | printf("open netlink socket: %s\n", strerror(errno)); | ||
41 | return -1; | ||
42 | } | ||
43 | |||
44 | if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) { | ||
45 | printf("bind to netlink: %s\n", strerror(errno)); | ||
46 | goto cleanup; | ||
47 | } | ||
48 | |||
49 | memset(&req, 0, sizeof(req)); | ||
50 | req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); | ||
51 | req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; | ||
52 | req.nh.nlmsg_type = RTM_SETLINK; | ||
53 | req.nh.nlmsg_pid = 0; | ||
54 | req.nh.nlmsg_seq = ++seq; | ||
55 | req.ifinfo.ifi_family = AF_UNSPEC; | ||
56 | req.ifinfo.ifi_index = ifindex; | ||
57 | nla = (struct nlattr *)(((char *)&req) | ||
58 | + NLMSG_ALIGN(req.nh.nlmsg_len)); | ||
59 | nla->nla_type = NLA_F_NESTED | 43/*IFLA_XDP*/; | ||
60 | |||
61 | nla_xdp = (struct nlattr *)((char *)nla + NLA_HDRLEN); | ||
62 | nla_xdp->nla_type = 1/*IFLA_XDP_FD*/; | ||
63 | nla_xdp->nla_len = NLA_HDRLEN + sizeof(int); | ||
64 | memcpy((char *)nla_xdp + NLA_HDRLEN, &fd, sizeof(fd)); | ||
65 | nla->nla_len = NLA_HDRLEN + nla_xdp->nla_len; | ||
66 | |||
67 | req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len); | ||
68 | |||
69 | if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) { | ||
70 | printf("send to netlink: %s\n", strerror(errno)); | ||
71 | goto cleanup; | ||
72 | } | ||
73 | |||
74 | len = recv(sock, buf, sizeof(buf), 0); | ||
75 | if (len < 0) { | ||
76 | printf("recv from netlink: %s\n", strerror(errno)); | ||
77 | goto cleanup; | ||
78 | } | ||
79 | |||
80 | for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); | ||
81 | nh = NLMSG_NEXT(nh, len)) { | ||
82 | if (nh->nlmsg_pid != getpid()) { | ||
83 | printf("Wrong pid %d, expected %d\n", | ||
84 | nh->nlmsg_pid, getpid()); | ||
85 | goto cleanup; | ||
86 | } | ||
87 | if (nh->nlmsg_seq != seq) { | ||
88 | printf("Wrong seq %d, expected %d\n", | ||
89 | nh->nlmsg_seq, seq); | ||
90 | goto cleanup; | ||
91 | } | ||
92 | switch (nh->nlmsg_type) { | ||
93 | case NLMSG_ERROR: | ||
94 | err = (struct nlmsgerr *)NLMSG_DATA(nh); | ||
95 | if (!err->error) | ||
96 | continue; | ||
97 | printf("nlmsg error %s\n", strerror(-err->error)); | ||
98 | goto cleanup; | ||
99 | case NLMSG_DONE: | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | ret = 0; | ||
105 | |||
106 | cleanup: | ||
107 | close(sock); | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | static int ifindex; | ||
112 | |||
113 | static void int_exit(int sig) | ||
114 | { | ||
115 | set_link_xdp_fd(ifindex, -1); | ||
116 | exit(0); | ||
117 | } | ||
118 | |||
119 | /* simple per-protocol drop counter | ||
120 | */ | ||
121 | static void poll_stats(int interval) | ||
122 | { | ||
123 | unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); | ||
124 | const unsigned int nr_keys = 256; | ||
125 | __u64 values[nr_cpus], prev[nr_keys][nr_cpus]; | ||
126 | __u32 key; | ||
127 | int i; | ||
128 | |||
129 | memset(prev, 0, sizeof(prev)); | ||
130 | |||
131 | while (1) { | ||
132 | sleep(interval); | ||
133 | |||
134 | for (key = 0; key < nr_keys; key++) { | ||
135 | __u64 sum = 0; | ||
136 | |||
137 | assert(bpf_lookup_elem(map_fd[0], &key, values) == 0); | ||
138 | for (i = 0; i < nr_cpus; i++) | ||
139 | sum += (values[i] - prev[key][i]); | ||
140 | if (sum) | ||
141 | printf("proto %u: %10llu pkt/s\n", | ||
142 | key, sum / interval); | ||
143 | memcpy(prev[key], values, sizeof(values)); | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | |||
148 | int main(int ac, char **argv) | ||
149 | { | ||
150 | char filename[256]; | ||
151 | |||
152 | snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); | ||
153 | |||
154 | if (ac != 2) { | ||
155 | printf("usage: %s IFINDEX\n", argv[0]); | ||
156 | return 1; | ||
157 | } | ||
158 | |||
159 | ifindex = strtoul(argv[1], NULL, 0); | ||
160 | |||
161 | if (load_bpf_file(filename)) { | ||
162 | printf("%s", bpf_log_buf); | ||
163 | return 1; | ||
164 | } | ||
165 | |||
166 | if (!prog_fd[0]) { | ||
167 | printf("load_bpf_file: %s\n", strerror(errno)); | ||
168 | return 1; | ||
169 | } | ||
170 | |||
171 | signal(SIGINT, int_exit); | ||
172 | |||
173 | if (set_link_xdp_fd(ifindex, prog_fd[0]) < 0) { | ||
174 | printf("link set xdp fd failed\n"); | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | poll_stats(2); | ||
179 | |||
180 | return 0; | ||
181 | } | ||
diff --git a/samples/bpf/xdp2_kern.c b/samples/bpf/xdp2_kern.c new file mode 100644 index 000000000000..e01288867d15 --- /dev/null +++ b/samples/bpf/xdp2_kern.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* Copyright (c) 2016 PLUMgrid | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or | ||
4 | * modify it under the terms of version 2 of the GNU General Public | ||
5 | * License as published by the Free Software Foundation. | ||
6 | */ | ||
7 | #define KBUILD_MODNAME "foo" | ||
8 | #include <uapi/linux/bpf.h> | ||
9 | #include <linux/in.h> | ||
10 | #include <linux/if_ether.h> | ||
11 | #include <linux/if_packet.h> | ||
12 | #include <linux/if_vlan.h> | ||
13 | #include <linux/ip.h> | ||
14 | #include <linux/ipv6.h> | ||
15 | #include "bpf_helpers.h" | ||
16 | |||
17 | struct bpf_map_def SEC("maps") rxcnt = { | ||
18 | .type = BPF_MAP_TYPE_PERCPU_ARRAY, | ||
19 | .key_size = sizeof(u32), | ||
20 | .value_size = sizeof(long), | ||
21 | .max_entries = 256, | ||
22 | }; | ||
23 | |||
24 | static void swap_src_dst_mac(void *data) | ||
25 | { | ||
26 | unsigned short *p = data; | ||
27 | unsigned short dst[3]; | ||
28 | |||
29 | dst[0] = p[0]; | ||
30 | dst[1] = p[1]; | ||
31 | dst[2] = p[2]; | ||
32 | p[0] = p[3]; | ||
33 | p[1] = p[4]; | ||
34 | p[2] = p[5]; | ||
35 | p[3] = dst[0]; | ||
36 | p[4] = dst[1]; | ||
37 | p[5] = dst[2]; | ||
38 | } | ||
39 | |||
40 | static int parse_ipv4(void *data, u64 nh_off, void *data_end) | ||
41 | { | ||
42 | struct iphdr *iph = data + nh_off; | ||
43 | |||
44 | if (iph + 1 > data_end) | ||
45 | return 0; | ||
46 | return iph->protocol; | ||
47 | } | ||
48 | |||
49 | static int parse_ipv6(void *data, u64 nh_off, void *data_end) | ||
50 | { | ||
51 | struct ipv6hdr *ip6h = data + nh_off; | ||
52 | |||
53 | if (ip6h + 1 > data_end) | ||
54 | return 0; | ||
55 | return ip6h->nexthdr; | ||
56 | } | ||
57 | |||
58 | SEC("xdp1") | ||
59 | int xdp_prog1(struct xdp_md *ctx) | ||
60 | { | ||
61 | void *data_end = (void *)(long)ctx->data_end; | ||
62 | void *data = (void *)(long)ctx->data; | ||
63 | struct ethhdr *eth = data; | ||
64 | int rc = XDP_DROP; | ||
65 | long *value; | ||
66 | u16 h_proto; | ||
67 | u64 nh_off; | ||
68 | u32 ipproto; | ||
69 | |||
70 | nh_off = sizeof(*eth); | ||
71 | if (data + nh_off > data_end) | ||
72 | return rc; | ||
73 | |||
74 | h_proto = eth->h_proto; | ||
75 | |||
76 | if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { | ||
77 | struct vlan_hdr *vhdr; | ||
78 | |||
79 | vhdr = data + nh_off; | ||
80 | nh_off += sizeof(struct vlan_hdr); | ||
81 | if (data + nh_off > data_end) | ||
82 | return rc; | ||
83 | h_proto = vhdr->h_vlan_encapsulated_proto; | ||
84 | } | ||
85 | if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) { | ||
86 | struct vlan_hdr *vhdr; | ||
87 | |||
88 | vhdr = data + nh_off; | ||
89 | nh_off += sizeof(struct vlan_hdr); | ||
90 | if (data + nh_off > data_end) | ||
91 | return rc; | ||
92 | h_proto = vhdr->h_vlan_encapsulated_proto; | ||
93 | } | ||
94 | |||
95 | if (h_proto == htons(ETH_P_IP)) | ||
96 | ipproto = parse_ipv4(data, nh_off, data_end); | ||
97 | else if (h_proto == htons(ETH_P_IPV6)) | ||
98 | ipproto = parse_ipv6(data, nh_off, data_end); | ||
99 | else | ||
100 | ipproto = 0; | ||
101 | |||
102 | value = bpf_map_lookup_elem(&rxcnt, &ipproto); | ||
103 | if (value) | ||
104 | *value += 1; | ||
105 | |||
106 | if (ipproto == IPPROTO_UDP) { | ||
107 | swap_src_dst_mac(data); | ||
108 | rc = XDP_TX; | ||
109 | } | ||
110 | |||
111 | return rc; | ||
112 | } | ||
113 | |||
114 | char _license[] SEC("license") = "GPL"; | ||
diff --git a/samples/kprobes/kprobe_example.c b/samples/kprobes/kprobe_example.c index ed0ca0c07242..f3b61b4ee09c 100644 --- a/samples/kprobes/kprobe_example.c +++ b/samples/kprobes/kprobe_example.c | |||
@@ -46,6 +46,11 @@ static int handler_pre(struct kprobe *p, struct pt_regs *regs) | |||
46 | " ex1 = 0x%lx\n", | 46 | " ex1 = 0x%lx\n", |
47 | p->symbol_name, p->addr, regs->pc, regs->ex1); | 47 | p->symbol_name, p->addr, regs->pc, regs->ex1); |
48 | #endif | 48 | #endif |
49 | #ifdef CONFIG_ARM64 | ||
50 | pr_info("<%s> pre_handler: p->addr = 0x%p, pc = 0x%lx," | ||
51 | " pstate = 0x%lx\n", | ||
52 | p->symbol_name, p->addr, (long)regs->pc, (long)regs->pstate); | ||
53 | #endif | ||
49 | 54 | ||
50 | /* A dump_stack() here will give a stack backtrace */ | 55 | /* A dump_stack() here will give a stack backtrace */ |
51 | return 0; | 56 | return 0; |
@@ -71,6 +76,10 @@ static void handler_post(struct kprobe *p, struct pt_regs *regs, | |||
71 | printk(KERN_INFO "<%s> post_handler: p->addr = 0x%p, ex1 = 0x%lx\n", | 76 | printk(KERN_INFO "<%s> post_handler: p->addr = 0x%p, ex1 = 0x%lx\n", |
72 | p->symbol_name, p->addr, regs->ex1); | 77 | p->symbol_name, p->addr, regs->ex1); |
73 | #endif | 78 | #endif |
79 | #ifdef CONFIG_ARM64 | ||
80 | pr_info("<%s> post_handler: p->addr = 0x%p, pstate = 0x%lx\n", | ||
81 | p->symbol_name, p->addr, (long)regs->pstate); | ||
82 | #endif | ||
74 | } | 83 | } |
75 | 84 | ||
76 | /* | 85 | /* |
diff --git a/samples/pktgen/parameters.sh b/samples/pktgen/parameters.sh index 33b70fdd5a4a..f70ea7dd5660 100644 --- a/samples/pktgen/parameters.sh +++ b/samples/pktgen/parameters.sh | |||
@@ -14,12 +14,13 @@ function usage() { | |||
14 | echo " -b : (\$BURST) HW level bursting of SKBs" | 14 | echo " -b : (\$BURST) HW level bursting of SKBs" |
15 | echo " -v : (\$VERBOSE) verbose" | 15 | echo " -v : (\$VERBOSE) verbose" |
16 | echo " -x : (\$DEBUG) debug" | 16 | echo " -x : (\$DEBUG) debug" |
17 | echo " -6 : (\$IP6) IPv6" | ||
17 | echo "" | 18 | echo "" |
18 | } | 19 | } |
19 | 20 | ||
20 | ## --- Parse command line arguments / parameters --- | 21 | ## --- Parse command line arguments / parameters --- |
21 | ## echo "Commandline options:" | 22 | ## echo "Commandline options:" |
22 | while getopts "s:i:d:m:t:c:b:vxh" option; do | 23 | while getopts "s:i:d:m:t:c:b:vxh6" option; do |
23 | case $option in | 24 | case $option in |
24 | i) # interface | 25 | i) # interface |
25 | export DEV=$OPTARG | 26 | export DEV=$OPTARG |
@@ -59,6 +60,10 @@ while getopts "s:i:d:m:t:c:b:vxh" option; do | |||
59 | export DEBUG=yes | 60 | export DEBUG=yes |
60 | info "Debug mode: DEBUG=$DEBUG" | 61 | info "Debug mode: DEBUG=$DEBUG" |
61 | ;; | 62 | ;; |
63 | 6) | ||
64 | export IP6=6 | ||
65 | info "IP6: IP6=$IP6" | ||
66 | ;; | ||
62 | h|?|*) | 67 | h|?|*) |
63 | usage; | 68 | usage; |
64 | err 2 "[ERROR] Unknown parameters!!!" | 69 | err 2 "[ERROR] Unknown parameters!!!" |
diff --git a/samples/pktgen/pktgen.conf-1-1-flows b/samples/pktgen/pktgen.conf-1-1-flows deleted file mode 100755 index 081749c9707d..000000000000 --- a/samples/pktgen/pktgen.conf-1-1-flows +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | #modprobe pktgen | ||
4 | |||
5 | |||
6 | function pgset() { | ||
7 | local result | ||
8 | |||
9 | echo $1 > $PGDEV | ||
10 | |||
11 | result=`cat $PGDEV | fgrep "Result: OK:"` | ||
12 | if [ "$result" = "" ]; then | ||
13 | cat $PGDEV | fgrep Result: | ||
14 | fi | ||
15 | } | ||
16 | |||
17 | # Config Start Here ----------------------------------------------------------- | ||
18 | |||
19 | |||
20 | # thread config | ||
21 | # Each CPU has its own thread. One CPU example. We add eth1. | ||
22 | |||
23 | PGDEV=/proc/net/pktgen/kpktgend_0 | ||
24 | echo "Removing all devices" | ||
25 | pgset "rem_device_all" | ||
26 | echo "Adding eth1" | ||
27 | pgset "add_device eth1" | ||
28 | |||
29 | |||
30 | # device config | ||
31 | # delay 0 | ||
32 | # We need to do alloc for every skb since we cannot clone here. | ||
33 | |||
34 | CLONE_SKB="clone_skb 0" | ||
35 | # NIC adds 4 bytes CRC | ||
36 | PKT_SIZE="pkt_size 60" | ||
37 | |||
38 | # COUNT 0 means forever | ||
39 | #COUNT="count 0" | ||
40 | COUNT="count 10000000" | ||
41 | DELAY="delay 0" | ||
42 | |||
43 | PGDEV=/proc/net/pktgen/eth1 | ||
44 | echo "Configuring $PGDEV" | ||
45 | pgset "$COUNT" | ||
46 | pgset "$CLONE_SKB" | ||
47 | pgset "$PKT_SIZE" | ||
48 | pgset "$DELAY" | ||
49 | # Random address with in the min-max range | ||
50 | pgset "flag IPDST_RND" | ||
51 | pgset "dst_min 10.0.0.0" | ||
52 | pgset "dst_max 10.255.255.255" | ||
53 | |||
54 | # 8k Concurrent flows at 4 pkts | ||
55 | pgset "flows 8192" | ||
56 | pgset "flowlen 4" | ||
57 | |||
58 | pgset "dst_mac 00:04:23:08:91:dc" | ||
59 | |||
60 | # Time to run | ||
61 | PGDEV=/proc/net/pktgen/pgctrl | ||
62 | |||
63 | echo "Running... ctrl^C to stop" | ||
64 | trap true INT | ||
65 | pgset "start" | ||
66 | echo "Done" | ||
67 | cat /proc/net/pktgen/eth1 | ||
diff --git a/samples/pktgen/pktgen.conf-1-1-rdos b/samples/pktgen/pktgen.conf-1-1-rdos deleted file mode 100755 index c7553be49b80..000000000000 --- a/samples/pktgen/pktgen.conf-1-1-rdos +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | #!/bin/bash | ||
2 | |||
3 | #modprobe pktgen | ||
4 | |||
5 | |||
6 | function pgset() { | ||
7 | local result | ||
8 | |||
9 | echo $1 > $PGDEV | ||
10 | |||
11 | result=`cat $PGDEV | fgrep "Result: OK:"` | ||
12 | if [ "$result" = "" ]; then | ||
13 | cat $PGDEV | fgrep Result: | ||
14 | fi | ||
15 | } | ||
16 | |||
17 | # Config Start Here ----------------------------------------------------------- | ||
18 | |||
19 | |||
20 | # thread config | ||
21 | # Each CPU has its own thread. One CPU example. We add eth1. | ||
22 | |||
23 | PGDEV=/proc/net/pktgen/kpktgend_0 | ||
24 | echo "Removing all devices" | ||
25 | pgset "rem_device_all" | ||
26 | echo "Adding eth1" | ||
27 | pgset "add_device eth1" | ||
28 | |||
29 | |||
30 | # device config | ||
31 | # delay 0 | ||
32 | |||
33 | # We need to do alloc for every skb since we cannot clone here. | ||
34 | |||
35 | CLONE_SKB="clone_skb 0" | ||
36 | # NIC adds 4 bytes CRC | ||
37 | PKT_SIZE="pkt_size 60" | ||
38 | |||
39 | # COUNT 0 means forever | ||
40 | #COUNT="count 0" | ||
41 | COUNT="count 10000000" | ||
42 | DELAY="delay 0" | ||
43 | |||
44 | PGDEV=/proc/net/pktgen/eth1 | ||
45 | echo "Configuring $PGDEV" | ||
46 | pgset "$COUNT" | ||
47 | pgset "$CLONE_SKB" | ||
48 | pgset "$PKT_SIZE" | ||
49 | pgset "$DELAY" | ||
50 | # Random address with in the min-max range | ||
51 | pgset "flag IPDST_RND" | ||
52 | pgset "dst_min 10.0.0.0" | ||
53 | pgset "dst_max 10.255.255.255" | ||
54 | |||
55 | pgset "dst_mac 00:04:23:08:91:dc" | ||
56 | |||
57 | # Time to run | ||
58 | PGDEV=/proc/net/pktgen/pgctrl | ||
59 | |||
60 | echo "Running... ctrl^C to stop" | ||
61 | trap true INT | ||
62 | pgset "start" | ||
63 | echo "Done" | ||
64 | cat /proc/net/pktgen/eth1 | ||
diff --git a/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh b/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh index cb1590331b47..f3e1bedfd77f 100755 --- a/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh +++ b/samples/pktgen/pktgen_bench_xmit_mode_netif_receive.sh | |||
@@ -34,7 +34,9 @@ root_check_run_with_sudo "$@" | |||
34 | source ${basedir}/parameters.sh | 34 | source ${basedir}/parameters.sh |
35 | # Using invalid DST_MAC will cause the packets to get dropped in | 35 | # Using invalid DST_MAC will cause the packets to get dropped in |
36 | # ip_rcv() which is part of the test | 36 | # ip_rcv() which is part of the test |
37 | [ -z "$DEST_IP" ] && DEST_IP="198.18.0.42" | 37 | if [ -z "$DEST_IP" ]; then |
38 | [ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1" | ||
39 | fi | ||
38 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" | 40 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" |
39 | [ -z "$BURST" ] && BURST=1024 | 41 | [ -z "$BURST" ] && BURST=1024 |
40 | 42 | ||
@@ -64,7 +66,7 @@ for ((thread = 0; thread < $THREADS; thread++)); do | |||
64 | 66 | ||
65 | # Destination | 67 | # Destination |
66 | pg_set $dev "dst_mac $DST_MAC" | 68 | pg_set $dev "dst_mac $DST_MAC" |
67 | pg_set $dev "dst $DEST_IP" | 69 | pg_set $dev "dst$IP6 $DEST_IP" |
68 | 70 | ||
69 | # Inject packet into RX path of stack | 71 | # Inject packet into RX path of stack |
70 | pg_set $dev "xmit_mode netif_receive" | 72 | pg_set $dev "xmit_mode netif_receive" |
diff --git a/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh b/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh new file mode 100755 index 000000000000..cc102e923241 --- /dev/null +++ b/samples/pktgen/pktgen_bench_xmit_mode_queue_xmit.sh | |||
@@ -0,0 +1,68 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Benchmark script: | ||
4 | # - developed for benchmarking egress qdisc path, derived (more | ||
5 | # like cut'n'pasted) from ingress benchmark script. | ||
6 | # | ||
7 | # Script for injecting packets into egress qdisc path of the stack | ||
8 | # with pktgen "xmit_mode queue_xmit". | ||
9 | # | ||
10 | basedir=`dirname $0` | ||
11 | source ${basedir}/functions.sh | ||
12 | root_check_run_with_sudo "$@" | ||
13 | |||
14 | # Parameter parsing via include | ||
15 | source ${basedir}/parameters.sh | ||
16 | if [ -z "$DEST_IP" ]; then | ||
17 | [ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1" | ||
18 | fi | ||
19 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" | ||
20 | |||
21 | # Burst greater than 1 are invalid for queue_xmit mode | ||
22 | if [[ -n "$BURST" ]]; then | ||
23 | err 1 "Bursting not supported for this mode" | ||
24 | fi | ||
25 | |||
26 | # Base Config | ||
27 | DELAY="0" # Zero means max speed | ||
28 | COUNT="10000000" # Zero means indefinitely | ||
29 | |||
30 | # General cleanup everything since last run | ||
31 | pg_ctrl "reset" | ||
32 | |||
33 | # Threads are specified with parameter -t value in $THREADS | ||
34 | for ((thread = 0; thread < $THREADS; thread++)); do | ||
35 | # The device name is extended with @name, using thread number to | ||
36 | # make then unique, but any name will do. | ||
37 | dev=${DEV}@${thread} | ||
38 | |||
39 | # Add remove all other devices and add_device $dev to thread | ||
40 | pg_thread $thread "rem_device_all" | ||
41 | pg_thread $thread "add_device" $dev | ||
42 | |||
43 | # Base config of dev | ||
44 | pg_set $dev "flag QUEUE_MAP_CPU" | ||
45 | pg_set $dev "count $COUNT" | ||
46 | pg_set $dev "pkt_size $PKT_SIZE" | ||
47 | pg_set $dev "delay $DELAY" | ||
48 | pg_set $dev "flag NO_TIMESTAMP" | ||
49 | |||
50 | # Destination | ||
51 | pg_set $dev "dst_mac $DST_MAC" | ||
52 | pg_set $dev "dst$IP6 $DEST_IP" | ||
53 | |||
54 | # Inject packet into TX qdisc egress path of stack | ||
55 | pg_set $dev "xmit_mode queue_xmit" | ||
56 | done | ||
57 | |||
58 | # start_run | ||
59 | echo "Running... ctrl^C to stop" >&2 | ||
60 | pg_ctrl "start" | ||
61 | echo "Done" >&2 | ||
62 | |||
63 | # Print results | ||
64 | for ((thread = 0; thread < $THREADS; thread++)); do | ||
65 | dev=${DEV}@${thread} | ||
66 | echo "Device: $dev" | ||
67 | cat /proc/net/pktgen/$dev | grep -A2 "Result:" | ||
68 | done | ||
diff --git a/samples/pktgen/pktgen_sample01_simple.sh b/samples/pktgen/pktgen_sample01_simple.sh index 8c9d318c221b..29ef4ba50796 100755 --- a/samples/pktgen/pktgen_sample01_simple.sh +++ b/samples/pktgen/pktgen_sample01_simple.sh | |||
@@ -14,7 +14,9 @@ root_check_run_with_sudo "$@" | |||
14 | source ${basedir}/parameters.sh | 14 | source ${basedir}/parameters.sh |
15 | # | 15 | # |
16 | # Set some default params, if they didn't get set | 16 | # Set some default params, if they didn't get set |
17 | [ -z "$DEST_IP" ] && DEST_IP="198.18.0.42" | 17 | if [ -z "$DEST_IP" ]; then |
18 | [ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1" | ||
19 | fi | ||
18 | [ -z "$CLONE_SKB" ] && CLONE_SKB="0" | 20 | [ -z "$CLONE_SKB" ] && CLONE_SKB="0" |
19 | # Example enforce param "-m" for dst_mac | 21 | # Example enforce param "-m" for dst_mac |
20 | [ -z "$DST_MAC" ] && usage && err 2 "Must specify -m dst_mac" | 22 | [ -z "$DST_MAC" ] && usage && err 2 "Must specify -m dst_mac" |
@@ -54,7 +56,7 @@ pg_set $DEV "flag NO_TIMESTAMP" | |||
54 | 56 | ||
55 | # Destination | 57 | # Destination |
56 | pg_set $DEV "dst_mac $DST_MAC" | 58 | pg_set $DEV "dst_mac $DST_MAC" |
57 | pg_set $DEV "dst $DEST_IP" | 59 | pg_set $DEV "dst$IP6 $DEST_IP" |
58 | 60 | ||
59 | # Setup random UDP port src range | 61 | # Setup random UDP port src range |
60 | pg_set $DEV "flag UDPSRC_RND" | 62 | pg_set $DEV "flag UDPSRC_RND" |
diff --git a/samples/pktgen/pktgen_sample02_multiqueue.sh b/samples/pktgen/pktgen_sample02_multiqueue.sh index 32467aea8e47..c88a161d3e6f 100755 --- a/samples/pktgen/pktgen_sample02_multiqueue.sh +++ b/samples/pktgen/pktgen_sample02_multiqueue.sh | |||
@@ -23,7 +23,9 @@ UDP_MIN=9 | |||
23 | UDP_MAX=109 | 23 | UDP_MAX=109 |
24 | 24 | ||
25 | # (example of setting default params in your script) | 25 | # (example of setting default params in your script) |
26 | [ -z "$DEST_IP" ] && DEST_IP="198.18.0.42" | 26 | if [ -z "$DEST_IP" ]; then |
27 | [ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1" | ||
28 | fi | ||
27 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" | 29 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" |
28 | 30 | ||
29 | # General cleanup everything since last run | 31 | # General cleanup everything since last run |
@@ -54,7 +56,7 @@ for ((thread = 0; thread < $THREADS; thread++)); do | |||
54 | 56 | ||
55 | # Destination | 57 | # Destination |
56 | pg_set $dev "dst_mac $DST_MAC" | 58 | pg_set $dev "dst_mac $DST_MAC" |
57 | pg_set $dev "dst $DEST_IP" | 59 | pg_set $dev "dst$IP6 $DEST_IP" |
58 | 60 | ||
59 | # Setup random UDP port src range | 61 | # Setup random UDP port src range |
60 | pg_set $dev "flag UDPSRC_RND" | 62 | pg_set $dev "flag UDPSRC_RND" |
diff --git a/samples/pktgen/pktgen_sample03_burst_single_flow.sh b/samples/pktgen/pktgen_sample03_burst_single_flow.sh index 775f5d0a1e53..80cf8f5ba6b2 100755 --- a/samples/pktgen/pktgen_sample03_burst_single_flow.sh +++ b/samples/pktgen/pktgen_sample03_burst_single_flow.sh | |||
@@ -25,7 +25,9 @@ root_check_run_with_sudo "$@" | |||
25 | # Parameter parsing via include | 25 | # Parameter parsing via include |
26 | source ${basedir}/parameters.sh | 26 | source ${basedir}/parameters.sh |
27 | # Set some default params, if they didn't get set | 27 | # Set some default params, if they didn't get set |
28 | [ -z "$DEST_IP" ] && DEST_IP="198.18.0.42" | 28 | if [ -z "$DEST_IP" ]; then |
29 | [ -z "$IP6" ] && DEST_IP="198.18.0.42" || DEST_IP="FD00::1" | ||
30 | fi | ||
29 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" | 31 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" |
30 | [ -z "$BURST" ] && BURST=32 | 32 | [ -z "$BURST" ] && BURST=32 |
31 | [ -z "$CLONE_SKB" ] && CLONE_SKB="100000" | 33 | [ -z "$CLONE_SKB" ] && CLONE_SKB="100000" |
@@ -55,7 +57,7 @@ for ((thread = 0; thread < $THREADS; thread++)); do | |||
55 | 57 | ||
56 | # Destination | 58 | # Destination |
57 | pg_set $dev "dst_mac $DST_MAC" | 59 | pg_set $dev "dst_mac $DST_MAC" |
58 | pg_set $dev "dst $DEST_IP" | 60 | pg_set $dev "dst$IP6 $DEST_IP" |
59 | 61 | ||
60 | # Setup burst, for easy testing -b 0 disable bursting | 62 | # Setup burst, for easy testing -b 0 disable bursting |
61 | # (internally in pktgen default and minimum burst=1) | 63 | # (internally in pktgen default and minimum burst=1) |
diff --git a/samples/pktgen/pktgen_sample04_many_flows.sh b/samples/pktgen/pktgen_sample04_many_flows.sh new file mode 100755 index 000000000000..f60412e445bb --- /dev/null +++ b/samples/pktgen/pktgen_sample04_many_flows.sh | |||
@@ -0,0 +1,93 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Script example for many flows testing | ||
4 | # | ||
5 | # Number of simultaneous flows limited by variable $FLOWS | ||
6 | # and number of packets per flow controlled by variable $FLOWLEN | ||
7 | # | ||
8 | basedir=`dirname $0` | ||
9 | source ${basedir}/functions.sh | ||
10 | root_check_run_with_sudo "$@" | ||
11 | |||
12 | # Parameter parsing via include | ||
13 | source ${basedir}/parameters.sh | ||
14 | # Set some default params, if they didn't get set | ||
15 | [ -z "$DEST_IP" ] && DEST_IP="198.18.0.42" | ||
16 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" | ||
17 | [ -z "$CLONE_SKB" ] && CLONE_SKB="0" | ||
18 | |||
19 | # NOTICE: Script specific settings | ||
20 | # ======= | ||
21 | # Limiting the number of concurrent flows ($FLOWS) | ||
22 | # and also set how many packets each flow contains ($FLOWLEN) | ||
23 | # | ||
24 | [ -z "$FLOWS" ] && FLOWS="8000" | ||
25 | [ -z "$FLOWLEN" ] && FLOWLEN="10" | ||
26 | |||
27 | # Base Config | ||
28 | DELAY="0" # Zero means max speed | ||
29 | COUNT="0" # Zero means indefinitely | ||
30 | |||
31 | if [[ -n "$BURST" ]]; then | ||
32 | err 1 "Bursting not supported for this mode" | ||
33 | fi | ||
34 | |||
35 | # General cleanup everything since last run | ||
36 | pg_ctrl "reset" | ||
37 | |||
38 | # Threads are specified with parameter -t value in $THREADS | ||
39 | for ((thread = 0; thread < $THREADS; thread++)); do | ||
40 | dev=${DEV}@${thread} | ||
41 | |||
42 | # Add remove all other devices and add_device $dev to thread | ||
43 | pg_thread $thread "rem_device_all" | ||
44 | pg_thread $thread "add_device" $dev | ||
45 | |||
46 | # Base config | ||
47 | pg_set $dev "flag QUEUE_MAP_CPU" | ||
48 | pg_set $dev "count $COUNT" | ||
49 | pg_set $dev "clone_skb $CLONE_SKB" | ||
50 | pg_set $dev "pkt_size $PKT_SIZE" | ||
51 | pg_set $dev "delay $DELAY" | ||
52 | pg_set $dev "flag NO_TIMESTAMP" | ||
53 | |||
54 | # Single destination | ||
55 | pg_set $dev "dst_mac $DST_MAC" | ||
56 | pg_set $dev "dst $DEST_IP" | ||
57 | |||
58 | # Randomize source IP-addresses | ||
59 | pg_set $dev "flag IPSRC_RND" | ||
60 | pg_set $dev "src_min 198.18.0.0" | ||
61 | pg_set $dev "src_max 198.19.255.255" | ||
62 | |||
63 | # Limit number of flows (max 65535) | ||
64 | pg_set $dev "flows $FLOWS" | ||
65 | # | ||
66 | # How many packets a flow will send, before flow "entry" is | ||
67 | # re-generated/setup. | ||
68 | pg_set $dev "flowlen $FLOWLEN" | ||
69 | # | ||
70 | # Flag FLOW_SEQ will cause $FLOWLEN packets from the same flow | ||
71 | # being send back-to-back, before next flow is selected | ||
72 | # incrementally. This helps lookup caches, and is more realistic. | ||
73 | # | ||
74 | pg_set $dev "flag FLOW_SEQ" | ||
75 | |||
76 | done | ||
77 | |||
78 | # Run if user hits control-c | ||
79 | function print_result() { | ||
80 | # Print results | ||
81 | for ((thread = 0; thread < $THREADS; thread++)); do | ||
82 | dev=${DEV}@${thread} | ||
83 | echo "Device: $dev" | ||
84 | cat /proc/net/pktgen/$dev | grep -A2 "Result:" | ||
85 | done | ||
86 | } | ||
87 | # trap keyboard interrupt (Ctrl-C) | ||
88 | trap true SIGINT | ||
89 | |||
90 | echo "Running... ctrl^C to stop" >&2 | ||
91 | pg_ctrl "start" | ||
92 | |||
93 | print_result | ||
diff --git a/samples/pktgen/pktgen_sample05_flow_per_thread.sh b/samples/pktgen/pktgen_sample05_flow_per_thread.sh new file mode 100755 index 000000000000..32ad818e2829 --- /dev/null +++ b/samples/pktgen/pktgen_sample05_flow_per_thread.sh | |||
@@ -0,0 +1,81 @@ | |||
1 | #!/bin/bash | ||
2 | # | ||
3 | # Script will generate one flow per thread (-t N) | ||
4 | # - Same destination IP | ||
5 | # - Fake source IPs for each flow (fixed based on thread number) | ||
6 | # | ||
7 | # Useful for scale testing on receiver, to see whether silo'ing flows | ||
8 | # works and scales. For optimal scalability (on receiver) each | ||
9 | # separate-flow should not access shared variables/data. This script | ||
10 | # helps magnify any of these scaling issues by overloading the receiver. | ||
11 | # | ||
12 | basedir=`dirname $0` | ||
13 | source ${basedir}/functions.sh | ||
14 | root_check_run_with_sudo "$@" | ||
15 | |||
16 | # Parameter parsing via include | ||
17 | source ${basedir}/parameters.sh | ||
18 | # Set some default params, if they didn't get set | ||
19 | [ -z "$DEST_IP" ] && DEST_IP="198.18.0.42" | ||
20 | [ -z "$DST_MAC" ] && DST_MAC="90:e2:ba:ff:ff:ff" | ||
21 | [ -z "$CLONE_SKB" ] && CLONE_SKB="0" | ||
22 | [ -z "$BURST" ] && BURST=32 | ||
23 | |||
24 | |||
25 | # Base Config | ||
26 | DELAY="0" # Zero means max speed | ||
27 | COUNT="0" # Zero means indefinitely | ||
28 | |||
29 | # General cleanup everything since last run | ||
30 | pg_ctrl "reset" | ||
31 | |||
32 | # Threads are specified with parameter -t value in $THREADS | ||
33 | for ((thread = 0; thread < $THREADS; thread++)); do | ||
34 | dev=${DEV}@${thread} | ||
35 | |||
36 | # Add remove all other devices and add_device $dev to thread | ||
37 | pg_thread $thread "rem_device_all" | ||
38 | pg_thread $thread "add_device" $dev | ||
39 | |||
40 | # Base config | ||
41 | pg_set $dev "flag QUEUE_MAP_CPU" | ||
42 | pg_set $dev "count $COUNT" | ||
43 | pg_set $dev "clone_skb $CLONE_SKB" | ||
44 | pg_set $dev "pkt_size $PKT_SIZE" | ||
45 | pg_set $dev "delay $DELAY" | ||
46 | pg_set $dev "flag NO_TIMESTAMP" | ||
47 | |||
48 | # Single destination | ||
49 | pg_set $dev "dst_mac $DST_MAC" | ||
50 | pg_set $dev "dst $DEST_IP" | ||
51 | |||
52 | # Setup source IP-addresses based on thread number | ||
53 | pg_set $dev "src_min 198.18.$((thread+1)).1" | ||
54 | pg_set $dev "src_max 198.18.$((thread+1)).1" | ||
55 | |||
56 | # Setup burst, for easy testing -b 0 disable bursting | ||
57 | # (internally in pktgen default and minimum burst=1) | ||
58 | if [[ ${BURST} -ne 0 ]]; then | ||
59 | pg_set $dev "burst $BURST" | ||
60 | else | ||
61 | info "$dev: Not using burst" | ||
62 | fi | ||
63 | |||
64 | done | ||
65 | |||
66 | # Run if user hits control-c | ||
67 | function print_result() { | ||
68 | # Print results | ||
69 | for ((thread = 0; thread < $THREADS; thread++)); do | ||
70 | dev=${DEV}@${thread} | ||
71 | echo "Device: $dev" | ||
72 | cat /proc/net/pktgen/$dev | grep -A2 "Result:" | ||
73 | done | ||
74 | } | ||
75 | # trap keyboard interrupt (Ctrl-C) | ||
76 | trap true SIGINT | ||
77 | |||
78 | echo "Running... ctrl^C to stop" >&2 | ||
79 | pg_ctrl "start" | ||
80 | |||
81 | print_result | ||
diff --git a/samples/trace_printk/Makefile b/samples/trace_printk/Makefile new file mode 100644 index 000000000000..19900ab2b00d --- /dev/null +++ b/samples/trace_printk/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # builds a module that calls various trace_printk routines | ||
2 | # then to use one (as root): insmod <module_name.ko> | ||
3 | |||
4 | # This module can also be used to test the trace_printk code. | ||
5 | |||
6 | obj-$(CONFIG_SAMPLE_TRACE_PRINTK) += trace-printk.o | ||
diff --git a/samples/trace_printk/trace-printk.c b/samples/trace_printk/trace-printk.c new file mode 100644 index 000000000000..e9e0040ff7be --- /dev/null +++ b/samples/trace_printk/trace-printk.c | |||
@@ -0,0 +1,56 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/kthread.h> | ||
3 | #include <linux/irq_work.h> | ||
4 | |||
5 | /* Must not be static to force gcc to consider these non constant */ | ||
6 | char *trace_printk_test_global_str = | ||
7 | "This is a dynamic string that will use trace_puts\n"; | ||
8 | |||
9 | char *trace_printk_test_global_str_irq = | ||
10 | "(irq) This is a dynamic string that will use trace_puts\n"; | ||
11 | |||
12 | char *trace_printk_test_global_str_fmt = | ||
13 | "%sThis is a %s that will use trace_printk\n"; | ||
14 | |||
15 | static struct irq_work irqwork; | ||
16 | |||
17 | static void trace_printk_irq_work(struct irq_work *work) | ||
18 | { | ||
19 | trace_printk("(irq) This is a static string that will use trace_bputs\n"); | ||
20 | trace_printk(trace_printk_test_global_str_irq); | ||
21 | |||
22 | trace_printk("(irq) This is a %s that will use trace_bprintk()\n", | ||
23 | "static string"); | ||
24 | |||
25 | trace_printk(trace_printk_test_global_str_fmt, | ||
26 | "(irq) ", "dynamic string"); | ||
27 | } | ||
28 | |||
29 | static int __init trace_printk_init(void) | ||
30 | { | ||
31 | init_irq_work(&irqwork, trace_printk_irq_work); | ||
32 | |||
33 | trace_printk("This is a static string that will use trace_bputs\n"); | ||
34 | trace_printk(trace_printk_test_global_str); | ||
35 | |||
36 | /* Kick off printing in irq context */ | ||
37 | irq_work_queue(&irqwork); | ||
38 | |||
39 | trace_printk("This is a %s that will use trace_bprintk()\n", | ||
40 | "static string"); | ||
41 | |||
42 | trace_printk(trace_printk_test_global_str_fmt, "", "dynamic string"); | ||
43 | |||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static void __exit trace_printk_exit(void) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | module_init(trace_printk_init); | ||
52 | module_exit(trace_printk_exit); | ||
53 | |||
54 | MODULE_AUTHOR("Steven Rostedt"); | ||
55 | MODULE_DESCRIPTION("trace-printk"); | ||
56 | MODULE_LICENSE("GPL"); | ||
diff --git a/samples/v4l/v4l2-pci-skeleton.c b/samples/v4l/v4l2-pci-skeleton.c index a55cf94ac907..93b76c3220fd 100644 --- a/samples/v4l/v4l2-pci-skeleton.c +++ b/samples/v4l/v4l2-pci-skeleton.c | |||
@@ -56,7 +56,6 @@ MODULE_LICENSE("GPL v2"); | |||
56 | * @format: current pix format | 56 | * @format: current pix format |
57 | * @input: current video input (0 = SDTV, 1 = HDTV) | 57 | * @input: current video input (0 = SDTV, 1 = HDTV) |
58 | * @queue: vb2 video capture queue | 58 | * @queue: vb2 video capture queue |
59 | * @alloc_ctx: vb2 contiguous DMA context | ||
60 | * @qlock: spinlock controlling access to buf_list and sequence | 59 | * @qlock: spinlock controlling access to buf_list and sequence |
61 | * @buf_list: list of buffers queued for DMA | 60 | * @buf_list: list of buffers queued for DMA |
62 | * @sequence: frame sequence counter | 61 | * @sequence: frame sequence counter |
@@ -73,7 +72,6 @@ struct skeleton { | |||
73 | unsigned input; | 72 | unsigned input; |
74 | 73 | ||
75 | struct vb2_queue queue; | 74 | struct vb2_queue queue; |
76 | struct vb2_alloc_ctx *alloc_ctx; | ||
77 | 75 | ||
78 | spinlock_t qlock; | 76 | spinlock_t qlock; |
79 | struct list_head buf_list; | 77 | struct list_head buf_list; |
@@ -165,7 +163,7 @@ static irqreturn_t skeleton_irq(int irq, void *dev_id) | |||
165 | */ | 163 | */ |
166 | static int queue_setup(struct vb2_queue *vq, | 164 | static int queue_setup(struct vb2_queue *vq, |
167 | unsigned int *nbuffers, unsigned int *nplanes, | 165 | unsigned int *nbuffers, unsigned int *nplanes, |
168 | unsigned int sizes[], void *alloc_ctxs[]) | 166 | unsigned int sizes[], struct device *alloc_devs[]) |
169 | { | 167 | { |
170 | struct skeleton *skel = vb2_get_drv_priv(vq); | 168 | struct skeleton *skel = vb2_get_drv_priv(vq); |
171 | 169 | ||
@@ -182,7 +180,6 @@ static int queue_setup(struct vb2_queue *vq, | |||
182 | 180 | ||
183 | if (vq->num_buffers + *nbuffers < 3) | 181 | if (vq->num_buffers + *nbuffers < 3) |
184 | *nbuffers = 3 - vq->num_buffers; | 182 | *nbuffers = 3 - vq->num_buffers; |
185 | alloc_ctxs[0] = skel->alloc_ctx; | ||
186 | 183 | ||
187 | if (*nplanes) | 184 | if (*nplanes) |
188 | return sizes[0] < skel->format.sizeimage ? -EINVAL : 0; | 185 | return sizes[0] < skel->format.sizeimage ? -EINVAL : 0; |
@@ -820,6 +817,7 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
820 | q = &skel->queue; | 817 | q = &skel->queue; |
821 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 818 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
822 | q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; | 819 | q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; |
820 | q->dev = &pdev->dev; | ||
823 | q->drv_priv = skel; | 821 | q->drv_priv = skel; |
824 | q->buf_struct_size = sizeof(struct skel_buffer); | 822 | q->buf_struct_size = sizeof(struct skel_buffer); |
825 | q->ops = &skel_qops; | 823 | q->ops = &skel_qops; |
@@ -850,12 +848,6 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
850 | if (ret) | 848 | if (ret) |
851 | goto free_hdl; | 849 | goto free_hdl; |
852 | 850 | ||
853 | skel->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
854 | if (IS_ERR(skel->alloc_ctx)) { | ||
855 | dev_err(&pdev->dev, "Can't allocate buffer context"); | ||
856 | ret = PTR_ERR(skel->alloc_ctx); | ||
857 | goto free_hdl; | ||
858 | } | ||
859 | INIT_LIST_HEAD(&skel->buf_list); | 851 | INIT_LIST_HEAD(&skel->buf_list); |
860 | spin_lock_init(&skel->qlock); | 852 | spin_lock_init(&skel->qlock); |
861 | 853 | ||
@@ -885,13 +877,11 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
885 | 877 | ||
886 | ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); | 878 | ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); |
887 | if (ret) | 879 | if (ret) |
888 | goto free_ctx; | 880 | goto free_hdl; |
889 | 881 | ||
890 | dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n"); | 882 | dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n"); |
891 | return 0; | 883 | return 0; |
892 | 884 | ||
893 | free_ctx: | ||
894 | vb2_dma_contig_cleanup_ctx(skel->alloc_ctx); | ||
895 | free_hdl: | 885 | free_hdl: |
896 | v4l2_ctrl_handler_free(&skel->ctrl_handler); | 886 | v4l2_ctrl_handler_free(&skel->ctrl_handler); |
897 | v4l2_device_unregister(&skel->v4l2_dev); | 887 | v4l2_device_unregister(&skel->v4l2_dev); |
@@ -907,7 +897,6 @@ static void skeleton_remove(struct pci_dev *pdev) | |||
907 | 897 | ||
908 | video_unregister_device(&skel->vdev); | 898 | video_unregister_device(&skel->vdev); |
909 | v4l2_ctrl_handler_free(&skel->ctrl_handler); | 899 | v4l2_ctrl_handler_free(&skel->ctrl_handler); |
910 | vb2_dma_contig_cleanup_ctx(skel->alloc_ctx); | ||
911 | v4l2_device_unregister(&skel->v4l2_dev); | 900 | v4l2_device_unregister(&skel->v4l2_dev); |
912 | pci_disable_device(skel->pdev); | 901 | pci_disable_device(skel->pdev); |
913 | } | 902 | } |