| 1 | #![no_std ] |
| 2 | #![warn (missing_docs)] |
| 3 | #![doc = include_str!("../README.md" )] |
| 4 | |
| 5 | use core::task::Context; |
| 6 | |
| 7 | /// Representation of an hardware address, such as an Ethernet address or an IEEE802.15.4 address. |
| 8 | #[derive (Debug, Clone, Copy, PartialEq, Eq)] |
| 9 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
| 10 | #[non_exhaustive ] |
| 11 | pub enum HardwareAddress { |
| 12 | /// Ethernet medium, with a A six-octet Ethernet address. |
| 13 | /// |
| 14 | /// Devices of this type send and receive Ethernet frames, |
| 15 | /// and interfaces using it must do neighbor discovery via ARP or NDISC. |
| 16 | /// |
| 17 | /// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode. |
| 18 | Ethernet([u8; 6]), |
| 19 | /// 6LoWPAN over IEEE802.15.4, with an eight-octet address. |
| 20 | Ieee802154([u8; 8]), |
| 21 | /// Indicates that a Driver is IP-native, and has no hardware address. |
| 22 | /// |
| 23 | /// Devices of this type send and receive IP frames, without an |
| 24 | /// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done. |
| 25 | /// |
| 26 | /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode. |
| 27 | Ip, |
| 28 | } |
| 29 | |
| 30 | /// Main `embassy-net` driver API. |
| 31 | /// |
| 32 | /// This is essentially an interface for sending and receiving raw network frames. |
| 33 | /// |
| 34 | /// The interface is based on _tokens_, which are types that allow to receive/transmit a |
| 35 | /// single packet. The `receive` and `transmit` functions only construct such tokens, the |
| 36 | /// real sending/receiving operation are performed when the tokens are consumed. |
| 37 | pub trait Driver { |
| 38 | /// A token to receive a single network packet. |
| 39 | type RxToken<'a>: RxToken |
| 40 | where |
| 41 | Self: 'a; |
| 42 | |
| 43 | /// A token to transmit a single network packet. |
| 44 | type TxToken<'a>: TxToken |
| 45 | where |
| 46 | Self: 'a; |
| 47 | |
| 48 | /// Construct a token pair consisting of one receive token and one transmit token. |
| 49 | /// |
| 50 | /// If there is a packet ready to be received, this function must return `Some`. |
| 51 | /// If there isn't, it must return `None`, and wake `cx.waker()` when a packet is ready. |
| 52 | /// |
| 53 | /// The additional transmit token makes it possible to generate a reply packet based |
| 54 | /// on the contents of the received packet. For example, this makes it possible to |
| 55 | /// handle arbitrarily large ICMP echo ("ping") requests, where the all received bytes |
| 56 | /// need to be sent back, without heap allocation. |
| 57 | fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>; |
| 58 | |
| 59 | /// Construct a transmit token. |
| 60 | /// |
| 61 | /// If there is free space in the transmit buffer to transmit a packet, this function must return `Some`. |
| 62 | /// If there isn't, it must return `None`, and wake `cx.waker()` when space becomes available. |
| 63 | /// |
| 64 | /// Note that [`TxToken::consume`] is infallible, so it is not allowed to return a token |
| 65 | /// if there is no free space and fail later. |
| 66 | fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>>; |
| 67 | |
| 68 | /// Get the link state. |
| 69 | /// |
| 70 | /// This function must return the current link state of the device, and wake `cx.waker()` when |
| 71 | /// the link state changes. |
| 72 | fn link_state(&mut self, cx: &mut Context) -> LinkState; |
| 73 | |
| 74 | /// Get a description of device capabilities. |
| 75 | fn capabilities(&self) -> Capabilities; |
| 76 | |
| 77 | /// Get the device's hardware address. |
| 78 | /// |
| 79 | /// The returned hardware address also determines the "medium" of this driver. This indicates |
| 80 | /// what kind of packet the sent/received bytes are, and determines some behaviors of |
| 81 | /// the interface. For example, ARP/NDISC address resolution is only done for Ethernet mediums. |
| 82 | fn hardware_address(&self) -> HardwareAddress; |
| 83 | } |
| 84 | |
| 85 | impl<T: ?Sized + Driver> Driver for &mut T { |
| 86 | type RxToken<'a> = T::RxToken<'a> |
| 87 | where |
| 88 | Self: 'a; |
| 89 | type TxToken<'a> = T::TxToken<'a> |
| 90 | where |
| 91 | Self: 'a; |
| 92 | |
| 93 | fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> { |
| 94 | T::transmit(self, cx) |
| 95 | } |
| 96 | fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { |
| 97 | T::receive(self, cx) |
| 98 | } |
| 99 | fn capabilities(&self) -> Capabilities { |
| 100 | T::capabilities(self) |
| 101 | } |
| 102 | fn link_state(&mut self, cx: &mut Context) -> LinkState { |
| 103 | T::link_state(self, cx) |
| 104 | } |
| 105 | fn hardware_address(&self) -> HardwareAddress { |
| 106 | T::hardware_address(self) |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | /// A token to receive a single network packet. |
| 111 | pub trait RxToken { |
| 112 | /// Consumes the token to receive a single network packet. |
| 113 | /// |
| 114 | /// This method receives a packet and then calls the given closure `f` with the raw |
| 115 | /// packet bytes as argument. |
| 116 | fn consume<R, F>(self, f: F) -> R |
| 117 | where |
| 118 | F: FnOnce(&mut [u8]) -> R; |
| 119 | } |
| 120 | |
| 121 | /// A token to transmit a single network packet. |
| 122 | pub trait TxToken { |
| 123 | /// Consumes the token to send a single network packet. |
| 124 | /// |
| 125 | /// This method constructs a transmit buffer of size `len` and calls the passed |
| 126 | /// closure `f` with a mutable reference to that buffer. The closure should construct |
| 127 | /// a valid network packet (e.g. an ethernet packet) in the buffer. When the closure |
| 128 | /// returns, the transmit buffer is sent out. |
| 129 | fn consume<R, F>(self, len: usize, f: F) -> R |
| 130 | where |
| 131 | F: FnOnce(&mut [u8]) -> R; |
| 132 | } |
| 133 | |
| 134 | /// A description of device capabilities. |
| 135 | /// |
| 136 | /// Higher-level protocols may achieve higher throughput or lower latency if they consider |
| 137 | /// the bandwidth or packet size limitations. |
| 138 | #[derive (Debug, Clone, Default)] |
| 139 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
| 140 | #[non_exhaustive ] |
| 141 | pub struct Capabilities { |
| 142 | /// Maximum transmission unit. |
| 143 | /// |
| 144 | /// The network device is unable to send or receive frames larger than the value returned |
| 145 | /// by this function. |
| 146 | /// |
| 147 | /// For Ethernet devices, this is the maximum Ethernet frame size, including the Ethernet header (14 octets), but |
| 148 | /// *not* including the Ethernet FCS (4 octets). Therefore, Ethernet MTU = IP MTU + 14. |
| 149 | /// |
| 150 | /// Note that in Linux and other OSes, "MTU" is the IP MTU, not the Ethernet MTU, even for Ethernet |
| 151 | /// devices. This is a common source of confusion. |
| 152 | /// |
| 153 | /// Most common IP MTU is 1500. Minimum is 576 (for IPv4) or 1280 (for IPv6). Maximum is 9216 octets. |
| 154 | pub max_transmission_unit: usize, |
| 155 | |
| 156 | /// Maximum burst size, in terms of MTU. |
| 157 | /// |
| 158 | /// The network device is unable to send or receive bursts large than the value returned |
| 159 | /// by this function. |
| 160 | /// |
| 161 | /// If `None`, there is no fixed limit on burst size, e.g. if network buffers are |
| 162 | /// dynamically allocated. |
| 163 | pub max_burst_size: Option<usize>, |
| 164 | |
| 165 | /// Checksum behavior. |
| 166 | /// |
| 167 | /// If the network device is capable of verifying or computing checksums for some protocols, |
| 168 | /// it can request that the stack not do so in software to improve performance. |
| 169 | pub checksum: ChecksumCapabilities, |
| 170 | } |
| 171 | |
| 172 | /// A description of checksum behavior for every supported protocol. |
| 173 | #[derive (Debug, Clone, Default)] |
| 174 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
| 175 | #[non_exhaustive ] |
| 176 | pub struct ChecksumCapabilities { |
| 177 | /// Checksum behavior for IPv4. |
| 178 | pub ipv4: Checksum, |
| 179 | /// Checksum behavior for UDP. |
| 180 | pub udp: Checksum, |
| 181 | /// Checksum behavior for TCP. |
| 182 | pub tcp: Checksum, |
| 183 | /// Checksum behavior for ICMPv4. |
| 184 | pub icmpv4: Checksum, |
| 185 | /// Checksum behavior for ICMPv6. |
| 186 | pub icmpv6: Checksum, |
| 187 | } |
| 188 | |
| 189 | /// A description of checksum behavior for a particular protocol. |
| 190 | #[derive (Debug, Clone, Copy)] |
| 191 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
| 192 | pub enum Checksum { |
| 193 | /// Verify checksum when receiving and compute checksum when sending. |
| 194 | Both, |
| 195 | /// Verify checksum when receiving. |
| 196 | Rx, |
| 197 | /// Compute checksum before sending. |
| 198 | Tx, |
| 199 | /// Ignore checksum completely. |
| 200 | None, |
| 201 | } |
| 202 | |
| 203 | impl Default for Checksum { |
| 204 | fn default() -> Checksum { |
| 205 | Checksum::Both |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | /// The link state of a network device. |
| 210 | #[derive (PartialEq, Eq, Clone, Copy)] |
| 211 | #[cfg_attr (feature = "defmt" , derive(defmt::Format))] |
| 212 | pub enum LinkState { |
| 213 | /// The link is down. |
| 214 | Down, |
| 215 | /// The link is up. |
| 216 | Up, |
| 217 | } |
| 218 | |