18#include "ns3/ampdu-subframe-header.h"
19#include "ns3/application-container.h"
20#include "ns3/boolean.h"
21#include "ns3/command-line.h"
22#include "ns3/config.h"
23#include "ns3/double.h"
24#include "ns3/gnuplot.h"
25#include "ns3/integer.h"
27#include "ns3/mobility-helper.h"
28#include "ns3/node-list.h"
29#include "ns3/packet-socket-client.h"
30#include "ns3/packet-socket-helper.h"
31#include "ns3/packet-socket-server.h"
32#include "ns3/propagation-delay-model.h"
33#include "ns3/propagation-loss-model.h"
34#include "ns3/queue-size.h"
35#include "ns3/rng-seed-manager.h"
37#include "ns3/string.h"
38#include "ns3/uinteger.h"
39#include "ns3/wifi-mac-header.h"
40#include "ns3/wifi-mac.h"
41#include "ns3/wifi-net-device.h"
42#include "ns3/wifi-phy-rx-trace-helper.h"
43#include "ns3/wifi-tx-stats-helper.h"
44#include "ns3/yans-wifi-helper.h"
58#define PI 3.1415926535
78std::map<Mac48Address, uint64_t>
80std::map<Mac48Address, uint64_t>
82std::map<Mac48Address, uint64_t>
86std::map<Mac48Address, uint64_t>
91std::map<Mac48Address, uint64_t>
94std::map<Mac48Address, uint64_t>
97std::map<Mac48Address, uint64_t>
100std::map<Mac48Address, uint64_t>
104std::map<Mac48Address, Time>
107std::map<Mac48Address, Time>
125std::map<std::string ,
126 std::map<
unsigned int ,
double >>
313 {
"ErpOfdmRate12Mbps",
326 {
"ErpOfdmRate18Mbps",
339 {
"ErpOfdmRate24Mbps",
352 {
"ErpOfdmRate36Mbps",
365 {
"ErpOfdmRate48Mbps",
378 {
"ErpOfdmRate54Mbps",
1019std::map<std::string ,
1020 std::map<
unsigned int ,
double >>
1181 {
"ErpOfdmRate6Mbps",
1194 {
"ErpOfdmRate9Mbps",
1207 {
"ErpOfdmRate12Mbps",
1220 {
"ErpOfdmRate18Mbps",
1233 {
"ErpOfdmRate24Mbps",
1246 {
"ErpOfdmRate36Mbps",
1259 {
"ErpOfdmRate48Mbps",
1272 {
"ErpOfdmRate54Mbps",
1921 std::string sub = context.substr(10);
1922 uint32_t pos = sub.find(
"/Device");
1923 return std::stoi(sub.substr(0, pos));
1935 std::string sub = context.substr(10);
1936 uint32_t pos = sub.find(
"/Device");
1937 uint32_t nodeId = std::stoi(sub.substr(0, pos));
1940 for (
uint32_t i = 0; i < n->GetNDevices(); i++)
1963 uint64_t increment = 1)
1965 auto it = counter.find(addr);
1966 if (it != counter.end())
1968 it->second += increment;
1972 counter.insert(std::make_pair(addr, increment));
1990 uint16_t channelFreqMhz,
2001 packet->RemoveHeader(subHdr);
2003 packet = packet->CreateFragment(0,
static_cast<uint32_t>(extractedLength));
2006 packet->PeekHeader(hdr);
2013 if (packet->GetSize() >=
pktSize)
2062 <<
" val=" << newVal);
2066 << newVal << std::endl;
2081 <<
" size=" << p->GetSize());
2096 <<
" psduDuration=" << psduDuration);
2110 <<
" size=" << p->GetSize() <<
" reason=" << reason);
2166 NS_FATAL_ERROR(
"All devices should send with same power, so no packet switch during "
2167 "preamble detection should occur!");
2194 <<
" size=" << p->GetSize());
2213 uint8_t nMpdus = (p->GetSize() /
pktSize);
2216 <<
" nMPDUs=" << +nMpdus <<
" snr=" << snr <<
" mode=" << mode
2217 <<
" preamble=" << preamble);
2222 NS_FATAL_ERROR(
"A-MPDU settings not properly applied: maximum configured MPDUs is "
2223 << +
maxMpdus <<
" but received an A-MPDU containing " << +nMpdus
2226 NS_LOG_WARN(
"Warning: less MPDUs aggregated in a received A-MPDU ("
2227 << +nMpdus <<
") than configured (" << +
maxMpdus <<
")");
2247 <<
" size=" << p->GetSize() <<
" snr=" << snr);
2266 <<
" size=" << p->GetSize() <<
" " << txPowerW);
2270 <<
" size=" << p->GetSize() <<
" " << txPowerW << std::endl;
2289 <<
" " << p->GetSize());
2304 << p->GetSize() << std::endl;
2320 << p->GetSize() << std::endl;
2337 <<
" " << p->GetSize() <<
" " << addr << std::endl;
2436 uint16_t guardIntervalNs,
2457 uint16_t guardIntervalNs,
2469 wifiNodes.
Create(networkSize + 1);
2473 wifiNodes.
Create(networkSize);
2477 phy.SetErrorRateModel(
"ns3::NistErrorRateModel");
2478 phy.SetChannel(wifiChannel.
Create());
2482 const auto& wifi = helper;
2488 uint64_t beaconInterval = std::min<uint64_t>(
2489 (ceil((duration.
GetSeconds() * 1000000) / 1024) * 1024),
2491 mac.SetType(
"ns3::ApWifiMac",
2498 devices = wifi.Install(phy, mac, wifiNodes.
Get(0));
2500 mac.SetType(
"ns3::StaWifiMac",
2507 for (
uint32_t i = 1; i < nNodes; ++i)
2509 devices.Add(wifi.Install(phy, mac, wifiNodes.
Get(i)));
2514 mac.SetType(
"ns3::AdhocWifiMac");
2517 devices = wifi.Install(phy, mac, wifiNodes);
2523 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/ShortGuardIntervalSupported",
2525 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HeConfiguration/GuardInterval",
2529 for (
uint32_t i = 0; i < nNodes; ++i)
2533 wifi_dev->GetMac()->SetAttribute(
"BE_MaxAmpduSize",
2535 wifi_dev->GetMac()->SetAttribute(
"BK_MaxAmpduSize",
2537 wifi_dev->GetMac()->SetAttribute(
"VO_MaxAmpduSize",
2539 wifi_dev->GetMac()->SetAttribute(
"VI_MaxAmpduSize",
2545 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
2547 positionAlloc->Add(Vector(1.0, 1.0, 0.0));
2550 const auto angle = (
static_cast<degree_u>(360) / (nNodes - 1));
2551 for (
uint32_t i = 0; i < (nNodes - 1); ++i)
2553 positionAlloc->Add(Vector(1.0 + (distance * cos((i * angle *
PI) / 180)),
2554 1.0 + (distance * sin((i * angle *
PI) / 180)),
2558 mobility.SetPositionAllocator(positionAlloc);
2559 mobility.Install(wifiNodes);
2562 packetSocket.
Install(wifiNodes);
2566 startTime->SetAttribute(
"Stream",
IntegerValue(trialNumber));
2570 for (; i < nNodes; ++i)
2572 uint32_t j = infra ? 0 : (i + 1) % nNodes;
2579 client->SetRemote(socketAddr);
2583 client->SetAttribute(
"Interval",
TimeValue(pktInterval));
2584 double start = startTime->GetValue();
2585 NS_LOG_DEBUG(
"Client " << i <<
" starting at " << start);
2586 client->SetStartTime(
Seconds(start));
2589 server->SetLocal(socketAddr);
2595 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/MonitorSnifferRx",
2601 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/Assoc",
2603 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/DeAssoc",
2612 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::WifiMac/" + txop +
2616 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::WifiMac/" + txop +
2620 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxBegin",
2623 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxEnd",
2626 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxBegin",
2630 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxPayloadBegin",
2633 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxDrop",
2636 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxEnd",
2639 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxError",
2642 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxOk",
2645 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx",
2648 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx",
2651 Config::Connect(
"/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::PacketSocketClient/Tx",
2658 wifiTxStats.
Enable(devices);
2667 rxTraceHelper.
Enable(devices);
2677 phy.EnablePcap(
"wifi_bianchi_pcap", devices);
2688 const auto numFailureDueToFailedEnqueuePerNodeDevice =
2690 const auto numFailureDueToExpiredLifetimePerNodeDevice =
2692 const auto numFailureDueToRetryLimitReachedPerNodeDevice =
2694 const auto numFailureDueToQosOldPacketPerNodeDevice =
2697 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs acked during (10, "
2699 if (numSuccessPerNodeDevice.empty())
2701 std::cout <<
"none\n";
2705 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nSuccess" << std::endl;
2706 for (
const auto& [nodeDevTuple, nSuccess] : numSuccessPerNodeDevice)
2708 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nSuccess
2713 <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to any reason) during (10, "
2715 if (numFailurePerNodeDevice.empty())
2717 std::cout <<
"none\n";
2721 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2722 for (
const auto& [nodeDevTuple, nFailure] : numFailurePerNodeDevice)
2724 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nFailure
2727 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2728 "WIFI_MAC_DROP_FAILED_ENQUEUE) during (10, "
2730 if (numFailureDueToFailedEnqueuePerNodeDevice.empty())
2732 std::cout <<
"none\n";
2736 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2737 for (
const auto& [nodeDevTuple, nFailure] :
2738 numFailureDueToFailedEnqueuePerNodeDevice)
2740 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2741 << nFailure << std::endl;
2744 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2745 "WIFI_MAC_DROP_EXPIRED_LIFETIME) during (10, "
2747 if (numFailureDueToExpiredLifetimePerNodeDevice.empty())
2749 std::cout <<
"none\n";
2753 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2754 for (
const auto& [nodeDevTuple, nFailure] :
2755 numFailureDueToExpiredLifetimePerNodeDevice)
2757 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2758 << nFailure << std::endl;
2761 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2762 "WIFI_MAC_DROP_REACHED_RETRY_LIMIT) during (10, "
2764 if (numFailureDueToRetryLimitReachedPerNodeDevice.empty())
2766 std::cout <<
"none\n";
2770 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2771 for (
const auto& [nodeDevTuple, nFailure] :
2772 numFailureDueToRetryLimitReachedPerNodeDevice)
2774 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2775 << nFailure << std::endl;
2778 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2779 "WIFI_MAC_DROP_QOS_OLD_PACKET) during (10, "
2781 if (numFailureDueToQosOldPacketPerNodeDevice.empty())
2783 std::cout <<
"none\n";
2787 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2788 for (
const auto& [nodeDevTuple, nFailure] :
2789 numFailureDueToQosOldPacketPerNodeDevice)
2791 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2792 << nFailure << std::endl;
2796 std::cout <<
"WifiTxStatsHelper: node to number of retransmissions of MPDUs "
2797 "Acked during (10, "
2799 if (numRetransPerNodeDevice.empty())
2801 std::cout <<
"none\n";
2805 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nRetrans" << std::endl;
2806 for (
const auto& [nodeDevTuple, nRetrans] : numRetransPerNodeDevice)
2808 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nRetrans
2817 std::cout <<
"\nWifiPhyRxTraceHelper: overall statistics" << std::endl;
2819 for (
uint32_t nodeIndex = 0; nodeIndex < nNodes; ++nodeIndex)
2821 std::cout <<
"\nWifiPhyRxTraceHelper: per-node statistics for node " << nodeIndex
2825 std::cout << std::endl;
2852 auto it = counter.find(addr);
2853 if (it != counter.end())
2863main(
int argc,
char* argv[])
2869 double duration = 100;
2874 std::string workDir =
"./";
2875 std::string phyMode =
2877 std::string standard(
"11a");
2878 bool validate =
false;
2880 uint16_t plotBianchiModel =
2882 double maxRelativeError =
2885 double frequency = 5;
2886 uint16_t channelWidth = 20;
2887 uint16_t guardIntervalNs = 800;
2889 uint16_t pktInterval =
2893 dBm_u apTxPower{16};
2894 dBm_u staTxPower{16};
2905 "ns3::WifiMacQueue::MaxSize",
2910 cmd.AddValue(
"verbose",
2911 "Logging level (0: no log - 1: simulation script logs - 2: all logs)",
2913 cmd.AddValue(
"tracing",
"Generate trace files",
tracing);
2914 cmd.AddValue(
"useTxHelper",
"Enable WifiTxStatsHelper on all devices",
useTxHelper);
2915 cmd.AddValue(
"useRxHelper",
"Enable WifiPhyRxTraceHelper on all devices",
useRxHelper);
2916 cmd.AddValue(
"pktSize",
"The packet size in bytes",
pktSize);
2917 cmd.AddValue(
"trials",
"The maximal number of runs per network size", trials);
2918 cmd.AddValue(
"duration",
"Time duration for each trial in seconds", duration);
2919 cmd.AddValue(
"pcap",
"Enable/disable PCAP tracing", pcap);
2920 cmd.AddValue(
"infra",
"True to use infrastructure mode, false to use ring adhoc mode", infra);
2921 cmd.AddValue(
"workDir",
"The working directory used to store generated files", workDir);
2922 cmd.AddValue(
"phyMode",
"Set the constant PHY mode string used to transmit frames", phyMode);
2923 cmd.AddValue(
"standard",
"Set the standard (11a, 11b, 11g, 11n, 11ac, 11ax)", standard);
2924 cmd.AddValue(
"nMinStas",
"Minimum number of stations to start with", nMinStas);
2925 cmd.AddValue(
"nMaxStas",
"Maximum number of stations to start with", nMaxStas);
2926 cmd.AddValue(
"nStepSize",
"Number of stations to add at each step", nStepSize);
2927 cmd.AddValue(
"plotBianchiModel",
2928 "First bit corresponds to the DIFS model, second bit to the EIFS model",
2930 cmd.AddValue(
"validate",
2931 "Enable/disable validation of the ns-3 simulations against the Bianchi model",
2933 cmd.AddValue(
"maxRelativeError",
2934 "The maximum relative error tolerated between ns-3 results and the Bianchi model "
2935 "(used for regression, i.e. when the validate flag is set)",
2937 cmd.AddValue(
"frequency",
"Set the operating frequency band in GHz: 2.4, 5 or 6", frequency);
2938 cmd.AddValue(
"channelWidth",
2939 "Set the constant channel width in MHz (only for 11n/ac/ax)",
2941 cmd.AddValue(
"guardIntervalNs",
2942 "Set the the guard interval in nanoseconds (800 or 400 for 11n/ac, 800 or 1600 or "
2945 cmd.AddValue(
"maxMpdus",
2946 "Set the maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation)",
2948 cmd.AddValue(
"distance",
"Set the distance in meters between the AP and the STAs", distance);
2949 cmd.AddValue(
"apTxPower",
2950 "Set the transmit power of the AP in dBm (if infrastructure only)",
2952 cmd.AddValue(
"staTxPower",
2953 "Set the transmit power of each STA in dBm (or all STAs if adhoc)",
2955 cmd.AddValue(
"pktInterval",
"Set the socket packet interval in microseconds", pktInterval);
2956 cmd.Parse(argc, argv);
2968 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-backoff-trace.out");
2973 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-phy-tx-trace.out");
2978 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-mac-tx-trace.out");
2983 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-mac-rx-trace.out");
2988 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-socket-send-trace.out");
3005 std::stringstream phyModeStr;
3006 phyModeStr << phyMode;
3007 if (phyMode.find(
"Mcs") != std::string::npos)
3009 phyModeStr <<
"_" << channelWidth <<
"MHz";
3012 std::stringstream ss;
3013 ss <<
"wifi-" << standard <<
"-p-" <<
pktSize << (infra ?
"-infrastructure" :
"-adhoc") <<
"-r-"
3014 << phyModeStr.str() <<
"-min-" << nMinStas <<
"-max-" << nMaxStas <<
"-step-" << nStepSize
3015 <<
"-throughput.plt";
3016 std::ofstream throughputPlot(ss.str());
3018 ss <<
"wifi-" << standard <<
"-p-" <<
pktSize << (infra ?
"-infrastructure" :
"-adhoc") <<
"-r-"
3019 << phyModeStr.str() <<
"-min-" << nMinStas <<
"-max-" << nMaxStas <<
"-step-" << nStepSize
3020 <<
"-throughput.eps";
3024 if (standard ==
"11a")
3030 else if (standard ==
"11b")
3036 else if (standard ==
"11g")
3042 else if (standard ==
"11n")
3044 if (frequency == 2.4 || frequency == 5)
3050 NS_FATAL_ERROR(
"Unsupported frequency band " << frequency <<
" GHz for standard "
3054 else if (standard ==
"11ac")
3059 else if (standard ==
"11ax")
3061 if (frequency == 2.4 || frequency == 5 || frequency == 6)
3067 NS_FATAL_ERROR(
"Unsupported frequency band " << frequency <<
" GHz for standard "
3076 std::string channelStr =
"{0, " + std::to_string(channelWidth) +
", BAND_" +
3077 (frequency == 2.4 ?
"2_4" : (frequency == 5 ?
"5" :
"6")) +
"GHZ, 0}";
3091 "ReferenceDistance",
3096 else if (frequency == 5)
3102 "ReferenceDistance",
3113 "ReferenceDistance",
3120 wifi.SetStandard(wifiStandard);
3121 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
3137 double averageThroughput;
3138 std::vector<double> throughputArray(trials);
3139 for (
uint32_t n = nMinStas; n <= nMaxStas; n += nStepSize)
3141 averageThroughput = 0;
3143 for (
uint32_t runIndex = 0; runIndex < trials; runIndex++)
3159 std::cout <<
"Trial " << runIndex + 1 <<
" of " << trials <<
"; " << phyModeStr.str()
3160 <<
" for " << n <<
" nodes " << std::endl;
3163 cwTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3164 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3166 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3167 phyTxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3168 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3169 macTxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3170 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3171 macRxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3172 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3174 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3199 Time dataTransferDuration = last -
first;
3200 double nodeThroughput =
3201 (it->second * 8 /
static_cast<double>(dataTransferDuration.
GetMicroSeconds()));
3208 uint64_t nodeRxEventWhileDecodingPreamble =
3213 uint64_t nodeRxEvents = nodePhyHeaderFailures + nodePsduFailures + nodePsduSuccess +
3214 nodeRxEventWhileDecodingPreamble + nodeRxEventWhileRxing +
3215 nodeRxEventWhileTxing + nodeRxEventAbortedByTx;
3216 std::cout <<
"Node " << it->first <<
": TX packets " << nodeTxPackets
3217 <<
"; RX packets " << nodeRxPackets <<
"; PHY header failures "
3218 << nodePhyHeaderFailures <<
"; PSDU failures " << nodePsduFailures
3219 <<
"; PSDU success " << nodePsduSuccess
3220 <<
"; RX events while decoding preamble "
3221 << nodeRxEventWhileDecodingPreamble <<
"; RX events while RXing "
3222 << nodeRxEventWhileRxing <<
"; RX events while TXing "
3223 << nodeRxEventWhileTxing <<
"; RX events aborted by TX "
3224 << nodeRxEventAbortedByTx <<
"; total RX events " << nodeRxEvents
3225 <<
"; total events " << nodeTxPackets + nodeRxEvents <<
"; time first RX "
3226 <<
first <<
"; time last RX " << last <<
"; dataTransferDuration "
3227 << dataTransferDuration <<
"; throughput " << nodeThroughput <<
" Mbps"
3230 std::cout <<
"Total throughput: " <<
throughput <<
" Mbps" << std::endl;
3234 averageThroughput = averageThroughput / trials;
3236 bool rateFound =
false;
3237 double relativeErrorDifs = 0;
3238 double relativeErrorEifs = 0;
3243 auto it = itDifs->second.find(n);
3244 if (it != itDifs->second.end())
3246 relativeErrorDifs = (std::abs(averageThroughput - it->second) / it->second);
3247 std::cout <<
"Relative error (DIFS): " << 100 * relativeErrorDifs <<
"%"
3252 NS_FATAL_ERROR(
"No Bianchi results (DIFS) calculated for that number of stations!");
3259 auto it = itEifs->second.find(n);
3260 if (it != itEifs->second.end())
3262 relativeErrorEifs = (std::abs(averageThroughput - it->second) / it->second);
3263 std::cout <<
"Relative error (EIFS): " << 100 * relativeErrorEifs <<
"%"
3268 NS_FATAL_ERROR(
"No Bianchi results (EIFS) calculated for that number of stations!");
3271 if (!rateFound && validate)
3275 double relativeError = std::min(relativeErrorDifs, relativeErrorEifs);
3276 if (validate && (relativeError > maxRelativeError))
3282 for (
uint32_t i = 0; i < trials; ++i)
3284 stDev += pow(throughputArray[i] - averageThroughput, 2);
3286 stDev = sqrt(stDev / (trials - 1));
3287 dataset.
Add(n, averageThroughput, stDev);
3294 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3297 auto it = itDifs->second.find(i);
3298 if (it != itDifs->second.end())
3302 datasetBianchiDifs.
Add(i, value);
3307 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3309 datasetBianchiDifs.
Add(i, 0.0);
3316 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3319 auto it = itEifs->second.find(i);
3320 if (it != itEifs->second.end())
3324 datasetBianchiEifs.
Add(i, value);
3329 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3331 datasetBianchiEifs.
Add(i, 0.0);
3335 datasetBianchiEifs.
SetTitle(
"Bianchi (EIFS - lower bound)");
3336 datasetBianchiDifs.
SetTitle(
"Bianchi (DIFS - upper bound)");
3338 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
3339 gnuplot.
SetLegend(
"Number of competing stations",
"Throughput (Mbps)");
3341 ss <<
"Frame size " <<
pktSize <<
" bytes";
3344 ss <<
"set xrange [" << nMinStas <<
":" << nMaxStas <<
"]\n"
3345 <<
"set xtics " << nStepSize <<
"\n"
3346 <<
"set grid xtics ytics\n"
3348 <<
"set style line 1 linewidth 5\n"
3349 <<
"set style line 2 linewidth 5\n"
3350 <<
"set style line 3 linewidth 5\n"
3351 <<
"set style line 4 linewidth 5\n"
3352 <<
"set style line 5 linewidth 5\n"
3353 <<
"set style line 6 linewidth 5\n"
3354 <<
"set style line 7 linewidth 5\n"
3355 <<
"set style line 8 linewidth 5\n"
3356 <<
"set style increment user";
3358 if (plotBianchiModel & 0x0001)
3360 datasetBianchiDifs.
SetTitle(
"Bianchi");
3363 if (plotBianchiModel & 0x0002)
3365 datasetBianchiEifs.
SetTitle(
"Bianchi");
3368 if (plotBianchiModel == 0x0003)
3370 datasetBianchiEifs.
SetTitle(
"Bianchi (EIFS - lower bound)");
3371 datasetBianchiDifs.
SetTitle(
"Bianchi (DIFS - upper bound)");
3374 throughputPlot.close();
Gnuplot2dDataset Run(const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel)
Run an experiment.
int Run(const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, uint32_t trialNumber, uint32_t networkSize, Time duration, bool pcap, bool infra, uint16_t guardIntervalNs, meter_u distance, dBm_u apTxPower, dBm_u staTxPower, Time pktInterval)
Configure and run the experiment.
a polymophic address class
holds a vector of ns3::Application pointers.
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 SetErrorBars(ErrorBars errorBars)
void SetStyle(Style style)
void Add(double x, double y)
void SetTitle(const std::string &title)
Change line title.
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 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)
Hold a signed integer type.
static Mac48Address ConvertFrom(const Address &address)
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
uint32_t GetN() const
Get the number of Ptr<Node> stored in this container.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
static Ptr< Node > GetNode(uint32_t n)
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.
Class for representing queue sizes.
AttributeValue implementation for QueueSize.
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.
Hold variables of type string.
Simulation virtual time values and global simulation resolution.
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
int64_t ToInteger(Unit unit) const
Get the Time value expressed in a particular unit.
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
AttributeValue implementation for Time.
Hold an unsigned integer type.
helps to create WifiNetDevice objects
static void EnableLogComponents(LogLevel logLevel=LOG_LEVEL_ALL)
Helper to enable all WifiNetDevice log components with one statement.
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.
represent a single transmission mode
Hold together all Wifi-related objects.
void DisablePreambleDetectionModel()
Disable the preamble detection model on all links.
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
Assists in tracing and analyzing Wi-Fi Physical Layer (PHY) receptions.
void PrintStatistics() const
Print statistics for all nodes, devices, and links during the collection period.
void Stop(Time stopTime)
Stops the collection of statistics at a specified time.
void Enable(NodeContainer nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
void Start(Time startTime)
Starts the collection of statistics from a specified start time.
Statistics helper for tracking outcomes of data MPDU transmissions.
void Stop(Time stopTime)
Set the stop time for statistics collection.
CountPerNodeDevice_t GetFailuresByNodeDevice() const
Return the counts of failed MPDU transmissions in a hash map.
CountPerNodeDevice_t GetSuccessesByNodeDevice() const
Return the counts of successful MPDU transmissions in a hash map.
void Enable(const NodeContainer &nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
CountPerNodeDevice_t GetRetransmissionsByNodeDevice() const
Return the counts of MPDU retransmissions in a hash map.
void Start(Time startTime)
Set the start time for statistics collection.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
bool IsAggregation() const
Checks whether the PSDU contains A-MPDU.
manage and create wifi channel objects for the YANS model.
void SetPropagationDelay(std::string name, Ts &&... args)
void AddPropagationLoss(std::string name, Ts &&... args)
Ptr< YansWifiChannel > Create() const
Make it easy to create and manage PHY objects for the YANS model.
void experiment(std::string queue_disc_type)
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...
void SetDefault(std::string name, const AttributeValue &value)
void Connect(std::string path, const CallbackBase &cb)
void Set(std::string path, const AttributeValue &value)
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#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_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
#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.
@ PACKETS
Use number of packets for queue size.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
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.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
@ PREAMBLE_DETECT_FAILURE
@ FRAME_CAPTURE_PACKET_SWITCH
@ SIGNAL_DETECTION_ABORTED_BY_TX
@ RECEPTION_ABORTED_BY_TX
@ PREAMBLE_DETECTION_PACKET_SWITCH
@ WIFI_MAC_DROP_QOS_OLD_PACKET
@ WIFI_MAC_DROP_FAILED_ENQUEUE
@ WIFI_MAC_DROP_EXPIRED_LIFETIME
@ WIFI_MAC_DROP_REACHED_RETRY_LIMIT
std::ofstream socketSendTraceFile
File that traces packets transmitted by the application over time.
bool tracing
Flag to enable/disable generation of tracing files.
uint8_t maxMpdus
The maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation).
Mac48Address ContextToMac(std::string context)
Parse context strings of the form "/NodeList/x/DeviceList/x/..." and fetch the Mac address.
std::map< Mac48Address, uint64_t > rxEventWhileDecodingPreamble
Map that stores the number of reception events per STA that occurred while PHY was already decoding a...
std::ofstream macTxTraceFile
File that traces MAC transmissions over time.
std::map< Mac48Address, uint64_t > rxEventWhileTxing
Map that stores the number of reception events per STA that occurred while PHY was already transmitti...
std::ofstream cwTraceFile
File that traces CW over time.
std::set< uint32_t > associated
Contains the IDs of the STAs that successfully associated to the access point (in infrastructure mode...
std::map< Mac48Address, uint64_t > packetsTransmitted
Map that stores the total packets transmitted per STA.
void PhyTxDoneTrace(std::string context, Ptr< const Packet > p)
PHY TX end trace.
uint32_t pktSize
packet size used for the simulation (in bytes)
bool useRxHelper
Flag to get PPDU statistics with WifiPhyRxTraceHelper.
std::map< Mac48Address, uint64_t > bytesReceived
Map that stores the total bytes received per STA (and addressed to that STA).
std::map< Mac48Address, uint64_t > packetsReceived
Map that stores the total packets received per STA (and addressed to that STA).
void TracePacketReception(std::string context, Ptr< const Packet > p, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise, uint16_t staId)
Trace a packet reception.
uint32_t ContextToNodeId(std::string context)
Parse context strings of the form "/NodeList/x/DeviceList/x/..." to extract the NodeId integer.
void AssociationLog(std::string context, Mac48Address address)
Association log trace.
void PhyRxTrace(std::string context, Ptr< const Packet > p, RxPowerWattPerChannelBand power)
PHY Rx trace.
void PhyRxErrorTrace(std::string context, Ptr< const Packet > p, double snr)
PHY RX error trace.
void PhyRxOkTrace(std::string context, Ptr< const Packet > p, double snr, WifiMode mode, WifiPreamble preamble)
PHY successful RX trace.
std::map< Mac48Address, uint64_t > phyHeaderFailed
Map that stores the total number of unsuccessfully received PHY headers per STA.
std::map< Mac48Address, Time > timeFirstReceived
Map that stores the time at which the first packet was received per STA (and the packet is addressed ...
std::ofstream backoffTraceFile
File that traces backoff over time.
void DisassociationLog(std::string context, Mac48Address address)
Deassociation log trace.
std::map< Mac48Address, uint64_t > rxEventWhileRxing
Map that stores the number of reception events per STA that occurred while PHY was already receiving ...
void PhyRxDoneTrace(std::string context, Ptr< const Packet > p)
PHY RX end trace.
void PhyTxTrace(std::string context, Ptr< const Packet > p, double txPowerW)
PHY TX trace.
std::map< Mac48Address, uint64_t > psduFailed
Map that stores the total number of unsuccessfully received PSDUS (for which the PHY header was succe...
std::map< Mac48Address, uint64_t > rxEventAbortedByTx
Map that stores the number of reception events aborted per STA because the PHY has started to transmi...
void CwTrace(std::string context, uint32_t cw, uint8_t)
Contention window trace.
std::map< std::string, std::map< unsigned int, double > > bianchiResultsEifs
Table of the expected values for EIFS.
uint64_t GetCount(const std::map< Mac48Address, uint64_t > &counter, Mac48Address addr)
Get the Counter associated with a MAC address.
void IncrementCounter(std::map< Mac48Address, uint64_t > &counter, Mac48Address addr, uint64_t increment=1)
Increment the counter for a given address.
bool useTxHelper
Flag to get MPDU statistics with WifiTxStatsHelper.
std::ofstream phyTxTraceFile
File that traces PHY transmissions over time.
std::map< Mac48Address, Time > timeLastReceived
Map that stores the time at which the last packet was received per STA (and the packet is addressed t...
std::map< std::string, std::map< unsigned int, double > > bianchiResultsDifs
Table of the expected values for DIFS.
void MacTxTrace(std::string context, Ptr< const Packet > p)
MAC TX trace.
void RestartCalc()
Reset the stats.
void SocketSendTrace(std::string context, Ptr< const Packet > p, const Address &addr)
Socket send trace.
std::ofstream macRxTraceFile
File that traces MAC receptions over time.
std::map< Mac48Address, uint64_t > psduSucceeded
Map that stores the total number of successfully received PSDUs per STA (including PSDUs not addresse...
void MacRxTrace(std::string context, Ptr< const Packet > p)
MAC RX trace.
void PhyRxPayloadTrace(std::string context, WifiTxVector txVector, Time psduDuration)
PHY Rx trace.
std::map< Mac48Address, Time > timeLastTransmitted
Map that stores the time at which the last packet was transmitted per STA.
std::map< Mac48Address, Time > timeFirstTransmitted
Map that stores the time at which the first packet was transmitted per STA.
void PhyRxDropTrace(std::string context, Ptr< const Packet > p, WifiPhyRxfailureReason reason)
PHY Drop trace.
void BackoffTrace(std::string context, uint32_t newVal, uint8_t)
Backoff trace.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
double dBm_u
dBm weak type
@ LOG_LEVEL_ALL
Print everything.
@ LOG_LEVEL_WARN
LOG_WARN and above.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
double degree_u
degree weak type (angle)
double meter_u
meter weak type
uint32_t bytesReceived
Counter of the received bytes.
SignalNoiseDbm structure.
#define PI
Avoid std::numbers::pi because it's C++20.