wlan_common/mac/data/
fields.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
5use crate::mac::{FrameControl, HtControl, MacAddr, OptionalField, Presence, SequenceControl};
6use wlan_bitfield::bitfield;
7use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
8
9// IEEE Std 802.11-2016, 9.2.4.5.1, Table 9-6
10#[bitfield(
11    0..=3   tid,
12    4       eosp,
13    5..=6   ack_policy,
14    7       amsdu_present,
15    8..=15  high_byte, // interpretation varies
16)]
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// IEEE Std 802.11-2016, 9.3.2.1
24#[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    /// Returns the length in bytes of a data header including all its fixed and optional
39    /// fields (if they are present).
40    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
73// IEEE Std 802.11-2016, Table 9-26 defines DA, SA, RA, TA, BSSID
74pub 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
100/// BSSID: basic service set ID
101pub 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])); // Addr3
163        fc.set_to_ds(false);
164        fixed_fields.frame_ctrl = fc;
165        assert_eq!(data_dst_addr(&fixed_fields), MacAddr::from([3; 6])); // Addr1
166    }
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        // to_ds == false && from_ds == false
176        fixed_fields.frame_ctrl = fc;
177        assert_eq!(data_src_addr(&fixed_fields, None), Some(MacAddr::from([4; 6]))); // Addr2
178
179        fc.set_to_ds(true);
180        // to_ds == true && from_ds == false
181        fixed_fields.frame_ctrl = fc;
182        assert_eq!(data_src_addr(&fixed_fields, None), Some(MacAddr::from([4; 6]))); // Addr2
183
184        fc.set_from_ds(true);
185        // to_ds == true && from_ds == true;
186        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])) // Addr4
190        );
191
192        fc.set_to_ds(false);
193        // to_ds == false && from_ds == true;
194        fixed_fields.frame_ctrl = fc;
195        assert_eq!(
196            data_src_addr(&fixed_fields, None),
197            Some(MacAddr::from([5; 6])) // Addr3
198        );
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]) // Addr2
209        );
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])); // Addr2
218    }
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        // to_ds == false && from_ds == false
228        fixed_fields.frame_ctrl = fc;
229        assert_eq!(data_bssid(&fixed_fields), Some(MacAddr::from([5; 6]))); // Addr3
230
231        fc.set_to_ds(true);
232        // to_ds == true && from_ds == false
233        fixed_fields.frame_ctrl = fc;
234        assert_eq!(data_bssid(&fixed_fields), Some(MacAddr::from([3; 6]))); // Addr1
235
236        fc.set_from_ds(true);
237        // to_ds == true && from_ds == true;
238        fixed_fields.frame_ctrl = fc;
239        assert_eq!(data_bssid(&fixed_fields), None);
240
241        fc.set_to_ds(false);
242        // to_ds == false && from_ds == true;
243        fixed_fields.frame_ctrl = fc;
244        assert_eq!(data_bssid(&fixed_fields), Some(MacAddr::from([4; 6]))); // Addr2
245    }
246}