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

#include <QosAckHandler.h>

Inheritance diagram for inet::ieee80211::QosAckHandler:
inet::ieee80211::IAckHandler

Public Types

enum  Status {
  Status::FRAME_NOT_YET_TRANSMITTED, Status::NO_ACK_REQUIRED, Status::BLOCK_ACK_NOT_YET_REQUESTED, Status::WAITING_FOR_NORMAL_ACK,
  Status::WAITING_FOR_BLOCK_ACK, Status::NORMAL_ACK_NOT_ARRIVED, Status::NORMAL_ACK_ARRIVED, Status::BLOCK_ACK_ARRIVED_UNACKED,
  Status::BLOCK_ACK_ARRIVED_ACKED, Status::BLOCK_ACK_NOT_ARRIVED
}
 

Public Member Functions

virtual ~QosAckHandler ()
 
virtual void processReceivedAck (const Ptr< const Ieee80211AckFrame > &ack, const Ptr< const Ieee80211DataOrMgmtHeader > &ackedHeader)
 
virtual std::set< std::pair< MacAddress, std::pair< Tid, SequenceControlField > > > processReceivedBlockAck (const Ptr< const Ieee80211BlockAck > &blockAck)
 
virtual void processFailedBlockAckReq (const Ptr< const Ieee80211BlockAckReq > &blockAckReq)
 
virtual void frameGotInProgress (const Ptr< const Ieee80211DataOrMgmtHeader > &dataOrMgmtHeader) override
 
virtual void processTransmittedDataOrMgmtFrame (const Ptr< const Ieee80211DataOrMgmtHeader > &header)
 
virtual void processTransmittedBlockAckReq (const Ptr< const Ieee80211BlockAckReq > &blockAckReq)
 
virtual void processFailedFrame (const Ptr< const Ieee80211DataOrMgmtHeader > &dataOrMgmtHeader)
 
virtual void dropFrame (const Ptr< const Ieee80211DataOrMgmtHeader > &dataOrMgmtHeader)
 
virtual void dropFrames (std::set< std::pair< MacAddress, std::pair< Tid, SequenceControlField >>> seqAndFragNums)
 
virtual Status getQoSDataAckStatus (const Ptr< const Ieee80211DataHeader > &header)
 
virtual Status getMgmtOrNonQoSAckStatus (const Ptr< const Ieee80211DataOrMgmtHeader > &header)
 
virtual bool isEligibleToTransmit (const Ptr< const Ieee80211DataOrMgmtHeader > &header) override
 
virtual bool isOutstandingFrame (const Ptr< const Ieee80211DataOrMgmtHeader > &header) override
 
- Public Member Functions inherited from inet::ieee80211::IAckHandler
virtual ~IAckHandler ()
 

Static Public Member Functions

static std::string getStatusString (Status status)
 

Protected Types

typedef std::pair< MacAddress, std::pair< Tid, SequenceControlField > > QoSKey
 
typedef std::pair< MacAddress, SequenceControlFieldKey
 

Protected Member Functions

virtual void initialize (int stage) override
 
virtual Status getQoSDataAckStatus (const QoSKey &id)
 
virtual Status getMgmtOrNonQoSAckStatus (const Key &id)
 
void printAckStatuses ()
 

Protected Attributes

std::map< QoSKey, StatusackStatuses
 
std::map< Key, StatusmgmtAckStatuses
 

Member Typedef Documentation

◆ Key

◆ QoSKey

typedef std::pair<MacAddress, std::pair<Tid, SequenceControlField> > inet::ieee80211::QosAckHandler::QoSKey
protected

Member Enumeration Documentation

◆ Status

Enumerator
FRAME_NOT_YET_TRANSMITTED 
NO_ACK_REQUIRED 
BLOCK_ACK_NOT_YET_REQUESTED 
WAITING_FOR_NORMAL_ACK 
WAITING_FOR_BLOCK_ACK 
NORMAL_ACK_NOT_ARRIVED 
NORMAL_ACK_ARRIVED 
BLOCK_ACK_ARRIVED_UNACKED 
BLOCK_ACK_ARRIVED_ACKED 
BLOCK_ACK_NOT_ARRIVED 
26  {
27  FRAME_NOT_YET_TRANSMITTED,
28  NO_ACK_REQUIRED,
29  BLOCK_ACK_NOT_YET_REQUESTED,
30  WAITING_FOR_NORMAL_ACK,
31  WAITING_FOR_BLOCK_ACK,
32  NORMAL_ACK_NOT_ARRIVED,
33  NORMAL_ACK_ARRIVED,
34  BLOCK_ACK_ARRIVED_UNACKED,
35  BLOCK_ACK_ARRIVED_ACKED,
36  BLOCK_ACK_NOT_ARRIVED
37  };

