strat9_kernel/hardware/nic/
mod.rs1pub mod common;
7pub mod data_plane;
8pub mod e1000_drv;
9pub mod e1000e_drv;
10pub mod igc_drv;
11pub mod pcnet_drv;
12pub mod rtl8139_drv;
13pub mod scheme;
14pub mod virtio_net;
15
16pub use net_core::{NetError, NetworkDevice, MTU};
17
18use alloc::{format, string::String, sync::Arc, vec::Vec};
19use spin::RwLock;
20
21struct NetDeviceEntry {
22 iface: String,
23 device: Arc<dyn NetworkDevice>,
24}
25
26static NET_DEVICES: RwLock<Vec<NetDeviceEntry>> = RwLock::new(Vec::new());
27
28fn bsd_prefix(driver_name: &str) -> &'static str {
36 let lower = driver_name.as_bytes();
37 if lower.len() >= 4
39 && (lower[0] | 0x20) == b'e'
40 && (lower[1] | 0x20) == b'1'
41 && lower[2] == b'0'
42 && lower[3] == b'0'
43 {
44 return "em"; }
46 if lower.len() >= 6
47 && (lower[0] | 0x20) == b'v'
48 && (lower[1] | 0x20) == b'i'
49 && (lower[2] | 0x20) == b'r'
50 && (lower[3] | 0x20) == b't'
51 && (lower[4] | 0x20) == b'i'
52 && (lower[5] | 0x20) == b'o'
53 {
54 return "vtnet"; }
56 "net" }
58
59static PREFIX_COUNTERS: RwLock<Vec<(String, usize)>> = RwLock::new(Vec::new());
61
62fn next_index_for(prefix: &str) -> usize {
64 let mut counters = PREFIX_COUNTERS.write();
65 for entry in counters.iter_mut() {
66 if entry.0 == prefix {
67 let idx = entry.1;
68 entry.1 += 1;
69 return idx;
70 }
71 }
72 counters.push((String::from(prefix), 1));
73 0
74}
75
76pub static NIC_IRQ_LINE: core::sync::atomic::AtomicU8 = core::sync::atomic::AtomicU8::new(0xFF);
83
84static NIC_DEVICE: spin::Mutex<Option<Arc<dyn NetworkDevice>>> = spin::Mutex::new(None);
92
93pub fn set_nic_device(dev: Arc<dyn NetworkDevice>, irq: u8) {
98 NIC_IRQ_LINE.store(irq, core::sync::atomic::Ordering::Relaxed);
99 *NIC_DEVICE.lock() = Some(dev);
100 log::info!("NIC dispatch set for IRQ {}", irq);
101}
102
103static STRATE_NET_TID: core::sync::atomic::AtomicU64 = core::sync::atomic::AtomicU64::new(0);
117
118pub fn register_strate_net_tid(tid: u64) {
120 STRATE_NET_TID.store(tid, core::sync::atomic::Ordering::Relaxed);
121 log::info!("NIC: strate-net task {} registered for IRQ wakeup", tid);
122}
123
124pub fn handle_interrupt() {
129 if let Some(ref dev) = *NIC_DEVICE.lock() {
130 dev.handle_interrupt();
131 if let Some(ref dp) = *NIC_DATA_PLANE.lock() {
133 let mut buf = [0u8; 2048];
134 while let Ok(n) = dev.receive(&mut buf) {
135 if dp.push_rx(0, &buf[..n]).is_err() {
136 break; }
138 }
139 }
140 }
141 let tid_u64 = STRATE_NET_TID.load(core::sync::atomic::Ordering::Relaxed);
142 if tid_u64 != 0 {
143 let _ = crate::process::scheduler::wake_task(crate::process::TaskId(tid_u64));
144 }
145}
146
147pub fn register_device(device: Arc<dyn NetworkDevice>) -> String {
149 let prefix = bsd_prefix(device.name());
150 let idx = next_index_for(prefix);
151 let iface = format!("{}{}", prefix, idx);
152 let mac = device.mac_address();
153 log::info!(
154 "[net] {} -> {} (MAC {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x})",
155 device.name(),
156 iface,
157 mac[0],
158 mac[1],
159 mac[2],
160 mac[3],
161 mac[4],
162 mac[5],
163 );
164 let mut devs = NET_DEVICES.write();
165 devs.push(NetDeviceEntry {
166 iface: iface.clone(),
167 device,
168 });
169 iface
170}
171
172pub fn get_device(name: &str) -> Option<Arc<dyn NetworkDevice>> {
174 NET_DEVICES
175 .read()
176 .iter()
177 .find(|e| e.iface == name)
178 .map(|e| e.device.clone())
179}
180
181pub fn get_default_device() -> Option<Arc<dyn NetworkDevice>> {
183 NET_DEVICES.read().first().map(|e| e.device.clone())
184}
185
186pub fn list_interfaces() -> Vec<String> {
188 NET_DEVICES.read().iter().map(|e| e.iface.clone()).collect()
189}
190
191pub fn poll_all() {
200 let guard = NET_DEVICES.read();
201 for entry in guard.iter() {
202 entry.device.poll();
203 }
204}
205
206pub fn try_register_strate_net() {
208 if STRATE_NET_TID.load(core::sync::atomic::Ordering::Relaxed) != 0 {
209 return;
210 }
211 if let Some(tasks) = crate::process::get_all_tasks() {
212 for t in &tasks {
213 if t.name == "strate-net" {
214 register_strate_net_tid(t.id.0);
215 return;
216 }
217 }
218 }
219}
220
221pub fn init() {
223 log::info!("[net] Scanning for network devices...");
224 e1000e_drv::init();
226 igc_drv::init();
227 e1000_drv::init();
228 pcnet_drv::init();
229 rtl8139_drv::init();
230 virtio_net::init();
231 if let Err(e) = scheme::register_net_scheme() {
232 log::warn!("[net] Failed to register net scheme: {:?}", e);
233 }
234 init_data_plane();
236}
237
238use data_plane::NicDataPlane;
241use spin::Mutex;
242
243static NIC_DATA_PLANE: Mutex<Option<NicDataPlane>> = Mutex::new(None);
245
246fn init_data_plane() {
249 let count = NET_DEVICES.read().len();
250 if count == 0 {
251 log::debug!("[net] No NIC devices found : skipping data plane init");
252 return;
253 }
254 match NicDataPlane::new(count, 256, 2048) {
256 Ok(dp) => {
257 *NIC_DATA_PLANE.lock() = Some(dp);
258 log::info!("[net] N2 data plane initialised with {} queue(s)", count);
259 }
260 Err(e) => {
261 log::warn!("[net] Failed to initialise N2 data plane: {}", e);
262 }
263 }
264}
265
266pub fn data_plane() -> &'static Mutex<Option<NicDataPlane>> {
268 &NIC_DATA_PLANE
269}