A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ap-wifi-mac.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006, 2009 INRIA
4  * Copyright (c) 2009 MIRKO BANCHI
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  * Author: Mirko Banchi <mk.banchi@gmail.com>
21  */
22 #include "ap-wifi-mac.h"
23 
24 #include "ns3/assert.h"
25 #include "ns3/log.h"
26 #include "ns3/simulator.h"
27 #include "ns3/string.h"
28 #include "ns3/pointer.h"
29 #include "ns3/boolean.h"
30 
31 #include "qos-tag.h"
32 #include "wifi-phy.h"
33 #include "dcf-manager.h"
34 #include "mac-rx-middle.h"
35 #include "mac-tx-middle.h"
36 #include "mgt-headers.h"
37 #include "mac-low.h"
38 #include "amsdu-subframe-header.h"
39 #include "msdu-aggregator.h"
40 
41 NS_LOG_COMPONENT_DEFINE ("ApWifiMac");
42 
43 namespace ns3 {
44 
45 NS_OBJECT_ENSURE_REGISTERED (ApWifiMac);
46 
47 TypeId
48 ApWifiMac::GetTypeId (void)
49 {
50  static TypeId tid = TypeId ("ns3::ApWifiMac")
51  .SetParent<RegularWifiMac> ()
52  .AddConstructor<ApWifiMac> ()
53  .AddAttribute ("BeaconInterval", "Delay between two beacons",
54  TimeValue (MicroSeconds (102400)),
55  MakeTimeAccessor (&ApWifiMac::GetBeaconInterval,
57  MakeTimeChecker ())
58  .AddAttribute ("BeaconGeneration", "Whether or not beacons are generated.",
59  BooleanValue (true),
60  MakeBooleanAccessor (&ApWifiMac::SetBeaconGeneration,
61  &ApWifiMac::GetBeaconGeneration),
62  MakeBooleanChecker ())
63  ;
64  return tid;
65 }
66 
67 ApWifiMac::ApWifiMac ()
68 {
69  NS_LOG_FUNCTION (this);
70  m_beaconDca = CreateObject<DcaTxop> ();
71  m_beaconDca->SetAifsn (1);
72  m_beaconDca->SetMinCw (0);
73  m_beaconDca->SetMaxCw (0);
74  m_beaconDca->SetLow (m_low);
75  m_beaconDca->SetManager (m_dcfManager);
76 
77  // Let the lower layers know that we are acting as an AP.
78  SetTypeOfStation (AP);
79 
80  m_enableBeaconGeneration = false;
81 }
82 
83 ApWifiMac::~ApWifiMac ()
84 {
85  NS_LOG_FUNCTION (this);
86 }
87 
88 void
90 {
91  NS_LOG_FUNCTION (this);
92  m_beaconDca = 0;
93  m_enableBeaconGeneration = false;
94  m_beaconEvent.Cancel ();
96 }
97 
98 void
100 {
101  NS_LOG_FUNCTION (this << address);
102  // As an AP, our MAC address is also the BSSID. Hence we are
103  // overriding this function and setting both in our parent class.
104  RegularWifiMac::SetAddress (address);
105  RegularWifiMac::SetBssid (address);
106 }
107 
108 void
109 ApWifiMac::SetBeaconGeneration (bool enable)
110 {
111  NS_LOG_FUNCTION (this << enable);
112  if (!enable)
113  {
114  m_beaconEvent.Cancel ();
115  }
116  else if (enable && !m_enableBeaconGeneration)
117  {
118  m_beaconEvent = Simulator::ScheduleNow (&ApWifiMac::SendOneBeacon, this);
119  }
120  m_enableBeaconGeneration = enable;
121 }
122 
123 bool
124 ApWifiMac::GetBeaconGeneration (void) const
125 {
126  NS_LOG_FUNCTION (this);
127  return m_enableBeaconGeneration;
128 }
129 
130 Time
132 {
133  NS_LOG_FUNCTION (this);
134  return m_beaconInterval;
135 }
136 
137 void
139 {
140  NS_LOG_FUNCTION (this << stationManager);
141  m_beaconDca->SetWifiRemoteStationManager (stationManager);
143 }
144 
145 void
147 {
148  NS_LOG_FUNCTION (this << &linkUp);
150 
151  // The approach taken here is that, from the point of view of an AP,
152  // the link is always up, so we immediately invoke the callback if
153  // one is set
154  linkUp ();
155 }
156 
157 void
159 {
160  NS_LOG_FUNCTION (this << interval);
161  if ((interval.GetMicroSeconds () % 1024) != 0)
162  {
163  NS_LOG_WARN ("beacon interval should be multiple of 1024us, see IEEE Std. 802.11-2007, section 11.1.1.1");
164  }
165  m_beaconInterval = interval;
166 }
167 
168 void
170 {
171  NS_LOG_FUNCTION (this);
172  SendOneBeacon ();
173 }
174 
175 void
176 ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from,
177  Mac48Address to)
178 {
179  NS_LOG_FUNCTION (this << packet << from << to);
180  // If we are not a QoS AP then we definitely want to use AC_BE to
181  // transmit the packet. A TID of zero will map to AC_BE (through \c
182  // QosUtilsMapTidToAc()), so we use that as our default here.
183  uint8_t tid = 0;
184 
185  // If we are a QoS AP then we attempt to get a TID for this packet
186  if (m_qosSupported)
187  {
188  tid = QosUtilsGetTidForPacket (packet);
189  // Any value greater than 7 is invalid and likely indicates that
190  // the packet had no QoS tag, so we revert to zero, which'll
191  // mean that AC_BE is used.
192  if (tid >= 7)
193  {
194  tid = 0;
195  }
196  }
197 
198  ForwardDown (packet, from, to, tid);
199 }
200 
201 void
202 ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from,
203  Mac48Address to, uint8_t tid)
204 {
205  NS_LOG_FUNCTION (this << packet << from << to << static_cast<uint32_t> (tid));
206  WifiMacHeader hdr;
207 
208  // For now, an AP that supports QoS does not support non-QoS
209  // associations, and vice versa. In future the AP model should
210  // support simultaneously associated QoS and non-QoS STAs, at which
211  // point there will need to be per-association QoS state maintained
212  // by the association state machine, and consulted here.
213  if (m_qosSupported)
214  {
215  hdr.SetType (WIFI_MAC_QOSDATA);
216  hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
217  hdr.SetQosNoEosp ();
218  hdr.SetQosNoAmsdu ();
219  // Transmission of multiple frames in the same TXOP is not
220  // supported for now
221  hdr.SetQosTxopLimit (0);
222  // Fill in the QoS control field in the MAC header
223  hdr.SetQosTid (tid);
224  }
225  else
226  {
227  hdr.SetTypeData ();
228  }
229 
230  hdr.SetAddr1 (to);
231  hdr.SetAddr2 (GetAddress ());
232  hdr.SetAddr3 (from);
233  hdr.SetDsFrom ();
234  hdr.SetDsNotTo ();
235 
236  if (m_qosSupported)
237  {
238  // Sanity check that the TID is valid
239  NS_ASSERT (tid < 8);
240  m_edca[QosUtilsMapTidToAc (tid)]->Queue (packet, hdr);
241  }
242  else
243  {
244  m_dca->Queue (packet, hdr);
245  }
246 }
247 
248 void
250 {
251  NS_LOG_FUNCTION (this << packet << to << from);
252  if (to.IsBroadcast () || m_stationManager->IsAssociated (to))
253  {
254  ForwardDown (packet, from, to);
255  }
256 }
257 
258 void
260 {
261  NS_LOG_FUNCTION (this << packet << to);
262  // We're sending this packet with a from address that is our own. We
263  // get that address from the lower MAC and make use of the
264  // from-spoofing Enqueue() method to avoid duplicated code.
265  Enqueue (packet, to, m_low->GetAddress ());
266 }
267 
268 bool
269 ApWifiMac::SupportsSendFrom (void) const
270 {
271  NS_LOG_FUNCTION (this);
272  return true;
273 }
274 
275 SupportedRates
276 ApWifiMac::GetSupportedRates (void) const
277 {
278  NS_LOG_FUNCTION (this);
279  // send the set of supported rates and make sure that we indicate
280  // the Basic Rate set in this set of supported rates.
281  SupportedRates rates;
282  for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
283  {
284  WifiMode mode = m_phy->GetMode (i);
285  rates.AddSupportedRate (mode.GetDataRate ());
286  }
287  // set the basic rates
288  for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
289  {
290  WifiMode mode = m_stationManager->GetBasicMode (j);
291  rates.SetBasicRate (mode.GetDataRate ());
292  }
293  return rates;
294 }
295 
296 void
297 ApWifiMac::SendProbeResp (Mac48Address to)
298 {
299  NS_LOG_FUNCTION (this << to);
300  WifiMacHeader hdr;
301  hdr.SetProbeResp ();
302  hdr.SetAddr1 (to);
303  hdr.SetAddr2 (GetAddress ());
304  hdr.SetAddr3 (GetAddress ());
305  hdr.SetDsNotFrom ();
306  hdr.SetDsNotTo ();
307  Ptr<Packet> packet = Create<Packet> ();
308  MgtProbeResponseHeader probe;
309  probe.SetSsid (GetSsid ());
310  probe.SetSupportedRates (GetSupportedRates ());
311  probe.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
312  packet->AddHeader (probe);
313 
314  // The standard is not clear on the correct queue for management
315  // frames if we are a QoS AP. The approach taken here is to always
316  // use the DCF for these regardless of whether we have a QoS
317  // association or not.
318  m_dca->Queue (packet, hdr);
319 }
320 
321 void
322 ApWifiMac::SendAssocResp (Mac48Address to, bool success)
323 {
324  NS_LOG_FUNCTION (this << to << success);
325  WifiMacHeader hdr;
326  hdr.SetAssocResp ();
327  hdr.SetAddr1 (to);
328  hdr.SetAddr2 (GetAddress ());
329  hdr.SetAddr3 (GetAddress ());
330  hdr.SetDsNotFrom ();
331  hdr.SetDsNotTo ();
332  Ptr<Packet> packet = Create<Packet> ();
333  MgtAssocResponseHeader assoc;
334  StatusCode code;
335  if (success)
336  {
337  code.SetSuccess ();
338  }
339  else
340  {
341  code.SetFailure ();
342  }
343  assoc.SetSupportedRates (GetSupportedRates ());
344  assoc.SetStatusCode (code);
345  packet->AddHeader (assoc);
346 
347  // The standard is not clear on the correct queue for management
348  // frames if we are a QoS AP. The approach taken here is to always
349  // use the DCF for these regardless of whether we have a QoS
350  // association or not.
351  m_dca->Queue (packet, hdr);
352 }
353 
354 void
355 ApWifiMac::SendOneBeacon (void)
356 {
357  NS_LOG_FUNCTION (this);
358  WifiMacHeader hdr;
359  hdr.SetBeacon ();
360  hdr.SetAddr1 (Mac48Address::GetBroadcast ());
361  hdr.SetAddr2 (GetAddress ());
362  hdr.SetAddr3 (GetAddress ());
363  hdr.SetDsNotFrom ();
364  hdr.SetDsNotTo ();
365  Ptr<Packet> packet = Create<Packet> ();
366  MgtBeaconHeader beacon;
367  beacon.SetSsid (GetSsid ());
368  beacon.SetSupportedRates (GetSupportedRates ());
369  beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
370 
371  packet->AddHeader (beacon);
372 
373  // The beacon has it's own special queue, so we load it in there
374  m_beaconDca->Queue (packet, hdr);
375  m_beaconEvent = Simulator::Schedule (m_beaconInterval, &ApWifiMac::SendOneBeacon, this);
376 }
377 
378 void
379 ApWifiMac::TxOk (const WifiMacHeader &hdr)
380 {
381  NS_LOG_FUNCTION (this);
382  RegularWifiMac::TxOk (hdr);
383 
384  if (hdr.IsAssocResp ()
385  && m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ()))
386  {
387  NS_LOG_DEBUG ("associated with sta=" << hdr.GetAddr1 ());
388  m_stationManager->RecordGotAssocTxOk (hdr.GetAddr1 ());
389  }
390 }
391 
392 void
393 ApWifiMac::TxFailed (const WifiMacHeader &hdr)
394 {
395  NS_LOG_FUNCTION (this);
396  RegularWifiMac::TxFailed (hdr);
397 
398  if (hdr.IsAssocResp ()
399  && m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ()))
400  {
401  NS_LOG_DEBUG ("assoc failed with sta=" << hdr.GetAddr1 ());
402  m_stationManager->RecordGotAssocTxFailed (hdr.GetAddr1 ());
403  }
404 }
405 
406 void
408 {
409  NS_LOG_FUNCTION (this << packet << hdr);
410 
411  Mac48Address from = hdr->GetAddr2 ();
412 
413  if (hdr->IsData ())
414  {
415  Mac48Address bssid = hdr->GetAddr1 ();
416  if (!hdr->IsFromDs ()
417  && hdr->IsToDs ()
418  && bssid == GetAddress ()
419  && m_stationManager->IsAssociated (from))
420  {
421  Mac48Address to = hdr->GetAddr3 ();
422  if (to == GetAddress ())
423  {
424  NS_LOG_DEBUG ("frame for me from=" << from);
425  if (hdr->IsQosData ())
426  {
427  if (hdr->IsQosAmsdu ())
428  {
429  NS_LOG_DEBUG ("Received A-MSDU from=" << from << ", size=" << packet->GetSize ());
430  DeaggregateAmsduAndForward (packet, hdr);
431  packet = 0;
432  }
433  else
434  {
435  ForwardUp (packet, from, bssid);
436  }
437  }
438  else
439  {
440  ForwardUp (packet, from, bssid);
441  }
442  }
443  else if (to.IsGroup ()
444  || m_stationManager->IsAssociated (to))
445  {
446  NS_LOG_DEBUG ("forwarding frame from=" << from << ", to=" << to);
447  Ptr<Packet> copy = packet->Copy ();
448 
449  // If the frame we are forwarding is of type QoS Data,
450  // then we need to preserve the UP in the QoS control
451  // header...
452  if (hdr->IsQosData ())
453  {
454  ForwardDown (packet, from, to, hdr->GetQosTid ());
455  }
456  else
457  {
458  ForwardDown (packet, from, to);
459  }
460  ForwardUp (copy, from, to);
461  }
462  else
463  {
464  ForwardUp (packet, from, to);
465  }
466  }
467  else if (hdr->IsFromDs ()
468  && hdr->IsToDs ())
469  {
470  // this is an AP-to-AP frame
471  // we ignore for now.
472  NotifyRxDrop (packet);
473  }
474  else
475  {
476  // we can ignore these frames since
477  // they are not targeted at the AP
478  NotifyRxDrop (packet);
479  }
480  return;
481  }
482  else if (hdr->IsMgt ())
483  {
484  if (hdr->IsProbeReq ())
485  {
486  NS_ASSERT (hdr->GetAddr1 ().IsBroadcast ());
487  SendProbeResp (from);
488  return;
489  }
490  else if (hdr->GetAddr1 () == GetAddress ())
491  {
492  if (hdr->IsAssocReq ())
493  {
494  // first, verify that the the station's supported
495  // rate set is compatible with our Basic Rate set
496  MgtAssocRequestHeader assocReq;
497  packet->RemoveHeader (assocReq);
498  SupportedRates rates = assocReq.GetSupportedRates ();
499  bool problem = false;
500  for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
501  {
502  WifiMode mode = m_stationManager->GetBasicMode (i);
503  if (!rates.IsSupportedRate (mode.GetDataRate ()))
504  {
505  problem = true;
506  break;
507  }
508  }
509  if (problem)
510  {
511  // one of the Basic Rate set mode is not
512  // supported by the station. So, we return an assoc
513  // response with an error status.
514  SendAssocResp (hdr->GetAddr2 (), false);
515  }
516  else
517  {
518  // station supports all rates in Basic Rate Set.
519  // record all its supported modes in its associated WifiRemoteStation
520  for (uint32_t j = 0; j < m_phy->GetNModes (); j++)
521  {
522  WifiMode mode = m_phy->GetMode (j);
523  if (rates.IsSupportedRate (mode.GetDataRate ()))
524  {
525  m_stationManager->AddSupportedMode (from, mode);
526  }
527  }
528  m_stationManager->RecordWaitAssocTxOk (from);
529  // send assoc response with success status.
530  SendAssocResp (hdr->GetAddr2 (), true);
531  }
532  return;
533  }
534  else if (hdr->IsDisassociation ())
535  {
536  m_stationManager->RecordDisassociated (from);
537  return;
538  }
539  }
540  }
541 
542  // Invoke the receive handler of our parent class to deal with any
543  // other frames. Specifically, this will handle Block Ack-related
544  // Management Action frames.
545  RegularWifiMac::Receive (packet, hdr);
546 }
547 
548 void
550  const WifiMacHeader *hdr)
551 {
552  NS_LOG_FUNCTION (this << aggregatedPacket << hdr);
553  MsduAggregator::DeaggregatedMsdus packets =
554  MsduAggregator::Deaggregate (aggregatedPacket);
555 
556  for (MsduAggregator::DeaggregatedMsdusCI i = packets.begin ();
557  i != packets.end (); ++i)
558  {
559  if ((*i).second.GetDestinationAddr () == GetAddress ())
560  {
561  ForwardUp ((*i).first, (*i).second.GetSourceAddr (),
562  (*i).second.GetDestinationAddr ());
563  }
564  else
565  {
566  Mac48Address from = (*i).second.GetSourceAddr ();
567  Mac48Address to = (*i).second.GetDestinationAddr ();
568  NS_LOG_DEBUG ("forwarding QoS frame from=" << from << ", to=" << to);
569  ForwardDown ((*i).first, from, to, hdr->GetQosTid ());
570  }
571  }
572 }
573 
574 void
576 {
577  NS_LOG_FUNCTION (this);
578  m_beaconDca->Initialize ();
579  m_beaconEvent.Cancel ();
580  if (m_enableBeaconGeneration)
581  {
582  m_beaconEvent = Simulator::ScheduleNow (&ApWifiMac::SendOneBeacon, this);
583  }
585 }
586 
587 } // namespace ns3
virtual void DoInitialize(void)
Definition: ap-wifi-mac.cc:575
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
void SetBeaconInterval(Time interval)
Definition: ap-wifi-mac.cc:158
keep track of time unit.
Definition: nstime.h:149
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > stationManager)
virtual uint32_t GetNModes(void) const =0
#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
bool IsBroadcast(void) const
void NotifyRxDrop(Ptr< const Packet > packet)
Definition: wifi-mac.cc:255
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:820
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
virtual void Receive(Ptr< Packet > packet, const WifiMacHeader *hdr)
uint8_t QosUtilsGetTidForPacket(Ptr< const Packet > packet)
Definition: qos-utils.cc:60
virtual void Enqueue(Ptr< const Packet > packet, Mac48Address to)
Definition: ap-wifi-mac.cc:259
virtual void SetBssid(Mac48Address bssid)
virtual void SetWifiRemoteStationManager(Ptr< WifiRemoteStationManager > stationManager)
Definition: ap-wifi-mac.cc:138
void SetTypeOfStation(TypeOfStation type)
int64_t GetMicroSeconds(void) const
Definition: nstime.h:279
Ptr< DcaTxop > m_dca
AcIndex QosUtilsMapTidToAc(uint8_t tid)
Definition: qos-utils.cc:27
virtual void SetAddress(Mac48Address address)
static Mac48Address GetBroadcast(void)
virtual void Receive(Ptr< Packet > packet, const WifiMacHeader *hdr)
Definition: ap-wifi-mac.cc:407
virtual void DeaggregateAmsduAndForward(Ptr< Packet > aggregatedPacket, const WifiMacHeader *hdr)
Definition: ap-wifi-mac.cc:549
Ptr< Packet > Copy(void) const
Definition: packet.cc:131
virtual void SetLinkUpCallback(Callback< void > linkUp)
virtual void SetLinkUpCallback(Callback< void > linkUp)
Definition: ap-wifi-mac.cc:146
virtual void DoDispose()
bool IsGroup(void) const
an EUI-48 address
Definition: mac48-address.h:41
virtual WifiMode GetMode(uint32_t mode) const =0
static EventId ScheduleNow(MEM mem_ptr, OBJ obj)
Definition: simulator.h:981
#define NS_LOG_WARN(msg)
Definition: log.h:246
virtual void DoDispose(void)
Definition: ap-wifi-mac.cc:89
virtual void SetAddress(Mac48Address address)
Definition: ap-wifi-mac.cc:99
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
virtual Mac48Address GetAddress(void) const
virtual void DoInitialize()
void Cancel(void)
Definition: event-id.cc:47
Time GetBeaconInterval(void) const
Definition: ap-wifi-mac.cc:131
uint64_t GetDataRate(void) const
Definition: wifi-mode.cc:57
void StartBeaconing(void)
Definition: ap-wifi-mac.cc:169
Time MicroSeconds(uint64_t us)
create ns3::Time instances in units of microseconds.
Definition: nstime.h:615