A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-ht-network.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 MIRKO BANCHI
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Mirko Banchi <mk.banchi@gmail.com>
7 * Sebastien Deronne <sebastien.deronne@gmail.com>
8 */
9
10#include "ns3/attribute-container.h"
11#include "ns3/boolean.h"
12#include "ns3/command-line.h"
13#include "ns3/config.h"
14#include "ns3/double.h"
15#include "ns3/enum.h"
16#include "ns3/ht-phy.h"
17#include "ns3/internet-stack-helper.h"
18#include "ns3/ipv4-address-helper.h"
19#include "ns3/ipv4-global-routing-helper.h"
20#include "ns3/log.h"
21#include "ns3/mobility-helper.h"
22#include "ns3/on-off-helper.h"
23#include "ns3/packet-sink-helper.h"
24#include "ns3/packet-sink.h"
25#include "ns3/ssid.h"
26#include "ns3/string.h"
27#include "ns3/tuple.h"
28#include "ns3/udp-client-server-helper.h"
29#include "ns3/udp-server.h"
30#include "ns3/uinteger.h"
31#include "ns3/yans-wifi-channel.h"
32#include "ns3/yans-wifi-helper.h"
33
34#include <algorithm>
35#include <vector>
36
37// This is a simple example in order to show how to configure an IEEE 802.11n Wi-Fi network.
38//
39// It outputs the UDP or TCP goodput for every HT MCS value, which depends on the MCS value (0 to
40// 7), the channel width (20 or 40 MHz) and the guard interval (long or short). The PHY bitrate is
41// constant over all the simulation run. The user can also specify the distance between the access
42// point and the station: the larger 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("ht-wifi-network");
56
57int
58main(int argc, char* argv[])
59{
60 bool udp{true};
61 bool useRts{false};
62 Time simulationTime{"10s"};
63 meter_u distance{1.0};
64 double frequency{5}; // whether 2.4 or 5 GHz
65 std::string mcsStr;
66 std::vector<uint64_t> mcsValues;
67 int channelWidth{-1}; // in MHz, -1 indicates an unset value
68 int guardInterval{-1}; // in nanoseconds, -1 indicates an unset value
69 double minExpectedThroughput{0.0};
70 double maxExpectedThroughput{0.0};
71
73 cmd.AddValue("frequency",
74 "Whether working in the 2.4 or 5.0 GHz band (other values gets rejected)",
75 frequency);
76 cmd.AddValue("distance",
77 "Distance in meters between the station and the access point",
78 distance);
79 cmd.AddValue("simulationTime", "Simulation time", simulationTime);
80 cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp);
81 cmd.AddValue("useRts", "Enable/disable RTS/CTS", useRts);
82 cmd.AddValue(
83 "mcs",
84 "list of comma separated MCS values to test; if unset, all MCS values (0-7) are tested",
85 mcsStr);
86 cmd.AddValue(
87 "channelWidth",
88 "if set, limit testing to a specific channel width expressed in MHz (20 or 40 MHz)",
89 channelWidth);
90 cmd.AddValue("guardInterval",
91 "if set, limit testing to a specific guard interval duration expressed in "
92 "nanoseconds (800 or 400 ns)",
94 cmd.AddValue("minExpectedThroughput",
95 "if set, simulation fails if the lowest throughput is below this value",
97 cmd.AddValue("maxExpectedThroughput",
98 "if set, simulation fails if the highest throughput is above this value",
100 cmd.Parse(argc, argv);
101
102 if (useRts)
103 {
104 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue("0"));
105 }
106
107 double prevThroughput[8] = {0};
108
109 std::cout << "MCS value"
110 << "\t\t"
111 << "Channel width"
112 << "\t\t"
113 << "short GI"
114 << "\t\t"
115 << "Throughput" << '\n';
116 uint8_t minMcs = 0;
117 uint8_t maxMcs = 7;
118
119 if (mcsStr.empty())
120 {
121 for (uint8_t mcs = minMcs; mcs <= maxMcs; ++mcs)
122 {
123 mcsValues.push_back(mcs);
124 }
125 }
126 else
127 {
128 AttributeContainerValue<UintegerValue, ',', std::vector> attr;
130 checker->SetItemChecker(MakeUintegerChecker<uint8_t>());
131 attr.DeserializeFromString(mcsStr, checker);
132 mcsValues = attr.Get();
133 std::sort(mcsValues.begin(), mcsValues.end());
134 }
135
136 int minChannelWidth = 20;
137 int maxChannelWidth = 40;
138 if (channelWidth >= minChannelWidth && channelWidth <= maxChannelWidth)
139 {
140 minChannelWidth = channelWidth;
141 maxChannelWidth = channelWidth;
142 }
143 int minGi = 400;
144 int maxGi = 800;
145 if (guardInterval >= minGi && guardInterval <= maxGi)
146 {
147 minGi = guardInterval;
149 }
150
151 for (const auto mcs : mcsValues)
152 {
153 uint8_t index = 0;
154 double previous = 0;
155 for (int width = minChannelWidth; width <= maxChannelWidth; width *= 2) // MHz
156 {
157 for (int gi = maxGi; gi >= minGi; gi /= 2) // Nanoseconds
158 {
159 const auto sgi = (gi == 400);
160 uint32_t payloadSize; // 1500 byte IP packet
161 if (udp)
162 {
163 payloadSize = 1472; // bytes
164 }
165 else
166 {
167 payloadSize = 1448; // bytes
168 Config::SetDefault("ns3::TcpSocket::SegmentSize", UintegerValue(payloadSize));
169 }
170
174 wifiApNode.Create(1);
175
178 phy.SetChannel(channel.Create());
179
182 std::ostringstream ossControlMode;
183
184 if (frequency == 5.0)
185 {
186 ossControlMode << "OfdmRate";
187 wifi.SetStandard(WIFI_STANDARD_80211n);
188 }
189 else if (frequency == 2.4)
190 {
191 wifi.SetStandard(WIFI_STANDARD_80211n);
192 ossControlMode << "ErpOfdmRate";
193 Config::SetDefault("ns3::LogDistancePropagationLossModel::ReferenceLoss",
194 DoubleValue(40.046));
195 }
196 else
197 {
198 NS_FATAL_ERROR("Wrong frequency value!");
199 }
200
202 ossControlMode << nonHtRefRateMbps << "Mbps";
203
204 std::ostringstream ossDataMode;
205 ossDataMode << "HtMcs" << mcs;
206 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
207 "DataMode",
209 "ControlMode",
211 // Set guard interval
212 wifi.ConfigHtOptions("ShortGuardIntervalSupported", BooleanValue(sgi));
213
214 Ssid ssid = Ssid("ns3-80211n");
217 ';'>
219 WifiPhyBand band = (frequency == 5.0 ? WIFI_PHY_BAND_5GHZ : WIFI_PHY_BAND_2_4GHZ);
220 channelValue.Set(WifiPhy::ChannelSegments{{0, width, band, 0}});
221
222 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
223 phy.Set("ChannelSettings", channelValue);
224
226 staDevice = wifi.Install(phy, mac, wifiStaNode);
227
228 mac.SetType("ns3::ApWifiMac",
229 "EnableBeaconJitter",
230 BooleanValue(false),
231 "Ssid",
232 SsidValue(ssid));
233
235 apDevice = wifi.Install(phy, mac, wifiApNode);
236
237 int64_t streamNumber = 150;
240
241 // mobility.
244
245 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
246 positionAlloc->Add(Vector(distance, 0.0, 0.0));
247 mobility.SetPositionAllocator(positionAlloc);
248
249 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
250
251 mobility.Install(wifiApNode);
252 mobility.Install(wifiStaNode);
253
254 /* Internet stack*/
256 stack.Install(wifiApNode);
257 stack.Install(wifiStaNode);
258 streamNumber += stack.AssignStreams(wifiApNode, streamNumber);
259 streamNumber += stack.AssignStreams(wifiStaNode, streamNumber);
260
262 address.SetBase("192.168.1.0", "255.255.255.0");
265
268
269 /* Setting applications */
270 const auto maxLoad = HtPhy::GetDataRate(mcs,
271 MHz_u{static_cast<double>(width)},
272 NanoSeconds(sgi ? 400 : 800),
273 1);
274 ApplicationContainer serverApp;
275 if (udp)
276 {
277 // UDP flow
278 uint16_t port = 9;
280 serverApp = server.Install(wifiStaNode.Get(0));
281 streamNumber += server.AssignStreams(wifiStaNode.Get(0), streamNumber);
282
283 serverApp.Start(Seconds(0));
284 serverApp.Stop(simulationTime + Seconds(1));
285 const auto packetInterval = payloadSize * 8.0 / maxLoad;
286
288 client.SetAttribute("MaxPackets", UintegerValue(4294967295U));
289 client.SetAttribute("Interval", TimeValue(Seconds(packetInterval)));
290 client.SetAttribute("PacketSize", UintegerValue(payloadSize));
291 ApplicationContainer clientApp = client.Install(wifiApNode.Get(0));
292 streamNumber += client.AssignStreams(wifiApNode.Get(0), streamNumber);
293
294 clientApp.Start(Seconds(1));
295 clientApp.Stop(simulationTime + Seconds(1));
296 }
297 else
298 {
299 // TCP flow
300 uint16_t port = 50000;
302 PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress);
303 serverApp = packetSinkHelper.Install(wifiStaNode.Get(0));
304 streamNumber +=
305 packetSinkHelper.AssignStreams(wifiStaNode.Get(0), streamNumber);
306
307 serverApp.Start(Seconds(0));
308 serverApp.Stop(simulationTime + Seconds(1));
309
310 OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny());
311 onoff.SetAttribute("OnTime",
312 StringValue("ns3::ConstantRandomVariable[Constant=1]"));
313 onoff.SetAttribute("OffTime",
314 StringValue("ns3::ConstantRandomVariable[Constant=0]"));
315 onoff.SetAttribute("PacketSize", UintegerValue(payloadSize));
316 onoff.SetAttribute("DataRate", DataRateValue(maxLoad));
318 InetSocketAddress(staNodeInterface.GetAddress(0), port));
319 onoff.SetAttribute("Remote", remoteAddress);
320 ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0));
321 streamNumber += onoff.AssignStreams(wifiApNode.Get(0), streamNumber);
322
323 clientApp.Start(Seconds(1));
324 clientApp.Stop(simulationTime + Seconds(1));
325 }
326
328
329 Simulator::Stop(simulationTime + Seconds(1));
331
332 auto rxBytes = 0.0;
333 if (udp)
334 {
335 rxBytes = payloadSize * DynamicCast<UdpServer>(serverApp.Get(0))->GetReceived();
336 }
337 else
338 {
339 rxBytes = DynamicCast<PacketSink>(serverApp.Get(0))->GetTotalRx();
340 }
341 auto throughput = (rxBytes * 8) / simulationTime.GetMicroSeconds(); // Mbit/s
342
344
345 std::cout << mcs << "\t\t\t" << width << " MHz\t\t\t" << std::boolalpha << sgi
346 << "\t\t\t" << throughput << " Mbit/s" << std::endl;
347
348 // test first element
349 if (mcs == minMcs && width == 20 && !sgi)
350 {
352 {
353 NS_FATAL_ERROR("Obtained throughput " << throughput << " is not expected!");
354 }
355 }
356 // test last element
357 if (mcs == maxMcs && width == 40 && sgi)
358 {
360 {
361 NS_FATAL_ERROR("Obtained throughput " << throughput << " is not expected!");
362 }
363 }
364 // test previous throughput is smaller (for the same mcs)
365 if (throughput > previous)
366 {
368 }
369 else
370 {
371 NS_FATAL_ERROR("Obtained throughput " << throughput << " is not expected!");
372 }
373 // test previous throughput is smaller (for the same channel width and GI)
374 if (throughput > prevThroughput[index])
375 {
376 prevThroughput[index] = throughput;
377 }
378 else
379 {
380 NS_FATAL_ERROR("Obtained throughput " << throughput << " is not expected!");
381 }
382 index++;
383 }
384 }
385 }
386 return 0;
387}
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
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
static uint64_t GetNonHtReferenceRate(uint8_t mcsValue)
Calculate the rate in bps of the non-HT Reference Rate corresponding to the supplied HT MCS index.
Definition ht-phy.cc:725
static uint64_t GetDataRate(uint8_t mcsValue, MHz_u channelWidth, Time guardInterval, uint8_t nss)
Return the data rate corresponding to the supplied HT MCS index, channel width, guard interval,...
Definition ht-phy.cc:687
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
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
AttributeValue implementation for Tuple.
Definition tuple.h:67
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
void Set(const uint64_t &value)
Set the value.
Definition uinteger.cc:26
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.
std::vector< ChannelTuple > ChannelSegments
segments identifying an operating channel
Definition wifi-phy.h:947
manage and create wifi channel objects for the YANS model.
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_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#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
WifiPhyBand
Identifies the PHY band.
@ WIFI_STANDARD_80211n
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
address
Definition first.py:36
stack
Definition first.py:33
Every class exported by the ns3 library is enclosed in the ns3 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