Skip to content

Commit

Permalink
Merge pull request #26 from SamClercky/feature-pan-id
Browse files Browse the repository at this point in the history
feat: Initial implementation of PAN IDs
  • Loading branch information
thvdveld authored Sep 27, 2024
2 parents 47ad021 + 4c539dd commit 45d0ad3
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 12 deletions.
4 changes: 3 additions & 1 deletion dot15d4/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ fn main() {
("MAC_AIFS_PERIOD", ("Duration", "Duration::from_us(1000)")),
("MAC_SIFS_PERIOD", ("Duration", "Duration::from_us(1000)")),
("MAC_LIFS_PERIOD", ("Duration", "Duration::from_us(10_000)")),
("MAC_PAN_ID", ("u16", "0xffff")),
("MAC_IMPLICIT_BROADCAST", ("bool", "false")),
]);

// Make sure we get rerun if needed
Expand All @@ -45,7 +47,7 @@ fn main() {
for (var, value) in std::env::vars() {
if let Some(name) = var.strip_prefix("DOT15D4_") {
// discard from hashmap as a way of consuming the setting
let Some((ty, _)) = configs.remove_entry(name) else {
let Some((_, (ty, _))) = configs.remove_entry(name) else {
panic!("Wrong configuration name {name}");
};

Expand Down
2 changes: 2 additions & 0 deletions dot15d4/src/csma/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub const TURNAROUND_TIME: u32 = 12;
/// The time required to perform CCA detection in symbol periods.
pub const CCA_TIME: u32 = 8;

pub const BROADCAST_PAN_ID: u16 = 0xffff;

// /// The delay between the start of the SFD and the LEIP, as described in
// /// 18.6.
// const A_LEIP_DELAY_TIME: u32 = 0.815 ms
Expand Down
110 changes: 100 additions & 10 deletions dot15d4/src/csma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{
},
time::Duration,
};
use dot15d4_frame::{Address, Frame, FrameBuilder, FrameType};
use dot15d4_frame::{Address, AddressingFieldsRepr, Frame, FrameBuilder, FrameType, FrameVersion};

#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -55,6 +55,10 @@ pub struct CsmaConfig {
pub ack_everything: bool,
/// The channel on which to transmit/receive
pub channel: config::Channel,
/// Overwrite all frames' destination PAN ID (default = false)
pub overwrite_dst_pan_id: bool,
/// Overwrite all frames' source PAN ID (default = true)
pub overwrite_src_pan_id: bool,
}

impl Default for CsmaConfig {
Expand All @@ -65,6 +69,8 @@ impl Default for CsmaConfig {
ignore_not_for_us: true,
ack_everything: false,
channel: config::Channel::_26,
overwrite_dst_pan_id: false,
overwrite_src_pan_id: true,
}
}
}
Expand Down Expand Up @@ -128,10 +134,32 @@ where
/// Checks if the current frame is intended for us. For the hardware
/// address, the full 64-bit address should be provided.
fn is_package_for_us(hardware_address: &[u8; 8], frame: &Frame<&'_ [u8]>) -> bool {
let Some(addr) = frame.addressing().and_then(|fields| fields.dst_address()) else {
// Check if the type is known, otherwise drop
if matches!(frame.frame_control().frame_type(), FrameType::Unknown) {
return false;
}
// Check if the Frame version is valid, otherwise drop
if matches!(frame.frame_control().frame_version(), FrameVersion::Unknown) {
return false;
}

let addr = match frame.addressing().and_then(|fields| fields.dst_address()) {
Some(addr) => addr,
None if MAC_IMPLICIT_BROADCAST => Address::BROADCAST,
_ => return false,
};

// Check if dst_pan (in present) is provided
let dst_pan_id = frame
.addressing()
.and_then(|fields| fields.dst_pan_id())
.unwrap_or(BROADCAST_PAN_ID);
if dst_pan_id != MAC_PAN_ID && dst_pan_id != BROADCAST_PAN_ID {
return false;
}

// TODO: Check rules if frame comes from PAN coordinator and the same MAC_PAN_ID
// TODO: Implement `macGroupRxMode` check here
match &addr {
_ if addr.is_broadcast() => true,
Address::Absent => false,
Expand Down Expand Up @@ -318,6 +346,52 @@ where
}
}

fn overwrite_pan_id<'a, RadioFrame>(
&self,
buffer: &'a mut [u8],
) -> Result<(), TransmissionTaskError<RadioFrame::Error>>
where
RadioFrame: RadioFrameMut<&'a mut [u8]>,
{
let mut frame =
RadioFrame::new_checked(buffer).map_err(TransmissionTaskError::InvalidDeviceFrame)?;
let mut frame =
Frame::new(frame.data_mut()).map_err(|_err| TransmissionTaskError::InvalidIEEEFrame)?;

let Some(mut addr) = frame
.addressing()
.map(|fields| AddressingFieldsRepr::parse(fields))
else {
return Ok(());
};

let mut changed = false;
if self.config.overwrite_src_pan_id
&& addr
.src_pan_id
.map(|pan_id| pan_id != MAC_PAN_ID)
.unwrap_or(false)
{
addr.src_pan_id = Some(MAC_PAN_ID);
changed = true;
}
if self.config.overwrite_dst_pan_id
&& addr
.dst_pan_id
.map(|pan_id| pan_id != MAC_PAN_ID)
.unwrap_or(false)
{
addr.dst_pan_id = Some(MAC_PAN_ID);
changed = true;
}

if changed {
frame.set_addressing_fields(&addr);
}

Ok(())
}

async fn wait_for_valid_ack(
radio: &mut R,
channel: config::Channel,
Expand Down Expand Up @@ -381,6 +455,22 @@ where
.await;
}
}
match self.overwrite_pan_id::<R::RadioFrame<_>>(&mut tx.buffer) {
Ok(()) => (),
Err(TransmissionTaskError::InvalidIEEEFrame) => {
// Invalid IEEE frame encountered
#[cfg(feature = "defmt")]
defmt::trace!("INVALID frame TX incoming buffer IEEE");
self.driver.error(driver::Error::InvalidIEEEStructure).await;
}
#[allow(unused_variables)]
Err(TransmissionTaskError::InvalidDeviceFrame(err)) => {
// Invalid device frame encountered
self.driver
.error(driver::Error::InvalidDeviceStructure)
.await;
}
}