Constructor & Destructor Documentation

◆ ~QosAckHandler()

virtual inet::ieee80211::QosAckHandler::~QosAckHandler ( )
inlinevirtual
54 {}

Member Function Documentation

◆ dropFrame()

void inet::ieee80211::QosAckHandler::dropFrame ( const Ptr< const Ieee80211DataOrMgmtHeader > &  dataOrMgmtHeader)
virtual
94 {
95  if (dataOrMgmtHeader->getType() == ST_DATA_WITH_QOS) {
96  auto dataHeader = dynamicPtrCast<const Ieee80211DataHeader>(dataOrMgmtHeader);
97  auto id = std::make_pair(dataHeader->getReceiverAddress(), std::make_pair(dataHeader->getTid(), SequenceControlField(dataHeader->getSequenceNumber().get(), dataHeader->getFragmentNumber())));
98  ackStatuses.erase(id);
99  }
100  else {
101  auto id = std::make_pair(dataOrMgmtHeader->getReceiverAddress(), SequenceControlField(dataOrMgmtHeader->getSequenceNumber().get(), dataOrMgmtHeader->getFragmentNumber()));
102  mgmtAckStatuses.erase(id);
103  }
104 }

◆ dropFrames()

void inet::ieee80211::QosAckHandler::dropFrames ( std::set< std::pair< MacAddress, std::pair< Tid, SequenceControlField >>>  seqAndFragNums)
virtual
107 {
108  for (auto it : seqAndFragNums)
109  ackStatuses.erase(it);
110 }

◆ frameGotInProgress()

void inet::ieee80211::QosAckHandler::frameGotInProgress ( const Ptr< const Ieee80211DataOrMgmtHeader > &  dataOrMgmtHeader)
overridevirtual

Implements inet::ieee80211::IAckHandler.

251 {
252  if (dataOrMgmtHeader->getType() == ST_DATA_WITH_QOS) {
253  auto dataHeader = dynamicPtrCast<const Ieee80211DataHeader>(dataOrMgmtHeader);
254  auto id = std::make_pair(dataHeader->getReceiverAddress(), std::make_pair(dataHeader->getTid(), SequenceControlField(dataHeader->getSequenceNumber().get(), dataHeader->getFragmentNumber())));
255  auto status = getQoSDataAckStatus(id);
258  }
259  else {
260  auto id = std::make_pair(dataOrMgmtHeader->getReceiverAddress(), SequenceControlField(dataOrMgmtHeader->getSequenceNumber().get(), dataOrMgmtHeader->getFragmentNumber()));
261  auto status = getMgmtOrNonQoSAckStatus(id);
262  ASSERT(status != Status::WAITING_FOR_NORMAL_ACK);
264  }
265 }

◆ getMgmtOrNonQoSAckStatus() [1/2]

QosAckHandler::Status inet::ieee80211::QosAckHandler::getMgmtOrNonQoSAckStatus ( const Key id)
protectedvirtual

◆ getMgmtOrNonQoSAckStatus() [2/2]

QosAckHandler::Status inet::ieee80211::QosAckHandler::getMgmtOrNonQoSAckStatus ( const Ptr< const Ieee80211DataOrMgmtHeader > &  header)
virtual
43 {
44  auto id = std::make_pair(header->getReceiverAddress(), SequenceControlField(header->getSequenceNumber().get(), header->getFragmentNumber()));
45  return getMgmtOrNonQoSAckStatus(id);
46 }

◆ getQoSDataAckStatus() [1/2]

QosAckHandler::Status inet::ieee80211::QosAckHandler::getQoSDataAckStatus ( const Ptr< const Ieee80211DataHeader > &  header)
virtual
49 {
50  auto id = std::make_pair(header->getReceiverAddress(), std::make_pair(header->getTid(), SequenceControlField(header->getSequenceNumber().get(), header->getFragmentNumber())));
51  return getQoSDataAckStatus(id);
52 }

