1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2016 Tom Henderson
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: Tom Henderson <tomh@tomh.org>
19  */
20 
21 // This example shows (and tests) some possible configurations for
22 // the Wi-Fi physical layer, particularly the interaction between
23 // WifiHelper.SetStandard () and the physical layer channel number,
24 // center frequency, and channel width.
25 
26 #include "ns3/log.h"
27 #include "ns3/command-line.h"
28 #include "ns3/config-store.h"
29 #include "ns3/config.h"
30 #include "ns3/boolean.h"
31 #include "ns3/uinteger.h"
32 #include "ns3/string.h"
33 #include "ns3/ssid.h"
34 #include "ns3/yans-wifi-phy.h"
35 #include "ns3/yans-wifi-helper.h"
36 #include "ns3/wifi-net-device.h"
37 
38 using namespace ns3;
39 
40 NS_LOG_COMPONENT_DEFINE ("WifiPhyConfigurationExample");
41 
42 Ptr<YansWifiPhy>
GetYansWifiPhyPtr(const NetDeviceContainer & nc)43 GetYansWifiPhyPtr (const NetDeviceContainer &nc)
44 {
45   Ptr<WifiNetDevice> wnd = nc.Get (0)->GetObject<WifiNetDevice> ();
46   Ptr<WifiPhy> wp = wnd->GetPhy ();
47   return wp->GetObject<YansWifiPhy> ();
48 }
49 
50 void
PrintAttributesIfEnabled(bool enabled)51 PrintAttributesIfEnabled (bool enabled)
52 {
53   if (enabled)
54     {
55       ConfigStore outputConfig;
56       outputConfig.ConfigureAttributes ();
57     }
58 }
59 
main(int argc,char * argv[])60 int main (int argc, char *argv[])
61 {
62   uint32_t testCase = 0;
63   bool printAttributes = false;
64   bool exceptionThrown = false;
65 
66   CommandLine cmd (__FILE__);
67   cmd.AddValue ("testCase", "Test case", testCase);
68   cmd.AddValue ("printAttributes", "If true, print out attributes", printAttributes);
69   cmd.Parse (argc, argv);
70 
71   NodeContainer wifiStaNode;
72   wifiStaNode.Create (1);
73   NodeContainer wifiApNode;
74   wifiApNode.Create (1);
75 
76   YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
77   YansWifiPhyHelper phy;
78   phy.SetChannel (channel.Create ());
79   WifiHelper wifi;
80   wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
81 
82   // Configure and declare other generic components of this example
83   Ssid ssid;
84   ssid = Ssid ("wifi-phy-configuration");
85   WifiMacHelper macSta;
86   macSta.SetType ("ns3::StaWifiMac",
87                   "Ssid", SsidValue (ssid),
88                   "ActiveProbing", BooleanValue (false));
89   WifiMacHelper macAp;
90   macAp.SetType ("ns3::ApWifiMac",
91                  "Ssid", SsidValue (ssid),
92                  "BeaconInterval", TimeValue (MicroSeconds (102400)),
93                  "BeaconGeneration", BooleanValue (true));
94   NetDeviceContainer staDevice;
95   NetDeviceContainer apDevice;
96   Ptr<YansWifiPhy> phySta;
97   Config::SetDefault ("ns3::ConfigStore::Filename", StringValue ("output-attributes-" + std::to_string (testCase) + ".txt"));
98   Config::SetDefault ("ns3::ConfigStore::FileFormat", StringValue ("RawText"));
99   Config::SetDefault ("ns3::ConfigStore::Mode", StringValue ("Save"));
100 
101   switch (testCase)
102     {
103     case 0:
104       // Default configuration, without WifiHelper::SetStandard or WifiHelper
105       phySta = CreateObject<YansWifiPhy> ();
106       // The default results in an invalid configuration
107       NS_ASSERT (!phySta->GetOperatingChannel ().IsSet ());
108       PrintAttributesIfEnabled (printAttributes);
109       break;
110 
111     // The following cases test the setting of WifiPhyStandard alone;
112     // i.e. without further channel number/width/frequency configuration
113 
114     case 1:
115       // By default, WifiHelper will use WIFI_STANDARD_80211a
116       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
117       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
118       phySta = GetYansWifiPhyPtr (staDevice);
119       // We expect channel 36, width 20, frequency 5180
120       NS_ASSERT (phySta->GetChannelNumber () == 36);
121       NS_ASSERT (phySta->GetChannelWidth () == 20);
122       NS_ASSERT (phySta->GetFrequency () == 5180);
123       PrintAttributesIfEnabled (printAttributes);
124       break;
125     case 2:
126       wifi.SetStandard (WIFI_STANDARD_80211b);
127       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
128       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
129       phySta = GetYansWifiPhyPtr (staDevice);
130       // We expect channel 1, width 22, frequency 2412
131       NS_ASSERT (phySta->GetChannelNumber () == 1);
132       NS_ASSERT (phySta->GetChannelWidth () == 22);
133       NS_ASSERT (phySta->GetFrequency () == 2412);
134       PrintAttributesIfEnabled (printAttributes);
135       break;
136     case 3:
137       wifi.SetStandard (WIFI_STANDARD_80211g);
138       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
139       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
140       phySta = GetYansWifiPhyPtr (staDevice);
141       // We expect channel 1, width 20, frequency 2412
142       NS_ASSERT (phySta->GetChannelNumber () == 1);
143       NS_ASSERT (phySta->GetChannelWidth () == 20);
144       NS_ASSERT (phySta->GetFrequency () == 2412);
145       PrintAttributesIfEnabled (printAttributes);
146       break;
147     case 4:
148       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
149       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
150       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
151       phySta = GetYansWifiPhyPtr (staDevice);
152       // We expect channel 36, width 20, frequency 5180
153       NS_ASSERT (phySta->GetChannelNumber () == 36);
154       NS_ASSERT (phySta->GetChannelWidth () == 20);
155       NS_ASSERT (phySta->GetFrequency () == 5180);
156       PrintAttributesIfEnabled (printAttributes);
157       break;
158     case 5:
159       wifi.SetStandard (WIFI_STANDARD_80211n_2_4GHZ);
160       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
161       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
162       phySta = GetYansWifiPhyPtr (staDevice);
163       // We expect channel 1, width 20, frequency 2412
164       NS_ASSERT (phySta->GetChannelNumber () == 1);
165       NS_ASSERT (phySta->GetChannelWidth () == 20);
166       NS_ASSERT (phySta->GetFrequency () == 2412);
167       PrintAttributesIfEnabled (printAttributes);
168       break;
169     case 6:
170       wifi.SetStandard (WIFI_STANDARD_80211ac);
171       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
172       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
173       phySta = GetYansWifiPhyPtr (staDevice);
174       // We expect channel 42, width 80, frequency 5210
175       NS_ASSERT (phySta->GetChannelNumber () == 42);
176       NS_ASSERT (phySta->GetChannelWidth () == 80);
177       NS_ASSERT (phySta->GetFrequency () == 5210);
178       PrintAttributesIfEnabled (printAttributes);
179       break;
180     case 7:
181       wifi.SetStandard (WIFI_STANDARD_80211ax_2_4GHZ);
182       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
183       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
184       phySta = GetYansWifiPhyPtr (staDevice);
185       // We expect channel 1, width 20, frequency 2412
186       NS_ASSERT (phySta->GetChannelNumber () == 1);
187       NS_ASSERT (phySta->GetChannelWidth () == 20);
188       NS_ASSERT (phySta->GetFrequency () == 2412);
189       PrintAttributesIfEnabled (printAttributes);
190       break;
191     case 8:
192       wifi.SetStandard (WIFI_STANDARD_80211ax_5GHZ);
193       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
194       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
195       phySta = GetYansWifiPhyPtr (staDevice);
196       // We expect channel 42, width 80, frequency 5210
197       NS_ASSERT (phySta->GetChannelNumber () == 42);
198       NS_ASSERT (phySta->GetChannelWidth () == 80);
199       NS_ASSERT (phySta->GetFrequency () == 5210);
200       PrintAttributesIfEnabled (printAttributes);
201       break;
202     case 9:
203       wifi.SetStandard (WIFI_STANDARD_80211ax_6GHZ);
204       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
205       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
206       phySta = GetYansWifiPhyPtr (staDevice);
207       // We expect channel 7, width 80, frequency 5975
208       NS_ASSERT (phySta->GetChannelNumber () == 7);
209       NS_ASSERT (phySta->GetChannelWidth () == 80);
210       NS_ASSERT (phySta->GetFrequency () == 5975);
211       PrintAttributesIfEnabled (printAttributes);
212       break;
213     case 10:
214       wifi.SetStandard (WIFI_STANDARD_80211p);
215       phy.Set ("ChannelWidth", UintegerValue (10));
216       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
217       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
218       phySta = GetYansWifiPhyPtr (staDevice);
219       // We expect channel 172, width 10, frequency 5860
220       NS_ASSERT (phySta->GetChannelNumber () == 172);
221       NS_ASSERT (phySta->GetChannelWidth () == 10);
222       NS_ASSERT (phySta->GetFrequency () == 5860);
223       PrintAttributesIfEnabled (printAttributes);
224       break;
225     case 11:
226       wifi.SetStandard (WIFI_STANDARD_80211p);
227       phy.Set ("ChannelWidth", UintegerValue (5));
228       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
229       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
230       phySta = GetYansWifiPhyPtr (staDevice);
231       // We expect channel 171, width 5, frequency 5860
232       NS_ASSERT (phySta->GetChannelNumber () == 171);
233       NS_ASSERT (phySta->GetChannelWidth () == 5);
234       NS_ASSERT (phySta->GetFrequency () == 5860);
235       PrintAttributesIfEnabled (printAttributes);
236       break;
237     case 12:
238       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
239       phy.Set ("ChannelNumber", UintegerValue (44));
240       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
241       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
242       phySta = GetYansWifiPhyPtr (staDevice);
243       // We expect channel 44, width 20, frequency 5220
244       NS_ASSERT (phySta->GetChannelNumber () == 44);
245       NS_ASSERT (phySta->GetChannelWidth () == 20);
246       NS_ASSERT (phySta->GetFrequency () == 5220);
247       PrintAttributesIfEnabled (printAttributes);
248       break;
249     case 13:
250       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
251       phy.Set ("ChannelNumber", UintegerValue (44));
252       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
253       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
254       phySta = GetYansWifiPhyPtr (staDevice);
255       // Post-install reconfiguration to channel number 40
256       Config::Set ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/ChannelNumber", UintegerValue (40));
257       Config::Set ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/ChannelNumber", UintegerValue (40));
258       // We expect channel 40, width 20, frequency 5200
259       NS_ASSERT (phySta->GetChannelNumber () == 40);
260       NS_ASSERT (phySta->GetChannelWidth () == 20);
261       NS_ASSERT (phySta->GetFrequency () == 5200);
262       PrintAttributesIfEnabled (printAttributes);
263       break;
264     case 14:
265       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
266       phy.Set ("ChannelNumber", UintegerValue (44));
267       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
268       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
269       phySta = GetYansWifiPhyPtr (staDevice);
270       // Post-install reconfiguration to a 40 MHz channel
271       Config::Set ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/ChannelNumber", UintegerValue (46));
272       Config::Set ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/ChannelNumber", UintegerValue (46));
273       NS_ASSERT (phySta->GetChannelNumber () == 46);
274       NS_ASSERT (phySta->GetChannelWidth () == 40);
275       NS_ASSERT (phySta->GetFrequency () == 5230);
276       PrintAttributesIfEnabled (printAttributes);
277       break;
278     case 15:
279       Config::SetDefault ("ns3::WifiPhy::ChannelNumber", UintegerValue (44));
280       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
281       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
282       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
283       phySta = GetYansWifiPhyPtr (staDevice);
284       // Post-install reconfiguration to a 40 MHz channel
285       Config::Set ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/ChannelNumber", UintegerValue (46));
286       Config::Set ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/ChannelNumber", UintegerValue (46));
287       NS_ASSERT (phySta->GetChannelNumber () == 46);
288       NS_ASSERT (phySta->GetChannelWidth () == 40);
289       NS_ASSERT (phySta->GetFrequency () == 5230);
290       PrintAttributesIfEnabled (printAttributes);
291       break;
292     case 16:
293       // Test that setting Frequency to a non-standard value will throw an exception
294       Config::SetDefault ("ns3::WifiPhy::Frequency", UintegerValue (5281));
295       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
296       exceptionThrown = false;
297       try
298         {
299           staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
300         }
301       catch (const std::runtime_error&)
302         {
303           exceptionThrown = true;
304         }
305       NS_ASSERT (exceptionThrown);
306       exceptionThrown = false;
307       try
308         {
309           apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
310         }
311       catch (const std::runtime_error&)
312         {
313           exceptionThrown = true;
314         }
315       NS_ASSERT (exceptionThrown);
316       PrintAttributesIfEnabled (printAttributes);
317       break;
318     case 17:
319       // Test that setting Frequency to a standard value will set the
320       // channel number correctly
321       Config::SetDefault ("ns3::WifiPhy::Frequency", UintegerValue (5500));
322       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
323       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
324       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
325       phySta = GetYansWifiPhyPtr (staDevice);
326       // We expect channel number to be 100 due to frequency 5500
327       NS_ASSERT (phySta->GetChannelNumber () == 100);
328       NS_ASSERT (phySta->GetChannelWidth () == 20);
329       NS_ASSERT (phySta->GetFrequency () == 5500);
330       PrintAttributesIfEnabled (printAttributes);
331       break;
332     case 18:
333       // Set a wrong channel after initialization
334       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
335       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
336       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
337       phySta = GetYansWifiPhyPtr (staDevice);
338       exceptionThrown = false;
339       try
340         {
341           phySta->SetOperatingChannel (99, 5185, 40);
342         }
343       catch (const std::runtime_error&)
344         {
345           exceptionThrown = true;
346         }
347       NS_ASSERT (exceptionThrown);
348       PrintAttributesIfEnabled (printAttributes);
349       break;
350     case 19:
351       // Test how channel number behaves when frequency is non-standard
352       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
353       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
354       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
355       phySta = GetYansWifiPhyPtr (staDevice);
356       exceptionThrown = false;
357       try
358         {
359           phySta->SetAttribute ("Frequency", UintegerValue (5181));
360         }
361       catch (const std::runtime_error&)
362         {
363           exceptionThrown = true;
364         }
365       // We expect that an exception is thrown due to unknown center frequency 5181
366       NS_ASSERT (exceptionThrown);
367       phySta->SetAttribute ("Frequency", UintegerValue (5180));
368       // We expect channel number to be 36 due to known center frequency 5180
369       NS_ASSERT (phySta->GetChannelNumber () == 36);
370       NS_ASSERT (phySta->GetChannelWidth () == 20);
371       NS_ASSERT (phySta->GetFrequency () == 5180);
372       exceptionThrown = false;
373       try
374         {
375           phySta->SetAttribute ("Frequency", UintegerValue (5179));
376         }
377       catch (const std::runtime_error&)
378         {
379           exceptionThrown = true;
380         }
381       // We expect that an exception is thrown due to unknown center frequency 5179
382       NS_ASSERT (exceptionThrown);
383       phySta->SetAttribute ("ChannelNumber", UintegerValue (36));
384       NS_ASSERT (phySta->GetChannelNumber () == 36);
385       NS_ASSERT (phySta->GetChannelWidth () == 20);
386       NS_ASSERT (phySta->GetFrequency () == 5180);
387       PrintAttributesIfEnabled (printAttributes);
388       break;
389     case 20:
390       // Set both channel and frequency to consistent values before initialization
391       Config::SetDefault ("ns3::WifiPhy::Frequency", UintegerValue (5200));
392       Config::SetDefault ("ns3::WifiPhy::ChannelNumber", UintegerValue (40));
393       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
394       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
395       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
396       phySta = GetYansWifiPhyPtr (staDevice);
397       NS_ASSERT (phySta->GetChannelNumber () == 40);
398       NS_ASSERT (phySta->GetChannelWidth () == 20);
399       NS_ASSERT (phySta->GetFrequency () == 5200);
400       // Set both channel and frequency to consistent values after initialization
401       wifi.SetStandard (WIFI_STANDARD_80211n_5GHZ);
402       staDevice = wifi.Install (phy, macSta, wifiStaNode.Get (0));
403       apDevice = wifi.Install (phy, macAp, wifiApNode.Get (0));
404       phySta = GetYansWifiPhyPtr (staDevice);
405       phySta->SetAttribute ("Frequency", UintegerValue (5200));
406       phySta->SetAttribute ("ChannelNumber", UintegerValue (40));
407       NS_ASSERT (phySta->GetChannelNumber () == 40);
408       NS_ASSERT (phySta->GetChannelWidth () == 20);
409       NS_ASSERT (phySta->GetFrequency () == 5200);
410       // Set both channel and frequency to inconsistent values
411       phySta->SetAttribute ("Frequency", UintegerValue (5200));
412       phySta->SetAttribute ("ChannelNumber", UintegerValue (36));
413       // We expect channel number to be 36
414       NS_ASSERT (phySta->GetChannelNumber () == 36);
415       NS_ASSERT (phySta->GetChannelWidth () == 20);
416       NS_ASSERT (phySta->GetFrequency () == 5180);
417       phySta->SetAttribute ("ChannelNumber", UintegerValue (36));
418       phySta->SetAttribute ("Frequency", UintegerValue (5200));
419       // We expect channel number to be 40
420       NS_ASSERT (phySta->GetChannelNumber () == 40);
421       NS_ASSERT (phySta->GetChannelWidth () == 20);
422       NS_ASSERT (phySta->GetFrequency () == 5200);
423       exceptionThrown = false;
424       try
425         {
426           phySta->SetAttribute ("Frequency", UintegerValue (5179));
427         }
428       catch (const std::runtime_error&)
429         {
430           exceptionThrown = true;
431         }
432       phySta->SetAttribute ("ChannelNumber", UintegerValue (36));
433       // We expect channel number to be 36 and an exception to be thrown
434       NS_ASSERT (phySta->GetChannelNumber () == 36);
435       NS_ASSERT (phySta->GetChannelWidth () == 20);
436       NS_ASSERT (phySta->GetFrequency () == 5180);
437       NS_ASSERT (exceptionThrown);
438       phySta->SetAttribute ("ChannelNumber", UintegerValue (36));
439       exceptionThrown = false;
440       try
441         {
442           phySta->SetAttribute ("Frequency", UintegerValue (5179));
443         }
444       catch (const std::runtime_error&)
445         {
446           exceptionThrown = true;
447         }
448       // We expect channel number to be 36 and an exception to be thrown
449       NS_ASSERT (phySta->GetChannelNumber () == 36);
450       NS_ASSERT (phySta->GetChannelWidth () == 20);
451       NS_ASSERT (phySta->GetFrequency () == 5180);
452       NS_ASSERT (exceptionThrown);
453       PrintAttributesIfEnabled (printAttributes);
454       break;
455     default:
456       std::cerr << "Invalid testcase number " << testCase << std::endl;
457       exit (1);
458       break;
459     }
460 
461   // No need to Simulator::Run (); this is a configuration example
462   Simulator::Destroy ();
463 }
464