mod.rs 50 KB

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