◆ getQoSDataAckStatus() [2/2]

QosAckHandler::Status inet::ieee80211::QosAckHandler::getQoSDataAckStatus ( const QoSKey id)
protectedvirtual

◆ getStatusString()

std::string inet::ieee80211::QosAckHandler::getStatusString ( Status  status)
static
268 {
269  switch (status) {
270  case Status::FRAME_NOT_YET_TRANSMITTED: return "FRAME_NOT_YET_TRANSMITTED";
271  case Status::NO_ACK_REQUIRED: return "NO_ACK_REQUIRED";
272  case Status::BLOCK_ACK_NOT_YET_REQUESTED: return "BLOCK_ACK_NOT_YET_REQUESTED";
273  case Status::WAITING_FOR_NORMAL_ACK: return "WAITING_FOR_NORMAL_ACK";
274  case Status::NORMAL_ACK_NOT_ARRIVED: return "NORMAL_ACK_NOT_ARRIVED";
275  case Status::BLOCK_ACK_ARRIVED_UNACKED: return "BLOCK_ACK_ARRIVED_UNACKED";
276  case Status::BLOCK_ACK_ARRIVED_ACKED: return "BLOCK_ACK_ARRIVED_ACKED";
277  case Status::WAITING_FOR_BLOCK_ACK: return "WAITING_FOR_BLOCK_ACK";
278  case Status::NORMAL_ACK_ARRIVED: return "NORMAL_ACK_ARRIVED";
279  default: throw cRuntimeError("Unknown status");
280  }
281 }

Referenced by inet::ieee80211::operator<<(), and printAckStatuses().

◆ initialize()

void inet::ieee80211::QosAckHandler::initialize ( int  stage)
overrideprotectedvirtual
23 {
24  if (stage == INITSTAGE_LOCAL) {
25  WATCH_MAP(ackStatuses);
26  WATCH_MAP(mgmtAckStatuses);
27  }
28 }

◆ isEligibleToTransmit()

bool inet::ieee80211::QosAckHandler::isEligibleToTransmit ( const Ptr< const Ieee80211DataOrMgmtHeader > &  header)
overridevirtual

Implements inet::ieee80211::IAckHandler.

224 {
225  QosAckHandler::Status status;
226  if (header->getType() == ST_DATA_WITH_QOS) {
227  auto dataHeader = dynamicPtrCast<const Ieee80211DataHeader>(header);
228  status = getQoSDataAckStatus(dataHeader);
229  }
230  else
231  status = getMgmtOrNonQoSAckStatus(header);
232  return status == QosAckHandler::Status::NO_ACK_REQUIRED ||
237 }

◆ isOutstandingFrame()

bool inet::ieee80211::QosAckHandler::isOutstandingFrame ( const Ptr< const Ieee80211DataOrMgmtHeader > &  header)
overridevirtual

Implements inet::ieee80211::IAckHandler.

240 {
241  if (header->getType() == ST_DATA_WITH_QOS) {
242  auto dataHeader = dynamicPtrCast<const Ieee80211DataHeader>(header);
243  auto status = getQoSDataAckStatus(dataHeader);
245  }
246  else
247  return false;
248 }

◆ printAckStatuses()

void inet::ieee80211::QosAckHandler::printAckStatuses ( )
protected
284 {
285  for (auto ackStatus : ackStatuses) {
286  std::cout << "Seq Num = " << ackStatus.first.second.second.getSequenceNumber() << " " << "Frag Num = " << (int)ackStatus.first.second.second.getFragmentNumber() << std::endl;
287  std::cout << "Status = " << getStatusString(ackStatus.second) << std::endl;
288  }
289  std::cout << "=========================================" << std::endl;
290 }

◆ processFailedBlockAckReq()

