Skip to content

Commit

Permalink
Merge pull request #3933 from tyler-potyondy/15.4-syscall
Browse files Browse the repository at this point in the history
IEEE802.15.4 Framer PSDU Offset Fix
  • Loading branch information
brghena committed Apr 2, 2024
2 parents 741d2c8 + cc07545 commit 95162bf
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 21 deletions.
19 changes: 8 additions & 11 deletions capsules/extra/src/ieee802154/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ use core::cell::Cell;

use kernel::deferred_call::{DeferredCall, DeferredCallClient};
use kernel::grant::{AllowRoCount, AllowRwCount, Grant, UpcallCount};
use kernel::hil::radio::{MAX_FRAME_SIZE, PSDU_OFFSET};
use kernel::hil::radio;
use kernel::processbuffer::{ReadableProcessBuffer, WriteableProcessBuffer};
use kernel::syscall::{CommandReturn, SyscallDriver};
use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell};
Expand All @@ -70,8 +70,8 @@ use kernel::{ErrorCode, ProcessId};
const MAX_NEIGHBORS: usize = 4;
const MAX_KEYS: usize = 4;

const USER_FRAME_MAX_SIZE: usize = USER_FRAME_METADATA_SIZE + MAX_FRAME_SIZE; // 127B max payload + 3B metadata
const USER_FRAME_METADATA_SIZE: usize = 3; // 3B metadata (offset, len, mic_len)
const USER_FRAME_MAX_SIZE: usize = USER_FRAME_METADATA_SIZE + radio::MAX_FRAME_SIZE; // 3B metadata + 127B max payload

