A Discrete-Event Network Simulator
API
hwmp-protocol-mac.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008,2009 IITP RAS
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Kirill Andreev <andreev@iitp.ru>
18  */
19 
20 #include "hwmp-protocol-mac.h"
21 
22 #include "dot11s-mac-header.h"
23 #include "hwmp-tag.h"
24 #include "ie-dot11s-perr.h"
25 #include "ie-dot11s-prep.h"
26 #include "ie-dot11s-preq.h"
27 #include "ie-dot11s-rann.h"
28 
29 #include "ns3/log.h"
30 #include "ns3/mesh-wifi-interface-mac.h"
31 #include "ns3/mgt-action-headers.h"
32 #include "ns3/nstime.h"
33 #include "ns3/packet.h"
34 #include "ns3/simulator.h"
35 #include "ns3/wifi-mac-header.h"
36 
37 namespace ns3
38 {
39 
40 NS_LOG_COMPONENT_DEFINE("HwmpProtocolMac");
41 
42 namespace dot11s
43 {
44 
46  : m_ifIndex(ifIndex),
47  m_protocol(protocol)
48 {
49  NS_LOG_FUNCTION(this << ifIndex << protocol);
50 }
51 
53 {
54 }
55 
56 void
58 {
59  NS_LOG_FUNCTION(this << parent);
60  m_parent = parent;
61 }
62 
63 bool
65 {
66  NS_LOG_FUNCTION(this << packet << header);
67  NS_ASSERT(header.IsData());
68 
69  MeshHeader meshHdr;
70  HwmpTag tag;
71  if (packet->PeekPacketTag(tag))
72  {
73  NS_FATAL_ERROR("HWMP tag is not supposed to be received by network");
74  }
75 
76  packet->RemoveHeader(meshHdr);
77  m_stats.rxData++;
78  m_stats.rxDataBytes += packet->GetSize();
79 
81  Mac48Address destination;
82  Mac48Address source;
83  switch (meshHdr.GetAddressExt())
84  {
85  case 0:
86  source = header.GetAddr4();
87  destination = header.GetAddr3();
88  break;
89  default:
90  NS_FATAL_ERROR("6-address scheme is not yet supported and 4-address extension is not "
91  "supposed to be used for data frames.");
92  }
93  tag.SetSeqno(meshHdr.GetMeshSeqno());
94  tag.SetTtl(meshHdr.GetMeshTtl());
95  packet->AddPacketTag(tag);
96 
97  if ((destination == Mac48Address::GetBroadcast()) &&
98  (m_protocol->DropDataFrame(meshHdr.GetMeshSeqno(), source)))
99  {
100  NS_LOG_DEBUG("Dropping frame; source " << source << " dest " << destination << " seqno "
101  << meshHdr.GetMeshSeqno());
102  return false;
103  }
104  return true;
105 }
106 
107 bool
109 {
110  NS_LOG_FUNCTION(this << packet << header);
111  m_stats.rxMgt++;
112  m_stats.rxMgtBytes += packet->GetSize();
113  WifiActionHeader actionHdr;
114  packet->RemoveHeader(actionHdr);
115  if (actionHdr.GetCategory() != WifiActionHeader::MESH)
116  {
117  return true;
118  }
120  // To determine header size here, we can rely on the knowledge that
121  // this is the last header to remove.
122  packet->RemoveHeader(elements, packet->GetSize());
123  std::vector<HwmpProtocol::FailedDestination> failedDestinations;
124  for (auto i = elements.Begin(); i != elements.End(); i++)
125  {
126  if ((*i)->ElementId() == IE_RANN)
127  {
128  NS_LOG_WARN("RANN is not supported!");
129  }
130  if ((*i)->ElementId() == IE_PREQ)
131  {
132  Ptr<IePreq> preq = DynamicCast<IePreq>(*i);
133  NS_ASSERT(preq);
134  m_stats.rxPreq++;
135  if (preq->GetOriginatorAddress() == m_protocol->GetAddress())
136  {
137  continue;
138  }
139  if (preq->GetTtl() == 0)
140  {
141  continue;
142  }
143  preq->DecrementTtl();
144  m_protocol->ReceivePreq(*preq,
145  header.GetAddr2(),
146  m_ifIndex,
147  header.GetAddr3(),
148  m_parent->GetLinkMetric(header.GetAddr2()));
149  }
150  if ((*i)->ElementId() == IE_PREP)
151  {
152  Ptr<IePrep> prep = DynamicCast<IePrep>(*i);
153  NS_ASSERT(prep);
154  m_stats.rxPrep++;
155  if (prep->GetTtl() == 0)
156  {
157  continue;
158  }
159  prep->DecrementTtl();
160  m_protocol->ReceivePrep(*prep,
161  header.GetAddr2(),
162  m_ifIndex,
163  header.GetAddr3(),
164  m_parent->GetLinkMetric(header.GetAddr2()));
165  }
166  if ((*i)->ElementId() == IE_PERR)
167  {
168  Ptr<IePerr> perr = DynamicCast<IePerr>(*i);
169  NS_ASSERT(perr);
170  m_stats.rxPerr++;
171  std::vector<HwmpProtocol::FailedDestination> destinations =
172  perr->GetAddressUnitVector();
173  for (auto i = destinations.begin(); i != destinations.end(); i++)
174  {
175  failedDestinations.push_back(*i);
176  }
177  }
178  }
179  if (!failedDestinations.empty())
180  {
181  m_protocol->ReceivePerr(failedDestinations,
182  header.GetAddr2(),
183  m_ifIndex,
184  header.GetAddr3());
185  }
186  NS_ASSERT(packet->GetSize() == 0);
187  return false;
188 }
189 
190 bool
192 {
193  NS_LOG_FUNCTION(this << packet << header);
194  if (header.IsData())
195  {
196  return ReceiveData(packet, header);
197  }
198  else
199  {
200  if (header.IsAction())
201  {
202  return ReceiveAction(packet, header);
203  }
204  else
205  {
206  return true; // don't care
207  }
208  }
209 }
210 
211 bool
213  WifiMacHeader& header,
214  Mac48Address from,
215  Mac48Address to)
216 {
217  NS_LOG_FUNCTION(this << packet << header << from << to);
218  if (!header.IsData())
219  {
220  return true;
221  }
222  HwmpTag tag;
223  bool tagExists = packet->RemovePacketTag(tag);
224  if (!tagExists)
225  {
226  NS_FATAL_ERROR("HWMP tag must exist at this point");
227  }
228  m_stats.txData++;
229  m_stats.txDataBytes += packet->GetSize();
230  MeshHeader meshHdr;
231  meshHdr.SetMeshSeqno(tag.GetSeqno());
232  meshHdr.SetMeshTtl(tag.GetTtl());
233  packet->AddHeader(meshHdr);
234  header.SetAddr1(tag.GetAddress());
235  header.SetQosMeshControlPresent();
236  return true;
237 }
238 
241 {
242  WifiActionHeader actionHdr;
246  return actionHdr;
247 }
248 
249 void
251 {
252  NS_LOG_FUNCTION(this);
253  std::vector<IePreq> preq_vector;
254  preq_vector.push_back(preq);
255  SendPreqVector(preq_vector);
256 }
257 
258 void
259 HwmpProtocolMac::SendPreqVector(std::vector<IePreq> preq)
260 {
261  NS_LOG_FUNCTION(this);
262  Ptr<Packet> packet = Create<Packet>();
264  for (auto i = preq.begin(); i != preq.end(); i++)
265  {
266  elements.AddInformationElement(Ptr<IePreq>(&(*i)));
267  }
268  packet->AddHeader(elements);
269  packet->AddHeader(GetWifiActionHeader());
270  // create 802.11 header:
271  WifiMacHeader hdr;
273  hdr.SetDsNotFrom();
274  hdr.SetDsNotTo();
275  hdr.SetAddr2(m_parent->GetAddress());
276  hdr.SetAddr3(m_protocol->GetAddress());
277  // Send Management frame
278  std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers(m_ifIndex);
279  for (auto i = receivers.begin(); i != receivers.end(); i++)
280  {
281  hdr.SetAddr1(*i);
282  m_stats.txPreq++;
283  m_stats.txMgt++;
284  m_stats.txMgtBytes += packet->GetSize();
285  m_parent->SendManagementFrame(packet, hdr);
286  }
287 }
288 
289 void
290 HwmpProtocolMac::RequestDestination(Mac48Address dst, uint32_t originator_seqno, uint32_t dst_seqno)
291 {
292  NS_LOG_FUNCTION(this << dst << originator_seqno << dst_seqno);
293  for (auto i = m_myPreq.begin(); i != m_myPreq.end(); i++)
294  {
295  if (i->IsFull())
296  {
297  continue;
298  }
299  NS_ASSERT(i->GetDestCount() > 0);
300  i->AddDestinationAddressElement(m_protocol->GetDoFlag(),
301  m_protocol->GetRfFlag(),
302  dst,
303  dst_seqno);
304  }
305  IePreq preq;
306  preq.SetHopcount(0);
307  preq.SetTTL(m_protocol->GetMaxTtl());
308  preq.SetPreqID(m_protocol->GetNextPreqId());
309  preq.SetOriginatorAddress(m_protocol->GetAddress());
310  preq.SetOriginatorSeqNumber(originator_seqno);
311  preq.SetLifetime(m_protocol->GetActivePathLifetime());
312  preq.AddDestinationAddressElement(m_protocol->GetDoFlag(),
313  m_protocol->GetRfFlag(),
314  dst,
315  dst_seqno);
316  m_myPreq.push_back(preq);
317  SendMyPreq();
318 }
319 
320 void
322 {
323  NS_LOG_FUNCTION(this);
324  if (m_preqTimer.IsRunning())
325  {
326  return;
327  }
328  if (m_myPreq.empty())
329  {
330  return;
331  }
332  // reschedule sending PREQ
334  m_preqTimer =
335  Simulator::Schedule(m_protocol->GetPreqMinInterval(), &HwmpProtocolMac::SendMyPreq, this);
337  m_myPreq.clear();
338 }
339 
340 void
342 {
343  NS_LOG_FUNCTION(this << receiver);
344  // Create packet
345  Ptr<Packet> packet = Create<Packet>();
347  elements.AddInformationElement(Ptr<IePrep>(&prep));
348  packet->AddHeader(elements);
349  packet->AddHeader(GetWifiActionHeader());
350  // create 802.11 header:
351  WifiMacHeader hdr;
353  hdr.SetDsNotFrom();
354  hdr.SetDsNotTo();
355  hdr.SetAddr1(receiver);
356  hdr.SetAddr2(m_parent->GetAddress());
357  hdr.SetAddr3(m_protocol->GetAddress());
358  // Send Management frame
359  m_stats.txPrep++;
360  m_stats.txMgt++;
361  m_stats.txMgtBytes += packet->GetSize();
362  m_parent->SendManagementFrame(packet, hdr);
363 }
364 
365 void
366 HwmpProtocolMac::ForwardPerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
367  std::vector<Mac48Address> receivers)
368 {
369  NS_LOG_FUNCTION(this);
370  Ptr<Packet> packet = Create<Packet>();
371  Ptr<IePerr> perr = Create<IePerr>();
373  for (auto i = failedDestinations.begin(); i != failedDestinations.end(); i++)
374  {
375  if (!perr->IsFull())
376  {
377  perr->AddAddressUnit(*i);
378  }
379  else
380  {
381  elements.AddInformationElement(perr);
382  perr->ResetPerr();
383  }
384  }
385  if (perr->GetNumOfDest() > 0)
386  {
387  elements.AddInformationElement(perr);
388  }
389  packet->AddHeader(elements);
390  packet->AddHeader(GetWifiActionHeader());
391  // create 802.11 header:
392  WifiMacHeader hdr;
394  hdr.SetDsNotFrom();
395  hdr.SetDsNotTo();
396  hdr.SetAddr2(m_parent->GetAddress());
397  hdr.SetAddr3(m_protocol->GetAddress());
398  if (receivers.size() >= m_protocol->GetUnicastPerrThreshold())
399  {
400  receivers.clear();
401  receivers.push_back(Mac48Address::GetBroadcast());
402  }
403  // Send Management frame
404  for (auto i = receivers.begin(); i != receivers.end(); i++)
405  {
406  //
407  // 64-bit Intel valgrind complains about hdr.SetAddr1 (*i). It likes this
408  // just fine.
409  //
410  Mac48Address address = *i;
411  hdr.SetAddr1(address);
412  m_stats.txPerr++;
413  m_stats.txMgt++;
414  m_stats.txMgtBytes += packet->GetSize();
415  m_parent->SendManagementFrame(packet, hdr);
416  }
417 }
418 
419 void
420 HwmpProtocolMac::InitiatePerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
421  std::vector<Mac48Address> receivers)
422 {
423  NS_LOG_FUNCTION(this);
424  // All duplicates in PERR are checked here, and there is no reason to
425  // check it at any other place
426  {
427  for (auto i = receivers.begin(); i != receivers.end(); i++)
428  {
429  bool should_add = true;
430  for (auto j = m_myPerr.receivers.begin(); j != m_myPerr.receivers.end(); j++)
431  {
432  if ((*i) == (*j))
433  {
434  should_add = false;
435  }
436  }
437  if (should_add)
438  {
439  m_myPerr.receivers.push_back(*i);
440  NS_LOG_DEBUG("Initiate PERR: Adding receiver: " << (*i));
441  }
442  }
443  }
444  {
445  for (auto i = failedDestinations.begin(); i != failedDestinations.end(); i++)
446  {
447  bool should_add = true;
448  for (auto j = m_myPerr.destinations.begin(); j != m_myPerr.destinations.end(); j++)
449  {
450  if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
451  {
452  should_add = false;
453  }
454  }
455  if (should_add)
456  {
457  m_myPerr.destinations.push_back(*i);
458  NS_LOG_DEBUG("Initiate PERR: Adding failed destination: " << (*i).destination);
459  }
460  }
461  }
462  SendMyPerr();
463 }
464 
465 void
467 {
468  NS_LOG_FUNCTION(this);
469  if (m_perrTimer.IsRunning())
470  {
471  return;
472  }
473  m_perrTimer =
474  Simulator::Schedule(m_protocol->GetPerrMinInterval(), &HwmpProtocolMac::SendMyPerr, this);
476  m_myPerr.destinations.clear();
477  m_myPerr.receivers.clear();
478 }
479 
480 uint32_t
482 {
483  return m_parent->GetLinkMetric(peerAddress);
484 }
485 
486 uint16_t
488 {
489  return m_parent->GetFrequencyChannel();
490 }
491 
493  : txPreq(0),
494  rxPreq(0),
495  txPrep(0),
496  rxPrep(0),
497  txPerr(0),
498  rxPerr(0),
499  txMgt(0),
500  txMgtBytes(0),
501  rxMgt(0),
502  rxMgtBytes(0),
503  txData(0),
504  txDataBytes(0),
505  rxData(0),
506  rxDataBytes(0)
507 {
508 }
509 
510 void
511 HwmpProtocolMac::Statistics::Print(std::ostream& os) const
512 {
513  os << "<Statistics "
514  "txPreq= \""
515  << txPreq << "\"" << std::endl
516  << "txPrep=\"" << txPrep << "\"" << std::endl
517  << "txPerr=\"" << txPerr << "\"" << std::endl
518  << "rxPreq=\"" << rxPreq << "\"" << std::endl
519  << "rxPrep=\"" << rxPrep << "\"" << std::endl
520  << "rxPerr=\"" << rxPerr << "\"" << std::endl
521  << "txMgt=\"" << txMgt << "\"" << std::endl
522  << "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl
523  << "rxMgt=\"" << rxMgt << "\"" << std::endl
524  << "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl
525  << "txData=\"" << txData << "\"" << std::endl
526  << "txDataBytes=\"" << txDataBytes << "\"" << std::endl
527  << "rxData=\"" << rxData << "\"" << std::endl
528  << "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
529 }
530 
531 void
532 HwmpProtocolMac::Report(std::ostream& os) const
533 {
534  os << "<HwmpProtocolMac" << std::endl
535  << "address =\"" << m_parent->GetAddress() << "\">" << std::endl;
536  m_stats.Print(os);
537  os << "</HwmpProtocolMac>" << std::endl;
538 }
539 
540 void
542 {
543  NS_LOG_FUNCTION(this);
544  m_stats = Statistics();
545 }
546 
547 int64_t
549 {
550  return m_protocol->AssignStreams(stream);
551 }
552 
553 } // namespace dot11s
554 } // namespace ns3
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address GetBroadcast()
Iterator End()
Returns End of the vector.
bool AddInformationElement(Ptr< WifiInformationElement > element)
add an IE, if maxSize has exceeded, returns false
Iterator Begin()
Returns Begin of the vector.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:967
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:960
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:983
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
CategoryValue GetCategory() const
Return the category value.
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr3() const
Return the address in the Address 3 field.
Mac48Address GetAddr4() const
Return the address in the Address 4 field.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
bool IsAction() const
Return true if the header is an Action header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool IsData() const
Return true if the Type is DATA.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetQosMeshControlPresent()
Set the Mesh Control Present flag for the QoS header.
static WifiActionHeader GetWifiActionHeader()
void SendMyPreq()
Sends one PREQ when PreqMinInterval after last PREQ expires (if any PREQ exists in rhe queue)
void SendPreq(IePreq preq)
Send PREQ function.
HwmpProtocolMac(uint32_t ifIndex, Ptr< HwmpProtocol > protocol)
Constructor.
void SetParent(Ptr< MeshWifiInterfaceMac > parent) override
Each plugin must be installed on an interface to work.
void SendPreqVector(std::vector< IePreq > preq)
Send PREQ function for vector of PREQ.
void SendPrep(IePrep prep, Mac48Address receiver)
Send PREP function.
void SendMyPerr()
Send PERR function.
uint16_t GetChannelId() const
Get the channel ID.
bool Receive(Ptr< Packet > packet, const WifiMacHeader &header) override
Process received frame.
void ForwardPerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
Forward a path error.
Ptr< HwmpProtocol > m_protocol
protocol
bool ReceiveData(Ptr< Packet > packet, const WifiMacHeader &header)
Receive data frame.
Statistics m_stats
statistics
EventId m_preqTimer
Timer for PREQs.
void ResetStats()
Reset statistics.
uint32_t GetLinkMetric(Mac48Address peerAddress) const
bool ReceiveAction(Ptr< Packet > packet, const WifiMacHeader &header)
Receive action management frame.
void InitiatePerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
initiate my own path error
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
std::vector< IePreq > m_myPreq
container of PREQs
void Report(std::ostream &os) const
Report statistics.
bool UpdateOutcomingFrame(Ptr< Packet > packet, WifiMacHeader &header, Mac48Address from, Mac48Address to) override
Update frame before it will be forwarded down.
Ptr< MeshWifiInterfaceMac > m_parent
parent
void RequestDestination(Mac48Address dest, uint32_t originator_seqno, uint32_t dst_seqno)
Request a destination.
Hwmp tag implements interaction between HWMP protocol and MeshWifiMac.
Definition: hwmp-tag.h:51
void SetTtl(uint8_t ttl)
Set the TTL value.
Definition: hwmp-tag.cc:55
uint32_t GetSeqno() const
Get the sequence number.
Definition: hwmp-tag.cc:85
void SetSeqno(uint32_t seqno)
Set sequence number.
Definition: hwmp-tag.cc:79
uint8_t GetTtl() const
Get the TTL value.
Definition: hwmp-tag.cc:61
Mac48Address GetAddress()
Get address from tag.
Definition: hwmp-tag.cc:49
See 7.3.2.97 of 802.11s draft 2.07.
See 7.3.2.96 of 802.11s draft 2.07.
void SetHopcount(uint8_t hopcount)
Set number of hops from originator to mesh STA transmitting this element.
void SetOriginatorSeqNumber(uint32_t originator_seq_number)
Set originator sequence number.
void SetTTL(uint8_t ttl)
Set remaining number of hops allowed for this element.
void SetOriginatorAddress(Mac48Address originator_address)
Set originator address value.
void SetPreqID(uint32_t id)
Set path discovery id field.
void AddDestinationAddressElement(bool doFlag, bool rfFlag, Mac48Address dest_address, uint32_t dest_seq_number)
Add a destination address unit: flags, destination and sequence number.
void SetLifetime(uint32_t lifetime)
Set lifetime in TUs for the forwarding information to be considered valid.
Mesh Control field, see Section 8.2.4.7.3 IEEE 802.11-2012.
void SetMeshSeqno(uint32_t seqno)
Set four-byte mesh sequence number.
uint32_t GetMeshSeqno() const
Get the four-byte mesh sequence number.
void SetMeshTtl(uint8_t TTL)
Set mesh TTL subfield corresponding to the remaining number of hops the MSDU/MMPDU is forwarded.
uint8_t GetAddressExt() const
Get Address Extension Mode.
uint8_t GetMeshTtl() const
Get mesh TTL function subfield value.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
@ WIFI_MAC_MGT_ACTION
std::vector< HwmpProtocol::FailedDestination > destinations
destinations
std::vector< Mac48Address > receivers
receivers
uint32_t txMgtBytes
transmit management bytes
void Print(std::ostream &os) const
Print function.
uint32_t txDataBytes
transmit data bytes
uint32_t rxMgtBytes
receive management bytes
typedef for union of different ActionValues
#define IE_PREQ
#define IE_RANN
#define IE_PREP
#define IE_PERR