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 starnix_sync::{EbpfStateLock, LockBefore, Locked, OrderedMutex};
23use starnix_uapi::{bpf_map_type, bpf_map_type_BPF_MAP_TYPE_SK_STORAGE};
24use std::collections::BTreeMap;
25use std::ops::Bound;
26use std::sync::Arc;
27use zerocopy::IntoBytes as _;
28
29struct WeakMapWithType {
30 map_type: bpf_map_type,
31 weak_map: WeakBpfMapHandle,
32}
33
34impl WeakMapWithType {
35 fn new(map: &BpfMapHandle) -> Self {
36 Self { map_type: map.schema.map_type, weak_map: Arc::downgrade(map) }
37 }
38}
39
40#[derive(Default)]
42pub struct EbpfState {
43 pub attachments: EbpfAttachments,
44
45 programs: OrderedMutex<BTreeMap<ProgramId, WeakProgramHandle>, EbpfStateLock>,
46 maps: OrderedMutex<BTreeMap<BpfMapId, WeakMapWithType>, EbpfStateLock>,
47}
48
49impl EbpfState {
50 fn register_program<L>(&self, locked: &mut Locked<L>, program: &ProgramHandle)
51 where
52 L: LockBefore<EbpfStateLock>,
53 {
54 self.programs.lock(locked).insert(program.id(), Arc::downgrade(program));
55 }
56
57 fn unregister_program<L>(&self, locked: &mut Locked<L>, id: ProgramId)
58 where
59 L: LockBefore<EbpfStateLock>,
60 {
61 self.programs.lock(locked).remove(&id).expect("Missing eBPF program");
62 }
63
64 fn get_next_program_id<L>(
65 &self,
66 locked: &mut Locked<L>,
67 start_id: ProgramId,
68 ) -> Option<ProgramId>
69 where
70 L: LockBefore<EbpfStateLock>,
71 {
72 self.programs
73 .lock(locked)
74 .range((Bound::Excluded(start_id), Bound::Unbounded))
75 .next()
76 .map(|(k, _)| *k)
77 }
78
79 fn get_program_by_id<L>(&self, locked: &mut Locked<L>, id: ProgramId) -> Option<ProgramHandle>
80 where
81 L: LockBefore<EbpfStateLock>,
82 {
83 self.programs.lock(locked).get(&id).map(|p| p.upgrade()).flatten()
84 }
85
86 fn register_map<L>(&self, locked: &mut Locked<L>, map: &BpfMapHandle)
87 where
88 L: LockBefore<EbpfStateLock>,
89 {
90 self.maps.lock(locked).insert(map.id(), WeakMapWithType::new(map));
91 }
92
93 fn unregister_map<L>(&self, locked: &mut Locked<L>, id: BpfMapId)
94 where
95 L: LockBefore<EbpfStateLock>,
96 {
97 self.maps.lock(locked).remove(&id).expect("Missing eBPF map");
98 }
99
100 fn get_next_map_id<L>(&self, locked: &mut Locked<L>, start_id: BpfMapId) -> Option<BpfMapId>
101 where
102 L: LockBefore<EbpfStateLock>,
103 {
104 self.maps
105 .lock(locked)
106 .range((Bound::Excluded(start_id), Bound::Unbounded))
107 .next()
108 .map(|(k, _)| *k)
109 }
110
111 fn get_map_by_id<L>(&self, locked: &mut Locked<L>, id: BpfMapId) -> Option<BpfMapHandle>
112 where
113 L: LockBefore<EbpfStateLock>,
114 {
115 self.maps.lock(locked).get(&id).map(|entry| entry.weak_map.upgrade()).flatten()
116 }
117
118 pub fn remove_sk_storage_entries<L>(&self, locked: &mut Locked<L>, cookie: u64)
121 where
122 L: LockBefore<EbpfStateLock>,
123 {
124 self.maps.lock(locked).iter().for_each(|(_, entry)| {
125 if entry.map_type == bpf_map_type_BPF_MAP_TYPE_SK_STORAGE
126 && let Some(map) = entry.weak_map.upgrade()
127 {
128 let _ = map.delete(cookie.as_bytes());
129 }
130 });
131 }
132}