A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
recipient-block-ack-agreement.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "ctrl-headers.h"
12#include "mac-rx-middle.h"
13#include "wifi-mpdu.h"
14#include "wifi-utils.h"
15
16#include "ns3/log.h"
17#include "ns3/packet.h"
18
19#include <algorithm>
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("RecipientBlockAckAgreement");
25
26bool
28{
29 return ((a.first - *a.second + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE) <
30 ((b.first - *b.second + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE);
31}
32
34 bool amsduSupported,
35 uint8_t tid,
36 uint16_t bufferSize,
37 uint16_t timeout,
38 uint16_t startingSeq,
39 bool htSupported)
40 : BlockAckAgreement(originator, tid)
41{
42 NS_LOG_FUNCTION(this << originator << amsduSupported << +tid << bufferSize << timeout
43 << startingSeq << htSupported);
44
45 m_amsduSupported = amsduSupported;
46 m_bufferSize = bufferSize;
48 m_startingSeq = startingSeq;
49 m_htSupported = htSupported;
50
51 m_scoreboard.Init(startingSeq, bufferSize);
52 m_winStartB = startingSeq;
53 m_winSizeB = bufferSize;
54}
55
62
63void
65{
66 NS_LOG_FUNCTION(this << rxMiddle);
67 m_rxMiddle = rxMiddle;
68}
69
70void
72{
73 NS_LOG_FUNCTION(this);
74
75 // There cannot be old MPDUs in the buffer (we just check the MPDU with the
76 // highest sequence number)
77 NS_ASSERT(m_bufferedMpdus.empty() || GetDistance(m_bufferedMpdus.rbegin()->first.first,
79
80 auto it = m_bufferedMpdus.begin();
81
82 while (it != m_bufferedMpdus.end() && it->first.first == m_winStartB)
83 {
84 NS_LOG_DEBUG("Forwarding up: " << *it->second);
85 m_rxMiddle->Receive(it->second, WIFI_LINKID_UNDEFINED);
86 it = m_bufferedMpdus.erase(it);
88 }
89}
90
91void
93{
94 NS_LOG_FUNCTION(this << newWinStartB);
95
96 // There cannot be old MPDUs in the buffer (we just check the MPDU with the
97 // highest sequence number)
98 NS_ASSERT(m_bufferedMpdus.empty() || GetDistance(m_bufferedMpdus.rbegin()->first.first,
100
101 auto it = m_bufferedMpdus.begin();
102
103 while (it != m_bufferedMpdus.end() &&
104 GetDistance(it->first.first, m_winStartB) < GetDistance(newWinStartB, m_winStartB))
105 {
106 NS_LOG_DEBUG("Forwarding up: " << *it->second);
107 m_rxMiddle->Receive(it->second, WIFI_LINKID_UNDEFINED);
108 it = m_bufferedMpdus.erase(it);
109 }
110 m_winStartB = newWinStartB;
111}
112
113void
115{
116 NS_LOG_FUNCTION(this << *mpdu);
117
118 uint16_t mpduSeqNumber = mpdu->GetHeader().GetSequenceNumber();
119 uint16_t distance = GetDistance(mpduSeqNumber, m_scoreboard.GetWinStart());
120
121 /* Update the scoreboard (see Section 10.24.7.3 of 802.11-2016) */
122 if (distance < m_scoreboard.GetWinSize())
123 {
124 // set to 1 the bit in position SN within the bitmap
125 m_scoreboard.At(distance) = true;
126 }
127 else if (distance < SEQNO_SPACE_HALF_SIZE)
128 {
131 }
132
133 distance = GetDistance(mpduSeqNumber, m_winStartB);
134
135 /* Update the receive reordering buffer (see Section 10.24.7.6.2 of 802.11-2016) */
136 if (distance < m_winSizeB)
137 {
138 // 1. Store the received MPDU in the buffer, if no MSDU with the same sequence
139 // number is already present
140 m_bufferedMpdus.insert({{mpdu->GetHeader().GetSequenceNumber(), &m_winStartB}, mpdu});
141
142 // 2. Pass MSDUs or A-MSDUs up to the next MAC process if they are stored in
143 // the buffer in order of increasing value of the Sequence Number subfield
144 // starting with the MSDU or A-MSDU that has SN=WinStartB
145 // 3. Set WinStartB to the value of the Sequence Number subfield of the last
146 // MSDU or A-MSDU that was passed up to the next MAC process plus one.
148 }
149 else if (distance < SEQNO_SPACE_HALF_SIZE)
150 {
151 // 1. Store the received MPDU in the buffer, if no MSDU with the same sequence
152 // number is already present
153 m_bufferedMpdus.insert({{mpdu->GetHeader().GetSequenceNumber(), &m_winStartB}, mpdu});
154
155 // 2. Set WinEndB = SN
156 // 3. Set WinStartB = WinEndB – WinSizeB + 1
157 // 4. Pass any complete MSDUs or A-MSDUs stored in the buffer with Sequence Number
158 // subfield values that are lower than the new value of WinStartB up to the next
159 // MAC process in order of increasing Sequence Number subfield value. Gaps may
160 // exist in the Sequence Number subfield values of the MSDUs or A-MSDUs that are
161 // passed up to the next MAC process.
162 PassBufferedMpdusWithSeqNumberLessThan(mpdu->GetHeader().GetSequenceNumber() - m_winSizeB +
163 1);
164
165 // 5. Pass MSDUs or A-MSDUs stored in the buffer up to the next MAC process in
166 // order of increasing value of the Sequence Number subfield starting with
167 // WinStartB and proceeding sequentially until there is no buffered MSDU or
168 // A-MSDU for the next sequential Sequence Number subfield value
170 }
171}
172
173void
180
181void
182RecipientBlockAckAgreement::NotifyReceivedBar(uint16_t startingSequenceNumber)
183{
184 NS_LOG_FUNCTION(this << startingSequenceNumber);
185
186 uint16_t distance = GetDistance(startingSequenceNumber, m_scoreboard.GetWinStart());
187
188 /* Update the scoreboard (see Section 10.24.7.3 of 802.11-2016) */
189 if (distance > 0 && distance < m_scoreboard.GetWinSize())
190 {
191 // advance by SSN - WinStartR, so that WinStartR becomes equal to SSN
192 m_scoreboard.Advance(distance);
193 NS_ASSERT(m_scoreboard.GetWinStart() == startingSequenceNumber);
194 }
195 else if (distance > 0 && distance < SEQNO_SPACE_HALF_SIZE)
196 {
197 // reset the window and set WinStartR to SSN
198 m_scoreboard.Reset(startingSequenceNumber);
199 }
200
201 distance = GetDistance(startingSequenceNumber, m_winStartB);
202
203 /* Update the receive reordering buffer (see Section 10.24.7.6.2 of 802.11-2016) */
204 if (distance > 0 && distance < SEQNO_SPACE_HALF_SIZE)
205 {
206 // 1. set WinStartB = SSN
207 // 3. Pass any complete MSDUs or A-MSDUs stored in the buffer with Sequence
208 // Number subfield values that are lower than the new value of WinStartB up to
209 // the next MAC process in order of increasing Sequence Number subfield value
210 PassBufferedMpdusWithSeqNumberLessThan(startingSequenceNumber);
211
212 // 4. Pass MSDUs or A-MSDUs stored in the buffer up to the next MAC process
213 // in order of increasing Sequence Number subfield value starting with
214 // SN=WinStartB and proceeding sequentially until there is no buffered MSDU
215 // or A-MSDU for the next sequential Sequence Number subfield value
217 }
218}
219
220void
222 std::size_t index) const
223{
224 NS_LOG_FUNCTION(this << blockAckHeader << index);
225 if (blockAckHeader->IsBasic())
226 {
227 NS_FATAL_ERROR("Basic block ack is not supported.");
228 }
229 else if (blockAckHeader->IsMultiTid())
230 {
231 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
232 }
233 else if (blockAckHeader->IsCompressed() || blockAckHeader->IsExtendedCompressed() ||
234 blockAckHeader->IsMultiSta())
235 {
236 // The Starting Sequence Number subfield of the Block Ack Starting Sequence
237 // Control subfield of the BlockAck frame shall be set to any value in the
238 // range (WinEndR – 63) to WinStartR (Sec. 10.24.7.5 of 802.11-2016).
239 // We set it to WinStartR
240 uint16_t ssn = m_scoreboard.GetWinStart();
241 NS_LOG_DEBUG("SSN=" << ssn);
242 blockAckHeader->SetStartingSequence(ssn, index);
243 blockAckHeader->ResetBitmap(index);
244
245 for (std::size_t i = 0; i < m_scoreboard.GetWinSize(); i++)
246 {
247 if (m_scoreboard.At(i))
248 {
249 blockAckHeader->SetReceivedPacket((ssn + i) % SEQNO_SPACE_SIZE, index);
250 }
251 }
252 }
253}
254
255} // namespace ns3
Maintains information for a block ack agreement.
uint8_t m_htSupported
Flag whether HT is supported.
uint16_t m_startingSeq
Starting sequence control.
uint16_t m_bufferSize
Buffer size.
uint8_t m_amsduSupported
Flag whether MSDU aggregation is supported.
static std::size_t GetDistance(uint16_t seqNumber, uint16_t startingSeqNumber)
Get the distance between the given starting sequence number and the given sequence number.
void Reset(uint16_t winStart)
Reset the window by clearing all the elements and setting winStart to the given value.
std::size_t GetWinSize() const
Get the window size.
void Advance(std::size_t count)
Advance the current winStart by the given number of positions.
uint16_t GetWinStart() const
Get the current winStart value.
void Init(uint16_t winStart, uint16_t winSize)
Initialize the window with the given starting sequence number and size.
std::vector< bool >::reference At(std::size_t distance)
Get a reference to the element in the window having the given distance from the current winStart.
Headers for BlockAck response.
bool IsExtendedCompressed() const
Check if the current BA policy is Extended Compressed Block Ack.
void SetStartingSequence(uint16_t seq, std::size_t index=0)
For Block Ack variants other than Multi-STA Block Ack, set the starting sequence number to the given ...
bool IsBasic() const
Check if the current BA policy is Basic Block Ack.
bool IsCompressed() const
Check if the current BA policy is Compressed Block Ack.
void ResetBitmap(std::size_t index=0)
Reset the bitmap to 0.
void SetReceivedPacket(uint16_t seq, std::size_t index=0)
Record in the bitmap that the packet with the given sequence number was received.
bool IsMultiTid() const
Check if the current BA policy is Multi-TID Block Ack.
bool IsMultiSta() const
Check if the BlockAck frame variant is Multi-STA Block Ack.
an EUI-48 address
Smart pointer class similar to boost::intrusive_ptr.
Ptr< MacRxMiddle > m_rxMiddle
the MAC RX Middle on this station
void PassBufferedMpdusWithSeqNumberLessThan(uint16_t newWinStartB)
Pass any complete MSDUs or A-MSDUs stored in the buffer with Sequence Number subfield values that are...
BlockAckWindow m_scoreboard
recipient's scoreboard
void NotifyReceivedBar(uint16_t startingSequenceNumber)
Update both the scoreboard and the receive reordering buffer upon reception of a Block Ack Request.
void Flush()
This is called when a Block Ack agreement is destroyed to flush the received packets.
void FillBlockAckBitmap(CtrlBAckResponseHeader *blockAckHeader, std::size_t index=0) const
Set the Starting Sequence Number subfield of the Block Ack Starting Sequence Control subfield of the ...
void PassBufferedMpdusUntilFirstLost()
Pass MSDUs or A-MSDUs up to the next MAC process if they are stored in the buffer in order of increas...
std::pair< uint16_t, uint16_t * > Key
The key of a buffered MPDU is the pair (MPDU sequence number, pointer to WinStartB)
void NotifyReceivedMpdu(Ptr< const WifiMpdu > mpdu)
Update both the scoreboard and the receive reordering buffer upon reception of the given MPDU.
RecipientBlockAckAgreement(Mac48Address originator, bool amsduSupported, uint8_t tid, uint16_t bufferSize, uint16_t timeout, uint16_t startingSeq, bool htSupported)
Constructor.
std::map< Key, Ptr< const WifiMpdu >, Compare > m_bufferedMpdus
buffered MPDUs sorted by Seq Number
uint16_t m_winStartB
starting SN for the reordering buffer
std::size_t m_winSizeB
size of the receive reordering buffer
void SetMacRxMiddle(const Ptr< MacRxMiddle > rxMiddle)
Set the MAC RX Middle to use.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static constexpr uint16_t SEQNO_SPACE_HALF_SIZE
Size of the half the space of sequence numbers (used to determine old packets)
Definition wifi-utils.h:179
static constexpr uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition wifi-utils.h:176
static constexpr uint8_t WIFI_LINKID_UNDEFINED
Invalid link identifier.
Definition wifi-utils.h:186
ns3::Time timeout
bool operator()(const Key &a, const Key &b) const
Functional operator for sorting the buffered MPDUs.