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"
51#define PI 3.1415926535
67std::map<Mac48Address, uint64_t>
69std::map<Mac48Address, uint64_t>
71std::map<Mac48Address, uint64_t>
75std::map<Mac48Address, uint64_t>
80std::map<Mac48Address, uint64_t>
83std::map<Mac48Address, uint64_t>
86std::map<Mac48Address, uint64_t>
89std::map<Mac48Address, uint64_t>
93std::map<Mac48Address, Time>
96std::map<Mac48Address, Time>
114std::map<std::string ,
115 std::map<
unsigned int ,
double >>
302 {
"ErpOfdmRate12Mbps",
315 {
"ErpOfdmRate18Mbps",
328 {
"ErpOfdmRate24Mbps",
341 {
"ErpOfdmRate36Mbps",
354 {
"ErpOfdmRate48Mbps",
367 {
"ErpOfdmRate54Mbps",
1008std::map<std::string ,
1009 std::map<
unsigned int ,
double >>
1170 {
"ErpOfdmRate6Mbps",
1183 {
"ErpOfdmRate9Mbps",
1196 {
"ErpOfdmRate12Mbps",
1209 {
"ErpOfdmRate18Mbps",
1222 {
"ErpOfdmRate24Mbps",
1235 {
"ErpOfdmRate36Mbps",
1248 {
"ErpOfdmRate48Mbps",
1261 {
"ErpOfdmRate54Mbps",
1910 std::string sub = context.substr(10);
1911 uint32_t pos = sub.find(
"/Device");
1912 return std::stoi(sub.substr(0, pos));
1924 std::string sub = context.substr(10);
1925 uint32_t pos = sub.find(
"/Device");
1926 uint32_t nodeId = std::stoi(sub.substr(0, pos));
1929 for (
uint32_t i = 0; i < n->GetNDevices(); i++)
1952 uint64_t increment = 1)
1954 auto it = counter.find(addr);
1955 if (it != counter.end())
1957 it->second += increment;
1961 counter.insert(std::make_pair(addr, increment));
1979 uint16_t channelFreqMhz,
1990 packet->RemoveHeader(subHdr);
1992 packet = packet->CreateFragment(0,
static_cast<uint32_t>(extractedLength));
1995 packet->PeekHeader(hdr);
2002 if (packet->GetSize() >=
pktSize)
2051 <<
" val=" << newVal);
2055 << newVal << std::endl;
2070 <<
" size=" << p->GetSize());
2085 <<
" psduDuration=" << psduDuration);
2099 <<
" size=" << p->GetSize() <<
" reason=" << reason);
2155 NS_FATAL_ERROR(
"All devices should send with same power, so no packet switch during "
2156 "preamble detection should occur!");
2183 <<
" size=" << p->GetSize());
2202 uint8_t nMpdus = (p->GetSize() /
pktSize);
2205 <<
" nMPDUs=" << +nMpdus <<
" snr=" << snr <<
" mode=" << mode
2206 <<
" preamble=" << preamble);
2211 NS_FATAL_ERROR(
"A-MPDU settings not properly applied: maximum configured MPDUs is "
2212 << +
maxMpdus <<
" but received an A-MPDU containing " << +nMpdus
2215 NS_LOG_WARN(
"Warning: less MPDUs aggregated in a received A-MPDU ("
2216 << +nMpdus <<
") than configured (" << +
maxMpdus <<
")");
2236 <<
" size=" << p->GetSize() <<
" snr=" << snr);
2255 <<
" size=" << p->GetSize() <<
" " << txPowerW);
2259 <<
" size=" << p->GetSize() <<
" " << txPowerW << std::endl;
2278 <<
" " << p->GetSize());
2293 << p->GetSize() << std::endl;
2309 << p->GetSize() << std::endl;
2326 <<
" " << p->GetSize() <<
" " << addr << std::endl;
2422 uint16_t guardIntervalNs,
2443 uint16_t guardIntervalNs,
2455 wifiNodes.
Create(networkSize + 1);
2459 wifiNodes.
Create(networkSize);
2463 phy.SetErrorRateModel(
"ns3::NistErrorRateModel");
2464 phy.SetChannel(wifiChannel.
Create());
2468 const auto& wifi = helper;
2474 uint64_t beaconInterval = std::min<uint64_t>(
2475 (ceil((duration.
GetSeconds() * 1000000) / 1024) * 1024),
2477 mac.SetType(
"ns3::ApWifiMac",
2484 devices = wifi.Install(phy, mac, wifiNodes.
Get(0));
2486 mac.SetType(
"ns3::StaWifiMac",
2493 for (
uint32_t i = 1; i < nNodes; ++i)
2495 devices.Add(wifi.Install(phy, mac, wifiNodes.
Get(i)));
2500 mac.SetType(
"ns3::AdhocWifiMac");
2503 devices = wifi.Install(phy, mac, wifiNodes);
2509 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/ShortGuardIntervalSupported",
2511 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HeConfiguration/GuardInterval",
2515 for (
uint32_t i = 0; i < nNodes; ++i)
2519 wifi_dev->GetMac()->SetAttribute(
"BE_MaxAmpduSize",
2521 wifi_dev->GetMac()->SetAttribute(
"BK_MaxAmpduSize",
2523 wifi_dev->GetMac()->SetAttribute(
"VO_MaxAmpduSize",
2525 wifi_dev->GetMac()->SetAttribute(
"VI_MaxAmpduSize",
2531 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
2533 positionAlloc->Add(Vector(1.0, 1.0, 0.0));
2536 const auto angle = (
static_cast<degree_u>(360) / (nNodes - 1));
2537 for (
uint32_t i = 0; i < (nNodes - 1); ++i)
2539 positionAlloc->Add(Vector(1.0 + (distance * cos((i * angle *
PI) / 180)),
2540 1.0 + (distance * sin((i * angle *
PI) / 180)),
2544 mobility.SetPositionAllocator(positionAlloc);
2545 mobility.Install(wifiNodes);
2548 packetSocket.
Install(wifiNodes);
2552 startTime->SetAttribute(
"Stream",
IntegerValue(trialNumber));
2556 for (; i < nNodes; ++i)
2558 uint32_t j = infra ? 0 : (i + 1) % nNodes;
2565 client->SetRemote(socketAddr);
2569 client->SetAttribute(
"Interval",
TimeValue(pktInterval));
2570 double start = startTime->GetValue();
2571 NS_LOG_DEBUG(
"Client " << i <<
" starting at " << start);
2572 client->SetStartTime(
Seconds(start));
2575 server->SetLocal(socketAddr);
2581 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/MonitorSnifferRx",
2587 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/Assoc",
2589 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/DeAssoc",
2598 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::WifiMac/" + txop +
2602 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::WifiMac/" + txop +
2606 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxBegin",
2609 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxEnd",
2612 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxBegin",
2616 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxPayloadBegin",
2619 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxDrop",
2622 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxEnd",
2625 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxError",
2628 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxOk",
2631 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx",
2634 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx",
2637 Config::Connect(
"/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::PacketSocketClient/Tx",
2644 wifiTxStats.
Enable(devices);
2653 rxTraceHelper.
Enable(devices);
2663 phy.EnablePcap(
"wifi_bianchi_pcap", devices);
2674 const auto numFailureDueToFailedEnqueuePerNodeDevice =
2676 const auto numFailureDueToExpiredLifetimePerNodeDevice =
2678 const auto numFailureDueToRetryLimitReachedPerNodeDevice =
2680 const auto numFailureDueToQosOldPacketPerNodeDevice =
2683 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs acked during (10, "
2685 if (numSuccessPerNodeDevice.empty())
2687 std::cout <<
"none\n";
2691 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nSuccess" << std::endl;
2692 for (
const auto& [nodeDevTuple, nSuccess] : numSuccessPerNodeDevice)
2694 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nSuccess
2699 <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to any reason) during (10, "
2701 if (numFailurePerNodeDevice.empty())
2703 std::cout <<
"none\n";
2707 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2708 for (
const auto& [nodeDevTuple, nFailure] : numFailurePerNodeDevice)
2710 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nFailure
2713 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2714 "WIFI_MAC_DROP_FAILED_ENQUEUE) during (10, "
2716 if (numFailureDueToFailedEnqueuePerNodeDevice.empty())
2718 std::cout <<
"none\n";
2722 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2723 for (
const auto& [nodeDevTuple, nFailure] :
2724 numFailureDueToFailedEnqueuePerNodeDevice)
2726 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2727 << nFailure << std::endl;
2730 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2731 "WIFI_MAC_DROP_EXPIRED_LIFETIME) during (10, "
2733 if (numFailureDueToExpiredLifetimePerNodeDevice.empty())
2735 std::cout <<
"none\n";
2739 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2740 for (
const auto& [nodeDevTuple, nFailure] :
2741 numFailureDueToExpiredLifetimePerNodeDevice)
2743 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2744 << nFailure << std::endl;
2747 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2748 "WIFI_MAC_DROP_REACHED_RETRY_LIMIT) during (10, "
2750 if (numFailureDueToRetryLimitReachedPerNodeDevice.empty())
2752 std::cout <<
"none\n";
2756 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2757 for (
const auto& [nodeDevTuple, nFailure] :
2758 numFailureDueToRetryLimitReachedPerNodeDevice)
2760 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2761 << nFailure << std::endl;
2764 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2765 "WIFI_MAC_DROP_QOS_OLD_PACKET) during (10, "
2767 if (numFailureDueToQosOldPacketPerNodeDevice.empty())
2769 std::cout <<
"none\n";
2773 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2774 for (
const auto& [nodeDevTuple, nFailure] :
2775 numFailureDueToQosOldPacketPerNodeDevice)
2777 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2778 << nFailure << std::endl;
2782 std::cout <<
"WifiTxStatsHelper: node to number of retransmissions of MPDUs "
2783 "Acked during (10, "
2785 if (numRetransPerNodeDevice.empty())
2787 std::cout <<
"none\n";
2791 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nRetrans" << std::endl;
2792 for (
const auto& [nodeDevTuple, nRetrans] : numRetransPerNodeDevice)
2794 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nRetrans
2803 std::cout <<
"\nWifiPhyRxTraceHelper: overall statistics" << std::endl;
2805 for (
uint32_t nodeIndex = 0; nodeIndex < nNodes; ++nodeIndex)
2807 std::cout <<
"\nWifiPhyRxTraceHelper: per-node statistics for node " << nodeIndex
2811 std::cout << std::endl;
2838 auto it = counter.find(addr);
2839 if (it != counter.end())
2847main(
int argc,
char* argv[])
2853 double duration = 100;
2858 std::string workDir =
"./";
2859 std::string phyMode =
2861 std::string standard(
"11a");
2862 bool validate =
false;
2864 uint16_t plotBianchiModel =
2866 double maxRelativeError =
2869 double frequency = 5;
2870 uint16_t channelWidth = 20;
2871 uint16_t guardIntervalNs = 800;
2873 uint16_t pktInterval =
2877 dBm_u apTxPower{16};
2878 dBm_u staTxPower{16};
2889 "ns3::WifiMacQueue::MaxSize",
2894 cmd.AddValue(
"verbose",
2895 "Logging level (0: no log - 1: simulation script logs - 2: all logs)",
2897 cmd.AddValue(
"tracing",
"Generate trace files",
tracing);
2898 cmd.AddValue(
"useTxHelper",
"Enable WifiTxStatsHelper on all devices",
useTxHelper);
2899 cmd.AddValue(
"useRxHelper",
"Enable WifiPhyRxTraceHelper on all devices",
useRxHelper);
2900 cmd.AddValue(
"pktSize",
"The packet size in bytes",
pktSize);
2901 cmd.AddValue(
"trials",
"The maximal number of runs per network size", trials);
2902 cmd.AddValue(
"duration",
"Time duration for each trial in seconds", duration);
2903 cmd.AddValue(
"pcap",
"Enable/disable PCAP tracing", pcap);
2904 cmd.AddValue(
"infra",
"True to use infrastructure mode, false to use ring adhoc mode", infra);
2905 cmd.AddValue(
"workDir",
"The working directory used to store generated files", workDir);
2906 cmd.AddValue(
"phyMode",
"Set the constant PHY mode string used to transmit frames", phyMode);
2907 cmd.AddValue(
"standard",
"Set the standard (11a, 11b, 11g, 11n, 11ac, 11ax)", standard);
2908 cmd.AddValue(
"nMinStas",
"Minimum number of stations to start with", nMinStas);
2909 cmd.AddValue(
"nMaxStas",
"Maximum number of stations to start with", nMaxStas);
2910 cmd.AddValue(
"nStepSize",
"Number of stations to add at each step", nStepSize);
2911 cmd.AddValue(
"plotBianchiModel",
2912 "First bit corresponds to the DIFS model, second bit to the EIFS model",
2914 cmd.AddValue(
"validate",
2915 "Enable/disable validation of the ns-3 simulations against the Bianchi model",
2917 cmd.AddValue(
"maxRelativeError",
2918 "The maximum relative error tolerated between ns-3 results and the Bianchi model "
2919 "(used for regression, i.e. when the validate flag is set)",
2921 cmd.AddValue(
"frequency",
"Set the operating frequency band in GHz: 2.4, 5 or 6", frequency);
2922 cmd.AddValue(
"channelWidth",
2923 "Set the constant channel width in MHz (only for 11n/ac/ax)",
2925 cmd.AddValue(
"guardIntervalNs",
2926 "Set the the guard interval in nanoseconds (800 or 400 for 11n/ac, 800 or 1600 or "
2929 cmd.AddValue(
"maxMpdus",
2930 "Set the maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation)",
2932 cmd.AddValue(
"distance",
"Set the distance in meters between the AP and the STAs", distance);
2933 cmd.AddValue(
"apTxPower",
2934 "Set the transmit power of the AP in dBm (if infrastructure only)",
2936 cmd.AddValue(
"staTxPower",
2937 "Set the transmit power of each STA in dBm (or all STAs if adhoc)",
2939 cmd.AddValue(
"pktInterval",
"Set the socket packet interval in microseconds", pktInterval);
2940 cmd.Parse(argc, argv);
2952 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-backoff-trace.out");
2957 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-phy-tx-trace.out");
2962 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-mac-tx-trace.out");
2967 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-mac-rx-trace.out");
2972 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-socket-send-trace.out");
2989 std::stringstream phyModeStr;
2990 phyModeStr << phyMode;
2991 if (phyMode.find(
"Mcs") != std::string::npos)
2993 phyModeStr <<
"_" << channelWidth <<
"MHz";
2996 std::stringstream ss;
2997 ss <<
"wifi-" << standard <<
"-p-" <<
pktSize << (infra ?
"-infrastructure" :
"-adhoc") <<
"-r-"
2998 << phyModeStr.str() <<
"-min-" << nMinStas <<
"-max-" << nMaxStas <<
"-step-" << nStepSize
2999 <<
"-throughput.plt";
3000 std::ofstream throughputPlot(ss.str());
3002 ss <<
"wifi-" << standard <<
"-p-" <<
pktSize << (infra ?
"-infrastructure" :
"-adhoc") <<
"-r-"
3003 << phyModeStr.str() <<
"-min-" << nMinStas <<
"-max-" << nMaxStas <<
"-step-" << nStepSize
3004 <<
"-throughput.eps";
3008 if (standard ==
"11a")
3014 else if (standard ==
"11b")
3020 else if (standard ==
"11g")
3026 else if (standard ==
"11n")
3028 if (frequency == 2.4 || frequency == 5)
3034 NS_FATAL_ERROR(
"Unsupported frequency band " << frequency <<
" GHz for standard "
3038 else if (standard ==
"11ac")
3043 else if (standard ==
"11ax")
3045 if (frequency == 2.4 || frequency == 5 || frequency == 6)
3051 NS_FATAL_ERROR(
"Unsupported frequency band " << frequency <<
" GHz for standard "
3060 std::string channelStr =
"{0, " + std::to_string(channelWidth) +
", BAND_" +
3061 (frequency == 2.4 ?
"2_4" : (frequency == 5 ?
"5" :
"6")) +
"GHZ, 0}";
3075 "ReferenceDistance",
3080 else if (frequency == 5)
3086 "ReferenceDistance",
3097 "ReferenceDistance",
3104 wifi.SetStandard(wifiStandard);
3105 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
3121 double averageThroughput;
3122 std::vector<double> throughputArray(trials);
3123 for (
uint32_t n = nMinStas; n <= nMaxStas; n += nStepSize)
3125 averageThroughput = 0;
3127 for (
uint32_t runIndex = 0; runIndex < trials; runIndex++)
3143 std::cout <<
"Trial " << runIndex + 1 <<
" of " << trials <<
"; " << phyModeStr.str()
3144 <<
" for " << n <<
" nodes " << std::endl;
3147 cwTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3148 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3150 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3151 phyTxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3152 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3153 macTxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3154 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3155 macRxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3156 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3158 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3183 Time dataTransferDuration = last -
first;
3184 double nodeThroughput =
3185 (it->second * 8 /
static_cast<double>(dataTransferDuration.
GetMicroSeconds()));
3192 uint64_t nodeRxEventWhileDecodingPreamble =
3197 uint64_t nodeRxEvents = nodePhyHeaderFailures + nodePsduFailures + nodePsduSuccess +
3198 nodeRxEventWhileDecodingPreamble + nodeRxEventWhileRxing +
3199 nodeRxEventWhileTxing + nodeRxEventAbortedByTx;
3200 std::cout <<
"Node " << it->first <<
": TX packets " << nodeTxPackets
3201 <<
"; RX packets " << nodeRxPackets <<
"; PHY header failures "
3202 << nodePhyHeaderFailures <<
"; PSDU failures " << nodePsduFailures
3203 <<
"; PSDU success " << nodePsduSuccess
3204 <<
"; RX events while decoding preamble "
3205 << nodeRxEventWhileDecodingPreamble <<
"; RX events while RXing "
3206 << nodeRxEventWhileRxing <<
"; RX events while TXing "
3207 << nodeRxEventWhileTxing <<
"; RX events aborted by TX "
3208 << nodeRxEventAbortedByTx <<
"; total RX events " << nodeRxEvents
3209 <<
"; total events " << nodeTxPackets + nodeRxEvents <<
"; time first RX "
3210 <<
first <<
"; time last RX " << last <<
"; dataTransferDuration "
3211 << dataTransferDuration <<
"; throughput " << nodeThroughput <<
" Mbps"
3214 std::cout <<
"Total throughput: " <<
throughput <<
" Mbps" << std::endl;
3218 averageThroughput = averageThroughput / trials;
3220 bool rateFound =
false;
3221 double relativeErrorDifs = 0;
3222 double relativeErrorEifs = 0;
3227 auto it = itDifs->second.find(n);
3228 if (it != itDifs->second.end())
3230 relativeErrorDifs = (std::abs(averageThroughput - it->second) / it->second);
3231 std::cout <<
"Relative error (DIFS): " << 100 * relativeErrorDifs <<
"%"
3236 NS_FATAL_ERROR(
"No Bianchi results (DIFS) calculated for that number of stations!");
3243 auto it = itEifs->second.find(n);
3244 if (it != itEifs->second.end())
3246 relativeErrorEifs = (std::abs(averageThroughput - it->second) / it->second);
3247 std::cout <<
"Relative error (EIFS): " << 100 * relativeErrorEifs <<
"%"
3252 NS_FATAL_ERROR(
"No Bianchi results (EIFS) calculated for that number of stations!");
3255 if (!rateFound && validate)
3259 double relativeError = std::min(relativeErrorDifs, relativeErrorEifs);
3260 if (validate && (relativeError > maxRelativeError))
3266 for (
uint32_t i = 0; i < trials; ++i)
3268 stDev += pow(throughputArray[i] - averageThroughput, 2);
3270 stDev = sqrt(stDev / (trials - 1));
3271 dataset.
Add(n, averageThroughput, stDev);
3278 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3281 auto it = itDifs->second.find(i);
3282 if (it != itDifs->second.end())
3286 datasetBianchiDifs.
Add(i, value);
3291 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3293 datasetBianchiDifs.
Add(i, 0.0);
3300 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3303 auto it = itEifs->second.find(i);
3304 if (it != itEifs->second.end())
3308 datasetBianchiEifs.
Add(i, value);
3313 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3315 datasetBianchiEifs.
Add(i, 0.0);
3319 datasetBianchiEifs.
SetTitle(
"Bianchi (EIFS - lower bound)");
3320 datasetBianchiDifs.
SetTitle(
"Bianchi (DIFS - upper bound)");
3322 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
3323 gnuplot.
SetLegend(
"Number of competing stations",
"Throughput (Mbps)");
3325 ss <<
"Frame size " <<
pktSize <<
" bytes";
3328 ss <<
"set xrange [" << nMinStas <<
":" << nMaxStas <<
"]\n"
3329 <<
"set xtics " << nStepSize <<
"\n"
3330 <<
"set grid xtics ytics\n"
3332 <<
"set style line 1 linewidth 5\n"
3333 <<
"set style line 2 linewidth 5\n"
3334 <<
"set style line 3 linewidth 5\n"
3335 <<
"set style line 4 linewidth 5\n"
3336 <<
"set style line 5 linewidth 5\n"
3337 <<
"set style line 6 linewidth 5\n"
3338 <<
"set style line 7 linewidth 5\n"
3339 <<
"set style line 8 linewidth 5\n"
3340 <<
"set style increment user";
3342 if (plotBianchiModel & 0x0001)
3344 datasetBianchiDifs.
SetTitle(
"Bianchi");
3347 if (plotBianchiModel & 0x0002)
3349 datasetBianchiEifs.
SetTitle(
"Bianchi");
3352 if (plotBianchiModel == 0x0003)
3354 datasetBianchiEifs.
SetTitle(
"Bianchi (EIFS - lower bound)");
3355 datasetBianchiDifs.
SetTitle(
"Bianchi (DIFS - upper bound)");
3358 throughputPlot.close();
WiFi adhoc experiment class.
Gnuplot2dDataset Run(const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy, const WifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel)
Run an 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)
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.
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
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.
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...
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
std::map< WifiSpectrumBandInfo, Watt_u > RxPowerWattPerChannelBand
A map of the received power for each band.
@ LOG_LEVEL_ALL
Print everything.
@ LOG_LEVEL_WARN
LOG_WARN and above.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
SignalNoiseDbm structure.
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 BackoffTrace(std::string context, uint32_t newVal, uint8_t)
Backoff trace.
std::map< Mac48Address, uint64_t > rxEventWhileTxing
Map that stores the number of reception events per STA that occurred while PHY was already transmitti...
void PhyRxErrorTrace(std::string context, Ptr< const Packet > p, double snr)
PHY RX error trace.
std::map< Mac48Address, uint64_t > packetsReceived
Map that stores the total packets received per STA (and addressed to that STA)
std::ofstream backoffTraceFile
File that traces backoff over time.
void RestartCalc()
Reset the stats.
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 > rxEventWhileDecodingPreamble
Map that stores the number of reception events per STA that occurred while PHY was already decoding a...
void AssociationLog(std::string context, Mac48Address address)
Association log trace.
void SocketSendTrace(std::string context, Ptr< const Packet > p, const Address &addr)
Socket send trace.
bool tracing
Flag to enable/disable generation of tracing files.
void CwTrace(std::string context, uint32_t cw, uint8_t)
Contention window trace.
uint32_t ContextToNodeId(std::string context)
Parse context strings of the form "/NodeList/x/DeviceList/x/..." to extract the NodeId integer.
std::map< Mac48Address, uint64_t > rxEventWhileRxing
Map that stores the number of reception events per STA that occurred while PHY was already receiving ...
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.
void PhyRxDropTrace(std::string context, Ptr< const Packet > p, WifiPhyRxfailureReason reason)
PHY Drop 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 unsuccessfuly received PSDUS (for which the PHY header was succes...
#define PI
Avoid std::numbers::pi because it's C++20.
std::map< Mac48Address, uint64_t > packetsTransmitted
Map that stores the total packets transmitted per STA.
std::map< std::string, std::map< unsigned int, double > > bianchiResultsDifs
Table of the expected values for DIFS.
bool useRxHelper
Flag to get PPDU statistics with WifiPhyRxTraceHelper.
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< Mac48Address, Time > timeFirstTransmitted
Map that stores the time at which the first packet was transmitted per STA.
uint8_t maxMpdus
The maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation)
void PhyRxDoneTrace(std::string context, Ptr< const Packet > p)
PHY RX end trace.
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 > phyHeaderFailed
Map that stores the total number of unsuccessfuly received PHY headers per STA.
void MacTxTrace(std::string context, Ptr< const Packet > p)
MAC TX trace.
std::ofstream socketSendTraceFile
File that traces packets transmitted by the application over time.
uint64_t GetCount(const std::map< Mac48Address, uint64_t > &counter, Mac48Address addr)
Get the Counter associated with a MAC address.
std::ofstream macTxTraceFile
File that traces MAC transmissions over time.
void PhyRxTrace(std::string context, Ptr< const Packet > p, RxPowerWattPerChannelBand power)
PHY Rx trace.
std::ofstream phyTxTraceFile
File that traces PHY transmissions over time.
void IncrementCounter(std::map< Mac48Address, uint64_t > &counter, Mac48Address addr, uint64_t increment=1)
Increment the counter for a given address.
std::map< Mac48Address, Time > timeFirstReceived
Map that stores the time at which the first packet was received per STA (and the packet is addressed ...
uint32_t pktSize
packet size used for the simulation (in bytes)
std::map< Mac48Address, uint64_t > psduSucceeded
Map that stores the total number of successfully received PSDUs per STA (including PSDUs not addresse...
std::map< Mac48Address, Time > timeLastTransmitted
Map that stores the time at which the last packet was transmitted per STA.
std::map< std::string, std::map< unsigned int, double > > bianchiResultsEifs
Table of the expected values for EIFS.
void MacRxTrace(std::string context, Ptr< const Packet > p)
MAC RX trace.
void PhyTxDoneTrace(std::string context, Ptr< const Packet > p)
PHY TX end trace.
void PhyRxPayloadTrace(std::string context, WifiTxVector txVector, Time psduDuration)
PHY Rx trace.
Mac48Address ContextToMac(std::string context)
Parse context strings of the form "/NodeList/x/DeviceList/x/..." and fetch the Mac address.
void PhyRxOkTrace(std::string context, Ptr< const Packet > p, double snr, WifiMode mode, WifiPreamble preamble)
PHY successful RX trace.
bool useTxHelper
Flag to get MPDU statistics with WifiTxStatsHelper.
void DisassociationLog(std::string context, Mac48Address address)
Deassociation log trace.
std::ofstream cwTraceFile
File that traces CW over time.
std::ofstream macRxTraceFile
File that traces MAC receptions over time.