Skip to content

Commit

Permalink
Merge pull request #21 from SamClercky/csma-ca-fixes
Browse files Browse the repository at this point in the history
CSMA-CA Fixes part 2
  • Loading branch information
thvdveld authored Apr 5, 2024
2 parents 8c9bf10 + 43a557f commit c5dcb71
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 19 deletions.
50 changes: 35 additions & 15 deletions dot15d4/src/csma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use user_configurable_constants::*;

use crate::{
phy::{
config::{RxConfig, TxConfig},
config::{self, RxConfig, TxConfig},
driver::{self, Driver, FrameBuffer},
radio::{
futures::{receive, transmit},
Expand Down Expand Up @@ -41,17 +41,19 @@ enum TransmissionTaskError<D: core::fmt::Debug> {
pub struct CsmaConfig {
/// All to be transmitted frames will get the ack_request flag set if they
/// are unicast and a data frame
ack_unicast: bool,
pub ack_unicast: bool,
/// All to be transmitted frames will get the ack_request flag set if they
/// are broadcast and a data frame
ack_broadcast: bool,
pub ack_broadcast: bool,
/// If false, all incoming frames will be sent up the layer stack, useful
/// if making a sniffer. This does not include MAC layer control traffic.
/// The default is true, meaning that frames not ment for us (non-broadcast
/// or frames with a different destination address) will be filtered out.
ignore_not_for_us: bool,
pub ignore_not_for_us: bool,
/// Even if there is no ack_request flag set, ack it anyway
ack_everything: bool,
pub ack_everything: bool,
/// The channel on which to transmit/receive
pub channel: config::Channel,
}

impl Default for CsmaConfig {
Expand All @@ -61,6 +63,7 @@ impl Default for CsmaConfig {
ack_broadcast: false,
ignore_not_for_us: true,
ack_everything: false,
channel: config::Channel::_26,
}
}
}
Expand Down Expand Up @@ -157,7 +160,9 @@ where
receive(
&mut **radio_guard.as_mut().unwrap(),
&mut rx.buffer,
RxConfig::default(),
RxConfig {
channel: self.config.channel,
},
),
wants_to_transmit_signal.receive(),
)
Expand Down Expand Up @@ -188,7 +193,7 @@ where

// Check if package is meant for us
if !Self::is_package_for_us(&self.hardware_address, &frame)
&& !self.config.ignore_not_for_us
&& self.config.ignore_not_for_us
{
// Package is not for us to handle, ignore
rx.dirty = false;
Expand Down Expand Up @@ -245,7 +250,10 @@ where
transmit(
&mut **radio_guard.as_mut().unwrap(),
&mut tx_ack.buffer,
TxConfig::default(),
TxConfig {
channel: self.config.channel,
..Default::default()
},
)
.await;
}
Expand Down Expand Up @@ -302,9 +310,14 @@ where
}
}

