aboutsummaryrefslogtreecommitdiff
path: root/embassy-net
diff options
context:
space:
mode:
authorGhaith Oueslati <[email protected]>2023-06-12 14:28:23 +0100
committerGitHub <[email protected]>2023-06-12 14:28:23 +0100
commitcf83f6820cf2c6ece607cd60cfdab9d5e47efd04 (patch)
tree6485dacac7e61c4378ac522e709edb0a86bd7523 /embassy-net
parent2dd5ce83ec0421564e85b667f5dabd592f313e5c (diff)
parent2d89cfb18f00aefbfa108728dfea3398e80ea3e4 (diff)
Merge pull request #3 from OueslatiGhaith/master
fix merge conflicts
Diffstat (limited to 'embassy-net')
-rw-r--r--embassy-net/Cargo.toml4
-rw-r--r--embassy-net/src/device.rs5
-rw-r--r--embassy-net/src/dns.rs1
-rw-r--r--embassy-net/src/lib.rs245
-rw-r--r--embassy-net/src/tcp.rs3
5 files changed, 231 insertions, 27 deletions
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index 0a47c5d94..4ac572577 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -26,7 +26,8 @@ unstable-traits = []
26udp = ["smoltcp/socket-udp"] 26udp = ["smoltcp/socket-udp"]
27tcp = ["smoltcp/socket-tcp"] 27tcp = ["smoltcp/socket-tcp"]
28dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"] 28dns = ["smoltcp/socket-dns", "smoltcp/proto-dns"]
29dhcpv4 = ["medium-ethernet", "smoltcp/socket-dhcpv4"] 29dhcpv4 = ["proto-ipv4", "medium-ethernet", "smoltcp/socket-dhcpv4"]
30proto-ipv4 = ["smoltcp/proto-ipv4"]
30proto-ipv6 = ["smoltcp/proto-ipv6"] 31proto-ipv6 = ["smoltcp/proto-ipv6"]
31medium-ethernet = ["smoltcp/medium-ethernet"] 32medium-ethernet = ["smoltcp/medium-ethernet"]
32medium-ip = ["smoltcp/medium-ip"] 33medium-ip = ["smoltcp/medium-ip"]
@@ -38,7 +39,6 @@ defmt = { version = "0.3", optional = true }
38log = { version = "0.4.14", optional = true } 39log = { version = "0.4.14", optional = true }
39 40
40smoltcp = { version = "0.9.0", default-features = false, features = [ 41smoltcp = { version = "0.9.0", default-features = false, features = [
41 "proto-ipv4",
42 "socket", 42 "socket",
43 "async", 43 "async",
44]} 44]}
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs
index 5daa00544..583cdc87f 100644
--- a/embassy-net/src/device.rs
+++ b/embassy-net/src/device.rs
@@ -59,7 +59,10 @@ where
59 smolcaps.checksum.ipv4 = convert(caps.checksum.ipv4); 59 smolcaps.checksum.ipv4 = convert(caps.checksum.ipv4);
60 smolcaps.checksum.tcp = convert(caps.checksum.tcp); 60 smolcaps.checksum.tcp = convert(caps.checksum.tcp);
61 smolcaps.checksum.udp = convert(caps.checksum.udp); 61 smolcaps.checksum.udp = convert(caps.checksum.udp);
62 smolcaps.checksum.icmpv4 = convert(caps.checksum.icmpv4); 62 #[cfg(feature = "proto-ipv4")]
63 {
64 smolcaps.checksum.icmpv4 = convert(caps.checksum.icmpv4);
65 }
63 #[cfg(feature = "proto-ipv6")] 66 #[cfg(feature = "proto-ipv6")]
64 { 67 {
65 smolcaps.checksum.icmpv6 = convert(caps.checksum.icmpv6); 68 smolcaps.checksum.icmpv6 = convert(caps.checksum.icmpv6);
diff --git a/embassy-net/src/dns.rs b/embassy-net/src/dns.rs
index 3fd235b2c..94f75f108 100644
--- a/embassy-net/src/dns.rs
+++ b/embassy-net/src/dns.rs
@@ -88,6 +88,7 @@ where
88 let addrs = self.query(host, qtype).await?; 88 let addrs = self.query(host, qtype).await?;
89 if let Some(first) = addrs.get(0) { 89 if let Some(first) = addrs.get(0) {
90 Ok(match first { 90 Ok(match first {
91 #[cfg(feature = "proto-ipv4")]
91 IpAddress::Ipv4(addr) => IpAddr::V4(addr.0.into()), 92 IpAddress::Ipv4(addr) => IpAddr::V4(addr.0.into()),
92 #[cfg(feature = "proto-ipv6")] 93 #[cfg(feature = "proto-ipv6")]
93 IpAddress::Ipv6(addr) => IpAddr::V6(addr.0.into()), 94 IpAddress::Ipv6(addr) => IpAddr::V6(addr.0.into()),
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs
index bccbad521..7e8f765f9 100644
--- a/embassy-net/src/lib.rs
+++ b/embassy-net/src/lib.rs
@@ -34,7 +34,9 @@ use smoltcp::socket::dhcpv4::{self, RetryConfig};
34pub use smoltcp::wire::IpListenEndpoint; 34pub use smoltcp::wire::IpListenEndpoint;
35#[cfg(feature = "medium-ethernet")] 35#[cfg(feature = "medium-ethernet")]
36pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; 36pub use smoltcp::wire::{EthernetAddress, HardwareAddress};
37pub use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; 37pub use smoltcp::wire::{IpAddress, IpCidr};
38#[cfg(feature = "proto-ipv4")]
39pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr};
38#[cfg(feature = "proto-ipv6")] 40#[cfg(feature = "proto-ipv6")]
39pub use smoltcp::wire::{Ipv6Address, Ipv6Cidr}; 41pub use smoltcp::wire::{Ipv6Address, Ipv6Cidr};
40 42
@@ -67,8 +69,9 @@ impl<const SOCK: usize> StackResources<SOCK> {
67} 69}
68 70
69/// Static IP address configuration. 71/// Static IP address configuration.
72#[cfg(feature = "proto-ipv4")]
70#[derive(Debug, Clone, PartialEq, Eq)] 73#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct StaticConfig { 74pub struct StaticConfigV4 {
72 /// IP address and subnet mask. 75 /// IP address and subnet mask.
73 pub address: Ipv4Cidr, 76 pub address: Ipv4Cidr,
74 /// Default gateway. 77 /// Default gateway.
@@ -77,6 +80,18 @@ pub struct StaticConfig {
77 pub dns_servers: Vec<Ipv4Address, 3>, 80 pub dns_servers: Vec<Ipv4Address, 3>,
78} 81}
79 82
83/// Static IPv6 address configuration
84#[cfg(feature = "proto-ipv6")]
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub struct StaticConfigV6 {
87 /// IP address and subnet mask.
88 pub address: Ipv6Cidr,
89 /// Default gateway.
90 pub gateway: Option<Ipv6Address>,
91 /// DNS servers.
92 pub dns_servers: Vec<Ipv6Address, 3>,
93}
94
80/// DHCP configuration. 95/// DHCP configuration.
81#[cfg(feature = "dhcpv4")] 96#[cfg(feature = "dhcpv4")]
82#[derive(Debug, Clone, PartialEq, Eq)] 97#[derive(Debug, Clone, PartialEq, Eq)]
@@ -112,12 +127,71 @@ impl Default for DhcpConfig {
112} 127}
113 128
114/// Network stack configuration. 129/// Network stack configuration.
115pub enum Config { 130pub struct Config {
116 /// Use a static IP address configuration. 131 /// IPv4 configuration
117 Static(StaticConfig), 132 #[cfg(feature = "proto-ipv4")]
133 pub ipv4: ConfigV4,
134 /// IPv6 configuration
135 #[cfg(feature = "proto-ipv6")]
136 pub ipv6: ConfigV6,
137}
138
139impl Config {
140 /// IPv4 configuration with static addressing.
141 #[cfg(feature = "proto-ipv4")]
142 pub fn ipv4_static(config: StaticConfigV4) -> Self {
143 Self {
144 ipv4: ConfigV4::Static(config),
145 #[cfg(feature = "proto-ipv6")]
146 ipv6: ConfigV6::None,
147 }
148 }
149
150 /// IPv6 configuration with static addressing.
151 #[cfg(feature = "proto-ipv6")]
152 pub fn ipv6_static(config: StaticConfigV6) -> Self {
153 Self {
154 #[cfg(feature = "proto-ipv4")]
155 ipv4: ConfigV4::None,
156 ipv6: ConfigV6::Static(config),
157 }
158 }
159
160 /// IPv6 configuration with dynamic addressing.
161 ///
162 /// # Example
163 /// ```rust
164 /// let _cfg = Config::dhcpv4(Default::default());
165 /// ```
166 #[cfg(feature = "dhcpv4")]
167 pub fn dhcpv4(config: DhcpConfig) -> Self {
168 Self {
169 ipv4: ConfigV4::Dhcp(config),
170 #[cfg(feature = "proto-ipv6")]
171 ipv6: ConfigV6::None,
172 }
173 }
174}
175
176/// Network stack IPv4 configuration.
177#[cfg(feature = "proto-ipv4")]
178pub enum ConfigV4 {
179 /// Use a static IPv4 address configuration.
180 Static(StaticConfigV4),
118 /// Use DHCP to obtain an IP address configuration. 181 /// Use DHCP to obtain an IP address configuration.
119 #[cfg(feature = "dhcpv4")] 182 #[cfg(feature = "dhcpv4")]
120 Dhcp(DhcpConfig), 183 Dhcp(DhcpConfig),
184 /// Do not configure IPv6.
185 None,
186}
187
188/// Network stack IPv6 configuration.
189#[cfg(feature = "proto-ipv6")]
190pub enum ConfigV6 {
191 /// Use a static IPv6 address configuration.
192 Static(StaticConfigV6),
193 /// Do not configure IPv6.
194 None,
121} 195}
122 196
123/// A network stack. 197/// A network stack.
@@ -131,7 +205,10 @@ pub struct Stack<D: Driver> {
131struct Inner<D: Driver> { 205struct Inner<D: Driver> {
132 device: D, 206 device: D,
133 link_up: bool, 207 link_up: bool,
134 config: Option<StaticConfig>, 208 #[cfg(feature = "proto-ipv4")]
209 static_v4: Option<StaticConfigV4>,
210 #[cfg(feature = "proto-ipv6")]
211 static_v6: Option<StaticConfigV6>,
135 #[cfg(feature = "dhcpv4")] 212 #[cfg(feature = "dhcpv4")]
136 dhcp_socket: Option<SocketHandle>, 213 dhcp_socket: Option<SocketHandle>,
137 #[cfg(feature = "dns")] 214 #[cfg(feature = "dns")]
@@ -187,7 +264,10 @@ impl<D: Driver + 'static> Stack<D> {
187 let mut inner = Inner { 264 let mut inner = Inner {
188 device, 265 device,
189 link_up: false, 266 link_up: false,
190 config: None, 267 #[cfg(feature = "proto-ipv4")]
268 static_v4: None,
269 #[cfg(feature = "proto-ipv6")]
270 static_v6: None,
191 #[cfg(feature = "dhcpv4")] 271 #[cfg(feature = "dhcpv4")]
192 dhcp_socket: None, 272 dhcp_socket: None,
193 #[cfg(feature = "dns")] 273 #[cfg(feature = "dns")]
@@ -199,17 +279,26 @@ impl<D: Driver + 'static> Stack<D> {
199 dns_waker: WakerRegistration::new(), 279 dns_waker: WakerRegistration::new(),
200 }; 280 };
201 281
202 match config { 282 #[cfg(feature = "proto-ipv4")]
203 Config::Static(config) => { 283 match config.ipv4 {
204 inner.apply_config(&mut socket, config); 284 ConfigV4::Static(config) => {
285 inner.apply_config_v4(&mut socket, config);
205 } 286 }
206 #[cfg(feature = "dhcpv4")] 287 #[cfg(feature = "dhcpv4")]
207 Config::Dhcp(config) => { 288 ConfigV4::Dhcp(config) => {
208 let mut dhcp_socket = smoltcp::socket::dhcpv4::Socket::new(); 289 let mut dhcp_socket = smoltcp::socket::dhcpv4::Socket::new();
209 inner.apply_dhcp_config(&mut dhcp_socket, config); 290 inner.apply_dhcp_config(&mut dhcp_socket, config);
210 let handle = socket.sockets.add(dhcp_socket); 291 let handle = socket.sockets.add(dhcp_socket);
211 inner.dhcp_socket = Some(handle); 292 inner.dhcp_socket = Some(handle);
212 } 293 }
294 ConfigV4::None => {}
295 }
296 #[cfg(feature = "proto-ipv6")]
297 match config.ipv6 {
298 ConfigV6::Static(config) => {
299 inner.apply_config_v6(&mut socket, config);
300 }
301 ConfigV6::None => {}
213 } 302 }
214 303
215 Self { 304 Self {
@@ -239,12 +328,40 @@ impl<D: Driver + 'static> Stack<D> {
239 /// Get whether the network stack has a valid IP configuration. 328 /// Get whether the network stack has a valid IP configuration.
240 /// This is true if the network stack has a static IP configuration or if DHCP has completed 329 /// This is true if the network stack has a static IP configuration or if DHCP has completed
241 pub fn is_config_up(&self) -> bool { 330 pub fn is_config_up(&self) -> bool {
242 self.with(|_s, i| i.config.is_some()) 331 let v4_up;
332 let v6_up;
333
334 #[cfg(feature = "proto-ipv4")]
335 {
336 v4_up = self.config_v4().is_some();
337 }
338 #[cfg(not(feature = "proto-ipv4"))]
339 {
340 v4_up = false;
341 }
342
343 #[cfg(feature = "proto-ipv6")]
344 {
345 v6_up = self.config_v6().is_some();
346 }
347 #[cfg(not(feature = "proto-ipv6"))]
348 {
349 v6_up = false;
350 }
351
352 v4_up || v6_up
243 } 353 }
244 354
245 /// Get the current IP configuration. 355 /// Get the current IPv4 configuration.
246 pub fn config(&self) -> Option<StaticConfig> { 356 #[cfg(feature = "proto-ipv4")]
247 self.with(|_s, i| i.config.clone()) 357 pub fn config_v4(&self) -> Option<StaticConfigV4> {
358 self.with(|_s, i| i.static_v4.clone())
359 }
360
361 /// Get the current IPv6 configuration.
362 #[cfg(feature = "proto-ipv6")]
363 pub fn config_v6(&self) -> Option<StaticConfigV6> {
364 self.with(|_s, i| i.static_v6.clone())
248 } 365 }
249 366
250 /// Run the network stack. 367 /// Run the network stack.
@@ -264,6 +381,7 @@ impl<D: Driver + 'static> Stack<D> {
264 pub async fn dns_query(&self, name: &str, qtype: dns::DnsQueryType) -> Result<Vec<IpAddress, 1>, dns::Error> { 381 pub async fn dns_query(&self, name: &str, qtype: dns::DnsQueryType) -> Result<Vec<IpAddress, 1>, dns::Error> {
265 // For A and AAAA queries we try detect whether `name` is just an IP address 382 // For A and AAAA queries we try detect whether `name` is just an IP address
266 match qtype { 383 match qtype {
384 #[cfg(feature = "proto-ipv4")]
267 dns::DnsQueryType::A => { 385 dns::DnsQueryType::A => {
268 if let Ok(ip) = name.parse().map(IpAddress::Ipv4) { 386 if let Ok(ip) = name.parse().map(IpAddress::Ipv4) {
269 return Ok([ip].into_iter().collect()); 387 return Ok([ip].into_iter().collect());
@@ -374,7 +492,8 @@ impl SocketStack {
374} 492}
375 493
376impl<D: Driver + 'static> Inner<D> { 494impl<D: Driver + 'static> Inner<D> {
377 fn apply_config(&mut self, s: &mut SocketStack, config: StaticConfig) { 495 #[cfg(feature = "proto-ipv4")]
496 fn apply_config_v4(&mut self, s: &mut SocketStack, config: StaticConfigV4) {
378 #[cfg(feature = "medium-ethernet")] 497 #[cfg(feature = "medium-ethernet")]
379 let medium = self.device.capabilities().medium; 498 let medium = self.device.capabilities().medium;
380 499
@@ -403,14 +522,86 @@ impl<D: Driver + 'static> Inner<D> {
403 debug!(" DNS server {}: {}", i, s); 522 debug!(" DNS server {}: {}", i, s);
404 } 523 }
405 524
525 self.static_v4 = Some(config);
526
406 #[cfg(feature = "dns")] 527 #[cfg(feature = "dns")]
407 { 528 {
408 let socket = s.sockets.get_mut::<smoltcp::socket::dns::Socket>(self.dns_socket); 529 self.update_dns_servers(s)
409 let servers: Vec<IpAddress, 3> = config.dns_servers.iter().map(|c| IpAddress::Ipv4(*c)).collect(); 530 }
410 socket.update_servers(&servers[..]); 531 }
532
533 /// Replaces the current IPv6 static configuration with a newly supplied config.
534 #[cfg(feature = "proto-ipv6")]
535 fn apply_config_v6(&mut self, s: &mut SocketStack, config: StaticConfigV6) {
536 #[cfg(feature = "medium-ethernet")]
537 let medium = self.device.capabilities().medium;
538
539 debug!("Acquired IPv6 configuration:");
540
541 debug!(" IP address: {}", config.address);
542 s.iface.update_ip_addrs(|addrs| {
543 if addrs.is_empty() {
544 addrs.push(IpCidr::Ipv6(config.address)).unwrap();
545 } else {
546 addrs[0] = IpCidr::Ipv6(config.address);
547 }
548 });
549
550 #[cfg(feature = "medium-ethernet")]
551 if Medium::Ethernet == medium {
552 if let Some(gateway) = config.gateway {
553 debug!(" Default gateway: {}", gateway);
554 s.iface.routes_mut().add_default_ipv6_route(gateway).unwrap();
555 } else {
556 debug!(" Default gateway: None");
557 s.iface.routes_mut().remove_default_ipv6_route();
558 }
559 }
560 for (i, s) in config.dns_servers.iter().enumerate() {
561 debug!(" DNS server {}: {}", i, s);
411 } 562 }
412 563
413 self.config = Some(config) 564 self.static_v6 = Some(config);
565
566 #[cfg(feature = "dns")]
567 {
568 self.update_dns_servers(s)
569 }
570 }
571
572 #[cfg(feature = "dns")]
573 fn update_dns_servers(&mut self, s: &mut SocketStack) {
574 let socket = s.sockets.get_mut::<smoltcp::socket::dns::Socket>(self.dns_socket);
575
576 let servers_v4;
577 #[cfg(feature = "proto-ipv4")]
578 {
579 servers_v4 = self
580 .static_v4
581 .iter()
582 .flat_map(|cfg| cfg.dns_servers.iter().map(|c| IpAddress::Ipv4(*c)));
583 };
584 #[cfg(not(feature = "proto-ipv4"))]
585 {
586 servers_v4 = core::iter::empty();
587 }
588
589 let servers_v6;
590 #[cfg(feature = "proto-ipv6")]
591 {
592 servers_v6 = self
593 .static_v6
594 .iter()
595 .flat_map(|cfg| cfg.dns_servers.iter().map(|c| IpAddress::Ipv6(*c)));
596 }
597 #[cfg(not(feature = "proto-ipv6"))]
598 {
599 servers_v6 = core::iter::empty();
600 }
601
602 // Prefer the v6 DNS servers over the v4 servers
603 let servers: Vec<IpAddress, 6> = servers_v6.chain(servers_v4).collect();
604 socket.update_servers(&servers[..]);
414 } 605 }
415 606
416 #[cfg(feature = "dhcpv4")] 607 #[cfg(feature = "dhcpv4")]
@@ -430,9 +621,15 @@ impl<D: Driver + 'static> Inner<D> {
430 s.iface.update_ip_addrs(|ip_addrs| ip_addrs.clear()); 621 s.iface.update_ip_addrs(|ip_addrs| ip_addrs.clear());
431 #[cfg(feature = "medium-ethernet")] 622 #[cfg(feature = "medium-ethernet")]
432 if medium == Medium::Ethernet { 623 if medium == Medium::Ethernet {
433 s.iface.routes_mut().remove_default_ipv4_route(); 624 #[cfg(feature = "proto-ipv4")]
625 {
626 s.iface.routes_mut().remove_default_ipv4_route();
627 }
628 }
629 #[cfg(feature = "proto-ipv4")]
630 {
631 self.static_v4 = None
434 } 632 }
435 self.config = None
436 } 633 }
437 634
438 fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { 635 fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) {
@@ -470,12 +667,12 @@ impl<D: Driver + 'static> Inner<D> {
470 None => {} 667 None => {}
471 Some(dhcpv4::Event::Deconfigured) => self.unapply_config(s), 668 Some(dhcpv4::Event::Deconfigured) => self.unapply_config(s),
472 Some(dhcpv4::Event::Configured(config)) => { 669 Some(dhcpv4::Event::Configured(config)) => {
473 let config = StaticConfig { 670 let config = StaticConfigV4 {
474 address: config.address, 671 address: config.address,
475 gateway: config.router, 672 gateway: config.router,
476 dns_servers: config.dns_servers, 673 dns_servers: config.dns_servers,
477 }; 674 };
478 self.apply_config(s, config) 675 self.apply_config_v4(s, config)
479 } 676 }
480 } 677 }
481 } else if old_link_up { 678 } else if old_link_up {
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs
index 515bbc5be..367675b13 100644
--- a/embassy-net/src/tcp.rs
+++ b/embassy-net/src/tcp.rs
@@ -480,7 +480,10 @@ pub mod client {
480 Self: 'a, 480 Self: 'a,
481 { 481 {
482 let addr: crate::IpAddress = match remote.ip() { 482 let addr: crate::IpAddress = match remote.ip() {
483 #[cfg(feature = "proto-ipv4")]
483 IpAddr::V4(addr) => crate::IpAddress::Ipv4(crate::Ipv4Address::from_bytes(&addr.octets())), 484 IpAddr::V4(addr) => crate::IpAddress::Ipv4(crate::Ipv4Address::from_bytes(&addr.octets())),
485 #[cfg(not(feature = "proto-ipv4"))]
486 IpAddr::V4(_) => panic!("ipv4 support not enabled"),
484 #[cfg(feature = "proto-ipv6")] 487 #[cfg(feature = "proto-ipv6")]
485 IpAddr::V6(addr) => crate::IpAddress::Ipv6(crate::Ipv6Address::from_bytes(&addr.octets())), 488 IpAddr::V6(addr) => crate::IpAddress::Ipv6(crate::Ipv6Address::from_bytes(&addr.octets())),
486 #[cfg(not(feature = "proto-ipv6"))] 489 #[cfg(not(feature = "proto-ipv6"))]