wlan_common/mac/data/
mod.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5mod amsdu;
6mod fields;
7mod msdu;
8
9pub use amsdu::*;
10pub use fields::*;
11pub use msdu::*;
12
13/// Test harnesses and fixtures.
14#[cfg(test)]
15pub mod harness {
16    use super::*;
17    use itertools::{EitherOrBoth, Itertools};
18    use std::fmt::Debug;
19    use zerocopy::SplitByteSlice;
20
21    pub fn assert_msdus_exactly_one_eq<M, E>(
22        msdus: impl IntoIterator<Item = Msdu<M>>,
23        expected: Msdu<E>,
24    ) where
25        M: SplitByteSlice + Debug,
26        E: SplitByteSlice + Debug,
27    {
28        let mut msdus = msdus.into_iter().peekable();
29        let Msdu { dst_addr, src_addr, llc_frame } =
30            msdus.next().expect("expected exactly one MSDU, but got zero");
31        assert_eq!(dst_addr, expected.dst_addr);
32        assert_eq!(src_addr, expected.src_addr);
33        assert_eq!(llc_frame.hdr.protocol_id, expected.llc_frame.hdr.protocol_id);
34        assert_eq!(&*llc_frame.body, &*expected.llc_frame.body);
35        if msdus.peek().is_some() {
36            panic!(
37                "expected exactly one MSDU, but got more\n{}",
38                format!("unexpected MSDU: {:x?}", msdus.map(Msdu::into_body).format("\n"))
39            );
40        }
41    }
42
43    pub fn assert_msdus_llc_frame_eq<M, E>(
44        msdus: impl IntoIterator<Item = Msdu<M>>,
45        expected: impl IntoIterator<Item = LlcFrame<E>>,
46    ) where
47        M: SplitByteSlice + Debug,
48        E: SplitByteSlice + Debug,
49    {
50        let mut msdus = msdus.into_iter().zip_longest(expected).peekable();
51        while let Some(EitherOrBoth::Both(Msdu { llc_frame, .. }, expected)) = msdus.peek() {
52            // Only LLC frame data is asserted here. Other `Msdu` fixture fields are not exposed to
53            // tests, but these fields are validated by other assertions.
54            assert_eq!(llc_frame.hdr.protocol_id, expected.hdr.protocol_id);
55            assert_eq!(&*llc_frame.body, &*expected.body);
56            msdus.next();
57        }
58        if let Some(zipped) = msdus.peek() {
59            let difference = if zipped.is_left() { "more" } else { "fewer" };
60            panic!(
61                "expected some number of MSDUs, but got {}\n{}",
62                difference,
63                msdus
64                    .map(|zipped| match zipped {
65                        EitherOrBoth::Left(msdu) =>
66                            format!("unexpected MSDU: {:x?}", msdu.into_body()),
67                        EitherOrBoth::Right(expected) =>
68                            format!("expected MSDU (not found): {:x?}", expected.into_body()),
69                        _ => unreachable!(),
70                    })
71                    .join("\n"),
72            );
73        }
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use crate::test_utils::fake_frames::*;
80    use crate::{assert_variant, mac};
81
82    #[test]
83    fn parse_data_frame() {
84        let bytes = make_data_frame_single_llc(None, None);
85        assert_variant!(
86            mac::DataFrame::parse(bytes.as_slice(), false),
87            Some(mac::DataFrame { fixed_fields, addr4, qos_ctrl, ht_ctrl, body }) => {
88                assert_eq!(0b00000000_10001000, { fixed_fields.frame_ctrl.0 });
89                assert_eq!(0x0202, { fixed_fields.duration });
90                assert_eq!(mac::MacAddr::from([3, 3, 3, 3, 3, 3]), fixed_fields.addr1);
91                assert_eq!(mac::MacAddr::from([4, 4, 4, 4, 4, 4]), fixed_fields.addr2);
92                assert_eq!(mac::MacAddr::from([5, 5, 5, 5, 5, 5]), fixed_fields.addr3);
93                assert_eq!(0x0606, { fixed_fields.seq_ctrl.0 });
94                assert!(addr4.is_none());
95                assert_eq!(qos_ctrl.expect("qos_ctrl not present").get().0, 0x0101);
96                assert!(ht_ctrl.is_none());
97                assert_eq!(&body[..], &[7, 7, 7, 8, 8, 8, 9, 10, 11, 11, 11]);
98            },
99            "failed to parse data frame",
100        );
101    }
102
103    #[test]
104    fn parse_data_frame_with_padding() {
105        let bytes = make_data_frame_with_padding();
106        assert_variant!(
107            mac::DataFrame::parse(bytes.as_slice(), true),
108            Some(mac::DataFrame { qos_ctrl, body, .. }) => {
109                assert_eq!(qos_ctrl.expect("qos_ctrl not present").get().0, 0x0101);
110                assert_eq!(&body[..], &[7, 7, 7, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11]);
111            },
112            "failed to parse padded data frame",
113        );
114    }
115}