Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pythops/oryx/llms.txt

Use this file to discover all available pages before exploring further.

Oryx is split across two execution contexts: a small eBPF program that runs inside the Linux kernel as a TC (Traffic Control) classifier, and a userspace application built on Aya and Ratatui. The kernel program sees every packet on the selected interface before the networking stack processes it, decodes the relevant headers, and writes the result into a shared ring buffer. The userspace process drains that buffer in a mio event loop, parses the raw bytes into typed Rust structures, and renders the TUI in real time. The current release is 0.8.0.

Workspace layout

The repository is a Cargo workspace with four crates:

oryx-ebpf

eBPF kernel programs. Compiled with #![no_std] for the BPF target using aya-ebpf. Contains the single oryx TC classifier entry point and all eBPF maps.

oryx-common

Shared data types that cross the kernel/userspace boundary: RawData, RawFrame, RawPacket, ProtoHdr, IgmpHdr, and the Protocol / TransportProtocol / NetworkProtocol / LinkProtocol enums. Also compiled with #![no_std] so it can be used by oryx-ebpf.

oryx-tui

Userspace TUI application. Loads the eBPF program with Aya, manages all eBPF maps, processes packets, and renders the interface with Ratatui and crossterm.

xtask

Build orchestration. Invoked via cargo xtask build or cargo xtask run. Compiles oryx-ebpf for the BPF target first, then compiles oryx-tui for the host.

Data flow

Network interface
       │  (all traffic)

┌─────────────────────────────┐
│   oryx TC classifier        │  kernel space (eBPF)
│                             │
│  1. Parse Ethernet header   │
│  2. Match EtherType         │
│  3. Decode IP / ARP header  │
│  4. Decode transport header │
│  5. Apply protocol filters  │
│  6. Apply firewall rules    │
│  7. Write RawData to DATA   │
│     RingBuf map             │
└────────────┬────────────────┘
             │  RingBuf ("DATA" map)

┌─────────────────────────────┐
│   Aya userspace thread      │  userspace (oryx-tui)
│                             │
│  mio event loop             │
│  ├─ RingBuffer::next()      │
│  ├─ Deserialise RawData     │
│  └─ Push to PacketStore     │
└────────────┬────────────────┘
             │  kanal channel

┌─────────────────────────────┐
│   Ratatui render loop       │
│                             │
│  ├─ Inspection section      │
│  ├─ Firewall section        │
│  ├─ Stats section           │
│  ├─ Metrics section         │
│  └─ Alert section           │
└─────────────────────────────┘

Key components

RingBuffer and the DATA map

The eBPF side declares a RingBuf map named DATA:
#[map]
static DATA: RingBuf = RingBuf::with_byte_size(4096 * RawFrame::LEN as u32, 0);
Each captured packet is written as a RawData value — a fixed-size repr(C) struct containing the Ethernet frame (RawFrame) and an optional PID for egress packets. The PID is available only on egress when the bpf_get_current_pid_tgid helper is enabled. On the userspace side, RingBuffer wraps the Aya RingBuf handle and implements mio::event::Source so it can be polled efficiently without spinning:
pub struct RingBuffer<'a> {
    pub buffer: RingBuf<&'a mut MapData>,
}

eBPF maps

MapTypePurpose
DATARingBufKernel-to-userspace packet stream
NETWORK_FILTERSArray<u32>Per-protocol network filter flags (8 slots)
TRANSPORT_FILTERSArray<u32>Per-protocol transport filter flags (8 slots)
LINK_FILTERSArray<u32>Per-protocol link filter flags (8 slots)
TRAFFIC_DIRECTION_FILTERArray<u8>Direction filter flag
BLOCKLIST_IPV4HashMap<u32, [u16; 32]>IPv4 firewall rules (up to 32 entries, 32 ports each)
BLOCKLIST_IPV6HashMap<u128, [u16; 32]>IPv6 firewall rules (up to 32 entries, 32 ports each)

Traffic direction

Two TC programs are attached — one on ingress and one on egress — sharing the same classifier function. Direction is communicated via the TRAFFIC_DIRECTION global variable (-1 = ingress, 1 = egress). The TRAFFIC_DIRECTION_FILTER map can suppress one direction entirely.

TUI sections

The Ratatui interface is divided into five sections, accessible via Tab / Shift+Tab:
SectionDescription
InspectionLive packet list with fuzzy search (/) and per-packet detail view (i)
FirewallCreate, edit, enable/disable, and persist eBPF-backed firewall rules
StatsTraffic statistics including top destinations
MetricsMetrics explorer for bandwidth and packet counts
AlertDisplays detected anomalies such as potential SYN flood attacks

Firewall

Firewall rules are enforced inside the kernel classifier before any data is written to the ring buffer. When a TCP, UDP, or SCTP packet arrives, the eBPF program looks up the relevant address in BLOCKLIST_IPV4 or BLOCKLIST_IPV6. If the address is found and either all ports are blocked (blocked_ports[0] == 0) or the specific port matches, the packet is dropped with TC_ACT_SHOT. Rules can be saved to ~/oryx/firewall.json and are reloaded on the next run.

Key dependencies

CrateVersionRole
aya0.13Load and manage eBPF programs and maps from userspace
aya-ebpf0.1.1eBPF-side macros and helpers (#[map], #[classifier], etc.)
ratatui0.30Terminal UI framework
crossterm0.29Cross-platform terminal backend for Ratatui
mio1Async I/O event loop for polling the ring buffer
kanal0.1Fast MPMC channels for passing packets between threads
network-typesgitZero-copy Rust structs for Ethernet, IP, TCP, UDP, SCTP, ICMP, IGMP, ARP headers
clap4CLI argument parsing
serde_json1Serialise/deserialise firewall rules

Build docs developers (and LLMs) love