Solnix Compiler - eBPF Support Details
Supported eBPF Program Types
Networking Programs
XDP (eXpress Data Path)
- Section:
xdp - Context:
struct xdp_md *ctx - Return Values:
XDP_PASS(2),XDP_DROP(1),XDP_TX(3),XDP_ABORTED(0),XDP_REDIRECT(4) - Use Case: Fast packet processing at the network driver level
TC (Traffic Control)
- Sections:
tc/classifier- Classic TC classifiertcx/ingress/tc/ingress- TCX ingress hooktcx/egress/tc/egress- TCX egress hook- Context:
struct __sk_buff *ctx - Return Values:
TC_ACT_OK(0),TC_ACT_SHOT(2),TC_ACT_UNSPEC(-1) - Use Case: Traffic control and packet filtering
Socket Programs
- Sections:
sk_skb/stream_parser- Stream parsersk_skb/stream_verdict- Stream verdictsk_msg- Socket message- Context:
struct __sk_buff *ctx(for sk_skb),struct sk_msg_md *ctx(for sk_msg) - Return Values:
SK_PASS(1),SK_DROP(0) - Use Case: Socket-level packet processing
Cgroup Programs
- Sections:
cgroup/skb/ingress- Cgroup SKB ingresscgroup/skb/egress- Cgroup SKB egresscgroup/sock- Cgroup socketcgroup/sock_addr- Cgroup socket address- Context:
struct __sk_buff *ctx(for skb),struct bpf_sock *ctx(for sock),struct bpf_sock_addr *ctx(for sock_addr) - Return Values:
SK_PASS(1),SK_DROP(0), or1(allow) for sock_addr - Use Case: Cgroup-based network filtering and policy enforcement
Tracing Programs
Kprobe/Kretprobe
- Sections:
kprobe/<function>/kretprobe/<function> - Context:
struct pt_regs *ctx - Return Values:
0(success) - Use Case: Dynamic kernel function tracing
Tracepoint
- Sections:
tracepoint/<category>/<event>(e.g.,tracepoint/syscalls/sys_enter_execve) - Context:
void *ctx(typed based on tracepoint) - Return Values:
0(success) - Use Case: Static kernel event tracing
Raw Tracepoint
- Sections:
raw_tracepoint/<event> - Context:
struct bpf_raw_tracepoint_args *ctx - Return Values:
0(success) - Use Case: Fast tracepoint access without type information
Fentry/Fexit
- Sections:
fentry/<function>/fexit/<function> - Context: Function arguments (typed)
- Return Values:
0(success) - Use Case: Modern kernel function entry/exit tracing
Security Programs
LSM (Linux Security Module)
- Sections:
lsm/<hook>(e.g.,lsm/file_open) - Context: Hook-specific context
- Return Values:
0(allow),-EPERM(deny) - Use Case: Security policy enforcement
Supported Map Types
Hash Maps
- Type:
.hash - Syntax:
type: .hash; - Use Case: Key-value storage with hash-based lookup
- BPF Type:
BPF_MAP_TYPE_HASH
Array Maps
- Type:
.array - Syntax:
type: .array; - Use Case: Indexed array storage
- BPF Type:
BPF_MAP_TYPE_ARRAY
Ring Buffer
- Type:
.ringbuf - Syntax:
type: .ringbuf; - Use Case: Efficient data streaming from kernel to userspace
- BPF Type:
BPF_MAP_TYPE_RINGBUF - Note: No key/value types required
LRU Hash
- Type:
.lru_hash - Syntax:
type: .lru_hash; - Use Case: Hash map with LRU eviction
- BPF Type:
BPF_MAP_TYPE_LRU_HASH
Program Array
- Type:
.prog_array - Syntax:
type: .prog_array; - Use Case: Array of eBPF programs for tail calls
- BPF Type:
BPF_MAP_TYPE_PROG_ARRAY
Perf Event Array
- Type:
.perf_event_array - Syntax:
type: .perf_event_array; - Use Case: Sending events to userspace via perf buffers
- BPF Type:
BPF_MAP_TYPE_PERF_EVENT_ARRAY
Supported Data Types
Integer Types
- u32: Unsigned 32-bit integer (
__u32in C) - u64: Unsigned 64-bit integer (
__u64in C) - i32: Signed 32-bit integer (
__s32in C) - i64: Signed 64-bit integer (
__s64in C)
Variable Storage Types
- reg: Register variable (stored in eBPF register)
- imm: Immediate value (compile-time constant)
- heap: Map pointer (result of map lookup)
Context Access Methods
Packet Data Access (Positive Offset)
When ctx.load_*() is called with a positive offset, it accesses packet data:
- ctx.load_u8(offset) - Load unsigned 8-bit value from packet
- ctx.load_u16(offset) - Load unsigned 16-bit value from packet
- ctx.load_u32(offset) - Load unsigned 32-bit value from packet
- ctx.load_u64(offset) - Load unsigned 64-bit value from packet
- ctx.load_i8(offset) - Load signed 8-bit value from packet
- ctx.load_i16(offset) - Load signed 16-bit value from packet
- ctx.load_i32(offset) - Load signed 32-bit value from packet
- ctx.load_i64(offset) - Load signed 64-bit value from packet
Context Field Access (Negative Offset)
When ctx.load_*() is called with a negative offset, it accesses context structure fields.
Supported Operations
Binary Operations
- Addition:
+(Add) - Subtraction:
-(Sub) - Multiplication:
*(Mul) - Division:
/(Div) - Modulo:
%(Mod)
Assignment Operations
- Simple Assignment:
= - Add and Assign:
+= - Subtract and Assign:
-= - Multiply and Assign:
*= - Divide and Assign:
/= - Modulo and Assign:
%=
Map Operations
- Map Lookup:
map_name.lookup(key_expr)- Returns a heap pointer - Dereference:
*ptr- Dereference a pointer (typically map value pointer) - Null Check:
guard(ptr)- Conditional block that only executes if pointer is non-null
Control Flow
- Return Statement:
return <value>; - If Guard:
if guard(ptr) { ... }- Conditional execution based on pointer null check
Map Declaration Syntax
map map_name {
type: .hash | .array | .ringbuf | .lru_hash | .prog_array | .perf_event_array;
key: u32 | u64 | i32 | i64;
value: u32 | u64 | i32 | i64;
max: <number>;
}
Unit (Program) Declaration Syntax
unit program_name {
section: "<section_name>";
license: "GPL" | "<other_license>";
// Variable declarations
reg var_name = <expression>;
imm const_name = <number>;
heap ptr_name = map_name.lookup(<key>);
// Operations
*ptr = <value>;
*ptr += <value>;
// Control flow
if guard(ptr) {
// statements
}
return <value>;
}
Supported eBPF Helpers
The compiler includes standard eBPF helper headers:
- #include "vmlinux.h" - Kernel type definitions
- #include <bpf/bpf_helpers.h> - Standard eBPF helpers
- #include <bpf/bpf_endian.h> - Endianness conversion helpers
Common helpers available (via bpf_helpers.h):
- bpf_map_lookup_elem() - Map lookup (generated automatically)
- bpf_map_update_elem() - Map update (via assignments)
- bpf_map_delete_elem() - Map delete
- bpf_get_current_pid_tgid() - Get process/thread ID
- bpf_get_current_uid_gid() - Get user/group ID
- And many more standard eBPF helpers
Compilation Process
- Lexing: Tokenizes the
.snxsource file - Parsing: Builds AST from tokens
- Semantic Analysis: Validates sections, types, and map declarations
- IR Lowering: Converts AST to intermediate representation
- Code Generation: Emits eBPF C code
- Object Compilation: Compiles C to eBPF object file using clang
Limitations and Notes
- Map Types: While the parser accepts
ringbuf,lru_hash,prog_array, andperf_event_array, full support may vary in code generation - Context Access: Context field access (negative offsets) is supported but packet bounds checking is program-type specific
- Helper Functions: Direct helper function calls are not yet supported in the language syntax (only via context methods)
- Loops: Currently no loop constructs (while, for) - programs are linear
- Functions: No user-defined functions - all code is in the unit body
- Tail Calls: Program arrays are supported but tail call syntax is not yet implemented
Example Programs
Current Test Program (test.snx)
map results {
type: .array;
key: u32;
value: u64;
max: 8;
}
unit sample_tracepoint {
section: "tracepoint/syscalls/sys_enter_execve";
license: "GPL";
reg a = 10;
reg b = 20;
reg c = a + b;
imm k0 = 0;
heap p0 = results.lookup(k0);
*p0 = c;
return 0;
}
XDP Example (from README)
map connection_counter {
type: .hash;
key: u32;
value: u64;
max: 1024;
}
unit filter_packets {
section: "xdp";
license: "GPL";
reg src_ip = ctx.load_u32(26);
heap count_ptr = connection_counter.lookup(src_ip);
if guard(count_ptr) {
*count_ptr += 1;
}
return 1;
}