hermit/executor/
device.rs1use alloc::boxed::Box;
2use alloc::vec::Vec;
3#[cfg(not(feature = "dhcpv4"))]
4use core::str::FromStr;
5
6use smoltcp::iface::{Config, Interface, SocketSet};
7use smoltcp::phy::{self, ChecksumCapabilities, Device, DeviceCapabilities, Medium};
8#[cfg(feature = "dhcpv4")]
9use smoltcp::socket::dhcpv4;
10#[cfg(all(feature = "dns", not(feature = "dhcpv4")))]
11use smoltcp::socket::dns;
12use smoltcp::time::Instant;
13#[cfg(not(feature = "dhcpv4"))]
14use smoltcp::wire::Ipv4Address;
15use smoltcp::wire::{EthernetAddress, HardwareAddress};
16#[cfg(not(feature = "dhcpv4"))]
17use smoltcp::wire::{IpAddress, IpCidr};
18
19use super::network::{NetworkInterface, NetworkState};
20use crate::arch;
21#[cfg(not(feature = "pci"))]
22use crate::arch::kernel::mmio as hardware;
23use crate::drivers::net::NetworkDriver;
24#[cfg(feature = "pci")]
25use crate::drivers::pci as hardware;
26
27#[derive(Debug, Clone)]
29#[repr(C)]
30pub(crate) struct HermitNet {
31 mtu: u16,
32 checksums: ChecksumCapabilities,
33}
34
35impl HermitNet {
36 pub(crate) const fn new(mtu: u16, checksums: ChecksumCapabilities) -> Self {
37 Self { mtu, checksums }
38 }
39}
40
41impl<'a> NetworkInterface<'a> {
42 #[cfg(feature = "dhcpv4")]
43 pub(crate) fn create() -> NetworkState<'a> {
44 let (mtu, mac, checksums) = if let Some(driver) = hardware::get_network_driver() {
45 let guard = driver.lock();
46 (
47 guard.get_mtu(),
48 guard.get_mac_address(),
49 guard.get_checksums(),
50 )
51 } else {
52 return NetworkState::InitializationFailed;
53 };
54
55 let mut device = HermitNet::new(mtu, checksums.clone());
56
57 if hermit_var!("HERMIT_IP").is_some() {
58 warn!(
59 "A static IP address is specified with the environment variable HERMIT_IP, but the device is configured to use DHCPv4!"
60 );
61 }
62
63 let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
64 let hardware_addr = HardwareAddress::Ethernet(ethernet_addr);
65
66 info!("MAC address {hardware_addr}");
67 info!("{checksums:?}");
68 info!("MTU: {mtu} bytes");
69
70 let dhcp = dhcpv4::Socket::new();
71
72 let mut config = Config::new(hardware_addr);
74 config.random_seed = (arch::kernel::systemtime::now_micros()) / 1_000_000;
75 if device.capabilities().medium == Medium::Ethernet {
76 config.hardware_addr = hardware_addr;
77 }
78
79 let iface = Interface::new(config, &mut device, crate::executor::network::now());
80 let mut sockets = SocketSet::new(vec![]);
81 let dhcp_handle = sockets.add(dhcp);
82
83 NetworkState::Initialized(Box::new(Self {
84 iface,
85 sockets,
86 device,
87 dhcp_handle,
88 #[cfg(feature = "dns")]
89 dns_handle: None,
90 }))
91 }
92
93 #[cfg(not(feature = "dhcpv4"))]
94 pub(crate) fn create() -> NetworkState<'a> {
95 let (mtu, mac, checksums) = if let Some(driver) = hardware::get_network_driver() {
96 let guard = driver.lock();
97 (
98 guard.get_mtu(),
99 guard.get_mac_address(),
100 guard.get_checksums(),
101 )
102 } else {
103 return NetworkState::InitializationFailed;
104 };
105
106 let mut device = HermitNet::new(mtu, checksums.clone());
107
108 let myip = Ipv4Address::from_str(hermit_var_or!("HERMIT_IP", "10.0.5.3")).unwrap();
109 let mygw = Ipv4Address::from_str(hermit_var_or!("HERMIT_GATEWAY", "10.0.5.1")).unwrap();
110 let mymask = Ipv4Address::from_str(hermit_var_or!("HERMIT_MASK", "255.255.255.0")).unwrap();
111 #[cfg(feature = "dns")]
113 let mydns1 = Ipv4Address::from_str(hermit_var_or!("HERMIT_DNS1", "9.9.9.9")).unwrap();
114 #[cfg(feature = "dns")]
116 let mydns2 = Ipv4Address::from_str(hermit_var_or!("HERMIT_DNS2", "1.1.1.1")).unwrap();
117
118 let mut prefix_len = (!mymask.octets()[0]).trailing_zeros();
122 if prefix_len == 8 {
123 prefix_len += (!mymask.octets()[1]).trailing_zeros();
124 }
125 if prefix_len == 16 {
126 prefix_len += (!mymask.octets()[2]).trailing_zeros();
127 }
128 if prefix_len == 24 {
129 prefix_len += (!mymask.octets()[3]).trailing_zeros();
130 }
131
132 let ethernet_addr = EthernetAddress([mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]]);
133 let hardware_addr = HardwareAddress::Ethernet(ethernet_addr);
134 let ip_addrs = [IpCidr::new(
135 IpAddress::v4(
136 myip.octets()[0],
137 myip.octets()[1],
138 myip.octets()[2],
139 myip.octets()[3],
140 ),
141 prefix_len.try_into().unwrap(),
142 )];
143
144 info!("MAC address {hardware_addr}");
145 info!("Configure network interface with address {}", ip_addrs[0]);
146 info!("Configure gateway with address {mygw}");
147 info!("{checksums:?}");
148 info!("MTU: {mtu} bytes");
149
150 let mut config = Config::new(hardware_addr);
152 config.random_seed = (arch::kernel::systemtime::now_micros()) / 1_000_000;
153 if device.capabilities().medium == Medium::Ethernet {
154 config.hardware_addr = hardware_addr;
155 }
156
157 let mut iface = Interface::new(config, &mut device, crate::executor::network::now());
158 iface.update_ip_addrs(|ip_addrs| {
159 ip_addrs
160 .push(IpCidr::new(
161 IpAddress::v4(
162 myip.octets()[0],
163 myip.octets()[1],
164 myip.octets()[2],
165 myip.octets()[3],
166 ),
167 prefix_len.try_into().unwrap(),
168 ))
169 .unwrap();
170 });
171 iface.routes_mut().add_default_ipv4_route(mygw).unwrap();
172
173 #[allow(unused_mut)]
174 let mut sockets = SocketSet::new(vec![]);
175
176 #[cfg(feature = "dns")]
177 let dns_handle = {
178 let servers = &[mydns1.into(), mydns2.into()];
179 let dns_socket = dns::Socket::new(servers, vec![]);
180 sockets.add(dns_socket)
181 };
182
183 NetworkState::Initialized(Box::new(Self {
184 iface,
185 sockets,
186 device,
187 #[cfg(feature = "dns")]
188 dns_handle: Some(dns_handle),
189 }))
190 }
191}
192
193impl Device for HermitNet {
194 type RxToken<'a> = RxToken;
195 type TxToken<'a> = TxToken;
196
197 fn capabilities(&self) -> DeviceCapabilities {
198 let mut cap = DeviceCapabilities::default();
199 cap.max_transmission_unit = self.mtu.into();
200 cap.max_burst_size = Some(0x10000 / cap.max_transmission_unit);
201 cap.checksum = self.checksums.clone();
202 cap
203 }
204
205 fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
206 if let Some(driver) = hardware::get_network_driver() {
207 driver.lock().receive_packet()
208 } else {
209 None
210 }
211 }
212
213 fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
214 Some(TxToken::new())
215 }
216}
217
218pub(crate) type RxHandle = usize;
220
221#[doc(hidden)]
222pub(crate) struct RxToken {
223 buffer: Vec<u8>,
224}
225
226impl RxToken {
227 pub(crate) fn new(buffer: Vec<u8>) -> Self {
228 Self { buffer }
229 }
230}
231
232impl phy::RxToken for RxToken {
233 fn consume<R, F>(self, f: F) -> R
234 where
235 F: FnOnce(&[u8]) -> R,
236 {
237 f(&self.buffer[..])
238 }
239}
240
241#[doc(hidden)]
242pub(crate) struct TxToken;
243
244impl TxToken {
245 pub(crate) fn new() -> Self {
246 Self {}
247 }
248}
249
250impl phy::TxToken for TxToken {
251 fn consume<R, F>(self, len: usize, f: F) -> R
252 where
253 F: FnOnce(&mut [u8]) -> R,
254 {
255 hardware::get_network_driver()
256 .unwrap()
257 .lock()
258 .send_packet(len, f)
259 }
260}