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