mod.rs 12 KB

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