A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-vht-network.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 SEBASTIEN DERONNE
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sebastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "ns3/attribute-container.h"
10#include "ns3/boolean.h"
11#include "ns3/command-line.h"
12#include "ns3/config.h"
13#include "ns3/double.h"
14#include "ns3/internet-stack-helper.h"
15#include "ns3/ipv4-address-helper.h"
16#include "ns3/ipv4-global-routing-helper.h"
17#include "ns3/log.h"
18#include "ns3/mobility-helper.h"
19#include "ns3/multi-model-spectrum-channel.h"
20#include "ns3/on-off-helper.h"
21#include "ns3/packet-sink-helper.h"
22#include "ns3/packet-sink.h"
23#include "ns3/spectrum-wifi-helper.h"
24#include "ns3/ssid.h"
25#include "ns3/string.h"
26#include "ns3/udp-client-server-helper.h"
27#include "ns3/udp-server.h"
28#include "ns3/uinteger.h"
29#include "ns3/vht-phy.h"
30#include "ns3/yans-wifi-channel.h"
31#include "ns3/yans-wifi-helper.h"
32
33#include <algorithm>
34#include <vector>
35
36// This is a simple example in order to show how to configure an IEEE 802.11ac Wi-Fi network.
37//
38// It outputs the UDP or TCP goodput for every VHT MCS value, which depends on the MCS value (0 to
39// 9, where 9 is forbidden when the channel width is 20 MHz), the channel width (20, 40, 80 or 160
40// MHz) and the guard interval (long or short). The PHY bitrate is constant over all the simulation
41// run. The user can also specify the distance between the access point and the station: the larger
42// the distance the smaller the goodput.
43//
44// The simulation assumes a single station in an infrastructure network:
45//
46// STA AP
47// * *
48// | |
49// n1 n2
50//
51// Packets in this simulation belong to BestEffort Access Class (AC_BE).
52
53using namespace ns3;
54
55NS_LOG_COMPONENT_DEFINE("vht-wifi-network");
56
57int
58main(int argc, char* argv[])
59{
60 bool udp{true};
61 bool useRts{false};
62 bool use80Plus80{false};
63 Time simulationTime{"10s"};
64 meter_u distance{1.0};
65 std::string mcsStr;
66 std::vector<uint64_t> mcsValues;
67 std::string phyModel{"Yans"};
68 int channelWidth{-1}; // in MHz, -1 indicates an unset value
69 int guardInterval{-1}; // in nanoseconds, -1 indicates an unset value
70 double minExpectedThroughput{0.0};
71 double maxExpectedThroughput{0.0};
72
74 cmd.AddValue("distance",
75 "Distance in meters between the station and the access point",
76 distance);
77 cmd.AddValue("simulationTime", "Simulation time", simulationTime);
78 cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp);
79 cmd.AddValue("useRts", "Enable/disable RTS/CTS", useRts);
80 cmd.AddValue("use80Plus80", "Enable/disable use of 80+80 MHz", use80Plus80);
81 cmd.AddValue(
82 "mcs",
83 "list of comma separated MCS values to test; if unset, all MCS values (0-9) are tested",
84 mcsStr);
85 cmd.AddValue("phyModel",
86 "PHY model to use (Yans or Spectrum). If 80+80 MHz is enabled, then Spectrum is "
87 "automatically selected",
88 phyModel);
89 cmd.AddValue("channelWidth",
90 "if set, limit testing to a specific channel width expressed in MHz (20, 40, 80 "
91 "or 160 MHz)",
92 channelWidth);
93 cmd.AddValue("guardInterval",
94 "if set, limit testing to a specific guard interval duration expressed in "
95 "nanoseconds (800 or 400 ns)",
97 cmd.AddValue("minExpectedThroughput",
98 "if set, simulation fails if the lowest throughput is below this value",
100 cmd.AddValue("maxExpectedThroughput",
101 "if set, simulation fails if the highest throughput is above this value",
103 cmd.Parse(argc, argv);
104
105 if (phyModel != "Yans" && phyModel != "Spectrum")
106 {
107 NS_ABORT_MSG("Invalid PHY model (must be Yans or Spectrum)");
108 }
109 if (use80Plus80)
110 {
111 // SpectrumWifiPhy is required for 80+80 MHz
112 phyModel = "Spectrum";
113 }
114
115 if (useRts)
116 {
117 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue("0"));
118 }
119
120 double prevThroughput[8] = {0};
121
122 std::cout << "MCS value"
123 << "\t\t"
124 << "Channel width"
125 << "\t\t"
126 << "short GI"
127 << "\t\t"
128 << "Throughput" << '\n';
129 uint8_t minMcs = 0;
130 uint8_t maxMcs = 9;
131
132 if (mcsStr.empty())
133 {
134 for (uint8_t mcs = minMcs; mcs <= maxMcs; ++mcs)
135 {
136 mcsValues.push_back(mcs);
137 }
138 }
139 else
140 {
141 AttributeContainerValue<UintegerValue, ',', std::vector> attr;
143 checker->SetItemChecker(MakeUintegerChecker<uint8_t>());
144 attr.DeserializeFromString(mcsStr, checker);
145 mcsValues = attr.Get();
146 std::sort(mcsValues.begin(), mcsValues.end());
147 }
148
149 int minChannelWidth = 20;
150 int maxChannelWidth = 160;
151 if (channelWidth >= minChannelWidth && channelWidth <= maxChannelWidth)
152 {
153 minChannelWidth = channelWidth;
154 maxChannelWidth = channelWidth;
155 }
156 int minGi = 400;
157 int maxGi = 800;
158 if (guardInterval >= minGi && guardInterval <= maxGi)
159 {
160 minGi = guardInterval;
162 }
163
164 for (const auto mcs : mcsValues)
165 {
166 uint8_t index = 0;
167 double previous = 0;
168 for (int width = minChannelWidth; width <= maxChannelWidth; width *= 2) // MHz
169 {
170 if (mcs == 9 && width == 20)
171 {
172 continue;
173 }
174 const auto is80Plus80 = (use80Plus80 && (width == 160));
175 const std::string widthStr = is80Plus80 ? "80+80" : std::to_string(width);
176 const auto segmentWidthStr = is80Plus80 ? "80" : widthStr;
177 for (int gi = maxGi; gi >= minGi; gi /= 2) // Nanoseconds
178 {
179 const auto sgi = (gi == 400);
180 uint32_t payloadSize; // 1500 byte IP packet
181 if (udp)
182 {
183 payloadSize = 1472; // bytes
184 }
185 else
186 {
187 payloadSize = 1448; // bytes
188 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(payloadSize));
189 }
190
194 wifiApNode.Create(1);
195
200 std::string channelStr{"{0, " + segmentWidthStr + ", BAND_5GHZ, 0}"};
201
202 std::ostringstream ossControlMode;
204 ossControlMode << "OfdmRate" << nonHtRefRateMbps << "Mbps";
205
206 std::ostringstream ossDataMode;
207 ossDataMode << "VhtMcs" << mcs;
208
209 if (is80Plus80)
210 {
211 channelStr += std::string(";") + channelStr;
212 }
213
214 wifi.SetStandard(WIFI_STANDARD_80211ac);
215 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
216 "DataMode",
218 "ControlMode",
220
221 // Set guard interval
222 wifi.ConfigHtOptions("ShortGuardIntervalSupported", BooleanValue(sgi));
223
224 Ssid ssid = Ssid("ns3-80211ac");
225
226 if (phyModel == "Spectrum")
227 {
230 spectrumChannel->AddPropagationLossModel(lossModel);
231
233 phy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11_RADIO);
234 phy.SetChannel(spectrumChannel);
235
236 phy.Set("ChannelSettings",
237 StringValue("{0, " + std::to_string(width) + ", BAND_5GHZ, 0}"));
238
239 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
240 staDevice = wifi.Install(phy, mac, wifiStaNode);
241
242 mac.SetType("ns3::ApWifiMac",
243 "EnableBeaconJitter",
244 BooleanValue(false),
245 "Ssid",
246 SsidValue(ssid));
247 apDevice = wifi.Install(phy, mac, wifiApNode);
248 }
249 else
250 {
253 phy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11_RADIO);
254 phy.SetChannel(channel.Create());
255
256 phy.Set("ChannelSettings",
257 StringValue("{0, " + std::to_string(width) + ", BAND_5GHZ, 0}"));
258
259 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
260 staDevice = wifi.Install(phy, mac, wifiStaNode);
261
262 mac.SetType("ns3::ApWifiMac",
263 "EnableBeaconJitter",
264 BooleanValue(false),
265 "Ssid",
266 SsidValue(ssid));
267 apDevice = wifi.Install(phy, mac, wifiApNode);
268 }
269
270 int64_t streamNumber = 150;
273
274 // mobility.
277
278 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
279 positionAlloc->Add(Vector(distance, 0.0, 0.0));
280 mobility.SetPositionAllocator(positionAlloc);
281
282 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
283
284 mobility.Install(wifiApNode);
285 mobility.Install(wifiStaNode);
286
287 /* Internet stack*/
289 stack.Install(wifiApNode);
290 stack.Install(wifiStaNode);
291 streamNumber += stack.AssignStreams(wifiApNode, streamNumber);
292 streamNumber += stack.AssignStreams(wifiStaNode, streamNumber);
293
295 address.SetBase("192.168.1.0", "255.255.255.0");
298
301
302 /* Setting applications */
303 const auto maxLoad = VhtPhy::GetDataRate(mcs,
304 MHz_u{static_cast<double>(width)},
305 NanoSeconds(sgi ? 400 : 800),
306 1);
307 ApplicationContainer serverApp;
308 if (udp)
309 {
310 // UDP flow
311 uint16_t port = 9;
313 serverApp = server.Install(wifiStaNode.Get(0));
314 streamNumber += server.AssignStreams(wifiStaNode.Get(0), streamNumber);
315
316 serverApp.Start(Seconds(0));
317 serverApp.Stop(simulationTime + Seconds(1));
318 const auto packetInterval = payloadSize * 8.0 / maxLoad;
319
321 client.SetAttribute("MaxPackets", UintegerValue(4294967295U));
322 client.SetAttribute("Interval", TimeValue(Seconds(packetInterval)));
323 client.SetAttribute("PacketSize", UintegerValue(payloadSize));
324 ApplicationContainer clientApp = client.Install(wifiApNode.Get(0));
325 streamNumber += client.AssignStreams(wifiApNode.Get(0), streamNumber);
326
327 clientApp.Start(Seconds(1));
328 clientApp.Stop(simulationTime + Seconds(1));
329 }
330 else
331 {
332 // TCP flow
333 uint16_t port = 50000;
335 PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress);
336 serverApp = packetSinkHelper.Install(wifiStaNode.Get(0));
337 streamNumber +=
338 packetSinkHelper.AssignStreams(wifiStaNode.Get(0), streamNumber);
339
340 serverApp.Start(Seconds(0));
341 serverApp.Stop(simulationTime + Seconds(1));
342
343 OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny());
344 onoff.SetAttribute("OnTime",
345 StringValue("ns3::ConstantRandomVariable[Constant=1]"));
346 onoff.SetAttribute("OffTime",
347 StringValue("ns3::ConstantRandomVariable[Constant=0]"));
348 onoff.SetAttribute("PacketSize", UintegerValue(payloadSize));
349 onoff.SetAttribute("DataRate", DataRateValue(maxLoad));
351 InetSocketAddress(staNodeInterface.GetAddress(0), port));
352 onoff.SetAttribute("Remote", remoteAddress);
353 ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0));
354 streamNumber += onoff.AssignStreams(wifiApNode.Get(0), streamNumber);
355
356 clientApp.Start(Seconds(1));
357 clientApp.Stop(simulationTime + Seconds(1));
358 }
359
361
362 Simulator::Stop(simulationTime + Seconds(1));
364
365 auto rxBytes = 0.0;
366 if (udp)
367 {
368 rxBytes = payloadSize * DynamicCast<UdpServer>(serverApp.Get(0))->GetReceived();
369 }
370 else
371 {
372 rxBytes = DynamicCast<PacketSink>(serverApp.Get(0))->GetTotalRx();
373 }
374 auto throughput = (rxBytes * 8) / simulationTime.GetMicroSeconds(); // Mbit/s
375
377
378 std::cout << +mcs << "\t\t\t" << widthStr << " MHz\t\t"
379 << (widthStr.size() > 3 ? "" : "\t") << (sgi ? "400 ns" : "800 ns")
380 << "\t\t\t" << throughput << " Mbit/s" << std::endl;
381
382 // test first element
383 if (mcs == minMcs && width == 20 && !sgi)
384 {
386 {
387 NS_LOG_ERROR("Obtained throughput " << throughput << " is not expected!");
388 exit(1);
389 }
390 }
391 // test last element
392 if (mcs == maxMcs && width == 160 && sgi)
393 {
395 {
396 NS_LOG_ERROR("Obtained throughput " << throughput << " is not expected!");
397 exit(1);
398 }
399 }
400 // test previous throughput is smaller (for the same mcs)
401 if (throughput > previous)
402 {
404 }
405 else
406 {
407 NS_LOG_ERROR("Obtained throughput " << throughput << " is not expected!");
408 exit(1);
409 }
410 // test previous throughput is smaller (for the same channel width and GI)
411 if (throughput > prevThroughput[index])
412 {
413 prevThroughput[index] = throughput;
414 }
415 else
416 {
417 NS_LOG_ERROR("Obtained throughput " << throughput << " is not expected!");
418 exit(1);
419 }
420 index++;
421 }
422 }
423 }
424 return 0;
425}
a polymophic address class
Definition address.h:90
AttributeValue implementation for Address.
Definition address.h:275
holds a vector of ns3::Application pointers.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
Ptr< Application > Get(uint32_t i) const
Get the Ptr<Application> stored in this container at a given index.
void Stop(Time stop) const
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
A container for one type of attribute.
AttributeValue implementation for Boolean.
Definition boolean.h:26
Parse command-line arguments.
AttributeValue implementation for DataRate.
Definition data-rate.h:285
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
static Ipv4Address GetAny()
static void PopulateRoutingTables()
Build a routing database and initialize the routing tables of the nodes in the simulation.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
A helper to make it easier to instantiate an ns3::OnOffApplication on a set of nodes.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
AttributeValue implementation for Time.
Definition nstime.h:1431
Create a client application which sends UDP packets carrying a 32bit sequence number and a 64 bit tim...
Create a server application which waits for input UDP packets and uses the information carried into t...
Hold an unsigned integer type.
Definition uinteger.h:34
static uint64_t GetDataRate(uint8_t mcsValue, MHz_u channelWidth, Time guardInterval, uint8_t nss)
Return the data rate corresponding to the supplied VHT MCS index, channel width, guard interval,...
Definition vht-phy.cc:448
static uint64_t GetNonHtReferenceRate(uint8_t mcsValue)
Calculate the rate in bps of the non-HT Reference Rate corresponding to the supplied VHT MCS index.
Definition vht-phy.cc:478
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
create MAC layers for a ns3::WifiNetDevice.
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
static YansWifiChannelHelper Default()
Create a channel helper in a default working state.
Make it easy to create and manage PHY objects for the YANS model.
uint16_t port
Definition dsdv-manet.cc:33
Ptr< AttributeChecker > MakeAttributeContainerChecker()
Make uninitialized AttributeContainerChecker using explicit types.
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:883
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1380
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
@ WIFI_STANDARD_80211ac
address
Definition first.py:36
stack
Definition first.py:33
Every class exported by the ns3 library is enclosed in the ns3 namespace.
STL namespace.
ssid
Definition third.py:82
channel
Definition third.py:77
mac
Definition third.py:81
wifi
Definition third.py:84
wifiApNode
Definition third.py:75
mobility
Definition third.py:92
phy
Definition third.py:78
std::ofstream throughput