1use crate::mac::{FrameControl, HtControl, MacAddr, OptionalField, Presence, SequenceControl};
6use wlan_bitfield::bitfield;
7use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
8
9#[bitfield(
11 0..=3 tid,
12 4 eosp,
13 5..=6 ack_policy,
14 7 amsdu_present,
15 8..=15 high_byte, )]
17#[repr(C)]
18#[derive(IntoBytes, KnownLayout, FromBytes, Immutable, Copy, Clone, PartialEq, Eq)]
19pub struct QosControl(pub u16);
20
21pub type Addr4 = MacAddr;
22
23#[derive(
25 KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned, PartialEq, Eq, Clone, Copy, Debug,
26)]
27#[repr(C, packed)]
28pub struct FixedDataHdrFields {
29 pub frame_ctrl: FrameControl,
30 pub duration: u16,
31 pub addr1: MacAddr,
32 pub addr2: MacAddr,
33 pub addr3: MacAddr,
34 pub seq_ctrl: SequenceControl,
35}
36
37impl FixedDataHdrFields {
38 pub fn len(
41 has_addr4: Presence<Addr4>,
42 has_qos_ctrl: Presence<QosControl>,
43 has_ht_ctrl: Presence<HtControl>,
44 ) -> usize {
45 let mut bytes = std::mem::size_of::<Self>();
46 bytes += match has_addr4 {
47 Addr4::PRESENT => std::mem::size_of::<MacAddr>(),
48 Addr4::ABSENT => 0,
49 };
50 bytes += match has_qos_ctrl {
51 QosControl::PRESENT => std::mem::size_of::<QosControl>(),
52 QosControl::ABSENT => 0,
53 };
54 bytes += match has_ht_ctrl {
55 HtControl::PRESENT => std::mem::size_of::<HtControl>(),
56 HtControl::ABSENT => 0,
57 };
58 bytes
59 }
60}
61
62pub struct OptionalDataHdrFields {
63 pub addr4: Option<Addr4>,
64 pub qos_ctrl: Option<QosControl>,
65 pub ht_ctrl: Option<HtControl>,
66}
67impl OptionalDataHdrFields {
68 pub fn none() -> Self {
69 Self { addr4: None, qos_ctrl: None, ht_ctrl: None }
70 }
71}
72
73pub fn data_dst_addr(hdr: &FixedDataHdrFields) -> MacAddr {
75 let fc = hdr.frame_ctrl;
76 if fc.to_ds() {
77 hdr.addr3
78 } else {
79 hdr.addr1
80 }
81}
82
83pub fn data_src_addr(hdr: &FixedDataHdrFields, addr4: Option<MacAddr>) -> Option<MacAddr> {
84 let fc = hdr.frame_ctrl;
85 match (fc.to_ds(), fc.from_ds()) {
86 (_, false) => Some(hdr.addr2),
87 (false, true) => Some(hdr.addr3),
88 (true, true) => addr4,
89 }
90}
91
92pub fn data_transmitter_addr(hdr: &FixedDataHdrFields) -> MacAddr {
93 hdr.addr2
94}
95
96pub fn data_receiver_addr(hdr: &FixedDataHdrFields) -> MacAddr {
97 hdr.addr1
98}
99
100pub fn data_bssid(hdr: &FixedDataHdrFields) -> Option<MacAddr> {
102 let fc = hdr.frame_ctrl;
103 match (fc.to_ds(), fc.from_ds()) {
104 (false, false) => Some(hdr.addr3),
105 (false, true) => Some(hdr.addr2),
106 (true, false) => Some(hdr.addr1),
107 (true, true) => None,
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::mac::*;
115 use crate::test_utils::fake_frames::*;
116
117 #[test]
118 fn fixed_fields_len() {
119 assert_eq!(
120 FixedDataHdrFields::len(Addr4::ABSENT, QosControl::ABSENT, HtControl::ABSENT),
121 24
122 );
123 assert_eq!(
124 FixedDataHdrFields::len(Addr4::PRESENT, QosControl::ABSENT, HtControl::ABSENT),
125 30
126 );
127 assert_eq!(
128 FixedDataHdrFields::len(Addr4::ABSENT, QosControl::PRESENT, HtControl::ABSENT),
129 26
130 );
131 assert_eq!(
132 FixedDataHdrFields::len(Addr4::ABSENT, QosControl::ABSENT, HtControl::PRESENT),
133 28
134 );
135 assert_eq!(
136 FixedDataHdrFields::len(Addr4::PRESENT, QosControl::PRESENT, HtControl::ABSENT),
137 32
138 );
139 assert_eq!(
140 FixedDataHdrFields::len(Addr4::ABSENT, QosControl::PRESENT, HtControl::PRESENT),
141 30
142 );
143 assert_eq!(
144 FixedDataHdrFields::len(Addr4::PRESENT, QosControl::ABSENT, HtControl::PRESENT),
145 34
146 );
147 assert_eq!(
148 FixedDataHdrFields::len(Addr4::PRESENT, QosControl::PRESENT, HtControl::PRESENT),
149 36
150 );
151 }
152
153 #[test]
154 fn fixed_fields_dst_addr() {
155 let mut fixed_fields = make_data_hdr(None, [0, 0], None);
156 let (mut fixed_fields, _) =
157 Ref::<_, FixedDataHdrFields>::from_prefix(&mut fixed_fields[..])
158 .expect("invalid data header");
159 let mut fc = FrameControl(0);
160 fc.set_to_ds(true);
161 fixed_fields.frame_ctrl = fc;
162 assert_eq!(data_dst_addr(&fixed_fields), MacAddr::from([5; 6])); fc.set_to_ds(false);
164 fixed_fields.frame_ctrl = fc;
165 assert_eq!(data_dst_addr(&fixed_fields), MacAddr::from([3; 6])); }
167
168 #[test]
169 fn fixed_fields_src_addr() {
170 let mut fixed_fields = make_data_hdr(None, [0, 0], None);
171 let (mut fixed_fields, _) =
172 Ref::<_, FixedDataHdrFields>::from_prefix(&mut fixed_fields[..])
173 .expect("invalid data header");
174 let mut fc = FrameControl(0);
175 fixed_fields.frame_ctrl = fc;
177 assert_eq!(data_src_addr(&fixed_fields, None), Some(MacAddr::from([4; 6]))); fc.set_to_ds(true);
180 fixed_fields.frame_ctrl = fc;
182 assert_eq!(data_src_addr(&fixed_fields, None), Some(MacAddr::from([4; 6]))); fc.set_from_ds(true);
185 fixed_fields.frame_ctrl = fc;
187 assert_eq!(
188 data_src_addr(&fixed_fields, Some(MacAddr::from([11; 6]))),
189 Some(MacAddr::from([11; 6])) );
191
192 fc.set_to_ds(false);
193 fixed_fields.frame_ctrl = fc;
195 assert_eq!(
196 data_src_addr(&fixed_fields, None),
197 Some(MacAddr::from([5; 6])) );
199 }
200
201 #[test]
202 fn fixed_fields_ta() {
203 let mut fixed_fields = make_data_hdr(None, [0, 0], None);
204 let (fixed_fields, _) = Ref::<_, FixedDataHdrFields>::from_prefix(&mut fixed_fields[..])
205 .expect("invalid data header");
206 assert_eq!(
207 data_transmitter_addr(&fixed_fields),
208 MacAddr::from([4; 6]) );
210 }
211
212 #[test]
213 fn fixed_fields_ra() {
214 let mut fixed_fields = make_data_hdr(None, [0, 0], None);
215 let (fixed_fields, _) = Ref::<_, FixedDataHdrFields>::from_prefix(&mut fixed_fields[..])
216 .expect("invalid data header");
217 assert_eq!(data_receiver_addr(&fixed_fields), MacAddr::from([3; 6])); }
219
220 #[test]
221 fn fixed_fields_bssid() {
222 let mut fixed_fields = make_data_hdr(None, [0, 0], None);
223 let (mut fixed_fields, _) =
224 Ref::<_, FixedDataHdrFields>::from_prefix(&mut fixed_fields[..])
225 .expect("invalid data header");
226 let mut fc = FrameControl(0);
227 fixed_fields.frame_ctrl = fc;
229 assert_eq!(data_bssid(&fixed_fields), Some(MacAddr::from([5; 6]))); fc.set_to_ds(true);
232 fixed_fields.frame_ctrl = fc;
234 assert_eq!(data_bssid(&fixed_fields), Some(MacAddr::from([3; 6]))); fc.set_from_ds(true);
237 fixed_fields.frame_ctrl = fc;
239 assert_eq!(data_bssid(&fixed_fields), None);
240
241 fc.set_to_ds(false);
242 fixed_fields.frame_ctrl = fc;
244 assert_eq!(data_bssid(&fixed_fields), Some(MacAddr::from([4; 6]))); }
246}