49#include "ns3/boolean.h"
50#include "ns3/command-line.h"
51#include "ns3/config.h"
52#include "ns3/double.h"
54#include "ns3/gnuplot.h"
55#include "ns3/he-configuration.h"
56#include "ns3/ht-configuration.h"
58#include "ns3/mobility-helper.h"
59#include "ns3/packet-socket-client.h"
60#include "ns3/packet-socket-helper.h"
61#include "ns3/packet-socket-server.h"
62#include "ns3/propagation-delay-model.h"
63#include "ns3/propagation-loss-model.h"
64#include "ns3/rng-seed-manager.h"
67#include "ns3/uinteger.h"
68#include "ns3/wifi-mac.h"
69#include "ns3/wifi-net-device.h"
70#include "ns3/yans-wifi-helper.h"
104 NS_LOG_DEBUG(
"Change from " << oldVal <<
" to " << newVal);
189 actualDataset.
Add(snr, currentRate);
190 rssModel->SetRss(rss - step.
stepSize);
193 <<
"; setting new power to " << rss - step.
stepSize);
205main(
int argc,
char* argv[])
207 std::vector<StandardInfo> serverStandards;
208 std::vector<StandardInfo> clientStandards;
215 bool broadcast =
false;
220 uint16_t serverNss = 1;
221 uint16_t clientNss = 1;
222 uint16_t serverShortGuardInterval = 800;
223 uint16_t clientShortGuardInterval = 800;
224 uint16_t serverChannelWidth = 0;
225 uint16_t clientChannelWidth = 0;
226 std::string wifiManager(
"Ideal");
227 std::string standard(
"802.11a");
230 bool infrastructure =
false;
238 cmd.AddValue(
"maxSsrc",
239 "The maximum number of retransmission attempts for a RTS packet",
241 cmd.AddValue(
"maxSlrc",
242 "The maximum number of retransmission attempts for a Data packet",
244 cmd.AddValue(
"rtsThreshold",
"RTS threshold", rtsThreshold);
245 cmd.AddValue(
"maxAmpduSize",
"Max A-MPDU size", maxAmpduSize);
246 cmd.AddValue(
"stepSize",
"Power between steps (dBm)", stepSize);
247 cmd.AddValue(
"stepTime",
"Time on each step (seconds)", stepTime);
248 cmd.AddValue(
"broadcast",
"Send broadcast instead of unicast", broadcast);
249 cmd.AddValue(
"serverChannelWidth",
250 "Set channel width of the server (valid only for 802.11n or ac)",
252 cmd.AddValue(
"clientChannelWidth",
253 "Set channel width of the client (valid only for 802.11n or ac)",
255 cmd.AddValue(
"serverNss",
"Set nss of the server (valid only for 802.11n or ac)", serverNss);
256 cmd.AddValue(
"clientNss",
"Set nss of the client (valid only for 802.11n or ac)", clientNss);
257 cmd.AddValue(
"serverShortGuardInterval",
258 "Set short guard interval of the server (802.11n/ac/ax) in nanoseconds",
259 serverShortGuardInterval);
260 cmd.AddValue(
"clientShortGuardInterval",
261 "Set short guard interval of the client (802.11n/ac/ax) in nanoseconds",
262 clientShortGuardInterval);
265 "Set standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, "
266 "802.11n-2.4GHz, 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz)",
268 cmd.AddValue(
"wifiManager",
269 "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, "
270 "MinstrelHt, Onoe, Rraa, ThompsonSampling)",
272 cmd.AddValue(
"infrastructure",
"Use infrastructure instead of adhoc", infrastructure);
273 cmd.Parse(argc, argv);
276 std::cout << std::endl
277 <<
"This program demonstrates and plots the operation of different " << std::endl;
278 std::cout <<
"Wi-Fi rate controls on different station configurations," << std::endl;
279 std::cout <<
"by stepping down the received signal strength across a wide range" << std::endl;
280 std::cout <<
"and observing the adjustment of the rate." << std::endl;
281 std::cout <<
"Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl
287 "In ad hoc mode, we assume sender and receiver are similarly configured");
290 if (standard ==
"802.11b")
292 if (serverChannelWidth == 0)
297 "Invalid channel width for standard " << standard);
298 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
299 if (clientChannelWidth == 0)
304 "Invalid channel width for standard " << standard);
305 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
307 else if (standard ==
"802.11a" || standard ==
"802.11g")
309 if (serverChannelWidth == 0)
314 "Invalid channel width for standard " << standard);
315 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
316 if (clientChannelWidth == 0)
321 "Invalid channel width for standard " << standard);
322 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
324 else if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz")
328 if (serverChannelWidth == 0)
333 "Invalid channel width for standard " << standard);
335 "Invalid nss " << serverNss <<
" for standard " << standard);
336 if (clientChannelWidth == 0)
341 "Invalid channel width for standard " << standard);
343 "Invalid nss " << clientNss <<
" for standard " << standard);
345 else if (standard ==
"802.11ac")
347 if (serverChannelWidth == 0)
351 NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40 &&
352 serverChannelWidth != 80 && serverChannelWidth != 160,
353 "Invalid channel width for standard " << standard);
355 "Invalid nss " << serverNss <<
" for standard " << standard);
356 if (clientChannelWidth == 0)
360 NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40 &&
361 clientChannelWidth != 80 && clientChannelWidth != 160,
362 "Invalid channel width for standard " << standard);
364 "Invalid nss " << clientNss <<
" for standard " << standard);
366 else if (standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" ||
367 standard ==
"802.11ax-2.4GHz")
372 if (serverChannelWidth == 0)
376 NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40 &&
377 serverChannelWidth != 80 && serverChannelWidth != 160,
378 "Invalid channel width for standard " << standard);
380 "Invalid nss " << serverNss <<
" for standard " << standard);
381 if (clientChannelWidth == 0)
385 NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40 &&
386 clientChannelWidth != 80 && clientChannelWidth != 160,
387 "Invalid channel width for standard " << standard);
389 "Invalid nss " << clientNss <<
" for standard " << standard);
393 uint32_t channelRateFactor = std::max(clientChannelWidth, serverChannelWidth) / 20;
394 channelRateFactor = channelRateFactor * std::max(clientNss, serverNss);
411 80 * channelRateFactor),
420 80 * channelRateFactor),
429 120 * channelRateFactor),
448 120 * channelRateFactor),
457 120 * channelRateFactor),
466 120 * channelRateFactor),
481 80 * channelRateFactor),
490 80 * channelRateFactor),
499 120 * channelRateFactor),
518 160 * channelRateFactor),
527 160 * channelRateFactor),
536 160 * channelRateFactor),
539 for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size(); i++)
541 if (standard == serverStandards[i].m_name)
543 serverSelectedStandard = serverStandards[i];
546 for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size(); i++)
548 if (standard == clientStandards[i].m_name)
550 clientSelectedStandard = clientStandards[i];
555 "Standard " << standard <<
" not found");
557 "Standard " << standard <<
" not found");
558 std::cout <<
"Testing " << serverSelectedStandard.
m_name <<
" with " << wifiManager <<
" ..."
561 "SNR values in wrong order");
562 steps =
static_cast<uint32_t>(std::abs(
static_cast<double>(clientSelectedStandard.
m_snrHigh -
567 <<
":" << clientSelectedStandard.
m_snrHigh);
568 Ptr<Node> clientNode = CreateObject<Node>();
569 Ptr<Node> serverNode = CreateObject<Node>();
571 std::string plotName =
"wifi-manager-example-";
572 std::string dataName =
"wifi-manager-example-";
573 plotName += wifiManager;
574 dataName += wifiManager;
577 plotName += standard;
578 dataName += standard;
579 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
580 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
582 plotName +=
"-server_";
583 dataName +=
"-server_";
584 std::ostringstream oss;
585 oss << serverChannelWidth <<
"MHz_" << serverShortGuardInterval <<
"ns_" << serverNss
587 plotName += oss.str();
588 dataName += oss.str();
589 plotName +=
"-client_";
590 dataName +=
"-client_";
592 oss << clientChannelWidth <<
"MHz_" << clientShortGuardInterval <<
"ns_" << clientNss
594 plotName += oss.str();
595 dataName += oss.str();
599 std::ofstream outfile(dataName);
629 CreateObject<ConstantSpeedPropagationDelayModel>();
630 wifiChannel->SetPropagationDelayModel(delayModel);
632 wifiChannel->SetPropagationLossModel(rssLossModel);
635 wifi.SetRemoteStationManager(
"ns3::" + wifiManager +
"WifiManager",
650 serverSelectedStandard.
m_width,
651 serverSelectedStandard.
m_band,
653 wifiPhy.
Set(
"ChannelSettings", channelValue);
654 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
658 clientSelectedStandard.
m_width,
659 clientSelectedStandard.
m_band,
661 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
665 wifiMac.
SetType(
"ns3::AdhocWifiMac");
667 serverSelectedStandard.
m_width,
668 serverSelectedStandard.
m_band,
670 wifiPhy.
Set(
"ChannelSettings", channelValue);
671 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
674 clientSelectedStandard.
m_width,
675 clientSelectedStandard.
m_band,
677 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
680 wifi.AssignStreams(serverDevice, 100);
681 wifi.AssignStreams(clientDevice, 200);
683 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
687 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
695 positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
696 NS_LOG_INFO(
"Setting initial AP position to " << Vector(ap1_x, ap1_y, 0.0));
697 positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
698 NS_LOG_INFO(
"Setting initial STA position to " << Vector(sta1_x, sta1_y, 0.0));
699 mobility.SetPositionAllocator(positionAlloc);
700 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
719 auto t_clientNss =
static_cast<uint8_t
>(clientNss);
720 auto t_serverNss =
static_cast<uint8_t
>(serverNss);
721 wifiPhyPtrClient->SetNumberOfAntennas(t_clientNss);
722 wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
723 wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
724 wifiPhyPtrServer->SetNumberOfAntennas(t_serverNss);
725 wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams(t_serverNss);
726 wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams(t_serverNss);
728 if (serverSelectedStandard.
m_name ==
"802.11n-5GHz" ||
729 serverSelectedStandard.
m_name ==
"802.11n-2.4GHz" ||
730 serverSelectedStandard.
m_name ==
"802.11ac")
733 clientHtConfiguration->SetShortGuardIntervalSupported(clientShortGuardInterval == 400);
735 serverHtConfiguration->SetShortGuardIntervalSupported(serverShortGuardInterval == 400);
737 else if (serverSelectedStandard.
m_name ==
"802.11ax-6GHz" ||
738 serverSelectedStandard.
m_name ==
"802.11ax-5GHz" ||
739 serverSelectedStandard.
m_name ==
"802.11ax-2.4GHz")
741 wndServer->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(serverShortGuardInterval));
742 wndClient->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(clientShortGuardInterval));
744 NS_LOG_DEBUG(
"Channel width " << wifiPhyPtrClient->GetChannelWidth() <<
" noiseDbm "
746 NS_LOG_DEBUG(
"NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
751 rssLossModel->SetRss(rssCurrent);
752 NS_LOG_INFO(
"Setting initial Rss to " << rssCurrent);
763 packetSocketHelper.
Install(serverNode);
764 packetSocketHelper.
Install(clientNode);
782 client->SetRemote(socketAddr);
788 double rate = clientSelectedStandard.
m_yMax * 1e6 * 1.10;
789 double clientInterval =
static_cast<double>(
packetSize) * 8 / rate;
790 NS_LOG_DEBUG(
"Setting interval to " << clientInterval <<
" sec for rate of " << rate
794 clientNode->AddApplication(client);
797 server->SetLocal(socketAddr);
799 serverNode->AddApplication(server);
807 wndServer->GetMac()->GetAddress(),
809 "Expected BA agreement established for standard "
818 std::ostringstream xMinStr;
819 std::ostringstream xMaxStr;
820 std::ostringstream yMaxStr;
821 std::string xRangeStr(
"set xrange [");
822 xMinStr << clientSelectedStandard.
m_xMin;
823 xRangeStr.append(xMinStr.str());
824 xRangeStr.append(
":");
825 xMaxStr << clientSelectedStandard.
m_xMax;
826 xRangeStr.append(xMaxStr.str());
827 xRangeStr.append(
"]");
828 std::string yRangeStr(
"set yrange [0:");
829 yMaxStr << clientSelectedStandard.
m_yMax;
830 yRangeStr.append(yMaxStr.str());
831 yRangeStr.append(
"]");
833 std::string title(
"Results for ");
834 title.append(standard);
835 title.append(
" with ");
836 title.append(wifiManager);
838 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
839 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
841 std::ostringstream serverGiStrStr;
842 std::ostringstream serverWidthStrStr;
843 std::ostringstream serverNssStrStr;
844 title.append(
"server: width=");
845 serverWidthStrStr << serverSelectedStandard.
m_width;
846 title.append(serverWidthStrStr.str());
848 title.append(
" GI=");
849 serverGiStrStr << serverShortGuardInterval;
850 title.append(serverGiStrStr.str());
852 title.append(
" nss=");
853 serverNssStrStr << serverNss;
854 title.append(serverNssStrStr.str());
856 std::ostringstream clientGiStrStr;
857 std::ostringstream clientWidthStrStr;
858 std::ostringstream clientNssStrStr;
859 title.append(
"client: width=");
860 clientWidthStrStr << clientSelectedStandard.
m_width;
861 title.append(clientWidthStrStr.str());
863 title.append(
" GI=");
864 clientGiStrStr << clientShortGuardInterval;
865 title.append(clientGiStrStr.str());
867 title.append(
" nss=");
868 clientNssStrStr << clientNss;
869 title.append(clientNssStrStr.str());
871 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
872 gnuplot.
SetLegend(
"SNR (dB)",
"Rate (Mb/s)");
a polymophic address class
AttributeValue implementation for Boolean.
Parse command-line arguments.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Class to represent a 2D points plot.
void Add(double x, double y)
a simple class to generate gnuplot-ready plotting commands from a set of datasets.
void AddDataset(const GnuplotDataset &dataset)
void SetLegend(const std::string &xLegend, const std::string &yLegend)
void SetTerminal(const std::string &terminal)
void AppendExtra(const std::string &extra)
void GenerateOutput(std::ostream &os)
Writes gnuplot commands and data values to a single output stream.
void SetExtra(const std::string &extra)
void SetTitle(const std::string &title)
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
static Time Now()
Return the current simulation virtual time.
static void Run()
Run the simulation.
static void Stop()
Tell the Simulator the calling event should be the last one executed.
The IEEE 802.11 SSID Information Element.
AttributeValue implementation for Ssid.
AttributeValue implementation for Time.
AttributeValue implementation for Tuple.
void Set(const result_type &value)
Set the stored values.
Hold an unsigned integer type.
helps to create WifiNetDevice objects
create MAC layers for a ns3::WifiNetDevice.
void SetType(std::string type, Args &&... args)
Hold together all Wifi-related objects.
void Set(std::string name, const AttributeValue &v)
void DisablePreambleDetectionModel()
Disable the preamble detection model on all links.
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Make it easy to create and manage PHY objects for the YANS model.
void SetChannel(Ptr< YansWifiChannel > channel)
void SetDefault(std::string name, const AttributeValue &value)
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
void Set(std::string path, const AttributeValue &value)
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiPhyBand
Identifies the PHY band.
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
uint16_t GetDefaultChannelWidth(WifiStandard standard, WifiPhyBand band)
Get the default channel width for the given PHY standard and band.
StandardInfo(std::string name, WifiStandard standard, WifiPhyBand band, uint16_t width, double snrLow, double snrHigh, double xMin, double xMax, double yMax)
Constructor.
uint16_t m_width
channel width
WifiStandard m_standard
standard
WifiPhyBand m_band
PHY band.
double m_snrHigh
highest SNR
double m_snrLow
lowest SNR
double stepSize
step size in dBm
double stepTime
step size in seconds
uint64_t g_intervalRate
Rate in an interval.
void RateChange(uint64_t oldVal, uint64_t newVal)
Rate changed.
const double NOISE_DBM_Hz
Default value for noise.
void PacketRx(Ptr< const Packet > pkt, const Address &addr)
Packet received.
double g_intervalBytes
Bytes received in an interval.
double noiseDbm
Value for noise.
void ChangeSignalAndReportRate(Ptr< FixedRssLossModel > rssModel, Step step, double rss, Gnuplot2dDataset &rateDataset, Gnuplot2dDataset &actualDataset)
Change the signal model and report the rate.
static const uint32_t packetSize
Packet size generated at the AP.