mod.rs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //! Access to networking hardware.
  2. //!
  3. //! The `phy` module deals with the *network devices*. It provides a trait
  4. //! for transmitting and receiving frames, [Device](trait.Device.html)
  5. //! and implementations of it:
  6. //!
  7. //! * the [_loopback_](struct.Loopback.html), for zero dependency testing;
  8. //! * _middleware_ [Tracer](struct.Tracer.html) and
  9. //! [FaultInjector](struct.FaultInjector.html), to facilitate debugging;
  10. //! * _adapters_ [RawSocket](struct.RawSocket.html) and
  11. //! [TapInterface](struct.TapInterface.html), to transmit and receive frames
  12. //! on the host OS.
  13. //!
  14. // https://github.com/rust-lang/rust/issues/38740
  15. //! <h1 id="examples" class="section-header"><a href="#examples">Examples</a></h1>
  16. //!
  17. //! An implementation of the [Device](trait.Device.html) trait for a simple hardware
  18. //! Ethernet controller could look as follows:
  19. //!
  20. /*!
  21. ```rust
  22. use smoltcp::Result;
  23. use smoltcp::phy::{self, DeviceCapabilities, Device};
  24. struct StmPhy {
  25. rx_buffer: [u8; 1536],
  26. tx_buffer: [u8; 1536],
  27. }
  28. impl<'a> StmPhy {
  29. fn new() -> StmPhy {
  30. StmPhy {
  31. rx_buffer: [0; 1536],
  32. tx_buffer: [0; 1536],
  33. }
  34. }
  35. }
  36. impl<'a> phy::Device<'a> for StmPhy {
  37. type RxToken = StmPhyRxToken<'a>;
  38. type TxToken = StmPhyTxToken<'a>;
  39. fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
  40. Some((StmPhyRxToken(&mut self.rx_buffer[..]),
  41. StmPhyTxToken(&mut self.tx_buffer[..])))
  42. }
  43. fn transmit(&'a mut self) -> Option<Self::TxToken> {
  44. Some(StmPhyTxToken(&mut self.tx_buffer[..]))
  45. }
  46. fn capabilities(&self) -> DeviceCapabilities {
  47. let mut caps = DeviceCapabilities::default();
  48. caps.max_transmission_unit = 1536;
  49. caps.max_burst_size = Some(1);
  50. caps
  51. }
  52. }
  53. struct StmPhyRxToken<'a>(&'a [u8]);
  54. impl<'a> phy::RxToken for StmPhyRxToken<'a> {
  55. fn consume<R, F>(self, _timestamp: u64, f: F) -> Result<R>
  56. where F: FnOnce(&[u8]) -> Result<R>
  57. {
  58. // TODO: receive packet into buffer
  59. let result = f(self.0);
  60. println!("rx called");
  61. result
  62. }
  63. }
  64. struct StmPhyTxToken<'a>(&'a mut [u8]);
  65. impl<'a> phy::TxToken for StmPhyTxToken<'a> {
  66. fn consume<R, F>(self, _timestamp: u64, len: usize, f: F) -> Result<R>
  67. where F: FnOnce(&mut [u8]) -> Result<R>
  68. {
  69. let result = f(&mut self.0[..len]);
  70. println!("tx called {}", len);
  71. // TODO: send packet out
  72. result
  73. }
  74. }
  75. ```
  76. */
  77. use Result;
  78. #[cfg(any(feature = "phy-raw_socket", feature = "phy-tap_interface"))]
  79. mod sys;
  80. mod tracer;
  81. mod fault_injector;
  82. mod pcap_writer;
  83. #[cfg(any(feature = "std", feature = "alloc"))]
  84. mod loopback;
  85. #[cfg(feature = "phy-raw_socket")]
  86. mod raw_socket;
  87. #[cfg(all(feature = "phy-tap_interface", target_os = "linux"))]
  88. mod tap_interface;
  89. #[cfg(any(feature = "phy-raw_socket", feature = "phy-tap_interface"))]
  90. pub use self::sys::wait;
  91. pub use self::tracer::Tracer;
  92. pub use self::fault_injector::FaultInjector;
  93. pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter};
  94. #[cfg(any(feature = "std", feature = "alloc"))]
  95. pub use self::loopback::Loopback;
  96. #[cfg(any(feature = "phy-raw_socket"))]
  97. pub use self::raw_socket::RawSocket;
  98. #[cfg(all(feature = "phy-tap_interface", target_os = "linux"))]
  99. pub use self::tap_interface::TapInterface;
  100. /// A tracer device for Ethernet frames.
  101. pub type EthernetTracer<T> = Tracer<T, super::wire::EthernetFrame<&'static [u8]>>;
  102. /// A description of checksum behavior for a particular protocol.
  103. #[derive(Debug, Clone, Copy)]
  104. pub enum Checksum {
  105. /// Verify checksum when receiving and compute checksum when sending.
  106. Both,
  107. /// Verify checksum when receiving.
  108. Rx,
  109. /// Compute checksum before sending.
  110. Tx,
  111. /// Ignore checksum completely.
  112. None,
  113. }
  114. impl Default for Checksum {
  115. fn default() -> Checksum {
  116. Checksum::Both
  117. }
  118. }
  119. impl Checksum {
  120. /// Returns whether checksum should be verified when receiving.
  121. pub fn rx(&self) -> bool {
  122. match *self {
  123. Checksum::Both | Checksum::Rx => true,
  124. _ => false
  125. }
  126. }
  127. /// Returns whether checksum should be verified when sending.
  128. pub fn tx(&self) -> bool {
  129. match *self {
  130. Checksum::Both | Checksum::Tx => true,
  131. _ => false
  132. }
  133. }
  134. }
  135. /// A description of checksum behavior for every supported protocol.
  136. #[derive(Debug, Clone, Default)]
  137. pub struct ChecksumCapabilities {
  138. pub ipv4: Checksum,
  139. pub udpv4: Checksum,
  140. pub tcpv4: Checksum,
  141. pub icmpv4: Checksum,
  142. dummy: (),
  143. }
  144. impl ChecksumCapabilities {
  145. /// Checksum behavior that results in not computing or verifying checksums
  146. /// for any of the supported protocols.
  147. pub fn ignored() -> Self {
  148. ChecksumCapabilities {
  149. ipv4: Checksum::None,
  150. udpv4: Checksum::None,
  151. tcpv4: Checksum::None,
  152. icmpv4: Checksum::None,
  153. ..Self::default()
  154. }
  155. }
  156. }
  157. /// A description of device capabilities.
  158. ///
  159. /// Higher-level protocols may achieve higher throughput or lower latency if they consider
  160. /// the bandwidth or packet size limitations.
  161. #[derive(Debug, Clone, Default)]
  162. pub struct DeviceCapabilities {
  163. /// Maximum transmission unit.
  164. ///
  165. /// The network device is unable to send or receive frames larger than the value returned
  166. /// by this function.
  167. ///
  168. /// For Ethernet, MTU will fall between 576 (for IPv4) or 1280 (for IPv6) and 9216 octets.
  169. pub max_transmission_unit: usize,
  170. /// Maximum burst size, in terms of MTU.
  171. ///
  172. /// The network device is unable to send or receive bursts large than the value returned
  173. /// by this function.
  174. ///
  175. /// If `None`, there is no fixed limit on burst size, e.g. if network buffers are
  176. /// dynamically allocated.
  177. pub max_burst_size: Option<usize>,
  178. /// The set of protocols for which checksum can be computed in hardware.
  179. pub checksum: ChecksumCapabilities,
  180. /// Only present to prevent people from trying to initialize every field of DeviceLimits,
  181. /// which would not let us add new fields in the future.
  182. dummy: ()
  183. }
  184. /// An interface for sending and receiving raw network frames.
  185. ///
  186. /// The interface is based on _tokens_, which are types that allow to receive/transmit a
  187. /// single packet. The `receive` and `transmit` functions only construct such tokens, the
  188. /// real sending/receiving operation are performed when the tokens are consumed.
  189. pub trait Device<'a> {
  190. type RxToken: RxToken + 'a;
  191. type TxToken: TxToken + 'a;
  192. /// Construct a token pair consisting of one receive token and one transmit token.
  193. ///
  194. /// The additional transmit token makes it possible to generate a reply packet based
  195. /// on the contents of the received packet. For example, this makes it possible to
  196. /// handle arbitrarily large ICMP echo ("ping") requests, where the all received bytes
  197. /// need to be sent back, without heap allocation.
  198. fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)>;
  199. /// Construct a transmit token.
  200. fn transmit(&'a mut self) -> Option<Self::TxToken>;
  201. /// Get a description of device capabilities.
  202. fn capabilities(&self) -> DeviceCapabilities;
  203. }
  204. /// A token to receive a single network packet.
  205. pub trait RxToken {
  206. /// Consumes the token to receive a single network packet.
  207. ///
  208. /// This method receives a packet and then calls the given closure `f` with the raw
  209. /// packet bytes as argument.
  210. ///
  211. /// The timestamp must be a number of milliseconds, monotonically increasing since an
  212. /// arbitrary moment in time, such as system startup.
  213. fn consume<R, F>(self, timestamp: u64, f: F) -> Result<R>
  214. where F: FnOnce(&[u8]) -> Result<R>;
  215. }
  216. /// A token to transmit a single network packet.
  217. pub trait TxToken {
  218. /// Consumes the token to send a single network packet.
  219. ///
  220. /// This method constructs a transmit buffer of size `len` and calls the passed
  221. /// closure `f` with a mutable reference to that buffer. The closure should construct
  222. /// a valid network packet (e.g. an ethernet packet) in the buffer. When the closure
  223. /// returns, the transmit buffer is sent out.
  224. ///
  225. /// The timestamp must be a number of milliseconds, monotonically increasing since an
  226. /// arbitrary moment in time, such as system startup.
  227. fn consume<R, F>(self, timestamp: u64, len: usize, f: F) -> Result<R>
  228. where F: FnOnce(&mut [u8]) -> Result<R>;
  229. }