38#include "ns3/attribute-container.h"
39#include "ns3/boolean.h"
40#include "ns3/command-line.h"
41#include "ns3/config.h"
42#include "ns3/double.h"
44#include "ns3/gnuplot.h"
45#include "ns3/he-configuration.h"
46#include "ns3/ht-configuration.h"
48#include "ns3/mobility-helper.h"
49#include "ns3/packet-socket-client.h"
50#include "ns3/packet-socket-helper.h"
51#include "ns3/packet-socket-server.h"
52#include "ns3/propagation-delay-model.h"
53#include "ns3/propagation-loss-model.h"
54#include "ns3/rng-seed-manager.h"
57#include "ns3/uinteger.h"
58#include "ns3/wifi-mac.h"
59#include "ns3/wifi-net-device.h"
60#include "ns3/yans-wifi-helper.h"
90 NS_LOG_DEBUG(
"Change from " << oldVal <<
" to " << newVal);
173 dB_u snr = rss - noise;
177 actualDataset.
Add(snr, currentRate);
178 rssModel->SetRss(rss - step.
stepSize);
181 <<
"; setting new power to " << rss - step.
stepSize);
194main(
int argc,
char* argv[])
196 std::vector<StandardInfo> serverStandards;
197 std::vector<StandardInfo> clientStandards;
204 bool broadcast =
false;
209 uint16_t serverNss = 1;
210 uint16_t clientNss = 1;
211 uint16_t serverShortGuardInterval = 800;
212 uint16_t clientShortGuardInterval = 800;
213 uint16_t serverChannelWidth = 0;
214 uint16_t clientChannelWidth = 0;
215 std::string wifiManager(
"Ideal");
216 std::string standard(
"802.11a");
219 bool infrastructure =
false;
227 cmd.AddValue(
"maxSsrc",
228 "The maximum number of retransmission attempts for a RTS packet",
230 cmd.AddValue(
"maxSlrc",
231 "The maximum number of retransmission attempts for a Data packet",
233 cmd.AddValue(
"rtsThreshold",
"RTS threshold", rtsThreshold);
234 cmd.AddValue(
"maxAmpduSize",
"Max A-MPDU size", maxAmpduSize);
235 cmd.AddValue(
"stepSize",
"Power between steps (dBm)", stepSize);
236 cmd.AddValue(
"stepTime",
"Time on each step (seconds)", stepTime);
237 cmd.AddValue(
"broadcast",
"Send broadcast instead of unicast", broadcast);
238 cmd.AddValue(
"serverChannelWidth",
239 "Set channel width of the server (valid only for 802.11n or ac)",
241 cmd.AddValue(
"clientChannelWidth",
242 "Set channel width of the client (valid only for 802.11n or ac)",
244 cmd.AddValue(
"serverNss",
"Set nss of the server (valid only for 802.11n or ac)", serverNss);
245 cmd.AddValue(
"clientNss",
"Set nss of the client (valid only for 802.11n or ac)", clientNss);
246 cmd.AddValue(
"serverShortGuardInterval",
247 "Set short guard interval of the server (802.11n/ac/ax) in nanoseconds",
248 serverShortGuardInterval);
249 cmd.AddValue(
"clientShortGuardInterval",
250 "Set short guard interval of the client (802.11n/ac/ax) in nanoseconds",
251 clientShortGuardInterval);
254 "Set standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, "
255 "802.11n-2.4GHz, 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz)",
257 cmd.AddValue(
"wifiManager",
258 "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, "
259 "MinstrelHt, Onoe, Rraa, ThompsonSampling)",
261 cmd.AddValue(
"infrastructure",
"Use infrastructure instead of adhoc", infrastructure);
262 cmd.Parse(argc, argv);
265 std::cout << std::endl
266 <<
"This program demonstrates and plots the operation of different " << std::endl;
267 std::cout <<
"Wi-Fi rate controls on different station configurations," << std::endl;
268 std::cout <<
"by stepping down the received signal strength across a wide range" << std::endl;
269 std::cout <<
"and observing the adjustment of the rate." << std::endl;
270 std::cout <<
"Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl
276 "In ad hoc mode, we assume sender and receiver are similarly configured");
279 if (standard ==
"802.11b")
281 if (serverChannelWidth == 0)
286 "Invalid channel width for standard " << standard);
287 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
288 if (clientChannelWidth == 0)
293 "Invalid channel width for standard " << standard);
294 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
296 else if (standard ==
"802.11a" || standard ==
"802.11g")
298 if (serverChannelWidth == 0)
303 "Invalid channel width for standard " << standard);
304 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
305 if (clientChannelWidth == 0)
310 "Invalid channel width for standard " << standard);
311 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
313 else if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz")
317 if (serverChannelWidth == 0)
322 "Invalid channel width for standard " << standard);
324 "Invalid nss " << serverNss <<
" for standard " << standard);
325 if (clientChannelWidth == 0)
330 "Invalid channel width for standard " << standard);
332 "Invalid nss " << clientNss <<
" for standard " << standard);
334 else if (standard ==
"802.11ac")
336 if (serverChannelWidth == 0)
340 NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40 &&
341 serverChannelWidth != 80 && serverChannelWidth != 160,
342 "Invalid channel width for standard " << standard);
344 "Invalid nss " << serverNss <<
" for standard " << standard);
345 if (clientChannelWidth == 0)
349 NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40 &&
350 clientChannelWidth != 80 && clientChannelWidth != 160,
351 "Invalid channel width for standard " << standard);
353 "Invalid nss " << clientNss <<
" for standard " << standard);
355 else if (standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" ||
356 standard ==
"802.11ax-2.4GHz")
361 if (serverChannelWidth == 0)
365 NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40 &&
366 serverChannelWidth != 80 && serverChannelWidth != 160,
367 "Invalid channel width for standard " << standard);
369 "Invalid nss " << serverNss <<
" for standard " << standard);
370 if (clientChannelWidth == 0)
374 NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40 &&
375 clientChannelWidth != 80 && clientChannelWidth != 160,
376 "Invalid channel width for standard " << standard);
378 "Invalid nss " << clientNss <<
" for standard " << standard);
382 uint32_t channelRateFactor = std::max(clientChannelWidth, serverChannelWidth) / 20;
383 channelRateFactor = channelRateFactor * std::max(clientNss, serverNss);
400 80 * channelRateFactor),
409 80 * channelRateFactor),
418 120 * channelRateFactor),
437 120 * channelRateFactor),
446 120 * channelRateFactor),
455 120 * channelRateFactor),
470 80 * channelRateFactor),
479 80 * channelRateFactor),
488 120 * channelRateFactor),
507 160 * channelRateFactor),
516 160 * channelRateFactor),
525 160 * channelRateFactor),
528 for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size(); i++)
530 if (standard == serverStandards[i].m_name)
532 serverSelectedStandard = serverStandards[i];
535 for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size(); i++)
537 if (standard == clientStandards[i].m_name)
539 clientSelectedStandard = clientStandards[i];
544 "Standard " << standard <<
" not found");
546 "Standard " << standard <<
" not found");
547 std::cout <<
"Testing " << serverSelectedStandard.
m_name <<
" with " << wifiManager <<
" ..."
550 "SNR values in wrong order");
551 steps =
static_cast<uint32_t>(std::abs(
static_cast<double>(clientSelectedStandard.
m_snrHigh -
556 <<
":" << clientSelectedStandard.
m_snrHigh);
560 std::string plotName =
"wifi-manager-example-";
561 std::string dataName =
"wifi-manager-example-";
562 plotName += wifiManager;
563 dataName += wifiManager;
566 plotName += standard;
567 dataName += standard;
568 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
569 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
571 plotName +=
"-server_";
572 dataName +=
"-server_";
573 std::ostringstream oss;
574 oss << serverChannelWidth <<
"MHz_" << serverShortGuardInterval <<
"ns_" << serverNss
576 plotName += oss.str();
577 dataName += oss.str();
578 plotName +=
"-client_";
579 dataName +=
"-client_";
581 oss << clientChannelWidth <<
"MHz_" << clientShortGuardInterval <<
"ns_" << clientNss
583 plotName += oss.str();
584 dataName += oss.str();
588 std::ofstream outfile(dataName);
619 wifiChannel->SetPropagationDelayModel(delayModel);
621 wifiChannel->SetPropagationLossModel(rssLossModel);
624 wifi.SetRemoteStationManager(
"ns3::" + wifiManager +
"WifiManager",
642 {0, serverSelectedStandard.
m_width, serverSelectedStandard.
m_band, 0}});
643 wifiPhy.
Set(
"ChannelSettings", channelValue);
644 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
648 {0, clientSelectedStandard.
m_width, clientSelectedStandard.
m_band, 0}});
649 wifiPhy.
Set(
"ChannelSettings", channelValue);
650 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
654 wifiMac.
SetType(
"ns3::AdhocWifiMac");
656 {0, serverSelectedStandard.
m_width, serverSelectedStandard.
m_band, 0}});
657 wifiPhy.
Set(
"ChannelSettings", channelValue);
658 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
661 {0, clientSelectedStandard.
m_width, clientSelectedStandard.
m_band, 0}});
662 wifiPhy.
Set(
"ChannelSettings", channelValue);
663 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
669 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
673 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
681 positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
682 NS_LOG_INFO(
"Setting initial AP position to " << Vector(ap1_x, ap1_y, 0.0));
683 positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
684 NS_LOG_INFO(
"Setting initial STA position to " << Vector(sta1_x, sta1_y, 0.0));
685 mobility.SetPositionAllocator(positionAlloc);
686 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
705 auto t_clientNss =
static_cast<uint8_t
>(clientNss);
706 auto t_serverNss =
static_cast<uint8_t
>(serverNss);
707 wifiPhyPtrClient->SetNumberOfAntennas(t_clientNss);
708 wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
709 wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
710 wifiPhyPtrServer->SetNumberOfAntennas(t_serverNss);
711 wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams(t_serverNss);
712 wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams(t_serverNss);
714 if (serverSelectedStandard.
m_name ==
"802.11n-5GHz" ||
715 serverSelectedStandard.
m_name ==
"802.11n-2.4GHz" ||
716 serverSelectedStandard.
m_name ==
"802.11ac")
719 clientHtConfiguration->SetShortGuardIntervalSupported(clientShortGuardInterval == 400);
721 serverHtConfiguration->SetShortGuardIntervalSupported(serverShortGuardInterval == 400);
723 else if (serverSelectedStandard.
m_name ==
"802.11ax-6GHz" ||
724 serverSelectedStandard.
m_name ==
"802.11ax-5GHz" ||
725 serverSelectedStandard.
m_name ==
"802.11ax-2.4GHz")
727 wndServer->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(serverShortGuardInterval));
728 wndClient->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(clientShortGuardInterval));
732 const auto BOLTZMANN = 1.3803e-23;
734 const dBm_u noise = noiseDensity + (10 * log10(clientSelectedStandard.
m_width * 1000000));
736 NS_LOG_DEBUG(
"Channel width " << wifiPhyPtrClient->GetChannelWidth() <<
" noise " << noise);
737 NS_LOG_DEBUG(
"NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
739 const dBm_u rssCurrent = (clientSelectedStandard.
m_snrHigh + noise);
740 rssLossModel->SetRss(rssCurrent);
741 NS_LOG_INFO(
"Setting initial Rss to " << rssCurrent);
753 packetSocketHelper.
Install(serverNode);
754 packetSocketHelper.
Install(clientNode);
772 client->SetRemote(socketAddr);
778 double rate = clientSelectedStandard.
m_yMax * 1e6 * 1.10;
779 double clientInterval =
static_cast<double>(
packetSize) * 8 / rate;
780 NS_LOG_DEBUG(
"Setting interval to " << clientInterval <<
" sec for rate of " << rate
784 clientNode->AddApplication(client);
787 server->SetLocal(socketAddr);
789 serverNode->AddApplication(server);
797 wndServer->GetMac()->GetAddress(),
799 "Expected BA agreement established for standard "
808 std::ostringstream xMinStr;
809 std::ostringstream xMaxStr;
810 std::ostringstream yMaxStr;
811 std::string xRangeStr(
"set xrange [");
812 xMinStr << clientSelectedStandard.
m_xMin;
813 xRangeStr.append(xMinStr.str());
814 xRangeStr.append(
":");
815 xMaxStr << clientSelectedStandard.
m_xMax;
816 xRangeStr.append(xMaxStr.str());
817 xRangeStr.append(
"]");
818 std::string yRangeStr(
"set yrange [0:");
819 yMaxStr << clientSelectedStandard.
m_yMax;
820 yRangeStr.append(yMaxStr.str());
821 yRangeStr.append(
"]");
823 std::string title(
"Results for ");
824 title.append(standard);
825 title.append(
" with ");
826 title.append(wifiManager);
828 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
829 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
831 std::ostringstream serverGiStrStr;
832 std::ostringstream serverWidthStrStr;
833 std::ostringstream serverNssStrStr;
834 title.append(
"server: width=");
835 serverWidthStrStr << serverSelectedStandard.
m_width;
836 title.append(serverWidthStrStr.str());
838 title.append(
" GI=");
839 serverGiStrStr << serverShortGuardInterval;
840 title.append(serverGiStrStr.str());
842 title.append(
" nss=");
843 serverNssStrStr << serverNss;
844 title.append(serverNssStrStr.str());
846 std::ostringstream clientGiStrStr;
847 std::ostringstream clientWidthStrStr;
848 std::ostringstream clientNssStrStr;
849 title.append(
"client: width=");
850 clientWidthStrStr << clientSelectedStandard.
m_width;
851 title.append(clientWidthStrStr.str());
853 title.append(
" GI=");
854 clientGiStrStr << clientShortGuardInterval;
855 title.append(clientGiStrStr.str());
857 title.append(
" nss=");
858 clientNssStrStr << clientNss;
859 title.append(clientNssStrStr.str());
861 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
862 gnuplot.
SetLegend(
"SNR (dB)",
"Rate (Mb/s)");
a polymophic address class
A container for one type of attribute.
void Set(const T &c)
Copy items from container c.
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 Tuple.
Hold an unsigned integer type.
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.
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::vector< ChannelTuple > ChannelSegments
segments 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.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
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...
dBm_u WToDbm(Watt_u val)
Convert from Watts to dBm.
MHz_u 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, MHz_u width, dB_u snrLow, dB_u snrHigh, double xMin, double xMax, double yMax)
Constructor.
WifiStandard m_standard
standard
WifiPhyBand m_band
PHY band.
dB_u m_snrHigh
highest SNR
MHz_u m_width
channel width
double stepTime
step size in seconds
uint64_t g_intervalRate
Rate in an interval.
void ChangeSignalAndReportRate(Ptr< FixedRssLossModel > rssModel, Step step, dBm_u rss, dBm_u noise, Gnuplot2dDataset &rateDataset, Gnuplot2dDataset &actualDataset)
Change the signal model and report the rate.
void RateChange(uint64_t oldVal, uint64_t newVal)
Rate changed.
void PacketRx(Ptr< const Packet > pkt, const Address &addr)
Packet received.
double g_intervalBytes
Bytes received in an interval.
static const uint32_t packetSize
Packet size generated at the AP.