Hi all,
I'd like to propose adding an eBPF-based forwarding backend to rtpengine,
and get feedback on the approach before I invest further.
Motivation
The use case driving this is managed Kubernetes. Loading an out-of-tree kernel module has non-trivial security and operational burden. Certain providers enforce kernel module signature verification and only accept their own signatures. So there is no way to load our own module without disabling signature verification on the node.
Beyond that:
- A privileged DaemonSet (CAP_SYS_MODULE) is needed to load the kernel module. eBPF only needs CAP_BPF and CAP_NET_ADMIN.
- A bug in the module could mean code execution in kernel context, and can panic a the node. A misbehaving BPF program would just drop the packet.
To be clear, this is not an attempt to beat the kernel module. I don't expect eBPF to achieve better throughput. However it gives us a fast path that bypasses user-space in an environment where loading the module is unattractive.
Proposed changes
- Carve the kernelize machinery out of media_socket.c to avoid mixing packet handling with fast-path registration.
- Introduce an abstraction for a forwarding backend. Each backend (kernel, ebpf) advertises what streams it supports: RTP, RTCP, SRTP, recording, etc. Unsupported streams fallback to user-space. The kernel module becomes the first backend, so behaviour doesn't change, it just gets dispatched through a vtable instead of being called directly.
- The eBPF backend, which hooks TC ingress and implements a subset of the kernel module features as a proof-of-concept but can be iterated upon.
Scope
The first iteration supports plain RTP UDP stream handling with a single output. The eBPF program would match the target, rewrite source and destination, patch the checksums, redirect.
Payload inspection, SRTP, ICE/STUN, DTLS are out-of-scope for the first iteration, and will continue using the user-space path. Support could be considered for future iterations.
Note: eBPF has no crypto, so SRTP support isn't quite possible yet.
Feedback welcome, particularly on the redirect approach, and whether the abstraction idea looks right.
Thanks!