Skip to content

Commit

Permalink
Merge branch 'main' into csma-ca-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
thvdveld authored Mar 15, 2024
2 parents f69dfcf + fe565c5 commit 4b40f1f
Show file tree
Hide file tree
Showing 10 changed files with 351 additions and 113 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Rust
name: Build and Test

on:
push:
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# dot15d4
# dot15d4 [![codecov](https://codecov.io/gh/thvdveld/dot15d4/graph/badge.svg?token=XETJ1SV5B0)](https://codecov.io/gh/thvdveld/dot15d4) ![example workflow](https://github.com/thvdveld/dot15d4/actions/workflows/rust.yml/badge.svg)


`dot15d4` is a IEEE 802.15.4 frame parsing library written in Rust.
It uses the same style of parsing and emitting as the [`smoltcp`](https://github.com/smoltcp-rs/smoltcp) library.
Expand Down Expand Up @@ -62,6 +63,10 @@ Information Elements
#slot frames: 0
```

## Coverage

![Coverage](https://codecov.io/gh/thvdveld/dot15d4/graphs/sunburst.svg?token=XETJ1SV5B0)

## License

Licensed under either of
Expand Down
8 changes: 4 additions & 4 deletions dot15d4-cat/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,11 @@ fn main() {
w.writeln(format!("{}", "Addressing".underline().bold()));
w.increase_indent();

if let Some(dst_pan_id) = addr.dst_pan_id(&fc) {
if let Some(dst_pan_id) = addr.dst_pan_id() {
w.writeln(format!("{}: {:x}", "dst pan id".bold(), dst_pan_id));
}

if let Some(dst_addr) = addr.dst_address(&fc) {
if let Some(dst_addr) = addr.dst_address() {
w.writeln(format!(
"{}: {}{}",
"dst addr".bold(),
Expand All @@ -147,11 +147,11 @@ fn main() {
));
}

if let Some(src_pan_id) = addr.src_pan_id(&fc) {
if let Some(src_pan_id) = addr.src_pan_id() {
w.writeln(format!("{}: {:x}", "src pan id".bold(), src_pan_id));
}

if let Some(src_addr) = addr.src_address(&fc) {
if let Some(src_addr) = addr.src_address() {
w.writeln(format!(
"{}: {}{}",
"src addr".bold(),
Expand Down
246 changes: 185 additions & 61 deletions dot15d4-frame/src/addressing.rs

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions dot15d4-frame/src/frame_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ impl<T: AsRef<[u8]>> FrameControl<T> {
Self { buffer }
}

/// Return the inner buffer.
pub fn into_inner(self) -> T {
self.buffer
}

/// Return the [`FrameType`] field.
pub fn frame_type(&self) -> FrameType {
let b = &self.buffer.as_ref()[..2];
Expand Down Expand Up @@ -276,3 +281,115 @@ impl<T: AsRef<[u8]>> core::fmt::Display for FrameControl<T> {
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn bad_length() {
let fc = [0x0];
assert!(FrameControl::new(&fc).is_err());
}

#[test]
fn get_fields() {
let fc = [0x0, 0x0];
let fc = FrameControl::new(&fc).unwrap();
assert_eq!(fc.frame_type(), FrameType::Beacon);
assert_eq!(fc.security_enabled(), false);
assert_eq!(fc.frame_pending(), false);
assert_eq!(fc.ack_request(), false);
assert_eq!(fc.pan_id_compression(), false);
assert_eq!(fc.sequence_number_suppression(), false);
assert_eq!(fc.information_elements_present(), false);
assert_eq!(fc.dst_addressing_mode(), AddressingMode::Absent);
assert_eq!(fc.src_addressing_mode(), AddressingMode::Absent);
assert_eq!(fc.frame_version(), FrameVersion::Ieee802154_2003);

let fc = [0b0010_1001, 0b1010_1010];
let fc = FrameControl::new(&fc).unwrap();
assert_eq!(fc.frame_type(), FrameType::Data);
assert_eq!(fc.security_enabled(), true);
assert_eq!(fc.frame_pending(), false);
assert_eq!(fc.ack_request(), true);
assert_eq!(fc.pan_id_compression(), false);
assert_eq!(fc.sequence_number_suppression(), false);
assert_eq!(fc.information_elements_present(), true);
assert_eq!(fc.dst_addressing_mode(), AddressingMode::Short);
assert_eq!(fc.src_addressing_mode(), AddressingMode::Short);
assert_eq!(fc.frame_version(), FrameVersion::Ieee802154_2020);
}

#[test]
fn set_fields() {
let mut fc = [0x0, 0x0];
let mut fc = FrameControl::new_unchecked(&mut fc);
fc.set_frame_type(FrameType::Beacon);
fc.set_security_enabled(false);
fc.set_frame_pending(false);
fc.set_ack_request(false);
fc.set_pan_id_compression(false);
fc.set_sequence_number_suppression(false);
fc.set_information_elements_present(false);
fc.set_dst_addressing_mode(AddressingMode::Absent);
fc.set_src_addressing_mode(AddressingMode::Absent);
fc.set_frame_version(FrameVersion::Ieee802154_2003);
assert_eq!(*fc.into_inner(), [0x0, 0x0]);

let mut fc = [0x0, 0x0];
let mut fc = FrameControl::new_unchecked(&mut fc);
fc.set_frame_type(FrameType::Data);
fc.set_security_enabled(true);
fc.set_frame_pending(false);
fc.set_ack_request(true);
fc.set_pan_id_compression(false);
fc.set_sequence_number_suppression(false);
fc.set_information_elements_present(true);
fc.set_dst_addressing_mode(AddressingMode::Short);
fc.set_src_addressing_mode(AddressingMode::Short);
fc.set_frame_version(FrameVersion::Ieee802154_2020);
assert_eq!(*fc.into_inner(), [0b0010_1001, 0b1010_1010]);
}

#[test]
fn frame_type() {
assert_eq!(FrameType::from(0b000), FrameType::Beacon);
assert_eq!(FrameType::from(0b001), FrameType::Data);
assert_eq!(FrameType::from(0b010), FrameType::Ack);
assert_eq!(FrameType::from(0b011), FrameType::MacCommand);
assert_eq!(FrameType::from(0b101), FrameType::Multipurpose);
assert_eq!(FrameType::from(0b110), FrameType::FragmentOrFrak);
assert_eq!(FrameType::from(0b111), FrameType::Extended);
assert_eq!(FrameType::from(0b100), FrameType::Unknown);
}

#[test]
fn frame_version() {
assert_eq!(FrameVersion::from(0b00), FrameVersion::Ieee802154_2003);
assert_eq!(FrameVersion::from(0b01), FrameVersion::Ieee802154_2006);
assert_eq!(FrameVersion::from(0b10), FrameVersion::Ieee802154_2020);
assert_eq!(FrameVersion::from(0b11), FrameVersion::Unknown);
}

#[test]
fn formatting() {
let fc = [0b0010_1001, 0b1010_1010];
let fc = FrameControl::new(&fc).unwrap();
assert_eq!(
format!("{}", fc),
r"Frame Control
type: Data
security enabled: 1
frame pending: 0
ack request: 1
pan id compression: 0
sequence number suppression: 0
information elements present: 1
dst addressing mode: Short
src addressing mode: Short
frame version: Ieee802154_2020
"
);
}
}
25 changes: 13 additions & 12 deletions dot15d4-frame/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
//! # ];
//! let frame = Frame::new(&frame).unwrap();
//! let fc = frame.frame_control();
//! let src_addr = frame.addressing().unwrap().src_address(&fc);
//! let dst_addr = frame.addressing().unwrap().dst_address(&fc);
//! let src_addr = frame.addressing().unwrap().src_address();
//! let dst_addr = frame.addressing().unwrap().dst_address();
//!
//! assert_eq!(fc.frame_type(), FrameType::Beacon);
//!
Expand Down Expand Up @@ -288,7 +288,7 @@ impl<T: AsRef<[u8]>> Frame<T> {
}

/// Return an [`AddressingFields`] reader.
pub fn addressing(&self) -> Option<AddressingFields<&'_ [u8]>> {
pub fn addressing(&self) -> Option<AddressingFields<&'_ [u8], &'_ [u8]>> {
let fc = self.frame_control();

if matches!(fc.frame_type(), FrameType::Ack)
Expand All @@ -302,9 +302,9 @@ impl<T: AsRef<[u8]>> Frame<T> {
}

if fc.sequence_number_suppression() {
AddressingFields::new(&self.buffer.as_ref()[2..], &fc).ok()
AddressingFields::new(&self.buffer.as_ref()[2..], fc).ok()
} else {
AddressingFields::new(&self.buffer.as_ref()[3..], &fc).ok()
AddressingFields::new(&self.buffer.as_ref()[3..], fc).ok()
}
}

Expand All @@ -318,7 +318,7 @@ impl<T: AsRef<[u8]>> Frame<T> {
offset += !fc.sequence_number_suppression() as usize;

if let Some(af) = self.addressing() {
offset += af.len(&fc);
offset += af.len();
}

Some(AuxiliarySecurityHeader::new(
Expand All @@ -337,7 +337,7 @@ impl<T: AsRef<[u8]>> Frame<T> {
offset += !fc.sequence_number_suppression() as usize;

if let Some(af) = self.addressing() {
offset += af.len(&fc);
offset += af.len();
}

Some(InformationElements::new(&self.buffer.as_ref()[offset..]).ok()?)
Expand All @@ -360,7 +360,7 @@ impl<'f, T: AsRef<[u8]> + ?Sized> Frame<&'f T> {
}

if let Some(af) = self.addressing() {
offset += af.len(&fc);
offset += af.len();
}

if fc.security_enabled() {
Expand Down Expand Up @@ -417,7 +417,8 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
pub fn set_addressing_fields(&mut self, addressing_fields: &AddressingFieldsRepr) {
let start = 2 + (!self.frame_control().sequence_number_suppression() as usize);

let mut w = AddressingFields::new_unchecked(&mut self.buffer.as_mut()[start..]);
let (fc, addressing) = self.buffer.as_mut().split_at_mut(start);
let mut w = AddressingFields::new_unchecked(addressing, FrameControl::new_unchecked(fc));
w.write_fields(addressing_fields);
}

Expand All @@ -438,7 +439,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
offset += !self.frame_control().sequence_number_suppression() as usize;

if let Some(af) = self.addressing() {
offset += af.len(&self.frame_control());
offset += af.len();
}

ie.emit(&mut self.buffer.as_mut()[offset..], contains_payload);
Expand All @@ -454,7 +455,7 @@ impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
}

if let Some(af) = self.addressing() {
offset += af.len(&self.frame_control());
offset += af.len();
}

if self.frame_control().security_enabled() {
Expand All @@ -478,7 +479,7 @@ impl<'f, T: AsRef<[u8]> + ?Sized> core::fmt::Display for Frame<&'f T> {
}

if let Some(af) = self.addressing() {
af.fmt(f, &fc)?;
write!(f, "{af}")?;
}

if fc.security_enabled() {
Expand Down
14 changes: 7 additions & 7 deletions dot15d4-frame/src/repr/addressing.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::super::{Address, AddressingFields, AddressingMode, FrameControl};
use super::super::{Address, AddressingFields, AddressingMode};
use super::FrameControlRepr;

/// A high-level representation of the IEEE 802.15.4 Addressing Fields.
Expand All @@ -17,12 +17,12 @@ pub struct AddressingFieldsRepr {

impl AddressingFieldsRepr {
/// Parse the Addressing Fields from the given buffer.
pub fn parse<'f>(addressing: AddressingFields<&'f [u8]>, fc: FrameControl<&'f [u8]>) -> Self {
pub fn parse(addressing: AddressingFields<&'_ [u8], &'_ [u8]>) -> Self {
Self {
dst_pan_id: addressing.dst_pan_id(&fc),
dst_address: addressing.dst_address(&fc),
src_pan_id: addressing.src_pan_id(&fc),
src_address: addressing.src_address(&fc),
dst_pan_id: addressing.dst_pan_id(),
dst_address: addressing.dst_address(),
src_pan_id: addressing.src_pan_id(),
src_address: addressing.src_address(),
}
}

Expand All @@ -48,7 +48,7 @@ impl AddressingFieldsRepr {
}

/// Emit the Addressing Fields into the given buffer.
pub fn emit(&self, _buffer: &AddressingFields<&'_ mut [u8]>, _fc: &FrameControl<&'_ [u8]>) {
pub fn emit(&self, _buffer: &AddressingFields<&'_ mut [u8], &'_ [u8]>) {
todo!();
}
}
2 changes: 1 addition & 1 deletion dot15d4-frame/src/repr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl<'f> FrameRepr<'f> {
let frame_control = FrameControlRepr::parse(reader.frame_control())?;
let addressing_fields = reader
.addressing()
.map(|af| AddressingFieldsRepr::parse(af, reader.frame_control()));
.map(|af| AddressingFieldsRepr::parse(af));
let information_elements = reader
.information_elements()
.map(InformationElementsRepr::parse)
Expand Down
26 changes: 13 additions & 13 deletions dot15d4-frame/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ fn parse_ack_frame() {
assert!(frame.sequence_number() == Some(55));

let addressing = frame.addressing().unwrap();
assert_eq!(addressing.dst_pan_id(&fc), Some(0xabcd));
assert_eq!(addressing.dst_pan_id(), Some(0xabcd));
assert_eq!(
addressing.dst_address(&fc),
addressing.dst_address(),
Some(Address::Extended([
0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02
]))
);
assert_eq!(addressing.src_pan_id(&fc), None);
assert_eq!(addressing.src_address(&fc), Some(Address::Absent));
assert_eq!(addressing.src_pan_id(), None);
assert_eq!(addressing.src_address(), Some(Address::Absent));

let ie = frame.information_elements().unwrap();
let mut headers = ie.header_information_elements();
Expand Down Expand Up @@ -137,11 +137,11 @@ fn parse_data_frame() {
assert!(frame.sequence_number() == Some(1));

let addressing = frame.addressing().unwrap();
assert_eq!(addressing.dst_pan_id(&fc), Some(0xabcd));
assert_eq!(addressing.dst_address(&fc), Some(Address::BROADCAST));
assert_eq!(addressing.src_pan_id(&fc), None);
assert_eq!(addressing.dst_pan_id(), Some(0xabcd));
assert_eq!(addressing.dst_address(), Some(Address::BROADCAST));
assert_eq!(addressing.src_pan_id(), None);
assert_eq!(
addressing.src_address(&fc),
addressing.src_address(),
Some(Address::Extended([
0x00, 0x12, 0x4b, 0x00, 0x14, 0xb5, 0xd9, 0xc7
]))
Expand Down Expand Up @@ -200,16 +200,16 @@ fn parse_enhanced_beacon() {
assert_eq!(fc.frame_version(), FrameVersion::Ieee802154_2020);

let addressing = frame.addressing().unwrap();
assert_eq!(addressing.dst_pan_id(&fc), Some(0xabcd),);
assert_eq!(addressing.src_pan_id(&fc), None,);
assert_eq!(addressing.dst_address(&fc), Some(Address::BROADCAST));
assert_eq!(addressing.dst_pan_id(), Some(0xabcd),);
assert_eq!(addressing.src_pan_id(), None,);
assert_eq!(addressing.dst_address(), Some(Address::BROADCAST));
assert_eq!(
addressing.src_address(&fc),
addressing.src_address(),
Some(Address::Extended([
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01
]))
);
assert_eq!(addressing.len(&fc), 12);
assert_eq!(addressing.len(), 12);

let ie = frame.information_elements().unwrap();

Expand Down
Loading

0 comments on commit 4b40f1f

Please sign in to comment.