void inet::ieee80211::QosAckHandler::processFailedBlockAckReq ( const Ptr< const Ieee80211BlockAckReq > &  blockAckReq)
virtual
154 {
155  if (auto basicBlockAckReq = dynamicPtrCast<const Ieee80211BasicBlockAckReq>(blockAckReq)) {
156  auto startingSeqNum = basicBlockAckReq->getStartingSequenceNumber();
157  for (int seqNum = 0; seqNum < 64; seqNum++) {
158  for (int fragNum = 0; fragNum < 16; fragNum++) { // TODO declare these const values
159  MacAddress receiverAddr = blockAckReq->getReceiverAddress();
160  auto id = std::make_pair(receiverAddr, std::make_pair(basicBlockAckReq->getTidInfo(), SequenceControlField((startingSeqNum + seqNum).get(), fragNum)));
161  auto status = getQoSDataAckStatus(id);
162  if (status == Status::WAITING_FOR_BLOCK_ACK)
164  }
165  }
166  }
167  else if (auto compressedBlockAckReq = dynamicPtrCast<const Ieee80211CompressedBlockAckReq>(blockAckReq)) {
168  auto startingSeqNum = compressedBlockAckReq->getStartingSequenceNumber();
169  for (int seqNum = 0; seqNum < 64; seqNum++) {
170  MacAddress receiverAddr = blockAckReq->getReceiverAddress();
171  auto id = std::make_pair(receiverAddr, std::make_pair(compressedBlockAckReq->getTidInfo(), SequenceControlField((startingSeqNum + seqNum).get(), 0)));
172  auto status = getQoSDataAckStatus(id);
173  if (status == Status::WAITING_FOR_BLOCK_ACK)
175  }
176  }
177  else
178  throw cRuntimeError("Unknown block ack request");
179 }

◆ processFailedFrame()

void inet::ieee80211::QosAckHandler::processFailedFrame ( const Ptr< const Ieee80211DataOrMgmtHeader > &  dataOrMgmtHeader)
virtual
74 {
75  if (dataOrMgmtHeader->getType() == ST_DATA_WITH_QOS) {
76  auto dataHeader = dynamicPtrCast<const Ieee80211DataHeader>(dataOrMgmtHeader);
77  auto id = std::make_pair(dataHeader->getReceiverAddress(), std::make_pair(dataHeader->getTid(), SequenceControlField(dataHeader->getSequenceNumber().get(), dataHeader->getFragmentNumber())));
78  auto status = getQoSDataAckStatus(id);
79  if (status == Status::WAITING_FOR_NORMAL_ACK)
81  else if (status == Status::WAITING_FOR_BLOCK_ACK)
83  else
84  throw cRuntimeError("Invalid ACK status");
85  }
86  else {
87  ASSERT(getMgmtOrNonQoSAckStatus(dataOrMgmtHeader) == Status::WAITING_FOR_NORMAL_ACK);
88  auto id = std::make_pair(dataOrMgmtHeader->getReceiverAddress(), SequenceControlField(dataOrMgmtHeader->getSequenceNumber().get(), dataOrMgmtHeader->getFragmentNumber()));
90  }
91 }

◆ processReceivedAck()

void inet::ieee80211::QosAckHandler::processReceivedAck ( const Ptr< const Ieee80211AckFrame > &  ack,
const Ptr< const Ieee80211DataOrMgmtHeader > &  ackedHeader 
)
virtual
55 {
56  if (ackedHeader->getType() == ST_DATA_WITH_QOS) {
57  auto dataHeader = dynamicPtrCast<const Ieee80211DataHeader>(ackedHeader);
58  auto id = std::make_pair(dataHeader->getReceiverAddress(), std::make_pair(dataHeader->getTid(), SequenceControlField(dataHeader->getSequenceNumber().get(), dataHeader->getFragmentNumber())));
59  auto status = getQoSDataAckStatus(id);
61  throw cRuntimeError("ackedFrame = %s is not yet transmitted", dataHeader->getName());
63  }
64  else {
65  auto id = std::make_pair(ackedHeader->getReceiverAddress(), SequenceControlField(ackedHeader->getSequenceNumber().get(), ackedHeader->getFragmentNumber()));
66  auto status = getMgmtOrNonQoSAckStatus(id);
68  throw cRuntimeError("ackedFrame = %s is not yet transmitted", ackedHeader->getName());
70  }
71 }

◆ processReceivedBlockAck()

