-
Notifications
You must be signed in to change notification settings - Fork 10
feat(thread): enable rx_on_when_idle for Matter CASE session support #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
69442be
71c1c12
0d3865d
51e4eb1
17ff631
d19ee66
1d5f257
5e45ecc
c6b0b83
2e452a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -296,6 +296,16 @@ impl NetCtl for OtNetCtl<'_> { | |
| select(self.0.wait_changed(), Timer::after(Duration::from_secs(1))).await; | ||
| } | ||
|
|
||
| // Enable rx_on_when_idle AFTER Thread attach so device can receive | ||
| // unsolicited messages (CASE sessions, etc.). Must be called after | ||
| // the device has joined the network, not before. | ||
| // Parameters: rx_on_when_idle=true, device_type=false (MTD), network_data=false | ||
| if let Err(e) = self.0.set_link_mode(true, false, false) { | ||
| warn!("Failed to set link mode: {:?}", e); | ||
| } else { | ||
| info!("Link mode set: rx_on_when_idle=true"); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
| } | ||
|
|
@@ -421,6 +431,14 @@ impl<'d> OtMdns<'d> { | |
|
|
||
| /// Run the `OtMdns` instance by listening to the mDNS services and registering them with the SRP server | ||
| pub async fn run(&self, matter: &Matter<'_>) -> Result<(), OtError> { | ||
| // On first iteration only: clean up any stale SRP records from previous runs. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have concerns with this. You really need to first remove your registration from the SRP server, and then re-register. Also, and if I remember correctly, when you claim a fqdn, you receive some sort of key from the SRP server, and the key and the fqdn are all saved (or should be saved) in the persistent storage of OpenThread => the persistent storage of But perhaps I'm missing something, if you could elaborate? |
||
| // Using immediate removal (true) avoids blocking on slow/unreachable | ||
| // SRP servers which would consume the Matter Fail-Safe timer. | ||
| if !self.ot.srp_is_empty()? { | ||
| let _ = self.ot.srp_remove_all(true); | ||
| info!("SRP startup cleanup: removed stale records"); | ||
| } | ||
|
|
||
| loop { | ||
| // TODO: Not very efficient to remove and re-add everything | ||
|
|
||
|
|
@@ -443,26 +461,6 @@ impl<'d> OtMdns<'d> { | |
| "Unreachable" | ||
| ); | ||
|
|
||
| // If the device was restarted, this call will make sure that | ||
| // the SRP records are removed from the SRP server | ||
| let _ = self.ot.srp_set_conf(&SrpConf { | ||
| host_name: hostname.as_str(), | ||
| ..Default::default() | ||
| }); | ||
|
|
||
| let _ = self.ot.srp_remove_all(false); | ||
|
|
||
| // TODO: Something is still not quite right with the SRP | ||
| // We seem to get stuck here | ||
| while !self.ot.srp_is_empty()? { | ||
| debug!("Waiting for SRP records to be removed..."); | ||
| select( | ||
| Timer::after(Duration::from_secs(1)), | ||
| self.ot.srp_wait_changed(), | ||
| ) | ||
| .await; | ||
| } | ||
|
|
||
| self.ot.srp_set_conf(&SrpConf { | ||
| host_name: hostname.as_str(), | ||
| ..Default::default() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| use core::pin::pin; | ||
|
|
||
| use embassy_futures::select::select3; | ||
| use embassy_futures::select::{select3, select4}; | ||
| use embassy_time::{Duration, Timer}; | ||
| use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; | ||
|
|
||
| use openthread::{OpenThread, Radio}; | ||
|
|
@@ -366,8 +367,51 @@ where | |
| let mut persist = pin!(persister.run()); | ||
| ot.enable_ipv6(true).map_err(to_matter_err)?; | ||
| ot.srp_autostart().map_err(to_matter_err)?; | ||
| info!("SRP autostart enabled"); | ||
|
|
||
| // Enable rx_on_when_idle so device can receive unsolicited messages (CASE, etc.) | ||
| // Parameters: rx_on_when_idle=true, device_type=false (MTD), network_data=false | ||
| ot.set_link_mode(true, false, false) | ||
| .map_err(to_matter_err)?; | ||
|
|
||
| // SRP diagnostic task - logs status every 1 second for debugging | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having this diagnostics doesn't hurt, but if you could move to a separate async function - |
||
| let ot_diag = ot.clone(); | ||
| let mut srp_diag = pin!(async { | ||
| let mut tick = 0u32; | ||
| loop { | ||
| Timer::after(Duration::from_secs(1)).await; | ||
| tick += 1; | ||
|
|
||
| let server_addr = ot_diag.srp_server_addr().ok().flatten(); | ||
|
|
||
| // Count services and their states | ||
| let mut total = 0u8; | ||
| let mut registered = 0u8; | ||
| let mut adding = 0u8; | ||
| let mut removing = 0u8; | ||
| let _ = ot_diag.srp_services(|svc| { | ||
| if let Some((_, state, _)) = svc { | ||
| total += 1; | ||
| match state { | ||
| openthread::SrpState::Registered => registered += 1, | ||
| openthread::SrpState::Adding | openthread::SrpState::ToAdd => adding += 1, | ||
| openthread::SrpState::Removing | openthread::SrpState::ToRemove => removing += 1, | ||
| _ => {} | ||
| } | ||
| } | ||
| }); | ||
|
|
||
| if let Some(addr) = server_addr { | ||
| info!("SRP[{}s]: srv={}, reg={}/{}, add={}, rm={}", tick, addr, registered, total, adding, removing); | ||
| } else { | ||
| warn!("SRP[{}s]: NO SERVER, svc={}", tick, total); | ||
| } | ||
| } | ||
| #[allow(unreachable_code)] | ||
| Ok::<(), Error>(()) | ||
| }); | ||
|
|
||
| let result = select3(&mut main, &mut radio, &mut persist) | ||
| let result = select4(&mut main, &mut radio, &mut persist, &mut srp_diag) | ||
| .coalesce() | ||
| .await; | ||
|
|
||
|
|
@@ -436,6 +480,11 @@ where | |
| ot.enable_ipv6(true).map_err(to_matter_err)?; | ||
| ot.srp_autostart().map_err(to_matter_err)?; | ||
|
|
||
| // Enable rx_on_when_idle so device can receive unsolicited messages (CASE, etc.) | ||
| // Parameters: rx_on_when_idle=true, device_type=false (MTD), network_data=false | ||
| ot.set_link_mode(true, false, false) | ||
| .map_err(to_matter_err)?; | ||
|
|
||
| let result = select3(&mut main, &mut radio, &mut persist) | ||
| .coalesce() | ||
| .await; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Must be called after the device has joined the network, not before".
Why is that? Do we know the root cause reason?