INET Framework for OMNeT++/OMNEST
inet::ieee80211::BlockAckReordering Class Reference

#include <BlockAckReordering.h>

Public Types

typedef std::vector< Ieee80211DataFrame * > Fragments
 
typedef std::map< SequenceNumber, FragmentsReorderBuffer
 

Public Member Functions

virtual ~BlockAckReordering ()
 
void processReceivedDelba (Ieee80211Delba *delba)
 
ReorderBuffer processReceivedQoSFrame (RecipientBlockAckAgreement *agreement, Ieee80211DataFrame *dataFrame)
 
ReorderBuffer processReceivedBlockAckReq (Ieee80211BlockAckReq *frame)
 

Protected Member Functions

ReorderBuffer collectCompletePrecedingMpdus (ReceiveBuffer *receiveBuffer, int startingSequenceNumber)
 
ReorderBuffer collectConsecutiveCompleteFollowingMpdus (ReceiveBuffer *receiveBuffer, int startingSequenceNumber)
 
std::vector< Ieee80211DataFrame * > getEarliestCompleteMsduOrAMsduIfExists (ReceiveBuffer *receiveBuffer)
 
bool isComplete (const Fragments &fragments)
 
void passedUp (ReceiveBuffer *receiveBuffer, int sequenceNumber)
 
void releaseReceiveBuffer (ReceiveBuffer *receiveBuffer, const ReorderBuffer &reorderBuffer)
 
ReceiveBuffercreateReceiveBufferIfNecessary (RecipientBlockAckAgreement *agreement)
 
bool addMsduIfComplete (ReceiveBuffer *receiveBuffer, ReorderBuffer &reorderBuffer, SequenceNumber seqNum)
 

Protected Attributes

std::map< std::pair< Tid, MACAddress >, ReceiveBuffer * > receiveBuffers
 

Member Typedef Documentation

Constructor & Destructor Documentation

inet::ieee80211::BlockAckReordering::~BlockAckReordering ( )
virtual
261 {
262  for (auto receiveBuffer : receiveBuffers)
263  delete receiveBuffer.second;
264 }
std::map< std::pair< Tid, MACAddress >, ReceiveBuffer * > receiveBuffers
Definition: BlockAckReordering.h:39

Member Function Documentation

bool inet::ieee80211::BlockAckReordering::addMsduIfComplete ( ReceiveBuffer receiveBuffer,
ReorderBuffer reorderBuffer,
SequenceNumber  seqNum 
)
protected

Referenced by collectConsecutiveCompleteFollowingMpdus().

160 {
161  const auto& buffer = receiveBuffer->getBuffer();
162  auto it = buffer.find(seqNum);
163  if (it != buffer.end()) {
164  auto fragments = it->second;
165  if (isComplete(fragments)) {
166  reorderBuffer[seqNum] = fragments;
167  return true;
168  }
169  }
170  return false;
171 }
bool isComplete(const Fragments &fragments)
Definition: BlockAckReordering.cc:182
BlockAckReordering::ReorderBuffer inet::ieee80211::BlockAckReordering::collectCompletePrecedingMpdus ( ReceiveBuffer receiveBuffer,
int  startingSequenceNumber 
)
protected

Referenced by processReceivedBlockAckReq().

117 {
118  ASSERT(startingSequenceNumber != -1);
119  ReorderBuffer completePrecedingMpdus;
120  const auto& buffer = receiveBuffer->getBuffer();
121  for (auto it : buffer) { // collects complete preceding MPDUs
122  int sequenceNumber = it.first;
123  auto fragments = it.second;
124  if (isSequenceNumberLess(sequenceNumber, startingSequenceNumber, receiveBuffer->getNextExpectedSequenceNumber(), receiveBuffer->getBufferSize()))
125  if (isComplete(fragments))
126  completePrecedingMpdus[sequenceNumber] = fragments;
127  }
128  return completePrecedingMpdus;
129 }
std::map< SequenceNumber, Fragments > ReorderBuffer
Definition: BlockAckReordering.h:36
bool isComplete(const Fragments &fragments)
Definition: BlockAckReordering.cc:182
BlockAckReordering::ReorderBuffer inet::ieee80211::BlockAckReordering::collectConsecutiveCompleteFollowingMpdus ( ReceiveBuffer receiveBuffer,
int  startingSequenceNumber 
)
protected

Referenced by processReceivedBlockAckReq().

