1pub mod attachments;
13pub mod context;
14pub mod fs;
15pub mod map;
16pub mod program;
17pub mod syscalls;
18
19use crate::bpf::attachments::EbpfAttachments;
20use crate::bpf::map::{BpfMapHandle, BpfMapId, WeakBpfMapHandle};
21use crate::bpf::program::{ProgramHandle, ProgramId, WeakProgramHandle};
22use ebpf::MapFlags;
23use starnix_sync::{EbpfStateLock, LockDepMutex};
24use starnix_uapi::{bpf_map_type, bpf_map_type_BPF_MAP_TYPE_SK_STORAGE};
25use std::collections::BTreeMap;
26use std::ops::Bound;
27use std::sync::Arc;
28use zerocopy::IntoBytes as _;
29
30struct WeakMapWithType {
31 map_type: bpf_map_type,
32 weak_map: WeakBpfMapHandle,
33}
34
35impl WeakMapWithType {
36 fn new(map: &BpfMapHandle) -> Self {
37 Self { map_type: map.schema.map_type, weak_map: Arc::downgrade(map) }
38 }
39}
40
41#[derive(Default)]
43pub struct EbpfState {
44 pub attachments: EbpfAttachments,
45
46 programs: LockDepMutex<BTreeMap<ProgramId, WeakProgramHandle>, EbpfStateLock>,
47 maps: LockDepMutex<BTreeMap<BpfMapId, WeakMapWithType>, EbpfStateLock>,
48}
49
50impl EbpfState {
51 fn register_program(&self, program: &ProgramHandle) {
52 self.programs.lock().insert(program.id(), Arc::downgrade(program));
53 }
54
55 fn unregister_program(&self, id: ProgramId) {
56 self.programs.lock().remove(&id).expect("Missing eBPF program");
57 }
58
59 fn get_next_program_id(&self, start_id: ProgramId) -> Option<ProgramId> {
60 self.programs
61 .lock()
62 .range((Bound::Excluded(start_id), Bound::Unbounded))
63 .next()
64 .map(|(k, _)| *k)
65 }
66
67 fn get_program_by_id(&self, id: ProgramId) -> Option<ProgramHandle> {
68 self.programs.lock().get(&id).map(|p| p.upgrade()).flatten()
69 }
70
71 fn register_map(&self, map: &BpfMapHandle) {
72 self.maps.lock().insert(map.id(), WeakMapWithType::new(map));
73 }
74
75 fn unregister_map(&self, id: BpfMapId) {
76 self.maps.lock().remove(&id).expect("Missing eBPF map");
77 }
78
79 fn get_next_map_id(&self, start_id: BpfMapId) -> Option<BpfMapId> {
80 self.maps
81 .lock()
82 .range((Bound::Excluded(start_id), Bound::Unbounded))
83 .next()
84 .map(|(k, _)| *k)
85 }
86
87 fn get_map_by_id(&self, id: BpfMapId) -> Option<BpfMapHandle> {
88 self.maps.lock().get(&id).map(|entry| entry.weak_map.upgrade()).flatten()
89 }
90
91 pub fn remove_sk_storage_entries(&self, cookie: u64) {
94 self.maps.lock().iter().for_each(|(_, entry)| {
95 if entry.map_type == bpf_map_type_BPF_MAP_TYPE_SK_STORAGE
96 && let Some(map) = entry.weak_map.upgrade()
97 {
98 let _ = map.delete(cookie.as_bytes());
99 }
100 });
101 }
102
103 pub fn clone_sk_storage_entries(&self, parent_cookie: u64, child_cookie: u64) {
106 self.maps.lock().iter().for_each(|(_, entry)| {
107 if entry.map_type == bpf_map_type_BPF_MAP_TYPE_SK_STORAGE
108 && let Some(map) = entry.weak_map.upgrade()
109 && map.schema.flags.contains(MapFlags::Clone)
110 {
111 if let Some(mut val) = map.load(parent_cookie.as_bytes()) {
112 let _ = map.update(child_cookie.as_bytes(), (&mut val[..]).into(), 0);
113 }
114 }
115 });
116 }
117}