mod.rs 46 KB

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