/// IDs for subscribed upcalls.
mod upcall {
Expand Down Expand Up @@ -1096,7 +1096,7 @@ impl<'a, M: device::MacDevice<'a>> device::RxClient for RadioDriver<'a, M> {
// Ring buffer format:
// | read index | write index | user_frame 0 | user_frame 1 | ... | user_frame n |
// user_frame format:
// | data_offset | data_len | mic_len | 15.4 frame |
// | header_len | payload_len | mic_len | 15.4 frame |
///////////////////////////////////////////////////////////////////////////////////////////

// 2 bytes for the readwrite buffer metadata (read / write index)
Expand All @@ -1120,11 +1120,6 @@ impl<'a, M: device::MacDevice<'a>> device::RxClient for RadioDriver<'a, M> {
let mic_len = header.security.map_or(0, |sec| sec.level.mic_len());
let frame_len = data_offset + data_len + mic_len;

// Frame length incorporates the PSDU offset, so we must subtract this value
// in addition to incorporating the user frame metadata size to obtain the
// length of the user frame.
let user_frame_len = frame_len + USER_FRAME_METADATA_SIZE - PSDU_OFFSET;

let mut read_index = rbuf[0].get() as usize;
let mut write_index = rbuf[1].get() as usize;

Expand All @@ -1140,9 +1135,11 @@ impl<'a, M: device::MacDevice<'a>> device::RxClient for RadioDriver<'a, M> {
let offset = RING_BUF_METADATA_SIZE + (write_index * USER_FRAME_MAX_SIZE);

// Copy the entire frame over to userland, preceded by three metadata bytes:
// the data offset, the data length, and the MIC length.
rbuf[(offset + USER_FRAME_METADATA_SIZE)..(offset + user_frame_len)]
.copy_from_slice(&buf[PSDU_OFFSET..frame_len]);
// the header length, the data length, and the MIC length.
rbuf[(offset + USER_FRAME_METADATA_SIZE)
..(offset + frame_len + USER_FRAME_METADATA_SIZE)]
.copy_from_slice(&buf[..frame_len]);

rbuf[offset].set(data_offset as u8);
rbuf[offset + 1].set(data_len as u8);
rbuf[offset + 2].set(mic_len as u8);
Expand Down
18 changes: 9 additions & 9 deletions capsules/extra/src/ieee802154/framer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ use crate::net::stream::{encode_bytes, encode_u32, encode_u8};

use core::cell::Cell;

use kernel::hil::radio;
use kernel::hil::radio::{self, PSDU_OFFSET};
use kernel::hil::symmetric_encryption::{CCMClient, AES128CCM};
use kernel::processbuffer::ReadableProcessSlice;
use kernel::utilities::cells::{MapCell, OptionalCell};
Expand Down Expand Up @@ -179,15 +179,15 @@ impl Frame {

/// Calculates how much more data this frame can hold
pub fn remaining_data_capacity(&self) -> usize {
self.buf.len() - radio::PSDU_OFFSET - radio::MFR_SIZE - self.info.secured_length()
self.buf.len() - self.info.secured_length()
}

/// Appends payload bytes into the frame if possible
pub fn append_payload(&mut self, payload: &[u8]) -> Result<(), ErrorCode> {
if payload.len() > self.remaining_data_capacity() {
return Err(ErrorCode::NOMEM);
}
let begin = radio::PSDU_OFFSET + self.info.unsecured_length();
let begin = self.info.unsecured_length();
self.buf[begin..begin + payload.len()].copy_from_slice(payload);
match self.info {
FrameInfoWrap::Raw(len) => self.info = FrameInfoWrap::Raw(len + payload.len()),
Expand All @@ -208,7 +208,7 @@ impl Frame {
if payload_buf.len() > self.remaining_data_capacity() {
return Err(ErrorCode::NOMEM);
}
let begin = radio::PSDU_OFFSET + self.info.unsecured_length();
let begin = self.info.unsecured_length();
payload_buf.copy_to_slice(&mut self.buf[begin..begin + payload_buf.len()]);
match self.info {
FrameInfoWrap::Raw(len) => self.info = FrameInfoWrap::Raw(len + payload_buf.len()),
Expand Down Expand Up @@ -499,7 +499,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> {
None => {
// Key not found -- pass raw encrypted packet to client
self.rx_client.map(|client| {
client.receive(buf, header, radio::PSDU_OFFSET + data_offset, data_len);
client.receive(&buf[PSDU_OFFSET..], header, data_offset, data_len);
});
return None;
}
Expand Down Expand Up @@ -555,7 +555,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> {
} else {
// No security needed, can yield the frame immediately
self.rx_client.map(|client| {
client.receive(buf, header, radio::PSDU_OFFSET + data_offset, data_len);
client.receive(&buf[PSDU_OFFSET..], header, data_offset, data_len);
});
None
}
Expand Down Expand Up @@ -755,9 +755,9 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> {
// always receiving the frame payload in plaintext.
self.rx_client.map(|client| {
client.receive(
buf,
&buf[PSDU_OFFSET..],
header,
radio::PSDU_OFFSET + data_offset,
data_offset,
frame_len - data_offset,
);
});
Expand Down Expand Up @@ -881,7 +881,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> {
payload_ies_len: 0,
};

match header.encode(&mut buf[radio::PSDU_OFFSET..], true).done() {
match header.encode(buf, true).done() {
Some((data_offset, mac_payload_offset)) => Ok(Frame {
buf: buf,
info: FrameInfoWrap::Parse(FrameInfo {
Expand Down
15 changes: 14 additions & 1 deletion capsules/extra/src/ieee802154/mac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//! through each frame for transmission.

use crate::net::ieee802154::{Header, MacAddress};
use kernel::hil::radio;
use kernel::hil::radio::{self, MAX_FRAME_SIZE, PSDU_OFFSET};
use kernel::utilities::cells::OptionalCell;
use kernel::ErrorCode;

Expand Down Expand Up @@ -146,6 +146,19 @@ impl<'a, R: radio::Radio<'a>> Mac<'a> for AwakeMac<'a, R> {
full_mac_frame: &'static mut [u8],
frame_len: usize,
) -> Result<(), (ErrorCode, &'static mut [u8])> {
// We must add the PSDU_OFFSET required for the radio
// hardware. We first error check the provided arguments
// and then shift the 15.4 frame by the `PSDU_OFFSET`.

if full_mac_frame.len() < frame_len + PSDU_OFFSET {
return Err((ErrorCode::NOMEM, full_mac_frame));
}

if frame_len > MAX_FRAME_SIZE {
return Err((ErrorCode::INVAL, full_mac_frame));
}

full_mac_frame.copy_within(0..frame_len, PSDU_OFFSET);
self.radio.transmit(full_mac_frame, frame_len)
}
}
Expand Down

0 comments on commit 95162bf

Please sign in to comment.