mod.rs 8.4 KB

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