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