A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
mesh-wifi-interface-mac.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 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  * Pavel Boyko <boyko@iitp.ru>
20  */
21 
22 #include "ns3/mesh-wifi-interface-mac.h"
23 #include "ns3/mesh-wifi-beacon.h"
24 #include "ns3/log.h"
25 #include "ns3/boolean.h"
26 #include "ns3/wifi-phy.h"
27 #include "ns3/dcf-manager.h"
28 #include "ns3/mac-rx-middle.h"
29 #include "ns3/mac-low.h"
30 #include "ns3/dca-txop.h"
31 #include "ns3/random-variable-stream.h"
32 #include "ns3/simulator.h"
33 #include "ns3/yans-wifi-phy.h"
34 #include "ns3/pointer.h"
35 #include "ns3/double.h"
36 #include "ns3/trace-source-accessor.h"
37 #include "ns3/qos-tag.h"
38 
39 NS_LOG_COMPONENT_DEFINE ("MeshWifiInterfaceMac");
40 
41 namespace ns3 {
42 
43 NS_OBJECT_ENSURE_REGISTERED (MeshWifiInterfaceMac);
44 
45 TypeId
47 {
48  static TypeId tid = TypeId ("ns3::MeshWifiInterfaceMac")
50  .AddConstructor<MeshWifiInterfaceMac> ()
51  .AddAttribute ( "BeaconInterval",
52  "Beacon Interval",
53  TimeValue (Seconds (0.5)),
54 
55  MakeTimeAccessor (
57  MakeTimeChecker ()
58  )
59  .AddAttribute ( "RandomStart",
60  "Window when beacon generating starts (uniform random) in seconds",
61  TimeValue (Seconds (0.5)),
62  MakeTimeAccessor (
64  MakeTimeChecker ()
65  )
66  .AddAttribute ( "BeaconGeneration",
67  "Enable/Disable Beaconing.",
68  BooleanValue (true),
69  MakeBooleanAccessor (
71  MakeBooleanChecker ()
72  )
73  ;
74  return tid;
75 }
77  m_standard (WIFI_PHY_STANDARD_80211a)
78 {
79  NS_LOG_FUNCTION (this);
80 
81  // Let the lower layers know that we are acting as a mesh node
82  SetTypeOfStation (MESH);
83  m_coefficient = CreateObject<UniformRandomVariable> ();
84 }
86 {
87  NS_LOG_FUNCTION (this);
88 }
89 //-----------------------------------------------------------------------------
90 // WifiMac inherited
91 //-----------------------------------------------------------------------------
92 void
94 {
95  NS_LOG_FUNCTION (this << packet << to << from);
96  ForwardDown (packet, from, to);
97 }
98 void
100 {
101  NS_LOG_FUNCTION (this << packet << to);
102  ForwardDown (packet, m_low->GetAddress (), to);
103 }
104 bool
105 MeshWifiInterfaceMac::SupportsSendFrom () const
106 {
107  return true;
108 }
109 void
111 {
112  NS_LOG_FUNCTION (this);
114 
115  // The approach taken here is that, from the point of view of a mesh
116  // node, the link is always up, so we immediately invoke the
117  // callback if one is set
118  linkUp ();
119 }
120 void
122 {
123  NS_LOG_FUNCTION (this);
124  m_plugins.clear ();
126 
128 }
129 void
131 {
133  if (m_beaconEnable)
134  {
135  Time randomStart = Seconds (m_coefficient->GetValue ());
136  // Now start sending beacons after some random delay (to avoid collisions)
139  m_tbtt = Simulator::Now () + randomStart;
140  }
141  else
142  {
143  // stop sending beacons
145  }
146 }
147 
148 int64_t
150 {
151  NS_LOG_FUNCTION (this << stream);
152  int64_t currentStream = stream;
153  m_coefficient->SetStream (currentStream++);
154  for (PluginList::const_iterator i = m_plugins.begin (); i < m_plugins.end (); i++)
155  {
156  currentStream += (*i)->AssignStreams (currentStream);
157  }
158  return (currentStream - stream);
159 }
160 
161 //-----------------------------------------------------------------------------
162 // Plugins
163 //-----------------------------------------------------------------------------
164 void
166 {
167  NS_LOG_FUNCTION (this);
168 
169  plugin->SetParent (this);
170  m_plugins.push_back (plugin);
171 }
172 //-----------------------------------------------------------------------------
173 // Switch channels
174 //-----------------------------------------------------------------------------
175 uint16_t
177 {
178  NS_LOG_FUNCTION (this);
179  NS_ASSERT (m_phy != 0); // need PHY to set/get channel
180 
181  Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
182  if (phy != 0)
183  {
184  return phy->GetChannelNumber ();
185  }
186  else
187  {
188  return 0;
189  }
190 }
191 void
193 {
194  NS_LOG_FUNCTION (this);
195  NS_ASSERT (m_phy != 0); // need PHY to set/get channel
196  /* TODO
197  *
198  * Correct channel switching is:
199  *
200  * 1. Interface down, e.g. to stop packets from layer 3
201  * 2. Wait before all output queues will be empty
202  * 3. Switch PHY channel
203  * 4. Interface up
204  *
205  * Now we use dirty channel switch -- just change frequency
206  */
207  Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
208  phy->SetChannelNumber (new_id);
209  // Don't know NAV on new channel
210  m_dcfManager->NotifyNavResetNow (Seconds (0));
211 }
212 //-----------------------------------------------------------------------------
213 // Forward frame down
214 //-----------------------------------------------------------------------------
215 void
217 {
218  // copy packet to allow modifications
219  Ptr<Packet> packet = const_packet->Copy ();
220  WifiMacHeader hdr;
221  hdr.SetTypeData ();
222  hdr.SetAddr2 (GetAddress ());
223  hdr.SetAddr3 (to);
224  hdr.SetAddr4 (from);
225  hdr.SetDsFrom ();
226  hdr.SetDsTo ();
227  // Fill QoS fields:
228  hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
229  hdr.SetQosNoEosp ();
230  hdr.SetQosNoAmsdu ();
231  hdr.SetQosTxopLimit (0);
232  // Address 1 is unknwon here. Routing plugin is responsible to correctly set it.
233  hdr.SetAddr1 (Mac48Address ());
234  // Filter packet through all installed plugins
235  for (PluginList::const_iterator i = m_plugins.end () - 1; i != m_plugins.begin () - 1; i--)
236  {
237  bool drop = !((*i)->UpdateOutcomingFrame (packet, hdr, from, to));
238  if (drop)
239  {
240  return; // plugin drops frame
241  }
242  }
243  // Assert that address1 is set. Assert will fail e.g. if there is no installed routing plugin.
244  NS_ASSERT (hdr.GetAddr1 () != Mac48Address ());
245  // Queue frame
246  if (m_stationManager->IsBrandNew (hdr.GetAddr1 ()))
247  {
248  // in adhoc mode, we assume that every destination
249  // supports all the rates we support.
250  for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
251  {
252  m_stationManager->AddSupportedMode (hdr.GetAddr1 (), m_phy->GetMode (i));
253  }
254  m_stationManager->RecordDisassociated (hdr.GetAddr1 ());
255  }
256  //Classify: application sets a tag, which is removed here
257  // Get Qos tag:
258  AcIndex ac = AC_BE;
259  QosTag tag;
260  if (packet->RemovePacketTag (tag))
261  {
262  hdr.SetType (WIFI_MAC_QOSDATA);
263  hdr.SetQosTid (tag.GetTid ());
264  //Aftre setting type DsFrom and DsTo fields are reset.
265  hdr.SetDsFrom ();
266  hdr.SetDsTo ();
267  ac = QosUtilsMapTidToAc (tag.GetTid ());
268  }
269  m_stats.sentFrames++;
270  m_stats.sentBytes += packet->GetSize ();
271  NS_ASSERT (m_edca.find (ac) != m_edca.end ());
272  m_edca[ac]->Queue (packet, hdr);
273 }
274 void
276 {
277  //Filter management frames:
278  WifiMacHeader header = hdr;
279  for (PluginList::const_iterator i = m_plugins.end () - 1; i != m_plugins.begin () - 1; i--)
280  {
281  bool drop = !((*i)->UpdateOutcomingFrame (packet, header, Mac48Address (), Mac48Address ()));
282  if (drop)
283  {
284  return; // plugin drops frame
285  }
286  }
287  m_stats.sentFrames++;
288  m_stats.sentBytes += packet->GetSize ();
289  if ((m_edca.find (AC_VO) == m_edca.end ()) || (m_edca.find (AC_BK) == m_edca.end ()))
290  {
291  NS_FATAL_ERROR ("Voice or Background queue is not set up!");
292  }
293  /*
294  * When we send a management frame - it is better to enqueue it to
295  * priority queue. But when we send a broadcast management frame,
296  * like PREQ, little MinCw value may cause collisions during
297  * retransmissions (two neighbor stations may choose the same window
298  * size, and two packets will be collided). So, broadcast management
299  * frames go to BK queue.
300  */
301  if (hdr.GetAddr1 () != Mac48Address::GetBroadcast ())
302  {
303  m_edca[AC_VO]->Queue (packet, header);
304  }
305  else
306  {
307  m_edca[AC_BK]->Queue (packet, header);
308  }
309 }
312 {
313  // set the set of supported rates and make sure that we indicate
314  // the Basic Rate set in this set of supported rates.
315  SupportedRates rates;
316  for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
317  {
318  WifiMode mode = m_phy->GetMode (i);
319  rates.AddSupportedRate (mode.GetDataRate ());
320  }
321  // set the basic rates
322  for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
323  {
324  WifiMode mode = m_stationManager->GetBasicMode (j);
325  rates.SetBasicRate (mode.GetDataRate ());
326  }
327  return rates;
328 }
329 bool
331 {
332  for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
333  {
334  WifiMode mode = m_stationManager->GetBasicMode (i);
335  if (!rates.IsSupportedRate (mode.GetDataRate ()))
336  {
337  return false;
338  }
339  }
340  return true;
341 }
342 //-----------------------------------------------------------------------------
343 // Beacons
344 //-----------------------------------------------------------------------------
345 void
347 {
348  NS_LOG_FUNCTION (this << interval);
349  m_randomStart = interval;
350 }
351 void
353 {
354  NS_LOG_FUNCTION (this << interval);
355  m_beaconInterval = interval;
356 }
357 Time
359 {
360  return m_beaconInterval;
361 }
362 void
364 {
365  NS_LOG_FUNCTION (this << enable);
366  m_beaconEnable = enable;
367 }
368 bool
370 {
371  return m_beaconSendEvent.IsRunning ();
372 }
373 Time
375 {
376  return m_tbtt;
377 }
378 void
380 {
381  // User of ShiftTbtt () must take care don't shift it to the past
382  NS_ASSERT (GetTbtt () + shift > Simulator::Now ());
383 
384  m_tbtt += shift;
385  // Shift scheduled event
388  this);
389 }
390 void
392 {
395 }
396 void
398 {
399  NS_LOG_FUNCTION (this);
400  NS_LOG_DEBUG (GetAddress () << " is sending beacon");
401 
403 
404  // Form & send beacon
406 
407  // Ask all plugins to add their specific information elements to beacon
408  for (PluginList::const_iterator i = m_plugins.begin (); i != m_plugins.end (); ++i)
409  {
410  (*i)->UpdateBeacon (beacon);
411  }
412  m_dca->Queue (beacon.CreatePacket (), beacon.CreateHeader (GetAddress (), GetMeshPointAddress ()));
413 
415 }
416 void
418 {
419  // Process beacon
420  if ((hdr->GetAddr1 () != GetAddress ()) && (hdr->GetAddr1 () != Mac48Address::GetBroadcast ()))
421  {
422  return;
423  }
424  if (hdr->IsBeacon ())
425  {
426  m_stats.recvBeacons++;
427  MgtBeaconHeader beacon_hdr;
428 
429  packet->PeekHeader (beacon_hdr);
430 
431  NS_LOG_DEBUG ("Beacon received from " << hdr->GetAddr2 () << " I am " << GetAddress () << " at "
432  << Simulator::Now ().GetMicroSeconds () << " microseconds");
433 
434  // update supported rates
435  if (beacon_hdr.GetSsid ().IsEqual (GetSsid ()))
436  {
437  SupportedRates rates = beacon_hdr.GetSupportedRates ();
438 
439  for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
440  {
441  WifiMode mode = m_phy->GetMode (i);
442  if (rates.IsSupportedRate (mode.GetDataRate ()))
443  {
444  m_stationManager->AddSupportedMode (hdr->GetAddr2 (), mode);
445  if (rates.IsBasicRate (mode.GetDataRate ()))
446  {
447  m_stationManager->AddBasicMode (mode);
448  }
449  }
450  }
451  }
452  }
453  else
454  {
455  m_stats.recvBytes += packet->GetSize ();
456  m_stats.recvFrames++;
457  }
458  // Filter frame through all installed plugins
459  for (PluginList::iterator i = m_plugins.begin (); i != m_plugins.end (); ++i)
460  {
461  bool drop = !((*i)->Receive (packet, *hdr));
462  if (drop)
463  {
464  return; // plugin drops frame
465  }
466  }
467  // Check if QoS tag exists and add it:
468  if (hdr->IsQosData ())
469  {
470  packet->AddPacketTag (QosTag (hdr->GetQosTid ()));
471  }
472  // Forward data up
473  if (hdr->IsData ())
474  {
475  ForwardUp (packet, hdr->GetAddr4 (), hdr->GetAddr3 ());
476  }
477 
478  // We don't bother invoking RegularWifiMac::Receive() here, because
479  // we've explicitly handled all the frames we care about. This is in
480  // contrast to most classes which derive from RegularWifiMac.
481 }
482 uint32_t
483 MeshWifiInterfaceMac::GetLinkMetric (Mac48Address peerAddress)
484 {
485  uint32_t metric = 1;
486  if (!m_linkMetricCallback.IsNull ())
487  {
488  metric = m_linkMetricCallback (peerAddress, this);
489  }
490  return metric;
491 }
492 void
493 MeshWifiInterfaceMac::SetLinkMetricCallback (Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > cb)
494 {
495  m_linkMetricCallback = cb;
496 }
497 void
498 MeshWifiInterfaceMac::SetMeshPointAddress (Mac48Address a)
499 {
500  m_mpAddress = a;
501 }
502 Mac48Address
503 MeshWifiInterfaceMac::GetMeshPointAddress () const
504 {
505  return m_mpAddress;
506 }
507 //Statistics:
508 MeshWifiInterfaceMac::Statistics::Statistics () :
509  recvBeacons (0), sentFrames (0), sentBytes (0), recvFrames (0), recvBytes (0)
510 {
511 }
512 void
513 MeshWifiInterfaceMac::Statistics::Print (std::ostream & os) const
514 {
515  os << "<Statistics "
516  // TODO txBeacons
517  "rxBeacons=\"" << recvBeacons << "\" "
518  "txFrames=\"" << sentFrames << "\" "
519  "txBytes=\"" << sentBytes << "\" "
520  "rxFrames=\"" << recvFrames << "\" "
521  "rxBytes=\"" << recvBytes << "\"/>" << std::endl;
522 }
523 void
524 MeshWifiInterfaceMac::Report (std::ostream & os) const
525 {
526  os << "<Interface "
527  "BeaconInterval=\"" << GetBeaconInterval ().GetSeconds () << "\" "
528  "Channel=\"" << GetFrequencyChannel () << "\" "
529  "Address = \"" << GetAddress () << "\">" << std::endl;
530  m_stats.Print (os);
531  os << "</Interface>" << std::endl;
532 }
533 void
534 MeshWifiInterfaceMac::ResetStats ()
535 {
536  m_stats = Statistics ();
537 }
538 
539 void
541 {
543  m_standard = standard;
544 
545  // We use the single DCF provided by WifiMac for the purpose of
546  // Beacon transmission. For this we need to reconfigure the channel
547  // access parameters slightly, and do so here.
548  m_dca->SetMinCw (0);
549  m_dca->SetMaxCw (0);
550  m_dca->SetAifsn (1);
551 }
553 MeshWifiInterfaceMac::GetPhyStandard () const
554 {
555  return m_standard;
556 }
557 } // namespace ns3
558 
keep track of time unit.
Definition: nstime.h:149
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
Hold a bool native type.
Definition: boolean.h:38
Ptr< UniformRandomVariable > m_coefficient
Add randomness to beacon generation.
bool m_beaconEnable
whether beaconing is enabled
virtual uint32_t GetNModes(void) const =0
SupportedRates GetSupportedRates() const
void AddPacketTag(const Tag &tag) const
Definition: packet.cc:868
bool CheckSupportedRates(SupportedRates rates) const
virtual void DoDispose()
Real d-tor.
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
uint32_t GetSize(void) const
Definition: packet.h:620
uint16_t GetChannelNumber() const
Return current channel number, see SetChannelNumber()
static void Cancel(const EventId &id)
Definition: simulator.cc:267
void SetChannelNumber(uint16_t id)
Set channel number.
bool IsRunning(void) const
Definition: event-id.cc:59
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
void SwitchFrequencyChannel(uint16_t new_id)
Switch channel.
virtual Ssid GetSsid(void) const
The Supported Rates Information ElementThis class knows how to serialise and deserialise the Supporte...
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:88
WifiPhyStandard m_standard
Current PHY standard: needed to configure metric.
virtual void Enqueue(Ptr< const Packet > packet, Mac48Address to, Mac48Address from)
Time GetTbtt() const
Next beacon frame time.
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
void SendManagementFrame(Ptr< Packet > frame, const WifiMacHeader &hdr)
To be used by plugins sending management frames.
void NotifyNavResetNow(Time duration)
Definition: dcf-manager.cc:805
void ScheduleNextBeacon()
Schedule next beacon.
double GetSeconds(void) const
Definition: nstime.h:262
base class for all MAC-level wifi objects.This class encapsulates all the low-level MAC functionality...
void SetTypeOfStation(TypeOfStation type)
int64_t GetMicroSeconds(void) const
Definition: nstime.h:279
hold objects of type ns3::Time
Definition: nstime.h:700
Ptr< DcaTxop > m_dca
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Definition: qos-utils.cc:27
static Mac48Address GetBroadcast(void)
uint16_t GetFrequencyChannel() const
Current channel Id.
virtual void FinishConfigureStandard(enum WifiPhyStandard standard)
bool GetBeaconGeneration() const
Get current beaconing status.
PluginList m_plugins
List of all installed plugins.
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
uint32_t PeekHeader(Header &header) const
Definition: packet.cc:294
Mac48Address m_mpAddress
Mesh point address.
virtual void SetLinkUpCallback(Callback< void > linkUp)
virtual void DoDispose()
802.11 PHY layer modelThis PHY implements a model of 802.11a. The model implemented here is based on ...
Definition: yans-wifi-phy.h:61
double GetValue(double min, double max)
Returns a random double from the uniform distribution with the specified range.
Time m_beaconInterval
Beaconing interval.
an EUI-48 address
Definition: mac48-address.h:41
virtual WifiMode GetMode(uint32_t mode) const =0
void Receive(Ptr< Packet > packet, WifiMacHeader const *hdr)
Frame receive handler.
static Time Now(void)
Definition: simulator.cc:179
Time m_randomStart
Maximum delay before first beacon.
Beacon is beacon header + list of arbitrary information elements.
static TypeId GetTypeId()
Never forget to support typeid.
virtual void SetLinkUpCallback(Callback< void > linkUp)
Time Seconds(double seconds)
create ns3::Time instances in units of seconds.
Definition: nstime.h:586
void ForwardDown(Ptr< const Packet > packet, Mac48Address from, Mac48Address to)
Send frame. Frame is supposed to be tagged by routing information. TODO: clarify this point...
void SetRandomStartDelay(Time interval)
Set maximum initial random delay before first beacon.
void InstallPlugin(Ptr< MeshWifiInterfaceMacPlugin > plugin)
Install plugin. TODO return unique ID to allow unregister plugins.
bool RemovePacketTag(Tag &tag)
Definition: packet.cc:874
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
virtual Mac48Address GetAddress(void) const
void Report(std::ostream &) const
Statistics:
void Cancel(void)
Definition: event-id.cc:47
void SetBeaconGeneration(bool enable)
Enable/disable beacons.
EventId m_beaconSendEvent
"Timer" for the next beacon
void SetBeaconInterval(Time interval)
Set interval between two successive beacons.
Time m_tbtt
Time for the next frame.
void ShiftTbtt(Time shift)
Shift TBTT.
Hold an floating point type.
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Definition: object-base.cc:160
Ptr< T > GetObject(void) const
Definition: object.h:332
a unique identifier for an interface.
Definition: type-id.h:44
uint64_t GetDataRate(void) const
Definition: wifi-mode.cc:57
TypeId SetParent(TypeId tid)
Definition: type-id.cc:471
AcIndex
Definition: qos-utils.h:35
int64_t AssignStreams(int64_t stream)
virtual void SetParent(Ptr< MeshWifiInterfaceMac > parent)=0
Each plugin must be installed on interface to work.
virtual void FinishConfigureStandard(enum WifiPhyStandard standard)