mod.rs 46 KB

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