A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
hwmp-protocol.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  * Authors: Kirill Andreev <andreev@iitp.ru>
19  */
20 
21 #include "hwmp-protocol.h"
22 #include "hwmp-protocol-mac.h"
23 #include "hwmp-tag.h"
24 #include "hwmp-rtable.h"
25 #include "ns3/log.h"
26 #include "ns3/simulator.h"
27 #include "ns3/packet.h"
28 #include "ns3/mesh-point-device.h"
29 #include "ns3/wifi-net-device.h"
30 #include "ns3/mesh-point-device.h"
31 #include "ns3/mesh-wifi-interface-mac.h"
32 #include "ns3/random-variable-stream.h"
33 #include "airtime-metric.h"
34 #include "ie-dot11s-preq.h"
35 #include "ie-dot11s-prep.h"
36 #include "ns3/trace-source-accessor.h"
37 #include "ie-dot11s-perr.h"
38 
39 NS_LOG_COMPONENT_DEFINE ("HwmpProtocol");
40 
41 namespace ns3 {
42 namespace dot11s {
43 
44 NS_OBJECT_ENSURE_REGISTERED (HwmpProtocol);
45 TypeId
47 {
48  static TypeId tid = TypeId ("ns3::dot11s::HwmpProtocol")
50  .AddConstructor<HwmpProtocol> ()
51  .AddAttribute ( "RandomStart",
52  "Random delay at first proactive PREQ",
53  TimeValue (Seconds (0.1)),
54  MakeTimeAccessor (
56  MakeTimeChecker ()
57  )
58  .AddAttribute ( "MaxQueueSize",
59  "Maximum number of packets we can store when resolving route",
60  UintegerValue (255),
61  MakeUintegerAccessor (
63  MakeUintegerChecker<uint16_t> (1)
64  )
65  .AddAttribute ( "Dot11MeshHWMPmaxPREQretries",
66  "Maximum number of retries before we suppose the destination to be unreachable",
67  UintegerValue (3),
68  MakeUintegerAccessor (
70  MakeUintegerChecker<uint8_t> (1)
71  )
72  .AddAttribute ( "Dot11MeshHWMPnetDiameterTraversalTime",
73  "Time we suppose the packet to go from one edge of the network to another",
74  TimeValue (MicroSeconds (1024*100)),
75  MakeTimeAccessor (
77  MakeTimeChecker ()
78  )
79  .AddAttribute ( "Dot11MeshHWMPpreqMinInterval",
80  "Minimal interval between to successive PREQs",
81  TimeValue (MicroSeconds (1024*100)),
82  MakeTimeAccessor (
84  MakeTimeChecker ()
85  )
86  .AddAttribute ( "Dot11MeshHWMPperrMinInterval",
87  "Minimal interval between to successive PREQs",
88  TimeValue (MicroSeconds (1024*100)),
90  MakeTimeChecker ()
91  )
92  .AddAttribute ( "Dot11MeshHWMPactiveRootTimeout",
93  "Lifetime of poractive routing information",
94  TimeValue (MicroSeconds (1024*5000)),
95  MakeTimeAccessor (
97  MakeTimeChecker ()
98  )
99  .AddAttribute ( "Dot11MeshHWMPactivePathTimeout",
100  "Lifetime of reactive routing information",
101  TimeValue (MicroSeconds (1024*5000)),
102  MakeTimeAccessor (
104  MakeTimeChecker ()
105  )
106  .AddAttribute ( "Dot11MeshHWMPpathToRootInterval",
107  "Interval between two successive proactive PREQs",
108  TimeValue (MicroSeconds (1024*2000)),
109  MakeTimeAccessor (
111  MakeTimeChecker ()
112  )
113  .AddAttribute ( "Dot11MeshHWMPrannInterval",
114  "Lifetime of poractive routing information",
115  TimeValue (MicroSeconds (1024*5000)),
116  MakeTimeAccessor (
118  MakeTimeChecker ()
119  )
120  .AddAttribute ( "MaxTtl",
121  "Initial value of Time To Live field",
122  UintegerValue (32),
123  MakeUintegerAccessor (
125  MakeUintegerChecker<uint8_t> (2)
126  )
127  .AddAttribute ( "UnicastPerrThreshold",
128  "Maximum number of PERR receivers, when we send a PERR as a chain of unicasts",
129  UintegerValue (32),
130  MakeUintegerAccessor (
132  MakeUintegerChecker<uint8_t> (1)
133  )
134  .AddAttribute ( "UnicastPreqThreshold",
135  "Maximum number of PREQ receivers, when we send a PREQ as a chain of unicasts",
136  UintegerValue (1),
137  MakeUintegerAccessor (
139  MakeUintegerChecker<uint8_t> (1)
140  )
141  .AddAttribute ( "UnicastDataThreshold",
142  "Maximum number ofbroadcast receivers, when we send a broadcast as a chain of unicasts",
143  UintegerValue (1),
144  MakeUintegerAccessor (
146  MakeUintegerChecker<uint8_t> (1)
147  )
148  .AddAttribute ( "DoFlag",
149  "Destination only HWMP flag",
150  BooleanValue (false),
151  MakeBooleanAccessor (
153  MakeBooleanChecker ()
154  )
155  .AddAttribute ( "RfFlag",
156  "Reply and forward flag",
157  BooleanValue (true),
158  MakeBooleanAccessor (
160  MakeBooleanChecker ()
161  )
162  .AddTraceSource ( "RouteDiscoveryTime",
163  "The time of route discovery procedure",
166  )
167  ;
168  return tid;
169 }
170 
172  m_dataSeqno (1),
173  m_hwmpSeqno (1),
174  m_preqId (0),
175  m_rtable (CreateObject<HwmpRtable> ()),
176  m_randomStart (Seconds (0.1)),
177  m_maxQueueSize (255),
178  m_dot11MeshHWMPmaxPREQretries (3),
179  m_dot11MeshHWMPnetDiameterTraversalTime (MicroSeconds (1024*100)),
180  m_dot11MeshHWMPpreqMinInterval (MicroSeconds (1024*100)),
181  m_dot11MeshHWMPperrMinInterval (MicroSeconds (1024*100)),
182  m_dot11MeshHWMPactiveRootTimeout (MicroSeconds (1024*5000)),
183  m_dot11MeshHWMPactivePathTimeout (MicroSeconds (1024*5000)),
184  m_dot11MeshHWMPpathToRootInterval (MicroSeconds (1024*2000)),
185  m_dot11MeshHWMPrannInterval (MicroSeconds (1024*5000)),
186  m_isRoot (false),
187  m_maxTtl (32),
188  m_unicastPerrThreshold (32),
189  m_unicastPreqThreshold (1),
190  m_unicastDataThreshold (1),
191  m_doFlag (false),
192  m_rfFlag (false)
193 {
195  m_coefficient = CreateObject<UniformRandomVariable> ();
196 }
197 
199 {
201 }
202 
203 void
205 {
207  if (m_isRoot)
208  {
209  SetRoot ();
210  }
211 }
212 
213 void
215 {
217  for (std::map<Mac48Address, PreqEvent>::iterator i = m_preqTimeouts.begin (); i != m_preqTimeouts.end (); i++)
218  {
219  i->second.preqTimeout.Cancel ();
220  }
222  m_preqTimeouts.clear ();
223  m_lastDataSeqno.clear ();
224  m_hwmpSeqnoMetricDatabase.clear ();
225  m_interfaces.clear ();
226  m_rqueue.clear ();
227  m_rtable = 0;
228  m_mp = 0;
229 }
230 
231 bool
233  uint32_t sourceIface,
234  const Mac48Address source,
235  const Mac48Address destination,
236  Ptr<const Packet> constPacket,
237  uint16_t protocolType, //ethrnet 'Protocol' field
239  )
240 {
241  Ptr <Packet> packet = constPacket->Copy ();
242  HwmpTag tag;
243  if (sourceIface == GetMeshPoint ()->GetIfIndex ())
244  {
245  // packet from level 3
246  if (packet->PeekPacketTag (tag))
247  {
248  NS_FATAL_ERROR ("HWMP tag has come with a packet from upper layer. This must not occur...");
249  }
250  //Filling TAG:
251  if (destination == Mac48Address::GetBroadcast ())
252  {
253  tag.SetSeqno (m_dataSeqno++);
254  }
255  tag.SetTtl (m_maxTtl);
256  }
257  else
258  {
259  if (!packet->RemovePacketTag (tag))
260  {
261  NS_FATAL_ERROR ("HWMP tag is supposed to be here at this point.");
262  }
263  tag.DecrementTtl ();
264  if (tag.GetTtl () == 0)
265  {
267  return false;
268  }
269  }
270  if (destination == Mac48Address::GetBroadcast ())
271  {
273  m_stats.txBytes += packet->GetSize ();
274  //channel IDs where we have already sent broadcast:
275  std::vector<uint16_t> channels;
276  for (HwmpProtocolMacMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin++)
277  {
278  bool shouldSend = true;
279  for (std::vector<uint16_t>::const_iterator chan = channels.begin (); chan != channels.end (); chan++)
280  {
281  if ((*chan) == plugin->second->GetChannelId ())
282  {
283  shouldSend = false;
284  }
285  }
286  if (!shouldSend)
287  {
288  continue;
289  }
290  channels.push_back (plugin->second->GetChannelId ());
291  std::vector<Mac48Address> receivers = GetBroadcastReceivers (plugin->first);
292  for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i++)
293  {
294  Ptr<Packet> packetCopy = packet->Copy ();
295  //
296  // 64-bit Intel valgrind complains about tag.SetAddress (*i). It
297  // likes this just fine.
298  //
299  Mac48Address address = *i;
300  tag.SetAddress (address);
301  packetCopy->AddPacketTag (tag);
302  routeReply (true, packetCopy, source, destination, protocolType, plugin->first);
303  }
304  }
305  }
306  else
307  {
308  return ForwardUnicast (sourceIface, source, destination, packet, protocolType, routeReply, tag.GetTtl ());
309  }
310  return true;
311 }
312 bool
313 HwmpProtocol::RemoveRoutingStuff (uint32_t fromIface, const Mac48Address source,
314  const Mac48Address destination, Ptr<Packet> packet, uint16_t& protocolType)
315 {
316  HwmpTag tag;
317  if (!packet->RemovePacketTag (tag))
318  {
319  NS_FATAL_ERROR ("HWMP tag must exist when packet received from the network");
320  }
321  return true;
322 }
323 bool
324 HwmpProtocol::ForwardUnicast (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
325  Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply, uint32_t ttl)
326 {
327  NS_ASSERT (destination != Mac48Address::GetBroadcast ());
328  HwmpRtable::LookupResult result = m_rtable->LookupReactive (destination);
329  NS_LOG_DEBUG ("Requested src = "<<source<<", dst = "<<destination<<", I am "<<GetAddress ()<<", RA = "<<result.retransmitter);
330  if (result.retransmitter == Mac48Address::GetBroadcast ())
331  {
332  result = m_rtable->LookupProactive ();
333  }
334  HwmpTag tag;
335  tag.SetAddress (result.retransmitter);
336  tag.SetTtl (ttl);
337  //seqno and metric is not used;
338  packet->AddPacketTag (tag);
339  if (result.retransmitter != Mac48Address::GetBroadcast ())
340  {
341  //reply immediately:
342  routeReply (true, packet, source, destination, protocolType, result.ifIndex);
343  m_stats.txUnicast++;
344  m_stats.txBytes += packet->GetSize ();
345  return true;
346  }
347  if (sourceIface != GetMeshPoint ()->GetIfIndex ())
348  {
349  //Start path error procedure:
350  NS_LOG_DEBUG ("Must Send PERR");
351  result = m_rtable->LookupReactiveExpired (destination);
352  //1. Lookup expired reactive path. If exists - start path error
353  // procedure towards a next hop of this path
354  //2. If there was no reactive path, we lookup expired proactive
355  // path. If exist - start path error procedure towards path to
356  // root
357  if (result.retransmitter == Mac48Address::GetBroadcast ())
358  {
359  result = m_rtable->LookupProactiveExpired ();
360  }
361  if (result.retransmitter != Mac48Address::GetBroadcast ())
362  {
363  std::vector<FailedDestination> destinations = m_rtable->GetUnreachableDestinations (result.retransmitter);
364  InitiatePathError (MakePathError (destinations));
365  }
367  return false;
368  }
369  //Request a destination:
370  result = m_rtable->LookupReactiveExpired (destination);
371  if (ShouldSendPreq (destination))
372  {
373  uint32_t originator_seqno = GetNextHwmpSeqno ();
374  uint32_t dst_seqno = 0;
375  if (result.retransmitter != Mac48Address::GetBroadcast ())
376  {
377  dst_seqno = result.seqnum;
378  }
380  for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
381  {
382  i->second->RequestDestination (destination, originator_seqno, dst_seqno);
383  }
384  }
385  QueuedPacket pkt;
386  pkt.pkt = packet;
387  pkt.dst = destination;
388  pkt.src = source;
389  pkt.protocol = protocolType;
390  pkt.reply = routeReply;
391  pkt.inInterface = sourceIface;
392  if (QueuePacket (pkt))
393  {
395  return true;
396  }
397  else
398  {
400  return false;
401  }
402 }
403 void
404 HwmpProtocol::ReceivePreq (IePreq preq, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric)
405 {
406  preq.IncrementMetric (metric);
407  //acceptance cretirea:
408  std::map<Mac48Address, std::pair<uint32_t, uint32_t> >::const_iterator i = m_hwmpSeqnoMetricDatabase.find (
409  preq.GetOriginatorAddress ());
410  bool freshInfo (true);
411  if (i != m_hwmpSeqnoMetricDatabase.end ())
412  {
413  if ((int32_t)(i->second.first - preq.GetOriginatorSeqNumber ()) > 0)
414  {
415  return;
416  }
417  if (i->second.first == preq.GetOriginatorSeqNumber ())
418  {
419  freshInfo = false;
420  if (i->second.second <= preq.GetMetric ())
421  {
422  return;
423  }
424  }
425  }
427  std::make_pair (preq.GetOriginatorSeqNumber (), preq.GetMetric ());
428  NS_LOG_DEBUG ("I am " << GetAddress () << "Accepted preq from address" << from << ", preq:" << preq);
429  std::vector<Ptr<DestinationAddressUnit> > destinations = preq.GetDestinationList ();
430  //Add reactive path to originator:
431  if (
432  (freshInfo) ||
433  (
434  (m_rtable->LookupReactive (preq.GetOriginatorAddress ()).retransmitter == Mac48Address::GetBroadcast ()) ||
435  (m_rtable->LookupReactive (preq.GetOriginatorAddress ()).metric > preq.GetMetric ())
436  )
437  )
438  {
440  preq.GetOriginatorAddress (),
441  from,
442  interface,
443  preq.GetMetric (),
444  MicroSeconds (preq.GetLifetime () * 1024),
445  preq.GetOriginatorSeqNumber ()
446  );
448  }
449  if (
451  (m_rtable->LookupReactive (fromMp).metric > metric)
452  )
453  {
455  fromMp,
456  from,
457  interface,
458  metric,
459  MicroSeconds (preq.GetLifetime () * 1024),
460  preq.GetOriginatorSeqNumber ()
461  );
462  ReactivePathResolved (fromMp);
463  }
464  for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator i = destinations.begin (); i != destinations.end (); i++)
465  {
466  if ((*i)->GetDestinationAddress () == Mac48Address::GetBroadcast ())
467  {
468  //only proactive PREQ contains destination
469  //address as broadcast! Proactive preq MUST
470  //have destination count equal to 1 and
471  //per destination flags DO and RF
472  NS_ASSERT (preq.GetDestCount () == 1);
473  NS_ASSERT (((*i)->IsDo ()) && ((*i)->IsRf ()));
474  //Add proactive path only if it is the better then existed
475  //before
476  if (
477  ((m_rtable->LookupProactive ()).retransmitter == Mac48Address::GetBroadcast ()) ||
478  ((m_rtable->LookupProactive ()).metric > preq.GetMetric ())
479  )
480  {
482  preq.GetMetric (),
483  preq.GetOriginatorAddress (),
484  from,
485  interface,
486  MicroSeconds (preq.GetLifetime () * 1024),
487  preq.GetOriginatorSeqNumber ()
488  );
490  }
491  if (!preq.IsNeedNotPrep ())
492  {
493  SendPrep (
494  GetAddress (),
495  preq.GetOriginatorAddress (),
496  from,
497  (uint32_t)0,
498  preq.GetOriginatorSeqNumber (),
499  GetNextHwmpSeqno (),
500  preq.GetLifetime (),
501  interface
502  );
503  }
504  break;
505  }
506  if ((*i)->GetDestinationAddress () == GetAddress ())
507  {
508  SendPrep (
509  GetAddress (),
510  preq.GetOriginatorAddress (),
511  from,
512  (uint32_t)0,
513  preq.GetOriginatorSeqNumber (),
514  GetNextHwmpSeqno (),
515  preq.GetLifetime (),
516  interface
517  );
519  preq.DelDestinationAddressElement ((*i)->GetDestinationAddress ());
520  continue;
521  }
522  //check if can answer:
523  HwmpRtable::LookupResult result = m_rtable->LookupReactive ((*i)->GetDestinationAddress ());
524  if ((!((*i)->IsDo ())) && (result.retransmitter != Mac48Address::GetBroadcast ()))
525  {
526  //have a valid information and can answer
527  uint32_t lifetime = result.lifetime.GetMicroSeconds () / 1024;
528  if ((lifetime > 0) && ((int32_t)(result.seqnum - (*i)->GetDestSeqNumber ()) >= 0))
529  {
530  SendPrep (
531  (*i)->GetDestinationAddress (),
532  preq.GetOriginatorAddress (),
533  from,
534  result.metric,
535  preq.GetOriginatorSeqNumber (),
536  result.seqnum,
537  lifetime,
538  interface
539  );
540  m_rtable->AddPrecursor ((*i)->GetDestinationAddress (), interface, from,
541  MicroSeconds (preq.GetLifetime () * 1024));
542  if ((*i)->IsRf ())
543  {
544  (*i)->SetFlags (true, false, (*i)->IsUsn ()); //DO = 1, RF = 0
545  }
546  else
547  {
548  preq.DelDestinationAddressElement ((*i)->GetDestinationAddress ());
549  continue;
550  }
551  }
552  }
553  }
554  //check if must retransmit:
555  if (preq.GetDestCount () == 0)
556  {
557  return;
558  }
559  //Forward PREQ to all interfaces:
560  NS_LOG_DEBUG ("I am " << GetAddress () << "retransmitting PREQ:" << preq);
561  for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
562  {
563  i->second->SendPreq (preq);
564  }
565 }
566 void
567 HwmpProtocol::ReceivePrep (IePrep prep, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric)
568 {
569  prep.IncrementMetric (metric);
570  //acceptance cretirea:
571  std::map<Mac48Address, std::pair<uint32_t, uint32_t> >::const_iterator i = m_hwmpSeqnoMetricDatabase.find (
572  prep.GetOriginatorAddress ());
573  bool freshInfo (true);
574  uint32_t sequence = prep.GetDestinationSeqNumber ();
575  if (i != m_hwmpSeqnoMetricDatabase.end ())
576  {
577  if ((int32_t)(i->second.first - sequence) > 0)
578  {
579  return;
580  }
581  if (i->second.first == sequence)
582  {
583  freshInfo = false;
584  }
585  }
586  m_hwmpSeqnoMetricDatabase[prep.GetOriginatorAddress ()] = std::make_pair (sequence, prep.GetMetric ());
587  //update routing info
588  //Now add a path to destination and add precursor to source
589  NS_LOG_DEBUG ("I am " << GetAddress () << ", received prep from " << prep.GetOriginatorAddress () << ", receiver was:" << from);
591  //Add a reactive path only if seqno is fresher or it improves the
592  //metric
593  if (
594  (freshInfo) ||
595  (
596  ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
597  ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).metric > prep.GetMetric ())
598  )
599  )
600  {
602  prep.GetOriginatorAddress (),
603  from,
604  interface,
605  prep.GetMetric (),
606  MicroSeconds (prep.GetLifetime () * 1024),
607  sequence);
608  m_rtable->AddPrecursor (prep.GetDestinationAddress (), interface, from,
609  MicroSeconds (prep.GetLifetime () * 1024));
610  if (result.retransmitter != Mac48Address::GetBroadcast ())
611  {
612  m_rtable->AddPrecursor (prep.GetOriginatorAddress (), interface, result.retransmitter,
613  result.lifetime);
614  }
616  }
617  if (
618  ((m_rtable->LookupReactive (fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
619  ((m_rtable->LookupReactive (fromMp)).metric > metric)
620  )
621  {
623  fromMp,
624  from,
625  interface,
626  metric,
627  MicroSeconds (prep.GetLifetime () * 1024),
628  sequence);
629  ReactivePathResolved (fromMp);
630  }
631  if (prep.GetDestinationAddress () == GetAddress ())
632  {
633  NS_LOG_DEBUG ("I am "<<GetAddress ()<<", resolved "<<prep.GetOriginatorAddress ());
634  return;
635  }
636  if (result.retransmitter == Mac48Address::GetBroadcast ())
637  {
638  return;
639  }
640  //Forward PREP
641  HwmpProtocolMacMap::const_iterator prep_sender = m_interfaces.find (result.ifIndex);
642  NS_ASSERT (prep_sender != m_interfaces.end ());
643  prep_sender->second->SendPrep (prep, result.retransmitter);
644 }
645 void
646 HwmpProtocol::ReceivePerr (std::vector<FailedDestination> destinations, Mac48Address from, uint32_t interface, Mac48Address fromMp)
647 {
648  //Acceptance cretirea:
649  NS_LOG_DEBUG ("I am "<<GetAddress ()<<", received PERR from "<<from);
650  std::vector<FailedDestination> retval;
652  for (unsigned int i = 0; i < destinations.size (); i++)
653  {
654  result = m_rtable->LookupReactiveExpired (destinations[i].destination);
655  if (!(
656  (result.retransmitter != from) ||
657  (result.ifIndex != interface) ||
658  ((int32_t)(result.seqnum - destinations[i].seqnum) > 0)
659  ))
660  {
661  retval.push_back (destinations[i]);
662  }
663  }
664  if (retval.size () == 0)
665  {
666  return;
667  }
668  ForwardPathError (MakePathError (retval));
669 }
670 void
672  Mac48Address src,
673  Mac48Address dst,
674  Mac48Address retransmitter,
675  uint32_t initMetric,
676  uint32_t originatorDsn,
677  uint32_t destinationSN,
678  uint32_t lifetime,
679  uint32_t interface)
680 {
681  IePrep prep;
682  prep.SetHopcount (0);
683  prep.SetTtl (m_maxTtl);
684  prep.SetDestinationAddress (dst);
685  prep.SetDestinationSeqNumber (destinationSN);
686  prep.SetLifetime (lifetime);
687  prep.SetMetric (initMetric);
688  prep.SetOriginatorAddress (src);
689  prep.SetOriginatorSeqNumber (originatorDsn);
690  HwmpProtocolMacMap::const_iterator prep_sender = m_interfaces.find (interface);
691  NS_ASSERT (prep_sender != m_interfaces.end ());
692  prep_sender->second->SendPrep (prep, retransmitter);
694 }
695 bool
697 {
698  m_mp = mp;
699  std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces ();
700  for (std::vector<Ptr<NetDevice> >::const_iterator i = interfaces.begin (); i != interfaces.end (); i++)
701  {
702  // Checking for compatible net device
703  Ptr<WifiNetDevice> wifiNetDev = (*i)->GetObject<WifiNetDevice> ();
704  if (wifiNetDev == 0)
705  {
706  return false;
707  }
708  Ptr<MeshWifiInterfaceMac> mac = wifiNetDev->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
709  if (mac == 0)
710  {
711  return false;
712  }
713  // Installing plugins:
714  Ptr<HwmpProtocolMac> hwmpMac = Create<HwmpProtocolMac> (wifiNetDev->GetIfIndex (), this);
715  m_interfaces[wifiNetDev->GetIfIndex ()] = hwmpMac;
716  mac->InstallPlugin (hwmpMac);
717  //Installing airtime link metric:
718  Ptr<AirtimeLinkMetricCalculator> metric = CreateObject <AirtimeLinkMetricCalculator> ();
720  }
721  mp->SetRoutingProtocol (this);
722  // Mesh point aggregates all installed protocols
723  mp->AggregateObject (this);
724  m_address = Mac48Address::ConvertFrom (mp->GetAddress ()); // address;
725  return true;
726 }
727 void
728 HwmpProtocol::PeerLinkStatus (Mac48Address meshPointAddress, Mac48Address peerAddress, uint32_t interface, bool status)
729 {
730  if (status)
731  {
732  return;
733  }
734  std::vector<FailedDestination> destinations = m_rtable->GetUnreachableDestinations (peerAddress);
735  InitiatePathError (MakePathError (destinations));
736 }
737 void
738 HwmpProtocol::SetNeighboursCallback (Callback<std::vector<Mac48Address>, uint32_t> cb)
739 {
741 }
742 bool
744 {
745  if (source == GetAddress ())
746  {
747  return true;
748  }
749  std::map<Mac48Address, uint32_t,std::less<Mac48Address> >::const_iterator i = m_lastDataSeqno.find (source);
750  if (i == m_lastDataSeqno.end ())
751  {
752  m_lastDataSeqno[source] = seqno;
753  }
754  else
755  {
756  if ((int32_t)(i->second - seqno) >= 0)
757  {
758  return true;
759  }
760  m_lastDataSeqno[source] = seqno;
761  }
762  return false;
763 }
765 HwmpProtocol::MakePathError (std::vector<FailedDestination> destinations)
766 {
767  PathError retval;
768  //HwmpRtable increments a sequence number as written in 11B.9.7.2
769  retval.receivers = GetPerrReceivers (destinations);
770  if (retval.receivers.size () == 0)
771  {
772  return retval;
773  }
775  for (unsigned int i = 0; i < destinations.size (); i++)
776  {
777  retval.destinations.push_back (destinations[i]);
778  m_rtable->DeleteReactivePath (destinations[i].destination);
779  }
780  return retval;
781 }
782 void
784 {
785  for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
786  {
787  std::vector<Mac48Address> receivers_for_interface;
788  for (unsigned int j = 0; j < perr.receivers.size (); j++)
789  {
790  if (i->first == perr.receivers[j].first)
791  {
792  receivers_for_interface.push_back (perr.receivers[j].second);
793  }
794  }
795  i->second->InitiatePerr (perr.destinations, receivers_for_interface);
796  }
797 }
798 void
800 {
801  for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
802  {
803  std::vector<Mac48Address> receivers_for_interface;
804  for (unsigned int j = 0; j < perr.receivers.size (); j++)
805  {
806  if (i->first == perr.receivers[j].first)
807  {
808  receivers_for_interface.push_back (perr.receivers[j].second);
809  }
810  }
811  i->second->ForwardPerr (perr.destinations, receivers_for_interface);
812  }
813 }
814 
815 std::vector<std::pair<uint32_t, Mac48Address> >
816 HwmpProtocol::GetPerrReceivers (std::vector<FailedDestination> failedDest)
817 {
819  for (unsigned int i = 0; i < failedDest.size (); i++)
820  {
821  HwmpRtable::PrecursorList precursors = m_rtable->GetPrecursors (failedDest[i].destination);
822  m_rtable->DeleteReactivePath (failedDest[i].destination);
823  m_rtable->DeleteProactivePath (failedDest[i].destination);
824  for (unsigned int j = 0; j < precursors.size (); j++)
825  {
826  retval.push_back (precursors[j]);
827  }
828  }
829  //Check if we have dublicates in retval and precursors:
830  for (unsigned int i = 0; i < retval.size (); i++)
831  {
832  for (unsigned int j = i+1; j < retval.size (); j++)
833  {
834  if (retval[i].second == retval[j].second)
835  {
836  retval.erase (retval.begin () + j);
837  }
838  }
839  }
840  return retval;
841 }
842 std::vector<Mac48Address>
843 HwmpProtocol::GetPreqReceivers (uint32_t interface)
844 {
845  std::vector<Mac48Address> retval;
847  {
848  retval = m_neighboursCallback (interface);
849  }
850  if ((retval.size () >= m_unicastPreqThreshold) || (retval.size () == 0))
851  {
852  retval.clear ();
853  retval.push_back (Mac48Address::GetBroadcast ());
854  }
855  return retval;
856 }
857 std::vector<Mac48Address>
859 {
860  std::vector<Mac48Address> retval;
862  {
863  retval = m_neighboursCallback (interface);
864  }
865  if ((retval.size () >= m_unicastDataThreshold) || (retval.size () == 0))
866  {
867  retval.clear ();
868  retval.push_back (Mac48Address::GetBroadcast ());
869  }
870  return retval;
871 }
872 
873 bool
875 {
876  if (m_rqueue.size () > m_maxQueueSize)
877  {
878  return false;
879  }
880  m_rqueue.push_back (packet);
881  return true;
882 }
883 
886 {
887  QueuedPacket retval;
888  retval.pkt = 0;
889  for (std::vector<QueuedPacket>::iterator i = m_rqueue.begin (); i != m_rqueue.end (); i++)
890  {
891  if ((*i).dst == dst)
892  {
893  retval = (*i);
894  m_rqueue.erase (i);
895  break;
896  }
897  }
898  return retval;
899 }
900 
903 {
904  QueuedPacket retval;
905  retval.pkt = 0;
906  if (m_rqueue.size () != 0)
907  {
908  retval = m_rqueue[0];
909  m_rqueue.erase (m_rqueue.begin ());
910  }
911  return retval;
912 }
913 
914 void
916 {
917  std::map<Mac48Address, PreqEvent>::iterator i = m_preqTimeouts.find (dst);
918  if (i != m_preqTimeouts.end ())
919  {
920  m_routeDiscoveryTimeCallback (Simulator::Now () - i->second.whenScheduled);
921  }
922 
925  //Send all packets stored for this destination
926  QueuedPacket packet = DequeueFirstPacketByDst (dst);
927  while (packet.pkt != 0)
928  {
929  //set RA tag for retransmitter:
930  HwmpTag tag;
931  packet.pkt->RemovePacketTag (tag);
932  tag.SetAddress (result.retransmitter);
933  packet.pkt->AddPacketTag (tag);
934  m_stats.txUnicast++;
935  m_stats.txBytes += packet.pkt->GetSize ();
936  packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
937 
938  packet = DequeueFirstPacketByDst (dst);
939  }
940 }
941 void
943 {
944  //send all packets to root
947  QueuedPacket packet = DequeueFirstPacket ();
948  while (packet.pkt != 0)
949  {
950  //set RA tag for retransmitter:
951  HwmpTag tag;
952  if (!packet.pkt->RemovePacketTag (tag))
953  {
954  NS_FATAL_ERROR ("HWMP tag must be present at this point");
955  }
956  tag.SetAddress (result.retransmitter);
957  packet.pkt->AddPacketTag (tag);
958  m_stats.txUnicast++;
959  m_stats.txBytes += packet.pkt->GetSize ();
960  packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
961 
962  packet = DequeueFirstPacket ();
963  }
964 }
965 
966 bool
968 {
969  std::map<Mac48Address, PreqEvent>::const_iterator i = m_preqTimeouts.find (dst);
970  if (i == m_preqTimeouts.end ())
971  {
972  m_preqTimeouts[dst].preqTimeout = Simulator::Schedule (
974  &HwmpProtocol::RetryPathDiscovery, this, dst, 1);
975  m_preqTimeouts[dst].whenScheduled = Simulator::Now ();
976  return true;
977  }
978  return false;
979 }
980 void
982 {
984  if (result.retransmitter == Mac48Address::GetBroadcast ())
985  {
986  result = m_rtable->LookupProactive ();
987  }
988  if (result.retransmitter != Mac48Address::GetBroadcast ())
989  {
990  std::map<Mac48Address, PreqEvent>::iterator i = m_preqTimeouts.find (dst);
991  NS_ASSERT (i != m_preqTimeouts.end ());
992  m_preqTimeouts.erase (i);
993  return;
994  }
995  if (numOfRetry > m_dot11MeshHWMPmaxPREQretries)
996  {
997  QueuedPacket packet = DequeueFirstPacketByDst (dst);
998  //purge queue and delete entry from retryDatabase
999  while (packet.pkt != 0)
1000  {
1002  packet.reply (false, packet.pkt, packet.src, packet.dst, packet.protocol, HwmpRtable::MAX_METRIC);
1003  packet = DequeueFirstPacketByDst (dst);
1004  }
1005  std::map<Mac48Address, PreqEvent>::iterator i = m_preqTimeouts.find (dst);
1006  NS_ASSERT (i != m_preqTimeouts.end ());
1007  m_routeDiscoveryTimeCallback (Simulator::Now () - i->second.whenScheduled);
1008  m_preqTimeouts.erase (i);
1009  return;
1010  }
1011  numOfRetry++;
1012  uint32_t originator_seqno = GetNextHwmpSeqno ();
1013  uint32_t dst_seqno = m_rtable->LookupReactiveExpired (dst).seqnum;
1014  for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1015  {
1016  i->second->RequestDestination (dst, originator_seqno, dst_seqno);
1017  }
1018  m_preqTimeouts[dst].preqTimeout = Simulator::Schedule (
1019  Time ((2 * (numOfRetry + 1)) * m_dot11MeshHWMPnetDiameterTraversalTime),
1020  &HwmpProtocol::RetryPathDiscovery, this, dst, numOfRetry);
1021 }
1022 //Proactive PREQ routines:
1023 void
1025 {
1026  Time randomStart = Seconds (m_coefficient->GetValue ());
1028  NS_LOG_DEBUG ("ROOT IS: " << m_address);
1029  m_isRoot = true;
1030 }
1031 void
1033 {
1035 }
1036 void
1038 {
1039  IePreq preq;
1040  //By default: must answer
1041  preq.SetHopcount (0);
1042  preq.SetTTL (m_maxTtl);
1044  //\attention: do not forget to set originator address, sequence
1045  //number and preq ID in HWMP-MAC plugin
1047  preq.SetOriginatorAddress (GetAddress ());
1048  preq.SetPreqID (GetNextPreqId ());
1050  for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1051  {
1052  i->second->SendPreq (preq);
1053  }
1055 }
1056 bool
1058 {
1059  return m_doFlag;
1060 }
1061 bool
1063 {
1064  return m_rfFlag;
1065 }
1066 Time
1068 {
1070 }
1071 Time
1073 {
1075 }
1076 uint8_t
1078 {
1079  return m_maxTtl;
1080 }
1081 uint32_t
1083 {
1084  m_preqId++;
1085  return m_preqId;
1086 }
1087 uint32_t
1089 {
1090  m_hwmpSeqno++;
1091  return m_hwmpSeqno;
1092 }
1093 uint32_t
1095 {
1097 }
1098 uint8_t
1100 {
1101  return m_unicastPerrThreshold;
1102 }
1105 {
1106  return m_address;
1107 }
1108 //Statistics:
1110  txUnicast (0),
1111  txBroadcast (0),
1112  txBytes (0),
1113  droppedTtl (0),
1114  totalQueued (0),
1115  totalDropped (0),
1116  initiatedPreq (0),
1117  initiatedPrep (0),
1118  initiatedPerr (0)
1119 {
1120 }
1121 void HwmpProtocol::Statistics::Print (std::ostream & os) const
1122 {
1123  os << "<Statistics "
1124  "txUnicast=\"" << txUnicast << "\" "
1125  "txBroadcast=\"" << txBroadcast << "\" "
1126  "txBytes=\"" << txBytes << "\" "
1127  "droppedTtl=\"" << droppedTtl << "\" "
1128  "totalQueued=\"" << totalQueued << "\" "
1129  "totalDropped=\"" << totalDropped << "\" "
1130  "initiatedPreq=\"" << initiatedPreq << "\" "
1131  "initiatedPrep=\"" << initiatedPrep << "\" "
1132  "initiatedPerr=\"" << initiatedPerr << "\"/>" << std::endl;
1133 }
1134 void
1135 HwmpProtocol::Report (std::ostream & os) const
1136 {
1137  os << "<Hwmp "
1138  "address=\"" << m_address << "\"" << std::endl <<
1139  "maxQueueSize=\"" << m_maxQueueSize << "\"" << std::endl <<
1140  "Dot11MeshHWMPmaxPREQretries=\"" << (uint16_t)m_dot11MeshHWMPmaxPREQretries << "\"" << std::endl <<
1141  "Dot11MeshHWMPnetDiameterTraversalTime=\"" << m_dot11MeshHWMPnetDiameterTraversalTime.GetSeconds () << "\"" << std::endl <<
1142  "Dot11MeshHWMPpreqMinInterval=\"" << m_dot11MeshHWMPpreqMinInterval.GetSeconds () << "\"" << std::endl <<
1143  "Dot11MeshHWMPperrMinInterval=\"" << m_dot11MeshHWMPperrMinInterval.GetSeconds () << "\"" << std::endl <<
1144  "Dot11MeshHWMPactiveRootTimeout=\"" << m_dot11MeshHWMPactiveRootTimeout.GetSeconds () << "\"" << std::endl <<
1145  "Dot11MeshHWMPactivePathTimeout=\"" << m_dot11MeshHWMPactivePathTimeout.GetSeconds () << "\"" << std::endl <<
1146  "Dot11MeshHWMPpathToRootInterval=\"" << m_dot11MeshHWMPpathToRootInterval.GetSeconds () << "\"" << std::endl <<
1147  "Dot11MeshHWMPrannInterval=\"" << m_dot11MeshHWMPrannInterval.GetSeconds () << "\"" << std::endl <<
1148  "isRoot=\"" << m_isRoot << "\"" << std::endl <<
1149  "maxTtl=\"" << (uint16_t)m_maxTtl << "\"" << std::endl <<
1150  "unicastPerrThreshold=\"" << (uint16_t)m_unicastPerrThreshold << "\"" << std::endl <<
1151  "unicastPreqThreshold=\"" << (uint16_t)m_unicastPreqThreshold << "\"" << std::endl <<
1152  "unicastDataThreshold=\"" << (uint16_t)m_unicastDataThreshold << "\"" << std::endl <<
1153  "doFlag=\"" << m_doFlag << "\"" << std::endl <<
1154  "rfFlag=\"" << m_rfFlag << "\">" << std::endl;
1155  m_stats.Print (os);
1156  for (HwmpProtocolMacMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin++)
1157  {
1158  plugin->second->Report (os);
1159  }
1160  os << "</Hwmp>" << std::endl;
1161 }
1162 void
1164 {
1165  m_stats = Statistics ();
1166  for (HwmpProtocolMacMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin++)
1167  {
1168  plugin->second->ResetStats ();
1169  }
1170 }
1171 
1172 int64_t
1174 {
1175  NS_LOG_FUNCTION (this << stream);
1176  m_coefficient->SetStream (stream);
1177  return 1;
1178 }
1179 
1181  pkt (0),
1182  protocol (0),
1183  inInterface (0)
1184 {
1185 }
1186 } // namespace dot11s
1187 } // namespace ns3