mod.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*! Access to networking hardware.
  2. The `phy` module deals with the *network devices*. It provides a trait
  3. for transmitting and receiving frames, [Device](trait.Device.html)
  4. and implementations of it:
  5. * the [_loopback_](struct.Loopback.html), for zero dependency testing;
  6. * _middleware_ [Tracer](struct.Tracer.html) and
  7. [FaultInjector](struct.FaultInjector.html), to facilitate debugging;
  8. * _adapters_ [RawSocket](struct.RawSocket.html) and
  9. [TunTapInterface](struct.TunTapInterface.html), to transmit and receive frames
  10. on the host OS.
  11. */
  12. #![cfg_attr(
  13. feature = "medium-ethernet",
  14. doc = r##"
  15. # Examples
  16. An implementation of the [Device](trait.Device.html) trait for a simple hardware
  17. Ethernet controller could look as follows:
  18. ```rust
  19. use smoltcp::phy::{self, DeviceCapabilities, Device, Medium};
  20. use smoltcp::time::Instant;
  21. struct StmPhy {
  22. rx_buffer: [u8; 1536],
  23. tx_buffer: [u8; 1536],
  24. }
  25. impl<'a> StmPhy {
  26. fn new() -> StmPhy {
  27. StmPhy {
  28. rx_buffer: [0; 1536],
  29. tx_buffer: [0; 1536],
  30. }
  31. }
  32. }
  33. impl phy::Device for StmPhy {
  34. type RxToken<'a> = StmPhyRxToken<'a> where Self: 'a;
  35. type TxToken<'a> = StmPhyTxToken<'a> where Self: 'a;
  36. fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
  37. Some((StmPhyRxToken(&mut self.rx_buffer[..]),
  38. StmPhyTxToken(&mut self.tx_buffer[..])))
  39. }
  40. fn transmit(&mut self, _timestamp: Instant) -> Option<Self::TxToken<'_>> {
  41. Some(StmPhyTxToken(&mut self.tx_buffer[..]))
  42. }
  43. fn capabilities(&self) -> DeviceCapabilities {
  44. let mut caps = DeviceCapabilities::default();
  45. caps.max_transmission_unit = 1536;
  46. caps.max_burst_size = Some(1);
  47. caps.medium = Medium::Ethernet;
  48. caps
  49. }
  50. }
  51. struct StmPhyRxToken<'a>(&'a mut [u8]);
  52. impl<'a> phy::RxToken for StmPhyRxToken<'a> {
  53. fn consume<R, F>(self, f: F) -> R
  54. where F: FnOnce(& [u8]) -> R
  55. {
  56. // TODO: receive packet into buffer
  57. let result = f(&self.0);
  58. println!("rx called");
  59. result
  60. }
  61. }
  62. struct StmPhyTxToken<'a>(&'a mut [u8]);
  63. impl<'a> phy::TxToken for StmPhyTxToken<'a> {
  64. fn consume<R, F>(self, len: usize, f: F) -> R
  65. where F: FnOnce(&mut [u8]) -> R
  66. {
  67. let result = f(&mut self.0[..len]);
  68. println!("tx called {}", len);
  69. // TODO: send packet out
  70. result
  71. }
  72. }
  73. ```
  74. "##
  75. )]
  76. use crate::time::Instant;
  77. #[cfg(all(
  78. any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"),
  79. unix
  80. ))]
  81. mod sys;
  82. mod fault_injector;
  83. mod fuzz_injector;
  84. #[cfg(feature = "alloc")]
  85. mod loopback;
  86. mod pcap_writer;
  87. #[cfg(all(feature = "phy-raw_socket", unix))]
  88. mod raw_socket;
  89. mod tracer;
  90. #[cfg(all(
  91. feature = "phy-tuntap_interface",
  92. any(target_os = "linux", target_os = "android")
  93. ))]
  94. mod tuntap_interface;
  95. #[cfg(all(
  96. any(feature = "phy-raw_socket", feature = "phy-tuntap_interface"),
  97. unix
  98. ))]
  99. pub use self::sys::wait;
  100. pub use self::fault_injector::FaultInjector;
  101. pub use self::fuzz_injector::{FuzzInjector, Fuzzer};
  102. #[cfg(feature = "alloc")]
  103. pub use self::loopback::Loopback;
  104. pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter};
  105. #[cfg(all(feature = "phy-raw_socket", unix))]
  106. pub use self::raw_socket::RawSocket;
  107. pub use self::tracer::Tracer;
  108. #[cfg(all(
  109. feature = "phy-tuntap_interface",
  110. any(target_os = "linux", target_os = "android")
  111. ))]
  112. pub use self::tuntap_interface::TunTapInterface;
  113. /// Metadata associated to a packet.
  114. ///
  115. /// The packet metadata is a set of attributes associated to network packets
  116. /// as they travel up or down the stack. The metadata is get/set by the
  117. /// [`Device`] implementations or by the user when sending/receiving packets from a
  118. /// socket.
  119. ///
  120. /// Metadata fields are enabled via Cargo features. If no field is enabled, this
  121. /// struct becomes zero-sized, which allows the compiler to optimize it out as if
  122. /// the packet metadata mechanism didn't exist at all.
  123. ///
  124. /// Currently only UDP sockets allow setting/retrieving packet metadata. The metadata
  125. /// for packets emitted with other sockets will be all default values.
  126. ///
  127. /// This struct is marked as `#[non_exhaustive]`. This means it is not possible to
  128. /// create it directly by specifying all fields. You have to instead create it with
  129. /// default values and then set the fields you want. This makes adding metadata
  130. /// fields a non-breaking change.
  131. ///
  132. /// ```rust
  133. /// let mut meta = smoltcp::phy::PacketMeta::default();
  134. /// #[cfg(feature = "packetmeta-id")]
  135. /// {
  136. /// meta.id = 15;
  137. /// }
  138. /// ```
  139. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  140. #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy, Default)]
  141. #[non_exhaustive]
  142. pub struct PacketMeta {
  143. #[cfg(feature = "packetmeta-id")]
  144. pub id: u32,
  145. }
  146. /// A description of checksum behavior for a particular protocol.
  147. #[derive(Debug, Clone, Copy, Default)]
  148. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  149. pub enum Checksum {
  150. /// Verify checksum when receiving and compute checksum when sending.
  151. #[default]
  152. Both,
  153. /// Verify checksum when receiving.
  154. Rx,
  155. /// Compute checksum before sending.
  156. Tx,
  157. /// Ignore checksum completely.
  158. None,
  159. }
  160. impl Checksum {
  161. /// Returns whether checksum should be verified when receiving.
  162. pub fn rx(&self) -> bool {
  163. match *self {
  164. Checksum::Both | Checksum::Rx => true,
  165. _ => false,
  166. }
  167. }
  168. /// Returns whether checksum should be verified when sending.
  169. pub fn tx(&self) -> bool {
  170. match *self {
  171. Checksum::Both | Checksum::Tx => true,
  172. _ => false,
  173. }
  174. }
  175. }
  176. /// A description of checksum behavior for every supported protocol.
  177. #[derive(Debug, Clone, Default)]
  178. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  179. #[non_exhaustive]
  180. pub struct ChecksumCapabilities {
  181. pub ipv4: Checksum,
  182. pub udp: Checksum,
  183. pub tcp: Checksum,
  184. #[cfg(feature = "proto-ipv4")]
  185. pub icmpv4: Checksum,
  186. #[cfg(feature = "proto-ipv6")]
  187. pub icmpv6: Checksum,
  188. }
  189. impl ChecksumCapabilities {
  190. /// Checksum behavior that results in not computing or verifying checksums
  191. /// for any of the supported protocols.
  192. pub fn ignored() -> Self {
  193. ChecksumCapabilities {
  194. ipv4: Checksum::None,
  195. udp: Checksum::None,
  196. tcp: Checksum::None,
  197. #[cfg(feature = "proto-ipv4")]
  198. icmpv4: Checksum::None,
  199. #[cfg(feature = "proto-ipv6")]
  200. icmpv6: Checksum::None,
  201. }
  202. }
  203. }
  204. /// A description of device capabilities.
  205. ///
  206. /// Higher-level protocols may achieve higher throughput or lower latency if they consider
  207. /// the bandwidth or packet size limitations.
  208. #[derive(Debug, Clone, Default)]
  209. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  210. #[non_exhaustive]
  211. pub struct DeviceCapabilities {
  212. /// Medium of the device.
  213. ///
  214. /// This indicates what kind of packet the sent/received bytes are, and determines
  215. /// some behaviors of Interface. For example, ARP/NDISC address resolution is only done
  216. /// for Ethernet mediums.
  217. pub medium: Medium,
  218. /// Maximum transmission unit.
  219. ///
  220. /// The network device is unable to send or receive frames larger than the value returned
  221. /// by this function.
  222. ///
  223. /// For Ethernet devices, this is the maximum Ethernet frame size, including the Ethernet header (14 octets), but
  224. /// *not* including the Ethernet FCS (4 octets). Therefore, Ethernet MTU = IP MTU + 14.
  225. ///
  226. /// Note that in Linux and other OSes, "MTU" is the IP MTU, not the Ethernet MTU, even for Ethernet
  227. /// devices. This is a common source of confusion.
  228. ///
  229. /// Most common IP MTU is 1500. Minimum is 576 (for IPv4) or 1280 (for IPv6). Maximum is 9216 octets.
  230. pub max_transmission_unit: usize,
  231. /// Maximum burst size, in terms of MTU.
  232. ///
  233. /// The network device is unable to send or receive bursts large than the value returned
  234. /// by this function.
  235. ///
  236. /// If `None`, there is no fixed limit on burst size, e.g. if network buffers are
  237. /// dynamically allocated.
  238. pub max_burst_size: Option<usize>,
  239. /// Checksum behavior.
  240. ///
  241. /// If the network device is capable of verifying or computing checksums for some protocols,
  242. /// it can request that the stack not do so in software to improve performance.
  243. pub checksum: ChecksumCapabilities,
  244. }
  245. impl DeviceCapabilities {
  246. pub fn ip_mtu(&self) -> usize {
  247. match self.medium {
  248. #[cfg(feature = "medium-ethernet")]
  249. Medium::Ethernet => {
  250. self.max_transmission_unit - crate::wire::EthernetFrame::<&[u8]>::header_len()
  251. }
  252. #[cfg(feature = "medium-ip")]
  253. Medium::Ip => self.max_transmission_unit,
  254. #[cfg(feature = "medium-ieee802154")]
  255. Medium::Ieee802154 => self.max_transmission_unit, // TODO(thvdveld): what is the MTU for Medium::IEEE802
  256. }
  257. }
  258. }
  259. /// Type of medium of a device.
  260. #[derive(Debug, Eq, PartialEq, Copy, Clone)]
  261. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  262. pub enum Medium {
  263. /// Ethernet medium. Devices of this type send and receive Ethernet frames,
  264. /// and interfaces using it must do neighbor discovery via ARP or NDISC.
  265. ///
  266. /// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode.
  267. #[cfg(feature = "medium-ethernet")]
  268. Ethernet,
  269. /// IP medium. Devices of this type send and receive IP frames, without an
  270. /// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done.
  271. ///
  272. /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode.
  273. #[cfg(feature = "medium-ip")]
  274. Ip,
  275. #[cfg(feature = "medium-ieee802154")]
  276. Ieee802154,
  277. }
  278. impl Default for Medium {
  279. fn default() -> Medium {
  280. #[cfg(feature = "medium-ethernet")]
  281. return Medium::Ethernet;
  282. #[cfg(all(feature = "medium-ip", not(feature = "medium-ethernet")))]
  283. return Medium::Ip;
  284. #[cfg(all(
  285. feature = "medium-ieee802154",
  286. not(feature = "medium-ip"),
  287. not(feature = "medium-ethernet")
  288. ))]
  289. return Medium::Ieee802154;
  290. #[cfg(all(
  291. not(feature = "medium-ip"),
  292. not(feature = "medium-ethernet"),
  293. not(feature = "medium-ieee802154")
  294. ))]
  295. return panic!("No medium enabled");
  296. }
  297. }
  298. /// An interface for sending and receiving raw network frames.
  299. ///
  300. /// The interface is based on _tokens_, which are types that allow to receive/transmit a
  301. /// single packet. The `receive` and `transmit` functions only construct such tokens, the
  302. /// real sending/receiving operation are performed when the tokens are consumed.
  303. pub trait Device {
  304. type RxToken<'a>: RxToken
  305. where
  306. Self: 'a;
  307. type TxToken<'a>: TxToken
  308. where
  309. Self: 'a;
  310. /// Construct a token pair consisting of one receive token and one transmit token.
  311. ///
  312. /// The additional transmit token makes it possible to generate a reply packet based
  313. /// on the contents of the received packet. For example, this makes it possible to
  314. /// handle arbitrarily large ICMP echo ("ping") requests, where the all received bytes
  315. /// need to be sent back, without heap allocation.
  316. ///
  317. /// The timestamp must be a number of milliseconds, monotonically increasing since an
  318. /// arbitrary moment in time, such as system startup.
  319. fn receive(&mut self, timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>;
  320. /// Construct a transmit token.
  321. ///
  322. /// The timestamp must be a number of milliseconds, monotonically increasing since an
  323. /// arbitrary moment in time, such as system startup.
  324. fn transmit(&mut self, timestamp: Instant) -> Option<Self::TxToken<'_>>;
  325. /// Get a description of device capabilities.
  326. fn capabilities(&self) -> DeviceCapabilities;
  327. }
  328. /// A token to receive a single network packet.
  329. pub trait RxToken {
  330. /// Consumes the token to receive a single network packet.
  331. ///
  332. /// This method receives a packet and then calls the given closure `f` with the raw
  333. /// packet bytes as argument.
  334. fn consume<R, F>(self, f: F) -> R
  335. where
  336. F: FnOnce(&[u8]) -> R;
  337. /// The Packet ID associated with the frame received by this [`RxToken`]
  338. fn meta(&self) -> PacketMeta {
  339. PacketMeta::default()
  340. }
  341. }
  342. /// A token to transmit a single network packet.
  343. pub trait TxToken {
  344. /// Consumes the token to send a single network packet.
  345. ///
  346. /// This method constructs a transmit buffer of size `len` and calls the passed
  347. /// closure `f` with a mutable reference to that buffer. The closure should construct
  348. /// a valid network packet (e.g. an ethernet packet) in the buffer. When the closure
  349. /// returns, the transmit buffer is sent out.
  350. fn consume<R, F>(self, len: usize, f: F) -> R
  351. where
  352. F: FnOnce(&mut [u8]) -> R;
  353. /// The Packet ID to be associated with the frame to be transmitted by this [`TxToken`].
  354. #[allow(unused_variables)]
  355. fn set_meta(&mut self, meta: PacketMeta) {}
  356. }