std::set< std::pair< MacAddress, std::pair< Tid, SequenceControlField > > > inet::ieee80211::QosAckHandler::processReceivedBlockAck ( const Ptr< const Ieee80211BlockAck > &  blockAck)
virtual
113 {
114  MacAddress receiverAddr = blockAck->getTransmitterAddress();
115  std::set<QoSKey> ackedFrames;
116  // Table 8-16—BlockAckReq frame variant encoding
117  if (auto basicBlockAck = dynamicPtrCast<const Ieee80211BasicBlockAck>(blockAck)) {
118  auto startingSeqNum = basicBlockAck->getStartingSequenceNumber();
119  for (int seqNum = 0; seqNum < 64; seqNum++) {
120  BitVector bitmap = basicBlockAck->getBlockAckBitmap(seqNum);
121  for (int fragNum = 0; fragNum < 16; fragNum++) { // TODO declare these const values
122  auto id = std::make_pair(receiverAddr, std::make_pair(basicBlockAck->getTidInfo(), SequenceControlField((startingSeqNum + seqNum).get(), fragNum)));
123  auto status = getQoSDataAckStatus(id);
124  if (status == Status::WAITING_FOR_BLOCK_ACK) {
125  bool acked = bitmap.getBit(fragNum) == 1;
126  if (acked) ackedFrames.insert(id);
128  }
129  else ; // TODO erroneous BlockAck
130  }
131  }
132  }
133  else if (auto compressedBlockAck = dynamicPtrCast<const Ieee80211CompressedBlockAck>(blockAck)) {
134  auto startingSeqNum = compressedBlockAck->getStartingSequenceNumber();
135  BitVector bitmap = compressedBlockAck->getBlockAckBitmap();
136  for (int seqNum = 0; seqNum < 64; seqNum++) {
137  auto id = std::make_pair(receiverAddr, std::make_pair(compressedBlockAck->getTidInfo(), SequenceControlField((startingSeqNum + seqNum).get(), 0)));
138  auto status = getQoSDataAckStatus(id);
139  if (status == Status::WAITING_FOR_BLOCK_ACK) {
140  bool acked = bitmap.getBit(seqNum) == 1;
142  if (acked) ackedFrames.insert(id);
143  }
144  else ; // TODO erroneous BlockAck
145  }
146  }
147  else {
148  throw cRuntimeError("Multi-TID BlockReq is unimplemented");
149  }
150  return ackedFrames;
151 }

◆ processTransmittedBlockAckReq()

void inet::ieee80211::QosAckHandler::processTransmittedBlockAckReq ( const Ptr< const Ieee80211BlockAckReq > &  blockAckReq)
virtual
199 {
200  for (auto& ackStatus : ackStatuses) {
201  auto tid = ackStatus.first.second.first;
202  auto seqCtrlField = ackStatus.first.second.second;
203  auto& status = ackStatus.second;
204  if (auto basicBlockAckReq = dynamicPtrCast<const Ieee80211BasicBlockAckReq>(blockAckReq)) {
205  if (basicBlockAckReq->getTidInfo() == tid) {
206  auto startingSeqNum = basicBlockAckReq->getStartingSequenceNumber();
207  if (status == Status::BLOCK_ACK_NOT_YET_REQUESTED && SequenceNumberCyclic(seqCtrlField.getSequenceNumber()) >= startingSeqNum)
209  }
210  }
211  else if (auto compressedBlockAckReq = dynamicPtrCast<const Ieee80211CompressedBlockAckReq>(blockAckReq)) {
212  if (compressedBlockAckReq->getTidInfo() == tid) {
213  auto startingSeqNum = compressedBlockAckReq->getStartingSequenceNumber();
214  if (status == Status::BLOCK_ACK_NOT_YET_REQUESTED && SequenceNumberCyclic(seqCtrlField.getSequenceNumber()) >= startingSeqNum && seqCtrlField.getFragmentNumber() == 0) // TODO ASSERT(seqCtrlField.second == 0)?
216  }
217  }
218  else
219  throw cRuntimeError("Multi-TID BlockReq is unimplemented");
220  }
221 }

◆ processTransmittedDataOrMgmtFrame()