137 {
138  ASSERT(startingSequenceNumber != -1);
139  ReorderBuffer framesToPassUp;
140  if (startingSequenceNumber + receiveBuffer->getBufferSize() > 4095) {
141  for (int i = startingSequenceNumber; i <= 4095; i++) {
142  if (!addMsduIfComplete(receiveBuffer, framesToPassUp, i))
143  return framesToPassUp;
144  }
145  for (int i = 0; i < (startingSequenceNumber + receiveBuffer->getBufferSize()) % 4096; i++) {
146  if (!addMsduIfComplete(receiveBuffer, framesToPassUp, i))
147  return framesToPassUp;
148  }
149  }
150  else {
151  for (int i = startingSequenceNumber; i < startingSequenceNumber + receiveBuffer->getBufferSize(); i++) {
152  if (!addMsduIfComplete(receiveBuffer, framesToPassUp, i))
153  return framesToPassUp;
154  }
155  }
156  return framesToPassUp;
157 }
std::map< SequenceNumber, Fragments > ReorderBuffer
Definition: BlockAckReordering.h:36
bool addMsduIfComplete(ReceiveBuffer *receiveBuffer, ReorderBuffer &reorderBuffer, SequenceNumber seqNum)
Definition: BlockAckReordering.cc:159
ReceiveBuffer * inet::ieee80211::BlockAckReordering::createReceiveBufferIfNecessary ( RecipientBlockAckAgreement agreement)
protected

Referenced by processReceivedQoSFrame().

195 {
196  SequenceNumber startingSequenceNumber = agreement->getStartingSequenceNumber();
197  int bufferSize = agreement->getBufferSize();
198  Tid tid = agreement->getBlockAckRecord()->getTid();
199  MACAddress originatorAddr = agreement->getBlockAckRecord()->getOriginatorAddress();
200  auto id = std::make_pair(tid, originatorAddr);
201  auto it = receiveBuffers.find(id);
202  if (it == receiveBuffers.end()) {
203  ReceiveBuffer *buffer = new ReceiveBuffer(bufferSize, startingSequenceNumber);
204  receiveBuffers[id] = buffer;
205  return buffer;
206  }
207  else
208  return it->second;
209 }
int8_t Tid
Definition: Ieee80211Defs.h:28
int16_t SequenceNumber
Definition: Ieee80211Defs.h:26
uint16_t id
Definition: TCP_NSC.cc:85
std::map< std::pair< Tid, MACAddress >, ReceiveBuffer * > receiveBuffers
Definition: BlockAckReordering.h:39
std::vector< Ieee80211DataFrame * > inet::ieee80211::BlockAckReordering::getEarliestCompleteMsduOrAMsduIfExists ( ReceiveBuffer receiveBuffer)
protected

Referenced by processReceivedQoSFrame().

235 {
236  Fragments earliestFragments = Fragments();
237  SequenceNumber earliestSeqNum = 0;
238  const auto& buffer = receiveBuffer->getBuffer();
239  for (auto it : buffer) {
240  if (isComplete(it.second)) {
241  earliestFragments = it.second;
242  earliestSeqNum = earliestFragments.at(0)->getSequenceNumber();
243  break;
244  }
245  }
246  if (earliestFragments.size() > 0) {
247  for (auto it : buffer) {
248  SequenceNumber currentSeqNum = it.second.at(0)->getSequenceNumber();
249  if (isSequenceNumberLess(currentSeqNum, earliestSeqNum, receiveBuffer->getNextExpectedSequenceNumber(), receiveBuffer->getBufferSize())) {
250  if (isComplete(it.second)) {
251  earliestFragments = it.second;
252  earliestSeqNum = currentSeqNum;
253  }
254  }
255  }
256  }
257  return earliestFragments;
258 }
int16_t SequenceNumber
Definition: Ieee80211Defs.h:26
bool isComplete(const Fragments &fragments)
Definition: BlockAckReordering.cc:182
std::vector< Ieee80211DataFrame * > Fragments
Definition: BlockAckReordering.h:35
bool inet::ieee80211::BlockAckReordering::isComplete ( const Fragments fragments)
protected

Referenced by addMsduIfComplete(), collectCompletePrecedingMpdus(), and getEarliestCompleteMsduOrAMsduIfExists().

183 {
184  int largestFragmentNumber = -1;
185  std::set<FragmentNumber> fragNums; // possible duplicate frames
186  for (auto fragment : fragments) {
187  if (!fragment->getMoreFragments())
188  largestFragmentNumber = fragment->getFragmentNumber();
189  fragNums.insert(fragment->getFragmentNumber());
190  }
191  return largestFragmentNumber != -1 && largestFragmentNumber + 1 == (int)fragNums.size();
192 }
void inet::ieee80211::BlockAckReordering::passedUp ( ReceiveBuffer receiveBuffer,
int  sequenceNumber 
)
protected

Referenced by processReceivedQoSFrame(), and releaseReceiveBuffer().

