mod.rs 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  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. pub fn poll<D>(
  351. &mut self,
  352. timestamp: Instant,
  353. device: &mut D,
  354. sockets: &mut SocketSet<'_>,
  355. ) -> bool
  356. where
  357. D: Device + ?Sized,
  358. {
  359. self.inner.now = timestamp;
  360. #[cfg(feature = "_proto-fragmentation")]
  361. self.fragments.assembler.remove_expired(timestamp);
  362. match self.inner.caps.medium {
  363. #[cfg(feature = "medium-ieee802154")]
  364. Medium::Ieee802154 =>
  365. {
  366. #[cfg(feature = "proto-sixlowpan-fragmentation")]
  367. if self.sixlowpan_egress(device) {
  368. return true;
  369. }
  370. }
  371. #[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))]
  372. _ =>
  373. {
  374. #[cfg(feature = "proto-ipv4-fragmentation")]
  375. if self.ipv4_egress(device) {
  376. return true;
  377. }
  378. }
  379. }
  380. let mut readiness_may_have_changed = false;
  381. loop {
  382. let mut did_something = false;
  383. did_something |= self.socket_ingress(device, sockets);
  384. did_something |= self.socket_egress(device, sockets);
  385. #[cfg(feature = "proto-igmp")]
  386. {
  387. did_something |= self.igmp_egress(device);
  388. }
  389. if did_something {
  390. readiness_may_have_changed = true;
  391. } else {
  392. break;
  393. }
  394. }
  395. readiness_may_have_changed
  396. }
  397. /// Return a _soft deadline_ for calling [poll] the next time.
  398. /// The [Instant] returned is the time at which you should call [poll] next.
  399. /// It is harmless (but wastes energy) to call it before the [Instant], and
  400. /// potentially harmful (impacting quality of service) to call it after the
  401. /// [Instant]
  402. ///
  403. /// [poll]: #method.poll
  404. /// [Instant]: struct.Instant.html
  405. pub fn poll_at(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Instant> {
  406. self.inner.now = timestamp;
  407. #[cfg(feature = "_proto-fragmentation")]
  408. if !self.fragmenter.is_empty() {
  409. return Some(Instant::from_millis(0));
  410. }
  411. let inner = &mut self.inner;
  412. sockets
  413. .items()
  414. .filter_map(move |item| {
  415. let socket_poll_at = item.socket.poll_at(inner);
  416. match item
  417. .meta
  418. .poll_at(socket_poll_at, |ip_addr| inner.has_neighbor(&ip_addr))
  419. {
  420. PollAt::Ingress => None,
  421. PollAt::Time(instant) => Some(instant),
  422. PollAt::Now => Some(Instant::from_millis(0)),
  423. }
  424. })
  425. .min()
  426. }
  427. /// Return an _advisory wait time_ for calling [poll] the next time.
  428. /// The [Duration] returned is the time left to wait before calling [poll] next.
  429. /// It is harmless (but wastes energy) to call it before the [Duration] has passed,
  430. /// and potentially harmful (impacting quality of service) to call it after the
  431. /// [Duration] has passed.
  432. ///
  433. /// [poll]: #method.poll
  434. /// [Duration]: struct.Duration.html
  435. pub fn poll_delay(&mut self, timestamp: Instant, sockets: &SocketSet<'_>) -> Option<Duration> {
  436. match self.poll_at(timestamp, sockets) {
  437. Some(poll_at) if timestamp < poll_at => Some(poll_at - timestamp),
  438. Some(_) => Some(Duration::from_millis(0)),
  439. _ => None,
  440. }
  441. }
  442. fn socket_ingress<D>(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool
  443. where
  444. D: Device + ?Sized,
  445. {
  446. let mut processed_any = false;
  447. while let Some((rx_token, tx_token)) = device.receive(self.inner.now) {
  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) = self.inner.process_ethernet(
  457. sockets,
  458. rx_meta,
  459. frame,
  460. &mut self.fragments,
  461. ) {
  462. if let Err(err) =
  463. self.inner.dispatch(tx_token, packet, &mut self.fragmenter)
  464. {
  465. net_debug!("Failed to send response: {:?}", err);
  466. }
  467. }
  468. }
  469. #[cfg(feature = "medium-ip")]
  470. Medium::Ip => {
  471. if let Some(packet) =
  472. self.inner
  473. .process_ip(sockets, rx_meta, frame, &mut self.fragments)
  474. {
  475. if let Err(err) = self.inner.dispatch_ip(
  476. tx_token,
  477. PacketMeta::default(),
  478. packet,
  479. &mut self.fragmenter,
  480. ) {
  481. net_debug!("Failed to send response: {:?}", err);
  482. }
  483. }
  484. }
  485. #[cfg(feature = "medium-ieee802154")]
  486. Medium::Ieee802154 => {
  487. if let Some(packet) = self.inner.process_ieee802154(
  488. sockets,
  489. rx_meta,
  490. frame,
  491. &mut self.fragments,
  492. ) {
  493. if let Err(err) = self.inner.dispatch_ip(
  494. tx_token,
  495. PacketMeta::default(),
  496. packet,
  497. &mut self.fragmenter,
  498. ) {
  499. net_debug!("Failed to send response: {:?}", err);
  500. }
  501. }
  502. }
  503. }
  504. processed_any = true;
  505. });
  506. }
  507. processed_any
  508. }
  509. fn socket_egress<D>(&mut self, device: &mut D, sockets: &mut SocketSet<'_>) -> bool
  510. where
  511. D: Device + ?Sized,
  512. {
  513. let _caps = device.capabilities();
  514. enum EgressError {
  515. Exhausted,
  516. Dispatch,
  517. }
  518. let mut emitted_any = false;
  519. for item in sockets.items_mut() {
  520. if !item
  521. .meta
  522. .egress_permitted(self.inner.now, |ip_addr| self.inner.has_neighbor(&ip_addr))
  523. {
  524. continue;
  525. }
  526. let mut neighbor_addr = None;
  527. let mut respond = |inner: &mut InterfaceInner, meta: PacketMeta, response: Packet| {
  528. neighbor_addr = Some(response.ip_repr().dst_addr());
  529. let t = device.transmit(inner.now).ok_or_else(|| {
  530. net_debug!("failed to transmit IP: device exhausted");
  531. EgressError::Exhausted
  532. })?;
  533. inner
  534. .dispatch_ip(t, meta, response, &mut self.fragmenter)
  535. .map_err(|_| EgressError::Dispatch)?;
  536. emitted_any = true;
  537. Ok(())
  538. };
  539. let result = match &mut item.socket {
  540. #[cfg(feature = "socket-raw")]
  541. Socket::Raw(socket) => socket.dispatch(&mut self.inner, |inner, (ip, raw)| {
  542. respond(
  543. inner,
  544. PacketMeta::default(),
  545. Packet::new(ip, IpPayload::Raw(raw)),
  546. )
  547. }),
  548. #[cfg(feature = "socket-icmp")]
  549. Socket::Icmp(socket) => {
  550. socket.dispatch(&mut self.inner, |inner, response| match response {
  551. #[cfg(feature = "proto-ipv4")]
  552. (IpRepr::Ipv4(ipv4_repr), IcmpRepr::Ipv4(icmpv4_repr)) => respond(
  553. inner,
  554. PacketMeta::default(),
  555. Packet::new_ipv4(ipv4_repr, IpPayload::Icmpv4(icmpv4_repr)),
  556. ),
  557. #[cfg(feature = "proto-ipv6")]
  558. (IpRepr::Ipv6(ipv6_repr), IcmpRepr::Ipv6(icmpv6_repr)) => respond(
  559. inner,
  560. PacketMeta::default(),
  561. Packet::new_ipv6(ipv6_repr, IpPayload::Icmpv6(icmpv6_repr)),
  562. ),
  563. #[allow(unreachable_patterns)]
  564. _ => unreachable!(),
  565. })
  566. }
  567. #[cfg(feature = "socket-udp")]
  568. Socket::Udp(socket) => {
  569. socket.dispatch(&mut self.inner, |inner, meta, (ip, udp, payload)| {
  570. respond(inner, meta, Packet::new(ip, IpPayload::Udp(udp, payload)))
  571. })
  572. }
  573. #[cfg(feature = "socket-tcp")]
  574. Socket::Tcp(socket) => socket.dispatch(&mut self.inner, |inner, (ip, tcp)| {
  575. respond(
  576. inner,
  577. PacketMeta::default(),
  578. Packet::new(ip, IpPayload::Tcp(tcp)),
  579. )
  580. }),
  581. #[cfg(feature = "socket-dhcpv4")]
  582. Socket::Dhcpv4(socket) => {
  583. socket.dispatch(&mut self.inner, |inner, (ip, udp, dhcp)| {
  584. respond(
  585. inner,
  586. PacketMeta::default(),
  587. Packet::new_ipv4(ip, IpPayload::Dhcpv4(udp, dhcp)),
  588. )
  589. })
  590. }
  591. #[cfg(feature = "socket-dns")]
  592. Socket::Dns(socket) => socket.dispatch(&mut self.inner, |inner, (ip, udp, dns)| {
  593. respond(
  594. inner,
  595. PacketMeta::default(),
  596. Packet::new(ip, IpPayload::Udp(udp, dns)),
  597. )
  598. }),
  599. };
  600. match result {
  601. Err(EgressError::Exhausted) => break, // Device buffer full.
  602. Err(EgressError::Dispatch) => {
  603. // `NeighborCache` already takes care of rate limiting the neighbor discovery
  604. // requests from the socket. However, without an additional rate limiting
  605. // mechanism, we would spin on every socket that has yet to discover its
  606. // neighbor.
  607. item.meta.neighbor_missing(
  608. self.inner.now,
  609. neighbor_addr.expect("non-IP response packet"),
  610. );
  611. }
  612. Ok(()) => {}
  613. }
  614. }
  615. emitted_any
  616. }
  617. }
  618. impl InterfaceInner {
  619. #[allow(unused)] // unused depending on which sockets are enabled
  620. pub(crate) fn now(&self) -> Instant {
  621. self.now
  622. }
  623. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  624. #[allow(unused)] // unused depending on which sockets are enabled
  625. pub(crate) fn hardware_addr(&self) -> HardwareAddress {
  626. self.hardware_addr
  627. }
  628. #[allow(unused)] // unused depending on which sockets are enabled
  629. pub(crate) fn checksum_caps(&self) -> ChecksumCapabilities {
  630. self.caps.checksum.clone()
  631. }
  632. #[allow(unused)] // unused depending on which sockets are enabled
  633. pub(crate) fn ip_mtu(&self) -> usize {
  634. self.caps.ip_mtu()
  635. }
  636. #[allow(unused)] // unused depending on which sockets are enabled, and in tests
  637. pub(crate) fn rand(&mut self) -> &mut Rand {
  638. &mut self.rand
  639. }
  640. #[allow(unused)] // unused depending on which sockets are enabled
  641. pub(crate) fn get_source_address(&self, dst_addr: &IpAddress) -> Option<IpAddress> {
  642. match dst_addr {
  643. #[cfg(feature = "proto-ipv4")]
  644. IpAddress::Ipv4(addr) => self.get_source_address_ipv4(addr).map(|a| a.into()),
  645. #[cfg(feature = "proto-ipv6")]
  646. IpAddress::Ipv6(addr) => Some(self.get_source_address_ipv6(addr).into()),
  647. }
  648. }
  649. #[cfg(test)]
  650. #[allow(unused)] // unused depending on which sockets are enabled
  651. pub(crate) fn set_now(&mut self, now: Instant) {
  652. self.now = now
  653. }
  654. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  655. fn check_hardware_addr(addr: &HardwareAddress) {
  656. if !addr.is_unicast() {
  657. panic!("Hardware address {addr} is not unicast")
  658. }
  659. }
  660. fn check_ip_addrs(addrs: &[IpCidr]) {
  661. for cidr in addrs {
  662. if !cidr.address().is_unicast() && !cidr.address().is_unspecified() {
  663. panic!("IP address {} is not unicast", cidr.address())
  664. }
  665. }
  666. }
  667. /// Check whether the interface has the given IP address assigned.
  668. fn has_ip_addr<T: Into<IpAddress>>(&self, addr: T) -> bool {
  669. let addr = addr.into();
  670. self.ip_addrs.iter().any(|probe| probe.address() == addr)
  671. }
  672. /// Check whether the interface listens to given destination multicast IP address.
  673. ///
  674. /// If built without feature `proto-igmp` this function will
  675. /// always return `false` when using IPv4.
  676. fn has_multicast_group<T: Into<IpAddress>>(&self, addr: T) -> bool {
  677. match addr.into() {
  678. #[cfg(feature = "proto-igmp")]
  679. IpAddress::Ipv4(key) => {
  680. key == Ipv4Address::MULTICAST_ALL_SYSTEMS
  681. || self.ipv4_multicast_groups.get(&key).is_some()
  682. }
  683. #[cfg(feature = "proto-ipv6")]
  684. IpAddress::Ipv6(key) => {
  685. key == Ipv6Address::LINK_LOCAL_ALL_NODES
  686. || self.has_solicited_node(key)
  687. || self.ipv6_multicast_groups.get(&key).is_some()
  688. }
  689. #[cfg(feature = "proto-rpl")]
  690. IpAddress::Ipv6(Ipv6Address::LINK_LOCAL_ALL_RPL_NODES) => true,
  691. #[allow(unreachable_patterns)]
  692. _ => false,
  693. }
  694. }
  695. #[cfg(feature = "medium-ip")]
  696. fn process_ip<'frame>(
  697. &mut self,
  698. sockets: &mut SocketSet,
  699. meta: PacketMeta,
  700. ip_payload: &'frame [u8],
  701. frag: &'frame mut FragmentsBuffer,
  702. ) -> Option<Packet<'frame>> {
  703. match IpVersion::of_packet(ip_payload) {
  704. #[cfg(feature = "proto-ipv4")]
  705. Ok(IpVersion::Ipv4) => {
  706. let ipv4_packet = check!(Ipv4Packet::new_checked(ip_payload));
  707. self.process_ipv4(sockets, meta, &ipv4_packet, frag)
  708. }
  709. #[cfg(feature = "proto-ipv6")]
  710. Ok(IpVersion::Ipv6) => {
  711. let ipv6_packet = check!(Ipv6Packet::new_checked(ip_payload));
  712. self.process_ipv6(sockets, meta, &ipv6_packet)
  713. }
  714. // Drop all other traffic.
  715. _ => None,
  716. }
  717. }
  718. #[cfg(feature = "socket-raw")]
  719. fn raw_socket_filter(
  720. &mut self,
  721. sockets: &mut SocketSet,
  722. ip_repr: &IpRepr,
  723. ip_payload: &[u8],
  724. ) -> bool {
  725. let mut handled_by_raw_socket = false;
  726. // Pass every IP packet to all raw sockets we have registered.
  727. for raw_socket in sockets
  728. .items_mut()
  729. .filter_map(|i| raw::Socket::downcast_mut(&mut i.socket))
  730. {
  731. if raw_socket.accepts(ip_repr) {
  732. raw_socket.process(self, ip_repr, ip_payload);
  733. handled_by_raw_socket = true;
  734. }
  735. }
  736. handled_by_raw_socket
  737. }
  738. /// Checks if an address is broadcast, taking into account ipv4 subnet-local
  739. /// broadcast addresses.
  740. pub(crate) fn is_broadcast(&self, address: &IpAddress) -> bool {
  741. match address {
  742. #[cfg(feature = "proto-ipv4")]
  743. IpAddress::Ipv4(address) => self.is_broadcast_v4(*address),
  744. #[cfg(feature = "proto-ipv6")]
  745. IpAddress::Ipv6(_) => false,
  746. }
  747. }
  748. #[cfg(feature = "medium-ethernet")]
  749. fn dispatch<Tx>(
  750. &mut self,
  751. tx_token: Tx,
  752. packet: EthernetPacket,
  753. frag: &mut Fragmenter,
  754. ) -> Result<(), DispatchError>
  755. where
  756. Tx: TxToken,
  757. {
  758. match packet {
  759. #[cfg(feature = "proto-ipv4")]
  760. EthernetPacket::Arp(arp_repr) => {
  761. let dst_hardware_addr = match arp_repr {
  762. ArpRepr::EthernetIpv4 {
  763. target_hardware_addr,
  764. ..
  765. } => target_hardware_addr,
  766. };
  767. self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
  768. frame.set_dst_addr(dst_hardware_addr);
  769. frame.set_ethertype(EthernetProtocol::Arp);
  770. let mut packet = ArpPacket::new_unchecked(frame.payload_mut());
  771. arp_repr.emit(&mut packet);
  772. })
  773. }
  774. EthernetPacket::Ip(packet) => {
  775. self.dispatch_ip(tx_token, PacketMeta::default(), packet, frag)
  776. }
  777. }
  778. }
  779. fn in_same_network(&self, addr: &IpAddress) -> bool {
  780. self.ip_addrs.iter().any(|cidr| cidr.contains_addr(addr))
  781. }
  782. fn route(&self, addr: &IpAddress, timestamp: Instant) -> Option<IpAddress> {
  783. // Send directly.
  784. // note: no need to use `self.is_broadcast()` to check for subnet-local broadcast addrs
  785. // here because `in_same_network` will already return true.
  786. if self.in_same_network(addr) || addr.is_broadcast() {
  787. return Some(*addr);
  788. }
  789. // Route via a router.
  790. self.routes.lookup(addr, timestamp)
  791. }
  792. fn has_neighbor(&self, addr: &IpAddress) -> bool {
  793. match self.route(addr, self.now) {
  794. Some(_routed_addr) => match self.caps.medium {
  795. #[cfg(feature = "medium-ethernet")]
  796. Medium::Ethernet => self.neighbor_cache.lookup(&_routed_addr, self.now).found(),
  797. #[cfg(feature = "medium-ieee802154")]
  798. Medium::Ieee802154 => self.neighbor_cache.lookup(&_routed_addr, self.now).found(),
  799. #[cfg(feature = "medium-ip")]
  800. Medium::Ip => true,
  801. },
  802. None => false,
  803. }
  804. }
  805. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  806. fn lookup_hardware_addr<Tx>(
  807. &mut self,
  808. tx_token: Tx,
  809. src_addr: &IpAddress,
  810. dst_addr: &IpAddress,
  811. fragmenter: &mut Fragmenter,
  812. ) -> Result<(HardwareAddress, Tx), DispatchError>
  813. where
  814. Tx: TxToken,
  815. {
  816. if self.is_broadcast(dst_addr) {
  817. let hardware_addr = match self.caps.medium {
  818. #[cfg(feature = "medium-ethernet")]
  819. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::BROADCAST),
  820. #[cfg(feature = "medium-ieee802154")]
  821. Medium::Ieee802154 => HardwareAddress::Ieee802154(Ieee802154Address::BROADCAST),
  822. #[cfg(feature = "medium-ip")]
  823. Medium::Ip => unreachable!(),
  824. };
  825. return Ok((hardware_addr, tx_token));
  826. }
  827. if dst_addr.is_multicast() {
  828. let b = dst_addr.as_bytes();
  829. let hardware_addr = match *dst_addr {
  830. #[cfg(feature = "proto-ipv4")]
  831. IpAddress::Ipv4(_addr) => match self.caps.medium {
  832. #[cfg(feature = "medium-ethernet")]
  833. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  834. 0x01,
  835. 0x00,
  836. 0x5e,
  837. b[1] & 0x7F,
  838. b[2],
  839. b[3],
  840. ])),
  841. #[cfg(feature = "medium-ieee802154")]
  842. Medium::Ieee802154 => unreachable!(),
  843. #[cfg(feature = "medium-ip")]
  844. Medium::Ip => unreachable!(),
  845. },
  846. #[cfg(feature = "proto-ipv6")]
  847. IpAddress::Ipv6(_addr) => match self.caps.medium {
  848. #[cfg(feature = "medium-ethernet")]
  849. Medium::Ethernet => HardwareAddress::Ethernet(EthernetAddress::from_bytes(&[
  850. 0x33, 0x33, b[12], b[13], b[14], b[15],
  851. ])),
  852. #[cfg(feature = "medium-ieee802154")]
  853. Medium::Ieee802154 => {
  854. // Not sure if this is correct
  855. HardwareAddress::Ieee802154(Ieee802154Address::BROADCAST)
  856. }
  857. #[cfg(feature = "medium-ip")]
  858. Medium::Ip => unreachable!(),
  859. },
  860. };
  861. return Ok((hardware_addr, tx_token));
  862. }
  863. let dst_addr = self
  864. .route(dst_addr, self.now)
  865. .ok_or(DispatchError::NoRoute)?;
  866. match self.neighbor_cache.lookup(&dst_addr, self.now) {
  867. NeighborAnswer::Found(hardware_addr) => return Ok((hardware_addr, tx_token)),
  868. NeighborAnswer::RateLimited => return Err(DispatchError::NeighborPending),
  869. _ => (), // XXX
  870. }
  871. match (src_addr, dst_addr) {
  872. #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))]
  873. (&IpAddress::Ipv4(src_addr), IpAddress::Ipv4(dst_addr))
  874. if matches!(self.caps.medium, Medium::Ethernet) =>
  875. {
  876. net_debug!(
  877. "address {} not in neighbor cache, sending ARP request",
  878. dst_addr
  879. );
  880. let src_hardware_addr = self.hardware_addr.ethernet_or_panic();
  881. let arp_repr = ArpRepr::EthernetIpv4 {
  882. operation: ArpOperation::Request,
  883. source_hardware_addr: src_hardware_addr,
  884. source_protocol_addr: src_addr,
  885. target_hardware_addr: EthernetAddress::BROADCAST,
  886. target_protocol_addr: dst_addr,
  887. };
  888. if let Err(e) =
  889. self.dispatch_ethernet(tx_token, arp_repr.buffer_len(), |mut frame| {
  890. frame.set_dst_addr(EthernetAddress::BROADCAST);
  891. frame.set_ethertype(EthernetProtocol::Arp);
  892. arp_repr.emit(&mut ArpPacket::new_unchecked(frame.payload_mut()))
  893. })
  894. {
  895. net_debug!("Failed to dispatch ARP request: {:?}", e);
  896. return Err(DispatchError::NeighborPending);
  897. }
  898. }
  899. #[cfg(feature = "proto-ipv6")]
  900. (&IpAddress::Ipv6(src_addr), IpAddress::Ipv6(dst_addr)) => {
  901. net_debug!(
  902. "address {} not in neighbor cache, sending Neighbor Solicitation",
  903. dst_addr
  904. );
  905. let solicit = Icmpv6Repr::Ndisc(NdiscRepr::NeighborSolicit {
  906. target_addr: dst_addr,
  907. lladdr: Some(self.hardware_addr.into()),
  908. });
  909. let packet = Packet::new_ipv6(
  910. Ipv6Repr {
  911. src_addr,
  912. dst_addr: dst_addr.solicited_node(),
  913. next_header: IpProtocol::Icmpv6,
  914. payload_len: solicit.buffer_len(),
  915. hop_limit: 0xff,
  916. },
  917. IpPayload::Icmpv6(solicit),
  918. );
  919. if let Err(e) =
  920. self.dispatch_ip(tx_token, PacketMeta::default(), packet, fragmenter)
  921. {
  922. net_debug!("Failed to dispatch NDISC solicit: {:?}", e);
  923. return Err(DispatchError::NeighborPending);
  924. }
  925. }
  926. #[allow(unreachable_patterns)]
  927. _ => (),
  928. }
  929. // The request got dispatched, limit the rate on the cache.
  930. self.neighbor_cache.limit_rate(self.now);
  931. Err(DispatchError::NeighborPending)
  932. }
  933. fn flush_neighbor_cache(&mut self) {
  934. #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
  935. self.neighbor_cache.flush()
  936. }
  937. fn dispatch_ip<Tx: TxToken>(
  938. &mut self,
  939. // NOTE(unused_mut): tx_token isn't always mutated, depending on
  940. // the feature set that is used.
  941. #[allow(unused_mut)] mut tx_token: Tx,
  942. meta: PacketMeta,
  943. packet: Packet,
  944. frag: &mut Fragmenter,
  945. ) -> Result<(), DispatchError> {
  946. let mut ip_repr = packet.ip_repr();
  947. assert!(!ip_repr.dst_addr().is_unspecified());
  948. // Dispatch IEEE802.15.4:
  949. #[cfg(feature = "medium-ieee802154")]
  950. if matches!(self.caps.medium, Medium::Ieee802154) {
  951. let (addr, tx_token) = self.lookup_hardware_addr(
  952. tx_token,
  953. &ip_repr.src_addr(),
  954. &ip_repr.dst_addr(),
  955. frag,
  956. )?;
  957. let addr = addr.ieee802154_or_panic();
  958. self.dispatch_ieee802154(addr, tx_token, meta, packet, frag);
  959. return Ok(());
  960. }
  961. // Dispatch IP/Ethernet:
  962. let caps = self.caps.clone();
  963. #[cfg(feature = "proto-ipv4-fragmentation")]
  964. let ipv4_id = self.next_ipv4_frag_ident();
  965. // First we calculate the total length that we will have to emit.
  966. let mut total_len = ip_repr.buffer_len();
  967. // Add the size of the Ethernet header if the medium is Ethernet.
  968. #[cfg(feature = "medium-ethernet")]
  969. if matches!(self.caps.medium, Medium::Ethernet) {
  970. total_len = EthernetFrame::<&[u8]>::buffer_len(total_len);
  971. }
  972. // If the medium is Ethernet, then we need to retrieve the destination hardware address.
  973. #[cfg(feature = "medium-ethernet")]
  974. let (dst_hardware_addr, mut tx_token) = match self.caps.medium {
  975. Medium::Ethernet => {
  976. match self.lookup_hardware_addr(
  977. tx_token,
  978. &ip_repr.src_addr(),
  979. &ip_repr.dst_addr(),
  980. frag,
  981. )? {
  982. (HardwareAddress::Ethernet(addr), tx_token) => (addr, tx_token),
  983. (_, _) => unreachable!(),
  984. }
  985. }
  986. _ => (EthernetAddress([0; 6]), tx_token),
  987. };
  988. // Emit function for the Ethernet header.
  989. #[cfg(feature = "medium-ethernet")]
  990. let emit_ethernet = |repr: &IpRepr, tx_buffer: &mut [u8]| {
  991. let mut frame = EthernetFrame::new_unchecked(tx_buffer);
  992. let src_addr = self.hardware_addr.ethernet_or_panic();
  993. frame.set_src_addr(src_addr);
  994. frame.set_dst_addr(dst_hardware_addr);
  995. match repr.version() {
  996. #[cfg(feature = "proto-ipv4")]
  997. IpVersion::Ipv4 => frame.set_ethertype(EthernetProtocol::Ipv4),
  998. #[cfg(feature = "proto-ipv6")]
  999. IpVersion::Ipv6 => frame.set_ethertype(EthernetProtocol::Ipv6),
  1000. }
  1001. Ok(())
  1002. };
  1003. // Emit function for the IP header and payload.
  1004. let emit_ip = |repr: &IpRepr, mut tx_buffer: &mut [u8]| {
  1005. repr.emit(&mut tx_buffer, &self.caps.checksum);
  1006. let payload = &mut tx_buffer[repr.header_len()..];
  1007. packet.emit_payload(repr, payload, &caps)
  1008. };
  1009. let total_ip_len = ip_repr.buffer_len();
  1010. match &mut ip_repr {
  1011. #[cfg(feature = "proto-ipv4")]
  1012. IpRepr::Ipv4(repr) => {
  1013. // If we have an IPv4 packet, then we need to check if we need to fragment it.
  1014. if total_ip_len > self.caps.max_transmission_unit {
  1015. #[cfg(feature = "proto-ipv4-fragmentation")]
  1016. {
  1017. net_debug!("start fragmentation");
  1018. // Calculate how much we will send now (including the Ethernet header).
  1019. let tx_len = self.caps.max_transmission_unit;
  1020. let ip_header_len = repr.buffer_len();
  1021. let first_frag_ip_len = self.caps.ip_mtu();
  1022. if frag.buffer.len() < total_ip_len {
  1023. net_debug!(
  1024. "Fragmentation buffer is too small, at least {} needed. Dropping",
  1025. total_ip_len
  1026. );
  1027. return Ok(());
  1028. }
  1029. #[cfg(feature = "medium-ethernet")]
  1030. {
  1031. frag.ipv4.dst_hardware_addr = dst_hardware_addr;
  1032. }
  1033. // Save the total packet len (without the Ethernet header, but with the first
  1034. // IP header).
  1035. frag.packet_len = total_ip_len;
  1036. // Save the IP header for other fragments.
  1037. frag.ipv4.repr = *repr;
  1038. // Save how much bytes we will send now.
  1039. frag.sent_bytes = first_frag_ip_len;
  1040. // Modify the IP header
  1041. repr.payload_len = first_frag_ip_len - repr.buffer_len();
  1042. // Emit the IP header to the buffer.
  1043. emit_ip(&ip_repr, &mut frag.buffer);
  1044. let mut ipv4_packet = Ipv4Packet::new_unchecked(&mut frag.buffer[..]);
  1045. frag.ipv4.ident = ipv4_id;
  1046. ipv4_packet.set_ident(ipv4_id);
  1047. ipv4_packet.set_more_frags(true);
  1048. ipv4_packet.set_dont_frag(false);
  1049. ipv4_packet.set_frag_offset(0);
  1050. if caps.checksum.ipv4.tx() {
  1051. ipv4_packet.fill_checksum();
  1052. }
  1053. // Transmit the first packet.
  1054. tx_token.consume(tx_len, |mut tx_buffer| {
  1055. #[cfg(feature = "medium-ethernet")]
  1056. if matches!(self.caps.medium, Medium::Ethernet) {
  1057. emit_ethernet(&ip_repr, tx_buffer)?;
  1058. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1059. }
  1060. // Change the offset for the next packet.
  1061. frag.ipv4.frag_offset = (first_frag_ip_len - ip_header_len) as u16;
  1062. // Copy the IP header and the payload.
  1063. tx_buffer[..first_frag_ip_len]
  1064. .copy_from_slice(&frag.buffer[..first_frag_ip_len]);
  1065. Ok(())
  1066. })
  1067. }
  1068. #[cfg(not(feature = "proto-ipv4-fragmentation"))]
  1069. {
  1070. net_debug!("Enable the `proto-ipv4-fragmentation` feature for fragmentation support.");
  1071. Ok(())
  1072. }
  1073. } else {
  1074. tx_token.set_meta(meta);
  1075. // No fragmentation is required.
  1076. tx_token.consume(total_len, |mut tx_buffer| {
  1077. #[cfg(feature = "medium-ethernet")]
  1078. if matches!(self.caps.medium, Medium::Ethernet) {
  1079. emit_ethernet(&ip_repr, tx_buffer)?;
  1080. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1081. }
  1082. emit_ip(&ip_repr, tx_buffer);
  1083. Ok(())
  1084. })
  1085. }
  1086. }
  1087. // We don't support IPv6 fragmentation yet.
  1088. #[cfg(feature = "proto-ipv6")]
  1089. IpRepr::Ipv6(_) => tx_token.consume(total_len, |mut tx_buffer| {
  1090. #[cfg(feature = "medium-ethernet")]
  1091. if matches!(self.caps.medium, Medium::Ethernet) {
  1092. emit_ethernet(&ip_repr, tx_buffer)?;
  1093. tx_buffer = &mut tx_buffer[EthernetFrame::<&[u8]>::header_len()..];
  1094. }
  1095. emit_ip(&ip_repr, tx_buffer);
  1096. Ok(())
  1097. }),
  1098. }
  1099. }
  1100. }
  1101. #[derive(Debug, Clone, Copy, PartialEq, Eq)]
  1102. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  1103. enum DispatchError {
  1104. /// No route to dispatch this packet. Retrying won't help unless
  1105. /// configuration is changed.
  1106. NoRoute,
  1107. /// We do have a route to dispatch this packet, but we haven't discovered
  1108. /// the neighbor for it yet. Discovery has been initiated, dispatch
  1109. /// should be retried later.
  1110. NeighborPending,
  1111. }