Macro wlan_frame_writer::write_frame
write_frame!() { /* proc-macro */ }
Expand description
Allocates a buffer in a new fdf::Arena
and writes a frame into the buffer.
This happens in three steps:
- Compute the frame’s length.
- Allocate a buffer an
fdf::Arena
. - Write the frame into the buffer.
§Headers
Headers must derive zerocopy’s various traits and be declared as packed & C-compatible. Headers are declared through a qualified path to a type followed by an expression evaluating to a reference of the same type. For example:
headers: {
mac::EthernetIIHdr: &mac::EthernetIIHdr {
da: dst_addr,
sa: src_addr,
ether_type: llc_frame.hdr.protocol_id,
},
},
§Body
An arbitrary body can be written to the end of the buffer’s header section. The body’s type must be a slice of a compatible type.
§IEs
§Supported IEs
- ssid: a byte slice
- supported_rates: a byte slice
- dsss_param_set: wlan_common::ie::DsssParamSet
- extended_supported_rates: a byte slice OR
{}
If{}
is used the rates supplied in thesupported_rates
IE will be continued in this one if they exceed the maximum amount of allowed supported rates. Note:extended_supported_rates
cannot be used without also declaringsupported_rates
first.extended_supported_rates
may not directly follow thesupported_rates
IE. - tim: wlan_common::ie::TimView
- ht_caps: wlan_common::ie::HtCapabilities
- vht_caps: wlan_common::ie::VhtCapabilities
- rsne: wlan_common::ie::rsn::rsne::Rsne
- bss_max_idle_period: wlan_common::ie::BssMaxIdlePeriod
- wsc: wlan_common::ie::Wsc
- wpa1: wlan_common::ie::Wpa1
§IE values
IE values can be any expression that evaluates to the corresponding IE type. For example the following expressions are valid:
ssid: vec![4u8; 12],
ssid: SSID_CONSTANT,
ssid: b"foobar",
ssid: self.generate_ssid(),
ssid: local_var,
ssid: match x { 0 => b"foo", _ => b"bar" },
ssid: if x { b"foo" } else { b"bar" },
§Optional IEs
IEs may be optional (see examples below). Optional IEs are declared through an ?
token.
Value expressions in optional IEs must evaluate to a value of type Option<V>
with V
being
a compatible value type. If the value is declared through an if-statement and NO else branch
was defined, the then-branch’s value must be of type V
and will automatically be wrapped with
Some(_)
if the condition was met. If the condition was not met, None
will be used.
If an else-brach was defined both branches must return an Option<V>
value.
§Emit IE offset
One can emit the offset at which a particular IE is written at.
let mut offset = 0;
let buffer = write_frame!({
...
ies: {
ssid: ssid,
supported_rates: &rates,
offset @ extended_supported_rates: {/* continue rates */},
},
...
});
§Payload
An arbitrary payload can be written to the end of the buffer. The payload’s type must be a slice of a compatible type.
§Return type
The macro returns a Result<ArenaStaticBuffer<[u8]>, Error>
.
§Constraints
The macro early returns with an error if the writing to the buffer failed, thus, the caller must
carry a return type of Result<(), Error>
. This macro is heavily dependent on the wlan_common
crates and assumes the caller to depend on those.
§Examples
let buffer = write_frame!({
headers: {
mac::MgmtHdr: &mac::MgmtHdr {
frame_ctrl: mac::FrameControl(0)
.with_frame_type(mac::FrameType::MGMT)
.with_mgmt_subtype(mac::MgmtSubtype::PROBE_REQ),
duration: 0,
addr1: mac::BCAST_ADDR,
addr2: self.iface_mac,
addr3: mac::BCAST_ADDR,
seq_ctrl: mac::SequenceControl(0)
.with_seq_num(self.ctx.seq_mgr.next_sns1(&mac::BCAST_ADDR) as u16),
},
},
ies: {
ssid: ssid,
supported_rates: &rates,
offset @ extended_supported_rates: {/* continue rates */},
ht_cap?: if band_info.ht_supported {
band_info.ht_caps.into()
},
vht_cap?: if band_info.vht_supported {
band_info.vht_caps.into()
}
},
payload: vec![42u8; 5],
});