wlan_common/mac/
frame_class.rs1use crate::mac;
6use zerocopy::SplitByteSlice;
7
8#[derive(Copy, Clone, PartialOrd, PartialEq, Debug, Ord, Eq)]
9pub enum FrameClass {
10    Class1 = 1,
11    Class2 = 2,
12    Class3 = 3,
13}
14
15impl<B: SplitByteSlice> From<&mac::MacFrame<B>> for FrameClass {
17    fn from(mac_frame: &mac::MacFrame<B>) -> FrameClass {
18        frame_class(&mac_frame.frame_ctrl())
19    }
20}
21
22pub fn frame_class(fc: &mac::FrameControl) -> FrameClass {
32    match fc.frame_type() {
34        mac::FrameType::CTRL => match fc.ctrl_subtype() {
35            mac::CtrlSubtype::RTS
38            | mac::CtrlSubtype::CTS
39            | mac::CtrlSubtype::ACK
40            | mac::CtrlSubtype::CF_END
41            | mac::CtrlSubtype::CF_END_ACK => return FrameClass::Class1,
42            _ => (),
43        },
44        mac::FrameType::MGMT => match fc.mgmt_subtype() {
45            mac::MgmtSubtype::ACTION
46            | mac::MgmtSubtype::PROBE_REQ
47            | mac::MgmtSubtype::PROBE_RESP
48            | mac::MgmtSubtype::BEACON
49            | mac::MgmtSubtype::AUTH
50            | mac::MgmtSubtype::DEAUTH
51            | mac::MgmtSubtype::ATIM => return FrameClass::Class1,
52            _ => (),
53        },
54        _ => (),
55    };
56
57    if let mac::FrameType::MGMT = fc.frame_type() {
60        match fc.mgmt_subtype() {
61            mac::MgmtSubtype::ASSOC_REQ
62            | mac::MgmtSubtype::ASSOC_RESP
63            | mac::MgmtSubtype::REASSOC_REQ
64            | mac::MgmtSubtype::REASSOC_RESP
65            | mac::MgmtSubtype::DISASSOC => return FrameClass::Class2,
66            _ => (),
67        }
68    };
69
70    FrameClass::Class3
71}
72
73pub fn action_frame_class(category: mac::ActionCategory) -> FrameClass {
75    match category {
76        mac::ActionCategory::PUBLIC | mac::ActionCategory::SELF_PROTECTED => FrameClass::Class1,
78        _ => FrameClass::Class3,
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn mgmt_frame_class() {
89        let mut fc = mac::FrameControl(0)
91            .with_frame_type(mac::FrameType::MGMT)
92            .with_mgmt_subtype(mac::MgmtSubtype::BEACON);
93        assert_eq!(FrameClass::Class1, frame_class(&fc));
94        fc.set_mgmt_subtype(mac::MgmtSubtype::AUTH);
95        assert_eq!(FrameClass::Class1, frame_class(&fc));
96        fc.set_mgmt_subtype(mac::MgmtSubtype::DEAUTH);
97        assert_eq!(FrameClass::Class1, frame_class(&fc));
98        fc.set_mgmt_subtype(mac::MgmtSubtype::PROBE_REQ);
99        assert_eq!(FrameClass::Class1, frame_class(&fc));
100        fc.set_mgmt_subtype(mac::MgmtSubtype::PROBE_RESP);
101        assert_eq!(FrameClass::Class1, frame_class(&fc));
102        fc.set_mgmt_subtype(mac::MgmtSubtype::ATIM);
103        assert_eq!(FrameClass::Class1, frame_class(&fc));
104        fc.set_mgmt_subtype(mac::MgmtSubtype::ACTION);
105        assert_eq!(FrameClass::Class1, frame_class(&fc));
106
107        fc.set_mgmt_subtype(mac::MgmtSubtype::ASSOC_REQ);
109        assert_eq!(FrameClass::Class2, frame_class(&fc));
110        fc.set_mgmt_subtype(mac::MgmtSubtype::ASSOC_RESP);
111        assert_eq!(FrameClass::Class2, frame_class(&fc));
112        fc.set_mgmt_subtype(mac::MgmtSubtype::REASSOC_REQ);
113        assert_eq!(FrameClass::Class2, frame_class(&fc));
114        fc.set_mgmt_subtype(mac::MgmtSubtype::REASSOC_RESP);
115        assert_eq!(FrameClass::Class2, frame_class(&fc));
116        fc.set_mgmt_subtype(mac::MgmtSubtype::DISASSOC);
117        assert_eq!(FrameClass::Class2, frame_class(&fc));
118
119        fc.set_mgmt_subtype(mac::MgmtSubtype::TIMING_AD);
121        assert_eq!(FrameClass::Class3, frame_class(&fc));
122        fc.set_mgmt_subtype(mac::MgmtSubtype::ACTION_NO_ACK);
123        assert_eq!(FrameClass::Class3, frame_class(&fc));
124    }
125
126    #[test]
127    fn data_frame_class() {
128        let fc = mac::FrameControl(0).with_frame_type(mac::FrameType::DATA);
130        assert_eq!(FrameClass::Class3, frame_class(&fc));
131    }
132
133    #[test]
134    fn ctrl_frame_class() {
135        let mut fc = mac::FrameControl(0)
137            .with_frame_type(mac::FrameType::CTRL)
138            .with_ctrl_subtype(mac::CtrlSubtype::ACK);
139        assert_eq!(FrameClass::Class1, frame_class(&fc));
140        fc.set_ctrl_subtype(mac::CtrlSubtype::RTS);
141        assert_eq!(FrameClass::Class1, frame_class(&fc));
142        fc.set_ctrl_subtype(mac::CtrlSubtype::CTS);
143        assert_eq!(FrameClass::Class1, frame_class(&fc));
144
145        fc.set_ctrl_subtype(mac::CtrlSubtype::PS_POLL);
147        assert_eq!(FrameClass::Class3, frame_class(&fc));
148        fc.set_ctrl_subtype(mac::CtrlSubtype::BLOCK_ACK);
149        assert_eq!(FrameClass::Class3, frame_class(&fc));
150        fc.set_ctrl_subtype(mac::CtrlSubtype::BLOCK_ACK_REQ);
151        assert_eq!(FrameClass::Class3, frame_class(&fc));
152    }
153
154    #[test]
155    fn action_frames() {
156        assert_eq!(FrameClass::Class1, action_frame_class(mac::ActionCategory::PUBLIC));
158        assert_eq!(FrameClass::Class1, action_frame_class(mac::ActionCategory::SELF_PROTECTED));
159
160        assert_eq!(FrameClass::Class3, action_frame_class(mac::ActionCategory::BLOCK_ACK));
162        assert_eq!(FrameClass::Class3, action_frame_class(mac::ActionCategory::MESH));
163    }
164}