Perf-based event notification for sock_ops
Subsystems (6)
PATCH v2 1/2 bpf: add perf-event notificaton support for sock_ops
In reply to Sowmini VaradhanThis patch allows eBPF programs that use sock_ops to send perf-based event notifications using bpf_perf_event_output()
--- net/core/filter.c | 19 +++++++++++++++++++ 1 files changed, 19 insertions(+), 0 deletions(-)
net/core/filter.c +19 -0
@@ -4048,6 +4048,23 @@ static unsigned long bpf_xdp_copy(void *dst_buff, const void *src_buff,return ret; } +BPF_CALL_5(bpf_sock_opts_event_output, struct bpf_sock_ops *, skops, + struct bpf_map *, map, u64, flags, void *, data, u64, size) +{ +return bpf_event_output (map, flags, data, size,NULL ,0 ,NULL ); +} + +static const struct bpf_func_proto bpf_sock_ops_event_output_proto = { + .func = bpf_sock_opts_event_output, + .gpl_only = true, + .ret_type =RET_INTEGER , + .arg1_type =ARG_PTR_TO_CTX , + .arg2_type =ARG_CONST_MAP_PTR , + .arg3_type =ARG_ANYTHING , + .arg4_type =ARG_PTR_TO_MEM , + .arg5_type =ARG_CONST_SIZE_OR_ZERO , +}; +static const struct bpf_func_proto bpf_setsockopt_proto = { .func = bpf_setsockopt, .gpl_only = false,
@@ -5226,6 +5243,8 @@ bool bpf_helper_changes_pkt_data(void *func) sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) { switch (func_id) { + case BPF_FUNC_perf_event_output: + return &bpf_sock_ops_event_output_proto;case BPF_FUNC_setsockopt:return &bpf_setsockopt_proto;case BPF_FUNC_getsockopt:
Signature · 1 line
1.7.1
PATCH v2 2/2 selftests/bpf: add a test case for sock_ops perf-event notification
In reply to Sowmini VaradhanThis patch provides a tcp_bpf based eBPF sample. The test
- ncat(1) as the TCP client program to connect() to a port with the intention of triggerring SYN retransmissions: we first install an iptables DROP rule to make sure ncat SYNs are resent (instead of aborting instantly after a TCP RST)
- has a bpf kernel module that sends a perf-event notification for each TCP retransmit, and also tracks the number of such notifications sent in the global_map
The test passes when the number of event notifications intercepted in user-space matches the value in the global_map.
---
V2: inline call to sys_perf_event_open() following the style of existing code in kselftests/bpf
tools/testing/selftests/bpf/Makefile | 4 +- tools/testing/selftests/bpf/test_tcpnotify.h | 19 ++ tools/testing/selftests/bpf/test_tcpnotify_kern.c | 95 +++++++++++ tools/testing/selftests/bpf/test_tcpnotify_user.c | 186 +++++++++++++++++++++ 4 files changed, 303 insertions(+), 1 deletions(-) create mode 100644 tools/testing/selftests/bpf/test_tcpnotify.h create mode 100644 tools/testing/selftests/bpf/test_tcpnotify_kern.c create mode 100644 tools/testing/selftests/bpf/test_tcpnotify_user.c
tools/testing/selftests/bpf/Makefile +3 -1
@@ -24,12 +24,13 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \ test_sock test_btf test_sockmap test_lirc_mode2_user get_cgroup_id_user \ test_socket_cookie test_cgroup_storage test_select_reuseport test_section_names \ - test_netcnt + test_netcnt test_tcpnotify_user TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \ test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \ + test_tcpnotify_kern.o \ sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \ sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o \ test_btf_haskv.o test_btf_nokv.o test_sockmap_kern.o test_tunnel_kern.o \
@@ -74,6 +75,7 @@ $(OUTPUT)/test_sock_addr: cgroup_helpers.c $(OUTPUT)/test_socket_cookie: cgroup_helpers.c $(OUTPUT)/test_sockmap: cgroup_helpers.c $(OUTPUT)/test_tcpbpf_user: cgroup_helpers.c +$(OUTPUT)/test_tcpnotify_user: cgroup_helpers.c trace_helpers.c $(OUTPUT)/test_progs: trace_helpers.c $(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c $(OUTPUT)/test_cgroup_storage: cgroup_helpers.c
tools/testing/selftests/bpf/test_tcpnotify.h new file +19 -0
@@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef _TEST_TCPBPF_H +#define _TEST_TCPBPF_H + +struct tcpnotify_globals { +__u32 total_retrans; +__u32 ncalls; +}; + +struct tcp_notifier { +__u8 type; +__u8 subtype; +__u8 source; +__u8 hash; +}; + +#define TESTPORT 12877 +#endif
tools/testing/selftests/bpf/test_tcpnotify_kern.c new file +95 -0
95 lines not on this page · raw message
tools/testing/selftests/bpf/test_tcpnotify_user.c new file +186 -0
186 lines not on this page · raw message
Signature · 1 line
1.7.1
v2 cover Perf-based event notification for sock_ops
This patchset uses eBPF perf-event based notification mechanism to solve the problem described in
https://marc.info/?l=linux-netdev&m=154022219423571&w=2.
Thanks to Daniel Borkmann for feedback/input.
V2: inlined the call to sys_perf_event_open() following the style
of existing code in kselftests/bpf
The problem statement is
We would like to monitor some subset of TCP sockets in user-space, (the monitoring application would define 4-tuples it wants to monitor) using TCP_INFO stats to analyze reported problems. The idea is to use those stats to see where the bottlenecks are likely to be ("is it application-limited?" or "is there evidence of BufferBloat in the path?" etc)
Today we can do this by periodically polling for tcp_info, but this could be made more efficient if the kernel would asynchronously notify the application via tcp_info when some "interesting" thresholds (e.g., "RTT variance > X", or "total_retrans > Y" etc) are reached. And to make this effective, it is better if we could apply the threshold check *before* constructing the tcp_info netlink notification, so that we don't waste resources constructing notifications that will be discarded by the filter.
This patchset solves the problem by adding perf-event based notification support for sock_ops (Patch1). The eBPF kernel module can thus be designed to apply any desired filters to the bpf_sock_ops and trigger a perf-event notification based on the verdict from the filter. The uspace component can use these perf-event notifications to either read any state managed by the eBPF kernel module, or issue a TCP_INFO netlink call if desired.
Patch 2 provides a simple example that shows how to use this infra (and also provides a test case for it)
Sowmini Varadhan (2):
bpf: add perf-event notificaton support for sock_ops selftests/bpf: add a test case for sock_ops perf-event notification
net/core/filter.c | 19 ++ tools/testing/selftests/bpf/Makefile | 4 +- tools/testing/selftests/bpf/test_tcpnotify.h | 19 ++ tools/testing/selftests/bpf/test_tcpnotify_kern.c | 95 +++++++++++ tools/testing/selftests/bpf/test_tcpnotify_user.c | 186 +++++++++++++++++++++ 5 files changed, 322 insertions(+), 1 deletions(-) create mode 100644 tools/testing/selftests/bpf/test_tcpnotify.h create mode 100644 tools/testing/selftests/bpf/test_tcpnotify_kern.c create mode 100644 tools/testing/selftests/bpf/test_tcpnotify_user.c