IEEE 802.11 Block Acknowledgment¶
IEEE 802.11 block acknowledgment is a feature of the Media Access Control (MAC) layer of the 802.11 protocol that is designed to increase throughput by reducing protocol overhead. It works by allowing a single block acknowledgment frame to acknowledge the reception of multiple packets, instead of individually acknowledging each packet with a separate acknowledgement (ACK) frame. This reduces the number of ACK frames and corresponding interframe spaces, resulting in increased throughput.
In this showcase, we will demonstrate the block acknowledgment feature in INET’s 802.11 model. By the end of this showcase, you will understand how to enable and configure block acknowledgment in INET to improve the performance of wireless networks that use the 802.11 protocol.
About Block Acknowledgment¶
In 802.11, block acknowledgment frames (block acks or BAs) are used within block ack sessions. To establish a block ack session, one of the participants, the originator, sends an ADDBA request frame. The other participant, the recipient, replies with an ADDBA response frame. This exchange establishes the block ack session. The frames contain information about the capabilities of each participant, such as buffer size, or whether aggregation is supported. Each ADDBA frame is acked. The block ack session is for one direction only, i.e. a separate block ack session must be established for the reverse direction. Block ack sessions are terminated by the originator sending a DELBA frame.
The originator sends multiple data frames, then sends a block ack request frame. The recipient replies with a block ack frame, acknowledging the correctly received frames from the previous block. The block ack request frame and block ack frame are acked if delayed block ack is used, and not acked if immediate block ack is used. The frames or fragments of frames from the previous block which are not acked are retransmitted in the next block by the originator.
There are several kinds of block acks, such as normal, compressed, and multi-tid. INET currently only supports normal block ack. Normal block acks contain a bitmap, which contains up to 64 entries, each entry being a 16-bit array. The bitmap can acknowledge up to 64 MSDUs. Each MSDU can be fragmented to at most 16 fragments. The 16 bits in a bitmap entry are used to acknowledge the individual fragments of the MSDU.
Block Acknowledgment in INET¶
In INET, the block ack mechanism can be enabled by setting the
parameter of the MAC’s Hcf submodule to
true (it is disabled by default).
Several submodules of Hcf are involved in the block ack mechanism. These modules have parameters controlling the block ack behavior. The following paragraphs list some of the main parameters.
The details of the block ack agreement, which is negotiated at the beginning of
the block ack session, are specified by block ack agreement policy modules.
There are two module types, one for the originator and one for the recipient direction.
They have the same set of parameters. The parameters of OriginatorBlockAckAgreementPolicy
mac.hcf.originatorBlockAckAgreementPolicy) and RecipientBlockAckAgreementPolicy
mac.hcf.recipientBlockAckAgreementPolicy) are the following:
true, aMSDUs are block acked; otherwise they are normal acked (default).
maximumAllowedBufferSize: Sets the buffer size, i.e. how many MSDUs can be acked with a block ack, 64 by default.
Ack policy modules control how packets are acked. There are two module types,
one for each direction (originator and recipient), but settings are configured in
the originator module. Parameters of OriginatorQosAckPolicy (at
mac.hcf.originatorAckPolicy) are the following:
blockAckReqThreshold: The originator sends a block ack request after sending this many packets
maxBlockAckPolicyFrameLength: Only packets below this length are block acked (others are normal acked)
Currently, only immediate block ack is implemented. Also, block ack sessions cannot be enabled in one direction and disabled in the other.
The example simulation uses a network that contains two AdhocHost modules,
an Ipv4NetworkConfigurator, an Ieee80211ScalarRadioMedium and
an IntegratedVisualizer module. During simulation,
host1 will send
UDP packets to
We’ll use three configurations to demonstrate various aspects of the block ack mechanism.
The configurations in
omnetpp.ini are the following:
NoFragmentation: Packets are sent without fragmentation or aggregation. Block ack requests are sent after five packets (default).
Fragmentation: Packets are fragmented to 16 pieces, block ack requests are sent after 16 fragments.
MixedTraffic: Two traffic sources in
host1generate packets below and above the
maxBlockAckPolicyFrameLengththreshold. Packets with size below the threshold are block acked; those above aren’t.
Parameter settings common to the three configurations are defined in the
omnetpp.ini. The rest of this section explains the most important
host1 is configured to send 700B UDP packets to
host2 with about 10Mbps:
*.host1.numApps = 1 *.host1.app.typename = "UdpBasicApp" *.host1.app.destAddresses = "host2" *.host1.app.destPort = 1000 *.host1.app.messageLength = 700B *.host1.app.sendInterval = 0.1ms # 10 Mbps *.host1.app.packetName = "Data" *.host2.numApps = 1 *.host2.app.typename = "UdpSink" *.host2.app.localPort = 1000
802.11 QoS is enabled in both hosts, and a classifier is included:
*.host*.wlan[*].mac.qosStation = true *.host*.wlan[*].classifier.typename = "QosClassifier"
Block ack support is enabled in both hosts:
*.host*.wlan[*].mac.hcf.isBlockAckSupported = true
The maximum block ack frame length is left on default, 1000B.
Fragmentation and aggregation is disabled by raising the thresholds:
**.hcf.originatorMacDataService.fragmentationPolicy.fragmentationThreshold = 10000B **.hcf.originatorMacDataService.msduAggregationPolicy.aggregationLengthThreshold = 10000
The transmitter power is lowered to make the communication more noisy, in order to get some lost packets:
*.host*.wlan[*].radio.transmitter.power = 0.12mW
In the next sections, we’ll look at the three configurations and their results.
In this simulation, packets are sent unfragmented, and
host1 sends a block ack request
after sending five frames (the default). The configuration in
[Config NoFragmentation] description = "Packets are not fragmented, block ack after 5 packet transmissions (default)"
Here is the starting frame sequence at the beginning of the simulation displayed in Qtenv’s packet traffic view:
host1 sends an UDP packet, then an ADDBA request frame.
with an ADDBA response frame (both frames are acked). This frame exchange establishes
the block ack session, and
host2 doesn’t normal ack the frames from this point forward
but waits for a block ack request.
Here are the ADDBA request and ADDBA response frames displayed in the packet traffic view:
It indicates that aggregate MSDUs (aMSDUs) are supported, and the buffer size in both hosts is 64.
After sending five UDP packets,
host1 sends a block ack request,
with a block ack. The block ack frame acks the five previous frames. Here is the block ack
request frame displayed in Qtenv’s packet inspector:
The block ack request contains the starting sequence number, which indicates the first packet to be acked. Here is the block ack response frame:
It contains the starting sequence number as well, and the bitmap which specifies which packets were received correctly. Here is the bitmap:
The first five entries are used. It acks the five packets, starting from sequence number 1.
When there is no fragmentation, only the first bit of the 16-bit entry is used to ack the frame. Here, the first three entries are all ones because the MAC already passed those packets to the higher layers, and has no information about the number of fragments, but still it indicates that the packets were successfully received. (This is an implementation detail.)
It is indicated in the block ack when some of the frames in a block were not received correctly. The MAC retransmits those in the next block. Here is a retransmission in the packet traffic view:
host1 sends five packets,
Data-20. Two of the frames,
Data-18 are not received correctly, indicated in the block ack’s bitmap (starting
sequence number is 16, corresponding to
The next block starts with
host1 retransmitting these two frames, then transmitting
three new ones.
In this simulation, 1080B packets are fragmented to 16 pieces, each 100B. Block ack requests
are sent after 16 frames. It is defined in the
Fragmentation configuration in
[Config Fragmentation] description = "Packets are fragmented to 16 pieces, block ack after 16 packet transmissions" **.hcf.originatorMacDataService.fragmentationPolicy.fragmentationThreshold = 100B *.host1.app.messageLength = 1080B *.host*.wlan[*].mac.hcf.originatorAckPolicy.blockAckReqThreshold = 16
Here is how the simulation starts displayed in the packet traffic view:
After sending a fragment, the block ack session is negotiated. After that,
the remaining fragments of
Data-0, which are normal acked. However, the fragments of the
Data-1, are block acked:
In the next block, two fragments of
Data-1 are retransmitted, then several fragments of
Here is the block ack bitmap for this block:
The first entry of the bitmap is all ones, indicating that
Data-1 was completely received
(all fragments), even though only two fragments of it were sent in this block. The second
entry has three zeros. The first zero indicates a lost fragment of
Data-2; the last two correspond to fragments that haven’t been sent yet.
In this configuration, there are two UDP apps in
host1, sending 1700B and 700B packets.
maxBlockAckPolicyFrameLength parameter is set to 1000B (default), so the large
packets are individually acked, while the smaller ones are block acked. The simulation is
defined in the
MixedTraffic configuration in
[Config MixedTraffic] description = "Mixed traffic of packets shorter and longer than blockAckReqThreshold" *.host1.numApps = 2 *.host1.app.typename = "UdpBasicApp" *.host1.app.destAddresses = "host2" *.host1.app.destPort = 2000 *.host1.app.messageLength = 1700B *.host1.app.sendInterval = 0.1ms # 10 Mbps *.host1.app.packetName = "Large" *.host2.numApps = 2 *.host2.app.typename = "UdpSink" *.host2.app.localPort = 2000
The smaller and larger packets are created at the same rate, so
host1 sends them alternately.
However, only the smaller ones are considered when sending block ack requests (sent after five
of the 700B packets). The larger packets are normal acked immediately:
Here, the block starts with
Data-10, and also some large packets, are sent.
Large-9, for example, are sent twice because they weren’t correctly received
for the first time (there was no ack). The 802.11 MAC sequence numbers are contiguous between
all the packets sent by the MAC, so the block ack bitmap contains (the already acked) large
packets as well:
Also, the block ack is lost, so the not-yet-acked packets in the previous block (
Data-10) are retransmitted.
Instead of retransmitting the data frames, the originator could send the block ack request again if it didn’t receive a block ack. This is currently a limitation of the implementation.
Use this page in the GitHub issue tracker for commenting on this showcase.