226 {
227  // Each time that the recipient passes an MSDU or A-MSDU for a Block Ack agreement up to the next MAC
228  // process, the NextExpectedSequenceNumber for that Block Ack agreement is set to the sequence number of the
229  // MSDU or A-MSDU that was passed up to the next MAC process plus one.
230  receiveBuffer->setNextExpectedSequenceNumber((sequenceNumber + 1) % 4096);
231  receiveBuffer->remove(sequenceNumber);
232 }
BlockAckReordering::ReorderBuffer inet::ieee80211::BlockAckReordering::processReceivedBlockAckReq ( Ieee80211BlockAckReq frame)

Referenced by inet::ieee80211::RecipientQoSMacDataService::controlFrameReceived().

64 {
65  // The originator shall use the Block Ack starting sequence control to signal the first MPDU in the block for
66  // which an acknowledgment is expected.
67  int startingSequenceNumber = -1;
68  Tid tid = -1;
69  if (auto basicReq = dynamic_cast<Ieee80211BasicBlockAckReq*>(frame)) {
70  tid = basicReq->getTidInfo();
71  startingSequenceNumber = basicReq->getStartingSequenceNumber();
72  }
73  else if (auto compressedReq = dynamic_cast<Ieee80211CompressedBlockAck*>(frame)) {
74  tid = compressedReq->getTidInfo();
75  startingSequenceNumber = compressedReq->getStartingSequenceNumber();
76  }
77  else {
78  throw cRuntimeError("Multi-Tid BlockAckReq is currently an unimplemented feature");
79  }
80  auto id = std::make_pair(tid, frame->getTransmitterAddress());
81  auto it = receiveBuffers.find(id);
82  if (it != receiveBuffers.end()) {
83  ReceiveBuffer *receiveBuffer = it->second;
84  // MPDUs in the recipient’s buffer with a sequence control value that
85  // precedes the starting sequence control value are called preceding MPDUs.
86  // The recipient shall reassemble any complete MSDUs from buffered preceding
87  // MPDUs and indicate these to its higher layer.
88  auto completePrecedingMpdus = collectCompletePrecedingMpdus(receiveBuffer, startingSequenceNumber);
89  // Upon arrival of a BlockAckReq frame, the recipient shall pass up the MSDUs and A-MSDUs starting with
90  // the starting sequence number sequentially until there is an incomplete or missing MSDU
91  // or A-MSDU in the buffer.
92  auto consecutiveCompleteFollowingMpdus = collectConsecutiveCompleteFollowingMpdus(receiveBuffer, startingSequenceNumber);
93  // If no MSDUs or A-MSDUs are passed up to the next MAC process after the receipt
94  // of the BlockAckReq frame and the starting sequence number of the BlockAckReq frame is newer than the
95  // NextExpectedSequenceNumber for that Block Ack agreement, then the NextExpectedSequenceNumber for
96  // that Block Ack agreement is set to the sequence number of the BlockAckReq frame.
97  int numOfMsdusToPassUp = completePrecedingMpdus.size() + consecutiveCompleteFollowingMpdus.size();
98  if (numOfMsdusToPassUp == 0 && isSequenceNumberLess(receiveBuffer->getNextExpectedSequenceNumber(), startingSequenceNumber, receiveBuffer->getNextExpectedSequenceNumber(), receiveBuffer->getBufferSize()))
99  receiveBuffer->setNextExpectedSequenceNumber(startingSequenceNumber);
100  // The recipient shall then release any buffers held by preceding MPDUs.
101  releaseReceiveBuffer(receiveBuffer, completePrecedingMpdus);
102  releaseReceiveBuffer(receiveBuffer, consecutiveCompleteFollowingMpdus);
103  // The recipient shall pass MSDUs and A-MSDUs up to the next MAC process in order of increasing sequence
104  // number.
105  completePrecedingMpdus.insert(consecutiveCompleteFollowingMpdus.begin(), consecutiveCompleteFollowingMpdus.end());
106  return completePrecedingMpdus;
107  }
108  return ReorderBuffer();
109 }
int8_t Tid
Definition: Ieee80211Defs.h:28
ReorderBuffer collectConsecutiveCompleteFollowingMpdus(ReceiveBuffer *receiveBuffer, int startingSequenceNumber)
Definition: BlockAckReordering.cc:136
void releaseReceiveBuffer(ReceiveBuffer *receiveBuffer, const ReorderBuffer &reorderBuffer)
Definition: BlockAckReordering.cc:173
std::map< SequenceNumber, Fragments > ReorderBuffer
Definition: BlockAckReordering.h:36
std::map< std::pair< Tid, MACAddress >, ReceiveBuffer * > receiveBuffers
Definition: BlockAckReordering.h:39
ReorderBuffer collectCompletePrecedingMpdus(ReceiveBuffer *receiveBuffer, int startingSequenceNumber)
Definition: BlockAckReordering.cc:116
void inet::ieee80211::BlockAckReordering::processReceivedDelba ( Ieee80211Delba delba)

