A Discrete-Event Network Simulator
API
hwmp-protocol-mac.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008,2009 IITP RAS
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: Kirill Andreev <andreev@iitp.ru>
19  */
20 
21 #include "ns3/mesh-wifi-interface-mac.h"
22 #include "ns3/packet.h"
23 #include "ns3/simulator.h"
24 #include "ns3/nstime.h"
25 #include "ns3/log.h"
26 #include "ns3/mgt-headers.h"
27 #include "dot11s-mac-header.h"
28 #include "hwmp-protocol-mac.h"
29 #include "hwmp-tag.h"
30 #include "ie-dot11s-preq.h"
31 #include "ie-dot11s-prep.h"
32 #include "ie-dot11s-rann.h"
33 #include "ie-dot11s-perr.h"
34 
35 namespace ns3 {
36 
37 NS_LOG_COMPONENT_DEFINE ("HwmpProtocolMac");
38 
39 namespace dot11s {
40 
42  m_ifIndex (ifIndex), m_protocol (protocol)
43 {
44 }
46 {
47 }
48 void
50 {
51  m_parent = parent;
52 }
53 
54 bool
56 {
57  NS_ASSERT (header.IsData ());
58 
59  MeshHeader meshHdr;
60  HwmpTag tag;
61  if (packet->PeekPacketTag (tag))
62  {
63  NS_FATAL_ERROR ("HWMP tag is not supposed to be received by network");
64  }
65 
66  packet->RemoveHeader (meshHdr);
67  m_stats.rxData++;
68  m_stats.rxDataBytes += packet->GetSize ();
69 
71  Mac48Address destination;
72  Mac48Address source;
73  switch (meshHdr.GetAddressExt ())
74  {
75  case 0:
76  source = header.GetAddr4 ();
77  destination = header.GetAddr3 ();
78  break;
79  default:
81  "6-address scheme is not yet supported and 4-address extension is not supposed to be used for data frames.");
82  }
83  tag.SetSeqno (meshHdr.GetMeshSeqno ());
84  tag.SetTtl (meshHdr.GetMeshTtl ());
85  packet->AddPacketTag (tag);
86 
87  if ((destination == Mac48Address::GetBroadcast ()) && (m_protocol->DropDataFrame (meshHdr.GetMeshSeqno (),
88  source)))
89  {
90  return false;
91  }
92  return true;
93 }
94 
95 bool
97 {
98  m_stats.rxMgt++;
99  m_stats.rxMgtBytes += packet->GetSize ();
100  WifiActionHeader actionHdr;
101  packet->RemoveHeader (actionHdr);
102  if (actionHdr.GetCategory () != WifiActionHeader::MESH)
103  {
104  return true;
105  }
107  packet->RemoveHeader (elements);
108  std::vector<HwmpProtocol::FailedDestination> failedDestinations;
109  for (MeshInformationElementVector::Iterator i = elements.Begin (); i != elements.End (); i++)
110  {
111  if ((*i)->ElementId () == IE11S_RANN)
112  {
113  NS_LOG_WARN ("RANN is not supported!");
114  }
115  if ((*i)->ElementId () == IE11S_PREQ)
116  {
117  Ptr<IePreq> preq = DynamicCast<IePreq> (*i);
118  NS_ASSERT (preq != 0);
119  m_stats.rxPreq++;
120  if (preq->GetOriginatorAddress () == m_protocol->GetAddress ())
121  {
122  continue;
123  }
124  if (preq->GetTtl () == 0)
125  {
126  continue;
127  }
128  preq->DecrementTtl ();
129  m_protocol->ReceivePreq (*preq, header.GetAddr2 (), m_ifIndex, header.GetAddr3 (),
130  m_parent->GetLinkMetric (header.GetAddr2 ()));
131  }
132  if ((*i)->ElementId () == IE11S_PREP)
133  {
134  Ptr<IePrep> prep = DynamicCast<IePrep> (*i);
135  NS_ASSERT (prep != 0);
136  m_stats.rxPrep++;
137  if (prep->GetTtl () == 0)
138  {
139  continue;
140  }
141  prep->DecrementTtl ();
142  m_protocol->ReceivePrep (*prep, header.GetAddr2 (), m_ifIndex, header.GetAddr3 (),
143  m_parent->GetLinkMetric (header.GetAddr2 ()));
144  }
145  if ((*i)->ElementId () == IE11S_PERR)
146  {
147  Ptr<IePerr> perr = DynamicCast<IePerr> (*i);
148  NS_ASSERT (perr != 0);
149  m_stats.rxPerr++;
150  std::vector<HwmpProtocol::FailedDestination> destinations = perr->GetAddressUnitVector ();
151  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = destinations.begin (); i
152  != destinations.end (); i++)
153  {
154  failedDestinations.push_back (*i);
155  }
156  }
157  }
158  if (failedDestinations.size () > 0)
159  {
160  m_protocol->ReceivePerr (failedDestinations, header.GetAddr2 (), m_ifIndex, header.GetAddr3 ());
161  }
162  NS_ASSERT (packet->GetSize () == 0);
163  return false;
164 }
165 
166 bool
168 {
169  if (header.IsData ())
170  {
171  return ReceiveData (packet, header);
172  }
173  else
174  {
175  if (header.IsAction ())
176  {
177  return ReceiveAction (packet, header);
178  }
179  else
180  {
181  return true; // don't care
182  }
183  }
184 }
185 bool
187  Mac48Address to)
188 {
189  if (!header.IsData ())
190  {
191  return true;
192  }
193  HwmpTag tag;
194  bool tagExists = packet->RemovePacketTag (tag);
195  if (!tagExists)
196  {
197  NS_FATAL_ERROR ("HWMP tag must exist at this point");
198  }
199  m_stats.txData++;
200  m_stats.txDataBytes += packet->GetSize ();
201  MeshHeader meshHdr;
202  meshHdr.SetMeshSeqno (tag.GetSeqno ());
203  meshHdr.SetMeshTtl (tag.GetTtl ());
204  packet->AddHeader (meshHdr);
205  header.SetAddr1 (tag.GetAddress ());
206  header.SetQosMeshControlPresent ();
207  return true;
208 }
211 {
212  WifiActionHeader actionHdr;
215  actionHdr.SetAction (WifiActionHeader::MESH, action);
216  return actionHdr;
217 }
218 void
220 {
222  std::vector<IePreq> preq_vector;
223  preq_vector.push_back (preq);
224  SendPreq (preq_vector);
225 }
226 void
227 HwmpProtocolMac::SendPreq (std::vector<IePreq> preq)
228 {
229  Ptr<Packet> packet = Create<Packet> ();
231  for (std::vector<IePreq>::iterator i = preq.begin (); i != preq.end (); i++)
232  {
233  elements.AddInformationElement (Ptr<IePreq> (&(*i)));
234  }
235  packet->AddHeader (elements);
236  packet->AddHeader (GetWifiActionHeader ());
237  //create 802.11 header:
238  WifiMacHeader hdr;
239  hdr.SetAction ();
240  hdr.SetDsNotFrom ();
241  hdr.SetDsNotTo ();
242  hdr.SetAddr2 (m_parent->GetAddress ());
243  hdr.SetAddr3 (m_protocol->GetAddress ());
244  //Send Management frame
245  std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers (m_ifIndex);
246  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i++)
247  {
248  hdr.SetAddr1 (*i);
249  m_stats.txPreq++;
250  m_stats.txMgt++;
251  m_stats.txMgtBytes += packet->GetSize ();
252  m_parent->SendManagementFrame (packet, hdr);
253  }
254 }
255 void
256 HwmpProtocolMac::RequestDestination (Mac48Address dst, uint32_t originator_seqno, uint32_t dst_seqno)
257 {
259  for (std::vector<IePreq>::iterator i = m_myPreq.begin (); i != m_myPreq.end (); i++)
260  {
261  if (i->IsFull ())
262  {
263  continue;
264  }
265  NS_ASSERT (i->GetDestCount () > 0);
266  i->AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
267  }
268  IePreq preq;
269  preq.SetHopcount (0);
270  preq.SetTTL (m_protocol->GetMaxTtl ());
271  preq.SetPreqID (m_protocol->GetNextPreqId ());
272  preq.SetOriginatorAddress (m_protocol->GetAddress ());
273  preq.SetOriginatorSeqNumber (originator_seqno);
274  preq.SetLifetime (m_protocol->GetActivePathLifetime ());
275  preq.AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
276  m_myPreq.push_back (preq);
277  SendMyPreq ();
278 }
279 void
281 {
283  if (m_preqTimer.IsRunning ())
284  {
285  return;
286  }
287  if (m_myPreq.size () == 0)
288  {
289  return;
290  }
291  //reschedule sending PREQ
293  m_preqTimer = Simulator::Schedule (m_protocol->GetPreqMinInterval (), &HwmpProtocolMac::SendMyPreq, this);
294  SendPreq (m_myPreq);
295  m_myPreq.clear ();
296 }
297 void
299 {
301  //Create packet
302  Ptr<Packet> packet = Create<Packet> ();
304  elements.AddInformationElement (Ptr<IePrep> (&prep));
305  packet->AddHeader (elements);
306  packet->AddHeader (GetWifiActionHeader ());
307  //create 802.11 header:
308  WifiMacHeader hdr;
309  hdr.SetAction ();
310  hdr.SetDsNotFrom ();
311  hdr.SetDsNotTo ();
312  hdr.SetAddr1 (receiver);
313  hdr.SetAddr2 (m_parent->GetAddress ());
314  hdr.SetAddr3 (m_protocol->GetAddress ());
315  //Send Management frame
316  m_stats.txPrep++;
317  m_stats.txMgt++;
318  m_stats.txMgtBytes += packet->GetSize ();
319  m_parent->SendManagementFrame (packet, hdr);
320 }
321 void
322 HwmpProtocolMac::ForwardPerr (std::vector<HwmpProtocol::FailedDestination> failedDestinations, std::vector<
323  Mac48Address> receivers)
324 {
326  Ptr<Packet> packet = Create<Packet> ();
327  Ptr<IePerr> perr = Create <IePerr> ();
329  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = failedDestinations.begin (); i
330  != failedDestinations.end (); i++)
331  {
332  if (!perr->IsFull ())
333  {
334  perr->AddAddressUnit (*i);
335  }
336  else
337  {
338  elements.AddInformationElement (perr);
339  perr->ResetPerr ();
340  }
341  }
342  if (perr->GetNumOfDest () > 0)
343  {
344  elements.AddInformationElement (perr);
345  }
346  packet->AddHeader (elements);
347  packet->AddHeader (GetWifiActionHeader ());
348  //create 802.11 header:
349  WifiMacHeader hdr;
350  hdr.SetAction ();
351  hdr.SetDsNotFrom ();
352  hdr.SetDsNotTo ();
353  hdr.SetAddr2 (m_parent->GetAddress ());
354  hdr.SetAddr3 (m_protocol->GetAddress ());
355  if (receivers.size () >= m_protocol->GetUnicastPerrThreshold ())
356  {
357  receivers.clear ();
358  receivers.push_back (Mac48Address::GetBroadcast ());
359  }
360  //Send Management frame
361  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i++)
362  {
363  //
364  // 64-bit Intel valgrind complains about hdr.SetAddr1 (*i). It likes this
365  // just fine.
366  //
367  Mac48Address address = *i;
368  hdr.SetAddr1 (address);
369  m_stats.txPerr++;
370  m_stats.txMgt++;
371  m_stats.txMgtBytes += packet->GetSize ();
372  m_parent->SendManagementFrame (packet, hdr);
373  }
374 }
375 void
376 HwmpProtocolMac::InitiatePerr (std::vector<HwmpProtocol::FailedDestination> failedDestinations, std::vector<
377  Mac48Address> receivers)
378 {
379  //All duplicates in PERR are checked here, and there is no reason to
380  //check it at any athoer place
381  {
382  std::vector<Mac48Address>::const_iterator end = receivers.end ();
383  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != end; i++)
384  {
385  bool should_add = true;
386  for (std::vector<Mac48Address>::const_iterator j = m_myPerr.receivers.begin (); j
387  != m_myPerr.receivers.end (); j++)
388  {
389  if ((*i) == (*j))
390  {
391  should_add = false;
392  }
393  }
394  if (should_add)
395  {
396  m_myPerr.receivers.push_back (*i);
397  }
398  }
399  }
400  {
401  std::vector<HwmpProtocol::FailedDestination>::const_iterator end = failedDestinations.end ();
402  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = failedDestinations.begin (); i != end; i++)
403  {
404  bool should_add = true;
405  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator j = m_myPerr.destinations.begin (); j
406  != m_myPerr.destinations.end (); j++)
407  {
408  if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
409  {
410  should_add = false;
411  }
412  }
413  if (should_add)
414  {
415  m_myPerr.destinations.push_back (*i);
416  }
417  }
418  }
419  SendMyPerr ();
420 }
421 void
423 {
425  if (m_perrTimer.IsRunning ())
426  {
427  return;
428  }
429  m_perrTimer = Simulator::Schedule (m_protocol->GetPerrMinInterval (), &HwmpProtocolMac::SendMyPerr, this);
431  m_myPerr.destinations.clear ();
432  m_myPerr.receivers.clear ();
433 }
434 uint32_t
436 {
437  return m_parent->GetLinkMetric (peerAddress);
438 }
439 uint16_t
441 {
442  return m_parent->GetFrequencyChannel ();
443 }
445  txPreq (0), rxPreq (0), txPrep (0), rxPrep (0), txPerr (0), rxPerr (0), txMgt (0), txMgtBytes (0),
446  rxMgt (0), rxMgtBytes (0), txData (0), txDataBytes (0), rxData (0), rxDataBytes (0)
447 {
448 }
449 void
450 HwmpProtocolMac::Statistics::Print (std::ostream & os) const
451 {
452  os << "<Statistics "
453  "txPreq= \"" << txPreq << "\"" << std::endl <<
454  "txPrep=\"" << txPrep << "\"" << std::endl <<
455  "txPerr=\"" << txPerr << "\"" << std::endl <<
456  "rxPreq=\"" << rxPreq << "\"" << std::endl <<
457  "rxPrep=\"" << rxPrep << "\"" << std::endl <<
458  "rxPerr=\"" << rxPerr << "\"" << std::endl <<
459  "txMgt=\"" << txMgt << "\"" << std::endl <<
460  "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl <<
461  "rxMgt=\"" << rxMgt << "\"" << std::endl <<
462  "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl <<
463  "txData=\"" << txData << "\"" << std::endl <<
464  "txDataBytes=\"" << txDataBytes << "\"" << std::endl <<
465  "rxData=\"" << rxData << "\"" << std::endl <<
466  "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
467 }
468 void
469 HwmpProtocolMac::Report (std::ostream & os) const
470 {
471  os << "<HwmpProtocolMac" << std::endl <<
472  "address =\"" << m_parent->GetAddress () << "\">" << std::endl;
473  m_stats.Print (os);
474  os << "</HwmpProtocolMac>" << std::endl;
475 }
476 void
478 {
479  m_stats = Statistics ();
480 }
481 
482 int64_t
484 {
485  return m_protocol->AssignStreams (stream);
486 }
487 
488 
489 } // namespace dot11s
490 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
void SetAction()
Set Type/Subtype values for an action header.
bool ReceiveAction(Ptr< Packet > packet, const WifiMacHeader &header)
Receive action management frame.
void SetPreqID(uint32_t id)
uint32_t GetLinkMetric(Mac48Address peerAddress) const
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
void SetParent(Ptr< MeshWifiInterfaceMac > parent)
Update beacon is empty, because HWMP does not know anything about beacons.
void SendMyPreq()
Sends one PREQ when PreqMinInterval after last PREQ expires (if any PREQ exists in rhe queue) ...
Hwmp tag implements interaction between HWMP protocol and MeshWifiMac.
Definition: hwmp-tag.h:48
void SetTTL(uint8_t ttl)
void SendPrep(IePrep prep, Mac48Address receiver)
Request a destination.
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
Definition: mgt-headers.h:548
bool IsAction() const
Return true if the header is an Action header.
void RequestDestination(Mac48Address dest, uint32_t originator_seqno, uint32_t dst_seqno)
Request a destination.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:824
Mac48Address GetAddr3(void) const
Return the address in the Address 3 field.
Mac48Address GetAddr4(void) const
Return the address in the Address 4 field.
#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
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
See 7.3.2.97 of 802.11s draft 2.07.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
std::vector< IePreq > m_myPreq
void SetAction(enum CategoryValue type, ActionValue action)
Set action for this Action header.
Definition: mgt-headers.cc:762
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
void SetMeshSeqno(uint32_t seqno)
CategoryValue GetCategory()
Return the category value.
Definition: mgt-headers.cc:796
uint32_t GetSeqno()
Definition: hwmp-tag.cc:81
void SetTtl(uint8_t ttl)
Definition: hwmp-tag.cc:51
bool AddInformationElement(Ptr< WifiInformationElement > element)
add an IE, if maxSize has exceeded, returns false
void SetLifetime(uint32_t lifetime)
void SendPreq(IePreq preq)
Request a destination.
Mac48Address GetAddress()
Definition: hwmp-tag.cc:45
void SetMeshTtl(uint8_t TTL)
Iterator End()
Returns End of the vector.
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:846
static WifiActionHeader GetWifiActionHeader()
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1238
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
See 7.3.2.96 of 802.11s draft 2.07.
std::vector< Ptr< WifiInformationElement > >::iterator Iterator
As soon as this is a vector, we define an Iterator.
enum MeshActionValue meshAction
Definition: mgt-headers.h:617
Ptr< MeshWifiInterfaceMac > m_parent
static Mac48Address GetBroadcast(void)
std::vector< Mac48Address > receivers
void SetOriginatorAddress(Mac48Address originator_address)
HwmpProtocolMac(uint32_t, Ptr< HwmpProtocol >)
Iterator Begin()
Returns Begin of the vector.
#define IE11S_RANN
void SetOriginatorSeqNumber(uint32_t originator_seq_number)
#define IE11S_PREP
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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 SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
an EUI-48 address
Definition: mac48-address.h:43
std::vector< HwmpProtocol::FailedDestination > destinations
Introspection did not find any typical Config paths.
bool UpdateOutcomingFrame(Ptr< Packet > packet, WifiMacHeader &header, Mac48Address from, Mac48Address to)
Update beacon is empty, because HWMP does not know anything about beacons.
Ptr< HwmpProtocol > m_protocol
uint8_t GetTtl()
Definition: hwmp-tag.cc:57
#define IE11S_PREQ
int64_t AssignStreams(int64_t stream)
Update beacon is empty, because HWMP does not know anything about beacons.
bool ReceiveData(Ptr< Packet > packet, const WifiMacHeader &header)
Receive data frame.
bool IsData(void) const
Return true if the Type is DATA.
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:228
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:831
void ForwardPerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
Request a destination.
typedef for union of different ActionValues
Definition: mgt-headers.h:615
#define IE11S_PERR
bool Receive(Ptr< Packet > packet, const WifiMacHeader &header)
Update beacon is empty, because HWMP does not know anything about beacons.
Mesh Control field, see IEEE 802.11s draft 3.0 section 7.1.3.5b.
void Report(std::ostream &) const
Report statistics.
void InitiatePerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
Request a destination.
tuple address
Definition: first.py:37
void SetSeqno(uint32_t seqno)
Definition: hwmp-tag.cc:75
void SetQosMeshControlPresent()
Set the Mesh Control Present flag for the QoS header.
void SetHopcount(uint8_t hopcount)
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:257
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.