mod.rs 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. // Heads up! Before working on this file you should read the parts
  2. // of RFC 1122 that discuss Ethernet, ARP and IP for any IPv4 work
  3. // and RFCs 8200 and 4861 for any IPv6 and NDISC work.
  4. #[cfg(test)]
  5. mod tests;
  6. #[cfg(feature = "medium-ethernet")]
  7. mod ethernet;
  8. #[cfg(feature = "medium-ieee802154")]
  9. mod ieee802154;
  10. #[cfg(feature = "proto-ipv4")]
  11. mod ipv4;
  12. #[cfg(feature = "proto-ipv6")]
  13. mod ipv6;
  14. #[cfg(feature = "proto-sixlowpan")]
  15. mod sixlowpan;
  16. #[cfg(feature = "multicast")]
  17. pub(crate) mod multicast;
  18. #[cfg(feature = "socket-tcp")]
  19. mod tcp;
  20. #[cfg(any(feature = "socket-udp", feature = "socket-dns"))]
  21. mod udp;
  22. use super::packet::*;
  23. use core::result::Result;
  24. use heapless::Vec;
  25. #[cfg(feature = "_proto-fragmentation")]
  26. use super::fragmentation::FragKey;
  27. #[cfg(any(feature = "proto-ipv4", feature = "proto-sixlowpan"))]
  28. use super::fragmentation::PacketAssemblerSet;
  29. use super::fragmentation::{Fragmenter, FragmentsBuffer};
  30. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  31. use super::neighbor::{Answer as NeighborAnswer, Cache as NeighborCache};
  32. use super::socket_set::SocketSet;
  33. use crate::config::{IFACE_MAX_ADDR_COUNT, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT};
  34. use crate::iface::Routes;
  35. use crate::phy::PacketMeta;
  36. use crate::phy::{ChecksumCapabilities, Device, DeviceCapabilities, Medium, RxToken, TxToken};
  37. use crate::rand::Rand;
  38. use crate::socket::*;
  39. use crate::time::{Duration, Instant};
  40. use crate::wire::*;
  41. macro_rules! check {
  42. ($e:expr) => {
  43. match $e {
  44. Ok(x) => x,
  45. Err(_) => {
  46. // concat!/stringify! doesn't work with defmt macros
  47. #[cfg(not(feature = "defmt"))]
  48. net_trace!(concat!("iface: malformed ", stringify!($e)));
  49. #[cfg(feature = "defmt")]
  50. net_trace!("iface: malformed");
  51. return Default::default();
  52. }
  53. }
  54. };
  55. }
  56. use check;
  57. /// Result returned by [`Interface::poll`].
  58. ///
  59. /// This contains information on whether socket states might have changed.
  60. #[derive(Copy, Clone, PartialEq, Eq, Debug)]
  61. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  62. pub enum PollResult {
  63. /// Socket state is guaranteed to not have changed.
  64. None,
  65. /// You should check the state of sockets again for received data or completion of operations.
  66. SocketStateChanged,
  67. }
  68. /// Result returned by [`Interface::poll_ingress_single`].
  69. ///
  70. /// This contains information on whether a packet was processed or not,
  71. /// and whether it might've affected socket states.
  72. #[derive(Copy, Clone, PartialEq, Eq, Debug)]
  73. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  74. pub enum PollIngressSingleResult {
  75. /// No packet was processed. You don't need to call [`Interface::poll_ingress_single`]
  76. /// again, until more packets arrive.
  77. ///
  78. /// Socket state is guaranteed to not have changed.
  79. None,
  80. /// A packet was processed.
  81. ///
  82. /// There may be more packets in the device's RX queue, so you should call [`Interface::poll_ingress_single`] again.
  83. ///
  84. /// Socket state is guaranteed to not have changed.
  85. PacketProcessed,
  86. /// A packet was processed, which might have caused socket state to change.
  87. ///
  88. /// There may be more packets in the device's RX queue, so you should call [`Interface::poll_ingress_single`] again.
  89. ///
  90. /// You should check the state of sockets again for received data or completion of operations.
  91. SocketStateChanged,
  92. }
  93. /// A network interface.
  94. ///
  95. /// The network interface logically owns a number of other data structures; to avoid
  96. /// a dependency on heap allocation, it instead owns a `BorrowMut<[T]>`, which can be
  97. /// a `&mut [T]`, or `Vec<T>` if a heap is available.
  98. pub struct Interface {
  99. pub(crate) inner: InterfaceInner,
  100. fragments: FragmentsBuffer,
  101. fragmenter: Fragmenter,
  102. }
  103. /// The device independent part of an Ethernet network interface.
  104. ///
  105. /// Separating the device from the data required for processing and dispatching makes
  106. /// it possible to borrow them independently. For example, the tx and rx tokens borrow
  107. /// the `device` mutably until they're used, which makes it impossible to call other
  108. /// methods on the `Interface` in this time (since its `device` field is borrowed
  109. /// exclusively). However, it is still possible to call methods on its `inner` field.
  110. pub struct InterfaceInner {
  111. caps: DeviceCapabilities,
  112. now: Instant,
  113. rand: Rand,
  114. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  115. neighbor_cache: NeighborCache,
  116. hardware_addr: HardwareAddress,
  117. #[cfg(feature = "medium-ieee802154")]
  118. sequence_no: u8,
  119. #[cfg(feature = "medium-ieee802154")]
  120. pan_id: Option<Ieee802154Pan>,
  121. #[cfg(feature = "proto-ipv4-fragmentation")]
  122. ipv4_id: u16,
  123. #[cfg(feature = "proto-sixlowpan")]
  124. sixlowpan_address_context:
  125. Vec<SixlowpanAddressContext, IFACE_MAX_SIXLOWPAN_ADDRESS_CONTEXT_COUNT>,
  126. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  127. tag: u16,
  128. ip_addrs: Vec<IpCidr, IFACE_MAX_ADDR_COUNT>,
  129. any_ip: bool,
  130. routes: Routes,
  131. #[cfg(feature = "multicast")]
  132. multicast: multicast::State,
  133. }
  134. /// Configuration structure used for creating a network interface.
  135. #[non_exhaustive]
  136. pub struct Config {
  137. /// Random seed.
  138. ///
  139. /// It is strongly recommended that the random seed is different on each boot,
  140. /// to avoid problems with TCP port/sequence collisions.
  141. ///
  142. /// The seed doesn't have to be cryptographically secure.
  143. pub random_seed: u64,
  144. /// Set the Hardware address the interface will use.
  145. ///
  146. /// # Panics
  147. /// Creating the interface panics if the address is not unicast.
  148. pub hardware_addr: HardwareAddress,
  149. /// Set the IEEE802.15.4 PAN ID the interface will use.
  150. ///
  151. /// **NOTE**: we use the same PAN ID for destination and source.
  152. #[cfg(feature = "medium-ieee802154")]
  153. pub pan_id: Option<Ieee802154Pan>,
  154. }
  155. impl Config {
  156. pub fn new(hardware_addr: HardwareAddress) -> Self {
  157. Config {
  158. random_seed: 0,
  159. hardware_addr,
  160. #[cfg(feature = "medium-ieee802154")]
  161. pan_id: None,
  162. }
  163. }
  164. }
  165. impl Interface {
  166. /// Create a network interface using the previously provided configuration.
  167. ///
  168. /// # Panics
  169. /// This function panics if the [`Config::hardware_address`] does not match
  170. /// the medium of the device.
  171. pub fn new(config: Config, device: &mut (impl Device + ?Sized), now: Instant) -> Self {
  172. let caps = device.capabilities();
  173. assert_eq!(
  174. config.hardware_addr.medium(),
  175. caps.medium,
  176. "The hardware address does not match the medium of the interface."
  177. );
  178. let mut rand = Rand::new(config.random_seed);
  179. #[cfg(feature = "medium-ieee802154")]
  180. let mut sequence_no;
  181. #[cfg(feature = "medium-ieee802154")]
  182. loop {
  183. sequence_no = (rand.rand_u32() & 0xff) as u8;
  184. if sequence_no != 0 {
  185. break;
  186. }
  187. }
  188. #[cfg(feature = "proto-sixlowpan")]
  189. let mut tag;
  190. #[cfg(feature = "proto-sixlowpan")]
  191. loop {
  192. tag = rand.rand_u16();
  193. if tag != 0 {
  194. break;
  195. }
  196. }
  197. #[cfg(feature = "proto-ipv4")]
  198. let mut ipv4_id;
  199. #[cfg(feature = "proto-ipv4")]
  200. loop {
  201. ipv4_id = rand.rand_u16();
  202. if ipv4_id != 0 {
  203. break;
  204. }
  205. }
  206. Interface {
  207. fragments: FragmentsBuffer {
  208. #[cfg(feature = "proto-sixlowpan")]
  209. decompress_buf: [0u8; sixlowpan::MAX_DECOMPRESSED_LEN],
  210. #[cfg(feature = "_proto-fragmentation")]
  211. assembler: PacketAssemblerSet::new(),
  212. #[cfg(feature = "_proto-fragmentation")]
  213. reassembly_timeout: Duration::from_secs(60),
  214. },
  215. fragmenter: Fragmenter::new(),
  216. inner: InterfaceInner {
  217. now,
  218. caps,
  219. hardware_addr: config.hardware_addr,
  220. ip_addrs: Vec::new(),
  221. any_ip: false,
  222. routes: Routes::new(),
  223. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  224. neighbor_cache: NeighborCache::new(),
  225. #[cfg(feature = "multicast")]
  226. multicast: multicast::State::new(),
  227. #[cfg(feature = "medium-ieee802154")]
  228. sequence_no,
  229. #[cfg(feature = "medium-ieee802154")]
  230. pan_id: config.pan_id,
  231. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  232. tag,
  233. #[cfg(feature = "proto-ipv4-fragmentation")]
  234. ipv4_id,
  235. #[cfg(feature = "proto-sixlowpan")]
  236. sixlowpan_address_context: Vec::new(),
  237. rand,
  238. },
  239. }
  240. }
  241. /// Get the socket context.
  242. ///
  243. /// The context is needed for some socket methods.
  244. pub fn context(&mut self) -> &mut InterfaceInner {
  245. &mut self.inner
  246. }
  247. /// Get the HardwareAddress address of the interface.
  248. ///
  249. /// # Panics
  250. /// This function panics if the medium is not Ethernet or Ieee802154.
  251. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  252. pub fn hardware_addr(&self) -> HardwareAddress {
  253. #[cfg(all(feature = "medium-ethernet", not(feature = "medium-ieee802154")))]
  254. assert!(self.inner.caps.medium == Medium::Ethernet);
  255. #[cfg(all(feature = "medium-ieee802154", not(feature = "medium-ethernet")))]
  256. assert!(self.inner.caps.medium == Medium::Ieee802154);
  257. #[cfg(all(feature = "medium-ieee802154", feature = "medium-ethernet"))]
  258. assert!(
  259. self.inner.caps.medium == Medium::Ethernet
  260. || self.inner.caps.medium == Medium::Ieee802154
  261. );
  262. self.inner.hardware_addr
  263. }
  264. /// Set the HardwareAddress address of the interface.
  265. ///
  266. /// # Panics
  267. /// This function panics if the address is not unicast, and if the medium is not Ethernet or
  268. /// Ieee802154.
  269. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  270. pub fn set_hardware_addr(&mut self, addr: HardwareAddress) {
  271. #[cfg(all(feature = "medium-ethernet", not(feature = "medium-ieee802154")))]
  272. assert!(self.inner.caps.medium == Medium::Ethernet);
  273. #[cfg(all(feature = "medium-ieee802154", not(feature = "medium-ethernet")))]
  274. assert!(self.inner.caps.medium == Medium::Ieee802154);
  275. #[cfg(all(feature = "medium-ieee802154", feature = "medium-ethernet"))]
  276. assert!(
  277. self.inner.caps.medium == Medium::Ethernet
  278. || self.inner.caps.medium == Medium::Ieee802154
  279. );
  280. InterfaceInner::check_hardware_addr(&addr);
  281. self.inner.hardware_addr = addr;
  282. }
  283. /// Get the IP addresses of the interface.
  284. pub fn ip_addrs(&self) -> &[IpCidr] {
  285. self.inner.ip_addrs.as_ref()
  286. }
  287. /// Get the first IPv4 address if present.
  288. #[cfg(feature = "proto-ipv4")]
  289. pub fn ipv4_addr(&self) -> Option<Ipv4Address> {
  290. self.inner.ipv4_addr()
  291. }
  292. /// Get the first IPv6 address if present.
  293. #[cfg(feature = "proto-ipv6")]
  294. pub fn ipv6_addr(&self) -> Option<Ipv6Address> {
  295. self.inner.ipv6_addr()
  296. }
  297. /// Get an address from the interface that could be used as source address. For IPv4, this is
  298. /// the first IPv4 address from the list of addresses. For IPv6, the address is based on the
  299. /// destination address and uses RFC6724 for selecting the source address.
  300. pub fn get_source_address(&self, dst_addr: &IpAddress) -> Option<IpAddress> {
  301. self.inner.get_source_address(dst_addr)
  302. }
  303. /// Get an address from the interface that could be used as source address. This is the first
  304. /// IPv4 address from the list of addresses in the interface.
  305. #[cfg(feature = "proto-ipv4")]
  306. pub fn get_source_address_ipv4(&self, dst_addr: &Ipv4Address) -> Option<Ipv4Address> {
  307. self.inner.get_source_address_ipv4(dst_addr)
  308. }
  309. /// Get an address from the interface that could be used as source address. The selection is
  310. /// based on RFC6724.
  311. #[cfg(feature = "proto-ipv6")]
  312. pub fn get_source_address_ipv6(&self, dst_addr: &Ipv6Address) -> Ipv6Address {
  313. self.inner.get_source_address_ipv6(dst_addr)
  314. }
  315. /// Update the IP addresses of the interface.
  316. ///
  317. /// # Panics
  318. /// This function panics if any of the addresses are not unicast.
  319. pub fn update_ip_addrs<F: FnOnce(&mut Vec<IpCidr, IFACE_MAX_ADDR_COUNT>)>(&mut self, f: F) {
  320. f(&mut self.inner.ip_addrs);
  321. InterfaceInner::flush_neighbor_cache(&mut self.inner);
  322. InterfaceInner::check_ip_addrs(&self.inner.ip_addrs)
  323. }
  324. /// Check whether the interface has the given IP address assigned.
  325. pub fn has_ip_addr<T: Into<IpAddress>>(&self, addr: T) -> bool {
  326. self.inner.has_ip_addr(addr)
  327. }
  328. pub fn routes(&self) -> &Routes {
  329. &self.inner.routes
  330. }
  331. pub fn routes_mut(&mut self) -> &mut Routes {
  332. &mut self.inner.routes
  333. }
  334. /// Enable or disable the AnyIP capability.
  335. ///
  336. /// AnyIP allowins packets to be received
  337. /// locally on IP addresses other than the interface's configured [ip_addrs].
  338. /// When AnyIP is enabled and a route prefix in [`routes`](Self::routes) specifies one of
  339. /// the interface's [`ip_addrs`](Self::ip_addrs) as its gateway, the interface will accept
  340. /// packets addressed to that prefix.
  341. pub fn set_any_ip(&mut self, any_ip: bool) {
  342. self.inner.any_ip = any_ip;
  343. }
  344. /// Get whether AnyIP is enabled.
  345. ///
  346. /// See [`set_any_ip`](Self::set_any_ip) for details on AnyIP
  347. pub fn any_ip(&self) -> bool {
  348. self.inner.any_ip
  349. }
  350. /// Get the packet reassembly timeout.
  351. #[cfg(feature = "_proto-fragmentation")]
  352. pub fn reassembly_timeout(&self) -> Duration {
  353. self.fragments.reassembly_timeout
  354. }
  355. /// Set the packet reassembly timeout.
  356. #[cfg(feature = "_proto-fragmentation")]
  357. pub fn set_reassembly_timeout(&mut self, timeout: Duration) {
  358. if timeout > Duration::from_secs(60) {
  359. net_debug!("RFC 4944 specifies that the reassembly timeout MUST be set to a maximum of 60 seconds");
  360. }
  361. self.fragments.reassembly_timeout = timeout;
  362. }
  363. /// Transmit packets queued in the sockets, and receive packets queued
  364. /// in the device.
  365. ///
  366. /// This function returns a value indicating whether the state of any socket
  367. /// might have changed.
  368. ///
  369. /// ## DoS warning
  370. ///
  371. /// This function processes all packets in the device's queue. This can
  372. /// be an unbounded amount of work if packets arrive faster than they're
  373. /// processed.
  374. ///
  375. /// If this is a concern for your application (i.e. your environment doesn't
  376. /// have preemptive scheduling, or `poll()` is called from a main loop where
  377. /// other important things are processed), you may use the lower-level methods
  378. /// [`poll_egress()`](Self::poll_egress) and [`poll_ingress_single()`](Self::poll_ingress_single).
  379. /// This allows you to insert yields or process other events between processing
  380. /// individual ingress packets.
  381. pub fn poll(
  382. &mut self,
  383. timestamp: Instant,
  384. device: &mut (impl Device + ?Sized),
  385. sockets: &mut SocketSet<'_>,
  386. ) -> PollResult {
  387. self.inner.now = timestamp;
  388. let mut res = PollResult::None;
  389. #[cfg(feature = "_proto-fragmentation")]
  390. self.fragments.assembler.remove_expired(timestamp);
  391. // Process ingress while there's packets available.
  392. loop {
  393. match self.socket_ingress(device, sockets) {
  394. PollIngressSingleResult::None => break,
  395. PollIngressSingleResult::PacketProcessed => {}
  396. PollIngressSingleResult::SocketStateChanged => res = PollResult::SocketStateChanged,
  397. }
  398. }
  399. // Process egress.
  400. match self.poll_egress(timestamp, device, sockets) {
  401. PollResult::None => {}
  402. PollResult::SocketStateChanged => res = PollResult::SocketStateChanged,
  403. }
  404. res
  405. }
  406. /// Transmit packets queued in the sockets.
  407. ///
  408. /// This function returns a value indicating whether the state of any socket
  409. /// might have changed.
  410. ///
  411. /// This is guaranteed to always perform a bounded amount of work.
  412. pub fn poll_egress(
  413. &mut self,
  414. timestamp: Instant,
  415. device: &mut (impl Device + ?Sized),
  416. sockets: &mut SocketSet<'_>,
  417. ) -> PollResult {
  418. self.inner.now = timestamp;
  419. match self.inner.caps.medium {
  420. #[cfg(feature = "medium-ieee802154")]
  421. Medium::Ieee802154 => {
  422. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  423. self.sixlowpan_egress(device);
  424. }
  425. #[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
  426. _ => {
  427. #[cfg(feature = "proto-ipv4-fragmentation")]
  428. self.ipv4_egress(device);
  429. }
  430. }
  431. #[cfg(feature = "multicast")]
  432. self.multicast_egress(device);
  433. self.socket_egress(device, sockets)
  434. }
  435. /// Process one incoming packet queued in the device.
  436. ///
  437. /// Returns a value indicating:
  438. /// - whether a packet was processed, in which case you have to call this method again in case there's more packets queued.
  439. /// - whether the state of any socket might have changed.
  440. ///
  441. /// Since it processes at most one packet, this is guaranteed to always perform a bounded amount of work.
  442. pub fn poll_ingress_single(
  443. &mut self,
  444. timestamp: Instant,
  445. device: &mut (impl Device + ?Sized),
  446. sockets: &mut SocketSet<'_>,
  447. ) -> PollIngressSingleResult {
  448. self.inner.now = timestamp;
  449. #[cfg(feature = "_proto-fragmentation")]
  450. self.fragments.assembler.remove_expired(timestamp);
  451. self.socket_ingress(device, sockets)
  452. }
  453. /// Return a _soft deadline_ for calling [poll] the next time.
  454. /// The [Instant] returned is the time at which you should call [poll] next.
  455. /// It is harmless (but wastes energy) to call it before the [Instant], and
  456. /// potentially harmful (impacting quality of service) to call it after the
  457. /// [Instant]
  458. ///
  459. /// [poll]: #method.poll
  460. /// [Instant]: struct.Instant.html
  461. pub fn poll_at(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Instant> {
  462. self.inner.now = timestamp;
  463. #[cfg(feature = "_proto-fragmentation")]
  464. if !self.fragmenter.is_empty() {
  465. return Some(Instant::from_millis(0));
  466. }
  467. let inner = &mut self.inner;
  468. sockets
  469. .items()
  470. .filter_map(move |item| {
  471. let socket_poll_at = item.socket.poll_at(inner);
  472. match item
  473. .meta
  474. .poll_at(socket_poll_at, |ip_addr| inner.has_neighbor(&ip_addr))
  475. {
  476. PollAt::Ingress => None,
  477. PollAt::Time(instant) => Some(instant),
  478. PollAt::Now => Some(Instant::from_millis(0)),
  479. }
  480. })
  481. .min()
  482. }
  483. /// Return an _advisory wait time_ for calling [poll] the next time.
  484. /// The [Duration] returned is the time left to wait before calling [poll] next.
  485. /// It is harmless (but wastes energy) to call it before the [Duration] has passed,
  486. /// and potentially harmful (impacting quality of service) to call it after the
  487. /// [Duration] has passed.
  488. ///
  489. /// [poll]: #method.poll
  490. /// [Duration]: struct.Duration.html
  491. pub fn poll_delay(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Duration> {
  492. match self.poll_at(timestamp, sockets) {
  493. Some(poll_at) if timestamp < poll_at => Some(poll_at - timestamp),
  494. Some(_) => Some(Duration::from_millis(0)),
  495. _ => None,
  496. }
  497. }
  498. fn socket_ingress(
  499. &mut self,
  500. device: &mut (impl Device + ?Sized),
  501. sockets: &mut SocketSet<'_>,
  502. ) -> PollIngressSingleResult {
  503. let Some((rx_token, tx_token)) = device.receive(self.inner.now) else {
  504. return PollIngressSingleResult::None;
  505. };
  506. let rx_meta = rx_token.meta();
  507. rx_token.consume(|frame| {
  508. if frame.is_empty() {
  509. return PollIngressSingleResult::PacketProcessed;
  510. }
  511. match self.inner.caps.medium {
  512. #[cfg(feature = "medium-ethernet")]
  513. Medium::Ethernet => {
  514. if let Some(packet) =
  515. self.inner
  516. .process_ethernet(sockets, rx_meta, frame, &mut self.fragments)
  517. {
  518. if let Err(err) =
  519. self.inner.dispatch(tx_token, packet, &mut self.fragmenter)
  520. {
  521. net_debug!("Failed to send response: {:?}", err);
  522. }
  523. }
  524. }
  525. #[cfg(feature = "medium-ip")]
  526. Medium::Ip => {
  527. if let Some(packet) =
  528. self.inner
  529. .process_ip(sockets, rx_meta, frame, &mut self.fragments)
  530. {
  531. if let Err(err) = self.inner.dispatch_ip(
  532. tx_token,
  533. PacketMeta::default(),
  534. packet,
  535. &mut self.fragmenter,
  536. ) {
  537. net_debug!("Failed to send response: {:?}", err);
  538. }
  539. }
  540. }
  541. #[cfg(feature = "medium-ieee802154")]
  542. Medium::Ieee802154 => {
  543. if let Some(packet) =
  544. self.inner
  545. .process_ieee802154(sockets, rx_meta, frame, &mut self.fragments)
  546. {
  547. if let Err(err) = self.inner.dispatch_ip(
  548. tx_token,
  549. PacketMeta::default(),
  550. packet,
  551. &mut self.fragmenter,
  552. ) {
  553. net_debug!("Failed to send response: {:?}", err);
  554. }
  555. }
  556. }
  557. }
  558. // TODO: Propagate the PollIngressSingleResult from deeper.
  559. // There's many received packets that we process but can't cause sockets
  560. // to change state. For example IP fragments, multicast stuff, ICMP pings
  561. // if they dont't match any raw socket...
  562. // We should return `PacketProcessed` for these to save the user from
  563. // doing useless socket polls.
  564. PollIngressSingleResult::SocketStateChanged
  565. })
  566. }
  567. fn socket_egress(
  568. &mut self,
  569. device: &mut (impl Device + ?Sized),
  570. sockets: &mut SocketSet<'_>,
  571. ) -> PollResult {
  572. let _caps = device.capabilities();
  573. enum EgressError {
  574. Exhausted,
  575. Dispatch,
  576. }
  577. let mut result = PollResult::None;
  578. for item in sockets.items_mut() {
  579. if !item
  580. .meta
  581. .egress_permitted(self.inner.now, |ip_addr| self.inner.has_neighbor(&ip_addr))
  582. {
  583. continue;
  584. }
  585. let mut neighbor_addr = None;
  586. let mut respond = |inner: &mut InterfaceInner, meta: PacketMeta, response: Packet| {
  587. neighbor_addr = Some(response.ip_repr().dst_addr());
  588. let t = device.transmit(inner.now).ok_or_else(|| {
  589. net_debug!("failed to transmit IP: device exhausted");
  590. EgressError::Exhausted
  591. })?;
  592. inner
  593. .dispatch_ip(t, meta, response, &mut self.fragmenter)
  594. .map_err(|_| EgressError::Dispatch)?;
  595. result = PollResult::SocketStateChanged;
  596. Ok(())
  597. };
  598. let result = match &mut item.socket {
  599. #[cfg(feature = "socket-raw")]
  600. Socket::Raw(socket) => socket.dispatch(&mut self.inner, |inner, (ip, raw)| {
  601. respond(
  602. inner,
  603. PacketMeta::default(),
  604. Packet::new(ip, IpPayload::Raw(raw)),
  605. )
  606. }),
  607. #[cfg(feature = "socket-icmp")]
  608. Socket::Icmp(socket) => {
  609. socket.dispatch(&mut self.inner, |inner, response| match response {
  610. #[cfg(feature = "proto-ipv4")]
  611. (IpRepr::Ipv4(ipv4_repr), IcmpRepr::Ipv4(icmpv4_repr)) => respond(
  612. inner,
  613. PacketMeta::default(),
  614. Packet::new_ipv4(ipv4_repr, IpPayload::Icmpv4(icmpv4_repr)),
  615. ),
  616. #[cfg(feature = "proto-ipv6")]
  617. (IpRepr::Ipv6(ipv6_repr), IcmpRepr::Ipv6(icmpv6_repr)) => respond(
  618. inner,
  619. PacketMeta::default(),
  620. Packet::new_ipv6(ipv6_repr, IpPayload::Icmpv6(icmpv6_repr)),
  621. ),
  622. #[allow(unreachable_patterns)]
  623. _ => unreachable!(),
  624. })
  625. }
  626. #[cfg(feature = "socket-udp")]
  627. Socket::Udp(socket) => {
  628. socket.dispatch(&mut self.inner, |inner, meta, (ip, udp, payload)| {
  629. respond(inner, meta, Packet::new(ip, IpPayload::Udp(udp, payload)))
  630. })
  631. }
  632. #[cfg(feature = "socket-tcp")]
  633. Socket::Tcp(socket) => socket.dispatch(&mut self.inner, |inner, (ip, tcp)| {
  634. respond(
  635. inner,
  636. PacketMeta::default(),
  637. Packet::new(ip, IpPayload::Tcp(tcp)),
  638. )
  639. }),
  640. #[cfg(feature = "socket-dhcpv4")]
  641. Socket::Dhcpv4(socket) => {
  642. socket.dispatch(&mut self.inner, |inner, (ip, udp, dhcp)| {
  643. respond(
  644. inner,
  645. PacketMeta::default(),
  646. Packet::new_ipv4(ip, IpPayload::Dhcpv4(udp, dhcp)),
  647. )
  648. })
  649. }
  650. #[cfg(feature = "socket-dns")]
  651. Socket::Dns(socket) => socket.dispatch(&mut self.inner, |inner, (ip, udp, dns)| {
  652. respond(
  653. inner,
  654. PacketMeta::default(),
  655. Packet::new(ip, IpPayload::Udp(udp, dns)),
  656. )
  657. }),
  658. };
  659. match result {
  660. Err(EgressError::Exhausted) => break, // Device buffer full.
  661. Err(EgressError::Dispatch) => {
  662. // `NeighborCache` already takes care of rate limiting the neighbor discovery
  663. // requests from the socket. However, without an additional rate limiting
  664. // mechanism, we would spin on every socket that has yet to discover its
  665. // neighbor.
  666. item.meta.neighbor_missing(
  667. self.inner.now,
  668. neighbor_addr.expect("non-IP response packet"),
  669. );
  670. }
  671. Ok(()) => {}
  672. }
  673. }
  674. result
  675. }
  676. }
  677. impl InterfaceInner {
  678. #[allow(unused)] // unused depending on which sockets are enabled
  679. pub(crate) fn now(&self) -> Instant {
  680. self.now
  681. }
  682. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  683. #[allow(unused)] // unused depending on which sockets are enabled
  684. pub(crate) fn hardware_addr(&self) -> HardwareAddress {
  685. self.hardware_addr
  686. }
  687. #[allow(unused)] // unused depending on which sockets are enabled
  688. pub(crate) fn checksum_caps(&self) -> ChecksumCapabilities {
  689. self.caps.checksum.clone()
  690. }
  691. #[allow(unused)] // unused depending on which sockets are enabled
  692. pub(crate) fn ip_mtu(&self) -> usize {
  693. self.caps.ip_mtu()
  694. }
  695. #[allow(unused)] // unused depending on which sockets are enabled, and in tests
  696. pub(crate) fn rand(&mut self) -> &mut Rand {
  697. &mut self.rand
  698. }
  699. #[allow(unused)] // unused depending on which sockets are enabled
  700. pub(crate) fn get_source_address(&self, dst_addr: &IpAddress) -> Option<IpAddress> {
  701. match dst_addr {
  702. #[cfg(feature = "proto-ipv4")]
  703. IpAddress::Ipv4(addr) => self.get_source_address_ipv4(addr).map(|a| a.into()),
  704. #[cfg(feature = "proto-ipv6")]
  705. IpAddress::Ipv6(addr) => Some(self.get_source_address_ipv6(addr).into()),
  706. }
  707. }
  708. #[cfg(test)]
  709. #[allow(unused)] // unused depending on which sockets are enabled
  710. pub(crate) fn set_now(&mut self, now: Instant) {
  711. self.now = now
  712. }
  713. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  714. fn check_hardware_addr(addr: &HardwareAddress) {
  715. if !addr.is_unicast() {
  716. panic!("Hardware address {addr} is not unicast")
  717. }
  718. }
  719. fn check_ip_addrs(addrs: &[IpCidr]) {
  720. for cidr in addrs {
  721. if !cidr.address().is_unicast() && !cidr.address().is_unspecified() {
  722. panic!("IP address {} is not unicast", cidr.address())
  723. }
  724. }
  725. }
  726. /// Check whether the interface has the given IP address assigned.
  727. fn has_ip_addr<T: Into<IpAddress>>(&self, addr: T) -> bool {
  728. let addr = addr.into();
  729. self.ip_addrs.iter().any(|probe| probe.address() == addr)
  730. }
  731. /// Check whether the interface listens to given destination multicast IP address.
  732. fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
  733. let addr = addr.into();
  734. #[cfg(feature = "multicast")]
  735. if self.multicast.has_multicast_group(addr) {
  736. return true;
  737. }
  738. match addr {
  739. #[cfg(feature = "proto-ipv4")]
  740. IpAddress::Ipv4(key) => key == Ipv4Address::MULTICAST_ALL_SYSTEMS,
  741. #[cfg(feature = "proto-rpl")]
  742. IpAddress::Ipv6(Ipv6Address::LINK_LOCAL_ALL_RPL_NODES) => true,
  743. #[cfg(feature = "proto-ipv6")]
  744. IpAddress::Ipv6(key) => {
  745. key == Ipv6Address::LINK_LOCAL_ALL_NODES || self.has_solicited_node(key)
  746. }
  747. #[allow(unreachable_patterns)]
  748. _ => false,
  749. }
  750. }
  751. #[cfg(feature = "medium-ip")]
  752. fn process_ip<'frame>(
  753. &mut self,
  754. sockets: &mut SocketSet,
  755. meta: PacketMeta,
  756. ip_payload: &'frame [u8],
  757. frag: &'frame mut FragmentsBuffer,
  758. ) -> Option<Packet<'frame>> {
  759. match IpVersion::of_packet(ip_payload) {
  760. #[cfg(feature = "proto-ipv4")]
  761. Ok(IpVersion::Ipv4) => {
  762. let ipv4_packet = check!(Ipv4Packet::new_checked(ip_payload));
  763. self.process_ipv4(sockets, meta, HardwareAddress::Ip, &ipv4_packet, frag)
  764. }
  765. #[cfg(feature = "proto-ipv6")]
  766. Ok(IpVersion::Ipv6) => {
  767. let ipv6_packet = check!(Ipv6Packet::new_checked(ip_payload));
  768. self.process_ipv6(sockets, meta, HardwareAddress::Ip, &ipv6_packet)
  769. }
  770. // Drop all other traffic.
  771. _ => None,
  772. }
  773. }
  774. #[cfg(feature = "socket-raw")]
  775. fn raw_socket_filter(
  776. &mut self,
  777. sockets: &mut SocketSet,
  778. ip_repr: &IpRepr,
  779. ip_payload: &[u8],
  780. ) -> bool {
  781. let mut handled_by_raw_socket = false;
  782. // Pass every IP packet to all raw sockets we have registered.
  783. for raw_socket in sockets
  784. .items_mut()
  785. .filter_map(|i| raw::Socket::downcast_mut(&mut i.socket))
  786. {
  787. if raw_socket.accepts(ip_repr) {
  788. raw_socket.process(self, ip_repr, ip_payload);
  789. handled_by_raw_socket = true;
  790. }
  791. }
  792. handled_by_raw_socket
  793. }
  794. /// Checks if an address is broadcast, taking into account ipv4 subnet-local
  795. /// broadcast addresses.
  796. pub(crate) fn is_broadcast(&self, address: &IpAddress) -> bool {
  797. match address {
  798. #[cfg(feature = "proto-ipv4")]
  799. IpAddress::Ipv4(address) => self.is_broadcast_v4(*address),
  800. #[cfg(feature = "proto-ipv6")]
  801. IpAddress::Ipv6(_) => false,
  802. }
  803. }
  804. #[cfg(feature = "medium-ethernet")]
  805. fn dispatch<Tx>(
  806. &mut self,
  807. tx_token: Tx,
  808. packet: EthernetPacket,
  809. frag: &mut Fragmenter,
  810. ) -> Result<(), DispatchError>
  811. where
  812. Tx: TxToken,
  813. {
  814. match packet {
  815. #[cfg(feature = "proto-ipv4")]
  816. EthernetPacket::Arp(arp_repr) => {
  817. let dst_hardware_addr = match arp_repr {
  818. ArpRepr::EthernetIpv4 {
  819. target_hardware_addr,
  820. ..
  821. } => target_hardware_addr,
  822. };
  823. self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
  824. frame.set_dst_addr(dst_hardware_addr);
  825. frame.set_ethertype(EthernetProtocol::Arp);
  826. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  827. arp_repr.emit(&mut packet);
  828. })
  829. }
  830. EthernetPacket::Ip(packet) => {
  831. self.dispatch_ip(tx_token, PacketMeta::default(), packet, frag)
  832. }
  833. }
  834. }
  835. fn in_same_network(&self, addr: &IpAddress) -> bool {
  836. self.ip_addrs.iter().any(|cidr| cidr.contains_addr(addr))
  837. }
  838. fn route(&self, addr: &IpAddress, timestamp: Instant) -> Option<IpAddress> {
  839. // Send directly.
  840. // note: no need to use `self.is_broadcast()` to check for subnet-local broadcast addrs
  841. // here because `in_same_network` will already return true.
  842. if self.in_same_network(addr) || addr.is_broadcast() {
  843. return Some(*addr);
  844. }
  845. // Route via a router.
  846. self.routes.lookup(addr, timestamp)
  847. }
  848. fn has_neighbor(&self, addr: &IpAddress) -> bool {
  849. match self.route(addr, self.now) {
  850. Some(_routed_addr) => match self.caps.medium {
  851. #[cfg(feature = "medium-ethernet")]
  852. Medium::Ethernet => self.neighbor_cache.lookup(&_routed_addr, self.now).found(),
  853. #[cfg(feature = "medium-ieee802154")]
  854. Medium::Ieee802154 => self.neighbor_cache.lookup(&_routed_addr, self.now).found(),
  855. #[cfg(feature = "medium-ip")]
  856. Medium::Ip => true,
  857. },
  858. None => false,
  859. }
  860. }
  861. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  862. fn lookup_hardware_addr<Tx>(
  863. &mut self,
  864. tx_token: Tx,
  865. dst_addr: &IpAddress,
  866. fragmenter: &mut Fragmenter,
  867. ) -> Result<(HardwareAddress, Tx), DispatchError>
  868. where
  869. Tx: TxToken,
  870. {
  871. if self.is_broadcast(dst_addr) {
  872. let hardware_addr = match self.caps.medium {
  873. #[cfg(feature = "medium-ethernet")]
  874. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::BROADCAST),
  875. #[cfg(feature = "medium-ieee802154")]
  876. Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::BROADCAST),
  877. #[cfg(feature = "medium-ip")]
  878. Medium::Ip => unreachable!(),
  879. };
  880. return Ok((hardware_addr, tx_token));
  881. }
  882. if dst_addr.is_multicast() {
  883. let b = dst_addr.as_bytes();
  884. let hardware_addr = match *dst_addr {
  885. #[cfg(feature = "proto-ipv4")]
  886. IpAddress::Ipv4(_addr) => match self.caps.medium {
  887. #[cfg(feature = "medium-ethernet")]
  888. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  889. 0x01,
  890. 0x00,
  891. 0x5e,
  892. b[1] & 0x7F,
  893. b[2],
  894. b[3],
  895. ])),
  896. #[cfg(feature = "medium-ieee802154")]
  897. Medium::Ieee802154 => unreachable!(),
  898. #[cfg(feature = "medium-ip")]
  899. Medium::Ip => unreachable!(),
  900. },
  901. #[cfg(feature = "proto-ipv6")]
  902. IpAddress::Ipv6(_addr) => match self.caps.medium {
  903. #[cfg(feature = "medium-ethernet")]
  904. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  905. 0x33, 0x33, b[12], b[13], b[14], b[15],
  906. ])),
  907. #[cfg(feature = "medium-ieee802154")]
  908. Medium::Ieee802154 => {
  909. // Not sure if this is correct
  910. HardwareAddress::Ieee802154(Ieee802154Address::BROADCAST)
  911. }
  912. #[cfg(feature = "medium-ip")]
  913. Medium::Ip => unreachable!(),
  914. },
  915. };
  916. return Ok((hardware_addr, tx_token));
  917. }
  918. let dst_addr = self
  919. .route(dst_addr, self.now)
  920. .ok_or(DispatchError::NoRoute)?;
  921. match self.neighbor_cache.lookup(&dst_addr, self.now) {
  922. NeighborAnswer::Found(hardware_addr) => return Ok((hardware_addr, tx_token)),
  923. NeighborAnswer::RateLimited => return Err(DispatchError::NeighborPending),
  924. _ => (), // XXX
  925. }
  926. match dst_addr {
  927. #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
  928. IpAddress::Ipv4(dst_addr) if matches!(self.caps.medium, Medium::Ethernet) => {
  929. net_debug!(
  930. "address {} not in neighbor cache, sending ARP request",
  931. dst_addr
  932. );
  933. let src_hardware_addr = self.hardware_addr.ethernet_or_panic();
  934. let arp_repr = ArpRepr::EthernetIpv4 {
  935. operation: ArpOperation::Request,
  936. source_hardware_addr: src_hardware_addr,
  937. source_protocol_addr: self
  938. .get_source_address_ipv4(&dst_addr)
  939. .ok_or(DispatchError::NoRoute)?,
  940. target_hardware_addr: EthernetAddress::BROADCAST,
  941. target_protocol_addr: dst_addr,
  942. };
  943. if let Err(e) =
  944. self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
  945. frame.set_dst_addr(EthernetAddress::BROADCAST);
  946. frame.set_ethertype(EthernetProtocol::Arp);
  947. arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
  948. })
  949. {
  950. net_debug!("Failed to dispatch ARP request: {:?}", e);
  951. return Err(DispatchError::NeighborPending);
  952. }
  953. }
  954. #[cfg(feature = "proto-ipv6")]
  955. IpAddress::Ipv6(dst_addr) => {
  956. net_debug!(
  957. "address {} not in neighbor cache, sending Neighbor Solicitation",
  958. dst_addr
  959. );
  960. let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit {
  961. target_addr: dst_addr,
  962. lladdr: Some(self.hardware_addr.into()),
  963. });
  964. let packet = Packet::new_ipv6(
  965. Ipv6Repr {
  966. src_addr: self.get_source_address_ipv6(&dst_addr),
  967. dst_addr: dst_addr.solicited_node(),
  968. next_header: IpProtocol::Icmpv6,
  969. payload_len: solicit.buffer_len(),
  970. hop_limit: 0xff,
  971. },
  972. IpPayload::Icmpv6(solicit),
  973. );
  974. if let Err(e) =
  975. self.dispatch_ip(tx_token, PacketMeta::default(), packet, fragmenter)
  976. {
  977. net_debug!("Failed to dispatch NDISC solicit: {:?}", e);
  978. return Err(DispatchError::NeighborPending);
  979. }
  980. }
  981. #[allow(unreachable_patterns)]
  982. _ => (),
  983. }
  984. // The request got dispatched, limit the rate on the cache.
  985. self.neighbor_cache.limit_rate(self.now);
  986. Err(DispatchError::NeighborPending)
  987. }
  988. fn flush_neighbor_cache(&mut self) {
  989. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  990. self.neighbor_cache.flush()
  991. }
  992. fn dispatch_ip<Tx: TxToken>(
  993. &mut self,
  994. // NOTE(unused_mut): tx_token isn't always mutated, depending on
  995. // the feature set that is used.
  996. #[allow(unused_mut)] mut tx_token: Tx,
  997. meta: PacketMeta,
  998. packet: Packet,
  999. frag: &mut Fragmenter,
  1000. ) -> Result<(), DispatchError> {
  1001. let mut ip_repr = packet.ip_repr();
  1002. assert!(!ip_repr.dst_addr().is_unspecified());
  1003. // Dispatch IEEE802.15.4:
  1004. #[cfg(feature = "medium-ieee802154")]
  1005. if matches!(self.caps.medium, Medium::Ieee802154) {
  1006. let (addr, tx_token) =
  1007. self.lookup_hardware_addr(tx_token, &ip_repr.dst_addr(), frag)?;
  1008. let addr = addr.ieee802154_or_panic();
  1009. self.dispatch_ieee802154(addr, tx_token, meta, packet, frag);
  1010. return Ok(());
  1011. }
  1012. // Dispatch IP/Ethernet:
  1013. let caps = self.caps.clone();
  1014. #[cfg(feature = "proto-ipv4-fragmentation")]
  1015. let ipv4_id = self.next_ipv4_frag_ident();
  1016. // First we calculate the total length that we will have to emit.
  1017. let mut total_len = ip_repr.buffer_len();
  1018. // Add the size of the Ethernet header if the medium is Ethernet.
  1019. #[cfg(feature = "medium-ethernet")]
  1020. if matches!(self.caps.medium, Medium::Ethernet) {
  1021. total_len = EthernetFrame::<&[u8]>::buffer_len(total_len);
  1022. }
  1023. // If the medium is Ethernet, then we need to retrieve the destination hardware address.
  1024. #[cfg(feature = "medium-ethernet")]
  1025. let (dst_hardware_addr, mut tx_token) = match self.caps.medium {
  1026. Medium::Ethernet => {
  1027. match self.lookup_hardware_addr(tx_token, &ip_repr.dst_addr(), frag)? {
  1028. (HardwareAddress::Ethernet(addr), tx_token) => (addr, tx_token),
  1029. (_, _) => unreachable!(),
  1030. }
  1031. }
  1032. _ => (EthernetAddress([0; 6]), tx_token),
  1033. };
  1034. // Emit function for the Ethernet header.
  1035. #[cfg(feature = "medium-ethernet")]
  1036. let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| {
  1037. let mut frame = EthernetFrame::new_unchecked(tx_buffer);
  1038. let src_addr = self.hardware_addr.ethernet_or_panic();
  1039. frame.set_src_addr(src_addr);
  1040. frame.set_dst_addr(dst_hardware_addr);
  1041. match repr.version() {
  1042. #[cfg(feature = "proto-ipv4")]
  1043. IpVersion::Ipv4 => frame.set_ethertype(EthernetProtocol::Ipv4),
  1044. #[cfg(feature = "proto-ipv6")]
  1045. IpVersion::Ipv6 => frame.set_ethertype(EthernetProtocol::Ipv6),
  1046. }
  1047. Ok(())
  1048. };
  1049. // Emit function for the IP header and payload.
  1050. let emit_ip = |repr: &IpRepr, tx_buffer: &mut [u8]| {
  1051. repr.emit(&mut *tx_buffer, &self.caps.checksum);
  1052. let payload = &mut tx_buffer[repr.header_len()..];
  1053. packet.emit_payload(repr, payload, &caps)
  1054. };
  1055. let total_ip_len = ip_repr.buffer_len();
  1056. match &mut ip_repr {
  1057. #[cfg(feature = "proto-ipv4")]
  1058. IpRepr::Ipv4(repr) => {
  1059. // If we have an IPv4 packet, then we need to check if we need to fragment it.
  1060. if total_ip_len > self.caps.max_transmission_unit {
  1061. #[cfg(feature = "proto-ipv4-fragmentation")]
  1062. {
  1063. net_debug!("start fragmentation");
  1064. // Calculate how much we will send now (including the Ethernet header).
  1065. let tx_len = self.caps.max_transmission_unit;
  1066. let ip_header_len = repr.buffer_len();
  1067. let first_frag_ip_len = self.caps.ip_mtu();
  1068. if frag.buffer.len() < total_ip_len {
  1069. net_debug!(
  1070. "Fragmentation buffer is too small, at least {} needed. Dropping",
  1071. total_ip_len
  1072. );
  1073. return Ok(());
  1074. }
  1075. #[cfg(feature = "medium-ethernet")]
  1076. {
  1077. frag.ipv4.dst_hardware_addr = dst_hardware_addr;
  1078. }
  1079. // Save the total packet len (without the Ethernet header, but with the first
  1080. // IP header).
  1081. frag.packet_len = total_ip_len;
  1082. // Save the IP header for other fragments.
  1083. frag.ipv4.repr = *repr;
  1084. // Save how much bytes we will send now.
  1085. frag.sent_bytes = first_frag_ip_len;
  1086. // Modify the IP header
  1087. repr.payload_len = first_frag_ip_len - repr.buffer_len();
  1088. // Emit the IP header to the buffer.
  1089. emit_ip(&ip_repr, &mut frag.buffer);
  1090. let mut ipv4_packet = Ipv4Packet::new_unchecked(&mut frag.buffer[..]);
  1091. frag.ipv4.ident = ipv4_id;
  1092. ipv4_packet.set_ident(ipv4_id);
  1093. ipv4_packet.set_more_frags(true);
  1094. ipv4_packet.set_dont_frag(false);
  1095. ipv4_packet.set_frag_offset(0);
  1096. if caps.checksum.ipv4.tx() {
  1097. ipv4_packet.fill_checksum();
  1098. }
  1099. // Transmit the first packet.
  1100. tx_token.consume(tx_len, |mut tx_buffer| {
  1101. #[cfg(feature = "medium-ethernet")]
  1102. if matches!(self.caps.medium, Medium::Ethernet) {
  1103. emit_ethernet(&ip_repr, tx_buffer)?;
  1104. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1105. }
  1106. // Change the offset for the next packet.
  1107. frag.ipv4.frag_offset = (first_frag_ip_len - ip_header_len) as u16;
  1108. // Copy the IP header and the payload.
  1109. tx_buffer[..first_frag_ip_len]
  1110. .copy_from_slice(&frag.buffer[..first_frag_ip_len]);
  1111. Ok(())
  1112. })
  1113. }
  1114. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  1115. {
  1116. net_debug!("Enable the `proto-ipv4-fragmentation` feature for fragmentation support.");
  1117. Ok(())
  1118. }
  1119. } else {
  1120. tx_token.set_meta(meta);
  1121. // No fragmentation is required.
  1122. tx_token.consume(total_len, |mut tx_buffer| {
  1123. #[cfg(feature = "medium-ethernet")]
  1124. if matches!(self.caps.medium, Medium::Ethernet) {
  1125. emit_ethernet(&ip_repr, tx_buffer)?;
  1126. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1127. }
  1128. emit_ip(&ip_repr, tx_buffer);
  1129. Ok(())
  1130. })
  1131. }
  1132. }
  1133. // We don't support IPv6 fragmentation yet.
  1134. #[cfg(feature = "proto-ipv6")]
  1135. IpRepr::Ipv6(_) => tx_token.consume(total_len, |mut tx_buffer| {
  1136. #[cfg(feature = "medium-ethernet")]
  1137. if matches!(self.caps.medium, Medium::Ethernet) {
  1138. emit_ethernet(&ip_repr, tx_buffer)?;
  1139. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1140. }
  1141. emit_ip(&ip_repr, tx_buffer);
  1142. Ok(())
  1143. }),
  1144. }
  1145. }
  1146. }
  1147. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  1148. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  1149. enum DispatchError {
  1150. /// No route to dispatch this packet. Retrying won't help unless
  1151. /// configuration is changed.
  1152. NoRoute,
  1153. /// We do have a route to dispatch this packet, but we haven't discovered
  1154. /// the neighbor for it yet. Discovery has been initiated, dispatch
  1155. /// should be retried later.
  1156. NeighborPending,
  1157. }