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,
  56. &ApWifiMac::SetBeaconInterval),
  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
  89. ApWifiMac::DoDispose ()
  90. {
  91. NS_LOG_FUNCTION (this);
  92. m_beaconDca = 0;
  93. m_enableBeaconGeneration = false;
  94. m_beaconEvent.Cancel ();
  95. RegularWifiMac::DoDispose ();
  96. }
  97.  
  98. void
  99. ApWifiMac::SetAddress (Mac48Address address)
  100. {
  101. // As an AP, our MAC address is also the BSSID. Hence we are
  102. // overriding this function and setting both in our parent class.
  103. RegularWifiMac::SetAddress (address);
  104. RegularWifiMac::SetBssid (address);
  105. }
  106.  
  107. void
  108. ApWifiMac::SetBeaconGeneration (bool enable)
  109. {
  110. NS_LOG_FUNCTION (this << enable);
  111. if (!enable)
  112. {
  113. m_beaconEvent.Cancel ();
  114. }
  115. else if (enable && !m_enableBeaconGeneration)
  116. {
  117. m_beaconEvent = Simulator::ScheduleNow (&ApWifiMac::SendOneBeacon, this);
  118. }
  119. m_enableBeaconGeneration = enable;
  120. }
  121.  
  122. bool
  123. ApWifiMac::GetBeaconGeneration (void) const
  124. {
  125. return m_enableBeaconGeneration;
  126. }
  127.  
  128. Time
  129. ApWifiMac::GetBeaconInterval (void) const
  130. {
  131. return m_beaconInterval;
  132. }
  133.  
  134. void
  135. ApWifiMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
  136. {
  137. NS_LOG_FUNCTION (this << stationManager);
  138. m_beaconDca->SetWifiRemoteStationManager (stationManager);
  139. RegularWifiMac::SetWifiRemoteStationManager (stationManager);
  140. }
  141.  
  142. void
  143. ApWifiMac::SetLinkUpCallback (Callback<void> linkUp)
  144. {
  145. NS_LOG_FUNCTION (this);
  146. RegularWifiMac::SetLinkUpCallback (linkUp);
  147.  
  148. // The approach taken here is that, from the point of view of an AP,
  149. // the link is always up, so we immediately invoke the callback if
  150. // one is set
  151. linkUp ();
  152. }
  153.  
  154. void
  155. ApWifiMac::SetBeaconInterval (Time interval)
  156. {
  157. NS_LOG_FUNCTION (this << interval);
  158. if ((interval.GetMicroSeconds () % 1024) != 0)
  159. {
  160. NS_LOG_WARN ("beacon interval should be multiple of 1024us, see IEEE Std. 802.11-2007, section 11.1.1.1");
  161. }
  162. m_beaconInterval = interval;
  163. }
  164.  
  165. void
  166. ApWifiMac::StartBeaconing (void)
  167. {
  168. NS_LOG_FUNCTION (this);
  169. SendOneBeacon ();
  170. }
  171.  
  172. void
  173. ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from,
  174. Mac48Address to)
  175. {
  176. // If we are not a QoS AP then we definitely want to use AC_BE to
  177. // transmit the packet. A TID of zero will map to AC_BE (through \c
  178. // QosUtilsMapTidToAc()), so we use that as our default here.
  179. uint8_t tid = 0;
  180.  
  181. // If we are a QoS AP then we attempt to get a TID for this packet
  182. if (m_qosSupported)
  183. {
  184. tid = QosUtilsGetTidForPacket (packet);
  185. // Any value greater than 7 is invalid and likely indicates that
  186. // the packet had no QoS tag, so we revert to zero, which'll
  187. // mean that AC_BE is used.
  188. if (tid >= 7)
  189. {
  190. tid = 0;
  191. }
  192. }
  193.  
  194. ForwardDown (packet, from, to, tid);
  195. }
  196.  
  197. void
  198. ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from,
  199. Mac48Address to, uint8_t tid)
  200. {
  201. NS_LOG_FUNCTION (this << packet << from << to);
  202. WifiMacHeader hdr;
  203.  
  204. // For now, an AP that supports QoS does not support non-QoS
  205. // associations, and vice versa. In future the AP model should
  206. // support simultaneously associated QoS and non-QoS STAs, at which
  207. // point there will need to be per-association QoS state maintained
  208. // by the association state machine, and consulted here.
  209. if (m_qosSupported)
  210. {
  211. hdr.SetType (WIFI_MAC_QOSDATA);
  212. hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
  213. hdr.SetQosNoEosp ();
  214. hdr.SetQosNoAmsdu ();
  215. // Transmission of multiple frames in the same TXOP is not
  216. // supported for now
  217. hdr.SetQosTxopLimit (0);
  218. // Fill in the QoS control field in the MAC header
  219. hdr.SetQosTid (tid);
  220. }
  221. else
  222. {
  223. hdr.SetTypeData ();
  224. }
  225.  
  226. hdr.SetAddr1 (to);
  227. hdr.SetAddr2 (GetAddress ());
  228. hdr.SetAddr3 (from);
  229. hdr.SetDsFrom ();
  230. hdr.SetDsNotTo ();
  231.  
  232. if (m_qosSupported)
  233. {
  234. // Sanity check that the TID is valid
  235. NS_ASSERT (tid < 8);
  236. m_edca[QosUtilsMapTidToAc (tid)]->Queue (packet, hdr);
  237. }
  238. else
  239. {
  240. m_dca->Queue (packet, hdr);
  241. }
  242. }
  243.  
  244. void
  245. ApWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from)
  246. {
  247. NS_LOG_FUNCTION (this << packet << to << from);
  248. if (to.IsBroadcast () || m_stationManager->IsAssociated (to))
  249. {
  250. ForwardDown (packet, from, to);
  251. }
  252. }
  253.  
  254. void
  255. ApWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)
  256. {
  257. // We're sending this packet with a from address that is our own. We
  258. // get that address from the lower MAC and make use of the
  259. // from-spoofing Enqueue() method to avoid duplicated code.
  260. Enqueue (packet, to, m_low->GetAddress ());
  261. }
  262.  
  263. bool
  264. ApWifiMac::SupportsSendFrom (void) const
  265. {
  266. return true;
  267. }
  268.  
  269. SupportedRates
  270. ApWifiMac::GetSupportedRates (void) const
  271. {
  272. // send the set of supported rates and make sure that we indicate
  273. // the Basic Rate set in this set of supported rates.
  274. SupportedRates rates;
  275. for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
  276. {
  277. WifiMode mode = m_phy->GetMode (i);
  278. rates.AddSupportedRate (mode.GetDataRate ());
  279. }
  280. // set the basic rates
  281. for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
  282. {
  283. WifiMode mode = m_stationManager->GetBasicMode (j);
  284. rates.SetBasicRate (mode.GetDataRate ());
  285. }
  286. return rates;
  287. }
  288.  
  289. void
  290. ApWifiMac::SendProbeResp (Mac48Address to)
  291. {
  292. NS_LOG_FUNCTION (this << to);
  293. WifiMacHeader hdr;
  294. hdr.SetProbeResp ();
  295. hdr.SetAddr1 (to);
  296. hdr.SetAddr2 (GetAddress ());
  297. hdr.SetAddr3 (GetAddress ());
  298. hdr.SetDsNotFrom ();
  299. hdr.SetDsNotTo ();
  300. Ptr<Packet> packet = Create<Packet> ();
  301. MgtProbeResponseHeader probe;
  302. probe.SetSsid (GetSsid ());
  303. probe.SetSupportedRates (GetSupportedRates ());
  304. probe.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
  305. packet->AddHeader (probe);
  306.  
  307. // The standard is not clear on the correct queue for management
  308. // frames if we are a QoS AP. The approach taken here is to always
  309. // use the DCF for these regardless of whether we have a QoS
  310. // association or not.
  311. m_dca->Queue (packet, hdr);
  312. }
  313.  
  314. void
  315. ApWifiMac::SendAssocResp (Mac48Address to, bool success)
  316. {
  317. NS_LOG_FUNCTION (this << to << success);
  318. WifiMacHeader hdr;
  319. hdr.SetAssocResp ();
  320. hdr.SetAddr1 (to);
  321. hdr.SetAddr2 (GetAddress ());
  322. hdr.SetAddr3 (GetAddress ());
  323. hdr.SetDsNotFrom ();
  324. hdr.SetDsNotTo ();
  325. Ptr<Packet> packet = Create<Packet> ();
  326. MgtAssocResponseHeader assoc;
  327. StatusCode code;
  328. if (success)
  329. {
  330. code.SetSuccess ();
  331. }
  332. else
  333. {
  334. code.SetFailure ();
  335. }
  336. assoc.SetSupportedRates (GetSupportedRates ());
  337. assoc.SetStatusCode (code);
  338. packet->AddHeader (assoc);
  339.  
  340. // The standard is not clear on the correct queue for management
  341. // frames if we are a QoS AP. The approach taken here is to always
  342. // use the DCF for these regardless of whether we have a QoS
  343. // association or not.
  344. m_dca->Queue (packet, hdr);
  345. }
  346.  
  347. void
  348. ApWifiMac::SendOneBeacon (void)
  349. {
  350. NS_LOG_FUNCTION (this);
  351. WifiMacHeader hdr;
  352. hdr.SetBeacon ();
  353. hdr.SetAddr1 (Mac48Address::GetBroadcast ());
  354. hdr.SetAddr2 (GetAddress ());
  355. hdr.SetAddr3 (GetAddress ());
  356. hdr.SetDsNotFrom ();
  357. hdr.SetDsNotTo ();
  358. Ptr<Packet> packet = Create<Packet> ();
  359. MgtBeaconHeader beacon;
  360. beacon.SetSsid (GetSsid ());
  361. beacon.SetSupportedRates (GetSupportedRates ());
  362. beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
  363.  
  364. packet->AddHeader (beacon);
  365.  
  366. // The beacon has it's own special queue, so we load it in there
  367. m_beaconDca->Queue (packet, hdr);
  368. m_beaconEvent = Simulator::Schedule (m_beaconInterval, &ApWifiMac::SendOneBeacon, this);
  369. }
  370.  
  371. void
  372. ApWifiMac::TxOk (const WifiMacHeader &hdr)
  373. {
  374. NS_LOG_FUNCTION (this);
  375. RegularWifiMac::TxOk (hdr);
  376.  
  377. if (hdr.IsAssocResp () &&
  378. m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ()))
  379. {
  380. NS_LOG_DEBUG ("associated with sta="<<hdr.GetAddr1 ());
  381. m_stationManager->RecordGotAssocTxOk (hdr.GetAddr1 ());
  382. }
  383. }
  384.  
  385. void
  386. ApWifiMac::TxFailed (const WifiMacHeader &hdr)
  387. {
  388. NS_LOG_FUNCTION (this);
  389. RegularWifiMac::TxFailed (hdr);
  390.  
  391. if (hdr.IsAssocResp () &&
  392. m_stationManager->IsWaitAssocTxOk (hdr.GetAddr1 ()))
  393. {
  394. NS_LOG_DEBUG ("assoc failed with sta="<<hdr.GetAddr1 ());
  395. m_stationManager->RecordGotAssocTxFailed (hdr.GetAddr1 ());
  396. }
  397. }
  398.  
  399. void
  400. ApWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
  401. {
  402. NS_LOG_FUNCTION (this << packet << hdr);
  403.  
  404. Mac48Address from = hdr->GetAddr2 ();
  405.  
  406. if (hdr->IsData ())
  407. {
  408. Mac48Address bssid = hdr->GetAddr1 ();
  409. if (!hdr->IsFromDs () &&
  410. hdr->IsToDs () &&
  411. bssid == GetAddress () &&
  412. m_stationManager->IsAssociated (from))
  413. {
  414. Mac48Address to = hdr->GetAddr3 ();
  415. if (to == GetAddress ())
  416. {
  417. NS_LOG_DEBUG ("frame for me from="<<from);
  418. if (hdr->IsQosData ())
  419. {
  420. if (hdr->IsQosAmsdu ())
  421. {
  422. NS_LOG_DEBUG ("Received A-MSDU from="<<from<<", size="<<packet->GetSize ());
  423. DeaggregateAmsduAndForward (packet, hdr);
  424. packet = 0;
  425. }
  426. else
  427. {
  428. ForwardUp (packet, from, bssid);
  429. }
  430. }
  431. else
  432. {
  433. ForwardUp (packet, from, bssid);
  434. }
  435. }
  436. else if (to.IsGroup () ||
  437. m_stationManager->IsAssociated (to))
  438. {
  439. NS_LOG_DEBUG ("forwarding frame from="<<from<<", to="<<to);
  440. Ptr<Packet> copy = packet->Copy ();
  441.  
  442. // If the frame we are forwarding is of type QoS Data,
  443. // then we need to preserve the UP in the QoS control
  444. // header...
  445. if (hdr->IsQosData ())
  446. {
  447. ForwardDown (packet, from, to, hdr->GetQosTid ());
  448. }
  449. else
  450. {
  451. ForwardDown (packet, from, to);
  452. }
  453. ForwardUp (copy, from, to);
  454. }
  455. else
  456. {
  457. ForwardUp (packet, from, to);
  458. }
  459. }
  460. else if (hdr->IsFromDs () &&
  461. hdr->IsToDs ())
  462. {
  463. // this is an AP-to-AP frame
  464. // we ignore for now.
  465. NotifyRxDrop (packet);
  466. }
  467. else
  468. {
  469. // we can ignore these frames since
  470. // they are not targeted at the AP
  471. NotifyRxDrop (packet);
  472. }
  473. return;
  474. }
  475. else if (hdr->IsMgt ())
  476. {
  477. if (hdr->IsProbeReq ())
  478. {
  479. NS_ASSERT (hdr->GetAddr1 ().IsBroadcast ());
  480. SendProbeResp (from);
  481. return;
  482. }
  483. else if (hdr->GetAddr1 () == GetAddress ())
  484. {
  485. if (hdr->IsAssocReq ())
  486. {
  487. // first, verify that the the station's supported
  488. // rate set is compatible with our Basic Rate set
  489. MgtAssocRequestHeader assocReq;
  490. packet->RemoveHeader (assocReq);
  491. SupportedRates rates = assocReq.GetSupportedRates ();
  492. bool problem = false;
  493. for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
  494. {
  495. WifiMode mode = m_stationManager->GetBasicMode (i);
  496. if (!rates.IsSupportedRate (mode.GetDataRate ()))
  497. {
  498. problem = true;
  499. break;
  500. }
  501. }
  502. if (problem)
  503. {
  504. // one of the Basic Rate set mode is not
  505. // supported by the station. So, we return an assoc
  506. // response with an error status.
  507. SendAssocResp (hdr->GetAddr2 (), false);
  508. }
  509. else
  510. {
  511. // station supports all rates in Basic Rate Set.
  512. // record all its supported modes in its associated WifiRemoteStation
  513. for (uint32_t j = 0; j < m_phy->GetNModes (); j++)
  514. {
  515. WifiMode mode = m_phy->GetMode (j);
  516. if (rates.IsSupportedRate (mode.GetDataRate ()))
  517. {
  518. m_stationManager->AddSupportedMode (from, mode);
  519. }
  520. }
  521. m_stationManager->RecordWaitAssocTxOk (from);
  522. // send assoc response with success status.
  523. SendAssocResp (hdr->GetAddr2 (), true);
  524. }
  525. return;
  526. }
  527. else if (hdr->IsDisassociation ())
  528. {
  529. m_stationManager->RecordDisassociated (from);
  530. return;
  531. }
  532. }
  533. else if(hdr->IsBeacon()) // WITHOUT MY PATCH BEACON WILL GO UP TO REGULAR_WIFI_MAC AND CRASSSH
  534. {
  535. NotifyRxDrop(packet);
  536. return;
  537. }
  538. }
  539.  
  540. // Invoke the receive handler of our parent class to deal with any
  541. // other frames. Specifically, this will handle Block Ack-related
  542. // Management Action frames.
  543. RegularWifiMac::Receive (packet, hdr);
  544. }
  545.  
  546. void
  547. ApWifiMac::DeaggregateAmsduAndForward (Ptr<Packet> aggregatedPacket,
  548. const WifiMacHeader *hdr)
  549. {
  550. MsduAggregator::DeaggregatedMsdus packets =
  551. MsduAggregator::Deaggregate (aggregatedPacket);
  552.  
  553. for (MsduAggregator::DeaggregatedMsdusCI i = packets.begin ();
  554. i != packets.end (); ++i)
  555. {
  556. if ((*i).second.GetDestinationAddr () == GetAddress ())
  557. {
  558. ForwardUp ((*i).first, (*i).second.GetSourceAddr (),
  559. (*i).second.GetDestinationAddr ());
  560. }
  561. else
  562. {
  563. Mac48Address from = (*i).second.GetSourceAddr ();
  564. Mac48Address to = (*i).second.GetDestinationAddr ();
  565. NS_LOG_DEBUG ("forwarding QoS frame from="<<from<<", to="<<to);
  566. ForwardDown ((*i).first, from, to, hdr->GetQosTid ());
  567. }
  568. }
  569. }
  570.  
  571. void
  572. ApWifiMac::DoStart (void)
  573. {
  574. m_beaconDca->Start ();
  575. m_beaconEvent.Cancel ();
  576. if (m_enableBeaconGeneration)
  577. {
  578. m_beaconEvent = Simulator::ScheduleNow (&ApWifiMac::SendOneBeacon, this);
  579. }
  580. RegularWifiMac::DoStart ();
  581. }
  582.  
  583. } // namespace ns3
  584.