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",
760 {0, serverSelectedStandard.
m_width, serverSelectedStandard.
m_band, 0}});
761 wifiPhy.
Set(
"ChannelSettings", channelValue);
762 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
766 {0, clientSelectedStandard.
m_width, clientSelectedStandard.
m_band, 0}});
767 wifiPhy.
Set(
"ChannelSettings", channelValue);
768 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
772 wifiMac.
SetType(
"ns3::AdhocWifiMac");
774 {0, serverSelectedStandard.
m_width, serverSelectedStandard.
m_band, 0}});
775 wifiPhy.
Set(
"ChannelSettings", channelValue);
776 serverDevice =
wifi.Install(wifiPhy, wifiMac, serverNode);
779 {0, clientSelectedStandard.
m_width, clientSelectedStandard.
m_band, 0}});
780 wifiPhy.
Set(
"ChannelSettings", channelValue);
781 clientDevice =
wifi.Install(wifiPhy, wifiMac, clientNode);
787 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
791 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/RemoteStationManager/$ns3::" + wifiManager +
799 positionAlloc->Add(Vector(ap1_x, ap1_y, 0.0));
800 NS_LOG_INFO(
"Setting initial AP position to " << Vector(ap1_x, ap1_y, 0.0));
801 positionAlloc->Add(Vector(sta1_x, sta1_y, 0.0));
802 NS_LOG_INFO(
"Setting initial STA position to " << Vector(sta1_x, sta1_y, 0.0));
803 mobility.SetPositionAllocator(positionAlloc);
804 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
823 auto t_clientNss =
static_cast<uint8_t
>(clientNss);
824 auto t_serverNss =
static_cast<uint8_t
>(serverNss);
825 wifiPhyPtrClient->SetNumberOfAntennas(t_clientNss);
826 wifiPhyPtrClient->SetMaxSupportedTxSpatialStreams(t_clientNss);
827 wifiPhyPtrClient->SetMaxSupportedRxSpatialStreams(t_clientNss);
828 wifiPhyPtrServer->SetNumberOfAntennas(t_serverNss);
829 wifiPhyPtrServer->SetMaxSupportedTxSpatialStreams(t_serverNss);
830 wifiPhyPtrServer->SetMaxSupportedRxSpatialStreams(t_serverNss);
832 if (serverSelectedStandard.
m_name ==
"802.11n-5GHz" ||
833 serverSelectedStandard.
m_name ==
"802.11n-2.4GHz" ||
834 serverSelectedStandard.
m_name ==
"802.11ac")
837 clientHtConfiguration->m_sgiSupported = (clientShortGuardInterval == 400);
839 serverHtConfiguration->m_sgiSupported = (serverShortGuardInterval == 400);
841 else if (serverSelectedStandard.
m_name ==
"802.11ax-6GHz" ||
842 serverSelectedStandard.
m_name ==
"802.11ax-5GHz" ||
843 serverSelectedStandard.
m_name ==
"802.11ax-2.4GHz" ||
844 serverSelectedStandard.
m_name ==
"802.11be-6GHz" ||
845 serverSelectedStandard.
m_name ==
"802.11be-5GHz" ||
846 serverSelectedStandard.
m_name ==
"802.11be-2.4GHz")
848 wndServer->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(serverShortGuardInterval));
849 wndClient->GetHeConfiguration()->SetGuardInterval(
NanoSeconds(clientShortGuardInterval));
853 const auto BOLTZMANN = 1.3803e-23;
855 const dBm_u noise = noiseDensity + (10 * log10(clientSelectedStandard.
m_width * 1000000));
857 NS_LOG_DEBUG(
"Channel width " << wifiPhyPtrClient->GetChannelWidth() <<
" noise " << noise);
858 NS_LOG_DEBUG(
"NSS " << wifiPhyPtrClient->GetMaxSupportedTxSpatialStreams());
860 const dBm_u rssCurrent = (clientSelectedStandard.
m_snrHigh + noise);
861 rssLossModel->SetRss(rssCurrent);
862 NS_LOG_INFO(
"Setting initial Rss to " << rssCurrent);
874 packetSocketHelper.
Install(serverNode);
875 packetSocketHelper.
Install(clientNode);
893 client->SetRemote(socketAddr);
899 double rate = clientSelectedStandard.
m_yMax * 1e6 * 1.10;
900 double clientInterval =
static_cast<double>(
packetSize) * 8 / rate;
901 NS_LOG_DEBUG(
"Setting interval to " << clientInterval <<
" sec for rate of " << rate
905 clientNode->AddApplication(client);
908 server->SetLocal(socketAddr);
910 serverNode->AddApplication(server);
918 wndServer->GetMac()->GetAddress(),
920 "Expected BA agreement established for standard "
929 std::ostringstream xMinStr;
930 std::ostringstream xMaxStr;
931 std::ostringstream yMaxStr;
932 std::string xRangeStr(
"set xrange [");
933 xMinStr << clientSelectedStandard.
m_xMin;
934 xRangeStr.append(xMinStr.str());
935 xRangeStr.append(
":");
936 xMaxStr << clientSelectedStandard.
m_xMax;
937 xRangeStr.append(xMaxStr.str());
938 xRangeStr.append(
"]");
939 std::string yRangeStr(
"set yrange [0:");
940 yMaxStr << clientSelectedStandard.
m_yMax;
941 yRangeStr.append(yMaxStr.str());
942 yRangeStr.append(
"]");
944 std::string title(
"Results for ");
945 title.append(standard);
946 title.append(
" with ");
947 title.append(wifiManager);
949 if (standard ==
"802.11n-5GHz" || standard ==
"802.11n-2.4GHz" || standard ==
"802.11ac" ||
950 standard ==
"802.11ax-6GHz" || standard ==
"802.11ax-5GHz" ||
951 standard ==
"802.11ax-2.4GHz" || standard ==
"802.11be-6GHz" ||
952 standard ==
"802.11be-5GHz" || standard ==
"802.11be-2.4GHz")
954 std::ostringstream serverGiStrStr;
955 std::ostringstream serverWidthStrStr;
956 std::ostringstream serverNssStrStr;
957 title.append(
"server: width=");
958 serverWidthStrStr << serverSelectedStandard.
m_width;
959 title.append(serverWidthStrStr.str());
961 title.append(
" GI=");
962 serverGiStrStr << serverShortGuardInterval;
963 title.append(serverGiStrStr.str());
965 title.append(
" nss=");
966 serverNssStrStr << serverNss;
967 title.append(serverNssStrStr.str());
969 std::ostringstream clientGiStrStr;
970 std::ostringstream clientWidthStrStr;
971 std::ostringstream clientNssStrStr;
972 title.append(
"client: width=");
973 clientWidthStrStr << clientSelectedStandard.
m_width;
974 title.append(clientWidthStrStr.str());
976 title.append(
" GI=");
977 clientGiStrStr << clientShortGuardInterval;
978 title.append(clientGiStrStr.str());
980 title.append(
" nss=");
981 clientNssStrStr << clientNss;
982 title.append(clientNssStrStr.str());
984 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
985 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.