diff options
| author | Dario Nieuwenhuis <[email protected]> | 2022-12-13 17:03:51 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-12-13 17:03:51 +0100 |
| commit | 5b65b0e84377338b615ba3fc16d0a96d2db5c206 (patch) | |
| tree | 627cc0abdfdf95f504728fceaaf9816575d05e84 /embassy-net/src | |
| parent | 47747d3b73f392e53ead8ff49cd09fd017df3215 (diff) | |
| parent | 790e4e1594d455d06c7303a628172244e78af0da (diff) | |
Merge pull request #1096 from embassy-rs/net-refactor2
net: remove packet pool
Diffstat (limited to 'embassy-net/src')
| -rw-r--r-- | embassy-net/src/device.rs | 163 | ||||
| -rw-r--r-- | embassy-net/src/lib.rs | 313 | ||||
| -rw-r--r-- | embassy-net/src/packet_pool.rs | 107 | ||||
| -rw-r--r-- | embassy-net/src/stack.rs | 302 | ||||
| -rw-r--r-- | embassy-net/src/tcp.rs | 5 | ||||
| -rw-r--r-- | embassy-net/src/udp.rs | 3 |
6 files changed, 395 insertions, 498 deletions
diff --git a/embassy-net/src/device.rs b/embassy-net/src/device.rs index 4bdfd7720..5d86ca91e 100644 --- a/embassy-net/src/device.rs +++ b/embassy-net/src/device.rs | |||
| @@ -1,10 +1,7 @@ | |||
| 1 | use core::task::Waker; | 1 | use core::task::Context; |
| 2 | 2 | ||
| 3 | use smoltcp::phy::{Device as SmolDevice, DeviceCapabilities}; | 3 | use smoltcp::phy; |
| 4 | use smoltcp::time::Instant as SmolInstant; | 4 | pub use smoltcp::phy::{Checksum, ChecksumCapabilities, DeviceCapabilities, Medium}; |
| 5 | |||
| 6 | use crate::packet_pool::PacketBoxExt; | ||
| 7 | use crate::{Packet, PacketBox, PacketBuf}; | ||
| 8 | 5 | ||
| 9 | #[derive(PartialEq, Eq, Clone, Copy)] | 6 | #[derive(PartialEq, Eq, Clone, Copy)] |
| 10 | pub enum LinkState { | 7 | pub enum LinkState { |
| @@ -13,115 +10,133 @@ pub enum LinkState { | |||
| 13 | } | 10 | } |
| 14 | 11 | ||
| 15 | pub trait Device { | 12 | pub trait Device { |
| 16 | fn is_transmit_ready(&mut self) -> bool; | 13 | type RxToken<'a>: RxToken |
| 17 | fn transmit(&mut self, pkt: PacketBuf); | 14 | where |
| 18 | fn receive(&mut self) -> Option<PacketBuf>; | 15 | Self: 'a; |
| 16 | type TxToken<'a>: TxToken | ||
| 17 | where | ||
| 18 | Self: 'a; | ||
| 19 | 19 | ||
| 20 | fn register_waker(&mut self, waker: &Waker); | 20 | fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)>; |
| 21 | fn capabilities(&self) -> DeviceCapabilities; | 21 | fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>>; |
| 22 | fn link_state(&mut self) -> LinkState; | 22 | fn link_state(&mut self, cx: &mut Context) -> LinkState; |
| 23 | |||
| 24 | fn capabilities(&self) -> phy::DeviceCapabilities; | ||
| 23 | fn ethernet_address(&self) -> [u8; 6]; | 25 | fn ethernet_address(&self) -> [u8; 6]; |
| 24 | } | 26 | } |
| 25 | 27 | ||
| 26 | impl<T: ?Sized + Device> Device for &mut T { | 28 | impl<T: ?Sized + Device> Device for &mut T { |
| 27 | fn is_transmit_ready(&mut self) -> bool { | 29 | type RxToken<'a> = T::RxToken<'a> |
| 28 | T::is_transmit_ready(self) | 30 | where |
| 29 | } | 31 | Self: 'a; |
| 30 | fn transmit(&mut self, pkt: PacketBuf) { | 32 | type TxToken<'a> = T::TxToken<'a> |
| 31 | T::transmit(self, pkt) | 33 | where |
| 32 | } | 34 | Self: 'a; |
| 33 | fn receive(&mut self) -> Option<PacketBuf> { | 35 | |
| 34 | T::receive(self) | 36 | fn transmit(&mut self, cx: &mut Context) -> Option<Self::TxToken<'_>> { |
| 37 | T::transmit(self, cx) | ||
| 35 | } | 38 | } |
| 36 | fn register_waker(&mut self, waker: &Waker) { | 39 | fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { |
| 37 | T::register_waker(self, waker) | 40 | T::receive(self, cx) |
| 38 | } | 41 | } |
| 39 | fn capabilities(&self) -> DeviceCapabilities { | 42 | fn capabilities(&self) -> phy::DeviceCapabilities { |
| 40 | T::capabilities(self) | 43 | T::capabilities(self) |
| 41 | } | 44 | } |
| 42 | fn link_state(&mut self) -> LinkState { | 45 | fn link_state(&mut self, cx: &mut Context) -> LinkState { |
| 43 | T::link_state(self) | 46 | T::link_state(self, cx) |
| 44 | } | 47 | } |
| 45 | fn ethernet_address(&self) -> [u8; 6] { | 48 | fn ethernet_address(&self) -> [u8; 6] { |
| 46 | T::ethernet_address(self) | 49 | T::ethernet_address(self) |
| 47 | } | 50 | } |
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | pub struct DeviceAdapter<D: Device> { | 53 | /// A token to receive a single network packet. |
| 51 | pub device: D, | 54 | pub trait RxToken { |
| 52 | caps: DeviceCapabilities, | 55 | /// Consumes the token to receive a single network packet. |
| 56 | /// | ||
| 57 | /// This method receives a packet and then calls the given closure `f` with the raw | ||
| 58 | /// packet bytes as argument. | ||
| 59 | fn consume<R, F>(self, f: F) -> R | ||
| 60 | where | ||
| 61 | F: FnOnce(&mut [u8]) -> R; | ||
| 53 | } | 62 | } |
| 54 | 63 | ||
| 55 | impl<D: Device> DeviceAdapter<D> { | 64 | /// A token to transmit a single network packet. |
| 56 | pub(crate) fn new(device: D) -> Self { | 65 | pub trait TxToken { |
| 57 | Self { | 66 | /// Consumes the token to send a single network packet. |
| 58 | caps: device.capabilities(), | 67 | /// |
| 59 | device, | 68 | /// This method constructs a transmit buffer of size `len` and calls the passed |
| 60 | } | 69 | /// closure `f` with a mutable reference to that buffer. The closure should construct |
| 61 | } | 70 | /// a valid network packet (e.g. an ethernet packet) in the buffer. When the closure |
| 71 | /// returns, the transmit buffer is sent out. | ||
| 72 | fn consume<R, F>(self, len: usize, f: F) -> R | ||
| 73 | where | ||
| 74 | F: FnOnce(&mut [u8]) -> R; | ||
| 75 | } | ||
| 76 | |||
| 77 | /////////////////////////// | ||
| 78 | |||
| 79 | pub(crate) struct DeviceAdapter<'d, 'c, T> | ||
| 80 | where | ||
| 81 | T: Device, | ||
| 82 | { | ||
| 83 | // must be Some when actually using this to rx/tx | ||
| 84 | pub cx: Option<&'d mut Context<'c>>, | ||
| 85 | pub inner: &'d mut T, | ||
| 62 | } | 86 | } |
| 63 | 87 | ||
| 64 | impl<D: Device> SmolDevice for DeviceAdapter<D> { | 88 | impl<'d, 'c, T> phy::Device for DeviceAdapter<'d, 'c, T> |
| 65 | type RxToken<'a> = RxToken where Self: 'a; | 89 | where |
| 66 | type TxToken<'a> = TxToken<'a, D> where Self: 'a; | 90 | T: Device, |
| 91 | { | ||
| 92 | type RxToken<'a> = RxTokenAdapter<T::RxToken<'a>> where Self: 'a; | ||
| 93 | type TxToken<'a> = TxTokenAdapter<T::TxToken<'a>> where Self: 'a; | ||
| 67 | 94 | ||
| 68 | fn receive(&mut self) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { | 95 | fn receive(&mut self) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { |
| 69 | let tx_pkt = PacketBox::new(Packet::new())?; | 96 | self.inner |
| 70 | let rx_pkt = self.device.receive()?; | 97 | .receive(self.cx.as_deref_mut().unwrap()) |
| 71 | let rx_token = RxToken { pkt: rx_pkt }; | 98 | .map(|(rx, tx)| (RxTokenAdapter(rx), TxTokenAdapter(tx))) |
| 72 | let tx_token = TxToken { | ||
| 73 | device: &mut self.device, | ||
| 74 | pkt: tx_pkt, | ||
| 75 | }; | ||
| 76 | |||
| 77 | Some((rx_token, tx_token)) | ||
| 78 | } | 99 | } |
| 79 | 100 | ||
| 80 | /// Construct a transmit token. | 101 | /// Construct a transmit token. |
| 81 | fn transmit(&mut self) -> Option<Self::TxToken<'_>> { | 102 | fn transmit(&mut self) -> Option<Self::TxToken<'_>> { |
| 82 | if !self.device.is_transmit_ready() { | 103 | self.inner.transmit(self.cx.as_deref_mut().unwrap()).map(TxTokenAdapter) |
| 83 | return None; | ||
| 84 | } | ||
| 85 | |||
| 86 | let tx_pkt = PacketBox::new(Packet::new())?; | ||
| 87 | Some(TxToken { | ||
| 88 | device: &mut self.device, | ||
| 89 | pkt: tx_pkt, | ||
| 90 | }) | ||
| 91 | } | 104 | } |
| 92 | 105 | ||
| 93 | /// Get a description of device capabilities. | 106 | /// Get a description of device capabilities. |
| 94 | fn capabilities(&self) -> DeviceCapabilities { | 107 | fn capabilities(&self) -> phy::DeviceCapabilities { |
| 95 | self.caps.clone() | 108 | self.inner.capabilities() |
| 96 | } | 109 | } |
| 97 | } | 110 | } |
| 98 | 111 | ||
| 99 | pub struct RxToken { | 112 | pub(crate) struct RxTokenAdapter<T>(T) |
| 100 | pkt: PacketBuf, | 113 | where |
| 101 | } | 114 | T: RxToken; |
| 102 | 115 | ||
| 103 | impl smoltcp::phy::RxToken for RxToken { | 116 | impl<T> phy::RxToken for RxTokenAdapter<T> |
| 104 | fn consume<R, F>(mut self, _timestamp: SmolInstant, f: F) -> smoltcp::Result<R> | 117 | where |
| 118 | T: RxToken, | ||
| 119 | { | ||
| 120 | fn consume<R, F>(self, _timestamp: smoltcp::time::Instant, f: F) -> smoltcp::Result<R> | ||
| 105 | where | 121 | where |
| 106 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, | 122 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, |
| 107 | { | 123 | { |
| 108 | f(&mut self.pkt) | 124 | self.0.consume(|buf| f(buf)) |
| 109 | } | 125 | } |
| 110 | } | 126 | } |
| 111 | 127 | ||
| 112 | pub struct TxToken<'a, D: Device> { | 128 | pub(crate) struct TxTokenAdapter<T>(T) |
| 113 | device: &'a mut D, | 129 | where |
| 114 | pkt: PacketBox, | 130 | T: TxToken; |
| 115 | } | ||
| 116 | 131 | ||
| 117 | impl<'a, D: Device> smoltcp::phy::TxToken for TxToken<'a, D> { | 132 | impl<T> phy::TxToken for TxTokenAdapter<T> |
| 118 | fn consume<R, F>(self, _timestamp: SmolInstant, len: usize, f: F) -> smoltcp::Result<R> | 133 | where |
| 134 | T: TxToken, | ||
| 135 | { | ||
| 136 | fn consume<R, F>(self, _timestamp: smoltcp::time::Instant, len: usize, f: F) -> smoltcp::Result<R> | ||
| 119 | where | 137 | where |
| 120 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, | 138 | F: FnOnce(&mut [u8]) -> smoltcp::Result<R>, |
| 121 | { | 139 | { |
| 122 | let mut buf = self.pkt.slice(0..len); | 140 | self.0.consume(len, |buf| f(buf)) |
| 123 | let r = f(&mut buf)?; | ||
| 124 | self.device.transmit(buf); | ||
| 125 | Ok(r) | ||
| 126 | } | 141 | } |
| 127 | } | 142 | } |
diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index edb969842..afe0d6da0 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs | |||
| @@ -8,22 +8,30 @@ | |||
| 8 | // This mod MUST go first, so that the others see its macros. | 8 | // This mod MUST go first, so that the others see its macros. |
| 9 | pub(crate) mod fmt; | 9 | pub(crate) mod fmt; |
| 10 | 10 | ||
| 11 | mod device; | 11 | pub mod device; |
| 12 | mod packet_pool; | ||
| 13 | mod stack; | ||
| 14 | |||
| 15 | pub use device::{Device, LinkState}; | ||
| 16 | pub use packet_pool::{Packet, PacketBox, PacketBoxExt, PacketBuf, MTU}; | ||
| 17 | pub use stack::{Config, ConfigStrategy, Stack, StackResources}; | ||
| 18 | |||
| 19 | #[cfg(feature = "tcp")] | 12 | #[cfg(feature = "tcp")] |
| 20 | pub mod tcp; | 13 | pub mod tcp; |
| 21 | |||
| 22 | #[cfg(feature = "udp")] | 14 | #[cfg(feature = "udp")] |
| 23 | pub mod udp; | 15 | pub mod udp; |
| 24 | 16 | ||
| 17 | use core::cell::RefCell; | ||
| 18 | use core::future::{poll_fn, Future}; | ||
| 19 | use core::task::{Context, Poll}; | ||
| 20 | |||
| 21 | use embassy_sync::waitqueue::WakerRegistration; | ||
| 22 | use embassy_time::{Instant, Timer}; | ||
| 23 | use futures::pin_mut; | ||
| 24 | use heapless::Vec; | ||
| 25 | #[cfg(feature = "dhcpv4")] | ||
| 26 | use smoltcp::iface::SocketHandle; | ||
| 27 | use smoltcp::iface::{Interface, InterfaceBuilder, SocketSet, SocketStorage}; | ||
| 28 | #[cfg(feature = "medium-ethernet")] | ||
| 29 | use smoltcp::iface::{Neighbor, NeighborCache, Route, Routes}; | ||
| 30 | #[cfg(feature = "medium-ethernet")] | ||
| 31 | use smoltcp::phy::Medium; | ||
| 32 | #[cfg(feature = "dhcpv4")] | ||
| 33 | use smoltcp::socket::dhcpv4; | ||
| 25 | // smoltcp reexports | 34 | // smoltcp reexports |
| 26 | pub use smoltcp::phy::{DeviceCapabilities, Medium}; | ||
| 27 | pub use smoltcp::time::{Duration as SmolDuration, Instant as SmolInstant}; | 35 | pub use smoltcp::time::{Duration as SmolDuration, Instant as SmolInstant}; |
| 28 | #[cfg(feature = "medium-ethernet")] | 36 | #[cfg(feature = "medium-ethernet")] |
| 29 | pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; | 37 | pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; |
| @@ -32,3 +40,288 @@ pub use smoltcp::wire::{IpAddress, IpCidr, Ipv4Address, Ipv4Cidr}; | |||
| 32 | pub use smoltcp::wire::{Ipv6Address, Ipv6Cidr}; | 40 | pub use smoltcp::wire::{Ipv6Address, Ipv6Cidr}; |
| 33 | #[cfg(feature = "udp")] | 41 | #[cfg(feature = "udp")] |
| 34 | pub use smoltcp::{socket::udp::PacketMetadata, wire::IpListenEndpoint}; | 42 | pub use smoltcp::{socket::udp::PacketMetadata, wire::IpListenEndpoint}; |
| 43 | |||
| 44 | use crate::device::{Device, DeviceAdapter, LinkState}; | ||
| 45 | |||
| 46 | const LOCAL_PORT_MIN: u16 = 1025; | ||
| 47 | const LOCAL_PORT_MAX: u16 = 65535; | ||
| 48 | |||
| 49 | pub struct StackResources<const ADDR: usize, const SOCK: usize, const NEIGHBOR: usize> { | ||
| 50 | addresses: [IpCidr; ADDR], | ||
| 51 | sockets: [SocketStorage<'static>; SOCK], | ||
| 52 | |||
| 53 | #[cfg(feature = "medium-ethernet")] | ||
| 54 | routes: [Option<(IpCidr, Route)>; 1], | ||
| 55 | #[cfg(feature = "medium-ethernet")] | ||
| 56 | neighbor_cache: [Option<(IpAddress, Neighbor)>; NEIGHBOR], | ||
| 57 | } | ||
| 58 | |||
| 59 | impl<const ADDR: usize, const SOCK: usize, const NEIGHBOR: usize> StackResources<ADDR, SOCK, NEIGHBOR> { | ||
| 60 | pub fn new() -> Self { | ||
| 61 | Self { | ||
| 62 | addresses: [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 32); ADDR], | ||
| 63 | sockets: [SocketStorage::EMPTY; SOCK], | ||
| 64 | #[cfg(feature = "medium-ethernet")] | ||
| 65 | routes: [None; 1], | ||
| 66 | #[cfg(feature = "medium-ethernet")] | ||
| 67 | neighbor_cache: [None; NEIGHBOR], | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
| 73 | pub struct Config { | ||
| 74 | pub address: Ipv4Cidr, | ||
| 75 | pub gateway: Option<Ipv4Address>, | ||
| 76 | pub dns_servers: Vec<Ipv4Address, 3>, | ||
| 77 | } | ||
| 78 | |||
| 79 | pub enum ConfigStrategy { | ||
| 80 | Static(Config), | ||
| 81 | #[cfg(feature = "dhcpv4")] | ||
| 82 | Dhcp, | ||
| 83 | } | ||
| 84 | |||
| 85 | pub struct Stack<D: Device> { | ||
| 86 | pub(crate) socket: RefCell<SocketStack>, | ||
| 87 | inner: RefCell<Inner<D>>, | ||
| 88 | } | ||
| 89 | |||
| 90 | struct Inner<D: Device> { | ||
| 91 | device: D, | ||
| 92 | link_up: bool, | ||
| 93 | config: Option<Config>, | ||
| 94 | #[cfg(feature = "dhcpv4")] | ||
| 95 | dhcp_socket: Option<SocketHandle>, | ||
| 96 | } | ||
| 97 | |||
| 98 | pub(crate) struct SocketStack { | ||
| 99 | pub(crate) sockets: SocketSet<'static>, | ||
| 100 | pub(crate) iface: Interface<'static>, | ||
| 101 | pub(crate) waker: WakerRegistration, | ||
| 102 | next_local_port: u16, | ||
| 103 | } | ||
| 104 | |||
| 105 | impl<D: Device + 'static> Stack<D> { | ||
| 106 | pub fn new<const ADDR: usize, const SOCK: usize, const NEIGH: usize>( | ||
| 107 | mut device: D, | ||
| 108 | config: ConfigStrategy, | ||
| 109 | resources: &'static mut StackResources<ADDR, SOCK, NEIGH>, | ||
| 110 | random_seed: u64, | ||
| 111 | ) -> Self { | ||
| 112 | #[cfg(feature = "medium-ethernet")] | ||
| 113 | let medium = device.capabilities().medium; | ||
| 114 | |||
| 115 | #[cfg(feature = "medium-ethernet")] | ||
| 116 | let ethernet_addr = if medium == Medium::Ethernet { | ||
| 117 | device.ethernet_address() | ||
| 118 | } else { | ||
| 119 | [0, 0, 0, 0, 0, 0] | ||
| 120 | }; | ||
| 121 | |||
| 122 | let mut b = InterfaceBuilder::new(); | ||
| 123 | b = b.ip_addrs(&mut resources.addresses[..]); | ||
| 124 | b = b.random_seed(random_seed); | ||
| 125 | |||
| 126 | #[cfg(feature = "medium-ethernet")] | ||
| 127 | if medium == Medium::Ethernet { | ||
| 128 | b = b.hardware_addr(HardwareAddress::Ethernet(EthernetAddress(ethernet_addr))); | ||
| 129 | b = b.neighbor_cache(NeighborCache::new(&mut resources.neighbor_cache[..])); | ||
| 130 | b = b.routes(Routes::new(&mut resources.routes[..])); | ||
| 131 | } | ||
| 132 | |||
| 133 | let iface = b.finalize(&mut DeviceAdapter { | ||
| 134 | inner: &mut device, | ||
| 135 | cx: None, | ||
| 136 | }); | ||
| 137 | |||
| 138 | let sockets = SocketSet::new(&mut resources.sockets[..]); | ||
| 139 | |||
| 140 | let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN; | ||
| 141 | |||
| 142 | let mut inner = Inner { | ||
| 143 | device, | ||
| 144 | link_up: false, | ||
| 145 | config: None, | ||
| 146 | #[cfg(feature = "dhcpv4")] | ||
| 147 | dhcp_socket: None, | ||
| 148 | }; | ||
| 149 | let mut socket = SocketStack { | ||
| 150 | sockets, | ||
| 151 | iface, | ||
| 152 | waker: WakerRegistration::new(), | ||
| 153 | next_local_port, | ||
| 154 | }; | ||
| 155 | |||
| 156 | match config { | ||
| 157 | ConfigStrategy::Static(config) => inner.apply_config(&mut socket, config), | ||
| 158 | #[cfg(feature = "dhcpv4")] | ||
| 159 | ConfigStrategy::Dhcp => { | ||
| 160 | let handle = socket.sockets.add(smoltcp::socket::dhcpv4::Socket::new()); | ||
| 161 | inner.dhcp_socket = Some(handle); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | Self { | ||
| 166 | socket: RefCell::new(socket), | ||
| 167 | inner: RefCell::new(inner), | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | fn with<R>(&self, f: impl FnOnce(&SocketStack, &Inner<D>) -> R) -> R { | ||
| 172 | f(&*self.socket.borrow(), &*self.inner.borrow()) | ||
| 173 | } | ||
| 174 | |||
| 175 | fn with_mut<R>(&self, f: impl FnOnce(&mut SocketStack, &mut Inner<D>) -> R) -> R { | ||
| 176 | f(&mut *self.socket.borrow_mut(), &mut *self.inner.borrow_mut()) | ||
| 177 | } | ||
| 178 | |||
| 179 | pub fn ethernet_address(&self) -> [u8; 6] { | ||
| 180 | self.with(|_s, i| i.device.ethernet_address()) | ||
| 181 | } | ||
| 182 | |||
| 183 | pub fn is_link_up(&self) -> bool { | ||
| 184 | self.with(|_s, i| i.link_up) | ||
| 185 | } | ||
| 186 | |||
| 187 | pub fn is_config_up(&self) -> bool { | ||
| 188 | self.with(|_s, i| i.config.is_some()) | ||
| 189 | } | ||
| 190 | |||
| 191 | pub fn config(&self) -> Option<Config> { | ||
| 192 | self.with(|_s, i| i.config.clone()) | ||
| 193 | } | ||
| 194 | |||
| 195 | pub async fn run(&self) -> ! { | ||
| 196 | poll_fn(|cx| { | ||
| 197 | self.with_mut(|s, i| i.poll(cx, s)); | ||
| 198 | Poll::<()>::Pending | ||
| 199 | }) | ||
| 200 | .await; | ||
| 201 | unreachable!() | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | impl SocketStack { | ||
| 206 | #[allow(clippy::absurd_extreme_comparisons)] | ||
| 207 | pub fn get_local_port(&mut self) -> u16 { | ||
| 208 | let res = self.next_local_port; | ||
| 209 | self.next_local_port = if res >= LOCAL_PORT_MAX { LOCAL_PORT_MIN } else { res + 1 }; | ||
| 210 | res | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | impl<D: Device + 'static> Inner<D> { | ||
| 215 | fn apply_config(&mut self, s: &mut SocketStack, config: Config) { | ||
| 216 | #[cfg(feature = "medium-ethernet")] | ||
| 217 | let medium = self.device.capabilities().medium; | ||
| 218 | |||
| 219 | debug!("Acquired IP configuration:"); | ||
| 220 | |||
| 221 | debug!(" IP address: {}", config.address); | ||
| 222 | self.set_ipv4_addr(s, config.address); | ||
| 223 | |||
| 224 | #[cfg(feature = "medium-ethernet")] | ||
| 225 | if medium == Medium::Ethernet { | ||
| 226 | if let Some(gateway) = config.gateway { | ||
| 227 | debug!(" Default gateway: {}", gateway); | ||
| 228 | s.iface.routes_mut().add_default_ipv4_route(gateway).unwrap(); | ||
| 229 | } else { | ||
| 230 | debug!(" Default gateway: None"); | ||
| 231 | s.iface.routes_mut().remove_default_ipv4_route(); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | for (i, s) in config.dns_servers.iter().enumerate() { | ||
| 235 | debug!(" DNS server {}: {}", i, s); | ||
| 236 | } | ||
| 237 | |||
| 238 | self.config = Some(config) | ||
| 239 | } | ||
| 240 | |||
| 241 | #[allow(unused)] // used only with dhcp | ||
| 242 | fn unapply_config(&mut self, s: &mut SocketStack) { | ||
| 243 | #[cfg(feature = "medium-ethernet")] | ||
| 244 | let medium = self.device.capabilities().medium; | ||
| 245 | |||
| 246 | debug!("Lost IP configuration"); | ||
| 247 | self.set_ipv4_addr(s, Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0)); | ||
| 248 | #[cfg(feature = "medium-ethernet")] | ||
| 249 | if medium == Medium::Ethernet { | ||
| 250 | s.iface.routes_mut().remove_default_ipv4_route(); | ||
| 251 | } | ||
| 252 | self.config = None | ||
| 253 | } | ||
| 254 | |||
| 255 | fn set_ipv4_addr(&mut self, s: &mut SocketStack, cidr: Ipv4Cidr) { | ||
| 256 | s.iface.update_ip_addrs(|addrs| { | ||
| 257 | let dest = addrs.iter_mut().next().unwrap(); | ||
| 258 | *dest = IpCidr::Ipv4(cidr); | ||
| 259 | }); | ||
| 260 | } | ||
| 261 | |||
| 262 | fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { | ||
| 263 | s.waker.register(cx.waker()); | ||
| 264 | |||
| 265 | let timestamp = instant_to_smoltcp(Instant::now()); | ||
| 266 | let mut smoldev = DeviceAdapter { | ||
| 267 | cx: Some(cx), | ||
| 268 | inner: &mut self.device, | ||
| 269 | }; | ||
| 270 | if s.iface.poll(timestamp, &mut smoldev, &mut s.sockets).is_err() { | ||
| 271 | // If poll() returns error, it may not be done yet, so poll again later. | ||
| 272 | cx.waker().wake_by_ref(); | ||
| 273 | return; | ||
| 274 | } | ||
| 275 | |||
| 276 | // Update link up | ||
| 277 | let old_link_up = self.link_up; | ||
| 278 | self.link_up = self.device.link_state(cx) == LinkState::Up; | ||
| 279 | |||
| 280 | // Print when changed | ||
| 281 | if old_link_up != self.link_up { | ||
| 282 | info!("link_up = {:?}", self.link_up); | ||
| 283 | } | ||
| 284 | |||
| 285 | #[cfg(feature = "dhcpv4")] | ||
| 286 | if let Some(dhcp_handle) = self.dhcp_socket { | ||
| 287 | let socket = s.sockets.get_mut::<dhcpv4::Socket>(dhcp_handle); | ||
| 288 | |||
| 289 | if self.link_up { | ||
| 290 | match socket.poll() { | ||
| 291 | None => {} | ||
| 292 | Some(dhcpv4::Event::Deconfigured) => self.unapply_config(s), | ||
| 293 | Some(dhcpv4::Event::Configured(config)) => { | ||
| 294 | let config = Config { | ||
| 295 | address: config.address, | ||
| 296 | gateway: config.router, | ||
| 297 | dns_servers: config.dns_servers, | ||
| 298 | }; | ||
| 299 | self.apply_config(s, config) | ||
| 300 | } | ||
| 301 | } | ||
| 302 | } else if old_link_up { | ||
| 303 | socket.reset(); | ||
| 304 | self.unapply_config(s); | ||
| 305 | } | ||
| 306 | } | ||
| 307 | //if old_link_up || self.link_up { | ||
| 308 | // self.poll_configurator(timestamp) | ||
| 309 | //} | ||
| 310 | |||
| 311 | if let Some(poll_at) = s.iface.poll_at(timestamp, &mut s.sockets) { | ||
| 312 | let t = Timer::at(instant_from_smoltcp(poll_at)); | ||
| 313 | pin_mut!(t); | ||
| 314 | if t.poll(cx).is_ready() { | ||
| 315 | cx.waker().wake_by_ref(); | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | fn instant_to_smoltcp(instant: Instant) -> SmolInstant { | ||
| 322 | SmolInstant::from_millis(instant.as_millis() as i64) | ||
| 323 | } | ||
| 324 | |||
| 325 | fn instant_from_smoltcp(instant: SmolInstant) -> Instant { | ||
| 326 | Instant::from_millis(instant.total_millis() as u64) | ||
| 327 | } | ||
diff --git a/embassy-net/src/packet_pool.rs b/embassy-net/src/packet_pool.rs deleted file mode 100644 index cb8a1316c..000000000 --- a/embassy-net/src/packet_pool.rs +++ /dev/null | |||
| @@ -1,107 +0,0 @@ | |||
| 1 | use core::ops::{Deref, DerefMut, Range}; | ||
| 2 | |||
| 3 | use as_slice::{AsMutSlice, AsSlice}; | ||
| 4 | use atomic_pool::{pool, Box}; | ||
| 5 | |||
| 6 | pub const MTU: usize = 1516; | ||
| 7 | |||
| 8 | #[cfg(feature = "pool-4")] | ||
| 9 | pub const PACKET_POOL_SIZE: usize = 4; | ||
| 10 | |||
| 11 | #[cfg(feature = "pool-8")] | ||
| 12 | pub const PACKET_POOL_SIZE: usize = 8; | ||
| 13 | |||
| 14 | #[cfg(feature = "pool-16")] | ||
| 15 | pub const PACKET_POOL_SIZE: usize = 16; | ||
| 16 | |||
| 17 | #[cfg(feature = "pool-32")] | ||
| 18 | pub const PACKET_POOL_SIZE: usize = 32; | ||
| 19 | |||
| 20 | #[cfg(feature = "pool-64")] | ||
| 21 | pub const PACKET_POOL_SIZE: usize = 64; | ||
| 22 | |||
| 23 | #[cfg(feature = "pool-128")] | ||
| 24 | pub const PACKET_POOL_SIZE: usize = 128; | ||
| 25 | |||
| 26 | pool!(pub PacketPool: [Packet; PACKET_POOL_SIZE]); | ||
| 27 | pub type PacketBox = Box<PacketPool>; | ||
| 28 | |||
| 29 | #[repr(align(4))] | ||
| 30 | pub struct Packet(pub [u8; MTU]); | ||
| 31 | |||
| 32 | impl Packet { | ||
| 33 | pub const fn new() -> Self { | ||
| 34 | Self([0; MTU]) | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | pub trait PacketBoxExt { | ||
| 39 | fn slice(self, range: Range<usize>) -> PacketBuf; | ||
| 40 | } | ||
| 41 | |||
| 42 | impl PacketBoxExt for PacketBox { | ||
| 43 | fn slice(self, range: Range<usize>) -> PacketBuf { | ||
| 44 | PacketBuf { packet: self, range } | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | impl AsSlice for Packet { | ||
| 49 | type Element = u8; | ||
| 50 | |||
| 51 | fn as_slice(&self) -> &[Self::Element] { | ||
| 52 | &self.deref()[..] | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | impl AsMutSlice for Packet { | ||
| 57 | fn as_mut_slice(&mut self) -> &mut [Self::Element] { | ||
| 58 | &mut self.deref_mut()[..] | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | impl Deref for Packet { | ||
| 63 | type Target = [u8; MTU]; | ||
| 64 | |||
| 65 | fn deref(&self) -> &[u8; MTU] { | ||
| 66 | &self.0 | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | impl DerefMut for Packet { | ||
| 71 | fn deref_mut(&mut self) -> &mut [u8; MTU] { | ||
| 72 | &mut self.0 | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | pub struct PacketBuf { | ||
| 77 | packet: PacketBox, | ||
| 78 | range: Range<usize>, | ||
| 79 | } | ||
| 80 | |||
| 81 | impl AsSlice for PacketBuf { | ||
| 82 | type Element = u8; | ||
| 83 | |||
| 84 | fn as_slice(&self) -> &[Self::Element] { | ||
| 85 | &self.packet[self.range.clone()] | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | impl AsMutSlice for PacketBuf { | ||
| 90 | fn as_mut_slice(&mut self) -> &mut [Self::Element] { | ||
| 91 | &mut self.packet[self.range.clone()] | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | impl Deref for PacketBuf { | ||
| 96 | type Target = [u8]; | ||
| 97 | |||
| 98 | fn deref(&self) -> &[u8] { | ||
| 99 | &self.packet[self.range.clone()] | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | impl DerefMut for PacketBuf { | ||
| 104 | fn deref_mut(&mut self) -> &mut [u8] { | ||
| 105 | &mut self.packet[self.range.clone()] | ||
| 106 | } | ||
| 107 | } | ||
diff --git a/embassy-net/src/stack.rs b/embassy-net/src/stack.rs deleted file mode 100644 index 5c4fb0442..000000000 --- a/embassy-net/src/stack.rs +++ /dev/null | |||
| @@ -1,302 +0,0 @@ | |||
| 1 | use core::cell::RefCell; | ||
| 2 | use core::future::{poll_fn, Future}; | ||
| 3 | use core::task::{Context, Poll}; | ||
| 4 | |||
| 5 | use embassy_sync::waitqueue::WakerRegistration; | ||
| 6 | use embassy_time::{Instant, Timer}; | ||
| 7 | use futures::pin_mut; | ||
| 8 | use heapless::Vec; | ||
| 9 | #[cfg(feature = "dhcpv4")] | ||
| 10 | use smoltcp::iface::SocketHandle; | ||
| 11 | use smoltcp::iface::{Interface, InterfaceBuilder, SocketSet, SocketStorage}; | ||
| 12 | #[cfg(feature = "medium-ethernet")] | ||
| 13 | use smoltcp::iface::{Neighbor, NeighborCache, Route, Routes}; | ||
| 14 | #[cfg(feature = "medium-ethernet")] | ||
| 15 | use smoltcp::phy::{Device as _, Medium}; | ||
| 16 | #[cfg(feature = "dhcpv4")] | ||
| 17 | use smoltcp::socket::dhcpv4; | ||
| 18 | use smoltcp::time::Instant as SmolInstant; | ||
| 19 | #[cfg(feature = "medium-ethernet")] | ||
| 20 | use smoltcp::wire::{EthernetAddress, HardwareAddress, IpAddress}; | ||
| 21 | use smoltcp::wire::{IpCidr, Ipv4Address, Ipv4Cidr}; | ||
| 22 | |||
| 23 | use crate::device::{Device, DeviceAdapter, LinkState}; | ||
| 24 | |||
| 25 | const LOCAL_PORT_MIN: u16 = 1025; | ||
| 26 | const LOCAL_PORT_MAX: u16 = 65535; | ||
| 27 | |||
| 28 | pub struct StackResources<const ADDR: usize, const SOCK: usize, const NEIGHBOR: usize> { | ||
| 29 | addresses: [IpCidr; ADDR], | ||
| 30 | sockets: [SocketStorage<'static>; SOCK], | ||
| 31 | |||
| 32 | #[cfg(feature = "medium-ethernet")] | ||
| 33 | routes: [Option<(IpCidr, Route)>; 1], | ||
| 34 | #[cfg(feature = "medium-ethernet")] | ||
| 35 | neighbor_cache: [Option<(IpAddress, Neighbor)>; NEIGHBOR], | ||
| 36 | } | ||
| 37 | |||
| 38 | impl<const ADDR: usize, const SOCK: usize, const NEIGHBOR: usize> StackResources<ADDR, SOCK, NEIGHBOR> { | ||
| 39 | pub fn new() -> Self { | ||
| 40 | Self { | ||
| 41 | addresses: [IpCidr::new(Ipv4Address::UNSPECIFIED.into(), 32); ADDR], | ||
| 42 | sockets: [SocketStorage::EMPTY; SOCK], | ||
| 43 | #[cfg(feature = "medium-ethernet")] | ||
| 44 | routes: [None; 1], | ||
| 45 | #[cfg(feature = "medium-ethernet")] | ||
| 46 | neighbor_cache: [None; NEIGHBOR], | ||
| 47 | } | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
| 52 | pub struct Config { | ||
| 53 | pub address: Ipv4Cidr, | ||
| 54 | pub gateway: Option<Ipv4Address>, | ||
| 55 | pub dns_servers: Vec<Ipv4Address, 3>, | ||
| 56 | } | ||
| 57 | |||
| 58 | pub enum ConfigStrategy { | ||
| 59 | Static(Config), | ||
| 60 | #[cfg(feature = "dhcpv4")] | ||
| 61 | Dhcp, | ||
| 62 | } | ||
| 63 | |||
| 64 | pub struct Stack<D: Device> { | ||
| 65 | pub(crate) socket: RefCell<SocketStack>, | ||
| 66 | inner: RefCell<Inner<D>>, | ||
| 67 | } | ||
| 68 | |||
| 69 | struct Inner<D: Device> { | ||
| 70 | device: DeviceAdapter<D>, | ||
| 71 | link_up: bool, | ||
| 72 | config: Option<Config>, | ||
| 73 | #[cfg(feature = "dhcpv4")] | ||
| 74 | dhcp_socket: Option<SocketHandle>, | ||
| 75 | } | ||
| 76 | |||
| 77 | pub(crate) struct SocketStack { | ||
| 78 | pub(crate) sockets: SocketSet<'static>, | ||
| 79 | pub(crate) iface: Interface<'static>, | ||
| 80 | pub(crate) waker: WakerRegistration, | ||
| 81 | next_local_port: u16, | ||
| 82 | } | ||
| 83 | |||
| 84 | impl<D: Device + 'static> Stack<D> { | ||
| 85 | pub fn new<const ADDR: usize, const SOCK: usize, const NEIGH: usize>( | ||
| 86 | device: D, | ||
| 87 | config: ConfigStrategy, | ||
| 88 | resources: &'static mut StackResources<ADDR, SOCK, NEIGH>, | ||
| 89 | random_seed: u64, | ||
| 90 | ) -> Self { | ||
| 91 | #[cfg(feature = "medium-ethernet")] | ||
| 92 | let medium = device.capabilities().medium; | ||
| 93 | |||
| 94 | #[cfg(feature = "medium-ethernet")] | ||
| 95 | let ethernet_addr = if medium == Medium::Ethernet { | ||
| 96 | device.ethernet_address() | ||
| 97 | } else { | ||
| 98 | [0, 0, 0, 0, 0, 0] | ||
| 99 | }; | ||
| 100 | |||
| 101 | let mut device = DeviceAdapter::new(device); | ||
| 102 | |||
| 103 | let mut b = InterfaceBuilder::new(); | ||
| 104 | b = b.ip_addrs(&mut resources.addresses[..]); | ||
| 105 | b = b.random_seed(random_seed); | ||
| 106 | |||
| 107 | #[cfg(feature = "medium-ethernet")] | ||
| 108 | if medium == Medium::Ethernet { | ||
| 109 | b = b.hardware_addr(HardwareAddress::Ethernet(EthernetAddress(ethernet_addr))); | ||
| 110 | b = b.neighbor_cache(NeighborCache::new(&mut resources.neighbor_cache[..])); | ||
| 111 | b = b.routes(Routes::new(&mut resources.routes[..])); | ||
| 112 | } | ||
| 113 | |||
| 114 | let iface = b.finalize(&mut device); | ||
| 115 | |||
| 116 | let sockets = SocketSet::new(&mut resources.sockets[..]); | ||
| 117 | |||
| 118 | let next_local_port = (random_seed % (LOCAL_PORT_MAX - LOCAL_PORT_MIN) as u64) as u16 + LOCAL_PORT_MIN; | ||
| 119 | |||
| 120 | let mut inner = Inner { | ||
| 121 | device, | ||
| 122 | link_up: false, | ||
| 123 | config: None, | ||
| 124 | #[cfg(feature = "dhcpv4")] | ||
| 125 | dhcp_socket: None, | ||
| 126 | }; | ||
| 127 | let mut socket = SocketStack { | ||
| 128 | sockets, | ||
| 129 | iface, | ||
| 130 | waker: WakerRegistration::new(), | ||
| 131 | next_local_port, | ||
| 132 | }; | ||
| 133 | |||
| 134 | match config { | ||
| 135 | ConfigStrategy::Static(config) => inner.apply_config(&mut socket, config), | ||
| 136 | #[cfg(feature = "dhcpv4")] | ||
| 137 | ConfigStrategy::Dhcp => { | ||
| 138 | let handle = socket.sockets.add(smoltcp::socket::dhcpv4::Socket::new()); | ||
| 139 | inner.dhcp_socket = Some(handle); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | Self { | ||
| 144 | socket: RefCell::new(socket), | ||
| 145 | inner: RefCell::new(inner), | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | fn with<R>(&self, f: impl FnOnce(&SocketStack, &Inner<D>) -> R) -> R { | ||
| 150 | f(&*self.socket.borrow(), &*self.inner.borrow()) | ||
| 151 | } | ||
| 152 | |||
| 153 | fn with_mut<R>(&self, f: impl FnOnce(&mut SocketStack, &mut Inner<D>) -> R) -> R { | ||
| 154 | f(&mut *self.socket.borrow_mut(), &mut *self.inner.borrow_mut()) | ||
| 155 | } | ||
| 156 | |||
| 157 | pub fn ethernet_address(&self) -> [u8; 6] { | ||
| 158 | self.with(|_s, i| i.device.device.ethernet_address()) | ||
| 159 | } | ||
| 160 | |||
| 161 | pub fn is_link_up(&self) -> bool { | ||
| 162 | self.with(|_s, i| i.link_up) | ||
| 163 | } | ||
| 164 | |||
| 165 | pub fn is_config_up(&self) -> bool { | ||
| 166 | self.with(|_s, i| i.config.is_some()) | ||
| 167 | } | ||
| 168 | |||
| 169 | pub fn config(&self) -> Option<Config> { | ||
| 170 | self.with(|_s, i| i.config.clone()) | ||
| 171 | } | ||
| 172 | |||
| 173 | pub async fn run(&self) -> ! { | ||
| 174 | poll_fn(|cx| { | ||
| 175 | self.with_mut(|s, i| i.poll(cx, s)); | ||
| 176 | Poll::<()>::Pending | ||
| 177 | }) | ||
| 178 | .await; | ||
| 179 | unreachable!() | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | impl SocketStack { | ||
| 184 | #[allow(clippy::absurd_extreme_comparisons)] | ||
| 185 | pub fn get_local_port(&mut self) -> u16 { | ||
| 186 | let res = self.next_local_port; | ||
| 187 | self.next_local_port = if res >= LOCAL_PORT_MAX { LOCAL_PORT_MIN } else { res + 1 }; | ||
| 188 | res | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | impl<D: Device + 'static> Inner<D> { | ||
| 193 | fn apply_config(&mut self, s: &mut SocketStack, config: Config) { | ||
| 194 | #[cfg(feature = "medium-ethernet")] | ||
| 195 | let medium = self.device.capabilities().medium; | ||
| 196 | |||
| 197 | debug!("Acquired IP configuration:"); | ||
| 198 | |||
| 199 | debug!(" IP address: {}", config.address); | ||
| 200 | self.set_ipv4_addr(s, config.address); | ||
| 201 | |||
| 202 | #[cfg(feature = "medium-ethernet")] | ||
| 203 | if medium == Medium::Ethernet { | ||
| 204 | if let Some(gateway) = config.gateway { | ||
| 205 | debug!(" Default gateway: {}", gateway); | ||
| 206 | s.iface.routes_mut().add_default_ipv4_route(gateway).unwrap(); | ||
| 207 | } else { | ||
| 208 | debug!(" Default gateway: None"); | ||
| 209 | s.iface.routes_mut().remove_default_ipv4_route(); | ||
| 210 | } | ||
| 211 | } | ||
| 212 | for (i, s) in config.dns_servers.iter().enumerate() { | ||
| 213 | debug!(" DNS server {}: {}", i, s); | ||
| 214 | } | ||
| 215 | |||
| 216 | self.config = Some(config) | ||
| 217 | } | ||
| 218 | |||
| 219 | #[allow(unused)] // used only with dhcp | ||
| 220 | fn unapply_config(&mut self, s: &mut SocketStack) { | ||
| 221 | #[cfg(feature = "medium-ethernet")] | ||
| 222 | let medium = self.device.capabilities().medium; | ||
| 223 | |||
| 224 | debug!("Lost IP configuration"); | ||
| 225 | self.set_ipv4_addr(s, Ipv4Cidr::new(Ipv4Address::UNSPECIFIED, 0)); | ||
| 226 | #[cfg(feature = "medium-ethernet")] | ||
| 227 | if medium == Medium::Ethernet { | ||
| 228 | s.iface.routes_mut().remove_default_ipv4_route(); | ||
| 229 | } | ||
| 230 | self.config = None | ||
| 231 | } | ||
| 232 | |||
| 233 | fn set_ipv4_addr(&mut self, s: &mut SocketStack, cidr: Ipv4Cidr) { | ||
| 234 | s.iface.update_ip_addrs(|addrs| { | ||
| 235 | let dest = addrs.iter_mut().next().unwrap(); | ||
| 236 | *dest = IpCidr::Ipv4(cidr); | ||
| 237 | }); | ||
| 238 | } | ||
| 239 | |||
| 240 | fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { | ||
| 241 | self.device.device.register_waker(cx.waker()); | ||
| 242 | s.waker.register(cx.waker()); | ||
| 243 | |||
| 244 | let timestamp = instant_to_smoltcp(Instant::now()); | ||
| 245 | if s.iface.poll(timestamp, &mut self.device, &mut s.sockets).is_err() { | ||
| 246 | // If poll() returns error, it may not be done yet, so poll again later. | ||
| 247 | cx.waker().wake_by_ref(); | ||
| 248 | return; | ||
| 249 | } | ||
| 250 | |||
| 251 | // Update link up | ||
| 252 | let old_link_up = self.link_up; | ||
| 253 | self.link_up = self.device.device.link_state() == LinkState::Up; | ||
| 254 | |||
| 255 | // Print when changed | ||
| 256 | if old_link_up != self.link_up { | ||
| 257 | info!("link_up = {:?}", self.link_up); | ||
| 258 | } | ||
| 259 | |||
| 260 | #[cfg(feature = "dhcpv4")] | ||
| 261 | if let Some(dhcp_handle) = self.dhcp_socket { | ||
| 262 | let socket = s.sockets.get_mut::<dhcpv4::Socket>(dhcp_handle); | ||
| 263 | |||
| 264 | if self.link_up { | ||
| 265 | match socket.poll() { | ||
| 266 | None => {} | ||
| 267 | Some(dhcpv4::Event::Deconfigured) => self.unapply_config(s), | ||
| 268 | Some(dhcpv4::Event::Configured(config)) => { | ||
| 269 | let config = Config { | ||
| 270 | address: config.address, | ||
| 271 | gateway: config.router, | ||
| 272 | dns_servers: config.dns_servers, | ||
| 273 | }; | ||
| 274 | self.apply_config(s, config) | ||
| 275 | } | ||
| 276 | } | ||
| 277 | } else if old_link_up { | ||
| 278 | socket.reset(); | ||
| 279 | self.unapply_config(s); | ||
| 280 | } | ||
| 281 | } | ||
| 282 | //if old_link_up || self.link_up { | ||
| 283 | // self.poll_configurator(timestamp) | ||
| 284 | //} | ||
| 285 | |||
| 286 | if let Some(poll_at) = s.iface.poll_at(timestamp, &mut s.sockets) { | ||
| 287 | let t = Timer::at(instant_from_smoltcp(poll_at)); | ||
| 288 | pin_mut!(t); | ||
| 289 | if t.poll(cx).is_ready() { | ||
| 290 | cx.waker().wake_by_ref(); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | fn instant_to_smoltcp(instant: Instant) -> SmolInstant { | ||
| 297 | SmolInstant::from_millis(instant.as_millis() as i64) | ||
| 298 | } | ||
| 299 | |||
| 300 | fn instant_from_smoltcp(instant: SmolInstant) -> Instant { | ||
| 301 | Instant::from_millis(instant.total_millis() as u64) | ||
| 302 | } | ||
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs index 73cf2d4e4..0dc8da73a 100644 --- a/embassy-net/src/tcp.rs +++ b/embassy-net/src/tcp.rs | |||
| @@ -8,9 +8,8 @@ use smoltcp::socket::tcp; | |||
| 8 | use smoltcp::time::Duration; | 8 | use smoltcp::time::Duration; |
| 9 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; | 9 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; |
| 10 | 10 | ||
| 11 | use super::stack::Stack; | 11 | use crate::device::Device; |
| 12 | use crate::stack::SocketStack; | 12 | use crate::{SocketStack, Stack}; |
| 13 | use crate::Device; | ||
| 14 | 13 | ||
| 15 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | 14 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
| 16 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 15 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
diff --git a/embassy-net/src/udp.rs b/embassy-net/src/udp.rs index 4ddad77d4..2f5334df3 100644 --- a/embassy-net/src/udp.rs +++ b/embassy-net/src/udp.rs | |||
| @@ -7,8 +7,7 @@ use smoltcp::iface::{Interface, SocketHandle}; | |||
| 7 | use smoltcp::socket::udp::{self, PacketMetadata}; | 7 | use smoltcp::socket::udp::{self, PacketMetadata}; |
| 8 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; | 8 | use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; |
| 9 | 9 | ||
| 10 | use super::stack::SocketStack; | 10 | use crate::{Device, SocketStack, Stack}; |
| 11 | use crate::{Device, Stack}; | ||
| 12 | 11 | ||
| 13 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] | 12 | #[derive(PartialEq, Eq, Clone, Copy, Debug)] |
| 14 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 13 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
