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/nstime.h"
32 #include "ns3/packet.h"
33 #include "ns3/simulator.h"
34 #include "ns3/wifi-mac-header.h"
35 
36 namespace ns3
37 {
38 
39 NS_LOG_COMPONENT_DEFINE("HwmpProtocolMac");
40 
41 namespace dot11s
42 {
43 
45  : m_ifIndex(ifIndex),
46  m_protocol(protocol)
47 {
48  NS_LOG_FUNCTION(this << ifIndex << protocol);
49 }
50 
52 {
53 }
54 
55 void
57 {
58  NS_LOG_FUNCTION(this << parent);
59  m_parent = parent;
60 }
61 
62 bool
64 {
65  NS_LOG_FUNCTION(this << packet << header);
66  NS_ASSERT(header.IsData());
67 
68  MeshHeader meshHdr;
69  HwmpTag tag;
70  if (packet->PeekPacketTag(tag))
71  {
72  NS_FATAL_ERROR("HWMP tag is not supposed to be received by network");
73  }
74 
75  packet->RemoveHeader(meshHdr);
76  m_stats.rxData++;
77  m_stats.rxDataBytes += packet->GetSize();
78 
80  Mac48Address destination;
81  Mac48Address source;
82  switch (meshHdr.GetAddressExt())
83  {
84  case 0:
85  source = header.GetAddr4();
86  destination = header.GetAddr3();
87  break;
88  default:
89  NS_FATAL_ERROR("6-address scheme is not yet supported and 4-address extension is not "
90  "supposed to be used for data frames.");
91  }
92  tag.SetSeqno(meshHdr.GetMeshSeqno());
93  tag.SetTtl(meshHdr.GetMeshTtl());
94  packet->AddPacketTag(tag);
95 
96  if ((destination == Mac48Address::GetBroadcast()) &&
97  (m_protocol->DropDataFrame(meshHdr.GetMeshSeqno(), source)))
98  {
99  NS_LOG_DEBUG("Dropping frame; source " << source << " dest " << destination << " seqno "
100  << meshHdr.GetMeshSeqno());
101  return false;
102  }
103  return true;
104 }
105 
106 bool
108 {
109  NS_LOG_FUNCTION(this << packet << header);
110  m_stats.rxMgt++;
111  m_stats.rxMgtBytes += packet->GetSize();
112  WifiActionHeader actionHdr;
113  packet->RemoveHeader(actionHdr);
114  if (actionHdr.GetCategory() != WifiActionHeader::MESH)
115  {
116  return true;
117  }
119  // To determine header size here, we can rely on the knowledge that
120  // this is the last header to remove.
121  packet->RemoveHeader(elements, packet->GetSize());
122  std::vector<HwmpProtocol::FailedDestination> failedDestinations;
123  for (MeshInformationElementVector::Iterator i = elements.Begin(); i != elements.End(); i++)
124  {
125  if ((*i)->ElementId() == IE_RANN)
126  {
127  NS_LOG_WARN("RANN is not supported!");
128  }
129  if ((*i)->ElementId() == IE_PREQ)
130  {
131  Ptr<IePreq> preq = DynamicCast<IePreq>(*i);
132  NS_ASSERT(preq);
133  m_stats.rxPreq++;
134  if (preq->GetOriginatorAddress() == m_protocol->GetAddress())
135  {
136  continue;
137  }
138  if (preq->GetTtl() == 0)
139  {
140  continue;
141  }
142  preq->DecrementTtl();
143  m_protocol->ReceivePreq(*preq,
144  header.GetAddr2(),
145  m_ifIndex,
146  header.GetAddr3(),
147  m_parent->GetLinkMetric(header.GetAddr2()));
148  }
149  if ((*i)->ElementId() == IE_PREP)
150  {
151  Ptr<IePrep> prep = DynamicCast<IePrep>(*i);
152  NS_ASSERT(prep);
153  m_stats.rxPrep++;
154  if (prep->GetTtl() == 0)
155  {
156  continue;
157  }
158  prep->DecrementTtl();
159  m_protocol->ReceivePrep(*prep,
160  header.GetAddr2(),
161  m_ifIndex,
162  header.GetAddr3(),
163  m_parent->GetLinkMetric(header.GetAddr2()));
164  }
165  if ((*i)->ElementId() == IE_PERR)
166  {
167  Ptr<IePerr> perr = DynamicCast<IePerr>(*i);
168  NS_ASSERT(perr);
169  m_stats.rxPerr++;
170  std::vector<HwmpProtocol::FailedDestination> destinations =
171  perr->GetAddressUnitVector();
172  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i =
173  destinations.begin();
174  i != destinations.end();
175  i++)
176  {
177  failedDestinations.push_back(*i);
178  }
179  }
180  }
181  if (!failedDestinations.empty())
182  {
183  m_protocol->ReceivePerr(failedDestinations,
184  header.GetAddr2(),
185  m_ifIndex,
186  header.GetAddr3());
187  }
188  NS_ASSERT(packet->GetSize() == 0);
189  return false;
190 }
191 
192 bool
194 {
195  NS_LOG_FUNCTION(this << packet << header);
196  if (header.IsData())
197  {
198  return ReceiveData(packet, header);
199  }
200  else
201  {
202  if (header.IsAction())
203  {
204  return ReceiveAction(packet, header);
205  }
206  else
207  {
208  return true; // don't care
209  }
210  }
211 }
212 
213 bool
215  WifiMacHeader& header,
216  Mac48Address from,
217  Mac48Address to)
218 {
219  NS_LOG_FUNCTION(this << packet << header << from << to);
220  if (!header.IsData())
221  {
222  return true;
223  }
224  HwmpTag tag;
225  bool tagExists = packet->RemovePacketTag(tag);
226  if (!tagExists)
227  {
228  NS_FATAL_ERROR("HWMP tag must exist at this point");
229  }
230  m_stats.txData++;
231  m_stats.txDataBytes += packet->GetSize();
232  MeshHeader meshHdr;
233  meshHdr.SetMeshSeqno(tag.GetSeqno());
234  meshHdr.SetMeshTtl(tag.GetTtl());
235  packet->AddHeader(meshHdr);
236  header.SetAddr1(tag.GetAddress());
237  header.SetQosMeshControlPresent();
238  return true;
239 }
240 
243 {
244  WifiActionHeader actionHdr;
248  return actionHdr;
249 }
250 
251 void
253 {
254  NS_LOG_FUNCTION(this);
255  std::vector<IePreq> preq_vector;
256  preq_vector.push_back(preq);
257  SendPreqVector(preq_vector);
258 }
259 
260 void
261 HwmpProtocolMac::SendPreqVector(std::vector<IePreq> preq)
262 {
263  NS_LOG_FUNCTION(this);
264  Ptr<Packet> packet = Create<Packet>();
266  for (std::vector<IePreq>::iterator i = preq.begin(); i != preq.end(); i++)
267  {
268  elements.AddInformationElement(Ptr<IePreq>(&(*i)));
269  }
270  packet->AddHeader(elements);
271  packet->AddHeader(GetWifiActionHeader());
272  // create 802.11 header:
273  WifiMacHeader hdr;
275  hdr.SetDsNotFrom();
276  hdr.SetDsNotTo();
277  hdr.SetAddr2(m_parent->GetAddress());
278  hdr.SetAddr3(m_protocol->GetAddress());
279  // Send Management frame
280  std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers(m_ifIndex);
281  for (std::vector<Mac48Address>::const_iterator i = receivers.begin(); i != receivers.end(); i++)
282  {
283  hdr.SetAddr1(*i);
284  m_stats.txPreq++;
285  m_stats.txMgt++;
286  m_stats.txMgtBytes += packet->GetSize();
287  m_parent->SendManagementFrame(packet, hdr);
288  }
289 }
290 
291 void
292 HwmpProtocolMac::RequestDestination(Mac48Address dst, uint32_t originator_seqno, uint32_t dst_seqno)
293 {
294  NS_LOG_FUNCTION(this << dst << originator_seqno << dst_seqno);
295  for (std::vector<IePreq>::iterator i = m_myPreq.begin(); i != m_myPreq.end(); i++)
296  {
297  if (i->IsFull())
298  {
299  continue;
300  }
301  NS_ASSERT(i->GetDestCount() > 0);
302  i->AddDestinationAddressElement(m_protocol->GetDoFlag(),
303  m_protocol->GetRfFlag(),
304  dst,
305  dst_seqno);
306  }
307  IePreq preq;
308  preq.SetHopcount(0);
309  preq.SetTTL(m_protocol->GetMaxTtl());
310  preq.SetPreqID(m_protocol->GetNextPreqId());
311  preq.SetOriginatorAddress(m_protocol->GetAddress());
312  preq.SetOriginatorSeqNumber(originator_seqno);
313  preq.SetLifetime(m_protocol->GetActivePathLifetime());
314  preq.AddDestinationAddressElement(m_protocol->GetDoFlag(),
315  m_protocol->GetRfFlag(),
316  dst,
317  dst_seqno);
318  m_myPreq.push_back(preq);
319  SendMyPreq();
320 }
321 
322 void
324 {
325  NS_LOG_FUNCTION(this);
326  if (m_preqTimer.IsRunning())
327  {
328  return;
329  }
330  if (m_myPreq.empty())
331  {
332  return;
333  }
334  // reschedule sending PREQ
336  m_preqTimer =
337  Simulator::Schedule(m_protocol->GetPreqMinInterval(), &HwmpProtocolMac::SendMyPreq, this);
339  m_myPreq.clear();
340 }
341 
342 void
344 {
345  NS_LOG_FUNCTION(this << receiver);
346  // Create packet
347  Ptr<Packet> packet = Create<Packet>();
349  elements.AddInformationElement(Ptr<IePrep>(&prep));
350  packet->AddHeader(elements);
351  packet->AddHeader(GetWifiActionHeader());
352  // create 802.11 header:
353  WifiMacHeader hdr;
355  hdr.SetDsNotFrom();
356  hdr.SetDsNotTo();
357  hdr.SetAddr1(receiver);
358  hdr.SetAddr2(m_parent->GetAddress());
359  hdr.SetAddr3(m_protocol->GetAddress());
360  // Send Management frame
361  m_stats.txPrep++;
362  m_stats.txMgt++;
363  m_stats.txMgtBytes += packet->GetSize();
364  m_parent->SendManagementFrame(packet, hdr);
365 }
366 
367 void
368 HwmpProtocolMac::ForwardPerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
369  std::vector<Mac48Address> receivers)
370 {
371  NS_LOG_FUNCTION(this);
372  Ptr<Packet> packet = Create<Packet>();
373  Ptr<IePerr> perr = Create<IePerr>();
375  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i =
376  failedDestinations.begin();
377  i != failedDestinations.end();
378  i++)
379  {
380  if (!perr->IsFull())
381  {
382  perr->AddAddressUnit(*i);
383  }
384  else
385  {
386  elements.AddInformationElement(perr);
387  perr->ResetPerr();
388  }
389  }
390  if (perr->GetNumOfDest() > 0)
391  {
392  elements.AddInformationElement(perr);
393  }
394  packet->AddHeader(elements);
395  packet->AddHeader(GetWifiActionHeader());
396  // create 802.11 header:
397  WifiMacHeader hdr;
399  hdr.SetDsNotFrom();
400  hdr.SetDsNotTo();
401  hdr.SetAddr2(m_parent->GetAddress());
402  hdr.SetAddr3(m_protocol->GetAddress());
403  if (receivers.size() >= m_protocol->GetUnicastPerrThreshold())
404  {
405  receivers.clear();
406  receivers.push_back(Mac48Address::GetBroadcast());
407  }
408  // Send Management frame
409  for (std::vector<Mac48Address>::const_iterator i = receivers.begin(); i != receivers.end(); i++)
410  {
411  //
412  // 64-bit Intel valgrind complains about hdr.SetAddr1 (*i). It likes this
413  // just fine.
414  //
415  Mac48Address address = *i;
416  hdr.SetAddr1(address);
417  m_stats.txPerr++;
418  m_stats.txMgt++;
419  m_stats.txMgtBytes += packet->GetSize();
420  m_parent->SendManagementFrame(packet, hdr);
421  }
422 }
423 
424 void
425 HwmpProtocolMac::InitiatePerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
426  std::vector<Mac48Address> receivers)
427 {
428  NS_LOG_FUNCTION(this);
429  // All duplicates in PERR are checked here, and there is no reason to
430  // check it at any other place
431  {
432  std::vector<Mac48Address>::const_iterator end = receivers.end();
433  for (std::vector<Mac48Address>::const_iterator i = receivers.begin(); i != end; i++)
434  {
435  bool should_add = true;
436  for (std::vector<Mac48Address>::const_iterator j = m_myPerr.receivers.begin();
437  j != m_myPerr.receivers.end();
438  j++)
439  {
440  if ((*i) == (*j))
441  {
442  should_add = false;
443  }
444  }
445  if (should_add)
446  {
447  m_myPerr.receivers.push_back(*i);
448  NS_LOG_DEBUG("Initiate PERR: Adding receiver: " << (*i));
449  }
450  }
451  }
452  {
453  std::vector<HwmpProtocol::FailedDestination>::const_iterator end = failedDestinations.end();
454  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i =
455  failedDestinations.begin();
456  i != end;
457  i++)
458  {
459  bool should_add = true;
460  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator j =
461  m_myPerr.destinations.begin();
462  j != m_myPerr.destinations.end();
463  j++)
464  {
465  if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
466  {
467  should_add = false;
468  }
469  }
470  if (should_add)
471  {
472  m_myPerr.destinations.push_back(*i);
473  NS_LOG_DEBUG("Initiate PERR: Adding failed destination: " << (*i).destination);
474  }
475  }
476  }
477  SendMyPerr();
478 }
479 
480 void
482 {
483  NS_LOG_FUNCTION(this);
484  if (m_perrTimer.IsRunning())
485  {
486  return;
487  }
488  m_perrTimer =
489  Simulator::Schedule(m_protocol->GetPerrMinInterval(), &HwmpProtocolMac::SendMyPerr, this);
491  m_myPerr.destinations.clear();
492  m_myPerr.receivers.clear();
493 }
494 
495 uint32_t
497 {
498  return m_parent->GetLinkMetric(peerAddress);
499 }
500 
501 uint16_t
503 {
504  return m_parent->GetFrequencyChannel();
505 }
506 
508  : txPreq(0),
509  rxPreq(0),
510  txPrep(0),
511  rxPrep(0),
512  txPerr(0),
513  rxPerr(0),
514  txMgt(0),
515  txMgtBytes(0),
516  rxMgt(0),
517  rxMgtBytes(0),
518  txData(0),
519  txDataBytes(0),
520  rxData(0),
521  rxDataBytes(0)
522 {
523 }
524 
525 void
526 HwmpProtocolMac::Statistics::Print(std::ostream& os) const
527 {
528  os << "<Statistics "
529  "txPreq= \""
530  << txPreq << "\"" << std::endl
531  << "txPrep=\"" << txPrep << "\"" << std::endl
532  << "txPerr=\"" << txPerr << "\"" << std::endl
533  << "rxPreq=\"" << rxPreq << "\"" << std::endl
534  << "rxPrep=\"" << rxPrep << "\"" << std::endl
535  << "rxPerr=\"" << rxPerr << "\"" << std::endl
536  << "txMgt=\"" << txMgt << "\"" << std::endl
537  << "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl
538  << "rxMgt=\"" << rxMgt << "\"" << std::endl
539  << "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl
540  << "txData=\"" << txData << "\"" << std::endl
541  << "txDataBytes=\"" << txDataBytes << "\"" << std::endl
542  << "rxData=\"" << rxData << "\"" << std::endl
543  << "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
544 }
545 
546 void
547 HwmpProtocolMac::Report(std::ostream& os) const
548 {
549  os << "<HwmpProtocolMac" << std::endl
550  << "address =\"" << m_parent->GetAddress() << "\">" << std::endl;
551  m_stats.Print(os);
552  os << "</HwmpProtocolMac>" << std::endl;
553 }
554 
555 void
557 {
558  NS_LOG_FUNCTION(this);
559  m_stats = Statistics();
560 }
561 
562 int64_t
564 {
565  return m_protocol->AssignStreams(stream);
566 }
567 
568 } // namespace dot11s
569 } // 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()
Introspection did not find any typical Config paths.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
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:863
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:1002
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
Definition: mgt-headers.h:1279
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
CategoryValue GetCategory() const
Return the category value.
std::vector< Ptr< WifiInformationElement > >::iterator Iterator
As soon as this is a vector, we define an Iterator.
Iterator End()
Returns End of the vector.
Iterator Begin()
Returns Begin of the vector.
bool AddInformationElement(Ptr< WifiInformationElement > element)
add an IE, if maxSize has exceeded, returns false
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.
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:40
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
Definition: mgt-headers.h:1444
#define IE_PREQ
#define IE_RANN
#define IE_PREP
#define IE_PERR