From 00c1a8bb86119d40327f9afa4b10828b2db91e90 Mon Sep 17 00:00:00 2001 From: tylerp Date: Mon, 12 Feb 2024 14:15:36 -0800 Subject: [PATCH 1/9] Alter Frame struct to support preformed packets These changes alter the Frame struct to support forming a frame object from a buffer that is provided from userland preformed (i.e. there is not a need to form the header). For a preformed object, the frame info is irrelevant. Wrapping this in an option allows this to be ignored in the case of when a provided packet is preformed. --- capsules/extra/src/ieee802154/device.rs | 2 + capsules/extra/src/ieee802154/framer.rs | 41 +++++++++++++++----- capsules/extra/src/ieee802154/virtual_mac.rs | 4 ++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/capsules/extra/src/ieee802154/device.rs b/capsules/extra/src/ieee802154/device.rs index 03ec7dda50..016535ccfe 100644 --- a/capsules/extra/src/ieee802154/device.rs +++ b/capsules/extra/src/ieee802154/device.rs @@ -73,6 +73,8 @@ pub trait MacDevice<'a> { security_needed: Option<(SecurityLevel, KeyId)>, ) -> Result; + fn buf_to_frame(&self, buf: &'static mut [u8]) -> Frame; + /// Transmits a frame that has been prepared by the above process. If the /// transmission process fails, the buffer inside the frame is returned so /// that it can be re-used. diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index a173a3419d..24cf7aaac0 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -99,7 +99,7 @@ use kernel::ErrorCode; #[derive(Eq, PartialEq, Debug)] pub struct Frame { buf: &'static mut [u8], - info: FrameInfo, + info: Option, } /// This contains just enough information about a frame to determine @@ -134,7 +134,13 @@ 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() + - radio::PSDU_OFFSET + - radio::MFR_SIZE + - self + .info + .expect("Invalid frame info provided") + .secured_length() } /// Appends payload bytes into the frame if possible @@ -142,9 +148,13 @@ impl Frame { if payload.len() > self.remaining_data_capacity() { return Err(ErrorCode::NOMEM); } - let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); + let begin = radio::PSDU_OFFSET + + self + .info + .expect("Invalid frame info provided") + .unsecured_length(); self.buf[begin..begin + payload.len()].copy_from_slice(payload); - self.info.data_len += payload.len(); + self.info.expect("Invalid frame info provided").data_len += payload.len(); Ok(()) } @@ -156,11 +166,16 @@ impl Frame { payload_buf: &ReadableProcessSlice, ) -> Result<(), ErrorCode> { if payload_buf.len() > self.remaining_data_capacity() { + kernel::debug!("here"); return Err(ErrorCode::NOMEM); } - let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); + let begin = radio::PSDU_OFFSET + + self + .info + .expect("Invalid frame info provided") + .unsecured_length(); payload_buf.copy_to_slice(&mut self.buf[begin..begin + payload_buf.len()]); - self.info.data_len += payload_buf.len(); + self.info.expect("Invalid frame info provided").data_len += payload_buf.len(); Ok(()) } @@ -816,19 +831,26 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { match header.encode(&mut buf[radio::PSDU_OFFSET..], true).done() { Some((data_offset, mac_payload_offset)) => Ok(Frame { buf: buf, - info: FrameInfo { + info: Some(FrameInfo { frame_type: FrameType::Data, mac_payload_offset: mac_payload_offset, data_offset: data_offset, data_len: 0, mic_len: mic_len, security_params: security_desc.map(|(sec, key, nonce)| (sec.level, key, nonce)), - }, + }), }), None => Err(buf), } } + fn buf_to_frame(&self, buf: &'static mut [u8]) -> Frame { + Frame { + buf: buf, + info: None, + } + } + fn transmit(&self, frame: Frame) -> Result<(), (ErrorCode, &'static mut [u8])> { let Frame { buf, info } = frame; let state = match self.tx_state.take() { @@ -839,7 +861,8 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { }; match state { TxState::Idle => { - let next_state = self.outgoing_frame_security(buf, info); + let next_state = + self.outgoing_frame_security(buf, info.expect("Invalid frame info provided")); self.tx_state.replace(next_state); self.step_transmit_state() } diff --git a/capsules/extra/src/ieee802154/virtual_mac.rs b/capsules/extra/src/ieee802154/virtual_mac.rs index efc499d375..918cd6b4f9 100644 --- a/capsules/extra/src/ieee802154/virtual_mac.rs +++ b/capsules/extra/src/ieee802154/virtual_mac.rs @@ -287,6 +287,10 @@ impl<'a> device::MacDevice<'a> for MacUser<'a> { .prepare_data_frame(buf, dst_pan, dst_addr, src_pan, src_addr, security_needed) } + fn buf_to_frame(&self, buf: &'static mut [u8]) -> framer::Frame { + self.mux.mac.buf_to_frame(buf) + } + fn transmit(&self, frame: framer::Frame) -> Result<(), (ErrorCode, &'static mut [u8])> { // If the muxer is idle, immediately transmit the frame, otherwise // attempt to queue the transmission request. However, each MAC user can From 84ce8ac674c49dba54c8d2cce3b06dcadc121c10 Mon Sep 17 00:00:00 2001 From: tylerp Date: Mon, 12 Feb 2024 14:20:10 -0800 Subject: [PATCH 2/9] Updates to 15.4 driver to support direct send - changes pending_tx flag from Option enum to now represent 3 possible states: Parse(..), Direct, Empty. The Parse(..) variant represents the case of the capsule forming the packet header / encrypting from the provided fields. The Direct variant operates to directly transmitted the provided buffer (assumes userprocess formed packet). The Empty state represents no packet pending. - adds syscall command to send packet directly without packet forming - updates logic to handle direct send instance --- capsules/extra/src/ieee802154/driver.rs | 151 ++++++++++++++++-------- 1 file changed, 101 insertions(+), 50 deletions(-) diff --git a/capsules/extra/src/ieee802154/driver.rs b/capsules/extra/src/ieee802154/driver.rs index 06e07efe6e..365b7fa441 100644 --- a/capsules/extra/src/ieee802154/driver.rs +++ b/capsules/extra/src/ieee802154/driver.rs @@ -177,9 +177,39 @@ impl KeyDescriptor { } } +enum PendingTX { + Parse(u16, Option<(SecurityLevel, KeyId)>), + Direct, + Empty, +} + +impl Default for PendingTX { + fn default() -> Self { + PendingTX::Empty + } +} + +impl PendingTX { + fn is_some(&self) -> bool { + match self { + PendingTX::Empty => false, + _ => true, + } + } + + /// Take the pending transmission, replacing it with `Empty` and return the current PendingTx + fn take(&mut self) -> PendingTX { + match core::mem::replace(self, PendingTX::Empty) { + PendingTX::Parse(addr, sec) => PendingTX::Parse(addr, sec), + PendingTX::Direct => PendingTX::Direct, + PendingTX::Empty => PendingTX::Empty, + } + } +} + #[derive(Default)] pub struct App { - pending_tx: Option<(u16, Option<(SecurityLevel, KeyId)>)>, + pending_tx: PendingTX, } pub struct RadioDriver<'a> { @@ -413,57 +443,63 @@ impl<'a> RadioDriver<'a> { /// idle and the app has a pending transmission. #[inline] fn perform_tx_sync(&self, processid: ProcessId) -> Result<(), ErrorCode> { - self.apps.enter(processid, |app, kerel_data| { - let (dst_addr, security_needed) = match app.pending_tx.take() { - Some(pending_tx) => pending_tx, - None => { - return Ok(()); - } - }; - let result = self.kernel_tx.take().map_or(Err(ErrorCode::NOMEM), |kbuf| { - // Prepare the frame headers - let pan = self.mac.get_pan(); - let dst_addr = MacAddress::Short(dst_addr); - let src_addr = MacAddress::Short(self.mac.get_address()); - let mut frame = match self.mac.prepare_data_frame( - kbuf, - pan, - dst_addr, - pan, - src_addr, - security_needed, - ) { - Ok(frame) => frame, - Err(kbuf) => { - self.kernel_tx.replace(kbuf); - return Err(ErrorCode::FAIL); - } - }; - - // Append the payload: there must be one - let result = kerel_data - .get_readonly_processbuffer(ro_allow::WRITE) - .and_then(|write| write.enter(|payload| frame.append_payload_process(payload))) - .unwrap_or(Err(ErrorCode::INVAL)); - if result != Ok(()) { - return result; - } + self.apps.enter(processid, |app, kernel_data| { + // The use of this take method is somewhat overkill, but serves to ensure that + // this, or future, implementations do not forget to "remove" the pending_tx + // from the app after processing. + let curr_tx = app.pending_tx.take(); + if let PendingTX::Empty = curr_tx { + // this may not be the correct return value for handling this. This is following current convention + return Ok(()) + } + + - // Finally, transmit the frame - match self.mac.transmit(frame) { - Ok(()) => Ok(()), - Err((ecode, buf)) => { - self.kernel_tx.put(Some(buf)); - Err(ecode) + self.kernel_tx.take().map_or(Err(ErrorCode::NOMEM), |kbuf| { + match curr_tx { + PendingTX::Empty => { + unreachable!("PendingTX::Empty should have been handled earlier with guard statement.") } - } - }); - if result == Ok(()) { - self.current_app.set(processid); - } - result + PendingTX::Direct => Ok(self.mac.buf_to_frame(kbuf)), + PendingTX::Parse(dst_addr, security_needed) => { + // Prepare the frame headers + let pan = self.mac.get_pan(); + let dst_addr = MacAddress::Short(dst_addr); + let src_addr = MacAddress::Short(self.mac.get_address()); + self.mac.prepare_data_frame( + kbuf, + pan, + dst_addr, + pan, + src_addr, + security_needed, + ).map_or_else(|err_buf| { + self.kernel_tx.replace(err_buf); + Err(ErrorCode::FAIL) + }, | frame | + Ok(frame) + ) + }}}).map(|mut frame| { + + // Obtain the payload from the userprocess. Although a ReadableProcess buffer has the potential + // to change, this given buffer is guaranteed to remain the same over the course of this method + // (TRD 4.4.1). As such, we can safely assume that the obtained reference to this payload is + // valid including when we copy the payload into the kernel_tx buffer. + kernel_data + .get_readonly_processbuffer(ro_allow::WRITE) + .and_then(|write| write.enter(|payload| + frame.append_payload_process(payload) + ))?.map( |()| + { + self.mac.transmit(frame).map_or_else(|(errorcode, error_buf)| { + self.kernel_tx.replace(error_buf); + Err(errorcode) + }, |_| {self.current_app.set(processid); Ok(())} + )} + )? + })? - } + })?} /// Schedule the next transmission if there is one pending. Performs the /// transmission asynchronously, returning any errors via callbacks. @@ -900,7 +936,11 @@ impl SyscallDriver for RadioDriver<'_> { if next_tx.is_none() { return Err(ErrorCode::INVAL); } - app.pending_tx = next_tx; + + match next_tx { + Some((dst_addr, sec)) => app.pending_tx = PendingTX::Parse(dst_addr, sec), + None => app.pending_tx = PendingTX::Empty, + } Ok(()) }) .map_or_else( @@ -911,6 +951,17 @@ impl SyscallDriver for RadioDriver<'_> { }, ) } + 27 => { + self.apps + .enter(processid, |app, _| { + if app.pending_tx.is_some() { + // Cannot support more than one pending tx per process. + return CommandReturn::failure(ErrorCode::BUSY); + } + app.pending_tx = PendingTX::Direct; + self.do_next_tx_sync(processid).into() + }).unwrap_or_else(|err| CommandReturn::failure(err.into())) + }, _ => CommandReturn::failure(ErrorCode::NOSUPPORT), } } From 60f5005ed6e91dbfc18544ac08a3b96249f4a50f Mon Sep 17 00:00:00 2001 From: tylerp Date: Mon, 12 Feb 2024 16:32:47 -0800 Subject: [PATCH 3/9] Updated wrapper for FrameInfo and added length arg This commit successfully sends "direct" 15.4 packets as framed by the userland application. Tested and exhibited correct behavior using wireshark. --- capsules/extra/src/ieee802154/device.rs | 2 +- capsules/extra/src/ieee802154/driver.rs | 12 +- capsules/extra/src/ieee802154/framer.rs | 118 ++++++++++++------- capsules/extra/src/ieee802154/virtual_mac.rs | 4 +- 4 files changed, 85 insertions(+), 51 deletions(-) diff --git a/capsules/extra/src/ieee802154/device.rs b/capsules/extra/src/ieee802154/device.rs index 016535ccfe..df45b2f6ba 100644 --- a/capsules/extra/src/ieee802154/device.rs +++ b/capsules/extra/src/ieee802154/device.rs @@ -73,7 +73,7 @@ pub trait MacDevice<'a> { security_needed: Option<(SecurityLevel, KeyId)>, ) -> Result; - fn buf_to_frame(&self, buf: &'static mut [u8]) -> Frame; + fn buf_to_frame(&self, buf: &'static mut [u8], len: usize) -> Frame; /// Transmits a frame that has been prepared by the above process. If the /// transmission process fails, the buffer inside the frame is returned so diff --git a/capsules/extra/src/ieee802154/driver.rs b/capsules/extra/src/ieee802154/driver.rs index 365b7fa441..25e3b1f596 100644 --- a/capsules/extra/src/ieee802154/driver.rs +++ b/capsules/extra/src/ieee802154/driver.rs @@ -460,7 +460,7 @@ impl<'a> RadioDriver<'a> { PendingTX::Empty => { unreachable!("PendingTX::Empty should have been handled earlier with guard statement.") } - PendingTX::Direct => Ok(self.mac.buf_to_frame(kbuf)), + PendingTX::Direct => Ok(self.mac.buf_to_frame(kbuf, 0)), PendingTX::Parse(dst_addr, security_needed) => { // Prepare the frame headers let pan = self.mac.get_pan(); @@ -491,6 +491,7 @@ impl<'a> RadioDriver<'a> { frame.append_payload_process(payload) ))?.map( |()| { + kernel::debug!("entered transmit"); self.mac.transmit(frame).map_or_else(|(errorcode, error_buf)| { self.kernel_tx.replace(error_buf); Err(errorcode) @@ -956,11 +957,14 @@ impl SyscallDriver for RadioDriver<'_> { .enter(processid, |app, _| { if app.pending_tx.is_some() { // Cannot support more than one pending tx per process. - return CommandReturn::failure(ErrorCode::BUSY); + return Err(ErrorCode::BUSY); } app.pending_tx = PendingTX::Direct; - self.do_next_tx_sync(processid).into() - }).unwrap_or_else(|err| CommandReturn::failure(err.into())) + Ok(()) + }).map_or_else( + |err| CommandReturn::failure(err.into()), + |_| self.do_next_tx_sync(processid).into() + ) }, _ => CommandReturn::failure(ErrorCode::NOSUPPORT), } diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index 24cf7aaac0..536aac66b5 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -99,7 +99,37 @@ use kernel::ErrorCode; #[derive(Eq, PartialEq, Debug)] pub struct Frame { buf: &'static mut [u8], - info: Option, + info: FrameInfoWrap, +} + +#[derive(Eq, PartialEq, Debug)] +enum FrameInfoWrap { + Direct(usize), + Parse(FrameInfo), +} + +impl FrameInfoWrap { + pub fn secured_length(&self) -> usize { + match self { + FrameInfoWrap::Parse(info) => info.secured_length(), + FrameInfoWrap::Direct(len) => *len, + } + } + pub fn unsecured_length(&self) -> usize { + match self { + FrameInfoWrap::Parse(info) => info.secured_length(), + FrameInfoWrap::Direct(len) => *len, + } + } + + pub fn expect(&self) -> FrameInfo { + match self { + FrameInfoWrap::Direct(_) => { + panic!("FrameInfoWrap::Direct called when expecting FrameInfoWrap::Parse") + } + FrameInfoWrap::Parse(info) => *info, + } + } } /// This contains just enough information about a frame to determine @@ -134,13 +164,7 @@ 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 - .expect("Invalid frame info provided") - .secured_length() + self.buf.len() - radio::PSDU_OFFSET - radio::MFR_SIZE - self.info.secured_length() } /// Appends payload bytes into the frame if possible @@ -148,14 +172,12 @@ impl Frame { if payload.len() > self.remaining_data_capacity() { return Err(ErrorCode::NOMEM); } - let begin = radio::PSDU_OFFSET - + self - .info - .expect("Invalid frame info provided") - .unsecured_length(); + let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); self.buf[begin..begin + payload.len()].copy_from_slice(payload); - self.info.expect("Invalid frame info provided").data_len += payload.len(); - + match self.info { + FrameInfoWrap::Direct(len) => self.info = FrameInfoWrap::Direct(len + payload.len()), + FrameInfoWrap::Parse(_) => self.info.expect().data_len += payload.len(), + } Ok(()) } @@ -169,14 +191,14 @@ impl Frame { kernel::debug!("here"); return Err(ErrorCode::NOMEM); } - let begin = radio::PSDU_OFFSET - + self - .info - .expect("Invalid frame info provided") - .unsecured_length(); + let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); payload_buf.copy_to_slice(&mut self.buf[begin..begin + payload_buf.len()]); - self.info.expect("Invalid frame info provided").data_len += payload_buf.len(); - + match self.info { + FrameInfoWrap::Direct(len) => { + self.info = FrameInfoWrap::Direct(len + payload_buf.len()) + } + FrameInfoWrap::Parse(_) => self.info.expect().data_len += payload_buf.len(), + } Ok(()) } } @@ -302,13 +324,13 @@ enum TxState { /// There is no frame to be transmitted. Idle, /// There is a valid frame that needs to be secured before transmission. - ReadyToEncrypt(FrameInfo, &'static mut [u8]), + ReadyToEncrypt(FrameInfoWrap, &'static mut [u8]), /// There is currently a frame being encrypted by the encryption facility. #[allow(dead_code)] - Encrypting(FrameInfo), + Encrypting(FrameInfoWrap), /// There is a frame that is completely secured or does not require /// security, and is waiting to be passed to the radio. - ReadyToTransmit(FrameInfo, &'static mut [u8]), + ReadyToTransmit(FrameInfoWrap, &'static mut [u8]), } #[derive(Eq, PartialEq, Debug)] @@ -316,14 +338,14 @@ enum RxState { /// There is no frame that has been received. Idle, /// There is a secured frame that needs to be decrypted. - ReadyToDecrypt(FrameInfo, &'static mut [u8]), + ReadyToDecrypt(FrameInfoWrap, &'static mut [u8]), /// A secured frame is currently being decrypted by the decryption facility. #[allow(dead_code)] - Decrypting(FrameInfo), + Decrypting(FrameInfoWrap), /// There is an unsecured frame that needs to be re-parsed and exposed to /// the client. #[allow(dead_code)] - ReadyToYield(FrameInfo, &'static mut [u8]), + ReadyToYield(FrameInfoWrap, &'static mut [u8]), } /// This struct wraps an IEEE 802.15.4 radio device `kernel::hil::radio::Radio` @@ -398,7 +420,16 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { /// Performs the first checks in the security procedure. The rest of the /// steps are performed as part of the transmission pipeline. /// Returns the next `TxState` to enter. - fn outgoing_frame_security(&self, buf: &'static mut [u8], frame_info: FrameInfo) -> TxState { + fn outgoing_frame_security( + &self, + buf: &'static mut [u8], + frame_info_wrap: FrameInfoWrap, + ) -> TxState { + let frame_info = match frame_info_wrap { + FrameInfoWrap::Parse(info) => info, + FrameInfoWrap::Direct(_) => return TxState::ReadyToTransmit(frame_info_wrap, buf), + }; + // IEEE 802.15.4-2015: 9.2.1, outgoing frame security // Steps a-e have already been performed in the frame preparation step, // so we only need to dispatch on the security parameters in the frame info @@ -407,12 +438,12 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { if level == SecurityLevel::None { // This case should never occur if the FrameInfo was // prepared by prepare_data_frame - TxState::ReadyToTransmit(frame_info, buf) + TxState::ReadyToTransmit(frame_info_wrap, buf) } else { - TxState::ReadyToEncrypt(frame_info, buf) + TxState::ReadyToEncrypt(frame_info_wrap, buf) } } - None => TxState::ReadyToTransmit(frame_info, buf), + None => TxState::ReadyToTransmit(frame_info_wrap, buf), } } @@ -515,7 +546,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { self.mac.set_receive_buffer(buf); RxState::Idle } - Some(frame_info) => RxState::ReadyToDecrypt(frame_info, buf), + Some(frame_info) => RxState::ReadyToDecrypt(FrameInfoWrap::Parse(frame_info), buf), } } @@ -529,14 +560,14 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { let (next_state, result) = match state { TxState::Idle => (TxState::Idle, Ok(())), TxState::ReadyToEncrypt(info, buf) => { - match info.security_params { + match info.expect().security_params { None => { // `ReadyToEncrypt` should only be entered when // `security_params` is not `None`. (TxState::Idle, Err((ErrorCode::FAIL, buf))) } Some((level, key, nonce)) => { - let (m_off, m_len) = info.ccm_encrypt_ranges(); + let (m_off, m_len) = info.expect().ccm_encrypt_ranges(); let (a_off, m_off) = (radio::PSDU_OFFSET, radio::PSDU_OFFSET + m_off); @@ -551,7 +582,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { a_off, m_off, m_len, - info.mic_len, + info.expect().mic_len, level.encryption_needed(), true, ); @@ -597,14 +628,14 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { let next_state = match state { RxState::Idle => RxState::Idle, RxState::ReadyToDecrypt(info, buf) => { - match info.security_params { + match info.expect().security_params { None => { // `ReadyToDecrypt` should only be entered when // `security_params` is not `None`. RxState::Idle } Some((level, key, nonce)) => { - let (m_off, m_len) = info.ccm_encrypt_ranges(); + let (m_off, m_len) = info.expect().ccm_encrypt_ranges(); let (a_off, m_off) = (radio::PSDU_OFFSET, radio::PSDU_OFFSET + m_off); // Crypto setup failed; fail receiving packet and return to idle @@ -635,7 +666,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { a_off, m_off, m_len, - info.mic_len, + info.expect().mic_len, level.encryption_needed(), true, ) @@ -831,7 +862,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { match header.encode(&mut buf[radio::PSDU_OFFSET..], true).done() { Some((data_offset, mac_payload_offset)) => Ok(Frame { buf: buf, - info: Some(FrameInfo { + info: FrameInfoWrap::Parse(FrameInfo { frame_type: FrameType::Data, mac_payload_offset: mac_payload_offset, data_offset: data_offset, @@ -844,10 +875,10 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { } } - fn buf_to_frame(&self, buf: &'static mut [u8]) -> Frame { + fn buf_to_frame(&self, buf: &'static mut [u8], len: usize) -> Frame { Frame { buf: buf, - info: None, + info: FrameInfoWrap::Direct(len), } } @@ -861,8 +892,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { }; match state { TxState::Idle => { - let next_state = - self.outgoing_frame_security(buf, info.expect("Invalid frame info provided")); + let next_state = self.outgoing_frame_security(buf, info); self.tx_state.replace(next_state); self.step_transmit_state() } diff --git a/capsules/extra/src/ieee802154/virtual_mac.rs b/capsules/extra/src/ieee802154/virtual_mac.rs index 918cd6b4f9..cf6740410d 100644 --- a/capsules/extra/src/ieee802154/virtual_mac.rs +++ b/capsules/extra/src/ieee802154/virtual_mac.rs @@ -287,8 +287,8 @@ impl<'a> device::MacDevice<'a> for MacUser<'a> { .prepare_data_frame(buf, dst_pan, dst_addr, src_pan, src_addr, security_needed) } - fn buf_to_frame(&self, buf: &'static mut [u8]) -> framer::Frame { - self.mux.mac.buf_to_frame(buf) + fn buf_to_frame(&self, buf: &'static mut [u8], len: usize) -> framer::Frame { + self.mux.mac.buf_to_frame(buf, len) } fn transmit(&self, frame: framer::Frame) -> Result<(), (ErrorCode, &'static mut [u8])> { From 5f3d5202316994cbf48618fa5676549773b57a94 Mon Sep 17 00:00:00 2001 From: tylerp Date: Tue, 13 Feb 2024 10:00:08 -0800 Subject: [PATCH 4/9] Update to formatting and commenting --- capsules/extra/src/ieee802154/device.rs | 19 +++- capsules/extra/src/ieee802154/driver.rs | 91 ++++++++++++-------- capsules/extra/src/ieee802154/framer.rs | 31 ++++++- capsules/extra/src/ieee802154/virtual_mac.rs | 6 +- 4 files changed, 108 insertions(+), 39 deletions(-) diff --git a/capsules/extra/src/ieee802154/device.rs b/capsules/extra/src/ieee802154/device.rs index df45b2f6ba..928b1c0c73 100644 --- a/capsules/extra/src/ieee802154/device.rs +++ b/capsules/extra/src/ieee802154/device.rs @@ -73,7 +73,24 @@ pub trait MacDevice<'a> { security_needed: Option<(SecurityLevel, KeyId)>, ) -> Result; - fn buf_to_frame(&self, buf: &'static mut [u8], len: usize) -> Frame; + /// Creates an IEEE 802.15.4 Frame object that is compatible with the + /// MAC transit and append payload methods. This serves to provide + /// functionality for sending packets fully formed by the userprocess + /// and that the 15.4 capsule does not modify. The len field may be less + /// than the length of the buffer as the len field is the length of + /// the current frame while the buffer is the maximum 15.4 frame size. + /// + /// - `buf`: The buffer to be used for the frame + /// - `len`: The length of the frame + /// + /// Returns a Result: + /// - on success a Frame object that can be used to. + /// - on failure an error returning the buffer. + fn buf_to_frame( + &self, + buf: &'static mut [u8], + len: usize, + ) -> Result; /// Transmits a frame that has been prepared by the above process. If the /// transmission process fails, the buffer inside the frame is returned so diff --git a/capsules/extra/src/ieee802154/driver.rs b/capsules/extra/src/ieee802154/driver.rs index 25e3b1f596..36520447d5 100644 --- a/capsules/extra/src/ieee802154/driver.rs +++ b/capsules/extra/src/ieee802154/driver.rs @@ -177,6 +177,10 @@ impl KeyDescriptor { } } +/// Denotes the type of pending transmission. A `Parse(..)` PendingTX +/// indicates that the 15.4 framer will need to form the packet header +/// from the provided address and security level. A `Direct` PendingTX +/// is formed by the userprocess and passes through the Framer unchanged. enum PendingTX { Parse(u16, Option<(SecurityLevel, KeyId)>), Direct, @@ -184,12 +188,14 @@ enum PendingTX { } impl Default for PendingTX { + /// The default PendingTX is `Empty` fn default() -> Self { PendingTX::Empty } } impl PendingTX { + /// Returns true if the PendingTX is not `Empty` fn is_some(&self) -> bool { match self { PendingTX::Empty => false, @@ -448,19 +454,32 @@ impl<'a> RadioDriver<'a> { // this, or future, implementations do not forget to "remove" the pending_tx // from the app after processing. let curr_tx = app.pending_tx.take(); - if let PendingTX::Empty = curr_tx { - // this may not be the correct return value for handling this. This is following current convention - return Ok(()) - } - - + // Before beginning the transmission process, confirm that the PendingTX + // is not Empty. In the Empty case, there is nothing to transmit and we + // can return Ok(()) immediately as there is nothing to transmit. + if let PendingTX::Empty = curr_tx { return Ok(()) } + + // At a high level, we must form a Frame from the provided userproceess data, + // place this frame into a static buffer, and then transmit the frame. This is + // somewhat complicated by the need to error handle each of these steps and also + // provide Direct and Parse sending modes (i.e. Direct mode userprocess fully forms + // 15.4 packet and Parse mode the 15.4 framer forms the packet from the userprocess + // parameters and payload). Because we first take this kernel buffer, we must + // replace the `kernel_tx` buffer upon handling any error. self.kernel_tx.take().map_or(Err(ErrorCode::NOMEM), |kbuf| { match curr_tx { PendingTX::Empty => { unreachable!("PendingTX::Empty should have been handled earlier with guard statement.") } - PendingTX::Direct => Ok(self.mac.buf_to_frame(kbuf, 0)), + PendingTX::Direct => { + // Here we form an empty frame from the buffer to later be filled by the specified + // userprocess frame data. Note, we must allocate the needed buffer for the frame, + // but set the `len` field to 0 as the frame is empty. + self.mac.buf_to_frame(kbuf, 0).map_err(|(err, buf)| { + self.kernel_tx.replace(buf); + err + })}, PendingTX::Parse(dst_addr, security_needed) => { // Prepare the frame headers let pan = self.mac.get_pan(); @@ -476,31 +495,32 @@ impl<'a> RadioDriver<'a> { ).map_or_else(|err_buf| { self.kernel_tx.replace(err_buf); Err(ErrorCode::FAIL) - }, | frame | + }, | frame| Ok(frame) ) - }}}).map(|mut frame| { + } + } + }).map(|mut frame| { - // Obtain the payload from the userprocess. Although a ReadableProcess buffer has the potential - // to change, this given buffer is guaranteed to remain the same over the course of this method - // (TRD 4.4.1). As such, we can safely assume that the obtained reference to this payload is - // valid including when we copy the payload into the kernel_tx buffer. - kernel_data + // Obtain the payload from the userprocess, append the "payload" to the previously formed frame + // and pass the frame to be transmitted. Note, the term "payload" is somewhat misleading in the + // case of Direct transmission as the payload is the entire 15.4 frame. + kernel_data .get_readonly_processbuffer(ro_allow::WRITE) - .and_then(|write| write.enter(|payload| - frame.append_payload_process(payload) + .and_then(|write| write.enter(|payload| + frame.append_payload_process(payload) ))?.map( |()| { - kernel::debug!("entered transmit"); self.mac.transmit(frame).map_or_else(|(errorcode, error_buf)| { self.kernel_tx.replace(error_buf); Err(errorcode) - }, |_| {self.current_app.set(processid); Ok(())} - )} + }, |()| {self.current_app.set(processid); Ok(()) } + ) + } )? - })? - })?} + })? + } /// Schedule the next transmission if there is one pending. Performs the /// transmission asynchronously, returning any errors via callbacks. @@ -939,7 +959,9 @@ impl SyscallDriver for RadioDriver<'_> { } match next_tx { - Some((dst_addr, sec)) => app.pending_tx = PendingTX::Parse(dst_addr, sec), + Some((dst_addr, sec)) => { + app.pending_tx = PendingTX::Parse(dst_addr, sec) + } None => app.pending_tx = PendingTX::Empty, } Ok(()) @@ -954,18 +976,19 @@ impl SyscallDriver for RadioDriver<'_> { } 27 => { self.apps - .enter(processid, |app, _| { - if app.pending_tx.is_some() { - // Cannot support more than one pending tx per process. - return Err(ErrorCode::BUSY); - } - app.pending_tx = PendingTX::Direct; - Ok(()) - }).map_or_else( - |err| CommandReturn::failure(err.into()), - |_| self.do_next_tx_sync(processid).into() - ) - }, + .enter(processid, |app, _| { + if app.pending_tx.is_some() { + // Cannot support more than one pending tx per process. + return Err(ErrorCode::BUSY); + } + app.pending_tx = PendingTX::Direct; + Ok(()) + }) + .map_or_else( + |err| CommandReturn::failure(err.into()), + |_| self.do_next_tx_sync(processid).into(), + ) + } _ => CommandReturn::failure(ErrorCode::NOSUPPORT), } } diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index 536aac66b5..2f8f173850 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -102,6 +102,12 @@ pub struct Frame { info: FrameInfoWrap, } +/// This enum wraps the `FrameInfo` struct and allows each sending type +/// (Parse or Direct) to only store the relevant information. In the +/// case of a Direct send, the `FrameInfo` struct is irrelevant as the +/// packet has been fully formed by the userprocess. For a direct send, +/// we only require knowledge on the frame length. In the case of a +/// Parse send, the wrapper provides all required frame header information. #[derive(Eq, PartialEq, Debug)] enum FrameInfoWrap { Direct(usize), @@ -109,12 +115,15 @@ enum FrameInfoWrap { } impl FrameInfoWrap { + /// Obtain secured_length of the Frame pub fn secured_length(&self) -> usize { match self { FrameInfoWrap::Parse(info) => info.secured_length(), FrameInfoWrap::Direct(len) => *len, } } + + /// Obtain unsecured_length of the Frame pub fn unsecured_length(&self) -> usize { match self { FrameInfoWrap::Parse(info) => info.secured_length(), @@ -122,9 +131,15 @@ impl FrameInfoWrap { } } + /// Fetcher of the FrameInfo struct for Parse sending and panic if + /// called for Direct sending. pub fn expect(&self) -> FrameInfo { match self { FrameInfoWrap::Direct(_) => { + // This should never be called for a Direct send. The Framer should never + // require information other than the Frame length for a Direct send. This + // warrants a panic condition as fetching the `FrameInfo` struct for a + // Direct send is undefined behavior. panic!("FrameInfoWrap::Direct called when expecting FrameInfoWrap::Parse") } FrameInfoWrap::Parse(info) => *info, @@ -875,11 +890,21 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { } } - fn buf_to_frame(&self, buf: &'static mut [u8], len: usize) -> Frame { - Frame { + fn buf_to_frame( + &self, + buf: &'static mut [u8], + len: usize, + ) -> Result { + // Error check input for compliance with max 15.4 buffer size and + // that the provided len is compatibile with the provided buffer. + if buf.len() < radio::MAX_BUF_SIZE || len > buf.len() { + return Err((ErrorCode::INVAL, buf)); + } + + Ok(Frame { buf: buf, info: FrameInfoWrap::Direct(len), - } + }) } fn transmit(&self, frame: Frame) -> Result<(), (ErrorCode, &'static mut [u8])> { diff --git a/capsules/extra/src/ieee802154/virtual_mac.rs b/capsules/extra/src/ieee802154/virtual_mac.rs index cf6740410d..db9b5baa5f 100644 --- a/capsules/extra/src/ieee802154/virtual_mac.rs +++ b/capsules/extra/src/ieee802154/virtual_mac.rs @@ -287,7 +287,11 @@ impl<'a> device::MacDevice<'a> for MacUser<'a> { .prepare_data_frame(buf, dst_pan, dst_addr, src_pan, src_addr, security_needed) } - fn buf_to_frame(&self, buf: &'static mut [u8], len: usize) -> framer::Frame { + fn buf_to_frame( + &self, + buf: &'static mut [u8], + len: usize, + ) -> Result { self.mux.mac.buf_to_frame(buf, len) } From 57f7c716797e4ff608b099aea2b2b7afb2fa2390 Mon Sep 17 00:00:00 2001 From: tylerp Date: Tue, 13 Feb 2024 13:17:27 -0800 Subject: [PATCH 5/9] Resolved 15.4 standard send issue Implemented changes resulted in the payload not being correctly sent using the standard 15.4 send. This was due to the manner the `data_len` field was updated in the match arm (change was only local). --- capsules/extra/src/ieee802154/device.rs | 4 ++-- capsules/extra/src/ieee802154/driver.rs | 10 +++++----- capsules/extra/src/ieee802154/framer.rs | 13 +++++++++---- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/capsules/extra/src/ieee802154/device.rs b/capsules/extra/src/ieee802154/device.rs index 928b1c0c73..b4cfc3557c 100644 --- a/capsules/extra/src/ieee802154/device.rs +++ b/capsules/extra/src/ieee802154/device.rs @@ -74,7 +74,7 @@ pub trait MacDevice<'a> { ) -> Result; /// Creates an IEEE 802.15.4 Frame object that is compatible with the - /// MAC transit and append payload methods. This serves to provide + /// MAC transmit and append payload methods. This serves to provide /// functionality for sending packets fully formed by the userprocess /// and that the 15.4 capsule does not modify. The len field may be less /// than the length of the buffer as the len field is the length of @@ -84,7 +84,7 @@ pub trait MacDevice<'a> { /// - `len`: The length of the frame /// /// Returns a Result: - /// - on success a Frame object that can be used to. + /// - on success a Frame object. /// - on failure an error returning the buffer. fn buf_to_frame( &self, diff --git a/capsules/extra/src/ieee802154/driver.rs b/capsules/extra/src/ieee802154/driver.rs index 36520447d5..8d7cece177 100644 --- a/capsules/extra/src/ieee802154/driver.rs +++ b/capsules/extra/src/ieee802154/driver.rs @@ -205,11 +205,7 @@ impl PendingTX { /// Take the pending transmission, replacing it with `Empty` and return the current PendingTx fn take(&mut self) -> PendingTX { - match core::mem::replace(self, PendingTX::Empty) { - PendingTX::Parse(addr, sec) => PendingTX::Parse(addr, sec), - PendingTX::Direct => PendingTX::Direct, - PendingTX::Empty => PendingTX::Empty, - } + core::mem::replace(self, PendingTX::Empty) } } @@ -680,6 +676,10 @@ impl SyscallDriver for RadioDriver<'_> { /// 9 bytes: the key ID (might not use all bytes) + /// 16 bytes: the key. /// - `25`: Remove the key at an index. + /// - `26`: Transmit a frame (parse required). Take the provided payload and + /// parameters to encrypt, form headers, and transmit the frame. + /// - `27`: Transmit a frame (direct). Transmit preformed 15.4 frame (i.e. + /// headers and security etc completed by userprocess). fn command( &self, command_number: usize, diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index 2f8f173850..c888339177 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -131,7 +131,7 @@ impl FrameInfoWrap { } } - /// Fetcher of the FrameInfo struct for Parse sending and panic if + /// Fetcher of the FrameInfo struct for Parse sending. Panics if /// called for Direct sending. pub fn expect(&self) -> FrameInfo { match self { @@ -191,7 +191,10 @@ impl Frame { self.buf[begin..begin + payload.len()].copy_from_slice(payload); match self.info { FrameInfoWrap::Direct(len) => self.info = FrameInfoWrap::Direct(len + payload.len()), - FrameInfoWrap::Parse(_) => self.info.expect().data_len += payload.len(), + FrameInfoWrap::Parse(mut info) => { + info.data_len += payload.len(); + self.info = FrameInfoWrap::Parse(info); + } } Ok(()) } @@ -203,7 +206,6 @@ impl Frame { payload_buf: &ReadableProcessSlice, ) -> Result<(), ErrorCode> { if payload_buf.len() > self.remaining_data_capacity() { - kernel::debug!("here"); return Err(ErrorCode::NOMEM); } let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); @@ -212,7 +214,10 @@ impl Frame { FrameInfoWrap::Direct(len) => { self.info = FrameInfoWrap::Direct(len + payload_buf.len()) } - FrameInfoWrap::Parse(_) => self.info.expect().data_len += payload_buf.len(), + FrameInfoWrap::Parse(mut info) => { + info.data_len += payload_buf.len(); + self.info = FrameInfoWrap::Parse(info); + } } Ok(()) } From 8db6c5dd1250519312470c083dae91e57b483579 Mon Sep 17 00:00:00 2001 From: tylerp Date: Mon, 19 Feb 2024 15:44:40 -0800 Subject: [PATCH 6/9] Changed naming convention from Direct to Raw --- capsules/extra/src/ieee802154/driver.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/capsules/extra/src/ieee802154/driver.rs b/capsules/extra/src/ieee802154/driver.rs index 8d7cece177..bcdbe56c37 100644 --- a/capsules/extra/src/ieee802154/driver.rs +++ b/capsules/extra/src/ieee802154/driver.rs @@ -179,11 +179,11 @@ impl KeyDescriptor { /// Denotes the type of pending transmission. A `Parse(..)` PendingTX /// indicates that the 15.4 framer will need to form the packet header -/// from the provided address and security level. A `Direct` PendingTX +/// from the provided address and security level. A `Raw` PendingTX /// is formed by the userprocess and passes through the Framer unchanged. enum PendingTX { Parse(u16, Option<(SecurityLevel, KeyId)>), - Direct, + Raw, Empty, } @@ -459,7 +459,7 @@ impl<'a> RadioDriver<'a> { // At a high level, we must form a Frame from the provided userproceess data, // place this frame into a static buffer, and then transmit the frame. This is // somewhat complicated by the need to error handle each of these steps and also - // provide Direct and Parse sending modes (i.e. Direct mode userprocess fully forms + // provide Raw and Parse sending modes (i.e. Raw mode userprocess fully forms // 15.4 packet and Parse mode the 15.4 framer forms the packet from the userprocess // parameters and payload). Because we first take this kernel buffer, we must // replace the `kernel_tx` buffer upon handling any error. @@ -468,7 +468,7 @@ impl<'a> RadioDriver<'a> { PendingTX::Empty => { unreachable!("PendingTX::Empty should have been handled earlier with guard statement.") } - PendingTX::Direct => { + PendingTX::Raw => { // Here we form an empty frame from the buffer to later be filled by the specified // userprocess frame data. Note, we must allocate the needed buffer for the frame, // but set the `len` field to 0 as the frame is empty. @@ -500,7 +500,7 @@ impl<'a> RadioDriver<'a> { // Obtain the payload from the userprocess, append the "payload" to the previously formed frame // and pass the frame to be transmitted. Note, the term "payload" is somewhat misleading in the - // case of Direct transmission as the payload is the entire 15.4 frame. + // case of Raw transmission as the payload is the entire 15.4 frame. kernel_data .get_readonly_processbuffer(ro_allow::WRITE) .and_then(|write| write.enter(|payload| @@ -678,7 +678,7 @@ impl SyscallDriver for RadioDriver<'_> { /// - `25`: Remove the key at an index. /// - `26`: Transmit a frame (parse required). Take the provided payload and /// parameters to encrypt, form headers, and transmit the frame. - /// - `27`: Transmit a frame (direct). Transmit preformed 15.4 frame (i.e. + /// - `27`: Transmit a frame (raw). Transmit preformed 15.4 frame (i.e. /// headers and security etc completed by userprocess). fn command( &self, @@ -981,7 +981,7 @@ impl SyscallDriver for RadioDriver<'_> { // Cannot support more than one pending tx per process. return Err(ErrorCode::BUSY); } - app.pending_tx = PendingTX::Direct; + app.pending_tx = PendingTX::Raw; Ok(()) }) .map_or_else( From 26b8f66027113d2876e550ba17843baa92540d04 Mon Sep 17 00:00:00 2001 From: tylerp Date: Tue, 20 Feb 2024 12:18:05 -0800 Subject: [PATCH 7/9] Renamed Direct to Raw in framer --- capsules/extra/src/ieee802154/framer.rs | 34 ++++++++++++------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index c888339177..d23ace599e 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -103,14 +103,14 @@ pub struct Frame { } /// This enum wraps the `FrameInfo` struct and allows each sending type -/// (Parse or Direct) to only store the relevant information. In the -/// case of a Direct send, the `FrameInfo` struct is irrelevant as the -/// packet has been fully formed by the userprocess. For a direct send, +/// (Parse or Raw) to only store the relevant information. In the +/// case of a Raw send, the `FrameInfo` struct is irrelevant as the +/// packet has been fully formed by the userprocess. For a Raw send, /// we only require knowledge on the frame length. In the case of a /// Parse send, the wrapper provides all required frame header information. #[derive(Eq, PartialEq, Debug)] enum FrameInfoWrap { - Direct(usize), + Raw(usize), Parse(FrameInfo), } @@ -119,7 +119,7 @@ impl FrameInfoWrap { pub fn secured_length(&self) -> usize { match self { FrameInfoWrap::Parse(info) => info.secured_length(), - FrameInfoWrap::Direct(len) => *len, + FrameInfoWrap::Raw(len) => *len, } } @@ -127,20 +127,20 @@ impl FrameInfoWrap { pub fn unsecured_length(&self) -> usize { match self { FrameInfoWrap::Parse(info) => info.secured_length(), - FrameInfoWrap::Direct(len) => *len, + FrameInfoWrap::Raw(len) => *len, } } /// Fetcher of the FrameInfo struct for Parse sending. Panics if - /// called for Direct sending. + /// called for Raw sending. pub fn expect(&self) -> FrameInfo { match self { - FrameInfoWrap::Direct(_) => { - // This should never be called for a Direct send. The Framer should never - // require information other than the Frame length for a Direct send. This + FrameInfoWrap::Raw(_) => { + // This should never be called for a Raw send. The Framer should never + // require information other than the Frame length for a Raw send. This // warrants a panic condition as fetching the `FrameInfo` struct for a - // Direct send is undefined behavior. - panic!("FrameInfoWrap::Direct called when expecting FrameInfoWrap::Parse") + // Raw send is undefined behavior. + panic!("FrameInfoWrap::Raw called when expecting FrameInfoWrap::Parse") } FrameInfoWrap::Parse(info) => *info, } @@ -190,7 +190,7 @@ impl Frame { let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); self.buf[begin..begin + payload.len()].copy_from_slice(payload); match self.info { - FrameInfoWrap::Direct(len) => self.info = FrameInfoWrap::Direct(len + payload.len()), + FrameInfoWrap::Raw(len) => self.info = FrameInfoWrap::Raw(len + payload.len()), FrameInfoWrap::Parse(mut info) => { info.data_len += payload.len(); self.info = FrameInfoWrap::Parse(info); @@ -211,9 +211,7 @@ impl Frame { let begin = radio::PSDU_OFFSET + self.info.unsecured_length(); payload_buf.copy_to_slice(&mut self.buf[begin..begin + payload_buf.len()]); match self.info { - FrameInfoWrap::Direct(len) => { - self.info = FrameInfoWrap::Direct(len + payload_buf.len()) - } + FrameInfoWrap::Raw(len) => self.info = FrameInfoWrap::Raw(len + payload_buf.len()), FrameInfoWrap::Parse(mut info) => { info.data_len += payload_buf.len(); self.info = FrameInfoWrap::Parse(info); @@ -447,7 +445,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { ) -> TxState { let frame_info = match frame_info_wrap { FrameInfoWrap::Parse(info) => info, - FrameInfoWrap::Direct(_) => return TxState::ReadyToTransmit(frame_info_wrap, buf), + FrameInfoWrap::Raw(_) => return TxState::ReadyToTransmit(frame_info_wrap, buf), }; // IEEE 802.15.4-2015: 9.2.1, outgoing frame security @@ -908,7 +906,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> MacDevice<'a> for Framer<'a, M, A> { Ok(Frame { buf: buf, - info: FrameInfoWrap::Direct(len), + info: FrameInfoWrap::Raw(len), }) } From 30f2d51764813f31b22cf609e42c28055f54c4a1 Mon Sep 17 00:00:00 2001 From: tylerp Date: Tue, 20 Feb 2024 15:11:54 -0800 Subject: [PATCH 8/9] Updated unsecured_length method The prior implementation obtained the incorrect field --- capsules/extra/src/ieee802154/framer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index d23ace599e..f7e6fbeb8c 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -126,7 +126,7 @@ impl FrameInfoWrap { /// Obtain unsecured_length of the Frame pub fn unsecured_length(&self) -> usize { match self { - FrameInfoWrap::Parse(info) => info.secured_length(), + FrameInfoWrap::Parse(info) => info.unsecured_length(), FrameInfoWrap::Raw(len) => *len, } } From 7a57025078e6d75abd9e88efa3ab910b83dcd3a2 Mon Sep 17 00:00:00 2001 From: tylerp Date: Mon, 26 Feb 2024 11:02:08 -0800 Subject: [PATCH 9/9] Updates to PendingTX method naming --- capsules/extra/src/ieee802154/driver.rs | 14 +++++++------- capsules/extra/src/ieee802154/framer.rs | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/capsules/extra/src/ieee802154/driver.rs b/capsules/extra/src/ieee802154/driver.rs index bcdbe56c37..5cfeec81e9 100644 --- a/capsules/extra/src/ieee802154/driver.rs +++ b/capsules/extra/src/ieee802154/driver.rs @@ -195,11 +195,11 @@ impl Default for PendingTX { } impl PendingTX { - /// Returns true if the PendingTX is not `Empty` - fn is_some(&self) -> bool { + /// Returns true if the PendingTX state is `Empty` + fn is_empty(&self) -> bool { match self { - PendingTX::Empty => false, - _ => true, + PendingTX::Empty => true, + _ => false, } } @@ -415,7 +415,7 @@ impl<'a> RadioDriver<'a> { for app in self.apps.iter() { let processid = app.processid(); app.enter(|app, _| { - if app.pending_tx.is_some() { + if !app.pending_tx.is_empty() { pending_app = Some(processid); } }); @@ -919,7 +919,7 @@ impl SyscallDriver for RadioDriver<'_> { 26 => { self.apps .enter(processid, |app, kernel_data| { - if app.pending_tx.is_some() { + if !app.pending_tx.is_empty() { // Cannot support more than one pending tx per process. return Err(ErrorCode::BUSY); } @@ -977,7 +977,7 @@ impl SyscallDriver for RadioDriver<'_> { 27 => { self.apps .enter(processid, |app, _| { - if app.pending_tx.is_some() { + if !app.pending_tx.is_empty() { // Cannot support more than one pending tx per process. return Err(ErrorCode::BUSY); } diff --git a/capsules/extra/src/ieee802154/framer.rs b/capsules/extra/src/ieee802154/framer.rs index f7e6fbeb8c..5cf5a4f733 100644 --- a/capsules/extra/src/ieee802154/framer.rs +++ b/capsules/extra/src/ieee802154/framer.rs @@ -133,7 +133,7 @@ impl FrameInfoWrap { /// Fetcher of the FrameInfo struct for Parse sending. Panics if /// called for Raw sending. - pub fn expect(&self) -> FrameInfo { + pub fn get_info(&self) -> FrameInfo { match self { FrameInfoWrap::Raw(_) => { // This should never be called for a Raw send. The Framer should never @@ -578,14 +578,14 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { let (next_state, result) = match state { TxState::Idle => (TxState::Idle, Ok(())), TxState::ReadyToEncrypt(info, buf) => { - match info.expect().security_params { + match info.get_info().security_params { None => { // `ReadyToEncrypt` should only be entered when // `security_params` is not `None`. (TxState::Idle, Err((ErrorCode::FAIL, buf))) } Some((level, key, nonce)) => { - let (m_off, m_len) = info.expect().ccm_encrypt_ranges(); + let (m_off, m_len) = info.get_info().ccm_encrypt_ranges(); let (a_off, m_off) = (radio::PSDU_OFFSET, radio::PSDU_OFFSET + m_off); @@ -600,7 +600,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { a_off, m_off, m_len, - info.expect().mic_len, + info.get_info().mic_len, level.encryption_needed(), true, ); @@ -646,14 +646,14 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { let next_state = match state { RxState::Idle => RxState::Idle, RxState::ReadyToDecrypt(info, buf) => { - match info.expect().security_params { + match info.get_info().security_params { None => { // `ReadyToDecrypt` should only be entered when // `security_params` is not `None`. RxState::Idle } Some((level, key, nonce)) => { - let (m_off, m_len) = info.expect().ccm_encrypt_ranges(); + let (m_off, m_len) = info.get_info().ccm_encrypt_ranges(); let (a_off, m_off) = (radio::PSDU_OFFSET, radio::PSDU_OFFSET + m_off); // Crypto setup failed; fail receiving packet and return to idle @@ -684,7 +684,7 @@ impl<'a, M: Mac<'a>, A: AES128CCM<'a>> Framer<'a, M, A> { a_off, m_off, m_len, - info.expect().mic_len, + info.get_info().mic_len, level.encryption_needed(), true, )