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
//! Access to networking hardware. //! //! The `phy` module deals with the *network devices*. It provides a trait //! for transmitting and receiving frames, [Device](trait.Device.html), //! as well as an implementations of that trait that uses the host OS, //! [RawSocket](struct.RawSocket.html) and [TapInterface](struct.TapInterface.html). //! //! It also provides the _middleware interfaces_ [Tracer](struct.Tracer.html) and //! [FaultInjector](struct.FaultInjector.html), to facilitate debugging. //! // https://github.com/rust-lang/rust/issues/38740 //! <h1 id="examples" class="section-header"><a href="#examples">Examples</a></h1> //! //! An implementation of the [Device](trait.Device.html) trait for a simple hardware //! Ethernet controller could look as follows: //! /*! ```rust use std::slice; use smoltcp::Error; use smoltcp::phy::Device; const TX_BUFFERS: [*mut u8; 2] = [0x10000000 as *mut u8, 0x10001000 as *mut u8]; const RX_BUFFERS: [*mut u8; 2] = [0x10002000 as *mut u8, 0x10003000 as *mut u8]; fn rx_full() -> bool { /* platform-specific code to check if an incoming packet has arrived */ false } fn rx_setup(buf: *mut u8, length: &mut usize) { /* platform-specific code to receive a packet into a buffer */ } fn tx_empty() -> bool { /* platform-specific code to check if the outgoing packet was sent */ false } fn tx_setup(buf: *const u8, length: usize) { /* platform-specific code to send a buffer with a packet */ } struct EthernetDevice { tx_next: usize, rx_next: usize } impl Device for EthernetDevice { type RxBuffer = &'static [u8]; type TxBuffer = EthernetTxBuffer; fn mtu(&self) -> usize { 1536 } fn receive(&mut self) -> Result<Self::RxBuffer, Error> { if rx_full() { let index = self.rx_next; self.rx_next = (self.rx_next + 1) % RX_BUFFERS.len(); let mut length = 0; rx_setup(RX_BUFFERS[self.rx_next], &mut length); Ok(unsafe { slice::from_raw_parts(RX_BUFFERS[index], length) }) } else { Err(Error::Exhausted) } } fn transmit(&mut self, length: usize) -> Result<Self::TxBuffer, Error> { if tx_empty() { let index = self.tx_next; self.tx_next = (self.tx_next + 1) % TX_BUFFERS.len(); Ok(EthernetTxBuffer(unsafe { slice::from_raw_parts_mut(TX_BUFFERS[index], length) })) } else { Err(Error::Exhausted) } } } struct EthernetTxBuffer(&'static mut [u8]); impl AsRef<[u8]> for EthernetTxBuffer { fn as_ref(&self) -> &[u8] { self.0 } } impl AsMut<[u8]> for EthernetTxBuffer { fn as_mut(&mut self) -> &mut [u8] { self.0 } } impl Drop for EthernetTxBuffer { fn drop(&mut self) { tx_setup(self.0.as_ptr(), self.0.len()) } } ``` */ use Error; #[cfg(feature = "use_std")] mod sys; mod tracer; mod fault_injector; #[cfg(feature = "use_std")] mod raw_socket; #[cfg(all(feature = "use_std", target_os = "linux"))] mod tap_interface; pub use self::tracer::Tracer; pub use self::fault_injector::FaultInjector; #[cfg(feature = "use_std")] pub use self::raw_socket::RawSocket; #[cfg(all(feature = "use_std", target_os = "linux"))] pub use self::tap_interface::TapInterface; /// An interface for sending and receiving raw network frames. /// /// It is expected that a `Device` implementation would allocate memory for both sending /// and receiving packets from memory pools; hence, the stack borrows the buffer for a packet /// that it is about to receive, as well for a packet that it is about to send, from the device. pub trait Device { type RxBuffer: AsRef<[u8]>; type TxBuffer: AsRef<[u8]> + AsMut<[u8]>; /// Get maximum transmission unit. /// /// The network device is unable to send or receive frames larger than the MTU. /// In practice, MTU will fall between 576 (for IPv4) or 1280 (for IPv6) and 9216 octets. fn mtu(&self) -> usize; /// Receive a frame. /// /// It is expected that a `receive` implementation, once a packet is written to memory /// through DMA, would gain ownership of the underlying buffer, provide it for parsing, /// and return it to the network device once it is dropped. fn receive(&mut self) -> Result<Self::RxBuffer, Error>; /// Transmit a frame. /// /// It is expected that a `transmit` implementation would gain ownership of a buffer with /// the requested length, provide it for emission, and schedule it to be read from /// memory by the network device once it is dropped. fn transmit(&mut self, length: usize) -> Result<Self::TxBuffer, Error>; }