wlan_common/mac/data/
amsdu.rs1use crate::big_endian::BigEndianU16;
6use crate::buffer_reader::BufferReader;
7use crate::mac::{round_up, MacAddr};
8use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, Unaligned};
9
10#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
12#[repr(C, packed)]
13pub struct AmsduSubframeHdr {
14 pub da: MacAddr,
16 pub sa: MacAddr,
17 pub msdu_len: BigEndianU16,
18}
19
20pub struct AmsduSubframe<B> {
21 pub hdr: Ref<B, AmsduSubframeHdr>,
22 pub body: B,
23}
24
25impl<B: SplitByteSlice> AmsduSubframe<B> {
30 pub fn parse(buffer_reader: &mut BufferReader<B>) -> Option<Self> {
31 let hdr = buffer_reader.read::<AmsduSubframeHdr>()?;
32 let msdu_len = hdr.msdu_len.to_native() as usize;
33 if buffer_reader.bytes_remaining() < msdu_len {
34 None
35 } else {
36 let body = buffer_reader.read_bytes(msdu_len)?;
37 let base_len = std::mem::size_of::<AmsduSubframeHdr>() + msdu_len;
38 let padded_len = round_up(base_len, 4);
39 let padding_len = padded_len - base_len;
40 if buffer_reader.bytes_remaining() == 0 {
41 Some(Self { hdr, body })
42 } else if buffer_reader.bytes_remaining() <= padding_len {
43 None
48 } else {
49 buffer_reader.read_bytes(padding_len)?;
50 Some(Self { hdr, body })
51 }
52 }
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use crate::mac::{self, data};
59 use crate::test_utils::fake_frames::*;
60 use zerocopy::Ref;
61
62 #[test]
63 fn msdu_iter_aggregated() {
64 let bytes = make_data_frame_amsdu();
65 data::harness::assert_msdus_llc_frame_eq(
66 mac::DataFrame::parse(bytes.as_slice(), false)
67 .expect("failed to parse aggregated data frame"),
68 [
69 mac::LlcFrame {
70 hdr: Ref::from_bytes(MSDU_1_LLC_HDR).unwrap(),
71 body: MSDU_1_PAYLOAD,
72 },
73 mac::LlcFrame {
74 hdr: Ref::from_bytes(MSDU_2_LLC_HDR).unwrap(),
75 body: MSDU_2_PAYLOAD,
76 },
77 ],
78 );
79 }
80
81 #[test]
82 fn msdu_iter_aggregated_with_padding_too_short() {
83 let bytes = make_data_frame_amsdu_padding_too_short();
84 data::harness::assert_msdus_llc_frame_eq(
85 mac::DataFrame::parse(bytes.as_slice(), false)
86 .expect("failed to parse aggregated data frame"),
87 [mac::LlcFrame { hdr: Ref::from_bytes(MSDU_1_LLC_HDR).unwrap(), body: MSDU_1_PAYLOAD }],
88 );
89 }
90}