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  return true;
207 }
210 {
211  WifiActionHeader actionHdr;
214  actionHdr.SetAction (WifiActionHeader::MESH, action);
215  return actionHdr;
216 }
217 void
219 {
221  std::vector<IePreq> preq_vector;
222  preq_vector.push_back (preq);
223  SendPreq (preq_vector);
224 }
225 void
226 HwmpProtocolMac::SendPreq (std::vector<IePreq> preq)
227 {
228  Ptr<Packet> packet = Create<Packet> ();
230  for (std::vector<IePreq>::iterator i = preq.begin (); i != preq.end (); i++)
231  {
232  elements.AddInformationElement (Ptr<IePreq> (&(*i)));
233  }
234  packet->AddHeader (elements);
235  packet->AddHeader (GetWifiActionHeader ());
236  //create 802.11 header:
237  WifiMacHeader hdr;
238  hdr.SetAction ();
239  hdr.SetDsNotFrom ();
240  hdr.SetDsNotTo ();
241  hdr.SetAddr2 (m_parent->GetAddress ());
242  hdr.SetAddr3 (m_protocol->GetAddress ());
243  //Send Management frame
244  std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers (m_ifIndex);
245  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i++)
246  {
247  hdr.SetAddr1 (*i);
248  m_stats.txPreq++;
249  m_stats.txMgt++;
250  m_stats.txMgtBytes += packet->GetSize ();
251  m_parent->SendManagementFrame (packet, hdr);
252  }
253 }
254 void
255 HwmpProtocolMac::RequestDestination (Mac48Address dst, uint32_t originator_seqno, uint32_t dst_seqno)
256 {
258  for (std::vector<IePreq>::iterator i = m_myPreq.begin (); i != m_myPreq.end (); i++)
259  {
260  if (i->IsFull ())
261  {
262  continue;
263  }
264  NS_ASSERT (i->GetDestCount () > 0);
265  i->AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
266  }
267  IePreq preq;
268  preq.SetHopcount (0);
269  preq.SetTTL (m_protocol->GetMaxTtl ());
270  preq.SetPreqID (m_protocol->GetNextPreqId ());
271  preq.SetOriginatorAddress (m_protocol->GetAddress ());
272  preq.SetOriginatorSeqNumber (originator_seqno);
273  preq.SetLifetime (m_protocol->GetActivePathLifetime ());
274  preq.AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
275  m_myPreq.push_back (preq);
276  SendMyPreq ();
277 }
278 void
280 {
282  if (m_preqTimer.IsRunning ())
283  {
284  return;
285  }
286  if (m_myPreq.size () == 0)
287  {
288  return;
289  }
290  //reschedule sending PREQ
292  m_preqTimer = Simulator::Schedule (m_protocol->GetPreqMinInterval (), &HwmpProtocolMac::SendMyPreq, this);
293  SendPreq (m_myPreq);
294  m_myPreq.clear ();
295 }
296 void
298 {
300  //Create packet
301  Ptr<Packet> packet = Create<Packet> ();
303  elements.AddInformationElement (Ptr<IePrep> (&prep));
304  packet->AddHeader (elements);
305  packet->AddHeader (GetWifiActionHeader ());
306  //create 802.11 header:
307  WifiMacHeader hdr;
308  hdr.SetAction ();
309  hdr.SetDsNotFrom ();
310  hdr.SetDsNotTo ();
311  hdr.SetAddr1 (receiver);
312  hdr.SetAddr2 (m_parent->GetAddress ());
313  hdr.SetAddr3 (m_protocol->GetAddress ());
314  //Send Management frame
315  m_stats.txPrep++;
316  m_stats.txMgt++;
317  m_stats.txMgtBytes += packet->GetSize ();
318  m_parent->SendManagementFrame (packet, hdr);
319 }
320 void
321 HwmpProtocolMac::ForwardPerr (std::vector<HwmpProtocol::FailedDestination> failedDestinations, std::vector<
322  Mac48Address> receivers)
323 {
325  Ptr<Packet> packet = Create<Packet> ();
326  Ptr<IePerr> perr = Create <IePerr> ();
328  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = failedDestinations.begin (); i
329  != failedDestinations.end (); i++)
330  {
331  if (!perr->IsFull ())
332  {
333  perr->AddAddressUnit (*i);
334  }
335  else
336  {
337  elements.AddInformationElement (perr);
338  perr->ResetPerr ();
339  }
340  }
341  if (perr->GetNumOfDest () > 0)
342  {
343  elements.AddInformationElement (perr);
344  }
345  packet->AddHeader (elements);
346  packet->AddHeader (GetWifiActionHeader ());
347  //create 802.11 header:
348  WifiMacHeader hdr;
349  hdr.SetAction ();
350  hdr.SetDsNotFrom ();
351  hdr.SetDsNotTo ();
352  hdr.SetAddr2 (m_parent->GetAddress ());
353  hdr.SetAddr3 (m_protocol->GetAddress ());
354  if (receivers.size () >= m_protocol->GetUnicastPerrThreshold ())
355  {
356  receivers.clear ();
357  receivers.push_back (Mac48Address::GetBroadcast ());
358  }
359  //Send Management frame
360  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i++)
361  {
362  //
363  // 64-bit Intel valgrind complains about hdr.SetAddr1 (*i). It likes this
364  // just fine.
365  //
366  Mac48Address address = *i;
367  hdr.SetAddr1 (address);
368  m_stats.txPerr++;
369  m_stats.txMgt++;
370  m_stats.txMgtBytes += packet->GetSize ();
371  m_parent->SendManagementFrame (packet, hdr);
372  }
373 }
374 void
375 HwmpProtocolMac::InitiatePerr (std::vector<HwmpProtocol::FailedDestination> failedDestinations, std::vector<
376  Mac48Address> receivers)
377 {
378  //All duplicates in PERR are checked here, and there is no reason to
379  //check it at any athoer place
380  {
381  std::vector<Mac48Address>::const_iterator end = receivers.end ();
382  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != end; i++)
383  {
384  bool should_add = true;
385  for (std::vector<Mac48Address>::const_iterator j = m_myPerr.receivers.begin (); j
386  != m_myPerr.receivers.end (); j++)
387  {
388  if ((*i) == (*j))
389  {
390  should_add = false;
391  }
392  }
393  if (should_add)
394  {
395  m_myPerr.receivers.push_back (*i);
396  }
397  }
398  }
399  {
400  std::vector<HwmpProtocol::FailedDestination>::const_iterator end = failedDestinations.end ();
401  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = failedDestinations.begin (); i != end; i++)
402  {
403  bool should_add = true;
404  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator j = m_myPerr.destinations.begin (); j
405  != m_myPerr.destinations.end (); j++)
406  {
407  if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
408  {
409  should_add = false;
410  }
411  }
412  if (should_add)
413  {
414  m_myPerr.destinations.push_back (*i);
415  }
416  }
417  }
418  SendMyPerr ();
419 }
420 void
422 {
424  if (m_perrTimer.IsRunning ())
425  {
426  return;
427  }
428  m_perrTimer = Simulator::Schedule (m_protocol->GetPerrMinInterval (), &HwmpProtocolMac::SendMyPerr, this);
430  m_myPerr.destinations.clear ();
431  m_myPerr.receivers.clear ();
432 }
433 uint32_t
435 {
436  return m_parent->GetLinkMetric (peerAddress);
437 }
438 uint16_t
440 {
441  return m_parent->GetFrequencyChannel ();
442 }
444  txPreq (0), rxPreq (0), txPrep (0), rxPrep (0), txPerr (0), rxPerr (0), txMgt (0), txMgtBytes (0),
445  rxMgt (0), rxMgtBytes (0), txData (0), txDataBytes (0), rxData (0), rxDataBytes (0)
446 {
447 }
448 void
449 HwmpProtocolMac::Statistics::Print (std::ostream & os) const
450 {
451  os << "<Statistics "
452  "txPreq= \"" << txPreq << "\"" << std::endl <<
453  "txPrep=\"" << txPrep << "\"" << std::endl <<
454  "txPerr=\"" << txPerr << "\"" << std::endl <<
455  "rxPreq=\"" << rxPreq << "\"" << std::endl <<
456  "rxPrep=\"" << rxPrep << "\"" << std::endl <<
457  "rxPerr=\"" << rxPerr << "\"" << std::endl <<
458  "txMgt=\"" << txMgt << "\"" << std::endl <<
459  "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl <<
460  "rxMgt=\"" << rxMgt << "\"" << std::endl <<
461  "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl <<
462  "txData=\"" << txData << "\"" << std::endl <<
463  "txDataBytes=\"" << txDataBytes << "\"" << std::endl <<
464  "rxData=\"" << rxData << "\"" << std::endl <<
465  "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
466 }
467 void
468 HwmpProtocolMac::Report (std::ostream & os) const
469 {
470  os << "<HwmpProtocolMac" << std::endl <<
471  "address =\"" << m_parent->GetAddress () << "\">" << std::endl;
472  m_stats.Print (os);
473  os << "</HwmpProtocolMac>" << std::endl;
474 }
475 void
477 {
478  m_stats = Statistics ();
479 }
480 
481 int64_t
483 {
484  return m_protocol->AssignStreams (stream);
485 }
486 
487 
488 } // namespace dot11s
489 } // 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:336
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:836
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:766
std::vector< IePreq > m_myPreq
void SetAction(enum CategoryValue type, ActionValue action)
Set action for this Action header.
Definition: mgt-headers.cc:482
#define NS_FATAL_ERROR(msg)
Fatal error handling.
Definition: fatal-error.h:100
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:515
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:819
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:858
static WifiActionHeader GetWifiActionHeader()
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:404
#define IE11S_PERR
#define IE11S_PREQ
Ptr< MeshWifiInterfaceMac > m_parent
#define IE11S_PREP
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.
void SetOriginatorSeqNumber(uint32_t originator_seq_number)
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
#define IE11S_RANN
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
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:843
void ForwardPerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
Request a destination.
typedef for union of different ActionValues
Definition: mgt-headers.h:402
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 SetHopcount(uint8_t hopcount)
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
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.