1use capsules_core::virtualizers::virtual_aes_ccm::MuxAES128CCM;
30use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
31use capsules_extra::net::ipv6::ipv6_send::IP6SendStruct;
32use capsules_extra::net::network_capabilities::{
33 AddrRange, NetworkCapability, PortRange, UdpVisibilityCapability,
34};
35use kernel::hil::symmetric_encryption::{self, AES, AES128, AESCBC, AESCCM, AESCtr, AESECB};
36
37use capsules_core::virtualizers::virtual_alarm::MuxAlarm;
38use capsules_extra::net::thread::thread_utils::THREAD_PORT_NUMBER;
39use capsules_extra::net::udp::udp_port_table::UdpPortManager;
40use capsules_extra::net::udp::udp_recv::MuxUdpReceiver;
41use capsules_extra::net::udp::udp_recv::UDPReceiver;
42use capsules_extra::net::udp::udp_send::{MuxUdpSender, UDPSendStruct, UDPSender};
43use core::mem::MaybeUninit;
44use kernel::capabilities::{
45 MemoryAllocationCapability, NetworkCapabilityCreationCapability, UdpDriverCapability,
46};
47use kernel::component::Component;
48use kernel::hil::radio;
49use kernel::hil::time::Alarm;
50
51const MAX_PAYLOAD_LEN: usize = super::udp_mux::MAX_PAYLOAD_LEN;
52pub const CRYPT_SIZE: usize = 3 * symmetric_encryption::AES_BLOCK_SIZE + radio::MAX_BUF_SIZE;
53
54#[macro_export]
56macro_rules! thread_network_component_static {
57 ($A:ty, $B:ty, $C:ty $(,)?) => {{
58 use components::udp_mux::MAX_PAYLOAD_LEN;
59
60 let udp_send = kernel::static_buf!(
61 capsules_extra::net::udp::udp_send::UDPSendStruct<
62 'static,
63 capsules_extra::net::ipv6::ipv6_send::IP6SendStruct<
64 'static,
65 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>,
66 >,
67 >
68 );
69 let udp_vis_cap =
70 kernel::static_buf!(capsules_extra::net::network_capabilities::UdpVisibilityCapability);
71 let net_cap =
72 kernel::static_buf!(capsules_extra::net::network_capabilities::NetworkCapability);
73 let thread_network_driver = kernel::static_buf!(
74 capsules_extra::net::thread::driver::ThreadNetworkDriver<
75 'static,
76 VirtualMuxAlarm<'static, $A>,
77 >
78 );
79 let send_buffer = kernel::static_buf!([u8; MAX_PAYLOAD_LEN]);
80 let recv_buffer = kernel::static_buf!([u8; MAX_PAYLOAD_LEN]);
81 let udp_recv =
82 kernel::static_buf!(capsules_extra::net::udp::udp_recv::UDPReceiver<'static>);
83 let crypt_buf = kernel::static_buf!([u8; components::ieee802154::CRYPT_SIZE]);
84 let crypt = kernel::static_buf!(
85 capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, $B>,
86 );
87 let alarm = kernel::static_buf!(VirtualMuxAlarm<'static, $A>);
88 let driver_cap = kernel::static_buf!($C);
89
90 (
91 udp_send,
92 udp_vis_cap,
93 net_cap,
94 thread_network_driver,
95 send_buffer,
96 recv_buffer,
97 udp_recv,
98 crypt_buf,
99 crypt,
100 alarm,
101 driver_cap,
102 )
103 }};
104}
105pub struct ThreadNetworkComponent<
106 A: Alarm<'static> + 'static,
107 B: AES<'static, AES128> + AESCtr + AESCBC + AESECB + 'static,
108 C: UdpDriverCapability + 'static,
109 MEM: MemoryAllocationCapability + 'static,
110 NET: NetworkCapabilityCreationCapability + 'static,
111> {
112 board_kernel: &'static kernel::Kernel,
113 driver_num: usize,
114 udp_send_mux:
115 &'static MuxUdpSender<'static, IP6SendStruct<'static, VirtualMuxAlarm<'static, A>>>,
116 udp_recv_mux: &'static MuxUdpReceiver<'static>,
117 port_table: &'static UdpPortManager,
118 aes_mux: &'static MuxAES128CCM<'static, B>,
119 serial_num: [u8; 8],
120 alarm_mux: &'static MuxAlarm<'static, A>,
121 driver_cap: C,
122 mem_cap: MEM,
123 create_cap: NET,
124}
125
126impl<
127 A: Alarm<'static> + 'static,
128 B: AES<'static, AES128> + AESCtr + AESCBC + AESECB + 'static,
129 C: UdpDriverCapability + 'static,
130 MEM: MemoryAllocationCapability + 'static,
131 NET: NetworkCapabilityCreationCapability + 'static,
132> ThreadNetworkComponent<A, B, C, MEM, NET>
133{
134 pub fn new(
135 board_kernel: &'static kernel::Kernel,
136 driver_num: usize,
137 udp_send_mux: &'static MuxUdpSender<
138 'static,
139 IP6SendStruct<'static, VirtualMuxAlarm<'static, A>>,
140 >,
141 udp_recv_mux: &'static MuxUdpReceiver<'static>,
142 port_table: &'static UdpPortManager,
143 aes_mux: &'static MuxAES128CCM<'static, B>,
144 serial_num: [u8; 8],
145 alarm_mux: &'static MuxAlarm<'static, A>,
146 driver_cap: C,
147 mem_cap: MEM,
148 create_cap: NET,
149 ) -> Self {
150 Self {
151 board_kernel,
152 driver_num,
153 udp_send_mux,
154 udp_recv_mux,
155 port_table,
156 aes_mux,
157 serial_num,
158 alarm_mux,
159 driver_cap,
160 mem_cap,
161 create_cap,
162 }
163 }
164}
165
166impl<
167 A: Alarm<'static> + 'static,
168 B: AES<'static, AES128> + AESCtr + AESCBC + AESECB + 'static,
169 C: UdpDriverCapability + 'static,
170 MEM: MemoryAllocationCapability + 'static,
171 NET: NetworkCapabilityCreationCapability + 'static,
172> Component for ThreadNetworkComponent<A, B, C, MEM, NET>
173{
174 type StaticInput = (
175 &'static mut MaybeUninit<
176 UDPSendStruct<
177 'static,
178 capsules_extra::net::ipv6::ipv6_send::IP6SendStruct<
179 'static,
180 VirtualMuxAlarm<'static, A>,
181 >,
182 >,
183 >,
184 &'static mut MaybeUninit<
185 capsules_extra::net::network_capabilities::UdpVisibilityCapability,
186 >,
187 &'static mut MaybeUninit<capsules_extra::net::network_capabilities::NetworkCapability>,
188 &'static mut MaybeUninit<
189 capsules_extra::net::thread::driver::ThreadNetworkDriver<
190 'static,
191 VirtualMuxAlarm<'static, A>,
192 >,
193 >,
194 &'static mut MaybeUninit<[u8; MAX_PAYLOAD_LEN]>,
195 &'static mut MaybeUninit<[u8; MAX_PAYLOAD_LEN]>,
196 &'static mut MaybeUninit<UDPReceiver<'static>>,
197 &'static mut MaybeUninit<[u8; CRYPT_SIZE]>,
198 &'static mut MaybeUninit<
199 capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM<'static, B>,
200 >,
201 &'static mut MaybeUninit<VirtualMuxAlarm<'static, A>>,
202 &'static mut MaybeUninit<C>,
203 );
204 type Output = &'static capsules_extra::net::thread::driver::ThreadNetworkDriver<
205 'static,
206 VirtualMuxAlarm<'static, A>,
207 >;
208
209 fn finalize(self, s: Self::StaticInput) -> Self::Output {
210 let thread_virtual_alarm: &mut VirtualMuxAlarm<'_, A> =
211 s.9.write(VirtualMuxAlarm::new(self.alarm_mux));
212 thread_virtual_alarm.setup();
213
214 let crypt_buf = s.7.write([0; CRYPT_SIZE]);
216 let aes_ccm = s.8.write(
217 capsules_core::virtualizers::virtual_aes_ccm::VirtualAES128CCM::new(
218 self.aes_mux,
219 crypt_buf,
220 ),
221 );
222 aes_ccm.setup();
223
224 let udp_vis = s.1.write(UdpVisibilityCapability::new(&self.create_cap));
225 let udp_send = s.0.write(UDPSendStruct::new(self.udp_send_mux, udp_vis));
226
227 let driver_cap: &'static C = s.10.write(self.driver_cap);
228
229 let net_cap = s.2.write(NetworkCapability::new(
230 AddrRange::Any,
231 PortRange::Any,
232 PortRange::Any,
233 &self.create_cap,
234 ));
235
236 let send_buffer = s.4.write([0; MAX_PAYLOAD_LEN]);
237 let recv_buffer = s.5.write([0; MAX_PAYLOAD_LEN]);
238
239 let thread_network_driver = s.3.write(
240 capsules_extra::net::thread::driver::ThreadNetworkDriver::new(
241 udp_send,
242 aes_ccm,
243 thread_virtual_alarm,
244 self.board_kernel
245 .create_grant(self.driver_num, &self.mem_cap),
246 self.serial_num,
247 MAX_PAYLOAD_LEN,
248 self.port_table,
249 kernel::utilities::leasable_buffer::SubSliceMut::new(send_buffer),
250 kernel::utilities::leasable_buffer::SubSliceMut::new(recv_buffer),
251 driver_cap,
252 net_cap,
253 ),
254 );
255
256 thread_virtual_alarm.set_alarm_client(thread_network_driver);
257
258 udp_send.set_client(thread_network_driver);
259 AESCCM::set_client(aes_ccm, thread_network_driver);
260
261 let udp_driver_rcvr = s.6.write(UDPReceiver::new());
262 udp_driver_rcvr.set_client(thread_network_driver);
263
264 self.port_table
272 .create_socket()
273 .map(|socket| {
274 self.port_table
275 .bind(socket, THREAD_PORT_NUMBER, net_cap)
276 .map_or_else(
277 |_| (),
278 |(tx_bind, rx_bind)| {
279 udp_driver_rcvr.set_binding(rx_bind);
280 udp_send.set_binding(tx_bind);
281 },
282 )
283 })
284 .unwrap();
285
286 self.udp_recv_mux.add_client(udp_driver_rcvr);
287
288 thread_network_driver
289 }
290}