components/
udp_driver.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Component to initialize the userland UDP driver.
6//!
7//! This provides one Component, UDPDriverComponent. This component initializes
8//! a userspace UDP driver that allows apps to use the UDP stack.
9//!
10//! Usage
11//! -----
12//! ```rust
13//!    let udp_driver = UDPDriverComponent::new(
14//!        board_kernel,
15//!        udp_send_mux,
16//!        udp_recv_mux,
17//!        udp_port_table,
18//!        local_ip_ifaces,
19//!        PAYLOAD_LEN,
20//!     )
21//!     .finalize(components::udp_driver_component_static!());
22//! ```
23
24use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
25use capsules_extra::net::ipv6::ip_utils::IPAddr;
26use capsules_extra::net::ipv6::ipv6_send::IP6SendStruct;
27use capsules_extra::net::network_capabilities::{
28    AddrRange, NetworkCapability, PortRange, UdpVisibilityCapability,
29};
30use capsules_extra::net::udp::udp_port_table::UdpPortManager;
31use capsules_extra::net::udp::udp_recv::MuxUdpReceiver;
32use capsules_extra::net::udp::udp_recv::UDPReceiver;
33use capsules_extra::net::udp::udp_send::{MuxUdpSender, UDPSendStruct, UDPSender};
34use core::mem::MaybeUninit;
35use kernel::capabilities;
36use kernel::capabilities::NetworkCapabilityCreationCapability;
37use kernel::component::Component;
38use kernel::create_capability;
39use kernel::hil::time::Alarm;
40
41const MAX_PAYLOAD_LEN: usize = super::udp_mux::MAX_PAYLOAD_LEN;
42
43// Setup static space for the objects.
44#[macro_export]
45macro_rules! udp_driver_component_static {
46    ($A:ty $(,)?) => {{
47        use components::udp_mux::MAX_PAYLOAD_LEN;
48
49        let udp_send = kernel::static_buf!(
50            capsules_extra::net::udp::udp_send::UDPSendStruct<
51                'static,
52                capsules_extra::net::ipv6::ipv6_send::IP6SendStruct<
53                    'static,
54                    capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<'static, $A>,
55                >,
56            >
57        );
58        let udp_vis_cap =
59            kernel::static_buf!(capsules_extra::net::network_capabilities::UdpVisibilityCapability);
60        let net_cap =
61            kernel::static_buf!(capsules_extra::net::network_capabilities::NetworkCapability);
62        let udp_driver = kernel::static_buf!(capsules_extra::net::udp::UDPDriver<'static>);
63        let buffer = kernel::static_buf!([u8; MAX_PAYLOAD_LEN]);
64        let udp_recv =
65            kernel::static_buf!(capsules_extra::net::udp::udp_recv::UDPReceiver<'static>);
66
67        (udp_send, udp_vis_cap, net_cap, udp_driver, buffer, udp_recv)
68    };};
69}
70
71pub struct UDPDriverComponent<A: Alarm<'static> + 'static> {
72    board_kernel: &'static kernel::Kernel,
73    driver_num: usize,
74    udp_send_mux:
75        &'static MuxUdpSender<'static, IP6SendStruct<'static, VirtualMuxAlarm<'static, A>>>,
76    udp_recv_mux: &'static MuxUdpReceiver<'static>,
77    port_table: &'static UdpPortManager,
78    interface_list: &'static [IPAddr],
79}
80
81impl<A: Alarm<'static>> UDPDriverComponent<A> {
82    pub fn new(
83        board_kernel: &'static kernel::Kernel,
84        driver_num: usize,
85        udp_send_mux: &'static MuxUdpSender<
86            'static,
87            IP6SendStruct<'static, VirtualMuxAlarm<'static, A>>,
88        >,
89        udp_recv_mux: &'static MuxUdpReceiver<'static>,
90        port_table: &'static UdpPortManager,
91        interface_list: &'static [IPAddr],
92    ) -> Self {
93        Self {
94            board_kernel,
95            driver_num,
96            udp_send_mux,
97            udp_recv_mux,
98            port_table,
99            interface_list,
100        }
101    }
102}
103
104impl<A: Alarm<'static>> Component for UDPDriverComponent<A> {
105    type StaticInput = (
106        &'static mut MaybeUninit<
107            UDPSendStruct<
108                'static,
109                capsules_extra::net::ipv6::ipv6_send::IP6SendStruct<
110                    'static,
111                    VirtualMuxAlarm<'static, A>,
112                >,
113            >,
114        >,
115        &'static mut MaybeUninit<
116            capsules_extra::net::network_capabilities::UdpVisibilityCapability,
117        >,
118        &'static mut MaybeUninit<capsules_extra::net::network_capabilities::NetworkCapability>,
119        &'static mut MaybeUninit<capsules_extra::net::udp::UDPDriver<'static>>,
120        &'static mut MaybeUninit<[u8; MAX_PAYLOAD_LEN]>,
121        &'static mut MaybeUninit<UDPReceiver<'static>>,
122    );
123    type Output = &'static capsules_extra::net::udp::UDPDriver<'static>;
124
125    fn finalize(self, s: Self::StaticInput) -> Self::Output {
126        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
127        // TODO: change initialization below
128        let create_cap = create_capability!(NetworkCapabilityCreationCapability);
129        let udp_vis = s.1.write(UdpVisibilityCapability::new(&create_cap));
130        let udp_send = s.0.write(UDPSendStruct::new(self.udp_send_mux, udp_vis));
131
132        // Can't use create_capability bc need capability to have a static lifetime
133        // so that UDP driver can use it as needed
134        struct DriverCap;
135        unsafe impl capabilities::UdpDriverCapability for DriverCap {}
136        static DRIVER_CAP: DriverCap = DriverCap;
137
138        let net_cap = s.2.write(NetworkCapability::new(
139            AddrRange::Any,
140            PortRange::Any,
141            PortRange::Any,
142            &create_cap,
143        ));
144
145        let buffer = s.4.write([0; MAX_PAYLOAD_LEN]);
146
147        let udp_driver = s.3.write(capsules_extra::net::udp::UDPDriver::new(
148            udp_send,
149            self.board_kernel.create_grant(self.driver_num, &grant_cap),
150            self.interface_list,
151            MAX_PAYLOAD_LEN,
152            self.port_table,
153            kernel::utilities::leasable_buffer::SubSliceMut::new(buffer),
154            &DRIVER_CAP,
155            net_cap,
156        ));
157        udp_send.set_client(udp_driver);
158        self.port_table.set_user_ports(udp_driver, &DRIVER_CAP);
159
160        let udp_driver_rcvr = s.5.write(UDPReceiver::new());
161        self.udp_recv_mux.set_driver(udp_driver);
162        self.udp_recv_mux.add_client(udp_driver_rcvr);
163        udp_driver
164    }
165}