1+ // Ring Buffer Demonstration for KernelScript
2+ // Shows complete ring buffer API usage from eBPF to userspace
3+
4+ // XDP context struct (from BTF)
5+ struct xdp_md {
6+ data: u64,
7+ data_end: u64,
8+ data_meta: u64,
9+ ingress_ifindex: u32,
10+ rx_queue_index: u32,
11+ egress_ifindex: u32,
12+ }
13+
14+ // XDP action enum (from BTF)
15+ enum xdp_action {
16+ XDP_ABORTED = 0 ,
17+ XDP_DROP = 1 ,
18+ XDP_PASS = 2 ,
19+ XDP_REDIRECT = 3 ,
20+ XDP_TX = 4 ,
21+ }
22+
23+ // Event structures for different types of events
24+ struct NetworkEvent {
25+ timestamp: u64,
26+ event_type: u32,
27+ src_ip: u32,
28+ dst_ip: u32,
29+ port: u16,
30+ protocol: u8,
31+ packet_size: u16,
32+ }
33+
34+ struct SecurityEvent {
35+ timestamp: u64,
36+ severity: u32,
37+ event_id: u32,
38+ pid: u32,
39+ message: u8[64 ],
40+ }
41+
42+ // Ring buffer declarations
43+ var network_events : ringbuf< NetworkEvent> ( 8192 ) // 8KB ring buffer
44+ pin var security_events : ringbuf< SecurityEvent> ( 16384 ) // 16KB pinned ring buffer
45+
46+ // Stats for monitoring
47+ struct Stats {
48+ events_submitted: u64,
49+ events_dropped: u64,
50+ buffer_full_count: u64,
51+ }
52+
53+ var stats : hash< u32, Stats> ( 1 )
54+
55+ @helper
56+ fn get_timestamp() - > u64 {
57+ return 1234567890 // Demo timestamp - would be bpf_ktime_get_ns() in real code
58+ }
59+
60+ @helper
61+ fn get_packet_info( ctx: * xdp_md) - > NetworkEvent {
62+ var event = NetworkEvent {
63+ timestamp: get_timestamp() ,
64+ event_type: 1 , // PACKET_RECEIVED
65+ src_ip: 0x7f000001, // 127.0.0.1
66+ dst_ip: 0x7f000002, // 127.0.0.2
67+ port: 80 ,
68+ protocol: 6 , // TCP
69+ packet_size: 64 ,
70+ }
71+ return event
72+ }
73+
74+ // XDP program that generates network events
75+ @xdp fn network_monitor( ctx: * xdp_md) - > xdp_action {
76+ var key: u32 = 0
77+ var stat = stats[key]
78+ if ( stat == none) {
79+ var init_stat = Stats { events_submitted: 0 , events_dropped: 0 , buffer_full_count: 0 }
80+ stats[key] = init_stat
81+ stat = stats[key]
82+ }
83+
84+ // Try to reserve space in ring buffer
85+ var reserved = network_events.reserve()
86+ if ( reserved != null) {
87+ // Successfully reserved space - build event and submit
88+ // For now, just submit the reserved space
89+ network_events.submit( reserved)
90+ stat.events_submitted = stat.events_submitted + 1
91+ } else {
92+ // Ring buffer is full - increment drop counter
93+ stat.events_dropped = stat.events_dropped + 1
94+ stat.buffer_full_count = stat.buffer_full_count + 1
95+ }
96+
97+ return XDP_PASS
98+ }
99+
100+ // Security monitoring program
101+ @kprobe fn security_monitor() - > i32 {
102+ var reserved = security_events.reserve()
103+ if ( reserved != null) {
104+ // Successfully reserved space - submit the event
105+ security_events.submit( reserved)
106+ } else {
107+ // Handle full buffer - could discard or try alternative logging
108+ // Note: discard not needed for failed reserve
109+ }
110+
111+ return 0
112+ }
113+
114+ // Userspace event handling
115+
116+ // Event handler for network events
117+ fn network_event_handler( event: * NetworkEvent) - > i32 {
118+ print ( "Network Event:" )
119+ print ( " Timestamp: " , event- > timestamp)
120+ print ( " Type: " , event- > event_type)
121+ print ( " Source IP: " , event- > src_ip)
122+ print ( " Destination IP: " , event- > dst_ip)
123+ print ( " Port: " , event- > port)
124+ print ( " Protocol: " , event- > protocol)
125+ print ( " Packet Size: " , event- > packet_size)
126+ return 0
127+ }
128+
129+ // Event handler for security events
130+ fn security_event_handler( event: * SecurityEvent) - > i32 {
131+ print ( "Security Event:" )
132+ print ( " Timestamp: " , event- > timestamp)
133+ print ( " Severity: " , event- > severity)
134+ print ( " Event ID: " , event- > event_id)
135+ print ( " PID: " , event- > pid)
136+ print ( " Message: [security event]" )
137+ return 0
138+ }
139+
140+ // Custom callback functions (override weak symbols)
141+ fn network_events_callback( event: * NetworkEvent) - > i32 {
142+ return network_event_handler( event)
143+ }
144+
145+ fn security_events_callback( event: * SecurityEvent) - > i32 {
146+ return security_event_handler( event)
147+ }
148+
149+ // Main userspace program
150+ fn main() - > i32 {
151+ print ( "Starting ring buffer demonstration..." )
152+
153+ // Load and attach eBPF programs
154+ var network_prog = load( network_monitor)
155+ var security_prog = load( security_monitor)
156+
157+ if ( network_prog == null || security_prog == null) {
158+ print ( "Failed to load eBPF programs" )
159+ return 1
160+ }
161+
162+ // Attach programs
163+ var net_result = attach( network_prog, "eth0" , 0 ) // Attach XDP to eth0
164+ var sec_result = attach( security_prog, "sys_openat" , 0 ) // Attach kprobe to sys_openat
165+
166+ if ( net_result != 0 || sec_result != 0 ) {
167+ print ( "Failed to attach eBPF programs" )
168+ return 1
169+ }
170+
171+ print ( "eBPF programs loaded and attached successfully" )
172+ print ( "Starting event processing..." )
173+ print ( "Press Ctrl+C to stop" )
174+
175+ // Start processing ring buffer events using the builtin dispatch() function
176+ dispatch( network_events, security_events)
177+
178+ return 0
179+ }
180+
181+ // Utility function to get statistics
182+ fn print_stats() - > i32 {
183+ print ( "=== Ring Buffer Statistics ===" )
184+ // In a real implementation, would read from stats map
185+ print ( "Network events processed: [would read from eBPF map]" )
186+ print ( "Security events processed: [would read from eBPF map]" )
187+ print ( "Buffer full events: [would read from eBPF map]" )
188+ return 0
189+ }
0 commit comments