|
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2005,2006 INRIA |
|
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 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> |
|
19 */ |
|
20 #include "ns3/assert.h" |
|
21 #include "ns3/log.h" |
|
22 #include "ns3/simulator.h" |
|
23 #include "ns3/node.h" |
|
24 |
|
25 #include "nqap-wifi-mac.h" |
|
26 #include "dca-txop.h" |
|
27 #include "wifi-mac-header.h" |
|
28 #include "mgt-headers.h" |
|
29 #include "wifi-phy.h" |
|
30 #include "dcf-manager.h" |
|
31 #include "mac-rx-middle.h" |
|
32 #include "mac-low.h" |
|
33 |
|
34 NS_LOG_COMPONENT_DEFINE ("NqapWifiMac"); |
|
35 |
|
36 #define TRACE(x) \ |
|
37 NS_LOG_DEBUG(Simulator::Now () << " " << GetAddress () << " " << x); |
|
38 |
|
39 namespace ns3 { |
|
40 |
|
41 NS_OBJECT_ENSURE_REGISTERED (NqapWifiMac); |
|
42 |
|
43 TypeId |
|
44 NqapWifiMac::GetTypeId (void) |
|
45 { |
|
46 static TypeId tid = TypeId ("NqapWifiMac") |
|
47 .SetParent<WifiMac> () |
|
48 .AddConstructor<NqapWifiMac> () |
|
49 .AddAttribute ("BeaconInterval", "Delay between two beacons", |
|
50 Seconds (1.0), |
|
51 MakeTimeAccessor (&NqapWifiMac::m_beaconInterval), |
|
52 MakeTimeChecker ()) |
|
53 ; |
|
54 return tid; |
|
55 } |
|
56 |
|
57 NqapWifiMac::NqapWifiMac () |
|
58 { |
|
59 m_dcfManager = new DcfManager (); |
|
60 |
|
61 m_rxMiddle = new MacRxMiddle (); |
|
62 m_rxMiddle->SetForwardCallback (MakeCallback (&NqapWifiMac::Receive, this)); |
|
63 |
|
64 m_low = new MacLow (); |
|
65 m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle)); |
|
66 |
|
67 m_dca = CreateObject<DcaTxop> (); |
|
68 m_dca->SetLow (m_low); |
|
69 m_dca->SetManager (m_dcfManager); |
|
70 m_dca->SetTxOkCallback (MakeCallback (&NqapWifiMac::TxOk, this)); |
|
71 m_dca->SetTxFailedCallback (MakeCallback (&NqapWifiMac::TxFailed, this)); |
|
72 |
|
73 m_beaconDca = CreateObject<DcaTxop> (); |
|
74 m_beaconDca->SetLow (m_low); |
|
75 m_beaconDca->SetManager (m_dcfManager); |
|
76 } |
|
77 NqapWifiMac::~NqapWifiMac () |
|
78 {} |
|
79 |
|
80 void |
|
81 NqapWifiMac::DoDispose (void) |
|
82 { |
|
83 delete m_rxMiddle; |
|
84 delete m_low; |
|
85 m_rxMiddle = 0; |
|
86 m_low = 0; |
|
87 m_phy = 0; |
|
88 m_dca = 0; |
|
89 m_beaconDca = 0; |
|
90 WifiMac::DoDispose (); |
|
91 } |
|
92 |
|
93 |
|
94 void |
|
95 NqapWifiMac::SetWifiPhy (Ptr<WifiPhy> phy) |
|
96 { |
|
97 m_phy = phy; |
|
98 } |
|
99 void |
|
100 NqapWifiMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager) |
|
101 { |
|
102 m_stationManager = stationManager; |
|
103 } |
|
104 void |
|
105 NqapWifiMac::SetForwardUpCallback (Callback<void,Ptr<Packet>, const Mac48Address &> upCallback) |
|
106 { |
|
107 m_upCallback = upCallback; |
|
108 } |
|
109 void |
|
110 NqapWifiMac::SetLinkUpCallback (Callback<void> linkUp) |
|
111 { |
|
112 |
|
113 } |
|
114 void |
|
115 NqapWifiMac::SetLinkDownCallback (Callback<void> linkDown) |
|
116 { |
|
117 |
|
118 } |
|
119 Mac48Address |
|
120 NqapWifiMac::GetAddress (void) const |
|
121 { |
|
122 return m_address; |
|
123 } |
|
124 Ssid |
|
125 NqapWifiMac::GetSsid (void) const |
|
126 { |
|
127 return m_ssid; |
|
128 } |
|
129 Mac48Address |
|
130 NqapWifiMac::GetBssid (void) const |
|
131 { |
|
132 return m_address; |
|
133 } |
|
134 void |
|
135 NqapWifiMac::SetAddress (Mac48Address address) |
|
136 { |
|
137 m_address = address; |
|
138 } |
|
139 void |
|
140 NqapWifiMac::SetSsid (Ssid ssid) |
|
141 { |
|
142 m_ssid = ssid; |
|
143 } |
|
144 |
|
145 |
|
146 void |
|
147 NqapWifiMac::SetBeaconInterval (Time interval) |
|
148 { |
|
149 m_beaconInterval = interval; |
|
150 } |
|
151 void |
|
152 NqapWifiMac::StartBeaconing (void) |
|
153 { |
|
154 SendOneBeacon (); |
|
155 } |
|
156 void |
|
157 NqapWifiMac::ForwardUp (Ptr<Packet> packet, Mac48Address from) |
|
158 { |
|
159 m_upCallback (packet, from); |
|
160 } |
|
161 void |
|
162 NqapWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to) |
|
163 { |
|
164 WifiMacHeader hdr; |
|
165 hdr.SetTypeData (); |
|
166 hdr.SetAddr1 (to); |
|
167 hdr.SetAddr2 (GetAddress ()); |
|
168 hdr.SetAddr3 (from); |
|
169 hdr.SetDsFrom (); |
|
170 hdr.SetDsNotTo (); |
|
171 m_dca->Queue (packet, hdr); |
|
172 } |
|
173 void |
|
174 NqapWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to) |
|
175 { |
|
176 ForwardDown (packet, GetAddress (), to); |
|
177 } |
|
178 SupportedRates |
|
179 NqapWifiMac::GetSupportedRates (void) const |
|
180 { |
|
181 // send the set of supported rates and make sure that we indicate |
|
182 // the Basic Rate set in this set of supported rates. |
|
183 SupportedRates rates; |
|
184 for (uint32_t i = 0; i < m_phy->GetNModes (); i++) |
|
185 { |
|
186 WifiMode mode = m_phy->GetMode (i); |
|
187 rates.AddSupportedRate (mode.GetDataRate ()); |
|
188 } |
|
189 // set the basic rates |
|
190 for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++) |
|
191 { |
|
192 WifiMode mode = m_stationManager->GetBasicMode (j); |
|
193 rates.SetBasicRate (mode.GetDataRate ()); |
|
194 } |
|
195 return rates; |
|
196 } |
|
197 void |
|
198 NqapWifiMac::SendProbeResp (Mac48Address to) |
|
199 { |
|
200 TRACE ("send probe response to="<<to); |
|
201 WifiMacHeader hdr; |
|
202 hdr.SetProbeResp (); |
|
203 hdr.SetAddr1 (to); |
|
204 hdr.SetAddr2 (GetAddress ()); |
|
205 hdr.SetAddr3 (GetAddress ()); |
|
206 hdr.SetDsNotFrom (); |
|
207 hdr.SetDsNotTo (); |
|
208 Ptr<Packet> packet = Create<Packet> (); |
|
209 MgtProbeResponseHeader probe; |
|
210 probe.SetSsid (GetSsid ()); |
|
211 probe.SetSupportedRates (GetSupportedRates ()); |
|
212 probe.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ()); |
|
213 packet->AddHeader (probe); |
|
214 |
|
215 m_dca->Queue (packet, hdr); |
|
216 } |
|
217 void |
|
218 NqapWifiMac::SendAssocResp (Mac48Address to, bool success) |
|
219 { |
|
220 TRACE ("send assoc response to="<<to); |
|
221 WifiMacHeader hdr; |
|
222 hdr.SetAssocResp (); |
|
223 hdr.SetAddr1 (to); |
|
224 hdr.SetAddr2 (GetAddress ()); |
|
225 hdr.SetAddr3 (GetAddress ()); |
|
226 hdr.SetDsNotFrom (); |
|
227 hdr.SetDsNotTo (); |
|
228 Ptr<Packet> packet = Create<Packet> (); |
|
229 MgtAssocResponseHeader assoc; |
|
230 StatusCode code; |
|
231 if (success) |
|
232 { |
|
233 code.SetSuccess (); |
|
234 } |
|
235 else |
|
236 { |
|
237 code.SetFailure (); |
|
238 } |
|
239 assoc.SetSupportedRates (GetSupportedRates ()); |
|
240 assoc.SetStatusCode (code); |
|
241 packet->AddHeader (assoc); |
|
242 |
|
243 m_dca->Queue (packet, hdr); |
|
244 } |
|
245 void |
|
246 NqapWifiMac::SendOneBeacon (void) |
|
247 { |
|
248 TRACE ("send beacon to="<<Mac48Address::GetBroadcast ()); |
|
249 WifiMacHeader hdr; |
|
250 hdr.SetBeacon (); |
|
251 hdr.SetAddr1 (Mac48Address::GetBroadcast ()); |
|
252 hdr.SetAddr2 (GetAddress ()); |
|
253 hdr.SetAddr3 (GetAddress ()); |
|
254 hdr.SetDsNotFrom (); |
|
255 hdr.SetDsNotTo (); |
|
256 Ptr<Packet> packet = Create<Packet> (); |
|
257 MgtBeaconHeader beacon; |
|
258 beacon.SetSsid (GetSsid ()); |
|
259 beacon.SetSupportedRates (GetSupportedRates ()); |
|
260 beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ()); |
|
261 packet->AddHeader (beacon); |
|
262 |
|
263 m_beaconDca->Queue (packet, hdr); |
|
264 Simulator::Schedule (m_beaconInterval, &NqapWifiMac::SendOneBeacon, this); |
|
265 } |
|
266 void |
|
267 NqapWifiMac::TxOk (WifiMacHeader const &hdr) |
|
268 { |
|
269 WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ()); |
|
270 if (hdr.IsAssocResp () && |
|
271 station->IsWaitAssocTxOk ()) |
|
272 { |
|
273 TRACE ("associated with sta="<<hdr.GetAddr1 ()); |
|
274 station->RecordGotAssocTxOk (); |
|
275 } |
|
276 } |
|
277 void |
|
278 NqapWifiMac::TxFailed (WifiMacHeader const &hdr) |
|
279 { |
|
280 WifiRemoteStation *station = m_stationManager->Lookup (hdr.GetAddr1 ()); |
|
281 if (hdr.IsAssocResp () && |
|
282 station->IsWaitAssocTxOk ()) |
|
283 { |
|
284 TRACE ("assoc failed with sta="<<hdr.GetAddr1 ()); |
|
285 station->RecordGotAssocTxFailed (); |
|
286 } |
|
287 } |
|
288 void |
|
289 NqapWifiMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr) |
|
290 { |
|
291 WifiRemoteStation *station = m_stationManager->Lookup (hdr->GetAddr2 ()); |
|
292 |
|
293 if (hdr->IsData ()) |
|
294 { |
|
295 if (!hdr->IsFromDs () && |
|
296 hdr->IsToDs () && |
|
297 hdr->GetAddr1 () == GetAddress () && |
|
298 station->IsAssociated ()) |
|
299 { |
|
300 if (hdr->GetAddr3 () == GetAddress ()) |
|
301 { |
|
302 TRACE ("frame for me from="<<hdr->GetAddr2 ()); |
|
303 ForwardUp (packet, hdr->GetAddr2 ()); |
|
304 } |
|
305 else |
|
306 { |
|
307 TRACE ("forwarding frame from="<<hdr->GetAddr2 ()<<", to="<<hdr->GetAddr3 ()); |
|
308 Ptr<Packet> copy = packet->Copy (); |
|
309 ForwardDown (packet, |
|
310 hdr->GetAddr2 (), |
|
311 hdr->GetAddr3 ()); |
|
312 ForwardUp (copy, hdr->GetAddr2 ()); |
|
313 } |
|
314 } |
|
315 else if (hdr->IsFromDs () && |
|
316 hdr->IsToDs ()) |
|
317 { |
|
318 // this is an AP-to-AP frame |
|
319 // we ignore for now. |
|
320 } |
|
321 else |
|
322 { |
|
323 // we can ignore these frames since |
|
324 // they are not targeted at the AP |
|
325 } |
|
326 } |
|
327 else if (hdr->IsMgt ()) |
|
328 { |
|
329 if (hdr->IsProbeReq ()) |
|
330 { |
|
331 NS_ASSERT (hdr->GetAddr1 ().IsBroadcast ()); |
|
332 SendProbeResp (hdr->GetAddr2 ()); |
|
333 } |
|
334 else if (hdr->GetAddr1 () == GetAddress ()) |
|
335 { |
|
336 if (hdr->IsAssocReq ()) |
|
337 { |
|
338 // first, verify that the the station's supported |
|
339 // rate set is compatible with our Basic Rate set |
|
340 MgtAssocRequestHeader assocReq; |
|
341 packet->RemoveHeader (assocReq); |
|
342 SupportedRates rates = assocReq.GetSupportedRates (); |
|
343 bool problem = false; |
|
344 for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++) |
|
345 { |
|
346 WifiMode mode = m_stationManager->GetBasicMode (i); |
|
347 if (!rates.IsSupportedRate (mode.GetDataRate ())) |
|
348 { |
|
349 problem = true; |
|
350 break; |
|
351 } |
|
352 } |
|
353 if (problem) |
|
354 { |
|
355 // one of the Basic Rate set mode is not |
|
356 // supported by the station. So, we return an assoc |
|
357 // response with an error status. |
|
358 SendAssocResp (hdr->GetAddr2 (), false); |
|
359 } |
|
360 else |
|
361 { |
|
362 // station supports all rates in Basic Rate Set. |
|
363 // record all its supported modes in its associated WifiRemoteStation |
|
364 for (uint32_t j = 0; j < m_phy->GetNModes (); j++) |
|
365 { |
|
366 WifiMode mode = m_phy->GetMode (j); |
|
367 if (rates.IsSupportedRate (mode.GetDataRate ())) |
|
368 { |
|
369 station->AddSupportedMode (mode); |
|
370 } |
|
371 } |
|
372 station->RecordWaitAssocTxOk (); |
|
373 // send assoc response with success status. |
|
374 SendAssocResp (hdr->GetAddr2 (), true); |
|
375 } |
|
376 } |
|
377 else if (hdr->IsDisassociation ()) |
|
378 { |
|
379 station->RecordDisassociated (); |
|
380 } |
|
381 else if (hdr->IsReassocReq ()) |
|
382 { |
|
383 /* we don't support reassoc frames for now */ |
|
384 } |
|
385 else if (hdr->IsAuthentication () || |
|
386 hdr->IsDeauthentication ()) |
|
387 { |
|
388 /* |
|
389 */ |
|
390 } |
|
391 else |
|
392 { |
|
393 /* unknown mgt frame |
|
394 */ |
|
395 } |
|
396 } |
|
397 } |
|
398 else |
|
399 { |
|
400 /* damn, what could this be ? a control frame ? |
|
401 * control frames should never reach the MacHigh so, |
|
402 * this is likely to be a bug. assert. |
|
403 */ |
|
404 NS_ASSERT (false); |
|
405 } |
|
406 } |
|
407 |
|
408 } // namespace ns3 |