Referenced by inet::ieee80211::RecipientQoSMacDataService::managementFrameReceived().

212 {
213  Tid tid = delba->getTid();
214  MACAddress originatorAddr = delba->getTransmitterAddress();
215  auto id = std::make_pair(tid, originatorAddr);
216  auto it = receiveBuffers.find(id);
217  if (it != receiveBuffers.end()) {
218  delete it->second;
219  receiveBuffers.erase(it);
220  }
221  else
222  EV_DETAIL << "Receive buffer is not found" << endl;
223 }
int8_t Tid
Definition: Ieee80211Defs.h:28
std::map< std::pair< Tid, MACAddress >, ReceiveBuffer * > receiveBuffers
Definition: BlockAckReordering.h:39
BlockAckReordering::ReorderBuffer inet::ieee80211::BlockAckReordering::processReceivedQoSFrame ( RecipientBlockAckAgreement agreement,
Ieee80211DataFrame dataFrame 
)

Referenced by inet::ieee80211::RecipientQoSMacDataService::dataFrameReceived().

28 {
29  ReceiveBuffer *receiveBuffer = createReceiveBufferIfNecessary(agreement);
30  // The reception of QoS data frames using Normal Ack policy shall not be used by the
31  // recipient to reset the timer to detect Block Ack timeout (see 10.5.4).
32  // This allows the recipient to delete the Block Ack if the originator does not switch
33  // back to using Block Ack.
34  if (receiveBuffer->insertFrame(dataFrame)) {
35  if (dataFrame->getAckPolicy() == BLOCK_ACK)
36  agreement->blockAckPolicyFrameReceived(dataFrame);
37  auto earliestCompleteMsduOrAMsdu = getEarliestCompleteMsduOrAMsduIfExists(receiveBuffer);
38  if (earliestCompleteMsduOrAMsdu.size() > 0) {
39  int earliestSequenceNumber = earliestCompleteMsduOrAMsdu.at(0)->getSequenceNumber();
40  // If, after an MPDU is received, the receive buffer is full, the complete MSDU or A-MSDU with the earliest
41  // sequence number shall be passed up to the next MAC process.
42  if (receiveBuffer->isFull()) {
43  passedUp(receiveBuffer, earliestSequenceNumber);
44  return ReorderBuffer({std::make_pair(earliestSequenceNumber, Fragments(earliestCompleteMsduOrAMsdu))});
45  }
46  // If, after an MPDU is received, the receive buffer is not full, but the sequence number of the complete MSDU or
47  // A-MSDU in the buffer with the lowest sequence number is equal to the NextExpectedSequenceNumber for
48  // that Block Ack agreement, then the MPDU shall be passed up to the next MAC process.
49  else if (earliestSequenceNumber == receiveBuffer->getNextExpectedSequenceNumber()) {
50  passedUp(receiveBuffer, earliestSequenceNumber);
51  return ReorderBuffer({std::make_pair(earliestSequenceNumber, Fragments(earliestCompleteMsduOrAMsdu))});
52  }
53  }
54  }
55  else
56  delete dataFrame;
57  return ReorderBuffer({});
58 }
Definition: Ieee80211Frame_m.h:142
std::map< SequenceNumber, Fragments > ReorderBuffer
Definition: BlockAckReordering.h:36
std::vector< Ieee80211DataFrame * > getEarliestCompleteMsduOrAMsduIfExists(ReceiveBuffer *receiveBuffer)
Definition: BlockAckReordering.cc:234
ReceiveBuffer * createReceiveBufferIfNecessary(RecipientBlockAckAgreement *agreement)
Definition: BlockAckReordering.cc:194
std::vector< Ieee80211DataFrame * > Fragments
Definition: BlockAckReordering.h:35
void passedUp(ReceiveBuffer *receiveBuffer, int sequenceNumber)
Definition: BlockAckReordering.cc:225
void inet::ieee80211::BlockAckReordering::releaseReceiveBuffer ( ReceiveBuffer receiveBuffer,
const ReorderBuffer reorderBuffer 
)
protected

Referenced by processReceivedBlockAckReq().

174 {
175  for (auto it : reorderBuffer) {
176  int sequenceNumber = it.first;
177  passedUp(receiveBuffer, sequenceNumber);
178  }
179 }
void passedUp(ReceiveBuffer *receiveBuffer, int sequenceNumber)
Definition: BlockAckReordering.cc:225

Member Data Documentation

std::map<std::pair<Tid, MACAddress>, ReceiveBuffer *> inet::ieee80211::BlockAckReordering::receiveBuffers
protected

The documentation for this class was generated from the following files: