High-performance user-space packet processing pipeline using AF_XDP. Bypasses the Linux kernel networking stack for low-latency, deterministic packet handling.
- Kernel-bypass via XDP + AF_XDP sockets
- Two-thread pipeline (poller + worker) with CPU pinning
- Lock-free SPSC queue (LFQueue) for inter-thread communication
- Batch RX, batch buffer recycling, CPU prefetching
- Full protocol parsing (Ethernet/IPv4/UDP/TCP)
- TCP flow tracking with state detection
- Latency measurement with percentiles (p50, p99, p999)
- Zero malloc in hot path
- Linux (kernel 5.4+)
libxdpandlibbpf(development headers)clang(for BPF compilation)cmake(>= 3.16)g++(C++17 support)bpftool(for map pinning)
Install on Ubuntu/Debian:
sudo apt install cmake build-essential clang libbpf-dev libxdp-dev linux-tools-commongit clone --recurse-submodules https://github.com/shuraih775/BriskNet.git
cd BriskNet
makeThis runs CMake under the hood and produces binaries in build/bin/.
make bpfmake link
make pin
make unlinkmake runonce done running the code
make link
make unpin
make unlink
Press Ctrl+C to stop. Stats are printed every second and saved to benchmark/results.txt.
Run a full benchmark (sender + receiver):
make bench MODE=xdp DUR=10 TARGET=127.0.0.1 PORT=9000 PKT=64Run components individually:
# Terminal 1: start BriskNet
make run
# Terminal 2: fire UDP packets
make sender TARGET=127.0.0.1 PORT=9000 PKT=64Kernel baseline comparison:
make bench MODE=kernel DUR=10| Command | Description |
|---|---|
make |
Build all targets |
make run |
Build + run BriskNet (sudo) |
make clean |
Remove build directory |
make bpf |
Compile XDP BPF program |
make link |
Attach XDP to NIC (wlo1) |
make unlink |
Detach XDP from NIC |
make pin |
Pin xsks_map to bpffs |
make bench |
Run full benchmark |
make sender |
Run UDP sender |
make receiver |
Run kernel UDP receiver |
make help |
Show all commands |
BriskNet components can be used independently in other projects:
#include "umem.h"
#include "af_xdp_socket.h"
struct umem_info umem;
umem_create(&umem);
struct xsk_socket_info *xsk;
xsk_socket_create(&xsk, &umem, "eth0", 0);
// Access RX ring, process packets, recycle buffers#include "packet_parser.h"
struct parsed_packet pkt;
if (parse_packet(raw_data, len, &pkt) == 0) {
// pkt.protocol, pkt.src_ip, pkt.dst_port, pkt.payload, etc.
}#include "lfqueue_wrapper.h"
lfqueue_t *q = lfqueue_create(8192);
lfqueue_enqueue(q, value);
lfqueue_flush(q);
uint64_t out;
lfqueue_dequeue(q, &out);
lfqueue_destroy(q);#include "tcp_flow.h"
struct tcp_flow_table flows;
tcp_flow_table_init(&flows);
enum tcp_event ev = tcp_flow_process(&flows, &parsed_pkt);Key constants in src/main.c:
| Constant | Default | Description |
|---|---|---|
POLLER_CPU_CORE |
2 | CPU core for poller thread |
WORKER_CPU_CORE |
3 | CPU core for worker thread |
BATCH_SIZE |
64 | Max packets per batch |
QUEUE_SIZE |
8192 | LFQueue capacity |
NIC interface is set in main() — change "wlo1" to your interface.
For detailed design decisions, data flow diagrams, and performance optimization rationale, see architecture.md.