diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-04-07 19:06:45 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-04-07 19:06:45 +0200 |
| commit | 9c5a8b945a743e75d586fdc2ef857d7c2a038e7d (patch) | |
| tree | c7e4c88840281b3b54fbda466c717a83094f8121 | |
| parent | 9bee576fd241f019c363919b0c29551c6b8ee4b2 (diff) | |
Update to latest embassy, atomic-pool, smoltcp
| -rw-r--r-- | Cargo.toml | 10 | ||||
| -rw-r--r-- | embassy-net-examples/Cargo.toml | 5 | ||||
| -rw-r--r-- | embassy-net-examples/src/main.rs | 36 | ||||
| -rw-r--r-- | embassy-net-examples/src/tuntap.rs | 35 | ||||
| -rw-r--r-- | embassy-net/Cargo.toml | 10 | ||||
| -rw-r--r-- | embassy-net/src/config/dhcp.rs | 75 | ||||
| -rw-r--r-- | embassy-net/src/config/mod.rs | 30 | ||||
| -rw-r--r-- | embassy-net/src/config/statik.rs | 19 | ||||
| -rw-r--r-- | embassy-net/src/device.rs | 1 | ||||
| -rw-r--r-- | embassy-net/src/lib.rs | 13 | ||||
| -rw-r--r-- | embassy-net/src/packet_pool.rs | 10 | ||||
| -rw-r--r-- | embassy-net/src/pool.rs | 245 | ||||
| -rw-r--r-- | embassy-net/src/stack.rs | 77 |
13 files changed, 185 insertions, 381 deletions
diff --git a/Cargo.toml b/Cargo.toml index 7ab99c2e9..8ed84db99 100644 --- a/Cargo.toml +++ b/Cargo.toml | |||
| @@ -42,8 +42,8 @@ opt-level = 0 | |||
| 42 | overflow-checks = false | 42 | overflow-checks = false |
| 43 | 43 | ||
| 44 | [patch.crates-io] | 44 | [patch.crates-io] |
| 45 | embassy = { git = "https://github.com/akiles/embassy" } | 45 | embassy = { git = "https://github.com/embassy-rs/embassy" } |
| 46 | embassy-std = { git = "https://github.com/akiles/embassy" } | 46 | embassy-std = { git = "https://github.com/embassy-rs/embassy" } |
| 47 | embassy-macros = { git = "https://github.com/akiles/embassy" } | 47 | embassy-macros = { git = "https://github.com/embassy-rs/embassy" } |
| 48 | embassy-traits = { git = "https://github.com/akiles/embassy" } | 48 | embassy-traits = { git = "https://github.com/embassy-rs/embassy" } |
| 49 | smoltcp = { git = "https://github.com/akiles/smoltcp" } \ No newline at end of file | 49 | smoltcp = { git = "https://github.com/smoltcp-rs/smoltcp", rev="9ce3d9505ef5455bb049713b9262561d78ebf330" } \ No newline at end of file |
diff --git a/embassy-net-examples/Cargo.toml b/embassy-net-examples/Cargo.toml index 944e91914..796c44745 100644 --- a/embassy-net-examples/Cargo.toml +++ b/embassy-net-examples/Cargo.toml | |||
| @@ -8,10 +8,11 @@ edition = "2018" | |||
| 8 | heapless = { version = "0.5.6", default-features = false } | 8 | heapless = { version = "0.5.6", default-features = false } |
| 9 | embassy = { version = "0.1.0", features=["std", "log"] } | 9 | embassy = { version = "0.1.0", features=["std", "log"] } |
| 10 | embassy-std = { version = "0.1.0" } | 10 | embassy-std = { version = "0.1.0" } |
| 11 | embassy-net = { version = "0.1.0", path = "../embassy-net", features=["std", "log"] } | 11 | embassy-net = { version = "0.1.0", path = "../embassy-net", features=["std", "log", "tcp", "dhcpv4"] } |
| 12 | env_logger = "0.8.2" | 12 | env_logger = "0.8.2" |
| 13 | log = "0.4.11" | 13 | log = "0.4.11" |
| 14 | futures = "0.3.8" | 14 | futures = "0.3.8" |
| 15 | libc = "0.2.81" | 15 | libc = "0.2.81" |
| 16 | async-io = "1.3.1" | 16 | async-io = "1.3.1" |
| 17 | smoltcp = { version = "0.6.0", default-features = false } | 17 | smoltcp = { version = "0.7.0", default-features = false } |
| 18 | clap = { version = "3.0.0-beta.2", features = ["derive"] } \ No newline at end of file | ||
diff --git a/embassy-net-examples/src/main.rs b/embassy-net-examples/src/main.rs index dba1415b7..c157ea34e 100644 --- a/embassy-net-examples/src/main.rs +++ b/embassy-net-examples/src/main.rs | |||
| @@ -1,6 +1,10 @@ | |||
| 1 | #![feature(type_alias_impl_trait)] | 1 | #![feature(type_alias_impl_trait)] |
| 2 | #![feature(min_type_alias_impl_trait)] | ||
| 3 | #![feature(impl_trait_in_bindings)] | ||
| 4 | #![allow(incomplete_features)] | ||
| 2 | 5 | ||
| 3 | use embassy::executor::{task, Spawner}; | 6 | use clap::{AppSettings, Clap}; |
| 7 | use embassy::executor::Spawner; | ||
| 4 | use embassy::io::AsyncWriteExt; | 8 | use embassy::io::AsyncWriteExt; |
| 5 | use embassy::util::Forever; | 9 | use embassy::util::Forever; |
| 6 | use embassy_net::*; | 10 | use embassy_net::*; |
| @@ -13,25 +17,39 @@ mod tuntap; | |||
| 13 | use crate::tuntap::TunTapDevice; | 17 | use crate::tuntap::TunTapDevice; |
| 14 | 18 | ||
| 15 | static DEVICE: Forever<TunTapDevice> = Forever::new(); | 19 | static DEVICE: Forever<TunTapDevice> = Forever::new(); |
| 16 | static CONFIG: Forever<StaticConfigurator> = Forever::new(); | 20 | static CONFIG: Forever<DhcpConfigurator> = Forever::new(); |
| 17 | 21 | ||
| 18 | #[task] | 22 | #[derive(Clap)] |
| 23 | #[clap(version = "1.0")] | ||
| 24 | #[clap(setting = AppSettings::ColoredHelp)] | ||
| 25 | struct Opts { | ||
| 26 | /// TAP device name | ||
| 27 | #[clap(long, default_value = "tap0")] | ||
| 28 | tap: String, | ||
| 29 | } | ||
| 30 | |||
| 31 | #[embassy::task] | ||
| 19 | async fn net_task() { | 32 | async fn net_task() { |
| 20 | embassy_net::run().await | 33 | embassy_net::run().await |
| 21 | } | 34 | } |
| 22 | 35 | ||
| 23 | #[task] | 36 | #[embassy::task] |
| 24 | async fn main_task(spawner: Spawner) { | 37 | async fn main_task(spawner: Spawner) { |
| 38 | let opts: Opts = Opts::parse(); | ||
| 39 | |||
| 25 | // Init network device | 40 | // Init network device |
| 26 | let device = TunTapDevice::new("tap0").unwrap(); | 41 | let device = TunTapDevice::new(&opts.tap).unwrap(); |
| 27 | 42 | ||
| 28 | // Static IP configuration | 43 | // Static IP configuration |
| 29 | let config = StaticConfigurator::new(UpConfig { | 44 | let config = StaticConfigurator::new(Config { |
| 30 | address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 1), 24), | 45 | address: Ipv4Cidr::new(Ipv4Address::new(192, 168, 69, 2), 24), |
| 31 | dns_servers: Vec::new(), | 46 | dns_servers: Vec::new(), |
| 32 | gateway: Ipv4Address::new(192, 168, 69, 100), | 47 | gateway: Some(Ipv4Address::new(192, 168, 69, 1)), |
| 33 | }); | 48 | }); |
| 34 | 49 | ||
| 50 | // DHCP configruation | ||
| 51 | let config = DhcpConfigurator::new(); | ||
| 52 | |||
| 35 | // Init network stack | 53 | // Init network stack |
| 36 | embassy_net::init(DEVICE.put(device), CONFIG.put(config)); | 54 | embassy_net::init(DEVICE.put(device), CONFIG.put(config)); |
| 37 | 55 | ||
| @@ -45,7 +63,7 @@ async fn main_task(spawner: Spawner) { | |||
| 45 | 63 | ||
| 46 | socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); | 64 | socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); |
| 47 | 65 | ||
| 48 | let remote_endpoint = (Ipv4Address::new(192, 168, 69, 100), 8000); | 66 | let remote_endpoint = (Ipv4Address::new(192, 168, 69, 74), 8000); |
| 49 | info!("connecting to {:?}...", remote_endpoint); | 67 | info!("connecting to {:?}...", remote_endpoint); |
| 50 | let r = socket.connect(remote_endpoint).await; | 68 | let r = socket.connect(remote_endpoint).await; |
| 51 | if let Err(e) = r { | 69 | if let Err(e) = r { |
diff --git a/embassy-net-examples/src/tuntap.rs b/embassy-net-examples/src/tuntap.rs index b2117e81b..dd453deb3 100644 --- a/embassy-net-examples/src/tuntap.rs +++ b/embassy-net-examples/src/tuntap.rs | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | use async_io::Async; | 1 | use async_io::Async; |
| 2 | use embassy::util::WakerRegistration; | ||
| 3 | use libc; | 2 | use libc; |
| 4 | use log::*; | 3 | use log::*; |
| 5 | use smoltcp::wire::EthernetFrame; | 4 | use smoltcp::wire::EthernetFrame; |
| @@ -130,20 +129,21 @@ impl io::Write for TunTap { | |||
| 130 | 129 | ||
| 131 | pub struct TunTapDevice { | 130 | pub struct TunTapDevice { |
| 132 | device: Async<TunTap>, | 131 | device: Async<TunTap>, |
| 133 | waker: WakerRegistration, | 132 | waker: Option<Waker>, |
| 134 | } | 133 | } |
| 135 | 134 | ||
| 136 | impl TunTapDevice { | 135 | impl TunTapDevice { |
| 137 | pub fn new(name: &str) -> io::Result<TunTapDevice> { | 136 | pub fn new(name: &str) -> io::Result<TunTapDevice> { |
| 138 | Ok(Self { | 137 | Ok(Self { |
| 139 | device: Async::new(TunTap::new(name)?)?, | 138 | device: Async::new(TunTap::new(name)?)?, |
| 140 | waker: WakerRegistration::new(), | 139 | waker: None, |
| 141 | }) | 140 | }) |
| 142 | } | 141 | } |
| 143 | } | 142 | } |
| 144 | 143 | ||
| 145 | use core::task::Waker; | 144 | use core::task::Waker; |
| 146 | use embassy_net::{DeviceCapabilities, LinkState, Packet, PacketBox, PacketBuf}; | 145 | use embassy_net::{DeviceCapabilities, LinkState, Packet, PacketBox, PacketBoxExt, PacketBuf}; |
| 146 | use std::task::Context; | ||
| 147 | 147 | ||
| 148 | impl crate::Device for TunTapDevice { | 148 | impl crate::Device for TunTapDevice { |
| 149 | fn is_transmit_ready(&mut self) -> bool { | 149 | fn is_transmit_ready(&mut self) -> bool { |
| @@ -169,7 +169,8 @@ impl crate::Device for TunTapDevice { | |||
| 169 | return Some(pkt.slice(0..n)); | 169 | return Some(pkt.slice(0..n)); |
| 170 | } | 170 | } |
| 171 | Err(e) if e.kind() == io::ErrorKind::WouldBlock => { | 171 | Err(e) if e.kind() == io::ErrorKind::WouldBlock => { |
| 172 | let ready = if let Some(mut cx) = self.waker.context() { | 172 | let ready = if let Some(w) = self.waker.as_ref() { |
| 173 | let mut cx = Context::from_waker(w); | ||
| 173 | let ready = self.device.poll_readable(&mut cx).is_ready(); | 174 | let ready = self.device.poll_readable(&mut cx).is_ready(); |
| 174 | ready | 175 | ready |
| 175 | } else { | 176 | } else { |
| @@ -184,8 +185,28 @@ impl crate::Device for TunTapDevice { | |||
| 184 | } | 185 | } |
| 185 | } | 186 | } |
| 186 | 187 | ||
| 187 | fn register_waker(&mut self, waker: &Waker) { | 188 | fn register_waker(&mut self, w: &Waker) { |
| 188 | self.waker.register(waker) | 189 | match self.waker { |
| 190 | // Optimization: If both the old and new Wakers wake the same task, we can simply | ||
| 191 | // keep the old waker, skipping the clone. (In most executor implementations, | ||
| 192 | // cloning a waker is somewhat expensive, comparable to cloning an Arc). | ||
| 193 | Some(ref w2) if (w2.will_wake(w)) => {} | ||
| 194 | _ => { | ||
| 195 | // clone the new waker and store it | ||
| 196 | if let Some(old_waker) = core::mem::replace(&mut self.waker, Some(w.clone())) { | ||
| 197 | // We had a waker registered for another task. Wake it, so the other task can | ||
| 198 | // reregister itself if it's still interested. | ||
| 199 | // | ||
| 200 | // If two tasks are waiting on the same thing concurrently, this will cause them | ||
| 201 | // to wake each other in a loop fighting over this WakerRegistration. This wastes | ||
| 202 | // CPU but things will still work. | ||
| 203 | // | ||
| 204 | // If the user wants to have two tasks waiting on the same thing they should use | ||
| 205 | // a more appropriate primitive that can store multiple wakers. | ||
| 206 | old_waker.wake() | ||
| 207 | } | ||
| 208 | } | ||
| 209 | } | ||
| 189 | } | 210 | } |
| 190 | 211 | ||
| 191 | fn capabilities(&mut self) -> DeviceCapabilities { | 212 | fn capabilities(&mut self) -> DeviceCapabilities { |
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml index de625018c..dccd7984d 100644 --- a/embassy-net/Cargo.toml +++ b/embassy-net/Cargo.toml | |||
| @@ -12,6 +12,9 @@ defmt-info = [] | |||
| 12 | defmt-warn = [] | 12 | defmt-warn = [] |
| 13 | defmt-error = [] | 13 | defmt-error = [] |
| 14 | 14 | ||
| 15 | tcp = ["smoltcp/socket-tcp"] | ||
| 16 | dhcpv4 = ["smoltcp/socket-dhcpv4"] | ||
| 17 | |||
| 15 | [dependencies] | 18 | [dependencies] |
| 16 | 19 | ||
| 17 | defmt = { version = "0.2.0", optional = true } | 20 | defmt = { version = "0.2.0", optional = true } |
| @@ -25,9 +28,10 @@ as-slice = { version = "0.1.4" } | |||
| 25 | generic-array = { version = "0.14.4", default-features = false } | 28 | generic-array = { version = "0.14.4", default-features = false } |
| 26 | stable_deref_trait = { version = "1.2.0", default-features = false } | 29 | stable_deref_trait = { version = "1.2.0", default-features = false } |
| 27 | futures = { version = "0.3.5", default-features = false, features = [ "async-await" ]} | 30 | futures = { version = "0.3.5", default-features = false, features = [ "async-await" ]} |
| 31 | atomic-pool = "0.1.0" | ||
| 28 | 32 | ||
| 29 | [dependencies.smoltcp] | 33 | [dependencies.smoltcp] |
| 30 | version = "0.6.0" | 34 | version = "0.7.0" |
| 31 | #git = "https://github.com/akiles/smoltcp" | 35 | #git = "https://github.com/akiles/smoltcp" |
| 32 | #rev = "00952e2c5cdf5667a1dfb6142258055f58d3851c" | 36 | #rev = "00952e2c5cdf5667a1dfb6142258055f58d3851c" |
| 33 | default-features = false | 37 | default-features = false |
| @@ -35,12 +39,12 @@ features = [ | |||
| 35 | "medium-ethernet", | 39 | "medium-ethernet", |
| 36 | "medium-ip", | 40 | "medium-ip", |
| 37 | "proto-ipv4", | 41 | "proto-ipv4", |
| 38 | "proto-dhcpv4", | 42 | #"proto-dhcpv4", |
| 39 | #"proto-igmp", | 43 | #"proto-igmp", |
| 40 | #"proto-ipv6", | 44 | #"proto-ipv6", |
| 41 | #"socket-raw", | 45 | #"socket-raw", |
| 42 | #"socket-icmp", | 46 | #"socket-icmp", |
| 43 | #"socket-udp", | 47 | #"socket-udp", |
| 44 | "socket-tcp", | 48 | #"socket-tcp", |
| 45 | "async", | 49 | "async", |
| 46 | ] | 50 | ] |
diff --git a/embassy-net/src/config/dhcp.rs b/embassy-net/src/config/dhcp.rs index 0df67baf5..007c398b3 100644 --- a/embassy-net/src/config/dhcp.rs +++ b/embassy-net/src/config/dhcp.rs | |||
| @@ -1,80 +1,59 @@ | |||
| 1 | use embassy::util::Forever; | ||
| 2 | use heapless::Vec; | 1 | use heapless::Vec; |
| 3 | use smoltcp::dhcp::Dhcpv4Client; | 2 | use smoltcp::socket::{Dhcpv4Event, Dhcpv4Socket, SocketHandle}; |
| 4 | use smoltcp::socket::{RawPacketMetadata, RawSocketBuffer}; | ||
| 5 | use smoltcp::time::Instant; | 3 | use smoltcp::time::Instant; |
| 6 | use smoltcp::wire::Ipv4Address; | ||
| 7 | 4 | ||
| 8 | use super::*; | 5 | use super::*; |
| 9 | use crate::device::LinkState; | 6 | use crate::device::LinkState; |
| 10 | use crate::fmt::*; | 7 | use crate::fmt::*; |
| 11 | use crate::{Interface, SocketSet}; | 8 | use crate::{Interface, SocketSet}; |
| 12 | 9 | ||
| 13 | pub struct DhcpResources { | ||
| 14 | rx_buffer: [u8; 900], | ||
| 15 | tx_buffer: [u8; 600], | ||
| 16 | rx_meta: [RawPacketMetadata; 1], | ||
| 17 | tx_meta: [RawPacketMetadata; 1], | ||
| 18 | } | ||
| 19 | |||
| 20 | pub struct DhcpConfigurator { | 10 | pub struct DhcpConfigurator { |
| 21 | client: Option<Dhcpv4Client>, | 11 | handle: Option<SocketHandle>, |
| 22 | } | 12 | } |
| 23 | 13 | ||
| 24 | impl DhcpConfigurator { | 14 | impl DhcpConfigurator { |
| 25 | pub fn new() -> Self { | 15 | pub fn new() -> Self { |
| 26 | Self { client: None } | 16 | Self { handle: None } |
| 27 | } | 17 | } |
| 28 | } | 18 | } |
| 29 | 19 | ||
| 30 | static DHCP_RESOURCES: Forever<DhcpResources> = Forever::new(); | ||
| 31 | |||
| 32 | impl Configurator for DhcpConfigurator { | 20 | impl Configurator for DhcpConfigurator { |
| 33 | fn poll( | 21 | fn poll( |
| 34 | &mut self, | 22 | &mut self, |
| 35 | iface: &mut Interface, | 23 | iface: &mut Interface, |
| 36 | sockets: &mut SocketSet, | 24 | sockets: &mut SocketSet, |
| 37 | timestamp: Instant, | 25 | _timestamp: Instant, |
| 38 | ) -> Option<Config> { | 26 | ) -> Event { |
| 39 | if self.client.is_none() { | 27 | if self.handle.is_none() { |
| 40 | let res = DHCP_RESOURCES.put(DhcpResources { | 28 | let handle = sockets.add(Dhcpv4Socket::new()); |
| 41 | rx_buffer: [0; 900], | 29 | self.handle = Some(handle) |
| 42 | tx_buffer: [0; 600], | ||
| 43 | rx_meta: [RawPacketMetadata::EMPTY; 1], | ||
| 44 | tx_meta: [RawPacketMetadata::EMPTY; 1], | ||
| 45 | }); | ||
| 46 | let rx_buffer = RawSocketBuffer::new(&mut res.rx_meta[..], &mut res.rx_buffer[..]); | ||
| 47 | let tx_buffer = RawSocketBuffer::new(&mut res.tx_meta[..], &mut res.tx_buffer[..]); | ||
| 48 | let dhcp = Dhcpv4Client::new(sockets, rx_buffer, tx_buffer, timestamp); | ||
| 49 | info!("created dhcp"); | ||
| 50 | self.client = Some(dhcp) | ||
| 51 | } | 30 | } |
| 52 | 31 | ||
| 53 | let client = self.client.as_mut().unwrap(); | 32 | let mut socket = sockets.get::<Dhcpv4Socket>(self.handle.unwrap()); |
| 54 | 33 | ||
| 55 | let link_up = iface.device_mut().device.link_state() == LinkState::Up; | 34 | let link_up = iface.device_mut().device.link_state() == LinkState::Up; |
| 56 | if !link_up { | 35 | if !link_up { |
| 57 | client.reset(timestamp); | 36 | socket.reset(); |
| 58 | return Some(Config::Down); | 37 | return Event::Deconfigured; |
| 59 | } | 38 | } |
| 60 | 39 | ||
| 61 | let config = client.poll(iface, sockets, timestamp).unwrap_or(None)?; | 40 | match socket.poll() { |
| 62 | 41 | Dhcpv4Event::NoChange => Event::NoChange, | |
| 63 | if config.address.is_none() { | 42 | Dhcpv4Event::Deconfigured => Event::Deconfigured, |
| 64 | return Some(Config::Down); | 43 | Dhcpv4Event::Configured(config) => { |
| 65 | } | 44 | let mut dns_servers = Vec::new(); |
| 66 | 45 | for s in &config.dns_servers { | |
| 67 | let mut dns_servers = Vec::new(); | 46 | if let Some(addr) = s { |
| 68 | for s in &config.dns_servers { | 47 | dns_servers.push(addr.clone()).unwrap(); |
| 69 | if let Some(addr) = s { | 48 | } |
| 70 | dns_servers.push(addr.clone()).unwrap(); | 49 | } |
| 50 | |||
| 51 | Event::Configured(Config { | ||
| 52 | address: config.address, | ||
| 53 | gateway: config.router, | ||
| 54 | dns_servers, | ||
| 55 | }) | ||
| 71 | } | 56 | } |
| 72 | } | 57 | } |
| 73 | |||
| 74 | return Some(Config::Up(UpConfig { | ||
| 75 | address: config.address.unwrap(), | ||
| 76 | gateway: config.router.unwrap_or(Ipv4Address::UNSPECIFIED), | ||
| 77 | dns_servers, | ||
| 78 | })); | ||
| 79 | } | 58 | } |
| 80 | } | 59 | } |
diff --git a/embassy-net/src/config/mod.rs b/embassy-net/src/config/mod.rs index 596374f9e..a090aaacf 100644 --- a/embassy-net/src/config/mod.rs +++ b/embassy-net/src/config/mod.rs | |||
| @@ -6,29 +6,33 @@ use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; | |||
| 6 | use crate::fmt::*; | 6 | use crate::fmt::*; |
| 7 | use crate::{Interface, SocketSet}; | 7 | use crate::{Interface, SocketSet}; |
| 8 | 8 | ||
| 9 | mod dhcp; | ||
| 10 | mod statik; | 9 | mod statik; |
| 11 | pub use dhcp::DhcpConfigurator; | ||
| 12 | pub use statik::StaticConfigurator; | 10 | pub use statik::StaticConfigurator; |
| 13 | 11 | ||
| 12 | #[cfg(feature = "dhcpv4")] | ||
| 13 | mod dhcp; | ||
| 14 | #[cfg(feature = "dhcpv4")] | ||
| 15 | pub use dhcp::DhcpConfigurator; | ||
| 16 | |||
| 17 | /// Return value for the `Configurator::poll` function | ||
| 14 | #[derive(Debug, Clone)] | 18 | #[derive(Debug, Clone)] |
| 15 | pub enum Config { | 19 | pub enum Event { |
| 16 | Down, | 20 | /// No change has occured to the configuration. |
| 17 | Up(UpConfig), | 21 | NoChange, |
| 22 | /// Configuration has been lost (for example, DHCP lease has expired) | ||
| 23 | Deconfigured, | ||
| 24 | /// Configuration has been newly acquired, or modified. | ||
| 25 | Configured(Config), | ||
| 18 | } | 26 | } |
| 19 | 27 | ||
| 20 | #[derive(Debug, Clone)] | 28 | #[derive(Debug, Clone)] |
| 21 | pub struct UpConfig { | 29 | pub struct Config { |
| 22 | pub address: Ipv4Cidr, | 30 | pub address: Ipv4Cidr, |
| 23 | pub gateway: Ipv4Address, | 31 | pub gateway: Option<Ipv4Address>, |
| 24 | pub dns_servers: Vec<Ipv4Address, U3>, | 32 | pub dns_servers: Vec<Ipv4Address, U3>, |
| 25 | } | 33 | } |
| 26 | 34 | ||
| 27 | pub trait Configurator { | 35 | pub trait Configurator { |
| 28 | fn poll( | 36 | fn poll(&mut self, iface: &mut Interface, sockets: &mut SocketSet, timestamp: Instant) |
| 29 | &mut self, | 37 | -> Event; |
| 30 | iface: &mut Interface, | ||
| 31 | sockets: &mut SocketSet, | ||
| 32 | timestamp: Instant, | ||
| 33 | ) -> Option<Config>; | ||
| 34 | } | 38 | } |
diff --git a/embassy-net/src/config/statik.rs b/embassy-net/src/config/statik.rs index 52196f48a..912143bff 100644 --- a/embassy-net/src/config/statik.rs +++ b/embassy-net/src/config/statik.rs | |||
| @@ -5,12 +5,16 @@ use crate::fmt::*; | |||
| 5 | use crate::{Interface, SocketSet}; | 5 | use crate::{Interface, SocketSet}; |
| 6 | 6 | ||
| 7 | pub struct StaticConfigurator { | 7 | pub struct StaticConfigurator { |
| 8 | config: UpConfig, | 8 | config: Config, |
| 9 | returned: bool, | ||
| 9 | } | 10 | } |
| 10 | 11 | ||
| 11 | impl StaticConfigurator { | 12 | impl StaticConfigurator { |
| 12 | pub fn new(config: UpConfig) -> Self { | 13 | pub fn new(config: Config) -> Self { |
| 13 | Self { config } | 14 | Self { |
| 15 | config, | ||
| 16 | returned: false, | ||
| 17 | } | ||
| 14 | } | 18 | } |
| 15 | } | 19 | } |
| 16 | 20 | ||
| @@ -20,7 +24,12 @@ impl Configurator for StaticConfigurator { | |||
| 20 | _iface: &mut Interface, | 24 | _iface: &mut Interface, |
| 21 | _sockets: &mut SocketSet, | 25 | _sockets: &mut SocketSet, |
| 22 | _timestamp: Instant, | 26 | _timestamp: Instant, |
| 23 | ) -> Option<Config> { | 27 | ) -> Event { |
| 24 | Some(Config::Up(self.config.clone())) | 28 | if self.returned { |
| 29 | Event::NoChange | ||
| 30 | } else { | ||
| 31 | self.returned = true; | ||
| 32 | Event::Configured(self.config.clone()) | ||
| 33 | } | ||
| 25 | } | 34 | } |
| 26 | } | 35 | } |
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index 32b56e5be..6c06b0605 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs | |||
| @@ -4,6 +4,7 @@ use smoltcp::phy::DeviceCapabilities; | |||
| 4 | use smoltcp::time::Instant as SmolInstant; | 4 | use smoltcp::time::Instant as SmolInstant; |
| 5 | 5 | ||
| 6 | use crate::fmt::*; | 6 | use crate::fmt::*; |
| 7 | use crate::packet_pool::PacketBoxExt; | ||
| 7 | use crate::Result; | 8 | use crate::Result; |
| 8 | use crate::{Packet, PacketBox, PacketBuf}; | 9 | use crate::{Packet, PacketBox, PacketBuf}; |
| 9 | 10 | ||
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index de2f2ea74..c79c38c0b 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -7,18 +7,19 @@ | |||
| 7 | // This mod MUST go first, so that the others see its macros. | 7 | // This mod MUST go first, so that the others see its macros. |
| 8 | pub(crate) mod fmt; | 8 | pub(crate) mod fmt; |
| 9 | 9 | ||
| 10 | mod pool; // TODO extract to embassy, or to own crate | ||
| 11 | |||
| 12 | mod config; | 10 | mod config; |
| 13 | mod device; | 11 | mod device; |
| 14 | mod packet_pool; | 12 | mod packet_pool; |
| 15 | mod stack; | 13 | mod stack; |
| 16 | mod tcp_socket; | ||
| 17 | 14 | ||
| 18 | pub use config::{Config, Configurator, DhcpConfigurator, StaticConfigurator, UpConfig}; | 15 | pub use config::{Config, Configurator, DhcpConfigurator, StaticConfigurator}; |
| 19 | pub use device::{Device, LinkState}; | 16 | pub use device::{Device, LinkState}; |
| 20 | pub use packet_pool::{Packet, PacketBox, PacketBuf}; | 17 | pub use packet_pool::{Packet, PacketBox, PacketBoxExt, PacketBuf}; |
| 21 | pub use stack::{init, is_init, run}; | 18 | pub use stack::{init, is_init, run}; |
| 19 | |||
| 20 | #[cfg(feature = "tcp")] | ||
| 21 | mod tcp_socket; | ||
| 22 | #[cfg(feature = "tcp")] | ||
| 22 | pub use tcp_socket::TcpSocket; | 23 | pub use tcp_socket::TcpSocket; |
| 23 | 24 | ||
| 24 | // smoltcp reexports | 25 | // smoltcp reexports |
| @@ -28,4 +29,4 @@ pub use smoltcp::time::Instant as SmolInstant; | |||
| 28 | pub use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; | 29 | pub use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; |
| 29 | pub type Interface = smoltcp::iface::Interface<'static, device::DeviceAdapter>; | 30 | pub type Interface = smoltcp::iface::Interface<'static, device::DeviceAdapter>; |
| 30 | pub type SocketSet = smoltcp::socket::SocketSet<'static>; | 31 | pub type SocketSet = smoltcp::socket::SocketSet<'static>; |
| 31 | pub use smoltcp::{Error, Result}; \ No newline at end of file | 32 | pub use smoltcp::{Error, Result}; |
diff --git a/embassy-net/src/packet_pool.rs b/embassy-net/src/packet_pool.rs index 246356431..2c27d4013 100644 --- a/embassy-net/src/packet_pool.rs +++ b/embassy-net/src/packet_pool.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | use as_slice::{AsMutSlice, AsSlice}; | 1 | use as_slice::{AsMutSlice, AsSlice}; |
| 2 | use core::ops::{Deref, DerefMut, Range}; | 2 | use core::ops::{Deref, DerefMut, Range}; |
| 3 | 3 | ||
| 4 | use super::pool::{BitPool, Box, StaticPool}; | 4 | use atomic_pool::{pool, Box}; |
| 5 | 5 | ||
| 6 | pub const MTU: usize = 1514; | 6 | pub const MTU: usize = 1514; |
| 7 | pub const PACKET_POOL_SIZE: usize = 4; | 7 | pub const PACKET_POOL_SIZE: usize = 4; |
| @@ -17,8 +17,12 @@ impl Packet { | |||
| 17 | } | 17 | } |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | impl Box<PacketPool> { | 20 | pub trait PacketBoxExt { |
| 21 | pub fn slice(self, range: Range<usize>) -> PacketBuf { | 21 | fn slice(self, range: Range<usize>) -> PacketBuf; |
| 22 | } | ||
| 23 | |||
| 24 | impl PacketBoxExt for PacketBox { | ||
| 25 | fn slice(self, range: Range<usize>) -> PacketBuf { | ||
| 22 | PacketBuf { | 26 | PacketBuf { |
| 23 | packet: self, | 27 | packet: self, |
| 24 | range, | 28 | range, |
diff --git a/embassy-net/src/pool.rs b/embassy-net/src/pool.rs deleted file mode 100644 index 3ab36e4cc..000000000 --- a/embassy-net/src/pool.rs +++ /dev/null | |||
| @@ -1,245 +0,0 @@ | |||
| 1 | #![macro_use] | ||
| 2 | |||
| 3 | use as_slice::{AsMutSlice, AsSlice}; | ||
| 4 | use core::cmp; | ||
| 5 | use core::fmt; | ||
| 6 | use core::hash::{Hash, Hasher}; | ||
| 7 | use core::mem::MaybeUninit; | ||
| 8 | use core::ops::{Deref, DerefMut}; | ||
| 9 | use core::sync::atomic::{AtomicU32, Ordering}; | ||
| 10 | |||
| 11 | use crate::fmt::{assert, *}; | ||
| 12 | |||
| 13 | struct AtomicBitset<const N: usize> | ||
| 14 | where | ||
| 15 | [AtomicU32; (N + 31) / 32]: Sized, | ||
| 16 | { | ||
| 17 | used: [AtomicU32; (N + 31) / 32], | ||
| 18 | } | ||
| 19 | |||
| 20 | impl<const N: usize> AtomicBitset<N> | ||
| 21 | where | ||
| 22 | [AtomicU32; (N + 31) / 32]: Sized, | ||
| 23 | { | ||
| 24 | const fn new() -> Self { | ||
| 25 | const Z: AtomicU32 = AtomicU32::new(0); | ||
| 26 | Self { | ||
| 27 | used: [Z; (N + 31) / 32], | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | fn alloc(&self) -> Option<usize> { | ||
| 32 | for (i, val) in self.used.iter().enumerate() { | ||
| 33 | let res = val.fetch_update(Ordering::AcqRel, Ordering::Acquire, |val| { | ||
| 34 | let n = val.trailing_ones() as usize + i * 32; | ||
| 35 | if n >= N { | ||
| 36 | None | ||
| 37 | } else { | ||
| 38 | Some(val | (1 << n)) | ||
| 39 | } | ||
| 40 | }); | ||
| 41 | if let Ok(val) = res { | ||
| 42 | let n = val.trailing_ones() as usize + i * 32; | ||
| 43 | return Some(n); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | None | ||
| 47 | } | ||
| 48 | fn free(&self, i: usize) { | ||
| 49 | assert!(i < N); | ||
| 50 | self.used[i / 32].fetch_and(!(1 << ((i % 32) as u32)), Ordering::AcqRel); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | pub trait Pool<T> { | ||
| 55 | fn alloc(&self) -> Option<*mut T>; | ||
| 56 | unsafe fn free(&self, p: *mut T); | ||
| 57 | } | ||
| 58 | |||
| 59 | pub struct BitPool<T, const N: usize> | ||
| 60 | where | ||
| 61 | [AtomicU32; (N + 31) / 32]: Sized, | ||
| 62 | { | ||
| 63 | used: AtomicBitset<N>, | ||
| 64 | data: MaybeUninit<[T; N]>, | ||
| 65 | } | ||
| 66 | |||
| 67 | impl<T, const N: usize> BitPool<T, N> | ||
| 68 | where | ||
| 69 | [AtomicU32; (N + 31) / 32]: Sized, | ||
| 70 | { | ||
| 71 | pub const fn new() -> Self { | ||
| 72 | Self { | ||
| 73 | used: AtomicBitset::new(), | ||
| 74 | data: MaybeUninit::uninit(), | ||
| 75 | } | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | impl<T, const N: usize> Pool<T> for BitPool<T, N> | ||
| 80 | where | ||
| 81 | [AtomicU32; (N + 31) / 32]: Sized, | ||
| 82 | { | ||
| 83 | fn alloc(&self) -> Option<*mut T> { | ||
| 84 | let n = self.used.alloc()?; | ||
| 85 | let origin = self.data.as_ptr() as *mut T; | ||
| 86 | Some(unsafe { origin.add(n) }) | ||
| 87 | } | ||
| 88 | |||
| 89 | /// safety: p must be a pointer obtained from self.alloc that hasn't been freed yet. | ||
| 90 | unsafe fn free(&self, p: *mut T) { | ||
| 91 | let origin = self.data.as_ptr() as *mut T; | ||
| 92 | let n = p.offset_from(origin); | ||
| 93 | assert!(n >= 0); | ||
| 94 | assert!((n as usize) < N); | ||
| 95 | self.used.free(n as usize); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | pub trait StaticPool: 'static { | ||
| 100 | type Item: 'static; | ||
| 101 | type Pool: Pool<Self::Item>; | ||
| 102 | fn get() -> &'static Self::Pool; | ||
| 103 | } | ||
| 104 | |||
| 105 | pub struct Box<P: StaticPool> { | ||
| 106 | ptr: *mut P::Item, | ||
| 107 | } | ||
| 108 | |||
| 109 | impl<P: StaticPool> Box<P> { | ||
| 110 | pub fn new(item: P::Item) -> Option<Self> { | ||
| 111 | let p = match P::get().alloc() { | ||
| 112 | Some(p) => p, | ||
| 113 | None => { | ||
| 114 | warn!("alloc failed!"); | ||
| 115 | return None; | ||
| 116 | } | ||
| 117 | }; | ||
| 118 | //trace!("allocated {:u32}", p as u32); | ||
| 119 | unsafe { p.write(item) }; | ||
| 120 | Some(Self { ptr: p }) | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | impl<P: StaticPool> Drop for Box<P> { | ||
| 125 | fn drop(&mut self) { | ||
| 126 | unsafe { | ||
| 127 | //trace!("dropping {:u32}", self.ptr as u32); | ||
| 128 | self.ptr.drop_in_place(); | ||
| 129 | P::get().free(self.ptr); | ||
| 130 | }; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | unsafe impl<P: StaticPool> Send for Box<P> where P::Item: Send {} | ||
| 135 | |||
| 136 | unsafe impl<P: StaticPool> Sync for Box<P> where P::Item: Sync {} | ||
| 137 | |||
| 138 | unsafe impl<P: StaticPool> stable_deref_trait::StableDeref for Box<P> {} | ||
| 139 | |||
| 140 | impl<P: StaticPool> AsSlice for Box<P> | ||
| 141 | where | ||
| 142 | P::Item: AsSlice, | ||
| 143 | { | ||
| 144 | type Element = <P::Item as AsSlice>::Element; | ||
| 145 | |||
| 146 | fn as_slice(&self) -> &[Self::Element] { | ||
| 147 | self.deref().as_slice() | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | impl<P: StaticPool> AsMutSlice for Box<P> | ||
| 152 | where | ||
| 153 | P::Item: AsMutSlice, | ||
| 154 | { | ||
| 155 | fn as_mut_slice(&mut self) -> &mut [Self::Element] { | ||
| 156 | self.deref_mut().as_mut_slice() | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | impl<P: StaticPool> Deref for Box<P> { | ||
| 161 | type Target = P::Item; | ||
| 162 | |||
| 163 | fn deref(&self) -> &P::Item { | ||
| 164 | unsafe { &*self.ptr } | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | impl<P: StaticPool> DerefMut for Box<P> { | ||
| 169 | fn deref_mut(&mut self) -> &mut P::Item { | ||
| 170 | unsafe { &mut *self.ptr } | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | impl<P: StaticPool> fmt::Debug for Box<P> | ||
| 175 | where | ||
| 176 | P::Item: fmt::Debug, | ||
| 177 | { | ||
| 178 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| 179 | <P::Item as fmt::Debug>::fmt(self, f) | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | impl<P: StaticPool> fmt::Display for Box<P> | ||
| 184 | where | ||
| 185 | P::Item: fmt::Display, | ||
| 186 | { | ||
| 187 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| 188 | <P::Item as fmt::Display>::fmt(self, f) | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | impl<P: StaticPool> PartialEq for Box<P> | ||
| 193 | where | ||
| 194 | P::Item: PartialEq, | ||
| 195 | { | ||
| 196 | fn eq(&self, rhs: &Box<P>) -> bool { | ||
| 197 | <P::Item as PartialEq>::eq(self, rhs) | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | impl<P: StaticPool> Eq for Box<P> where P::Item: Eq {} | ||
| 202 | |||
| 203 | impl<P: StaticPool> PartialOrd for Box<P> | ||
| 204 | where | ||
| 205 | P::Item: PartialOrd, | ||
| 206 | { | ||
| 207 | fn partial_cmp(&self, rhs: &Box<P>) -> Option<cmp::Ordering> { | ||
| 208 | <P::Item as PartialOrd>::partial_cmp(self, rhs) | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | impl<P: StaticPool> Ord for Box<P> | ||
| 213 | where | ||
| 214 | P::Item: Ord, | ||
| 215 | { | ||
| 216 | fn cmp(&self, rhs: &Box<P>) -> cmp::Ordering { | ||
| 217 | <P::Item as Ord>::cmp(self, rhs) | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | impl<P: StaticPool> Hash for Box<P> | ||
| 222 | where | ||
| 223 | P::Item: Hash, | ||
| 224 | { | ||
| 225 | fn hash<H>(&self, state: &mut H) | ||
| 226 | where | ||
| 227 | H: Hasher, | ||
| 228 | { | ||
| 229 | <P::Item as Hash>::hash(self, state) | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | macro_rules! pool { | ||
| 234 | ($vis:vis $name:ident: [$ty:ty; $size:expr]) => { | ||
| 235 | $vis struct $name; | ||
| 236 | impl StaticPool for $name { | ||
| 237 | type Item = $ty; | ||
| 238 | type Pool = BitPool<$ty, $size>; | ||
| 239 | fn get() -> &'static Self::Pool { | ||
| 240 | static POOL: BitPool<$ty, $size> = BitPool::new(); | ||
| 241 | &POOL | ||
| 242 | } | ||
| 243 | } | ||
| 244 | }; | ||
| 245 | } | ||
diff --git a/embassy-net/src/stack.rs b/embassy-net/src/stack.rs index f8a945a54..dc8043e67 100644 --- a/embassy-net/src/stack.rs +++ b/embassy-net/src/stack.rs | |||
| @@ -11,14 +11,12 @@ use smoltcp::phy::Device as _; | |||
| 11 | use smoltcp::phy::Medium; | 11 | use smoltcp::phy::Medium; |
| 12 | use smoltcp::socket::SocketSetItem; | 12 | use smoltcp::socket::SocketSetItem; |
| 13 | use smoltcp::time::Instant as SmolInstant; | 13 | use smoltcp::time::Instant as SmolInstant; |
| 14 | use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address}; | 14 | use smoltcp::wire::{EthernetAddress, IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; |
| 15 | 15 | ||
| 16 | use crate::device::{Device, DeviceAdapter}; | 16 | use crate::config::Configurator; |
| 17 | use crate::config::Event; | ||
| 18 | use crate::device::{Device, DeviceAdapter, LinkState}; | ||
| 17 | use crate::fmt::*; | 19 | use crate::fmt::*; |
| 18 | use crate::{ | ||
| 19 | config::{Config, Configurator}, | ||
| 20 | device::LinkState, | ||
| 21 | }; | ||
| 22 | use crate::{Interface, SocketSet}; | 20 | use crate::{Interface, SocketSet}; |
| 23 | 21 | ||
| 24 | const ADDRESSES_LEN: usize = 1; | 22 | const ADDRESSES_LEN: usize = 1; |
| @@ -68,39 +66,41 @@ impl Stack { | |||
| 68 | } | 66 | } |
| 69 | 67 | ||
| 70 | fn poll_configurator(&mut self, timestamp: SmolInstant) { | 68 | fn poll_configurator(&mut self, timestamp: SmolInstant) { |
| 71 | if let Some(config) = self | 69 | let medium = self.iface.device().capabilities().medium; |
| 70 | |||
| 71 | match self | ||
| 72 | .configurator | 72 | .configurator |
| 73 | .poll(&mut self.iface, &mut self.sockets, timestamp) | 73 | .poll(&mut self.iface, &mut self.sockets, timestamp) |
| 74 | { | 74 | { |
| 75 | let medium = self.iface.device().capabilities().medium; | 75 | Event::NoChange => {} |
| 76 | 76 | Event::Configured(config) => { | |
| 77 | let (addr, gateway) = match config { | 77 | debug!("Acquired IP configuration:"); |
| 78 | Config::Up(config) => (config.address.into(), Some(config.gateway)), | 78 | |
| 79 | Config::Down => (IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 32), None), | 79 | debug!(" IP address: {}", config.address); |
| 80 | }; | 80 | set_ipv4_addr(&mut self.iface, config.address); |
| 81 | 81 | ||
| 82 | self.iface.update_ip_addrs(|addrs| { | 82 | if medium == Medium::Ethernet { |
| 83 | let curr_addr = &mut addrs[0]; | 83 | if let Some(gateway) = config.gateway { |
| 84 | if *curr_addr != addr { | 84 | debug!(" Default gateway: {}", gateway); |
| 85 | info!("IPv4 address: {:?} -> {:?}", *curr_addr, addr); | 85 | self.iface |
| 86 | *curr_addr = addr; | 86 | .routes_mut() |
| 87 | } | 87 | .add_default_ipv4_route(gateway) |
| 88 | }); | 88 | .unwrap(); |
| 89 | 89 | } else { | |
| 90 | if medium == Medium::Ethernet { | 90 | debug!(" Default gateway: None"); |
| 91 | self.iface.routes_mut().update(|r| { | 91 | self.iface.routes_mut().remove_default_ipv4_route(); |
| 92 | let cidr = IpCidr::new(IpAddress::v4(0, 0, 0, 0), 0); | ||
| 93 | let curr_gateway = r.get(&cidr).map(|r| r.via_router); | ||
| 94 | |||
| 95 | if curr_gateway != gateway.map(|a| a.into()) { | ||
| 96 | info!("IPv4 gateway: {:?} -> {:?}", curr_gateway, gateway); | ||
| 97 | if let Some(gateway) = gateway { | ||
| 98 | r.insert(cidr, Route::new_ipv4_gateway(gateway)).unwrap(); | ||
| 99 | } else { | ||
| 100 | r.remove(&cidr); | ||
| 101 | } | ||
| 102 | } | 92 | } |
| 103 | }); | 93 | } |
| 94 | for (i, s) in config.dns_servers.iter().enumerate() { | ||
| 95 | debug!(" DNS server {}: {}", i, s); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | Event::Deconfigured => { | ||
| 99 | debug!("Lost IP configuration"); | ||
| 100 | set_ipv4_addr(&mut self.iface, Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0)); | ||
| 101 | if medium == Medium::Ethernet { | ||
| 102 | self.iface.routes_mut().remove_default_ipv4_route(); | ||
| 103 | } | ||
| 104 | } | 104 | } |
| 105 | } | 105 | } |
| 106 | } | 106 | } |
| @@ -143,6 +143,13 @@ impl Stack { | |||
| 143 | } | 143 | } |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | fn set_ipv4_addr(iface: &mut Interface, cidr: Ipv4Cidr) { | ||
| 147 | iface.update_ip_addrs(|addrs| { | ||
| 148 | let dest = addrs.iter_mut().next().unwrap(); | ||
| 149 | *dest = IpCidr::Ipv4(cidr); | ||
| 150 | }); | ||
| 151 | } | ||
| 152 | |||
| 146 | /// Initialize embassy_net. | 153 | /// Initialize embassy_net. |
| 147 | /// This function must be called from thread mode. | 154 | /// This function must be called from thread mode. |
| 148 | pub fn init(device: &'static mut dyn Device, configurator: &'static mut dyn Configurator) { | 155 | pub fn init(device: &'static mut dyn Device, configurator: &'static mut dyn Configurator) { |