let mut radio_guard = None;
'ack: for i_ack in 1..MAC_MAX_FRAME_RETIES + 1 {
Expand Down Expand Up @@ -640,8 +730,8 @@ pub mod tests {
.set_sequence_number(sequence_number)
.set_dst_address(Address::Extended(radio.ieee802154_address()))
.set_src_address(Address::Extended([1, 2, 3, 4, 9, 8, 7, 6]))
.set_dst_pan_id(0xfff)
.set_src_pan_id(0xfff)
.set_dst_pan_id(MAC_PAN_ID)
.set_src_pan_id(MAC_PAN_ID)
.finalize()
.unwrap();
frame_repr.frame_control.ack_request = true;
Expand Down Expand Up @@ -709,8 +799,8 @@ pub mod tests {
.set_sequence_number(sequence_number)
.set_dst_address(Address::Extended(radio.ieee802154_address()))
.set_src_address(Address::Extended([1, 2, 3, 4, 9, 8, 7, 6]))
.set_dst_pan_id(0xfff)
.set_src_pan_id(0xfff)
.set_dst_pan_id(MAC_PAN_ID)
.set_src_pan_id(MAC_PAN_ID)
.finalize()
.unwrap();
frame_repr.frame_control.ack_request = false;
Expand Down Expand Up @@ -759,8 +849,8 @@ pub mod tests {
.set_sequence_number(sequence_number)
.set_dst_address(Address::Extended([1, 2, 3, 4, 5, 6, 7, 8]))
.set_src_address(Address::Extended([1, 2, 3, 4, 9, 8, 7, 6]))
.set_dst_pan_id(0xfff)
.set_src_pan_id(0xfff)
.set_dst_pan_id(MAC_PAN_ID)
.set_src_pan_id(MAC_PAN_ID)
.finalize()
.unwrap();
// Set ACK to false, such that we can test if it acks
Expand Down Expand Up @@ -963,8 +1053,8 @@ pub mod tests {
.set_sequence_number(sequence_number)
.set_dst_address(Address::BROADCAST)
.set_src_address(Address::Extended([1, 2, 3, 4, 9, 8, 7, 6]))
.set_dst_pan_id(0xfff)
.set_src_pan_id(0xfff)
.set_dst_pan_id(MAC_PAN_ID)
.set_src_pan_id(MAC_PAN_ID)
.finalize()
.unwrap();
frame_repr.frame_control.ack_request = true; // This should be ignored
Expand Down
3 changes: 3 additions & 0 deletions dot15d4/src/csma/user_configurable_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ mod constants {
pub const MAC_AIFS_PERIOD: Duration = Duration::from_us(1000);
pub const MAC_SIFS_PERIOD: Duration = Duration::from_us(1000); // TODO: SIFS=XXX
pub const MAC_LIFS_PERIOD: Duration = Duration::from_us(10_000); // TODO: LIFS=XXX
// PAN Id
pub const MAC_PAN_ID: u16 = 0xffff;
pub const MAC_IMPLICIT_BROADCAST: bool = false;
}

#[cfg(not(test))]
Expand Down
9 changes: 8 additions & 1 deletion dot15d4/src/phy/radio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ pub trait TxToken {

#[cfg(test)]
pub mod tests {
use core::panic;
use std::{
cell::RefCell,
collections::VecDeque,
Expand Down Expand Up @@ -178,6 +179,10 @@ pub mod tests {
if let Some(waker) = inner.assert_waker.take() {
waker.wake();
}
// Do not check if we are already panicking
if std::thread::panicking() {
return;
}
if let Some(assert_nxt) = inner.assert_nxt.pop_front() {
assert_eq!(
assert_nxt, evnt,
Expand Down Expand Up @@ -215,7 +220,9 @@ pub mod tests {
match select::select(wait_for_events, StdDelay::default().delay_ms(5000)).await {
crate::sync::Either::First(_) => {}
crate::sync::Either::Second(_) => {
panic!("Waiting timedout for events -> there is a bug in the code")
if !std::thread::panicking() {
panic!("Waiting timedout for events -> there is a bug in the code")
}
}
}
}
Expand Down

0 comments on commit 45d0ad3

Please sign in to comment.