aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2016-04-18 15:01:24 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-19 20:26:11 -0400
commitbd570ff970a54df653b48ed0cfb373f2ebed083d (patch)
tree85e4ed3aa2bb859cf770247735eb9e7d9a909cb7
parent1e33759c788c78f31d4d6f65bac647b23624734c (diff)
bpf: add event output helper for notifications/sampling/logging
This patch adds a new helper for cls/act programs that can push events to user space applications. For networking, this can be f.e. for sampling, debugging, logging purposes or pushing of arbitrary wake-up events. The idea is similar to a43eec304259 ("bpf: introduce bpf_perf_event_output() helper") and 39111695b1b8 ("samples: bpf: add bpf_perf_event_output example"). The eBPF program utilizes a perf event array map that user space populates with fds from perf_event_open(), the eBPF program calls into the helper f.e. as skb_event_output(skb, &my_map, BPF_F_CURRENT_CPU, raw, sizeof(raw)) so that the raw data is pushed into the fd f.e. at the map index of the current CPU. User space can poll/mmap/etc on this and has a data channel for receiving events that can be post-processed. The nice thing is that since the eBPF program and user space application making use of it are tightly coupled, they can define their own arbitrary raw data format and what/when they want to push. While f.e. packet headers could be one part of the meta data that is being pushed, this is not a substitute for things like packet sockets as whole packet is not being pushed and push is only done in a single direction. Intention is more of a generically usable, efficient event pipe to applications. Workflow is that tc can pin the map and applications can attach themselves e.g. after cls/act setup to one or multiple map slots, demuxing is done by the eBPF program. Adding this facility is with minimal effort, it reuses the helper introduced in a43eec304259 ("bpf: introduce bpf_perf_event_output() helper") and we get its functionality for free by overloading its BPF_FUNC_ identifier for cls/act programs, ctx is currently unused, but will be made use of in future. Example will be added to iproute2's BPF example files. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/bpf.h2
-rw-r--r--kernel/bpf/core.c7
-rw-r--r--kernel/trace/bpf_trace.c27
-rw-r--r--net/core/filter.c2
4 files changed, 38 insertions, 0 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 5fb3c610fa96..f63afdc43bec 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -169,7 +169,9 @@ u64 bpf_tail_call(u64 ctx, u64 r2, u64 index, u64 r4, u64 r5);
169u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); 169u64 bpf_get_stackid(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
170void bpf_fd_array_map_clear(struct bpf_map *map); 170void bpf_fd_array_map_clear(struct bpf_map *map);
171bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp); 171bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp);
172
172const struct bpf_func_proto *bpf_get_trace_printk_proto(void); 173const struct bpf_func_proto *bpf_get_trace_printk_proto(void);
174const struct bpf_func_proto *bpf_get_event_output_proto(void);
173 175
174#ifdef CONFIG_BPF_SYSCALL 176#ifdef CONFIG_BPF_SYSCALL
175DECLARE_PER_CPU(int, bpf_prog_active); 177DECLARE_PER_CPU(int, bpf_prog_active);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index be0abf669ced..e4248fe79513 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -764,14 +764,21 @@ const struct bpf_func_proto bpf_map_delete_elem_proto __weak;
764const struct bpf_func_proto bpf_get_prandom_u32_proto __weak; 764const struct bpf_func_proto bpf_get_prandom_u32_proto __weak;
765const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak; 765const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak;
766const struct bpf_func_proto bpf_ktime_get_ns_proto __weak; 766const struct bpf_func_proto bpf_ktime_get_ns_proto __weak;
767
767const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak; 768const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak;
768const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak; 769const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
769const struct bpf_func_proto bpf_get_current_comm_proto __weak; 770const struct bpf_func_proto bpf_get_current_comm_proto __weak;
771
770const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void) 772const struct bpf_func_proto * __weak bpf_get_trace_printk_proto(void)
771{ 773{
772 return NULL; 774 return NULL;
773} 775}
774 776
777const struct bpf_func_proto * __weak bpf_get_event_output_proto(void)
778{
779 return NULL;
780}
781
775/* Always built-in helper functions. */ 782/* Always built-in helper functions. */
776const struct bpf_func_proto bpf_tail_call_proto = { 783const struct bpf_func_proto bpf_tail_call_proto = {
777 .func = NULL, 784 .func = NULL,
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index b3cc24cb4321..780bcbe1d4de 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -277,6 +277,33 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = {
277 .arg5_type = ARG_CONST_STACK_SIZE, 277 .arg5_type = ARG_CONST_STACK_SIZE,
278}; 278};
279 279
280static DEFINE_PER_CPU(struct pt_regs, bpf_pt_regs);
281
282static u64 bpf_event_output(u64 r1, u64 r2, u64 flags, u64 r4, u64 size)
283{
284 struct pt_regs *regs = this_cpu_ptr(&bpf_pt_regs);
285
286 perf_fetch_caller_regs(regs);
287
288 return bpf_perf_event_output((long)regs, r2, flags, r4, size);
289}
290
291static const struct bpf_func_proto bpf_event_output_proto = {
292 .func = bpf_event_output,
293 .gpl_only = true,
294 .ret_type = RET_INTEGER,
295 .arg1_type = ARG_PTR_TO_CTX,
296 .arg2_type = ARG_CONST_MAP_PTR,
297 .arg3_type = ARG_ANYTHING,
298 .arg4_type = ARG_PTR_TO_STACK,
299 .arg5_type = ARG_CONST_STACK_SIZE,
300};
301
302const struct bpf_func_proto *bpf_get_event_output_proto(void)
303{
304 return &bpf_event_output_proto;
305}
306
280static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id) 307static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id)
281{ 308{
282 switch (func_id) { 309 switch (func_id) {
diff --git a/net/core/filter.c b/net/core/filter.c
index 5d2ac2b9d1c4..218e5de8c402 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2039,6 +2039,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id)
2039 return &bpf_redirect_proto; 2039 return &bpf_redirect_proto;
2040 case BPF_FUNC_get_route_realm: 2040 case BPF_FUNC_get_route_realm:
2041 return &bpf_get_route_realm_proto; 2041 return &bpf_get_route_realm_proto;
2042 case BPF_FUNC_perf_event_output:
2043 return bpf_get_event_output_proto();
2042 default: 2044 default:
2043 return sk_filter_func_proto(func_id); 2045 return sk_filter_func_proto(func_id);
2044 } 2046 }