Nothing to see here, move along
1use core::sync::atomic::{AtomicBool, Ordering};
2use smoltcp::iface::{Config, Interface, SocketHandle, SocketSet, SocketStorage};
3use smoltcp::socket::{dhcpv4, dns, icmp, tcp, udp};
4use smoltcp::time::{Duration, Instant};
5use smoltcp::wire::{
6 EthernetAddress, HardwareAddress, IpAddress, IpCidr, Ipv4Address, Ipv6Address, Ipv6Cidr,
7};
8
9use crate::device::PacketDevice;
10
11static CREATED: AtomicBool = AtomicBool::new(false);
12pub static MDNS_JOIN_FAILED: AtomicBool = AtomicBool::new(false);
13
14const TCP_RX_BUF_SIZE: usize = 8192;
15const TCP_TX_BUF_SIZE: usize = 8192;
16const SHELL_TCP_RX_SIZE: usize = 8192;
17const SHELL_TCP_TX_SIZE: usize = 8192;
18pub const MAX_SHELL_SOCKETS: usize = 4;
19pub const MAX_UDP_SOCKETS: usize = 4;
20const DNS_QUERY_SLOTS: usize = 2;
21const MAX_SOCKETS: usize = 2 + MAX_SHELL_SOCKETS + 2 + 1 + MAX_UDP_SOCKETS + 1;
22
23static mut TCP_RX_DATA: [u8; TCP_RX_BUF_SIZE] = [0u8; TCP_RX_BUF_SIZE];
24static mut TCP_TX_DATA: [u8; TCP_TX_BUF_SIZE] = [0u8; TCP_TX_BUF_SIZE];
25static mut SHELL_TCP_RX_POOL: [[u8; SHELL_TCP_RX_SIZE]; MAX_SHELL_SOCKETS] =
26 [[0u8; SHELL_TCP_RX_SIZE]; MAX_SHELL_SOCKETS];
27static mut SHELL_TCP_TX_POOL: [[u8; SHELL_TCP_TX_SIZE]; MAX_SHELL_SOCKETS] =
28 [[0u8; SHELL_TCP_TX_SIZE]; MAX_SHELL_SOCKETS];
29static mut SOCKET_STORAGE: [SocketStorage<'static>; MAX_SOCKETS] =
30 [SocketStorage::EMPTY; MAX_SOCKETS];
31static mut DNS_QUERIES: [Option<dns::DnsQuery>; DNS_QUERY_SLOTS] =
32 [const { None }; DNS_QUERY_SLOTS];
33
34const ICMP_META_SLOTS: usize = 4;
35const ICMP_PAYLOAD_SIZE: usize = 512;
36static mut ICMP_RX_META: [icmp::PacketMetadata; ICMP_META_SLOTS] =
37 [icmp::PacketMetadata::EMPTY; ICMP_META_SLOTS];
38static mut ICMP_RX_DATA: [u8; ICMP_PAYLOAD_SIZE] = [0u8; ICMP_PAYLOAD_SIZE];
39static mut ICMP_TX_META: [icmp::PacketMetadata; ICMP_META_SLOTS] =
40 [icmp::PacketMetadata::EMPTY; ICMP_META_SLOTS];
41static mut ICMP_TX_DATA: [u8; ICMP_PAYLOAD_SIZE] = [0u8; ICMP_PAYLOAD_SIZE];
42
43const UDP_BUF_SIZE: usize = 2048;
44const UDP_META_SLOTS: usize = 4;
45static mut UDP_RX_META_POOL: [[udp::PacketMetadata; UDP_META_SLOTS]; MAX_UDP_SOCKETS] =
46 [[udp::PacketMetadata::EMPTY; UDP_META_SLOTS]; MAX_UDP_SOCKETS];
47static mut UDP_RX_DATA_POOL: [[u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS] =
48 [[0u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS];
49static mut UDP_TX_META_POOL: [[udp::PacketMetadata; UDP_META_SLOTS]; MAX_UDP_SOCKETS] =
50 [[udp::PacketMetadata::EMPTY; UDP_META_SLOTS]; MAX_UDP_SOCKETS];
51static mut UDP_TX_DATA_POOL: [[u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS] =
52 [[0u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS];
53
54const MDNS_META_SLOTS: usize = 4;
55const MDNS_BUF_SIZE: usize = 1500;
56static mut MDNS_RX_META: [udp::PacketMetadata; MDNS_META_SLOTS] =
57 [udp::PacketMetadata::EMPTY; MDNS_META_SLOTS];
58static mut MDNS_RX_DATA: [u8; MDNS_BUF_SIZE] = [0u8; MDNS_BUF_SIZE];
59static mut MDNS_TX_META: [udp::PacketMetadata; MDNS_META_SLOTS] =
60 [udp::PacketMetadata::EMPTY; MDNS_META_SLOTS];
61static mut MDNS_TX_DATA: [u8; MDNS_BUF_SIZE] = [0u8; MDNS_BUF_SIZE];
62
63pub struct NetStack {
64 pub iface: Interface,
65 pub sockets: SocketSet<'static>,
66 pub tcp_handle: SocketHandle,
67 pub shell_handles: [SocketHandle; MAX_SHELL_SOCKETS],
68 pub dhcp_handle: SocketHandle,
69 pub dns_handle: SocketHandle,
70 pub icmp_handle: SocketHandle,
71 pub udp_handles: [SocketHandle; MAX_UDP_SOCKETS],
72 pub mdns_handle: SocketHandle,
73}
74
75#[allow(clippy::deref_addrof)]
76pub fn create(device: &mut PacketDevice, mac: [u8; 6], now: Instant) -> NetStack {
77 assert!(
78 !CREATED.swap(true, Ordering::Relaxed),
79 "stack::create() called twice"
80 );
81 let hw_addr = HardwareAddress::Ethernet(EthernetAddress(mac));
82 let config = Config::new(hw_addr);
83 let mut iface = Interface::new(config, device, now);
84
85 let socket_storage: &'static mut [SocketStorage<'static>; MAX_SOCKETS] =
86 unsafe { &mut *(&raw mut SOCKET_STORAGE) };
87 let mut sockets = SocketSet::new(&mut socket_storage[..]);
88
89 let tcp_rx_data: &'static mut [u8] = unsafe { &mut *(&raw mut TCP_RX_DATA) };
90 let tcp_rx_buf = tcp::SocketBuffer::new(tcp_rx_data);
91 let tcp_tx_data: &'static mut [u8] = unsafe { &mut *(&raw mut TCP_TX_DATA) };
92 let tcp_tx_buf = tcp::SocketBuffer::new(tcp_tx_data);
93 let tcp_socket = tcp::Socket::new(tcp_rx_buf, tcp_tx_buf);
94 let tcp_handle = sockets.add(tcp_socket);
95
96 let rx_pool: &'static mut [[u8; SHELL_TCP_RX_SIZE]; MAX_SHELL_SOCKETS] =
97 unsafe { &mut *(&raw mut SHELL_TCP_RX_POOL) };
98 let tx_pool: &'static mut [[u8; SHELL_TCP_TX_SIZE]; MAX_SHELL_SOCKETS] =
99 unsafe { &mut *(&raw mut SHELL_TCP_TX_POOL) };
100
101 let mut shell_handles_tmp: [Option<SocketHandle>; MAX_SHELL_SOCKETS] =
102 [None; MAX_SHELL_SOCKETS];
103 rx_pool
104 .iter_mut()
105 .zip(tx_pool.iter_mut())
106 .zip(shell_handles_tmp.iter_mut())
107 .for_each(|((rx_data, tx_data), slot)| {
108 let mut sock = tcp::Socket::new(
109 tcp::SocketBuffer::new(&mut rx_data[..]),
110 tcp::SocketBuffer::new(&mut tx_data[..]),
111 );
112 sock.set_nagle_enabled(false);
113 sock.set_ack_delay(None);
114 sock.set_keep_alive(Some(Duration::from_secs(30)));
115 *slot = Some(sockets.add(sock));
116 });
117
118 let shell_handles = shell_handles_tmp.map(|opt| opt.unwrap());
119
120 let dhcp_socket = dhcpv4::Socket::new();
121 let dhcp_handle = sockets.add(dhcp_socket);
122
123 let dns_queries: &'static mut [Option<dns::DnsQuery>; DNS_QUERY_SLOTS] =
124 unsafe { &mut *(&raw mut DNS_QUERIES) };
125 let dns_socket = dns::Socket::new(&[] as &[IpAddress], &mut dns_queries[..]);
126 let dns_handle = sockets.add(dns_socket);
127
128 let icmp_rx_meta: &'static mut [icmp::PacketMetadata; ICMP_META_SLOTS] =
129 unsafe { &mut *(&raw mut ICMP_RX_META) };
130 let icmp_rx_data: &'static mut [u8; ICMP_PAYLOAD_SIZE] =
131 unsafe { &mut *(&raw mut ICMP_RX_DATA) };
132 let icmp_tx_meta: &'static mut [icmp::PacketMetadata; ICMP_META_SLOTS] =
133 unsafe { &mut *(&raw mut ICMP_TX_META) };
134 let icmp_tx_data: &'static mut [u8; ICMP_PAYLOAD_SIZE] =
135 unsafe { &mut *(&raw mut ICMP_TX_DATA) };
136 let icmp_rx_buf = icmp::PacketBuffer::new(&mut icmp_rx_meta[..], &mut icmp_rx_data[..]);
137 let icmp_tx_buf = icmp::PacketBuffer::new(&mut icmp_tx_meta[..], &mut icmp_tx_data[..]);
138 let mut icmp_socket = icmp::Socket::new(icmp_rx_buf, icmp_tx_buf);
139 icmp_socket.bind(icmp::Endpoint::Ident(0x4C41)).unwrap();
140 let icmp_handle = sockets.add(icmp_socket);
141
142 let udp_rx_meta_pool: &'static mut [[udp::PacketMetadata; UDP_META_SLOTS]; MAX_UDP_SOCKETS] =
143 unsafe { &mut *(&raw mut UDP_RX_META_POOL) };
144 let udp_rx_data_pool: &'static mut [[u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS] =
145 unsafe { &mut *(&raw mut UDP_RX_DATA_POOL) };
146 let udp_tx_meta_pool: &'static mut [[udp::PacketMetadata; UDP_META_SLOTS]; MAX_UDP_SOCKETS] =
147 unsafe { &mut *(&raw mut UDP_TX_META_POOL) };
148 let udp_tx_data_pool: &'static mut [[u8; UDP_BUF_SIZE]; MAX_UDP_SOCKETS] =
149 unsafe { &mut *(&raw mut UDP_TX_DATA_POOL) };
150
151 let mut udp_handles_tmp: [Option<SocketHandle>; MAX_UDP_SOCKETS] = [None; MAX_UDP_SOCKETS];
152 udp_rx_meta_pool
153 .iter_mut()
154 .zip(udp_rx_data_pool.iter_mut())
155 .zip(udp_tx_meta_pool.iter_mut())
156 .zip(udp_tx_data_pool.iter_mut())
157 .zip(udp_handles_tmp.iter_mut())
158 .for_each(|((((rx_meta, rx_data), tx_meta), tx_data), slot)| {
159 let sock = udp::Socket::new(
160 udp::PacketBuffer::new(&mut rx_meta[..], &mut rx_data[..]),
161 udp::PacketBuffer::new(&mut tx_meta[..], &mut tx_data[..]),
162 );
163 *slot = Some(sockets.add(sock));
164 });
165
166 let udp_handles = udp_handles_tmp.map(|opt| opt.unwrap());
167
168 let mdns_rx_meta: &'static mut [udp::PacketMetadata; MDNS_META_SLOTS] =
169 unsafe { &mut *(&raw mut MDNS_RX_META) };
170 let mdns_rx_data: &'static mut [u8; MDNS_BUF_SIZE] = unsafe { &mut *(&raw mut MDNS_RX_DATA) };
171 let mdns_tx_meta: &'static mut [udp::PacketMetadata; MDNS_META_SLOTS] =
172 unsafe { &mut *(&raw mut MDNS_TX_META) };
173 let mdns_tx_data: &'static mut [u8; MDNS_BUF_SIZE] = unsafe { &mut *(&raw mut MDNS_TX_DATA) };
174 let mdns_rx_buf = udp::PacketBuffer::new(&mut mdns_rx_meta[..], &mut mdns_rx_data[..]);
175 let mdns_tx_buf = udp::PacketBuffer::new(&mut mdns_tx_meta[..], &mut mdns_tx_data[..]);
176 let mut mdns_socket = udp::Socket::new(mdns_rx_buf, mdns_tx_buf);
177 mdns_socket
178 .bind(smoltcp::wire::IpListenEndpoint {
179 addr: None,
180 port: 5353,
181 })
182 .unwrap();
183 let mdns_handle = sockets.add(mdns_socket);
184
185 let link_local = eui64_link_local(&mac);
186 iface.update_ip_addrs(|addrs| {
187 let _ = addrs.push(IpCidr::Ipv6(Ipv6Cidr::new(link_local, 64)));
188 });
189
190 if iface
191 .join_multicast_group(Ipv4Address::new(224, 0, 0, 251))
192 .is_err()
193 {
194 MDNS_JOIN_FAILED.store(true, Ordering::Relaxed);
195 }
196
197 NetStack {
198 iface,
199 sockets,
200 tcp_handle,
201 shell_handles,
202 dhcp_handle,
203 dns_handle,
204 icmp_handle,
205 udp_handles,
206 mdns_handle,
207 }
208}
209
210pub fn eui64_link_local_bytes(mac: &[u8; 6]) -> [u8; 16] {
211 let addr = eui64_link_local(mac);
212 addr.octets()
213}
214
215fn eui64_link_local(mac: &[u8; 6]) -> Ipv6Address {
216 Ipv6Address::new(
217 0xfe80,
218 0,
219 0,
220 0,
221 ((mac[0] ^ 0x02) as u16) << 8 | mac[1] as u16,
222 (mac[2] as u16) << 8 | 0x00ff,
223 0xfe00 | mac[3] as u16,
224 (mac[4] as u16) << 8 | mac[5] as u16,
225 )
226}