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() || blockAckHeader.IsGcr())
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.
uint16_t m_startingSeq
Starting sequence control.
bool m_amsduSupported
Flag whether MSDU aggregation is supported.
uint16_t m_bufferSize
Buffer size.
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.
bool m_htSupported
Flag whether HT is supported.
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.
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 ...
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.
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 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
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 ...
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:188
static constexpr uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition wifi-utils.h:185
static constexpr uint8_t WIFI_LINKID_UNDEFINED
Invalid link identifier.
Definition wifi-utils.h:195
ns3::Time timeout
bool operator()(const Key &a, const Key &b) const
Functional operator for sorting the buffered MPDUs.