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, 802.11be-6GHz, "
252 "802.11be-5GHz, 802.11be-2.4GHz)",
254 cmd.AddValue(
"wifiManager",
255 "Set wifi rate manager (Aarf, Aarfcd, Amrr, Arf, Cara, Ideal, Minstrel, "
256 "MinstrelHt, Onoe, Rraa, ThompsonSampling)",
258 cmd.AddValue(
"infrastructure",
"Use infrastructure instead of adhoc", infrastructure);
259 cmd.Parse(argc, argv);
262 std::cout << std::endl
263 <<
"This program demonstrates and plots the operation of different " << std::endl;
264 std::cout <<
"Wi-Fi rate controls on different station configurations," << std::endl;
265 std::cout <<
"by stepping down the received signal strength across a wide range" << std::endl;
266 std::cout <<
"and observing the adjustment of the rate." << std::endl;
267 std::cout <<
"Run 'wifi-manager-example --PrintHelp' to show program options." << std::endl
273 "In ad hoc mode, we assume sender and receiver are similarly configured");
276 if (standard ==
"802.11b")
278 if (serverChannelWidth ==
MHz_u{0})
283 "Invalid channel width for standard " << standard);
284 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
285 if (clientChannelWidth ==
MHz_u{0})
290 "Invalid channel width for standard " << standard);
291 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
293 else if (standard ==
"802.11a" || standard ==
"802.11g")
295 if (serverChannelWidth ==
MHz_u{0})
300 "Invalid channel width for standard " << standard);
301 NS_ABORT_MSG_IF(serverNss != 1,
"Invalid nss for standard " << standard);
302 if (clientChannelWidth ==
MHz_u{0})
307 "Invalid channel width for standard " << standard);
308 NS_ABORT_MSG_IF(clientNss != 1,
"Invalid nss for standard " << standard);
310 else if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz")
314 if (serverChannelWidth ==
MHz_u{0})
319 "Invalid channel width for standard " << standard);
321 "Invalid nss " << serverNss <<
" for standard " << standard);
322 if (clientChannelWidth ==
MHz_u{0})
327 "Invalid channel width for standard " << standard);
329 "Invalid nss " << clientNss <<
" for standard " << standard);
331 else if (standard ==
"802.11ac")
333 if (serverChannelWidth ==
MHz_u{0})
338 serverChannelWidth !=
MHz_u{80} && serverChannelWidth !=
MHz_u{160} &&
339 serverChannelWidth !=
MHz_u{320},
340 "Invalid channel width for standard " << standard);
342 "Invalid nss " << serverNss <<
" for standard " << standard);
343 if (clientChannelWidth ==
MHz_u{0})
348 clientChannelWidth !=
MHz_u{80} && clientChannelWidth !=
MHz_u{160} &&
349 clientChannelWidth !=
MHz_u{320},
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" || standard ==
"802.11be-6GHz" ||
356 standard ==
"802.11be-5GHz" || standard ==
"802.11be-2.4GHz")
361 if (serverChannelWidth ==
MHz_u{0})
366 serverChannelWidth !=
MHz_u{80} && serverChannelWidth !=
MHz_u{160} &&
367 serverChannelWidth !=
MHz_u{320},
368 "Invalid channel width for standard " << standard);
370 "Invalid nss " << serverNss <<
" for standard " << standard);
371 if (clientChannelWidth ==
MHz_u{0})
376 clientChannelWidth !=
MHz_u{80} && clientChannelWidth !=
MHz_u{160} &&
377 clientChannelWidth !=
MHz_u{320},
378 "Invalid channel width for standard " << standard);
380 "Invalid nss " << clientNss <<
" for standard " << standard);
384 uint32_t channelRateFactor = std::max(clientChannelWidth, serverChannelWidth) /
MHz_u{20};
385 channelRateFactor = channelRateFactor * std::max(clientNss, serverNss);
426 80 * channelRateFactor),
435 80 * channelRateFactor),
444 120 * channelRateFactor),
471 120 * channelRateFactor),
480 120 * channelRateFactor),
489 120 * channelRateFactor),
498 120 * channelRateFactor),
507 120 * channelRateFactor),
516 120 * channelRateFactor),
555 80 * channelRateFactor),
564 80 * channelRateFactor),
573 120 * channelRateFactor),
600 160 * channelRateFactor),
609 160 * channelRateFactor),
618 160 * channelRateFactor),
627 160 * channelRateFactor),
636 160 * channelRateFactor),
645 160 * channelRateFactor),
648 for (std::vector<StandardInfo>::size_type i = 0; i != serverStandards.size(); i++)
650 if (standard == serverStandards[i].m_name)
652 serverSelectedStandard = serverStandards[i];
655 for (std::vector<StandardInfo>::size_type i = 0; i != clientStandards.size(); i++)
657 if (standard == clientStandards[i].m_name)
659 clientSelectedStandard = clientStandards[i];
664 "Standard " << standard <<
" not found");
666 "Standard " << standard <<
" not found");
667 std::cout <<
"Testing " << serverSelectedStandard.
m_name <<
" with " << wifiManager <<
" ..."
670 "SNR values in wrong order");
671 steps =
static_cast<uint32_t>(std::abs(
static_cast<double>(clientSelectedStandard.
m_snrHigh -
676 <<
":" << clientSelectedStandard.
m_snrHigh);
680 std::string plotName =
"wifi-manager-example-";
681 std::string dataName =
"wifi-manager-example-";
682 plotName += wifiManager;
683 dataName += wifiManager;
686 plotName += standard;
687 dataName += standard;
688 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
689 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" || standard ==
"802.11ax-2.4GHz")
691 plotName +=
"-server_";
692 dataName +=
"-server_";
693 std::ostringstream oss;
694 oss << serverChannelWidth <<
"MHz_" << serverShortGuardInterval <<
"ns_" << serverNss
696 plotName += oss.str();
697 dataName += oss.str();
698 plotName +=
"-client_";
699 dataName +=
"-client_";
701 oss << clientChannelWidth <<
"MHz_" << clientShortGuardInterval <<
"ns_" << clientNss
703 plotName += oss.str();
704 dataName += oss.str();
708 std::ofstream outfile(dataName);
737 wifiChannel->SetPropagationDelayModel(delayModel);
739 wifiChannel->SetPropagationLossModel(rssLossModel);
742 wifi.SetRemoteStationManager(
"ns3::" + wifiManager +
"WifiManager",
757 {0, serverSelectedStandard.
m_width, serverSelectedStandard.
m_band, 0}});
758 wifiPhy.
Set(
"ChannelSettings", channelValue);
759 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
763 {0, clientSelectedStandard.
m_width, clientSelectedStandard.
m_band, 0}});
764 wifiPhy.
Set(
"ChannelSettings", channelValue);
765 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
769 wifiMac.
SetType(
"ns3::AdhocWifiMac");
771 {0, serverSelectedStandard.
m_width, serverSelectedStandard.
m_band, 0}});
772 wifiPhy.
Set(
"ChannelSettings", channelValue);
773 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
776 {0, clientSelectedStandard.
m_width, clientSelectedStandard.
m_band, 0}});
777 wifiPhy.
Set(
"ChannelSettings", channelValue);
778 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
784 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
788 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
796 positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
797 NS_LOG_INFO(
"Setting initial AP position to " << Vector(ap1_x, ap1_y, 0.0));
798 positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
799 NS_LOG_INFO(
"Setting initial STA position to " << Vector(sta1_x, sta1_y, 0.0));
800 mobility.SetPositionAllocator(positionAlloc);
801 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
820 auto t_clientNss =
static_cast<uint8_t
>(clientNss);
821 auto t_serverNss =
static_cast<uint8_t
>(serverNss);
822 wifiPhyPtrClient->SetNumberOfAntennas(t_clientNss);
823 wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
824 wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
825 wifiPhyPtrServer->SetNumberOfAntennas(t_serverNss);
826 wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams(t_serverNss);
827 wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams(t_serverNss);
829 if (serverSelectedStandard.
m_name ==
"802.11n-5GHz" ||
830 serverSelectedStandard.
m_name ==
"802.11n-2.4GHz" ||
831 serverSelectedStandard.
m_name ==
"802.11ac")
834 clientHtConfiguration->m_sgiSupported = (clientShortGuardInterval == 400);
836 serverHtConfiguration->m_sgiSupported = (serverShortGuardInterval == 400);
838 else if (serverSelectedStandard.
m_name ==
"802.11ax-6GHz" ||
839 serverSelectedStandard.
m_name ==
"802.11ax-5GHz" ||
840 serverSelectedStandard.
m_name ==
"802.11ax-2.4GHz" ||
841 serverSelectedStandard.
m_name ==
"802.11be-6GHz" ||
842 serverSelectedStandard.
m_name ==
"802.11be-5GHz" ||
843 serverSelectedStandard.
m_name ==
"802.11be-2.4GHz")
845 wndServer->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(serverShortGuardInterval));
846 wndClient->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(clientShortGuardInterval));
850 const auto BOLTZMANN = 1.3803e-23;
852 const dBm_u noise = noiseDensity + (10 * log10(clientSelectedStandard.
m_width * 1000000));
854 NS_LOG_DEBUG(
"Channel width " << wifiPhyPtrClient->GetChannelWidth() <<
" noise " << noise);
855 NS_LOG_DEBUG(
"NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
857 const dBm_u rssCurrent = (clientSelectedStandard.
m_snrHigh + noise);
858 rssLossModel->SetRss(rssCurrent);
859 NS_LOG_INFO(
"Setting initial Rss to " << rssCurrent);
871 packetSocketHelper.
Install(serverNode);
872 packetSocketHelper.
Install(clientNode);
890 client->SetRemote(socketAddr);
896 double rate = clientSelectedStandard.
m_yMax * 1e6 * 1.10;
897 double clientInterval =
static_cast<double>(
packetSize) * 8 / rate;
898 NS_LOG_DEBUG(
"Setting interval to " << clientInterval <<
" sec for rate of " << rate
902 clientNode->AddApplication(client);
905 server->SetLocal(socketAddr);
907 serverNode->AddApplication(server);
915 wndServer->GetMac()->GetAddress(),
917 "Expected BA agreement established for standard "
926 std::ostringstream xMinStr;
927 std::ostringstream xMaxStr;
928 std::ostringstream yMaxStr;
929 std::string xRangeStr(
"set xrange [");
930 xMinStr << clientSelectedStandard.
m_xMin;
931 xRangeStr.append(xMinStr.str());
932 xRangeStr.append(
":");
933 xMaxStr << clientSelectedStandard.
m_xMax;
934 xRangeStr.append(xMaxStr.str());
935 xRangeStr.append(
"]");
936 std::string yRangeStr(
"set yrange [0:");
937 yMaxStr << clientSelectedStandard.
m_yMax;
938 yRangeStr.append(yMaxStr.str());
939 yRangeStr.append(
"]");
941 std::string title(
"Results for ");
942 title.append(standard);
943 title.append(
" with ");
944 title.append(wifiManager);
946 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
947 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" ||
948 standard ==
"802.11ax-2.4GHz" || standard ==
"802.11be-6GHz" ||
949 standard ==
"802.11be-5GHz" || standard ==
"802.11be-2.4GHz")
951 std::ostringstream serverGiStrStr;
952 std::ostringstream serverWidthStrStr;
953 std::ostringstream serverNssStrStr;
954 title.append(
"server: width=");
955 serverWidthStrStr << serverSelectedStandard.
m_width;
956 title.append(serverWidthStrStr.str());
958 title.append(
" GI=");
959 serverGiStrStr << serverShortGuardInterval;
960 title.append(serverGiStrStr.str());
962 title.append(
" nss=");
963 serverNssStrStr << serverNss;
964 title.append(serverNssStrStr.str());
966 std::ostringstream clientGiStrStr;
967 std::ostringstream clientWidthStrStr;
968 std::ostringstream clientNssStrStr;
969 title.append(
"client: width=");
970 clientWidthStrStr << clientSelectedStandard.
m_width;
971 title.append(clientWidthStrStr.str());
973 title.append(
" GI=");
974 clientGiStrStr << clientShortGuardInterval;
975 title.append(clientGiStrStr.str());
977 title.append(
" nss=");
978 clientNssStrStr << clientNss;
979 title.append(clientNssStrStr.str());
981 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
982 gnuplot.
SetLegend(
"SNR (dB)",
"Rate (Mb/s)");
a polymophic address class
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.
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::list< WifiChannelConfig::TupleWithoutUnits > ChannelSegments
segments identifying an operating channel
AttributeContainerValue< ChannelTupleValue, ';'> ChannelSettingsValue
AttributeValue type of a ChannelSegments object.
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.
double MHz_u
MHz weak type.
double dBm_per_Hz_u
dBm/Hz weak type
MHz_u GetDefaultChannelWidth(WifiStandard standard, WifiPhyBand band)
Get the default channel width for the given PHY standard and band.
double dBm_u
dBm weak type
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.