void inet::ieee80211::QosAckHandler::processTransmittedDataOrMgmtFrame ( const Ptr< const Ieee80211DataOrMgmtHeader > &  header)
virtual
182 {
183  if (header->getType() == ST_DATA_WITH_QOS) {
184  auto dataHeader = dynamicPtrCast<const Ieee80211DataHeader>(header);
185  auto id = std::make_pair(dataHeader->getReceiverAddress(), std::make_pair(dataHeader->getTid(), SequenceControlField(dataHeader->getSequenceNumber().get(), dataHeader->getFragmentNumber())));
186  switch (dataHeader->getAckPolicy()) {
189  case NO_ACK : ackStatuses[id] = Status::NO_ACK_REQUIRED; break;
190  case NO_EXPLICIT_ACK : throw cRuntimeError("Unimplemented"); /* TODO ACKED by default? */ break;
191  default: throw cRuntimeError("Unknown Ack Policy = %d", dataHeader->getAckPolicy());
192  }
193  }
194  else
195  mgmtAckStatuses[std::make_pair(header->getReceiverAddress(), SequenceControlField(header->getSequenceNumber().get(), header->getFragmentNumber()))] = Status::WAITING_FOR_NORMAL_ACK;
196 }

Member Data Documentation

◆ ackStatuses

◆ mgmtAckStatuses

std::map<Key, Status> inet::ieee80211::QosAckHandler::mgmtAckStatuses
protected

The documentation for this class was generated from the following files:
inet::ieee80211::QosAckHandler::Status
Status
Definition: QosAckHandler.h:26
inet::ieee80211::QosAckHandler::Status::FRAME_NOT_YET_TRANSMITTED
@ FRAME_NOT_YET_TRANSMITTED
inet::ieee80211::QosAckHandler::getStatusString
static std::string getStatusString(Status status)
Definition: QosAckHandler.cc:267
inet::ieee80211::QosAckHandler::Status::BLOCK_ACK_NOT_YET_REQUESTED
@ BLOCK_ACK_NOT_YET_REQUESTED
inet::ieee80211::QosAckHandler::Status::WAITING_FOR_NORMAL_ACK
@ WAITING_FOR_NORMAL_ACK
inet::ieee80211::BLOCK_ACK
@ BLOCK_ACK
Definition: Ieee80211Frame_m.h:196
inet::ieee80211::QosAckHandler::Status::NORMAL_ACK_ARRIVED
@ NORMAL_ACK_ARRIVED
inet::ieee80211::QosAckHandler::Status::BLOCK_ACK_ARRIVED_ACKED
@ BLOCK_ACK_ARRIVED_ACKED
inet::ieee80211::QosAckHandler::Status::WAITING_FOR_BLOCK_ACK
@ WAITING_FOR_BLOCK_ACK
inet::ieee80211::QosAckHandler::Status::BLOCK_ACK_NOT_ARRIVED
@ BLOCK_ACK_NOT_ARRIVED
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::ieee80211::QosAckHandler::mgmtAckStatuses
std::map< Key, Status > mgmtAckStatuses
Definition: QosAckHandler.h:43
inet::ieee80211::ST_DATA_WITH_QOS
@ ST_DATA_WITH_QOS
Definition: Ieee80211Frame_m.h:169
inet::ieee80211::QosAckHandler::getQoSDataAckStatus
virtual Status getQoSDataAckStatus(const QoSKey &id)
Definition: QosAckHandler.cc:30
inet::ieee80211::NO_EXPLICIT_ACK
@ NO_EXPLICIT_ACK
Definition: Ieee80211Frame_m.h:195
inet::ieee80211::QosAckHandler::Status::NORMAL_ACK_NOT_ARRIVED
@ NORMAL_ACK_NOT_ARRIVED
inet::ieee80211::QosAckHandler::ackStatuses
std::map< QoSKey, Status > ackStatuses
Definition: QosAckHandler.h:42
inet::ieee80211::QosAckHandler::Status::BLOCK_ACK_ARRIVED_UNACKED
@ BLOCK_ACK_ARRIVED_UNACKED
inet::ieee80211::QosAckHandler::Status::NO_ACK_REQUIRED
@ NO_ACK_REQUIRED
inet::ieee80211::NO_ACK
@ NO_ACK
Definition: Ieee80211Frame_m.h:194
inet::ieee80211::QosAckHandler::getMgmtOrNonQoSAckStatus
virtual Status getMgmtOrNonQoSAckStatus(const Key &id)
Definition: QosAckHandler.cc:36
inet::ieee80211::NORMAL_ACK
@ NORMAL_ACK
Definition: Ieee80211Frame_m.h:193