Merge pull request #1874 from JuliDi/eth-getstatus-async

embassy-net: add async wait_config_up
This commit is contained in:
Dario Nieuwenhuis 2023-09-09 20:06:52 +00:00 committed by GitHub
commit 2132afb48b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 6 deletions

View file

@ -172,6 +172,7 @@ impl Config {
/// ///
/// # Example /// # Example
/// ```rust /// ```rust
/// # use embassy_net::Config;
/// let _cfg = Config::dhcpv4(Default::default()); /// let _cfg = Config::dhcpv4(Default::default());
/// ``` /// ```
#[cfg(feature = "dhcpv4")] #[cfg(feature = "dhcpv4")]
@ -226,6 +227,7 @@ struct Inner<D: Driver> {
static_v6: Option<StaticConfigV6>, static_v6: Option<StaticConfigV6>,
#[cfg(feature = "dhcpv4")] #[cfg(feature = "dhcpv4")]
dhcp_socket: Option<SocketHandle>, dhcp_socket: Option<SocketHandle>,
config_waker: WakerRegistration,
#[cfg(feature = "dns")] #[cfg(feature = "dns")]
dns_socket: SocketHandle, dns_socket: SocketHandle,
#[cfg(feature = "dns")] #[cfg(feature = "dns")]
@ -297,6 +299,7 @@ impl<D: Driver + 'static> Stack<D> {
static_v6: None, static_v6: None,
#[cfg(feature = "dhcpv4")] #[cfg(feature = "dhcpv4")]
dhcp_socket: None, dhcp_socket: None,
config_waker: WakerRegistration::new(),
#[cfg(feature = "dns")] #[cfg(feature = "dns")]
dns_socket: socket.sockets.add(dns::Socket::new( dns_socket: socket.sockets.add(dns::Socket::new(
&[], &[],
@ -363,6 +366,55 @@ impl<D: Driver + 'static> Stack<D> {
v4_up || v6_up v4_up || v6_up
} }
/// Wait for the network stack to obtain a valid IP configuration.
///
/// ## Notes:
/// - Ensure [`Stack::run`] has been called before using this function.
///
/// - This function may never return (e.g. if no configuration is obtained through DHCP).
/// The caller is supposed to handle a timeout for this case.
///
/// ## Example
/// ```ignore
/// let config = embassy_net::Config::dhcpv4(Default::default());
///// Init network stack
/// let stack = &*make_static!(embassy_net::Stack::new(
/// device,
/// config,
/// make_static!(embassy_net::StackResources::<2>::new()),
/// seed
/// ));
/// // Launch network task that runs `stack.run().await`
/// spawner.spawn(net_task(stack)).unwrap();
/// // Wait for DHCP config
/// stack.wait_config_up().await;
/// // use the network stack
/// // ...
/// ```
pub async fn wait_config_up(&self) {
// If the config is up already, we can return immediately.
if self.is_config_up() {
return;
}
poll_fn(|cx| {
if self.is_config_up() {
Poll::Ready(())
} else {
// If the config is not up, we register a waker that is woken up
// when a config is applied (static or DHCP).
trace!("Waiting for config up");
self.with_mut(|_, i| {
i.config_waker.register(cx.waker());
});
Poll::Pending
}
})
.await;
}
/// Get the current IPv4 configuration. /// Get the current IPv4 configuration.
/// ///
/// If using DHCP, this will be None if DHCP hasn't been able to /// If using DHCP, this will be None if DHCP hasn't been able to
@ -706,6 +758,8 @@ impl<D: Driver + 'static> Inner<D> {
s.sockets s.sockets
.get_mut::<smoltcp::socket::dns::Socket>(self.dns_socket) .get_mut::<smoltcp::socket::dns::Socket>(self.dns_socket)
.update_servers(&dns_servers[..]); .update_servers(&dns_servers[..]);
self.config_waker.wake();
} }
fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) { fn poll(&mut self, cx: &mut Context<'_>, s: &mut SocketStack) {

View file

@ -79,7 +79,10 @@ async fn main(spawner: Spawner) -> ! {
)); ));
// Launch network task // Launch network task
unwrap!(spawner.spawn(net_task(&stack))); unwrap!(spawner.spawn(net_task(stack)));
// Ensure DHCP configuration is up before trying connect
stack.wait_config_up().await;
info!("Network task initialized"); info!("Network task initialized");

View file

@ -80,7 +80,10 @@ async fn main(spawner: Spawner) -> ! {
)); ));
// Launch network task // Launch network task
unwrap!(spawner.spawn(net_task(&stack))); unwrap!(spawner.spawn(net_task(stack)));
// Ensure DHCP configuration is up before trying connect
stack.wait_config_up().await;
info!("Network task initialized"); info!("Network task initialized");

View file

@ -101,6 +101,9 @@ async fn main(spawner: Spawner) -> ! {
// Launch network task // Launch network task
unwrap!(spawner.spawn(net_task(&stack))); unwrap!(spawner.spawn(net_task(&stack)));
// Ensure DHCP configuration is up before trying connect
stack.wait_config_up().await;
info!("Network task initialized"); info!("Network task initialized");
// Then we can use it! // Then we can use it!

View file

@ -83,6 +83,9 @@ async fn main(spawner: Spawner) -> ! {
// Launch network task // Launch network task
unwrap!(spawner.spawn(net_task(&stack))); unwrap!(spawner.spawn(net_task(&stack)));
// Ensure DHCP configuration is up before trying connect
stack.wait_config_up().await;
info!("Network task initialized"); info!("Network task initialized");
// Then we can use it! // Then we can use it!

View file

@ -82,13 +82,13 @@ async fn main(spawner: Spawner) -> ! {
)); ));
// Launch network task // Launch network task
unwrap!(spawner.spawn(net_task(&stack))); unwrap!(spawner.spawn(net_task(stack)));
// Ensure DHCP configuration is up before trying connect
stack.wait_config_up().await;
info!("Network task initialized"); info!("Network task initialized");
// To ensure DHCP configuration before trying connect
Timer::after(Duration::from_secs(20)).await;
static STATE: TcpClientState<1, 1024, 1024> = TcpClientState::new(); static STATE: TcpClientState<1, 1024, 1024> = TcpClientState::new();
let client = TcpClient::new(&stack, &STATE); let client = TcpClient::new(&stack, &STATE);