diff options
| author | Tyler <[email protected]> | 2023-09-29 20:02:24 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-09-29 20:02:24 -0600 |
| commit | 2f9b59c5cf21f1e2761a9ccefdfd86f0edea829c (patch) | |
| tree | 8964744b4fb753cf98f6f413464106c4d2a72976 /embassy-net/src/lib.rs | |
| parent | ce91fb2bfc846570ef543a09396c428d70675245 (diff) | |
| parent | 95b3d9eb3b3657de3d7bc9c04f8fb83eae901640 (diff) | |
Merge branch 'main' into issue-1974-add-sai-driver
Diffstat (limited to 'embassy-net/src/lib.rs')
| -rw-r--r-- | embassy-net/src/lib.rs | 385 |
1 files changed, 209 insertions, 176 deletions
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 2fb34f43a..0d7ac47a2 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | #![warn(missing_docs)] | 3 | #![warn(missing_docs)] |
| 4 | #![doc = include_str!("../README.md")] | 4 | #![doc = include_str!("../README.md")] |
| 5 | 5 | ||
| 6 | #[cfg(not(any(feature = "proto-ipv4", feature = "proto-ipv6")))] | ||
| 7 | compile_error!("You must enable at least one of the following features: proto-ipv4, proto-ipv6"); | ||
| 8 | |||
| 6 | // This mod MUST go first, so that the others see its macros. | 9 | // This mod MUST go first, so that the others see its macros. |
| 7 | pub(crate) mod fmt; | 10 | pub(crate) mod fmt; |
| 8 | 11 | ||
| @@ -20,7 +23,7 @@ use core::future::{poll_fn, Future}; | |||
| 20 | use core::task::{Context, Poll}; | 23 | use core::task::{Context, Poll}; |
| 21 | 24 | ||
| 22 | pub use embassy_net_driver as driver; | 25 | pub use embassy_net_driver as driver; |
| 23 | use embassy_net_driver::{Driver, LinkState, Medium}; | 26 | use embassy_net_driver::{Driver, LinkState}; |
| 24 | use embassy_sync::waitqueue::WakerRegistration; | 27 | use embassy_sync::waitqueue::WakerRegistration; |
| 25 | use embassy_time::{Instant, Timer}; | 28 | use embassy_time::{Instant, Timer}; |
| 26 | use futures::pin_mut; | 29 | use futures::pin_mut; |
| @@ -133,6 +136,8 @@ impl Default for DhcpConfig { | |||
| 133 | } | 136 | } |
| 134 | 137 | ||
| 135 | /// Network stack configuration. | 138 | /// Network stack configuration. |
| 139 | #[derive(Debug, Clone, Default)] | ||
| 140 | #[non_exhaustive] | ||
| 136 | pub struct Config { | 141 | pub struct Config { |
| 137 | /// IPv4 configuration | 142 | /// IPv4 configuration |
| 138 | #[cfg(feature = "proto-ipv4")] | 143 | #[cfg(feature = "proto-ipv4")] |
| @@ -163,10 +168,11 @@ impl Config { | |||
| 163 | } | 168 | } |
| 164 | } | 169 | } |
| 165 | 170 | ||
| 166 | /// IPv6 configuration with dynamic addressing. | 171 | /// IPv4 configuration with dynamic addressing. |
| 167 | /// | 172 | /// |
| 168 | /// # Example | 173 | /// # Example |
| 169 | /// ```rust | 174 | /// ```rust |
| 175 | /// # use embassy_net::Config; | ||
| 170 | /// let _cfg = Config::dhcpv4(Default::default()); | 176 | /// let _cfg = Config::dhcpv4(Default::default()); |
| 171 | /// ``` | 177 | /// ``` |
| 172 | #[cfg(feature = "dhcpv4")] | 178 | #[cfg(feature = "dhcpv4")] |
| @@ -181,23 +187,27 @@ impl Config { | |||
| 181 | 187 | ||
| 182 | /// Network stack IPv4 configuration. | 188 | /// Network stack IPv4 configuration. |
| 183 | #[cfg(feature = "proto-ipv4")] | 189 | #[cfg(feature = "proto-ipv4")] |
| 190 | #[derive(Debug, Clone, Default)] | ||
| 184 | pub enum ConfigV4 { | 191 | pub enum ConfigV4 { |
| 192 | /// Do not configure IPv4. | ||
| 193 | #[default] | ||
| 194 | None, | ||
| 185 | /// Use a static IPv4 address configuration. | 195 | /// Use a static IPv4 address configuration. |
| 186 | Static(StaticConfigV4), | 196 | Static(StaticConfigV4), |
| 187 | /// Use DHCP to obtain an IP address configuration. | 197 | /// Use DHCP to obtain an IP address configuration. |
| 188 | #[cfg(feature = "dhcpv4")] | 198 | #[cfg(feature = "dhcpv4")] |
| 189 | Dhcp(DhcpConfig), | 199 | Dhcp(DhcpConfig), |
| 190 | /// Do not configure IPv6. | ||
| 191 | None, | ||
| 192 | } | 200 | } |
| 193 | 201 | ||
| 194 | /// Network stack IPv6 configuration. | 202 | /// Network stack IPv6 configuration. |
| 195 | #[cfg(feature = "proto-ipv6")] | 203 | #[cfg(feature = "proto-ipv6")] |
| 204 | #[derive(Debug, Clone, Default)] | ||
| 196 | pub enum ConfigV6 { | 205 | pub enum ConfigV6 { |
| 197 | /// Use a static IPv6 address configuration. | ||
| 198 | Static(StaticConfigV6), | ||
| 199 | /// Do not configure IPv6. | 206 | /// Do not configure IPv6. |
| 207 | #[default] | ||
| 200 | None, | 208 | None, |
| 209 | /// Use a static IPv6 address configuration. | ||
| 210 | Static(StaticConfigV6), | ||
| 201 | } | 211 | } |
| 202 | 212 | ||
| 203 | /// A network stack. | 213 | /// A network stack. |
| @@ -217,6 +227,7 @@ struct Inner<D: Driver> { | |||
| 217 | static_v6: Option<StaticConfigV6>, | 227 | static_v6: Option<StaticConfigV6>, |
| 218 | #[cfg(feature = "dhcpv4")] | 228 | #[cfg(feature = "dhcpv4")] |
| 219 | dhcp_socket: Option<SocketHandle>, | 229 | dhcp_socket: Option<SocketHandle>, |
| 230 | config_waker: WakerRegistration, | ||
| 220 | #[cfg(feature = "dns")] | 231 | #[cfg(feature = "dns")] |
| 221 | dns_socket: SocketHandle, | 232 | dns_socket: SocketHandle, |
| 222 | #[cfg(feature = "dns")] | 233 | #[cfg(feature = "dns")] |
| @@ -240,11 +251,14 @@ fn to_smoltcp_hardware_address(addr: driver::HardwareAddress) -> HardwareAddress | |||
| 240 | driver::HardwareAddress::Ip => HardwareAddress::Ip, | 251 | driver::HardwareAddress::Ip => HardwareAddress::Ip, |
| 241 | 252 | ||
| 242 | #[allow(unreachable_patterns)] | 253 | #[allow(unreachable_patterns)] |
| 243 | _ => panic!("Unsupported address {:?}. Make sure to enable medium-ethernet or medium-ieee802154 in embassy-net's Cargo features.", addr), | 254 | _ => panic!( |
| 255 | "Unsupported medium {:?}. Make sure to enable the right medium feature in embassy-net's Cargo features.", | ||
| 256 | addr | ||
| 257 | ), | ||
| 244 | } | 258 | } |
| 245 | } | 259 | } |
| 246 | 260 | ||
| 247 | impl<D: Driver + 'static> Stack<D> { | 261 | impl<D: Driver> Stack<D> { |
| 248 | /// Create a new network stack. | 262 | /// Create a new network stack. |
| 249 | pub fn new<const SOCK: usize>( | 263 | pub fn new<const SOCK: usize>( |
| 250 | mut device: D, | 264 | mut device: D, |
| @@ -276,7 +290,6 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 276 | next_local_port, | 290 | next_local_port, |
| 277 | }; | 291 | }; |
| 278 | 292 | ||
| 279 | #[cfg_attr(feature = "medium-ieee802154", allow(unused_mut))] | ||
| 280 | let mut inner = Inner { | 293 | let mut inner = Inner { |
| 281 | device, | 294 | device, |
| 282 | link_up: false, | 295 | link_up: false, |
| @@ -286,6 +299,7 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 286 | static_v6: None, | 299 | static_v6: None, |
| 287 | #[cfg(feature = "dhcpv4")] | 300 | #[cfg(feature = "dhcpv4")] |
| 288 | dhcp_socket: None, | 301 | dhcp_socket: None, |
| 302 | config_waker: WakerRegistration::new(), | ||
| 289 | #[cfg(feature = "dns")] | 303 | #[cfg(feature = "dns")] |
| 290 | dns_socket: socket.sockets.add(dns::Socket::new( | 304 | dns_socket: socket.sockets.add(dns::Socket::new( |
| 291 | &[], | 305 | &[], |
| @@ -295,30 +309,11 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 295 | dns_waker: WakerRegistration::new(), | 309 | dns_waker: WakerRegistration::new(), |
| 296 | }; | 310 | }; |
| 297 | 311 | ||
| 298 | #[cfg(feature = "medium-ieee802154")] | ||
| 299 | let _ = config; | ||
| 300 | |||
| 301 | #[cfg(feature = "proto-ipv4")] | 312 | #[cfg(feature = "proto-ipv4")] |
| 302 | match config.ipv4 { | 313 | inner.set_config_v4(&mut socket, config.ipv4); |
| 303 | ConfigV4::Static(config) => { | ||
| 304 | inner.apply_config_v4(&mut socket, config); | ||
| 305 | } | ||
| 306 | #[cfg(feature = "dhcpv4")] | ||
| 307 | ConfigV4::Dhcp(config) => { | ||
| 308 | let mut dhcp_socket = smoltcp::socket::dhcpv4::Socket::new(); | ||
| 309 | inner.apply_dhcp_config(&mut dhcp_socket, config); | ||
| 310 | let handle = socket.sockets.add(dhcp_socket); | ||
| 311 | inner.dhcp_socket = Some(handle); | ||
| 312 | } | ||
| 313 | ConfigV4::None => {} | ||
| 314 | } | ||
| 315 | #[cfg(feature = "proto-ipv6")] | 314 | #[cfg(feature = "proto-ipv6")] |
| 316 | match config.ipv6 { | 315 | inner.set_config_v6(&mut socket, config.ipv6); |
| 317 | ConfigV6::Static(config) => { | 316 | inner.apply_static_config(&mut socket); |
| 318 | inner.apply_config_v6(&mut socket, config); | ||
| 319 | } | ||
| 320 | ConfigV6::None => {} | ||
| 321 | } | ||
| 322 | 317 | ||
| 323 | Self { | 318 | Self { |
| 324 | socket: RefCell::new(socket), | 319 | socket: RefCell::new(socket), |
| @@ -371,16 +366,86 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 371 | v4_up || v6_up | 366 | v4_up || v6_up |
| 372 | } | 367 | } |
| 373 | 368 | ||
| 369 | /// Wait for the network stack to obtain a valid IP configuration. | ||
| 370 | /// | ||
| 371 | /// ## Notes: | ||
| 372 | /// - Ensure [`Stack::run`] has been called before using this function. | ||
| 373 | /// | ||
| 374 | /// - This function may never return (e.g. if no configuration is obtained through DHCP). | ||
| 375 | /// The caller is supposed to handle a timeout for this case. | ||
| 376 | /// | ||
| 377 | /// ## Example | ||
| 378 | /// ```ignore | ||
| 379 | /// let config = embassy_net::Config::dhcpv4(Default::default()); | ||
| 380 | ///// Init network stack | ||
| 381 | /// let stack = &*make_static!(embassy_net::Stack::new( | ||
| 382 | /// device, | ||
| 383 | /// config, | ||
| 384 | /// make_static!(embassy_net::StackResources::<2>::new()), | ||
| 385 | /// seed | ||
| 386 | /// )); | ||
| 387 | /// // Launch network task that runs `stack.run().await` | ||
| 388 | /// spawner.spawn(net_task(stack)).unwrap(); | ||
| 389 | /// // Wait for DHCP config | ||
| 390 | /// stack.wait_config_up().await; | ||
| 391 | /// // use the network stack | ||
| 392 | /// // ... | ||
| 393 | /// ``` | ||
| 394 | pub async fn wait_config_up(&self) { | ||
| 395 | // If the config is up already, we can return immediately. | ||
| 396 | if self.is_config_up() { | ||
| 397 | return; | ||
| 398 | } | ||
| 399 | |||
| 400 | poll_fn(|cx| { | ||
| 401 | if self.is_config_up() { | ||
| 402 | Poll::Ready(()) | ||
| 403 | } else { | ||
| 404 | // If the config is not up, we register a waker that is woken up | ||
| 405 | // when a config is applied (static or DHCP). | ||
| 406 | trace!("Waiting for config up"); | ||
| 407 | |||
| 408 | self.with_mut(|_, i| { | ||
| 409 | i.config_waker.register(cx.waker()); | ||
| 410 | }); | ||
| 411 | |||
| 412 | Poll::Pending | ||
| 413 | } | ||
| 414 | }) | ||
| 415 | .await; | ||
| 416 | } | ||
| 417 | |||
| 374 | /// Get the current IPv4 configuration. | 418 | /// Get the current IPv4 configuration. |
| 419 | /// | ||
| 420 | /// If using DHCP, this will be None if DHCP hasn't been able to | ||
| 421 | /// acquire an IP address, or Some if it has. | ||
| 375 | #[cfg(feature = "proto-ipv4")] | 422 | #[cfg(feature = "proto-ipv4")] |
| 376 | pub fn config_v4(&self) -> Option<StaticConfigV4> { | 423 | pub fn config_v4(&self) -> Option<StaticConfigV4> { |
| 377 | self.with(|_s, i| i.static_v4.clone()) | 424 | self.with(|_, i| i.static_v4.clone()) |
| 378 | } | 425 | } |
| 379 | 426 | ||
| 380 | /// Get the current IPv6 configuration. | 427 | /// Get the current IPv6 configuration. |
| 381 | #[cfg(feature = "proto-ipv6")] | 428 | #[cfg(feature = "proto-ipv6")] |
| 382 | pub fn config_v6(&self) -> Option<StaticConfigV6> { | 429 | pub fn config_v6(&self) -> Option<StaticConfigV6> { |
| 383 | self.with(|_s, i| i.static_v6.clone()) | 430 | self.with(|_, i| i.static_v6.clone()) |
| 431 | } | ||
| 432 | |||
| 433 | /// Set the IPv4 configuration. | ||
| 434 | #[cfg(feature = "proto-ipv4")] | ||
| 435 | pub fn set_config_v4(&self, config: ConfigV4) { | ||
| 436 | self.with_mut(|s, i| { | ||
| 437 | i.set_config_v4(s, config); | ||
| 438 | i.apply_static_config(s); | ||
| 439 | }) | ||
| 440 | } | ||
| 441 | |||
| 442 | /// Set the IPv6 configuration. | ||
| 443 | #[cfg(feature = "proto-ipv6")] | ||
| 444 | pub fn set_config_v6(&self, config: ConfigV6) { | ||
| 445 | self.with_mut(|s, i| { | ||
| 446 | i.set_config_v6(s, config); | ||
| 447 | i.apply_static_config(s); | ||
| 448 | }) | ||
| 384 | } | 449 | } |
| 385 | 450 | ||
| 386 | /// Run the network stack. | 451 | /// Run the network stack. |
| @@ -490,7 +555,7 @@ impl<D: Driver + 'static> Stack<D> { | |||
| 490 | } | 555 | } |
| 491 | 556 | ||
| 492 | #[cfg(feature = "igmp")] | 557 | #[cfg(feature = "igmp")] |
| 493 | impl<D: Driver + 'static> Stack<D> { | 558 | impl<D: Driver> Stack<D> { |
| 494 | /// Join a multicast group. | 559 | /// Join a multicast group. |
| 495 | pub async fn join_multicast_group<T>(&self, addr: T) -> Result<bool, MulticastError> | 560 | pub async fn join_multicast_group<T>(&self, addr: T) -> Result<bool, MulticastError> |
| 496 | where | 561 | where |
| @@ -580,168 +645,129 @@ impl SocketStack { | |||
| 580 | } | 645 | } |
| 581 | } | 646 | } |
| 582 | 647 | ||
| 583 | impl<D: Driver + 'static> Inner<D> { | 648 | impl<D: Driver> Inner<D> { |
| 584 | #[cfg(feature = "proto-ipv4")] | 649 | #[cfg(feature = "proto-ipv4")] |
| 585 | fn apply_config_v4(&mut self, s: &mut SocketStack, config: StaticConfigV4) { | 650 | pub fn set_config_v4(&mut self, _s: &mut SocketStack, config: ConfigV4) { |
| 586 | debug!("Acquired IP configuration:"); | 651 | // Handle static config. |
| 587 | 652 | self.static_v4 = match config.clone() { | |
| 588 | debug!(" IP address: {}", config.address); | 653 | ConfigV4::None => None, |
| 589 | s.iface.update_ip_addrs(|addrs| { | 654 | #[cfg(feature = "dhcpv4")] |
| 590 | if let Some((index, _)) = addrs | 655 | ConfigV4::Dhcp(_) => None, |
| 591 | .iter() | 656 | ConfigV4::Static(c) => Some(c), |
| 592 | .enumerate() | 657 | }; |
| 593 | .find(|(_, &addr)| matches!(addr, IpCidr::Ipv4(_))) | ||
| 594 | { | ||
| 595 | addrs.remove(index); | ||
| 596 | } | ||
| 597 | addrs.push(IpCidr::Ipv4(config.address)).unwrap(); | ||
| 598 | }); | ||
| 599 | |||
| 600 | #[cfg(feature = "medium-ip")] | ||
| 601 | let skip_gateway = self.device.capabilities().medium != Medium::Ip; | ||
| 602 | #[cfg(not(feature = "medium-ip"))] | ||
| 603 | let skip_gateway = false; | ||
| 604 | |||
| 605 | if !skip_gateway { | ||
| 606 | if let Some(gateway) = config.gateway { | ||
| 607 | debug!(" Default gateway: {}", gateway); | ||
| 608 | s.iface.routes_mut().add_default_ipv4_route(gateway).unwrap(); | ||
| 609 | } else { | ||
| 610 | debug!(" Default gateway: None"); | ||
| 611 | s.iface.routes_mut().remove_default_ipv4_route(); | ||
| 612 | } | ||
| 613 | } | ||
| 614 | for (i, s) in config.dns_servers.iter().enumerate() { | ||
| 615 | debug!(" DNS server {}: {}", i, s); | ||
| 616 | } | ||
| 617 | 658 | ||
| 618 | self.static_v4 = Some(config); | 659 | // Handle DHCP config. |
| 660 | #[cfg(feature = "dhcpv4")] | ||
| 661 | match config { | ||
| 662 | ConfigV4::Dhcp(c) => { | ||
| 663 | // Create the socket if it doesn't exist. | ||
| 664 | if self.dhcp_socket.is_none() { | ||
| 665 | let socket = smoltcp::socket::dhcpv4::Socket::new(); | ||
| 666 | let handle = _s.sockets.add(socket); | ||
| 667 | self.dhcp_socket = Some(handle); | ||
| 668 | } | ||
| 619 | 669 | ||
| 620 | #[cfg(feature = "dns")] | 670 | // Configure it |
| 621 | { | 671 | let socket = _s.sockets.get_mut::<dhcpv4::Socket>(unwrap!(self.dhcp_socket)); |
| 622 | self.update_dns_servers(s) | 672 | socket.set_ignore_naks(c.ignore_naks); |
| 673 | socket.set_max_lease_duration(c.max_lease_duration.map(crate::time::duration_to_smoltcp)); | ||
| 674 | socket.set_ports(c.server_port, c.client_port); | ||
| 675 | socket.set_retry_config(c.retry_config); | ||
| 676 | socket.reset(); | ||
| 677 | } | ||
| 678 | _ => { | ||
| 679 | // Remove DHCP socket if any. | ||
| 680 | if let Some(socket) = self.dhcp_socket { | ||
| 681 | _s.sockets.remove(socket); | ||
| 682 | self.dhcp_socket = None; | ||
| 683 | } | ||
| 684 | } | ||
| 623 | } | 685 | } |
| 624 | } | 686 | } |
| 625 | 687 | ||
| 626 | /// Replaces the current IPv6 static configuration with a newly supplied config. | ||
| 627 | #[cfg(feature = "proto-ipv6")] | 688 | #[cfg(feature = "proto-ipv6")] |
| 628 | fn apply_config_v6(&mut self, s: &mut SocketStack, config: StaticConfigV6) { | 689 | pub fn set_config_v6(&mut self, _s: &mut SocketStack, config: ConfigV6) { |
| 629 | #[cfg(feature = "medium-ethernet")] | 690 | self.static_v6 = match config { |
| 630 | let medium = self.device.capabilities().medium; | 691 | ConfigV6::None => None, |
| 692 | ConfigV6::Static(c) => Some(c), | ||
| 693 | }; | ||
| 694 | } | ||
| 631 | 695 | ||
| 632 | debug!("Acquired IPv6 configuration:"); | 696 | fn apply_static_config(&mut self, s: &mut SocketStack) { |
| 697 | let mut addrs = Vec::new(); | ||
| 698 | #[cfg(feature = "dns")] | ||
| 699 | let mut dns_servers: Vec<_, 6> = Vec::new(); | ||
| 700 | #[cfg(feature = "proto-ipv4")] | ||
| 701 | let mut gateway_v4 = None; | ||
| 702 | #[cfg(feature = "proto-ipv6")] | ||
| 703 | let mut gateway_v6 = None; | ||
| 633 | 704 | ||
| 634 | debug!(" IP address: {}", config.address); | 705 | #[cfg(feature = "proto-ipv4")] |
| 635 | s.iface.update_ip_addrs(|addrs| { | 706 | if let Some(config) = &self.static_v4 { |
| 636 | if let Some((index, _)) = addrs | 707 | debug!("IPv4: UP"); |
| 637 | .iter() | 708 | debug!(" IP address: {:?}", config.address); |
| 638 | .enumerate() | 709 | debug!(" Default gateway: {:?}", config.gateway); |
| 639 | .find(|(_, &addr)| matches!(addr, IpCidr::Ipv6(_))) | ||
| 640 | { | ||
| 641 | addrs.remove(index); | ||
| 642 | } | ||
| 643 | addrs.push(IpCidr::Ipv6(config.address)).unwrap(); | ||
| 644 | }); | ||
| 645 | 710 | ||
| 646 | #[cfg(feature = "medium-ethernet")] | 711 | unwrap!(addrs.push(IpCidr::Ipv4(config.address)).ok()); |
| 647 | if Medium::Ethernet == medium { | 712 | gateway_v4 = config.gateway.into(); |
| 648 | if let Some(gateway) = config.gateway { | 713 | #[cfg(feature = "dns")] |
| 649 | debug!(" Default gateway: {}", gateway); | 714 | for s in &config.dns_servers { |
| 650 | s.iface.routes_mut().add_default_ipv6_route(gateway).unwrap(); | 715 | debug!(" DNS server: {:?}", s); |
| 651 | } else { | 716 | unwrap!(dns_servers.push(s.clone().into()).ok()); |
| 652 | debug!(" Default gateway: None"); | ||
| 653 | s.iface.routes_mut().remove_default_ipv6_route(); | ||
| 654 | } | 717 | } |
| 655 | } | 718 | } else { |
| 656 | for (i, s) in config.dns_servers.iter().enumerate() { | 719 | info!("IPv4: DOWN"); |
| 657 | debug!(" DNS server {}: {}", i, s); | ||
| 658 | } | 720 | } |
| 659 | 721 | ||
| 660 | self.static_v6 = Some(config); | 722 | #[cfg(feature = "proto-ipv6")] |
| 723 | if let Some(config) = &self.static_v6 { | ||
| 724 | debug!("IPv6: UP"); | ||
| 725 | debug!(" IP address: {:?}", config.address); | ||
| 726 | debug!(" Default gateway: {:?}", config.gateway); | ||
| 661 | 727 | ||
| 662 | #[cfg(feature = "dns")] | 728 | unwrap!(addrs.push(IpCidr::Ipv6(config.address)).ok()); |
| 663 | { | 729 | gateway_v6 = config.gateway.into(); |
| 664 | self.update_dns_servers(s) | 730 | #[cfg(feature = "dns")] |
| 731 | for s in &config.dns_servers { | ||
| 732 | debug!(" DNS server: {:?}", s); | ||
| 733 | unwrap!(dns_servers.push(s.clone().into()).ok()); | ||
| 734 | } | ||
| 735 | } else { | ||
| 736 | info!("IPv6: DOWN"); | ||
| 665 | } | 737 | } |
| 666 | } | ||
| 667 | 738 | ||
| 668 | #[cfg(feature = "dns")] | 739 | // Apply addresses |
| 669 | fn update_dns_servers(&mut self, s: &mut SocketStack) { | 740 | s.iface.update_ip_addrs(|a| *a = addrs); |
| 670 | let socket = s.sockets.get_mut::<smoltcp::socket::dns::Socket>(self.dns_socket); | ||
| 671 | 741 | ||
| 672 | let servers_v4; | 742 | // Apply gateways |
| 673 | #[cfg(feature = "proto-ipv4")] | 743 | #[cfg(feature = "proto-ipv4")] |
| 674 | { | 744 | if let Some(gateway) = gateway_v4 { |
| 675 | servers_v4 = self | 745 | unwrap!(s.iface.routes_mut().add_default_ipv4_route(gateway)); |
| 676 | .static_v4 | 746 | } else { |
| 677 | .iter() | 747 | s.iface.routes_mut().remove_default_ipv4_route(); |
| 678 | .flat_map(|cfg| cfg.dns_servers.iter().map(|c| IpAddress::Ipv4(*c))); | ||
| 679 | }; | ||
| 680 | #[cfg(not(feature = "proto-ipv4"))] | ||
| 681 | { | ||
| 682 | servers_v4 = core::iter::empty(); | ||
| 683 | } | 748 | } |
| 684 | |||
| 685 | let servers_v6; | ||
| 686 | #[cfg(feature = "proto-ipv6")] | 749 | #[cfg(feature = "proto-ipv6")] |
| 687 | { | 750 | if let Some(gateway) = gateway_v6 { |
| 688 | servers_v6 = self | 751 | unwrap!(s.iface.routes_mut().add_default_ipv6_route(gateway)); |
| 689 | .static_v6 | 752 | } else { |
| 690 | .iter() | 753 | s.iface.routes_mut().remove_default_ipv6_route(); |
| 691 | .flat_map(|cfg| cfg.dns_servers.iter().map(|c| IpAddress::Ipv6(*c))); | ||
| 692 | } | 754 | } |
| 693 | #[cfg(not(feature = "proto-ipv6"))] | ||
| 694 | { | ||
| 695 | servers_v6 = core::iter::empty(); | ||
| 696 | } | ||
| 697 | |||
| 698 | // Prefer the v6 DNS servers over the v4 servers | ||
| 699 | let servers: Vec<IpAddress, 6> = servers_v6.chain(servers_v4).collect(); | ||
| 700 | socket.update_servers(&servers[..]); | ||
| 701 | } | ||
| 702 | 755 | ||
| 703 | #[cfg(feature = "dhcpv4")] | 756 | // Apply DNS servers |
| 704 | fn apply_dhcp_config(&self, socket: &mut smoltcp::socket::dhcpv4::Socket, config: DhcpConfig) { | 757 | #[cfg(feature = "dns")] |
| 705 | socket.set_ignore_naks(config.ignore_naks); | 758 | s.sockets |
| 706 | socket.set_max_lease_duration(config.max_lease_duration.map(crate::time::duration_to_smoltcp)); | 759 | .get_mut::<smoltcp::socket::dns::Socket>(self.dns_socket) |
| 707 | socket.set_ports(config.server_port, config.client_port); | 760 | .update_servers(&dns_servers[..]); |
| 708 | socket.set_retry_config(config.retry_config); | ||
| 709 | } | ||
| 710 | 761 | ||
| 711 | #[cfg(feature = "dhcpv4")] | 762 | self.config_waker.wake(); |
| 712 | fn unapply_config_v4(&mut self, s: &mut SocketStack) { | ||
| 713 | #[cfg(feature = "medium-ethernet")] | ||
| 714 | let medium = self.device.capabilities().medium; | ||
| 715 | debug!("Lost IP configuration"); | ||
| 716 | s.iface.update_ip_addrs(|ip_addrs| { | ||
| 717 | #[cfg(feature = "proto-ipv4")] | ||
| 718 | if let Some((index, _)) = ip_addrs | ||
| 719 | .iter() | ||
| 720 | .enumerate() | ||
| 721 | .find(|(_, &addr)| matches!(addr, IpCidr::Ipv4(_))) | ||
| 722 | { | ||
| 723 | ip_addrs.remove(index); | ||
| 724 | } | ||
| 725 | }); | ||
| 726 | #[cfg(feature = "medium-ethernet")] | ||
| 727 | if medium == Medium::Ethernet { | ||
| 728 | #[cfg(feature = "proto-ipv4")] | ||
| 729 | { | ||
| 730 | s.iface.routes_mut().remove_default_ipv4_route(); | ||
| 731 | } | ||
| 732 | } | ||
| 733 | #[cfg(feature = "proto-ipv4")] | ||
| 734 | { | ||
| 735 | self.static_v4 = None | ||
| 736 | } | ||
| 737 | } | 763 | } |
| 738 | 764 | ||
| 739 | fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { | 765 | fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { |
| 740 | s.waker.register(cx.waker()); | 766 | s.waker.register(cx.waker()); |
| 741 | 767 | ||
| 742 | #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] | 768 | #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] |
| 743 | if self.device.capabilities().medium == Medium::Ethernet | 769 | if self.device.capabilities().medium == embassy_net_driver::Medium::Ethernet |
| 744 | || self.device.capabilities().medium == Medium::Ieee802154 | 770 | || self.device.capabilities().medium == embassy_net_driver::Medium::Ieee802154 |
| 745 | { | 771 | { |
| 746 | s.iface | 772 | s.iface |
| 747 | .set_hardware_addr(to_smoltcp_hardware_address(self.device.hardware_address())); | 773 | .set_hardware_addr(to_smoltcp_hardware_address(self.device.hardware_address())); |
| @@ -763,6 +789,9 @@ impl<D: Driver + 'static> Inner<D> { | |||
| 763 | info!("link_up = {:?}", self.link_up); | 789 | info!("link_up = {:?}", self.link_up); |
| 764 | } | 790 | } |
| 765 | 791 | ||
| 792 | #[allow(unused_mut)] | ||
| 793 | let mut apply_config = false; | ||
| 794 | |||
| 766 | #[cfg(feature = "dhcpv4")] | 795 | #[cfg(feature = "dhcpv4")] |
| 767 | if let Some(dhcp_handle) = self.dhcp_socket { | 796 | if let Some(dhcp_handle) = self.dhcp_socket { |
| 768 | let socket = s.sockets.get_mut::<dhcpv4::Socket>(dhcp_handle); | 797 | let socket = s.sockets.get_mut::<dhcpv4::Socket>(dhcp_handle); |
| @@ -770,25 +799,29 @@ impl<D: Driver + 'static> Inner<D> { | |||
| 770 | if self.link_up { | 799 | if self.link_up { |
| 771 | match socket.poll() { | 800 | match socket.poll() { |
| 772 | None => {} | 801 | None => {} |
| 773 | Some(dhcpv4::Event::Deconfigured) => self.unapply_config_v4(s), | 802 | Some(dhcpv4::Event::Deconfigured) => { |
| 803 | self.static_v4 = None; | ||
| 804 | apply_config = true; | ||
| 805 | } | ||
| 774 | Some(dhcpv4::Event::Configured(config)) => { | 806 | Some(dhcpv4::Event::Configured(config)) => { |
| 775 | let config = StaticConfigV4 { | 807 | self.static_v4 = Some(StaticConfigV4 { |
| 776 | address: config.address, | 808 | address: config.address, |
| 777 | gateway: config.router, | 809 | gateway: config.router, |
| 778 | dns_servers: config.dns_servers, | 810 | dns_servers: config.dns_servers, |
| 779 | }; | 811 | }); |
| 780 | self.apply_config_v4(s, config) | 812 | apply_config = true; |
| 781 | } | 813 | } |
| 782 | } | 814 | } |
| 783 | } else if old_link_up { | 815 | } else if old_link_up { |
| 784 | socket.reset(); | 816 | socket.reset(); |
| 785 | self.unapply_config_v4(s); | 817 | self.static_v4 = None; |
| 818 | apply_config = true; | ||
| 786 | } | 819 | } |
| 787 | } | 820 | } |
| 788 | //if old_link_up || self.link_up { | 821 | |
| 789 | // self.poll_configurator(timestamp) | 822 | if apply_config { |
| 790 | //} | 823 | self.apply_static_config(s); |
| 791 | // | 824 | } |
| 792 | 825 | ||
| 793 | if let Some(poll_at) = s.iface.poll_at(timestamp, &mut s.sockets) { | 826 | if let Some(poll_at) = s.iface.poll_at(timestamp, &mut s.sockets) { |
| 794 | let t = Timer::at(instant_from_smoltcp(poll_at)); | 827 | let t = Timer::at(instant_from_smoltcp(poll_at)); |
