|
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
|
2 /* |
|
3 * Copyright (c) 2013 Dalian University of Technology |
|
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: Junling Bu <linlinjavaer@gmail.com> |
|
19 */ |
|
20 #include "ns3/test.h" |
|
21 #include "ns3/rng-seed-manager.h" |
|
22 #include "ns3/config.h" |
|
23 #include "ns3/data-rate.h" |
|
24 #include "ns3/vector.h" |
|
25 #include "ns3/string.h" |
|
26 #include "ns3/ssid.h" |
|
27 #include "ns3/packet-socket-address.h" |
|
28 #include "ns3/mobility-model.h" |
|
29 #include "ns3/on-off-helper.h" |
|
30 #include "ns3/yans-wifi-helper.h" |
|
31 #include "ns3/position-allocator.h" |
|
32 #include "ns3/packet-socket-helper.h" |
|
33 #include "ns3/mobility-helper.h" |
|
34 #include "ns3/nqos-wifi-mac-helper.h" |
|
35 #include "ns3/wifi-net-device.h" |
|
36 #include <iostream> |
|
37 |
|
38 #include "ns3/ocb-wifi-mac.h" |
|
39 #include "ns3/wifi-80211p-helper.h" |
|
40 #include "ns3/wave-mac-helper.h" |
|
41 |
|
42 using namespace ns3; |
|
43 // helper function to assign streams to random variables, to control |
|
44 // randomness in the tests |
|
45 static void |
|
46 AssignWifiRandomStreams (Ptr<WifiMac> mac, int64_t stream) |
|
47 { |
|
48 int64_t currentStream = stream; |
|
49 Ptr<RegularWifiMac> rmac = DynamicCast<RegularWifiMac> (mac); |
|
50 if (rmac) |
|
51 { |
|
52 PointerValue ptr; |
|
53 rmac->GetAttribute ("DcaTxop", ptr); |
|
54 Ptr<DcaTxop> dcaTxop = ptr.Get<DcaTxop> (); |
|
55 currentStream += dcaTxop->AssignStreams (currentStream); |
|
56 |
|
57 rmac->GetAttribute ("VO_EdcaTxopN", ptr); |
|
58 Ptr<EdcaTxopN> vo_edcaTxopN = ptr.Get<EdcaTxopN> (); |
|
59 currentStream += vo_edcaTxopN->AssignStreams (currentStream); |
|
60 |
|
61 rmac->GetAttribute ("VI_EdcaTxopN", ptr); |
|
62 Ptr<EdcaTxopN> vi_edcaTxopN = ptr.Get<EdcaTxopN> (); |
|
63 currentStream += vi_edcaTxopN->AssignStreams (currentStream); |
|
64 |
|
65 rmac->GetAttribute ("BE_EdcaTxopN", ptr); |
|
66 Ptr<EdcaTxopN> be_edcaTxopN = ptr.Get<EdcaTxopN> (); |
|
67 currentStream += be_edcaTxopN->AssignStreams (currentStream); |
|
68 |
|
69 rmac->GetAttribute ("BK_EdcaTxopN", ptr); |
|
70 Ptr<EdcaTxopN> bk_edcaTxopN = ptr.Get<EdcaTxopN> (); |
|
71 currentStream += bk_edcaTxopN->AssignStreams (currentStream); |
|
72 } |
|
73 } |
|
74 |
|
75 class OcbWifiMacTestCase : public TestCase |
|
76 { |
|
77 public: |
|
78 OcbWifiMacTestCase (void); |
|
79 virtual ~OcbWifiMacTestCase (void); |
|
80 private: |
|
81 virtual void DoRun (void); |
|
82 |
|
83 void MacAssoc (std::string context,Mac48Address bssid); |
|
84 void PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble); |
|
85 void PhyTxTrace (std::string context, Ptr<const Packet> packet, WifiMode mode, WifiPreamble preamble, uint8_t txPower); |
|
86 Vector GetCurrentPosition (uint32_t i); |
|
87 void AdvancePosition (Ptr<Node> node); |
|
88 |
|
89 void PreRandomConfiguration (void); |
|
90 void ConfigureApStaMode (Ptr<Node> static_node, Ptr<Node> mobile_node); |
|
91 void ConfigureAdhocMode (Ptr<Node> static_node, Ptr<Node> mobile_node); |
|
92 void ConfigureOcbMode (Ptr<Node> static_node, Ptr<Node> mobile_node); |
|
93 void PostDeviceConfiguration (Ptr<Node> static_node, Ptr<Node> mobile_node); |
|
94 |
|
95 Time phytx_time; |
|
96 Vector phytx_pos; |
|
97 |
|
98 Time macassoc_time; |
|
99 Vector macassoc_pos; |
|
100 |
|
101 Time phyrx_time; |
|
102 Vector phyrx_pos; |
|
103 |
|
104 // nodes.Get (0) is static node |
|
105 // nodes.Get (1) is mobile node |
|
106 NodeContainer nodes; |
|
107 }; |
|
108 |
|
109 OcbWifiMacTestCase::OcbWifiMacTestCase (void) |
|
110 : TestCase ("Association time: Ap+Sta mode vs Adhoc mode vs Ocb mode") |
|
111 { |
|
112 } |
|
113 |
|
114 OcbWifiMacTestCase::~OcbWifiMacTestCase (void) |
|
115 { |
|
116 } |
|
117 |
|
118 // mobility is like walk on line with velocity 5 m/s |
|
119 // We prefer to update 0.5m every 0.1s rather than 5m every 1s |
|
120 void |
|
121 OcbWifiMacTestCase::AdvancePosition (Ptr<Node> node) |
|
122 { |
|
123 Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> (); |
|
124 Vector pos = mobility->GetPosition (); |
|
125 pos.x -= 0.5; |
|
126 if (pos.x < 1.0 ) |
|
127 { |
|
128 pos.x = 1.0; |
|
129 return; |
|
130 } |
|
131 mobility->SetPosition (pos); |
|
132 |
|
133 Simulator::Schedule (Seconds (0.1), &OcbWifiMacTestCase::AdvancePosition, this, node); |
|
134 } |
|
135 |
|
136 // here are only two nodes, a stationary and a mobile one |
|
137 // the i value of the first = 0; the i value of second = 1. |
|
138 Vector |
|
139 OcbWifiMacTestCase::GetCurrentPosition (uint32_t i) |
|
140 { |
|
141 NS_ASSERT (i < 2); |
|
142 Ptr<Node> node = nodes.Get (i); |
|
143 Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> (); |
|
144 Vector pos = mobility->GetPosition (); |
|
145 return pos; |
|
146 } |
|
147 |
|
148 void |
|
149 OcbWifiMacTestCase::MacAssoc (std::string context,Mac48Address bssid) |
|
150 { |
|
151 if (macassoc_time == Time (0)) |
|
152 { |
|
153 macassoc_time = Now (); |
|
154 macassoc_pos = GetCurrentPosition (1); |
|
155 std::cout << "MacAssoc time = " << macassoc_time.GetNanoSeconds () |
|
156 << " position = " << macassoc_pos |
|
157 << std::endl; |
|
158 } |
|
159 } |
|
160 |
|
161 // We want to get the time that sta receives the first beacon frame from AP |
|
162 // it means that in this time this sta has ability to receive frame |
|
163 void |
|
164 OcbWifiMacTestCase::PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble) |
|
165 { |
|
166 if (phyrx_time == Time (0)) |
|
167 { |
|
168 phyrx_time = Now (); |
|
169 phyrx_pos = GetCurrentPosition (1); |
|
170 std::cout << "PhyRxOk time = " << phyrx_time.GetNanoSeconds () |
|
171 << " position = " << phyrx_pos |
|
172 << std::endl; |
|
173 } |
|
174 } |
|
175 |
|
176 // We want to get the time that STA sends the first data packet successfully |
|
177 void |
|
178 OcbWifiMacTestCase::PhyTxTrace (std::string context, Ptr<const Packet> packet, WifiMode mode, WifiPreamble preamble, uint8_t txPower) |
|
179 { |
|
180 WifiMacHeader h; |
|
181 packet->PeekHeader (h); |
|
182 if ((phytx_time == Time (0)) && h.IsData ()) |
|
183 { |
|
184 phytx_time = Now (); |
|
185 phytx_pos = GetCurrentPosition (1); |
|
186 std::cout << "PhyTx data time = " << phytx_time.GetNanoSeconds () |
|
187 << " position = " << phytx_pos |
|
188 << std::endl; |
|
189 } |
|
190 } |
|
191 |
|
192 void |
|
193 OcbWifiMacTestCase::ConfigureApStaMode (Ptr<Node> static_node, Ptr<Node> mobile_node) |
|
194 { |
|
195 YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); |
|
196 YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); |
|
197 wifiPhy.SetChannel (wifiChannel.Create ()); |
|
198 |
|
199 Ssid ssid = Ssid ("wifi-default"); |
|
200 NqosWifiMacHelper wifiStaMac = NqosWifiMacHelper::Default (); |
|
201 wifiStaMac.SetType ("ns3::StaWifiMac", "Ssid", SsidValue (ssid)); |
|
202 NqosWifiMacHelper wifiApMac = NqosWifiMacHelper::Default (); |
|
203 wifiApMac.SetType ("ns3::ApWifiMac","Ssid", SsidValue (ssid)); |
|
204 |
|
205 WifiHelper wifi = WifiHelper::Default (); |
|
206 wifi.SetStandard (WIFI_PHY_STANDARD_80211_10MHZ); |
|
207 wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", |
|
208 "DataMode", StringValue ("OfdmRate6MbpsBW10MHz"), |
|
209 "ControlMode",StringValue ("OfdmRate6MbpsBW10MHz")); |
|
210 wifi.Install (wifiPhy, wifiStaMac, mobile_node); |
|
211 wifi.Install (wifiPhy, wifiApMac, static_node); |
|
212 } |
|
213 |
|
214 void |
|
215 OcbWifiMacTestCase::ConfigureAdhocMode (Ptr<Node> static_node, Ptr<Node> mobile_node) |
|
216 { |
|
217 YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); |
|
218 YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); |
|
219 wifiPhy.SetChannel (wifiChannel.Create ()); |
|
220 |
|
221 NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default (); |
|
222 wifiMac.SetType ("ns3::AdhocWifiMac"); |
|
223 |
|
224 WifiHelper wifi = WifiHelper::Default (); |
|
225 wifi.SetStandard (WIFI_PHY_STANDARD_80211_10MHZ); |
|
226 wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", |
|
227 "DataMode", StringValue ("OfdmRate6MbpsBW10MHz"), |
|
228 "ControlMode",StringValue ("OfdmRate6MbpsBW10MHz")); |
|
229 wifi.Install (wifiPhy, wifiMac, mobile_node); |
|
230 wifi.Install (wifiPhy, wifiMac, static_node); |
|
231 } |
|
232 |
|
233 void |
|
234 OcbWifiMacTestCase::ConfigureOcbMode (Ptr<Node> static_node, Ptr<Node> mobile_node) |
|
235 { |
|
236 YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default (); |
|
237 YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); |
|
238 wifiPhy.SetChannel (wifiChannel.Create ()); |
|
239 |
|
240 NqosWaveMacHelper wifi80211pMac = NqosWaveMacHelper::Default (); |
|
241 |
|
242 Wifi80211pHelper wifi80211p = Wifi80211pHelper::Default (); |
|
243 wifi80211p.SetRemoteStationManager ("ns3::ConstantRateWifiManager", |
|
244 "DataMode", StringValue ("OfdmRate6MbpsBW10MHz"), |
|
245 "ControlMode",StringValue ("OfdmRate6MbpsBW10MHz")); |
|
246 wifi80211p.Install (wifiPhy, wifi80211pMac, mobile_node); |
|
247 wifi80211p.Install (wifiPhy, wifi80211pMac, static_node); |
|
248 } |
|
249 |
|
250 void |
|
251 OcbWifiMacTestCase::PostDeviceConfiguration (Ptr<Node> static_node, Ptr<Node> mobile_node) |
|
252 { |
|
253 Ptr<WifiNetDevice> static_device = DynamicCast<WifiNetDevice> (static_node->GetDevice (0)); |
|
254 Ptr<WifiNetDevice> mobile_device = DynamicCast<WifiNetDevice> (mobile_node->GetDevice (0)); |
|
255 |
|
256 // Fix the stream assignment to the Dcf Txop objects (backoffs) |
|
257 // The below stream assignment will result in the DcaTxop object |
|
258 // using a backoff value of zero for this test when the |
|
259 // DcaTxop::EndTxNoAck() calls to StartBackoffNow() |
|
260 AssignWifiRandomStreams (static_device->GetMac (), 21); |
|
261 AssignWifiRandomStreams (mobile_device->GetMac (), 22); |
|
262 |
|
263 // setup mobility |
|
264 // the initial position of static node is at 0, |
|
265 // and the initial position of mobile node is 350. |
|
266 MobilityHelper mobility; |
|
267 mobility.Install (mobile_node); |
|
268 mobility.Install (static_node); |
|
269 Ptr<MobilityModel> mm = mobile_node->GetObject<MobilityModel> (); |
|
270 Vector possta = mm->GetPosition (); |
|
271 possta.x = 350; |
|
272 mm->SetPosition (possta); |
|
273 Simulator::Schedule (Seconds (1.0), &OcbWifiMacTestCase::AdvancePosition, this, mobile_node); |
|
274 |
|
275 PacketSocketAddress socket; |
|
276 socket.SetSingleDevice (mobile_device->GetIfIndex ()); |
|
277 socket.SetPhysicalAddress (static_device->GetAddress ()); |
|
278 socket.SetProtocol (1); |
|
279 |
|
280 // give packet socket powers to nodes. |
|
281 PacketSocketHelper packetSocket; |
|
282 packetSocket.Install (static_node); |
|
283 packetSocket.Install (mobile_node); |
|
284 |
|
285 OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket)); |
|
286 onoff.SetConstantRate (DataRate ("500kb/s")); |
|
287 ApplicationContainer apps = onoff.Install (mobile_node); |
|
288 apps.Start (Seconds (0.5)); |
|
289 apps.Stop (Seconds (70.0)); |
|
290 |
|
291 phytx_time = macassoc_time = phyrx_time = Time (); |
|
292 phytx_pos = macassoc_pos = phyrx_pos = Vector (); |
|
293 |
|
294 Config::Connect ("/NodeList/1/DeviceList/*/Mac/Assoc", MakeCallback (&OcbWifiMacTestCase::MacAssoc, this)); |
|
295 Config::Connect ("/NodeList/1/DeviceList/*/Phy/State/RxOk", MakeCallback (&OcbWifiMacTestCase::PhyRxOkTrace, this)); |
|
296 Config::Connect ("/NodeList/1/DeviceList/*/Phy/State/Tx", MakeCallback (&OcbWifiMacTestCase::PhyTxTrace, this)); |
|
297 } |
|
298 |
|
299 /** |
|
300 * |
|
301 * static-node:0 <---- mobile-node:1 |
|
302 * * ------ 350m ------- * |
|
303 * |
|
304 * the node transmit range is less than 150m |
|
305 * |
|
306 * Ap+Sta mode vs Adhoc mode vs Ocb mode |
|
307 * first test the time point when the stationary node is |
|
308 * an AP and the mobile node is a Sta |
|
309 * then test when one Ad-hoc node and another Ad-hoc node |
|
310 * last test when one OCB node and another OCB node |
|
311 */ |
|
312 void |
|
313 OcbWifiMacTestCase::DoRun () |
|
314 { |
|
315 std::cout << "test time point for Ap-Sta mode" << std::endl; |
|
316 PreRandomConfiguration (); |
|
317 nodes = NodeContainer (); |
|
318 nodes.Create (2); |
|
319 Ptr<Node> static_node = nodes.Get (0); |
|
320 Ptr<Node> mobile_node = nodes.Get (1); |
|
321 ConfigureApStaMode (static_node, mobile_node); |
|
322 PostDeviceConfiguration (static_node, mobile_node); |
|
323 Simulator::Stop (Seconds (71.0)); |
|
324 Simulator::Run (); |
|
325 Simulator::Destroy (); |
|
326 NS_TEST_ASSERT_MSG_LT (phyrx_time, macassoc_time, "In Sta mode with AP, you cannot associate until receive beacon or AssocResponse frame" ); |
|
327 NS_TEST_ASSERT_MSG_LT (macassoc_time, phytx_time, "In Sta mode with AP, you cannot send data packet until associate" ); |
|
328 NS_TEST_ASSERT_MSG_GT ((phyrx_pos.x - macassoc_pos.x), 0.0, ""); |
|
329 //actually macassoc_pos.x - phytx_pos.x is greater than 0 |
|
330 //however associate switch to send is so fast with less than 100ms |
|
331 //and in our mobility model that every 0.1s update position, |
|
332 //so turn out to be that macassoc_pos.x - phytx_pos.x is equal to 0 |
|
333 //NS_TEST_ASSERT_MSG_GT ((macassoc_pos.x - phytx_pos.x), 0.0, ""); |
|
334 |
|
335 std::cout << "test time point for Adhoc mode" << std::endl; |
|
336 PreRandomConfiguration (); |
|
337 nodes = NodeContainer (); |
|
338 nodes.Create (2); |
|
339 static_node = nodes.Get (0); |
|
340 mobile_node = nodes.Get (1); |
|
341 ConfigureAdhocMode (static_node, mobile_node); |
|
342 PostDeviceConfiguration (static_node, mobile_node); |
|
343 Simulator::Stop (Seconds (71.0)); |
|
344 Simulator::Run (); |
|
345 Simulator::Destroy (); |
|
346 // below test assert will fail, because AdhocWifiMac has not implement state machine. |
|
347 // if someone takes a look at the output in adhoc mode and in Ocb mode |
|
348 // he will find these two outputs are almost same. |
|
349 //NS_TEST_ASSERT_MSG_LT (phyrx_time, macassoc_time, "In Adhoc mode, you cannot associate until receive beacon or AssocResponse frame" ); |
|
350 //NS_TEST_ASSERT_MSG_LT (macassoc_time, phytx_time, "In Adhoc mode, you cannot send data packet until associate" ); |
|
351 //NS_TEST_ASSERT_MSG_GT ((phyrx_pos.x - macassoc_pos.x), 0.0, ""); |
|
352 // below test assert result refer to Ap-Sta mode |
|
353 //NS_TEST_ASSERT_MSG_GT ((macassoc_pos.x - phytx_pos.x), 0.0, ""); |
|
354 |
|
355 std::cout << "test time point for Ocb mode" << std::endl; |
|
356 PreRandomConfiguration (); |
|
357 nodes = NodeContainer (); |
|
358 nodes.Create (2); |
|
359 static_node = nodes.Get (0); |
|
360 mobile_node = nodes.Get (1); |
|
361 ConfigureOcbMode (static_node, mobile_node); |
|
362 PostDeviceConfiguration (static_node, mobile_node); |
|
363 Simulator::Stop (Seconds (71.0)); |
|
364 Simulator::Run (); |
|
365 Simulator::Destroy (); |
|
366 NS_TEST_ASSERT_MSG_EQ (macassoc_time.GetNanoSeconds (), 0, "In Ocb mode, there is no associate state machine" ); |
|
367 NS_TEST_ASSERT_MSG_LT (phytx_time, phyrx_time, "before mobile node receives frames from far static node, it can send data packet directly" ); |
|
368 NS_TEST_ASSERT_MSG_EQ (macassoc_pos.x, 0.0, ""); |
|
369 NS_TEST_ASSERT_MSG_GT ((phytx_pos.x - phyrx_pos.x), 0.0, ""); |
|
370 } |
|
371 void |
|
372 OcbWifiMacTestCase::PreRandomConfiguration () |
|
373 { |
|
374 // Assign a seed and run number, and later fix the assignment of streams to |
|
375 // WiFi random variables, so that the first backoff used is zero slots |
|
376 RngSeedManager::SetSeed (1); |
|
377 RngSeedManager::SetRun (17); |
|
378 // the WiFi random variables is set in PostDeviceConfiguration method. |
|
379 } |
|
380 |
|
381 class OcbTestSuite : public TestSuite |
|
382 { |
|
383 public: |
|
384 OcbTestSuite (); |
|
385 }; |
|
386 |
|
387 OcbTestSuite::OcbTestSuite () |
|
388 : TestSuite ("wifi-80211p-ocb", UNIT) |
|
389 { |
|
390 // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER |
|
391 AddTestCase (new OcbWifiMacTestCase, TestCase::QUICK); |
|
392 } |
|
393 |
|
394 // Do not forget to allocate an instance of this TestSuite |
|
395 static OcbTestSuite ocbTestSuite; |
|
396 |