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 MHz_u serverChannelWidth{0};
214 MHz_u clientChannelWidth{0};
215 std::string wifiManager(
"Ideal");
216 std::string standard(
"802.11a");
219 bool infrastructure =
false;
226 cmd.AddValue(
"maxRetryCount",
227 "The maximum number of retransmission attempts for a Data packet",
229 cmd.AddValue(
"rtsThreshold",
"RTS threshold", rtsThreshold);
230 cmd.AddValue(
"maxAmpduSize",
"Max A-MPDU size", maxAmpduSize);
231 cmd.AddValue(
"stepSize",
"Power between steps (dBm)", stepSize);
232 cmd.AddValue(
"stepTime",
"Time on each step (seconds)", stepTime);
233 cmd.AddValue(
"broadcast",
"Send broadcast instead of unicast", broadcast);
234 cmd.AddValue(
"serverChannelWidth",
235 "Set channel width of the server (valid only for 802.11n or ac)",
237 cmd.AddValue(
"clientChannelWidth",
238 "Set channel width of the client (valid only for 802.11n or ac)",
240 cmd.AddValue(
"serverNss",
"Set nss of the server (valid only for 802.11n or ac)", serverNss);
241 cmd.AddValue(
"clientNss",
"Set nss of the client (valid only for 802.11n or ac)", clientNss);
242 cmd.AddValue(
"serverShortGuardInterval",
243 "Set short guard interval of the server (802.11n/ac/ax) in nanoseconds",
244 serverShortGuardInterval);
245 cmd.AddValue(
"clientShortGuardInterval",
246 "Set short guard interval of the client (802.11n/ac/ax) in nanoseconds",
247 clientShortGuardInterval);
250 "Set standard (802.11a, 802.11b, 802.11g, 802.11p-10MHz, 802.11p-5MHz, 802.11n-5GHz, "
251 "802.11n-2.4GHz, 802.11ac, 802.11ax-6GHz, 802.11ax-5GHz, 802.11ax-2.4GHz)",
253 cmd.AddValue(
"wifiManager",
254 "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, "
255 "MinstrelHt, Onoe, Rraa, ThompsonSampling)",
257 cmd.AddValue(
"infrastructure",
"Use infrastructure instead of adhoc", infrastructure);
258 cmd.Parse(argc, argv);
261 std::cout << std::endl
262 <<
"This program demonstrates and plots the operation of different " << std::endl;
263 std::cout <<
"Wi-Fi rate controls on different station configurations," << std::endl;
264 std::cout <<
"by stepping down the received signal strength across a wide range" << std::endl;
265 std::cout <<
"and observing the adjustment of the rate." << std::endl;
266 std::cout <<
"Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl
272 "In ad hoc mode, we assume sender and receiver are similarly configured");
275 if (standard ==
"802.11b")
277 if (serverChannelWidth ==
MHz_u{0})
282 "Invalid channel width for standard " << standard);
283 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
284 if (clientChannelWidth ==
MHz_u{0})
289 "Invalid channel width for standard " << standard);
290 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
292 else if (standard ==
"802.11a" || standard ==
"802.11g")
294 if (serverChannelWidth ==
MHz_u{0})
299 "Invalid channel width for standard " << standard);
300 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
301 if (clientChannelWidth ==
MHz_u{0})
306 "Invalid channel width for standard " << standard);
307 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
309 else if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz")
313 if (serverChannelWidth ==
MHz_u{0})
318 "Invalid channel width for standard " << standard);
320 "Invalid nss " << serverNss <<
" for standard " << standard);
321 if (clientChannelWidth ==
MHz_u{0})
326 "Invalid channel width for standard " << standard);
328 "Invalid nss " << clientNss <<
" for standard " << standard);
330 else if (standard ==
"802.11ac")
332 if (serverChannelWidth ==
MHz_u{0})
337 serverChannelWidth !=
MHz_u{80} && serverChannelWidth !=
MHz_u{160},
338 "Invalid channel width for standard " << standard);
340 "Invalid nss " << serverNss <<
" for standard " << standard);
341 if (clientChannelWidth ==
MHz_u{0})
346 clientChannelWidth !=
MHz_u{80} && clientChannelWidth !=
MHz_u{160},
347 "Invalid channel width for standard " << standard);
349 "Invalid nss " << clientNss <<
" for standard " << standard);
351 else if (standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" ||
352 standard ==
"802.11ax-2.4GHz")
357 if (serverChannelWidth ==
MHz_u{0})
362 serverChannelWidth !=
MHz_u{80} && serverChannelWidth !=
MHz_u{160},
363 "Invalid channel width for standard " << standard);
365 "Invalid nss " << serverNss <<
" for standard " << standard);
366 if (clientChannelWidth ==
MHz_u{0})
371 clientChannelWidth !=
MHz_u{80} && clientChannelWidth !=
MHz_u{160},
372 "Invalid channel width for standard " << standard);
374 "Invalid nss " << clientNss <<
" for standard " << standard);
378 uint32_t channelRateFactor = std::max(clientChannelWidth, serverChannelWidth) /
MHz_u{20};
379 channelRateFactor = channelRateFactor * std::max(clientNss, serverNss);
420 80 * channelRateFactor),
429 80 * channelRateFactor),
438 120 * channelRateFactor),
465 120 * channelRateFactor),
474 120 * channelRateFactor),
483 120 * channelRateFactor),
522 80 * channelRateFactor),
531 80 * channelRateFactor),
540 120 * channelRateFactor),
567 160 * channelRateFactor),
576 160 * channelRateFactor),
585 160 * channelRateFactor),
588 for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size(); i++)
590 if (standard == serverStandards[i].m_name)
592 serverSelectedStandard = serverStandards[i];
595 for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size(); i++)
597 if (standard == clientStandards[i].m_name)
599 clientSelectedStandard = clientStandards[i];
604 "Standard " << standard <<
" not found");
606 "Standard " << standard <<
" not found");
607 std::cout <<
"Testing " << serverSelectedStandard.
m_name <<
" with " << wifiManager <<
" ..."
610 "SNR values in wrong order");
611 steps =
static_cast<uint32_t>(std::abs(
static_cast<double>(clientSelectedStandard.
m_snrHigh -
616 <<
":" << clientSelectedStandard.
m_snrHigh);
620 std::string plotName =
"wifi-manager-example-";
621 std::string dataName =
"wifi-manager-example-";
622 plotName += wifiManager;
623 dataName += wifiManager;
626 plotName += standard;
627 dataName += standard;
628 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
629 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
631 plotName +=
"-server_";
632 dataName +=
"-server_";
633 std::ostringstream oss;
634 oss << serverChannelWidth <<
"MHz_" << serverShortGuardInterval <<
"ns_" << serverNss
636 plotName += oss.str();
637 dataName += oss.str();
638 plotName +=
"-client_";
639 dataName +=
"-client_";
641 oss << clientChannelWidth <<
"MHz_" << clientShortGuardInterval <<
"ns_" << clientNss
643 plotName += oss.str();
644 dataName += oss.str();
648 std::ofstream outfile(dataName);
677 wifiChannel->SetPropagationDelayModel(delayModel);
679 wifiChannel->SetPropagationLossModel(rssLossModel);
682 wifi.SetRemoteStationManager(
"ns3::" + wifiManager +
"WifiManager",
700 {0, serverSelectedStandard.
m_width, serverSelectedStandard.
m_band, 0}});
701 wifiPhy.
Set(
"ChannelSettings", channelValue);
702 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
706 {0, clientSelectedStandard.
m_width, clientSelectedStandard.
m_band, 0}});
707 wifiPhy.
Set(
"ChannelSettings", channelValue);
708 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
712 wifiMac.
SetType(
"ns3::AdhocWifiMac");
714 {0, serverSelectedStandard.
m_width, serverSelectedStandard.
m_band, 0}});
715 wifiPhy.
Set(
"ChannelSettings", channelValue);
716 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
719 {0, clientSelectedStandard.
m_width, clientSelectedStandard.
m_band, 0}});
720 wifiPhy.
Set(
"ChannelSettings", channelValue);
721 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
727 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
731 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
739 positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
740 NS_LOG_INFO(
"Setting initial AP position to " << Vector(ap1_x, ap1_y, 0.0));
741 positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
742 NS_LOG_INFO(
"Setting initial STA position to " << Vector(sta1_x, sta1_y, 0.0));
743 mobility.SetPositionAllocator(positionAlloc);
744 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
763 auto t_clientNss =
static_cast<uint8_t
>(clientNss);
764 auto t_serverNss =
static_cast<uint8_t
>(serverNss);
765 wifiPhyPtrClient->SetNumberOfAntennas(t_clientNss);
766 wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
767 wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
768 wifiPhyPtrServer->SetNumberOfAntennas(t_serverNss);
769 wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams(t_serverNss);
770 wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams(t_serverNss);
772 if (serverSelectedStandard.
m_name ==
"802.11n-5GHz" ||
773 serverSelectedStandard.
m_name ==
"802.11n-2.4GHz" ||
774 serverSelectedStandard.
m_name ==
"802.11ac")
777 clientHtConfiguration->m_sgiSupported = (clientShortGuardInterval == 400);
779 serverHtConfiguration->m_sgiSupported = (serverShortGuardInterval == 400);
781 else if (serverSelectedStandard.
m_name ==
"802.11ax-6GHz" ||
782 serverSelectedStandard.
m_name ==
"802.11ax-5GHz" ||
783 serverSelectedStandard.
m_name ==
"802.11ax-2.4GHz")
785 wndServer->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(serverShortGuardInterval));
786 wndClient->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(clientShortGuardInterval));
790 const auto BOLTZMANN = 1.3803e-23;
792 const dBm_u noise = noiseDensity + (10 * log10(clientSelectedStandard.
m_width * 1000000));
794 NS_LOG_DEBUG(
"Channel width " << wifiPhyPtrClient->GetChannelWidth() <<
" noise " << noise);
795 NS_LOG_DEBUG(
"NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
797 const dBm_u rssCurrent = (clientSelectedStandard.
m_snrHigh + noise);
798 rssLossModel->SetRss(rssCurrent);
799 NS_LOG_INFO(
"Setting initial Rss to " << rssCurrent);
811 packetSocketHelper.
Install(serverNode);
812 packetSocketHelper.
Install(clientNode);
830 client->SetRemote(socketAddr);
836 double rate = clientSelectedStandard.
m_yMax * 1e6 * 1.10;
837 double clientInterval =
static_cast<double>(
packetSize) * 8 / rate;
838 NS_LOG_DEBUG(
"Setting interval to " << clientInterval <<
" sec for rate of " << rate
842 clientNode->AddApplication(client);
845 server->SetLocal(socketAddr);
847 serverNode->AddApplication(server);
855 wndServer->GetMac()->GetAddress(),
857 "Expected BA agreement established for standard "
866 std::ostringstream xMinStr;
867 std::ostringstream xMaxStr;
868 std::ostringstream yMaxStr;
869 std::string xRangeStr(
"set xrange [");
870 xMinStr << clientSelectedStandard.
m_xMin;
871 xRangeStr.append(xMinStr.str());
872 xRangeStr.append(
":");
873 xMaxStr << clientSelectedStandard.
m_xMax;
874 xRangeStr.append(xMaxStr.str());
875 xRangeStr.append(
"]");
876 std::string yRangeStr(
"set yrange [0:");
877 yMaxStr << clientSelectedStandard.
m_yMax;
878 yRangeStr.append(yMaxStr.str());
879 yRangeStr.append(
"]");
881 std::string title(
"Results for ");
882 title.append(standard);
883 title.append(
" with ");
884 title.append(wifiManager);
886 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
887 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
889 std::ostringstream serverGiStrStr;
890 std::ostringstream serverWidthStrStr;
891 std::ostringstream serverNssStrStr;
892 title.append(
"server: width=");
893 serverWidthStrStr << serverSelectedStandard.
m_width;
894 title.append(serverWidthStrStr.str());
896 title.append(
" GI=");
897 serverGiStrStr << serverShortGuardInterval;
898 title.append(serverGiStrStr.str());
900 title.append(
" nss=");
901 serverNssStrStr << serverNss;
902 title.append(serverNssStrStr.str());
904 std::ostringstream clientGiStrStr;
905 std::ostringstream clientWidthStrStr;
906 std::ostringstream clientNssStrStr;
907 title.append(
"client: width=");
908 clientWidthStrStr << clientSelectedStandard.
m_width;
909 title.append(clientWidthStrStr.str());
911 title.append(
" GI=");
912 clientGiStrStr << clientShortGuardInterval;
913 title.append(clientGiStrStr.str());
915 title.append(
" nss=");
916 clientNssStrStr << clientNss;
917 title.append(clientNssStrStr.str());
919 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
920 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.
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.
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.