41#include "ns3/boolean.h"
42#include "ns3/command-line.h"
43#include "ns3/config.h"
44#include "ns3/double.h"
46#include "ns3/gnuplot.h"
47#include "ns3/he-configuration.h"
48#include "ns3/ht-configuration.h"
50#include "ns3/mobility-helper.h"
51#include "ns3/packet-socket-client.h"
52#include "ns3/packet-socket-helper.h"
53#include "ns3/packet-socket-server.h"
54#include "ns3/propagation-delay-model.h"
55#include "ns3/propagation-loss-model.h"
56#include "ns3/rng-seed-manager.h"
59#include "ns3/uinteger.h"
60#include "ns3/wifi-net-device.h"
61#include "ns3/yans-wifi-helper.h"
95 NS_LOG_DEBUG(
"Change from " << oldVal <<
" to " << newVal);
180 actualDataset.
Add(snr, currentRate);
181 rssModel->SetRss(rss - step.
stepSize);
184 <<
"; setting new power to " << rss - step.
stepSize);
196main(
int argc,
char* argv[])
198 std::vector<StandardInfo> serverStandards;
199 std::vector<StandardInfo> clientStandards;
211 uint16_t serverNss = 1;
212 uint16_t clientNss = 1;
213 uint16_t serverShortGuardInterval = 800;
214 uint16_t clientShortGuardInterval = 800;
215 uint16_t serverChannelWidth = 0;
216 uint16_t clientChannelWidth = 0;
217 std::string wifiManager(
"Ideal");
218 std::string standard(
"802.11a");
221 bool infrastructure =
false;
226 cmd.AddValue(
"maxSsrc",
227 "The maximum number of retransmission attempts for a RTS packet",
229 cmd.AddValue(
"maxSlrc",
230 "The maximum number of retransmission attempts for a Data packet",
232 cmd.AddValue(
"rtsThreshold",
"RTS threshold", rtsThreshold);
233 cmd.AddValue(
"maxAmpduSize",
"Max A-MPDU size", maxAmpduSize);
234 cmd.AddValue(
"stepSize",
"Power between steps (dBm)", stepSize);
235 cmd.AddValue(
"stepTime",
"Time on each step (seconds)", stepTime);
236 cmd.AddValue(
"broadcast",
"Send broadcast instead of unicast", broadcast);
237 cmd.AddValue(
"serverChannelWidth",
238 "Set channel width of the server (valid only for 802.11n or ac)",
240 cmd.AddValue(
"clientChannelWidth",
241 "Set channel width of the client (valid only for 802.11n or ac)",
243 cmd.AddValue(
"serverNss",
"Set nss of the server (valid only for 802.11n or ac)", serverNss);
244 cmd.AddValue(
"clientNss",
"Set nss of the client (valid only for 802.11n or ac)", clientNss);
245 cmd.AddValue(
"serverShortGuardInterval",
246 "Set short guard interval of the server (802.11n/ac/ax) in nanoseconds",
247 serverShortGuardInterval);
248 cmd.AddValue(
"clientShortGuardInterval",
249 "Set short guard interval of the client (802.11n/ac/ax) in nanoseconds",
250 clientShortGuardInterval);
253 "Set standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, "
254 "802.11n-2.4GHz, 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz)",
256 cmd.AddValue(
"wifiManager",
257 "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, "
258 "MinstrelHt, Onoe, Rraa, ThompsonSampling)",
260 cmd.AddValue(
"infrastructure",
"Use infrastructure instead of adhoc", infrastructure);
261 cmd.Parse(argc, argv);
264 std::cout << std::endl
265 <<
"This program demonstrates and plots the operation of different " << std::endl;
266 std::cout <<
"Wi-Fi rate controls on different station configurations," << std::endl;
267 std::cout <<
"by stepping down the received signal strength across a wide range" << std::endl;
268 std::cout <<
"and observing the adjustment of the rate." << std::endl;
269 std::cout <<
"Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl
272 if (infrastructure ==
false)
275 "In ad hoc mode, we assume sender and receiver are similarly configured");
278 if (standard ==
"802.11b")
280 if (serverChannelWidth == 0)
285 "Invalid channel width for standard " << standard);
286 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
287 if (clientChannelWidth == 0)
292 "Invalid channel width for standard " << standard);
293 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
295 else if (standard ==
"802.11a" || standard ==
"802.11g")
297 if (serverChannelWidth == 0)
302 "Invalid channel width for standard " << standard);
303 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
304 if (clientChannelWidth == 0)
309 "Invalid channel width for standard " << standard);
310 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
312 else if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz")
316 if (serverChannelWidth == 0)
321 "Invalid channel width for standard " << standard);
323 "Invalid nss " << serverNss <<
" for standard " << standard);
324 if (clientChannelWidth == 0)
329 "Invalid channel width for standard " << standard);
331 "Invalid nss " << clientNss <<
" for standard " << standard);
333 else if (standard ==
"802.11ac")
335 if (serverChannelWidth == 0)
339 NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40 &&
340 serverChannelWidth != 80 && serverChannelWidth != 160,
341 "Invalid channel width for standard " << standard);
343 "Invalid nss " << serverNss <<
" for standard " << standard);
344 if (clientChannelWidth == 0)
348 NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40 &&
349 clientChannelWidth != 80 && clientChannelWidth != 160,
350 "Invalid channel width for standard " << standard);
352 "Invalid nss " << clientNss <<
" for standard " << standard);
354 else if (standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" ||
355 standard ==
"802.11ax-2.4GHz")
360 if (serverChannelWidth == 0)
364 NS_ABORT_MSG_IF(serverChannelWidth != 20 && serverChannelWidth != 40 &&
365 serverChannelWidth != 80 && serverChannelWidth != 160,
366 "Invalid channel width for standard " << standard);
368 "Invalid nss " << serverNss <<
" for standard " << standard);
369 if (clientChannelWidth == 0)
373 NS_ABORT_MSG_IF(clientChannelWidth != 20 && clientChannelWidth != 40 &&
374 clientChannelWidth != 80 && clientChannelWidth != 160,
375 "Invalid channel width for standard " << standard);
377 "Invalid nss " << clientNss <<
" for standard " << standard);
381 uint32_t channelRateFactor =
std::max(clientChannelWidth, serverChannelWidth) / 20;
382 channelRateFactor = channelRateFactor *
std::max(clientNss, serverNss);
399 80 * channelRateFactor),
408 80 * channelRateFactor),
417 120 * channelRateFactor),
436 120 * channelRateFactor),
445 120 * channelRateFactor),
454 120 * channelRateFactor),
469 80 * channelRateFactor),
478 80 * channelRateFactor),
487 120 * channelRateFactor),
506 160 * channelRateFactor),
515 160 * channelRateFactor),
524 160 * channelRateFactor),
527 for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size(); i++)
529 if (standard == serverStandards[i].m_name)
531 serverSelectedStandard = serverStandards[i];
534 for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size(); i++)
536 if (standard == clientStandards[i].m_name)
538 clientSelectedStandard = clientStandards[i];
543 "Standard " << standard <<
" not found");
545 "Standard " << standard <<
" not found");
546 std::cout <<
"Testing " << serverSelectedStandard.
m_name <<
" with " << wifiManager <<
" ..."
549 "SNR values in wrong order");
550 steps =
static_cast<uint32_t>(std::abs(
static_cast<double>(clientSelectedStandard.
m_snrHigh -
555 <<
":" << clientSelectedStandard.
m_snrHigh);
556 Ptr<Node> clientNode = CreateObject<Node>();
557 Ptr<Node> serverNode = CreateObject<Node>();
559 std::string plotName =
"wifi-manager-example-";
560 std::string dataName =
"wifi-manager-example-";
561 plotName += wifiManager;
562 dataName += wifiManager;
565 plotName += standard;
566 dataName += standard;
567 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
568 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
570 plotName +=
"-server_";
571 dataName +=
"-server_";
572 std::ostringstream oss;
573 oss << serverChannelWidth <<
"MHz_" << serverShortGuardInterval <<
"ns_" << serverNss
575 plotName += oss.str();
576 dataName += oss.str();
577 plotName +=
"-client_";
578 dataName +=
"-client_";
580 oss << clientChannelWidth <<
"MHz_" << clientShortGuardInterval <<
"ns_" << clientNss
582 plotName += oss.str();
583 dataName += oss.str();
587 std::ofstream outfile(dataName);
602 CreateObject<ConstantSpeedPropagationDelayModel>();
603 wifiChannel->SetPropagationDelayModel(delayModel);
605 wifiChannel->SetPropagationLossModel(rssLossModel);
608 wifi.SetRemoteStationManager(
"ns3::" + wifiManager +
"WifiManager",
623 serverSelectedStandard.
m_width,
624 serverSelectedStandard.
m_band,
626 wifiPhy.
Set(
"ChannelSettings", channelValue);
627 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
631 clientSelectedStandard.
m_width,
632 clientSelectedStandard.
m_band,
634 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
638 wifiMac.
SetType(
"ns3::AdhocWifiMac");
640 serverSelectedStandard.
m_width,
641 serverSelectedStandard.
m_band,
643 wifiPhy.
Set(
"ChannelSettings", channelValue);
644 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
647 clientSelectedStandard.
m_width,
648 clientSelectedStandard.
m_band,
650 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
653 RngSeedManager::SetSeed(1);
654 RngSeedManager::SetRun(2);
655 wifi.AssignStreams(serverDevice, 100);
656 wifi.AssignStreams(clientDevice, 100);
658 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
662 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
670 positionAlloc->Add(
Vector(ap1_x, ap1_y, 0.0));
672 positionAlloc->Add(
Vector(sta1_x, sta1_y, 0.0));
674 mobility.SetPositionAllocator(positionAlloc);
675 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
694 uint8_t t_clientNss =
static_cast<uint8_t
>(clientNss);
695 uint8_t t_serverNss =
static_cast<uint8_t
>(serverNss);
697 wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
698 wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
703 if (serverSelectedStandard.
m_name ==
"802.11n-5GHz" ||
704 serverSelectedStandard.
m_name ==
"802.11n-2.4GHz" ||
705 serverSelectedStandard.
m_name ==
"802.11ac")
708 clientHtConfiguration->SetShortGuardIntervalSupported(clientShortGuardInterval == 400);
710 serverHtConfiguration->SetShortGuardIntervalSupported(serverShortGuardInterval == 400);
712 else if (serverSelectedStandard.
m_name ==
"802.11ax-6GHz" ||
713 serverSelectedStandard.
m_name ==
"802.11ax-5GHz" ||
714 serverSelectedStandard.
m_name ==
"802.11ax-2.4GHz")
716 wndServer->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(serverShortGuardInterval));
719 NS_LOG_DEBUG(
"Channel width " << wifiPhyPtrClient->GetChannelWidth() <<
" noiseDbm "
721 NS_LOG_DEBUG(
"NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
726 rssLossModel->SetRss(rssCurrent);
727 NS_LOG_INFO(
"Setting initial Rss to " << rssCurrent);
729 Simulator::Schedule(
Seconds(0.5 + stepTime),
738 packetSocketHelper.
Install(serverNode);
739 packetSocketHelper.
Install(clientNode);
757 client->SetRemote(socketAddr);
758 client->SetStartTime(
Seconds(0.5));
763 double rate = clientSelectedStandard.
m_yMax * 1e6 * 1.10;
764 double clientInterval =
static_cast<double>(
packetSize) * 8 / rate;
765 NS_LOG_DEBUG(
"Setting interval to " << clientInterval <<
" sec for rate of " << rate
772 server->SetLocal(socketAddr);
776 Simulator::Stop(
Seconds((steps + 1) * stepTime));
778 Simulator::Destroy();
783 std::ostringstream xMinStr;
784 std::ostringstream xMaxStr;
785 std::ostringstream yMaxStr;
786 std::string xRangeStr(
"set xrange [");
787 xMinStr << clientSelectedStandard.
m_xMin;
788 xRangeStr.append(xMinStr.str());
789 xRangeStr.append(
":");
790 xMaxStr << clientSelectedStandard.
m_xMax;
791 xRangeStr.append(xMaxStr.str());
792 xRangeStr.append(
"]");
793 std::string yRangeStr(
"set yrange [0:");
794 yMaxStr << clientSelectedStandard.
m_yMax;
795 yRangeStr.append(yMaxStr.str());
796 yRangeStr.append(
"]");
798 std::string title(
"Results for ");
799 title.append(standard);
800 title.append(
" with ");
801 title.append(wifiManager);
803 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
804 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
806 std::ostringstream serverGiStrStr;
807 std::ostringstream serverWidthStrStr;
808 std::ostringstream serverNssStrStr;
809 title.append(
"server: width=");
810 serverWidthStrStr << serverSelectedStandard.
m_width;
811 title.append(serverWidthStrStr.str());
813 title.append(
" GI=");
814 serverGiStrStr << serverShortGuardInterval;
815 title.append(serverGiStrStr.str());
817 title.append(
" nss=");
818 serverNssStrStr << serverNss;
819 title.append(serverNssStrStr.str());
821 std::ostringstream clientGiStrStr;
822 std::ostringstream clientWidthStrStr;
823 std::ostringstream clientNssStrStr;
824 title.append(
"client: width=");
825 clientWidthStrStr << clientSelectedStandard.
m_width;
826 title.append(clientWidthStrStr.str());
828 title.append(
" GI=");
829 clientGiStrStr << clientShortGuardInterval;
830 title.append(clientGiStrStr.str());
832 title.append(
" nss=");
833 clientNssStrStr << clientNss;
834 title.append(clientNssStrStr.str());
836 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
837 gnuplot.
SetLegend(
"SNR (dB)",
"Rate (Mb/s)");
a polymophic address class
AttributeValue implementation for Boolean.
Parse command-line arguments.
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.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
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.
The IEEE 802.11 SSID Information Element.
AttributeValue implementation for Ssid.
AttributeValue implementation for Time.
Hold objects of type std::tuple<Args...>.
void Set(const result_type &value)
Set the stored values.
Hold an unsigned integer type.
Vector3D Vector
Vector alias typedef for compatibility with mobility models.
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.
Ptr< HtConfiguration > GetHtConfiguration() const
Ptr< HeConfiguration > GetHeConfiguration() const
Ptr< WifiPhy > GetPhy() const
void Set(std::string name, const AttributeValue &v)
void SetNumberOfAntennas(uint8_t antennas)
void SetMaxSupportedRxSpatialStreams(uint8_t streams)
void SetMaxSupportedTxSpatialStreams(uint8_t streams)
std::tuple< uint8_t, uint16_t, int, 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_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 Now()
create an ns3::Time instance which contains the current simulation time.
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.