A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
mesh-wifi-interface-mac.cc
Go to the documentation of this file.
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
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
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 
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  */
208  phy->SetChannelNumber (new_id);
209  // Don't know NAV on new channel
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:
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  {
253  }
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  {
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  }
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  }
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  {
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  {
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  {
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  {
448  }
449  }
450  }
451  }
452  }
453  else
454  {
455  m_stats.recvBytes += packet->GetSize ();
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
484 {
485  uint32_t metric = 1;
487  {
488  metric = m_linkMetricCallback (peerAddress, this);
489  }
490  return metric;
491 }
492 void
494 {
496 }
497 void
499 {
500  m_mpAddress = a;
501 }
504 {
505  return m_mpAddress;
506 }
507 //Statistics:
509  recvBeacons (0), sentFrames (0), sentBytes (0), recvFrames (0), recvBytes (0)
510 {
511 }
512 void
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
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 }
554 {
555  return m_standard;
556 }
557 } // namespace ns3
558