async fn wait_for_valid_ack(radio: &mut R, sequence_number: u8, ack_rx: &mut [u8; 128]) {
async fn wait_for_valid_ack(
radio: &mut R,
channel: config::Channel,
sequence_number: u8,
ack_rx: &mut [u8; 128],
) {
loop {
let result = receive(radio, ack_rx, RxConfig::default()).await;
let result = receive(radio, ack_rx, RxConfig { channel }).await;
if !result {
// No succesful receive, try again
continue;
Expand Down Expand Up @@ -348,11 +361,16 @@ where
Ok(seq_number) => sequence_number = seq_number,
Err(TransmissionTaskError::InvalidIEEEFrame) => {
// Invalid IEEE frame encountered
self.driver.error(driver::Error::InvalidStructure).await;
#[cfg(feature = "defmt")]
defmt::trace!("INVALID frame TX incoming buffer IEEE");
self.driver.error(driver::Error::InvalidIEEEStructure).await;
}
Err(TransmissionTaskError::InvalidDeviceFrame(_err)) => {
#[allow(unused_variables)]
Err(TransmissionTaskError::InvalidDeviceFrame(err)) => {
// Invalid device frame encountered
self.driver.error(driver::Error::InvalidStructure).await;
self.driver
.error(driver::Error::InvalidDeviceStructure)
.await;
}
}

Expand All @@ -365,6 +383,7 @@ where
match transmission::transmit_cca(
&self.radio,
&mut radio_guard,
self.config.channel,
&wants_to_transmit_signal,
&mut tx,
&mut timer,
Expand Down Expand Up @@ -392,6 +411,7 @@ where
match select::select(
Self::wait_for_valid_ack(
&mut *radio_guard.unwrap(),
self.config.channel,
sequence_number,
&mut ack_rx.buffer,
),
Expand Down Expand Up @@ -606,7 +626,7 @@ pub mod tests {
let mut f = FrameBuffer::default();
let mut frame_repr = FrameBuilder::new_data(&[1, 2, 3, 4])
.set_sequence_number(sequence_number)
.set_dst_address(Address::Extended([1, 2, 3, 4, 5, 6, 7, 8]))
.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)
Expand Down Expand Up @@ -675,7 +695,7 @@ pub mod tests {
let mut f = FrameBuffer::default();
let mut frame_repr = FrameBuilder::new_data(&[1, 2, 3, 4])
.set_sequence_number(sequence_number)
.set_dst_address(Address::Extended([1, 2, 3, 4, 5, 6, 7, 8]))
.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)
Expand Down
7 changes: 6 additions & 1 deletion dot15d4/src/csma/transmission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use rand_core::RngCore;
use super::user_configurable_constants::*;
use super::utils;

use crate::phy::config;
use crate::phy::config::TxConfig;
use crate::phy::driver::FrameBuffer;
use crate::phy::radio::futures::transmit;
Expand All @@ -21,6 +22,7 @@ pub enum TransmissionError {
pub async fn transmit_cca<'m, R, TIMER, Rng>(
radio: &'m Mutex<R>,
radio_guard: &mut Option<MutexGuard<'m, R>>,
channel: config::Channel,
wants_to_transmit_signal: &Sender<'_, ()>,
tx_frame: &mut FrameBuffer,
timer: &mut TIMER,
Expand All @@ -38,7 +40,10 @@ where
transmit(
&mut **radio_guard.as_mut().unwrap(),
&mut tx_frame.buffer,
TxConfig::default_with_cca(),
TxConfig {
channel,
..TxConfig::default_with_cca()
},
)
.await
};
Expand Down
2 changes: 1 addition & 1 deletion dot15d4/src/csma/user_configurable_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub const MAC_MAX_BE: u16 = 8;
pub const MAC_MAX_CSMA_BACKOFFS: u16 = 16;
pub const MAC_UNIT_BACKOFF_DURATION: Duration =
Duration::from_us((UNIT_BACKOFF_PERIOD * SYMBOL_RATE_INV_US) as i64);
pub const MAC_MAX_FRAME_RETIES: u16 = 16; // TODO: XXX
pub const MAC_MAX_FRAME_RETIES: u16 = 3; // 0-7
pub const _MAC_INTER_FRAME_TIME: Duration = Duration::from_us(1000); // TODO: XXX
/// AIFS=1ms, for SUN PHY, LECIM PHY, TVWS PHY
pub const ACKNOWLEDGEMENT_INTERFRAME_SPACING: Duration = Duration::from_us(1000);
Expand Down
8 changes: 7 additions & 1 deletion dot15d4/src/phy/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ use core::future::Future;
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Error {
/// Cca failed after to many fallbacks
CcaFailed,
/// Ack failed, after to many retransmissions
AckFailed,
InvalidStructure,
/// The buffer did not follow the correct device structure
InvalidDeviceStructure,
/// Invalid IEEE frame
InvalidIEEEStructure,
/// Something went wrong in the radio
RadioError,
}

Expand Down
7 changes: 6 additions & 1 deletion dot15d4/src/phy/radio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ pub mod tests {
return;
}

println!(
"New event arrived [{}]: {:?}",
inner.total_event_count, evnt
);

inner.total_event_count += 1;
if let Some(waker) = inner.assert_waker.take() {
waker.wake();
Expand Down Expand Up @@ -218,7 +223,7 @@ pub mod tests {

impl Default for TestRadio {
fn default() -> Self {
Self::new([0; 8])
Self::new([0xca; 8])
}
}

Expand Down

0 comments on commit c5dcb71

Please sign in to comment.