mod.rs 49 KB

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