A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ap-wifi-mac.cc
Go to the documentation of this file.
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
49 {
50  static TypeId tid = TypeId ("ns3::ApWifiMac")
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,
62  MakeBooleanChecker ())
63  ;
64  return tid;
65 }
66 
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);
76 
77  // Let the lower layers know that we are acting as an AP.
79 
81 }
82 
84 {
85  NS_LOG_FUNCTION (this);
86 }
87 
88 void
90 {
91  NS_LOG_FUNCTION (this);
92  m_beaconDca = 0;
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
110 {
111  NS_LOG_FUNCTION (this << enable);
112  if (!enable)
113  {
115  }
116  else if (enable && !m_enableBeaconGeneration)
117  {
119  }
120  m_enableBeaconGeneration = enable;
121 }
122 
123 bool
125 {
126  NS_LOG_FUNCTION (this);
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
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
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  {
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  if (m_htSupported)
231  hdr.SetNoOrder();
232  hdr.SetAddr1 (to);
233  hdr.SetAddr2 (GetAddress ());
234  hdr.SetAddr3 (from);
235  hdr.SetDsFrom ();
236  hdr.SetDsNotTo ();
237 
238  if (m_qosSupported)
239  {
240  // Sanity check that the TID is valid
241  NS_ASSERT (tid < 8);
242  m_edca[QosUtilsMapTidToAc (tid)]->Queue (packet, hdr);
243  }
244  else
245  {
246  m_dca->Queue (packet, hdr);
247  }
248 }
249 
250 void
252 {
253  NS_LOG_FUNCTION (this << packet << to << from);
254  if (to.IsBroadcast () || m_stationManager->IsAssociated (to))
255  {
256  ForwardDown (packet, from, to);
257  }
258 }
259 
260 void
262 {
263  NS_LOG_FUNCTION (this << packet << to);
264  // We're sending this packet with a from address that is our own. We
265  // get that address from the lower MAC and make use of the
266  // from-spoofing Enqueue() method to avoid duplicated code.
267  Enqueue (packet, to, m_low->GetAddress ());
268 }
269 
270 bool
272 {
273  NS_LOG_FUNCTION (this);
274  return true;
275 }
276 
279 {
280  NS_LOG_FUNCTION (this);
281  SupportedRates rates;
282  // If it is an HT-AP then add the BSSMembershipSelectorSet
283  // which only includes 127 for HT now. The standard says that the BSSMembershipSelectorSet
284  // must have its MSB set to 1 (must be treated as a Basic Rate)
285  // Also the standard mentioned that at leat 1 element should be included in the SupportedRates the rest can be in the ExtendedSupportedRates
286  if (m_htSupported)
287  {
288  for (uint32_t i = 0; i < m_phy->GetNBssMembershipSelectors(); i++)
289  {
291  }
292  }
293  // send the set of supported rates and make sure that we indicate
294  // the Basic Rate set in this set of supported rates.
295  for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
296  {
297  WifiMode mode = m_phy->GetMode (i);
298  rates.AddSupportedRate (mode.GetDataRate ());
299  }
300  // set the basic rates
301  for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
302  {
304  rates.SetBasicRate (mode.GetDataRate ());
305  }
306 
307  return rates;
308 }
311 {
312  HtCapabilities capabilities;
313  capabilities.SetHtSupported(1);
314  capabilities.SetLdpc (m_phy->GetLdpc());
316  capabilities.SetGreenfield (m_phy->GetGreenfield());
317  for (uint8_t i =0 ; i < m_phy->GetNMcs();i++)
318  {
319  capabilities.SetRxMcsBitmask(m_phy->GetMcs(i));
320  }
321  return capabilities;
322 }
323 void
325 {
326  NS_LOG_FUNCTION (this << to);
327  WifiMacHeader hdr;
328  hdr.SetProbeResp ();
329  hdr.SetAddr1 (to);
330  hdr.SetAddr2 (GetAddress ());
331  hdr.SetAddr3 (GetAddress ());
332  hdr.SetDsNotFrom ();
333  hdr.SetDsNotTo ();
334  Ptr<Packet> packet = Create<Packet> ();
336  probe.SetSsid (GetSsid ());
337  probe.SetSupportedRates (GetSupportedRates ());
338  probe.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
339 if (m_htSupported)
340  {
341  probe.SetHtCapabilities (GetHtCapabilities());
342  hdr.SetNoOrder();
343  }
344  packet->AddHeader (probe);
345 
346  // The standard is not clear on the correct queue for management
347  // frames if we are a QoS AP. The approach taken here is to always
348  // use the DCF for these regardless of whether we have a QoS
349  // association or not.
350  m_dca->Queue (packet, hdr);
351 }
352 
353 void
355 {
356  NS_LOG_FUNCTION (this << to << success);
357  WifiMacHeader hdr;
358  hdr.SetAssocResp ();
359  hdr.SetAddr1 (to);
360  hdr.SetAddr2 (GetAddress ());
361  hdr.SetAddr3 (GetAddress ());
362  hdr.SetDsNotFrom ();
363  hdr.SetDsNotTo ();
364  Ptr<Packet> packet = Create<Packet> ();
366  StatusCode code;
367  if (success)
368  {
369  code.SetSuccess ();
370  }
371  else
372  {
373  code.SetFailure ();
374  }
375  assoc.SetSupportedRates (GetSupportedRates ());
376  assoc.SetStatusCode (code);
377 
378  if (m_htSupported)
379  {
380  assoc.SetHtCapabilities (GetHtCapabilities());
381  hdr.SetNoOrder();
382  }
383  packet->AddHeader (assoc);
384 
385  // The standard is not clear on the correct queue for management
386  // frames if we are a QoS AP. The approach taken here is to always
387  // use the DCF for these regardless of whether we have a QoS
388  // association or not.
389  m_dca->Queue (packet, hdr);
390 }
391 
392 void
394 {
395  NS_LOG_FUNCTION (this);
396  WifiMacHeader hdr;
397  hdr.SetBeacon ();
399  hdr.SetAddr2 (GetAddress ());
400  hdr.SetAddr3 (GetAddress ());
401  hdr.SetDsNotFrom ();
402  hdr.SetDsNotTo ();
403  Ptr<Packet> packet = Create<Packet> ();
404  MgtBeaconHeader beacon;
405  beacon.SetSsid (GetSsid ());
406  beacon.SetSupportedRates (GetSupportedRates ());
407  beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
408  if (m_htSupported)
409  {
410  beacon.SetHtCapabilities (GetHtCapabilities());
411  hdr.SetNoOrder();
412  }
413  packet->AddHeader (beacon);
414 
415  // The beacon has it's own special queue, so we load it in there
416  m_beaconDca->Queue (packet, hdr);
418 }
419 
420 void
422 {
423  NS_LOG_FUNCTION (this);
424  RegularWifiMac::TxOk (hdr);
425 
426  if (hdr.IsAssocResp ()
428  {
429  NS_LOG_DEBUG ("associated with sta=" << hdr.GetAddr1 ());
431  }
432 }
433 
434 void
436 {
437  NS_LOG_FUNCTION (this);
439 
440  if (hdr.IsAssocResp ()
442  {
443  NS_LOG_DEBUG ("assoc failed with sta=" << hdr.GetAddr1 ());
445  }
446 }
447 
448 void
450 {
451  NS_LOG_FUNCTION (this << packet << hdr);
452 
453  Mac48Address from = hdr->GetAddr2 ();
454 
455  if (hdr->IsData ())
456  {
457  Mac48Address bssid = hdr->GetAddr1 ();
458  if (!hdr->IsFromDs ()
459  && hdr->IsToDs ()
460  && bssid == GetAddress ()
461  && m_stationManager->IsAssociated (from))
462  {
463  Mac48Address to = hdr->GetAddr3 ();
464  if (to == GetAddress ())
465  {
466  NS_LOG_DEBUG ("frame for me from=" << from);
467  if (hdr->IsQosData ())
468  {
469  if (hdr->IsQosAmsdu ())
470  {
471  NS_LOG_DEBUG ("Received A-MSDU from=" << from << ", size=" << packet->GetSize ());
472  DeaggregateAmsduAndForward (packet, hdr);
473  packet = 0;
474  }
475  else
476  {
477  ForwardUp (packet, from, bssid);
478  }
479  }
480  else
481  {
482  ForwardUp (packet, from, bssid);
483  }
484  }
485  else if (to.IsGroup ()
487  {
488  NS_LOG_DEBUG ("forwarding frame from=" << from << ", to=" << to);
489  Ptr<Packet> copy = packet->Copy ();
490 
491  // If the frame we are forwarding is of type QoS Data,
492  // then we need to preserve the UP in the QoS control
493  // header...
494  if (hdr->IsQosData ())
495  {
496  ForwardDown (packet, from, to, hdr->GetQosTid ());
497  }
498  else
499  {
500  ForwardDown (packet, from, to);
501  }
502  ForwardUp (copy, from, to);
503  }
504  else
505  {
506  ForwardUp (packet, from, to);
507  }
508  }
509  else if (hdr->IsFromDs ()
510  && hdr->IsToDs ())
511  {
512  // this is an AP-to-AP frame
513  // we ignore for now.
514  NotifyRxDrop (packet);
515  }
516  else
517  {
518  // we can ignore these frames since
519  // they are not targeted at the AP
520  NotifyRxDrop (packet);
521  }
522  return;
523  }
524  else if (hdr->IsMgt ())
525  {
526  if (hdr->IsProbeReq ())
527  {
528  NS_ASSERT (hdr->GetAddr1 ().IsBroadcast ());
529  SendProbeResp (from);
530  return;
531  }
532  else if (hdr->GetAddr1 () == GetAddress ())
533  {
534  if (hdr->IsAssocReq ())
535  {
536  // first, verify that the the station's supported
537  // rate set is compatible with our Basic Rate set
538  MgtAssocRequestHeader assocReq;
539  packet->RemoveHeader (assocReq);
540  SupportedRates rates = assocReq.GetSupportedRates ();
541  bool problem = false;
542  for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
543  {
545  if (!rates.IsSupportedRate (mode.GetDataRate ()))
546  {
547  problem = true;
548  break;
549  }
550  }
551  if (m_htSupported)
552  {//check that the STA supports all MCSs in Basic MCS Set
553  HtCapabilities htcapabilities = assocReq.GetHtCapabilities ();
554  for (uint32_t i = 0; i < m_stationManager->GetNBasicMcs (); i++)
555  {
556  uint8_t mcs = m_stationManager->GetBasicMcs (i);
557  if (!htcapabilities.IsSupportedMcs (mcs))
558  {
559  problem = true;
560  break;
561  }
562  }
563 
564  }
565  if (problem)
566  {
567  // one of the Basic Rate set mode is not
568  // supported by the station. So, we return an assoc
569  // response with an error status.
570  SendAssocResp (hdr->GetAddr2 (), false);
571  }
572  else
573  {
574  // station supports all rates in Basic Rate Set.
575  // record all its supported modes in its associated WifiRemoteStation
576  for (uint32_t j = 0; j < m_phy->GetNModes (); j++)
577  {
578  WifiMode mode = m_phy->GetMode (j);
579  if (rates.IsSupportedRate (mode.GetDataRate ()))
580  {
581  m_stationManager->AddSupportedMode (from, mode);
582  }
583  }
584  if (m_htSupported)
585  {
586  HtCapabilities htcapabilities = assocReq.GetHtCapabilities ();
587  m_stationManager->AddStationHtCapabilities (from,htcapabilities);
588  for (uint32_t j = 0; j < m_phy->GetNMcs (); j++)
589  {
590  uint8_t mcs = m_phy->GetMcs (j);
591  if (htcapabilities.IsSupportedMcs (mcs))
592  {
593  m_stationManager->AddSupportedMcs (from, mcs);
594  }
595  }
596  }
598  // send assoc response with success status.
599  SendAssocResp (hdr->GetAddr2 (), true);
600  }
601  return;
602  }
603  else if (hdr->IsDisassociation ())
604  {
606  return;
607  }
608  }
609  }
610 
611  // Invoke the receive handler of our parent class to deal with any
612  // other frames. Specifically, this will handle Block Ack-related
613  // Management Action frames.
614  RegularWifiMac::Receive (packet, hdr);
615 }
616 
617 void
619  const WifiMacHeader *hdr)
620 {
621  NS_LOG_FUNCTION (this << aggregatedPacket << hdr);
623  MsduAggregator::Deaggregate (aggregatedPacket);
624 
625  for (MsduAggregator::DeaggregatedMsdusCI i = packets.begin ();
626  i != packets.end (); ++i)
627  {
628  if ((*i).second.GetDestinationAddr () == GetAddress ())
629  {
630  ForwardUp ((*i).first, (*i).second.GetSourceAddr (),
631  (*i).second.GetDestinationAddr ());
632  }
633  else
634  {
635  Mac48Address from = (*i).second.GetSourceAddr ();
636  Mac48Address to = (*i).second.GetDestinationAddr ();
637  NS_LOG_DEBUG ("forwarding QoS frame from=" << from << ", to=" << to);
638  ForwardDown ((*i).first, from, to, hdr->GetQosTid ());
639  }
640  }
641 }
642 
643 void
645 {
646  NS_LOG_FUNCTION (this);
650  {
652  }
654 }
655 
656 } // namespace ns3