A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
hwmp-protocol-mac.cc
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 namespace dot11s {
37 
38 NS_LOG_COMPONENT_DEFINE ("HwmpProtocolMac");
39 HwmpProtocolMac::HwmpProtocolMac (uint32_t ifIndex, Ptr<HwmpProtocol> protocol) :
40  m_ifIndex (ifIndex), m_protocol (protocol)
41 {
42 }
43 HwmpProtocolMac::~HwmpProtocolMac ()
44 {
45 }
46 void
48 {
49  m_parent = parent;
50 }
51 
52 bool
54 {
55  NS_ASSERT (header.IsData ());
56 
57  MeshHeader meshHdr;
58  HwmpTag tag;
59  if (packet->PeekPacketTag (tag))
60  {
61  NS_FATAL_ERROR ("HWMP tag is not supposed to be received by network");
62  }
63 
64  packet->RemoveHeader (meshHdr);
65  m_stats.rxData++;
66  m_stats.rxDataBytes += packet->GetSize ();
67 
68  //TODO: address extension
69  Mac48Address destination;
70  Mac48Address source;
71  switch (meshHdr.GetAddressExt ())
72  {
73  case 0:
74  source = header.GetAddr4 ();
75  destination = header.GetAddr3 ();
76  break;
77  default:
79  "6-address scheme is not yet supported and 4-address extension is not supposed to be used for data frames.");
80  }
81  tag.SetSeqno (meshHdr.GetMeshSeqno ());
82  tag.SetTtl (meshHdr.GetMeshTtl ());
83  packet->AddPacketTag (tag);
84 
85  if ((destination == Mac48Address::GetBroadcast ()) && (m_protocol->DropDataFrame (meshHdr.GetMeshSeqno (),
86  source)))
87  {
88  return false;
89  }
90  return true;
91 }
92 
93 bool
95 {
96  m_stats.rxMgt++;
97  m_stats.rxMgtBytes += packet->GetSize ();
98  WifiActionHeader actionHdr;
99  packet->RemoveHeader (actionHdr);
100  if (actionHdr.GetCategory () != WifiActionHeader::MESH_PATH_SELECTION)
101  {
102  return true;
103  }
105  packet->RemoveHeader (elements);
106  std::vector<HwmpProtocol::FailedDestination> failedDestinations;
107  for (MeshInformationElementVector::Iterator i = elements.Begin (); i != elements.End (); i++)
108  {
109  if ((*i)->ElementId () == IE11S_RANN)
110  {
111  NS_LOG_WARN ("RANN is not supported!");
112  }
113  if ((*i)->ElementId () == IE11S_PREQ)
114  {
115  Ptr<IePreq> preq = DynamicCast<IePreq> (*i);
116  NS_ASSERT (preq != 0);
117  m_stats.rxPreq++;
118  if (preq->GetOriginatorAddress () == m_protocol->GetAddress ())
119  {
120  continue;
121  }
122  if (preq->GetTtl () == 0)
123  {
124  continue;
125  }
126  preq->DecrementTtl ();
127  m_protocol->ReceivePreq (*preq, header.GetAddr2 (), m_ifIndex, header.GetAddr3 (),
128  m_parent->GetLinkMetric (header.GetAddr2 ()));
129  }
130  if ((*i)->ElementId () == IE11S_PREP)
131  {
132  Ptr<IePrep> prep = DynamicCast<IePrep> (*i);
133  NS_ASSERT (prep != 0);
134  m_stats.rxPrep++;
135  if (prep->GetTtl () == 0)
136  {
137  continue;
138  }
139  prep->DecrementTtl ();
140  m_protocol->ReceivePrep (*prep, header.GetAddr2 (), m_ifIndex, header.GetAddr3 (),
141  m_parent->GetLinkMetric (header.GetAddr2 ()));
142  }
143  if ((*i)->ElementId () == IE11S_PERR)
144  {
145  Ptr<IePerr> perr = DynamicCast<IePerr> (*i);
146  NS_ASSERT (perr != 0);
147  m_stats.rxPerr++;
148  std::vector<HwmpProtocol::FailedDestination> destinations = perr->GetAddressUnitVector ();
149  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = destinations.begin (); i
150  != destinations.end (); i++)
151  {
152  failedDestinations.push_back (*i);
153  }
154  }
155  }
156  if (failedDestinations.size () > 0)
157  {
158  m_protocol->ReceivePerr (failedDestinations, header.GetAddr2 (), m_ifIndex, header.GetAddr3 ());
159  }
160  NS_ASSERT (packet->GetSize () == 0);
161  return false;
162 }
163 
164 bool
166 {
167  if (header.IsData ())
168  {
169  return ReceiveData (packet, header);
170  }
171  else
172  {
173  if (header.IsAction ())
174  {
175  return ReceiveAction (packet, header);
176  }
177  else
178  {
179  return true; // don't care
180  }
181  }
182 }
183 bool
185  Mac48Address to)
186 {
187  if (!header.IsData ())
188  {
189  return true;
190  }
191  HwmpTag tag;
192  bool tagExists = packet->RemovePacketTag (tag);
193  if (!tagExists)
194  {
195  NS_FATAL_ERROR ("HWMP tag must exist at this point");
196  }
197  m_stats.txData++;
198  m_stats.txDataBytes += packet->GetSize ();
199  MeshHeader meshHdr;
200  meshHdr.SetMeshSeqno (tag.GetSeqno ());
201  meshHdr.SetMeshTtl (tag.GetTtl ());
202  packet->AddHeader (meshHdr);
203  header.SetAddr1 (tag.GetAddress ());
204  return true;
205 }
208 {
209  WifiActionHeader actionHdr;
211  action.pathSelection = WifiActionHeader::PATH_SELECTION;
212  actionHdr.SetAction (WifiActionHeader::MESH_PATH_SELECTION, action);
213  return actionHdr;
214 }
215 void
216 HwmpProtocolMac::SendPreq (IePreq preq)
217 {
219  std::vector<IePreq> preq_vector;
220  preq_vector.push_back (preq);
221  SendPreq (preq_vector);
222 }
223 void
224 HwmpProtocolMac::SendPreq (std::vector<IePreq> preq)
225 {
226  Ptr<Packet> packet = Create<Packet> ();
228  for (std::vector<IePreq>::iterator i = preq.begin (); i != preq.end (); i++)
229  {
230  elements.AddInformationElement (Ptr<IePreq> (&(*i)));
231  }
232  packet->AddHeader (elements);
233  packet->AddHeader (GetWifiActionHeader ());
234  //create 802.11 header:
235  WifiMacHeader hdr;
236  hdr.SetAction ();
237  hdr.SetDsNotFrom ();
238  hdr.SetDsNotTo ();
239  hdr.SetAddr2 (m_parent->GetAddress ());
240  hdr.SetAddr3 (m_protocol->GetAddress ());
241  //Send Management frame
242  std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers (m_ifIndex);
243  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i++)
244  {
245  hdr.SetAddr1 (*i);
246  m_stats.txPreq++;
247  m_stats.txMgt++;
248  m_stats.txMgtBytes += packet->GetSize ();
249  m_parent->SendManagementFrame (packet, hdr);
250  }
251 }
252 void
253 HwmpProtocolMac::RequestDestination (Mac48Address dst, uint32_t originator_seqno, uint32_t dst_seqno)
254 {
256  for (std::vector<IePreq>::iterator i = m_myPreq.begin (); i != m_myPreq.end (); i++)
257  {
258  if (i->IsFull ())
259  {
260  continue;
261  }
262  NS_ASSERT (i->GetDestCount () > 0);
263  i->AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
264  }
265  IePreq preq;
266  preq.SetHopcount (0);
267  preq.SetTTL (m_protocol->GetMaxTtl ());
268  preq.SetPreqID (m_protocol->GetNextPreqId ());
269  preq.SetOriginatorAddress (m_protocol->GetAddress ());
270  preq.SetOriginatorSeqNumber (originator_seqno);
271  preq.SetLifetime (m_protocol->GetActivePathLifetime ());
272  preq.AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
273  m_myPreq.push_back (preq);
274  SendMyPreq ();
275 }
276 void
278 {
280  if (m_preqTimer.IsRunning ())
281  {
282  return;
283  }
284  if (m_myPreq.size () == 0)
285  {
286  return;
287  }
288  //reschedule sending PREQ
289  NS_ASSERT (!m_preqTimer.IsRunning ());
290  m_preqTimer = Simulator::Schedule (m_protocol->GetPreqMinInterval (), &HwmpProtocolMac::SendMyPreq, this);
291  SendPreq (m_myPreq);
292  m_myPreq.clear ();
293 }
294 void
295 HwmpProtocolMac::SendPrep (IePrep prep, Mac48Address receiver)
296 {
298  //Create packet
299  Ptr<Packet> packet = Create<Packet> ();
301  elements.AddInformationElement (Ptr<IePrep> (&prep));
302  packet->AddHeader (elements);
303  packet->AddHeader (GetWifiActionHeader ());
304  //create 802.11 header:
305  WifiMacHeader hdr;
306  hdr.SetAction ();
307  hdr.SetDsNotFrom ();
308  hdr.SetDsNotTo ();
309  hdr.SetAddr1 (receiver);
310  hdr.SetAddr2 (m_parent->GetAddress ());
311  hdr.SetAddr3 (m_protocol->GetAddress ());
312  //Send Management frame
313  m_stats.txPrep++;
314  m_stats.txMgt++;
315  m_stats.txMgtBytes += packet->GetSize ();
316  m_parent->SendManagementFrame (packet, hdr);
317 }
318 void
319 HwmpProtocolMac::ForwardPerr (std::vector<HwmpProtocol::FailedDestination> failedDestinations, std::vector<
320  Mac48Address> receivers)
321 {
323  Ptr<Packet> packet = Create<Packet> ();
324  Ptr<IePerr> perr = Create <IePerr> ();
326  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = failedDestinations.begin (); i
327  != failedDestinations.end (); i++)
328  {
329  if (!perr->IsFull ())
330  {
331  perr->AddAddressUnit (*i);
332  }
333  else
334  {
335  elements.AddInformationElement (perr);
336  perr->ResetPerr ();
337  }
338  }
339  if (perr->GetNumOfDest () > 0)
340  {
341  elements.AddInformationElement (perr);
342  }
343  packet->AddHeader (elements);
344  packet->AddHeader (GetWifiActionHeader ());
345  //create 802.11 header:
346  WifiMacHeader hdr;
347  hdr.SetAction ();
348  hdr.SetDsNotFrom ();
349  hdr.SetDsNotTo ();
350  hdr.SetAddr2 (m_parent->GetAddress ());
351  hdr.SetAddr3 (m_protocol->GetAddress ());
352  if (receivers.size () >= m_protocol->GetUnicastPerrThreshold ())
353  {
354  receivers.clear ();
355  receivers.push_back (Mac48Address::GetBroadcast ());
356  }
357  //Send Management frame
358  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i++)
359  {
360  //
361  // 64-bit Intel valgrind complains about hdr.SetAddr1 (*i). It likes this
362  // just fine.
363  //
364  Mac48Address address = *i;
365  hdr.SetAddr1 (address);
366  m_stats.txPerr++;
367  m_stats.txMgt++;
368  m_stats.txMgtBytes += packet->GetSize ();
369  m_parent->SendManagementFrame (packet, hdr);
370  }
371 }
372 void
373 HwmpProtocolMac::InitiatePerr (std::vector<HwmpProtocol::FailedDestination> failedDestinations, std::vector<
374  Mac48Address> receivers)
375 {
376  //All duplicates in PERR are checked here, and there is no reason to
377  //check it at any athoer place
378  {
379  std::vector<Mac48Address>::const_iterator end = receivers.end ();
380  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != end; i++)
381  {
382  bool should_add = true;
383  for (std::vector<Mac48Address>::const_iterator j = m_myPerr.receivers.begin (); j
384  != m_myPerr.receivers.end (); j++)
385  {
386  if ((*i) == (*j))
387  {
388  should_add = false;
389  }
390  }
391  if (should_add)
392  {
393  m_myPerr.receivers.push_back (*i);
394  }
395  }
396  }
397  {
398  std::vector<HwmpProtocol::FailedDestination>::const_iterator end = failedDestinations.end ();
399  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = failedDestinations.begin (); i != end; i++)
400  {
401  bool should_add = true;
402  for (std::vector<HwmpProtocol::FailedDestination>::const_iterator j = m_myPerr.destinations.begin (); j
403  != m_myPerr.destinations.end (); j++)
404  {
405  if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
406  {
407  should_add = false;
408  }
409  }
410  if (should_add)
411  {
412  m_myPerr.destinations.push_back (*i);
413  }
414  }
415  }
416  SendMyPerr ();
417 }
418 void
419 HwmpProtocolMac::SendMyPerr ()
420 {
422  if (m_perrTimer.IsRunning ())
423  {
424  return;
425  }
426  m_perrTimer = Simulator::Schedule (m_protocol->GetPerrMinInterval (), &HwmpProtocolMac::SendMyPerr, this);
427  ForwardPerr (m_myPerr.destinations, m_myPerr.receivers);
428  m_myPerr.destinations.clear ();
429  m_myPerr.receivers.clear ();
430 }
431 uint32_t
433 {
434  return m_parent->GetLinkMetric (peerAddress);
435 }
436 uint16_t
437 HwmpProtocolMac::GetChannelId () const
438 {
439  return m_parent->GetFrequencyChannel ();
440 }
441 HwmpProtocolMac::Statistics::Statistics () :
442  txPreq (0), rxPreq (0), txPrep (0), rxPrep (0), txPerr (0), rxPerr (0), txMgt (0), txMgtBytes (0),
443  rxMgt (0), rxMgtBytes (0), txData (0), txDataBytes (0), rxData (0), rxDataBytes (0)
444 {
445 }
446 void
447 HwmpProtocolMac::Statistics::Print (std::ostream & os) const
448 {
449  os << "<Statistics "
450  "txPreq= \"" << txPreq << "\"" << std::endl <<
451  "txPrep=\"" << txPrep << "\"" << std::endl <<
452  "txPerr=\"" << txPerr << "\"" << std::endl <<
453  "rxPreq=\"" << rxPreq << "\"" << std::endl <<
454  "rxPrep=\"" << rxPrep << "\"" << std::endl <<
455  "rxPerr=\"" << rxPerr << "\"" << std::endl <<
456  "txMgt=\"" << txMgt << "\"" << std::endl <<
457  "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl <<
458  "rxMgt=\"" << rxMgt << "\"" << std::endl <<
459  "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl <<
460  "txData=\"" << txData << "\"" << std::endl <<
461  "txDataBytes=\"" << txDataBytes << "\"" << std::endl <<
462  "rxData=\"" << rxData << "\"" << std::endl <<
463  "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
464 }
465 void
466 HwmpProtocolMac::Report (std::ostream & os) const
467 {
468  os << "<HwmpProtocolMac" << std::endl <<
469  "address =\"" << m_parent->GetAddress () << "\">" << std::endl;
470  m_stats.Print (os);
471  os << "</HwmpProtocolMac>" << std::endl;
472 }
473 void
474 HwmpProtocolMac::ResetStats ()
475 {
476  m_stats = Statistics ();
477 }
478 
479 int64_t
481 {
482  return m_protocol->AssignStreams (stream);
483 }
484 
485 
486 } // namespace dot11s
487 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
bool ReceiveAction(Ptr< Packet > packet, const WifiMacHeader &header)
Receive action management frame.
uint32_t GetLinkMetric(Mac48Address peerAddress) const
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
void SetParent(Ptr< MeshWifiInterfaceMac > parent)
Each plugin must be installed on interface to work.
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 RequestDestination(Mac48Address dest, uint32_t originator_seqno, uint32_t dst_seqno)
Request a destination. If can not send preq immediately - add a destination to existing PREQ generate...
void AddPacketTag(const Tag &tag) const
Definition: packet.cc:868
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
See 7.3.2.97 of 802.11s draft 2.07.
uint32_t GetSize(void) const
Definition: packet.h:620
bool IsRunning(void) const
Definition: event-id.cc:59
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
bool AddInformationElement(Ptr< WifiInformationElement > element)
add an IE, if maxSize has exceeded, returns false
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
Iterator End()
Returns End of the vector.
bool PeekPacketTag(Tag &tag) const
Definition: packet.cc:881
static WifiActionHeader GetWifiActionHeader()
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.
static Mac48Address GetBroadcast(void)
Iterator Begin()
Returns Begin of the vector.
void AddDestinationAddressElement(bool doFlag, bool rfFlag, Mac48Address dest_address, uint32_t dest_seq_number)
an EUI-48 address
Definition: mac48-address.h:41
bool UpdateOutcomingFrame(Ptr< Packet > packet, WifiMacHeader &header, Mac48Address from, Mac48Address to)
Update frame before it will be forwarded down.
int64_t AssignStreams(int64_t stream)
bool ReceiveData(Ptr< Packet > packet, const WifiMacHeader &header)
Receive data frame.
#define NS_LOG_WARN(msg)
Definition: log.h:246
bool RemovePacketTag(Tag &tag)
Definition: packet.cc:874
bool Receive(Ptr< Packet > packet, const WifiMacHeader &header)
Process received frame.
Mesh Control field, see IEEE 802.11s draft 3.0 section 7.1.3.5b.
void Report(std::ostream &) const
Report statistics.
void AddHeader(const Header &header)
Definition: packet.cc:270