hermit/executor/
network.rs1use alloc::boxed::Box;
2#[cfg(feature = "dns")]
3use alloc::vec::Vec;
4use core::future;
5use core::sync::atomic::{AtomicU16, Ordering};
6use core::task::Poll;
7
8use hermit_sync::InterruptTicketMutex;
9use smoltcp::iface::{PollResult, SocketHandle, SocketSet};
10use smoltcp::socket::AnySocket;
11#[cfg(feature = "dhcpv4")]
12use smoltcp::socket::dhcpv4;
13#[cfg(feature = "dns")]
14use smoltcp::socket::dns::{self, GetQueryResultError, QueryHandle};
15#[cfg(feature = "tcp")]
16use smoltcp::socket::tcp;
17#[cfg(feature = "udp")]
18use smoltcp::socket::udp;
19use smoltcp::time::{Duration, Instant};
20#[cfg(feature = "dns")]
21use smoltcp::wire::{DnsQueryType, IpAddress};
22#[cfg(feature = "dhcpv4")]
23use smoltcp::wire::{IpCidr, Ipv4Address, Ipv4Cidr};
24
25use crate::arch;
26use crate::executor::device::HermitNet;
27use crate::executor::spawn;
28#[cfg(feature = "dns")]
29use crate::io;
30use crate::scheduler::PerCoreSchedulerExt;
31
32pub(crate) enum NetworkState<'a> {
33 Missing,
34 InitializationFailed,
35 Initialized(Box<NetworkInterface<'a>>),
36}
37
38impl<'a> NetworkState<'a> {
39 pub fn as_nic_mut(&mut self) -> Result<&mut NetworkInterface<'a>, &'static str> {
40 match self {
41 NetworkState::Initialized(nic) => Ok(nic),
42 _ => Err("Network is not initialized!"),
43 }
44 }
45}
46
47pub(crate) type Handle = SocketHandle;
48
49static LOCAL_ENDPOINT: AtomicU16 = AtomicU16::new(0);
50pub(crate) static NIC: InterruptTicketMutex<NetworkState<'_>> =
51 InterruptTicketMutex::new(NetworkState::Missing);
52
53pub(crate) struct NetworkInterface<'a> {
54 pub(super) iface: smoltcp::iface::Interface,
55 pub(super) sockets: SocketSet<'a>,
56 pub(super) device: HermitNet,
57 #[cfg(feature = "dhcpv4")]
58 pub(super) dhcp_handle: SocketHandle,
59 #[cfg(feature = "dns")]
60 pub(super) dns_handle: Option<SocketHandle>,
61}
62
63#[cfg(target_arch = "x86_64")]
64fn start_endpoint() -> u16 {
65 ((unsafe { core::arch::x86_64::_rdtsc() }) % u64::from(u16::MAX))
66 .try_into()
67 .unwrap()
68}
69
70#[cfg(target_arch = "aarch64")]
71fn start_endpoint() -> u16 {
72 use core::arch::asm;
73 let value: u64;
74
75 unsafe {
76 asm!(
77 "mrs {value}, cntpct_el0",
78 value = out(reg) value,
79 options(nostack),
80 );
81 }
82
83 (value % u64::from(u16::MAX)).try_into().unwrap()
84}
85
86#[cfg(target_arch = "riscv64")]
87fn start_endpoint() -> u16 {
88 (riscv::register::time::read64() % u64::from(u16::MAX))
89 .try_into()
90 .unwrap()
91}
92
93#[inline]
94pub(crate) fn now() -> Instant {
95 Instant::from_micros_const(arch::kernel::systemtime::now_micros().try_into().unwrap())
96}
97
98#[cfg(feature = "dhcpv4")]
99async fn dhcpv4_run() {
100 let dhcp_handle = NIC.lock().as_nic_mut().unwrap().dhcp_handle;
101
102 future::poll_fn(|cx| {
103 let mut guard = NIC.lock();
104 let nic = guard.as_nic_mut().unwrap();
105 let socket = nic.sockets.get_mut::<dhcpv4::Socket<'_>>(dhcp_handle);
106
107 socket.register_waker(cx.waker());
108
109 match socket.poll() {
110 None => {}
111 Some(dhcpv4::Event::Configured(config)) => {
112 info!("DHCP config acquired!");
113 info!("IP address: {}", config.address);
114 nic.iface.update_ip_addrs(|addrs| {
115 if let Some(dest) = addrs.iter_mut().next() {
116 *dest = IpCidr::Ipv4(config.address);
117 } else if addrs.push(IpCidr::Ipv4(config.address)).is_err() {
118 info!("Unable to update IP address");
119 }
120 });
121 if let Some(router) = config.router {
122 info!("Default gateway: {router}");
123 nic.iface
124 .routes_mut()
125 .add_default_ipv4_route(router)
126 .unwrap();
127 } else {
128 info!("Default gateway: None");
129 nic.iface.routes_mut().remove_default_ipv4_route();
130 }
131
132 #[cfg(feature = "dns")]
133 let mut dns_servers: Vec<IpAddress> = Vec::new();
134 for (i, s) in config.dns_servers.iter().enumerate() {
135 info!("DNS server {i}: {s}");
136 #[cfg(feature = "dns")]
137 dns_servers.push(IpAddress::Ipv4(*s));
138 }
139
140 #[cfg(feature = "dns")]
141 if !dns_servers.is_empty() {
142 let dns_socket = dns::Socket::new(dns_servers.as_slice(), vec![]);
143 nic.dns_handle = Some(nic.sockets.add(dns_socket));
144 }
145 }
146 Some(dhcpv4::Event::Deconfigured) => {
147 info!("DHCP lost config!");
148 let cidr = Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0);
149 nic.iface.update_ip_addrs(|addrs| {
150 if let Some(dest) = addrs.iter_mut().next() {
151 *dest = IpCidr::Ipv4(cidr);
152 }
153 });
154 nic.iface.routes_mut().remove_default_ipv4_route();
155
156 #[cfg(feature = "dns")]
157 {
158 if let Some(dns_handle) = nic.dns_handle {
159 nic.sockets.remove(dns_handle);
160 }
161
162 nic.dns_handle = None;
163 }
164 }
165 };
166
167 Poll::<()>::Pending
168 })
169 .await;
170}
171
172async fn network_run() {
173 future::poll_fn(|_cx| {
174 if let Some(mut guard) = NIC.try_lock() {
175 match &mut *guard {
176 NetworkState::Initialized(nic) => {
177 nic.poll_common(now());
178 Poll::Pending
179 }
180 _ => Poll::Ready(()),
181 }
182 } else {
183 Poll::Pending
185 }
186 })
187 .await;
188}
189
190#[cfg(feature = "dns")]
191pub(crate) async fn get_query_result(query: QueryHandle) -> io::Result<Vec<IpAddress>> {
192 future::poll_fn(|cx| {
193 let mut guard = NIC.lock();
194 let nic = guard.as_nic_mut().unwrap();
195 let socket = nic.get_mut_dns_socket()?;
196 match socket.get_query_result(query) {
197 Ok(addrs) => {
198 let mut ips = Vec::new();
199 for x in &addrs {
200 ips.push(*x);
201 }
202
203 Poll::Ready(Ok(ips))
204 }
205 Err(GetQueryResultError::Pending) => {
206 socket.register_query_waker(query, cx.waker());
207 Poll::Pending
208 }
209 Err(e) => {
210 warn!("DNS query failed: {e:?}");
211 Poll::Ready(Err(io::Error::ENOENT))
212 }
213 }
214 })
215 .await
216}
217
218pub(crate) fn init() {
219 info!("Try to initialize network!");
220
221 LOCAL_ENDPOINT.store(start_endpoint(), Ordering::Relaxed);
223
224 let mut guard = NIC.lock();
225
226 *guard = NetworkInterface::create();
227
228 if let NetworkState::Initialized(nic) = &mut *guard {
229 let time = now();
230 nic.poll_common(time);
231 let wakeup_time = nic
232 .poll_delay(time)
233 .map(|d| crate::arch::processor::get_timer_ticks() + d.total_micros());
234 crate::core_scheduler().add_network_timer(wakeup_time);
235
236 spawn(network_run());
237 #[cfg(feature = "dhcpv4")]
238 spawn(dhcpv4_run());
239 }
240}
241
242impl<'a> NetworkInterface<'a> {
243 #[cfg(feature = "udp")]
244 pub(crate) fn create_udp_handle(&mut self) -> Result<Handle, ()> {
245 let udp_rx_buffer =
246 udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY; 4], vec![0; 0x10000]);
247 let udp_tx_buffer =
248 udp::PacketBuffer::new(vec![udp::PacketMetadata::EMPTY; 4], vec![0; 0x10000]);
249 let udp_socket = udp::Socket::new(udp_rx_buffer, udp_tx_buffer);
250 let udp_handle = self.sockets.add(udp_socket);
251
252 Ok(udp_handle)
253 }
254
255 #[cfg(feature = "tcp")]
256 pub(crate) fn create_tcp_handle(&mut self) -> Result<Handle, ()> {
257 let tcp_rx_buffer = tcp::SocketBuffer::new(vec![0; 0x10000]);
258 let tcp_tx_buffer = tcp::SocketBuffer::new(vec![0; 0x10000]);
259 let mut tcp_socket = tcp::Socket::new(tcp_rx_buffer, tcp_tx_buffer);
260 tcp_socket.set_nagle_enabled(true);
261 let tcp_handle = self.sockets.add(tcp_socket);
262
263 Ok(tcp_handle)
264 }
265
266 pub(crate) fn poll_common(&mut self, timestamp: Instant) -> PollResult {
267 self.iface
268 .poll(timestamp, &mut self.device, &mut self.sockets)
269 }
270
271 pub(crate) fn poll_delay(&mut self, timestamp: Instant) -> Option<Duration> {
272 self.iface.poll_delay(timestamp, &self.sockets)
273 }
274
275 #[allow(dead_code)]
276 pub(crate) fn get_socket<T: AnySocket<'a>>(&self, handle: SocketHandle) -> &T {
277 self.sockets.get(handle)
278 }
279
280 pub(crate) fn get_mut_socket<T: AnySocket<'a>>(&mut self, handle: SocketHandle) -> &mut T {
281 self.sockets.get_mut(handle)
282 }
283
284 pub(crate) fn get_socket_and_context<T: AnySocket<'a>>(
285 &mut self,
286 handle: SocketHandle,
287 ) -> (&mut T, &mut smoltcp::iface::Context) {
288 (self.sockets.get_mut(handle), self.iface.context())
289 }
290
291 pub(crate) fn destroy_socket(&mut self, handle: Handle) {
292 self.sockets.remove(handle);
294 }
295
296 #[cfg(feature = "dns")]
297 pub(crate) fn start_query(
298 &mut self,
299 name: &str,
300 query_type: DnsQueryType,
301 ) -> io::Result<QueryHandle> {
302 let dns_handle = self.dns_handle.ok_or(io::Error::EINVAL)?;
303 let socket: &mut dns::Socket<'a> = self.sockets.get_mut(dns_handle);
304 socket
305 .start_query(self.iface.context(), name, query_type)
306 .map_err(|_| io::Error::EIO)
307 }
308
309 #[allow(dead_code)]
310 #[cfg(feature = "dns")]
311 pub(crate) fn get_dns_socket(&self) -> io::Result<&dns::Socket<'a>> {
312 let dns_handle = self.dns_handle.ok_or(io::Error::EINVAL)?;
313 Ok(self.sockets.get(dns_handle))
314 }
315
316 #[cfg(feature = "dns")]
317 pub(crate) fn get_mut_dns_socket(&mut self) -> io::Result<&mut dns::Socket<'a>> {
318 let dns_handle = self.dns_handle.ok_or(io::Error::EINVAL)?;
319 Ok(self.sockets.get_mut(dns_handle))
320 }
321}