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"
76std::map<Mac48Address, uint64_t>
78std::map<Mac48Address, uint64_t>
80std::map<Mac48Address, uint64_t>
84std::map<Mac48Address, uint64_t>
89std::map<Mac48Address, uint64_t>
92std::map<Mac48Address, uint64_t>
95std::map<Mac48Address, uint64_t>
98std::map<Mac48Address, uint64_t>
102std::map<Mac48Address, Time>
105std::map<Mac48Address, Time>
123std::map<std::string ,
124 std::map<
unsigned int ,
double >>
311 {
"ErpOfdmRate12Mbps",
324 {
"ErpOfdmRate18Mbps",
337 {
"ErpOfdmRate24Mbps",
350 {
"ErpOfdmRate36Mbps",
363 {
"ErpOfdmRate48Mbps",
376 {
"ErpOfdmRate54Mbps",
1017std::map<std::string ,
1018 std::map<
unsigned int ,
double >>
1179 {
"ErpOfdmRate6Mbps",
1192 {
"ErpOfdmRate9Mbps",
1205 {
"ErpOfdmRate12Mbps",
1218 {
"ErpOfdmRate18Mbps",
1231 {
"ErpOfdmRate24Mbps",
1244 {
"ErpOfdmRate36Mbps",
1257 {
"ErpOfdmRate48Mbps",
1270 {
"ErpOfdmRate54Mbps",
1919 std::string sub = context.substr(10);
1920 uint32_t pos = sub.find(
"/Device");
1921 return std::stoi(sub.substr(0, pos));
1933 std::string sub = context.substr(10);
1934 uint32_t pos = sub.find(
"/Device");
1935 uint32_t nodeId = std::stoi(sub.substr(0, pos));
1938 for (
uint32_t i = 0; i < n->GetNDevices(); i++)
1961 uint64_t increment = 1)
1963 auto it = counter.find(addr);
1964 if (it != counter.end())
1966 it->second += increment;
1970 counter.insert(std::make_pair(addr, increment));
1988 uint16_t channelFreqMhz,
1999 packet->RemoveHeader(subHdr);
2001 packet = packet->CreateFragment(0,
static_cast<uint32_t>(extractedLength));
2004 packet->PeekHeader(hdr);
2011 if (packet->GetSize() >=
pktSize)
2060 <<
" val=" << newVal);
2064 << newVal << std::endl;
2079 <<
" size=" << p->GetSize());
2094 <<
" psduDuration=" << psduDuration);
2108 <<
" size=" << p->GetSize() <<
" reason=" << reason);
2164 NS_FATAL_ERROR(
"All devices should send with same power, so no packet switch during "
2165 "preamble detection should occur!");
2192 <<
" size=" << p->GetSize());
2211 uint8_t nMpdus = (p->GetSize() /
pktSize);
2214 <<
" nMPDUs=" << +nMpdus <<
" snr=" << snr <<
" mode=" << mode
2215 <<
" preamble=" << preamble);
2220 NS_FATAL_ERROR(
"A-MPDU settings not properly applied: maximum configured MPDUs is "
2221 << +
maxMpdus <<
" but received an A-MPDU containing " << +nMpdus
2224 NS_LOG_WARN(
"Warning: less MPDUs aggregated in a received A-MPDU ("
2225 << +nMpdus <<
") than configured (" << +
maxMpdus <<
")");
2245 <<
" size=" << p->GetSize() <<
" snr=" << snr);
2264 <<
" size=" << p->GetSize() <<
" " << txPowerW);
2268 <<
" size=" << p->GetSize() <<
" " << txPowerW << std::endl;
2287 <<
" " << p->GetSize());
2302 << p->GetSize() << std::endl;
2318 << p->GetSize() << std::endl;
2335 <<
" " << p->GetSize() <<
" " << addr << std::endl;
2434 uint16_t guardIntervalNs,
2455 uint16_t guardIntervalNs,
2467 wifiNodes.
Create(networkSize + 1);
2471 wifiNodes.
Create(networkSize);
2475 phy.SetErrorRateModel(
"ns3::NistErrorRateModel");
2476 phy.SetChannel(wifiChannel.
Create());
2480 const auto& wifi = helper;
2486 uint64_t beaconInterval = std::min<uint64_t>(
2487 (ceil((duration.
GetSeconds() * 1000000) / 1024) * 1024),
2489 mac.SetType(
"ns3::ApWifiMac",
2496 devices = wifi.Install(phy, mac, wifiNodes.
Get(0));
2498 mac.SetType(
"ns3::StaWifiMac",
2505 for (
uint32_t i = 1; i < nNodes; ++i)
2507 devices.Add(wifi.Install(phy, mac, wifiNodes.
Get(i)));
2512 mac.SetType(
"ns3::AdhocWifiMac");
2515 devices = wifi.Install(phy, mac, wifiNodes);
2521 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/ShortGuardIntervalSupported",
2523 Config::Set(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HeConfiguration/GuardInterval",
2527 for (
uint32_t i = 0; i < nNodes; ++i)
2531 wifi_dev->GetMac()->SetAttribute(
"BE_MaxAmpduSize",
2533 wifi_dev->GetMac()->SetAttribute(
"BK_MaxAmpduSize",
2535 wifi_dev->GetMac()->SetAttribute(
"VO_MaxAmpduSize",
2537 wifi_dev->GetMac()->SetAttribute(
"VI_MaxAmpduSize",
2543 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
2545 positionAlloc->Add(Vector(1.0, 1.0, 0.0));
2548 const auto angle = (
static_cast<degree_u>(360) / (nNodes - 1));
2549 for (
uint32_t i = 0; i < (nNodes - 1); ++i)
2551 positionAlloc->Add(Vector(1.0 + (distance * cos((i * angle * std::numbers::pi) / 180)),
2552 1.0 + (distance * sin((i * angle * std::numbers::pi) / 180)),
2556 mobility.SetPositionAllocator(positionAlloc);
2557 mobility.Install(wifiNodes);
2560 packetSocket.
Install(wifiNodes);
2564 startTime->SetAttribute(
"Stream",
IntegerValue(trialNumber));
2568 for (; i < nNodes; ++i)
2570 uint32_t j = infra ? 0 : (i + 1) % nNodes;
2577 client->SetRemote(socketAddr);
2581 client->SetAttribute(
"Interval",
TimeValue(pktInterval));
2582 double start = startTime->GetValue();
2583 NS_LOG_DEBUG(
"Client " << i <<
" starting at " << start);
2584 client->SetStartTime(
Seconds(start));
2587 server->SetLocal(socketAddr);
2593 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/MonitorSnifferRx",
2599 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/Assoc",
2601 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::StaWifiMac/DeAssoc",
2610 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::WifiMac/" + txop +
2614 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/$ns3::WifiMac/" + txop +
2618 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxBegin",
2621 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyTxEnd",
2624 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxBegin",
2628 "/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxPayloadBegin",
2631 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxDrop",
2634 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/PhyRxEnd",
2637 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxError",
2640 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/State/RxOk",
2643 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacTx",
2646 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/MacRx",
2649 Config::Connect(
"/NodeList/*/$ns3::Node/ApplicationList/*/$ns3::PacketSocketClient/Tx",
2656 wifiTxStats.
Enable(devices);
2665 rxTraceHelper.
Enable(devices);
2675 phy.EnablePcap(
"wifi_bianchi_pcap", devices);
2686 const auto numFailureDueToFailedEnqueuePerNodeDevice =
2688 const auto numFailureDueToExpiredLifetimePerNodeDevice =
2690 const auto numFailureDueToRetryLimitReachedPerNodeDevice =
2692 const auto numFailureDueToQosOldPacketPerNodeDevice =
2695 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs acked during (10, "
2697 if (numSuccessPerNodeDevice.empty())
2699 std::cout <<
"none\n";
2703 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nSuccess" << std::endl;
2704 for (
const auto& [nodeDevTuple, nSuccess] : numSuccessPerNodeDevice)
2706 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nSuccess
2711 <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to any reason) during (10, "
2713 if (numFailurePerNodeDevice.empty())
2715 std::cout <<
"none\n";
2719 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2720 for (
const auto& [nodeDevTuple, nFailure] : numFailurePerNodeDevice)
2722 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nFailure
2725 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2726 "WIFI_MAC_DROP_FAILED_ENQUEUE) during (10, "
2728 if (numFailureDueToFailedEnqueuePerNodeDevice.empty())
2730 std::cout <<
"none\n";
2734 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2735 for (
const auto& [nodeDevTuple, nFailure] :
2736 numFailureDueToFailedEnqueuePerNodeDevice)
2738 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2739 << nFailure << std::endl;
2742 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2743 "WIFI_MAC_DROP_EXPIRED_LIFETIME) during (10, "
2745 if (numFailureDueToExpiredLifetimePerNodeDevice.empty())
2747 std::cout <<
"none\n";
2751 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2752 for (
const auto& [nodeDevTuple, nFailure] :
2753 numFailureDueToExpiredLifetimePerNodeDevice)
2755 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2756 << nFailure << std::endl;
2759 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2760 "WIFI_MAC_DROP_REACHED_RETRY_LIMIT) during (10, "
2762 if (numFailureDueToRetryLimitReachedPerNodeDevice.empty())
2764 std::cout <<
"none\n";
2768 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2769 for (
const auto& [nodeDevTuple, nFailure] :
2770 numFailureDueToRetryLimitReachedPerNodeDevice)
2772 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2773 << nFailure << std::endl;
2776 std::cout <<
"WifiTxStatsHelper: node to number of MPDUs failed (due to "
2777 "WIFI_MAC_DROP_QOS_OLD_PACKET) during (10, "
2779 if (numFailureDueToQosOldPacketPerNodeDevice.empty())
2781 std::cout <<
"none\n";
2785 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nFailed" << std::endl;
2786 for (
const auto& [nodeDevTuple, nFailure] :
2787 numFailureDueToQosOldPacketPerNodeDevice)
2789 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10)
2790 << nFailure << std::endl;
2794 std::cout <<
"WifiTxStatsHelper: node to number of retransmissions of MPDUs "
2795 "Acked during (10, "
2797 if (numRetransPerNodeDevice.empty())
2799 std::cout <<
"none\n";
2803 std::cout << std::setw(5) <<
"node" << std::setw(10) <<
"nRetrans" << std::endl;
2804 for (
const auto& [nodeDevTuple, nRetrans] : numRetransPerNodeDevice)
2806 std::cout << std::setw(5) << std::get<0>(nodeDevTuple) << std::setw(10) << nRetrans
2815 std::cout <<
"\nWifiPhyRxTraceHelper: overall statistics" << std::endl;
2817 for (
uint32_t nodeIndex = 0; nodeIndex < nNodes; ++nodeIndex)
2819 std::cout <<
"\nWifiPhyRxTraceHelper: per-node statistics for node " << nodeIndex
2823 std::cout << std::endl;
2850 auto it = counter.find(addr);
2851 if (it != counter.end())
2861main(
int argc,
char* argv[])
2867 double duration = 100;
2872 std::string workDir =
"./";
2873 std::string phyMode =
2875 std::string standard(
"11a");
2876 bool validate =
false;
2878 uint16_t plotBianchiModel =
2880 double maxRelativeError =
2883 double frequency = 5;
2884 uint16_t channelWidth = 20;
2885 uint16_t guardIntervalNs = 800;
2887 uint16_t pktInterval =
2891 dBm_u apTxPower{16};
2892 dBm_u staTxPower{16};
2903 "ns3::WifiMacQueue::MaxSize",
2908 cmd.AddValue(
"verbose",
2909 "Logging level (0: no log - 1: simulation script logs - 2: all logs)",
2911 cmd.AddValue(
"tracing",
"Generate trace files",
tracing);
2912 cmd.AddValue(
"useTxHelper",
"Enable WifiTxStatsHelper on all devices",
useTxHelper);
2913 cmd.AddValue(
"useRxHelper",
"Enable WifiPhyRxTraceHelper on all devices",
useRxHelper);
2914 cmd.AddValue(
"pktSize",
"The packet size in bytes",
pktSize);
2915 cmd.AddValue(
"trials",
"The maximal number of runs per network size", trials);
2916 cmd.AddValue(
"duration",
"Time duration for each trial in seconds", duration);
2917 cmd.AddValue(
"pcap",
"Enable/disable PCAP tracing", pcap);
2918 cmd.AddValue(
"infra",
"True to use infrastructure mode, false to use ring adhoc mode", infra);
2919 cmd.AddValue(
"workDir",
"The working directory used to store generated files", workDir);
2920 cmd.AddValue(
"phyMode",
"Set the constant PHY mode string used to transmit frames", phyMode);
2921 cmd.AddValue(
"standard",
"Set the standard (11a, 11b, 11g, 11n, 11ac, 11ax)", standard);
2922 cmd.AddValue(
"nMinStas",
"Minimum number of stations to start with", nMinStas);
2923 cmd.AddValue(
"nMaxStas",
"Maximum number of stations to start with", nMaxStas);
2924 cmd.AddValue(
"nStepSize",
"Number of stations to add at each step", nStepSize);
2925 cmd.AddValue(
"plotBianchiModel",
2926 "First bit corresponds to the DIFS model, second bit to the EIFS model",
2928 cmd.AddValue(
"validate",
2929 "Enable/disable validation of the ns-3 simulations against the Bianchi model",
2931 cmd.AddValue(
"maxRelativeError",
2932 "The maximum relative error tolerated between ns-3 results and the Bianchi model "
2933 "(used for regression, i.e. when the validate flag is set)",
2935 cmd.AddValue(
"frequency",
"Set the operating frequency band in GHz: 2.4, 5 or 6", frequency);
2936 cmd.AddValue(
"channelWidth",
2937 "Set the constant channel width in MHz (only for 11n/ac/ax)",
2939 cmd.AddValue(
"guardIntervalNs",
2940 "Set the the guard interval in nanoseconds (800 or 400 for 11n/ac, 800 or 1600 or "
2943 cmd.AddValue(
"maxMpdus",
2944 "Set the maximum number of MPDUs in A-MPDUs (0 to disable MPDU aggregation)",
2946 cmd.AddValue(
"distance",
"Set the distance in meters between the AP and the STAs", distance);
2947 cmd.AddValue(
"apTxPower",
2948 "Set the transmit power of the AP in dBm (if infrastructure only)",
2950 cmd.AddValue(
"staTxPower",
2951 "Set the transmit power of each STA in dBm (or all STAs if adhoc)",
2953 cmd.AddValue(
"pktInterval",
"Set the socket packet interval in microseconds", pktInterval);
2954 cmd.Parse(argc, argv);
2966 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-backoff-trace.out");
2971 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-phy-tx-trace.out");
2976 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-mac-tx-trace.out");
2981 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-mac-rx-trace.out");
2986 NS_FATAL_ERROR(
"Failed to open file wifi-bianchi-socket-send-trace.out");
3003 std::stringstream phyModeStr;
3004 phyModeStr << phyMode;
3005 if (phyMode.find(
"Mcs") != std::string::npos)
3007 phyModeStr <<
"_" << channelWidth <<
"MHz";
3010 std::stringstream ss;
3011 ss <<
"wifi-" << standard <<
"-p-" <<
pktSize << (infra ?
"-infrastructure" :
"-adhoc") <<
"-r-"
3012 << phyModeStr.str() <<
"-min-" << nMinStas <<
"-max-" << nMaxStas <<
"-step-" << nStepSize
3013 <<
"-throughput.plt";
3014 std::ofstream throughputPlot(ss.str());
3016 ss <<
"wifi-" << standard <<
"-p-" <<
pktSize << (infra ?
"-infrastructure" :
"-adhoc") <<
"-r-"
3017 << phyModeStr.str() <<
"-min-" << nMinStas <<
"-max-" << nMaxStas <<
"-step-" << nStepSize
3018 <<
"-throughput.eps";
3022 if (standard ==
"11a")
3028 else if (standard ==
"11b")
3034 else if (standard ==
"11g")
3040 else if (standard ==
"11n")
3042 if (frequency == 2.4 || frequency == 5)
3048 NS_FATAL_ERROR(
"Unsupported frequency band " << frequency <<
" GHz for standard "
3052 else if (standard ==
"11ac")
3057 else if (standard ==
"11ax")
3059 if (frequency == 2.4 || frequency == 5 || frequency == 6)
3065 NS_FATAL_ERROR(
"Unsupported frequency band " << frequency <<
" GHz for standard "
3074 std::string channelStr =
"{0, " + std::to_string(channelWidth) +
", BAND_" +
3075 (frequency == 2.4 ?
"2_4" : (frequency == 5 ?
"5" :
"6")) +
"GHZ, 0}";
3089 "ReferenceDistance",
3094 else if (frequency == 5)
3100 "ReferenceDistance",
3111 "ReferenceDistance",
3118 wifi.SetStandard(wifiStandard);
3119 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
3135 double averageThroughput;
3136 std::vector<double> throughputArray(trials);
3137 for (
uint32_t n = nMinStas; n <= nMaxStas; n += nStepSize)
3139 averageThroughput = 0;
3141 for (
uint32_t runIndex = 0; runIndex < trials; runIndex++)
3157 std::cout <<
"Trial " << runIndex + 1 <<
" of " << trials <<
"; " << phyModeStr.str()
3158 <<
" for " << n <<
" nodes " << std::endl;
3161 cwTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3162 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3164 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3165 phyTxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3166 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3167 macTxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3168 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3169 macRxTraceFile <<
"# Trial " << runIndex + 1 <<
" of " << trials <<
"; "
3170 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3172 << phyModeStr.str() <<
" for " << n <<
" nodes" << std::endl;
3197 Time dataTransferDuration = last -
first;
3198 double nodeThroughput =
3199 (it->second * 8 /
static_cast<double>(dataTransferDuration.
GetMicroSeconds()));
3206 uint64_t nodeRxEventWhileDecodingPreamble =
3211 uint64_t nodeRxEvents = nodePhyHeaderFailures + nodePsduFailures + nodePsduSuccess +
3212 nodeRxEventWhileDecodingPreamble + nodeRxEventWhileRxing +
3213 nodeRxEventWhileTxing + nodeRxEventAbortedByTx;
3214 std::cout <<
"Node " << it->first <<
": TX packets " << nodeTxPackets
3215 <<
"; RX packets " << nodeRxPackets <<
"; PHY header failures "
3216 << nodePhyHeaderFailures <<
"; PSDU failures " << nodePsduFailures
3217 <<
"; PSDU success " << nodePsduSuccess
3218 <<
"; RX events while decoding preamble "
3219 << nodeRxEventWhileDecodingPreamble <<
"; RX events while RXing "
3220 << nodeRxEventWhileRxing <<
"; RX events while TXing "
3221 << nodeRxEventWhileTxing <<
"; RX events aborted by TX "
3222 << nodeRxEventAbortedByTx <<
"; total RX events " << nodeRxEvents
3223 <<
"; total events " << nodeTxPackets + nodeRxEvents <<
"; time first RX "
3224 <<
first <<
"; time last RX " << last <<
"; dataTransferDuration "
3225 << dataTransferDuration <<
"; throughput " << nodeThroughput <<
" Mbps"
3228 std::cout <<
"Total throughput: " <<
throughput <<
" Mbps" << std::endl;
3232 averageThroughput = averageThroughput / trials;
3234 bool rateFound =
false;
3235 double relativeErrorDifs = 0;
3236 double relativeErrorEifs = 0;
3241 auto it = itDifs->second.find(n);
3242 if (it != itDifs->second.end())
3244 relativeErrorDifs = (std::abs(averageThroughput - it->second) / it->second);
3245 std::cout <<
"Relative error (DIFS): " << 100 * relativeErrorDifs <<
"%"
3250 NS_FATAL_ERROR(
"No Bianchi results (DIFS) calculated for that number of stations!");
3257 auto it = itEifs->second.find(n);
3258 if (it != itEifs->second.end())
3260 relativeErrorEifs = (std::abs(averageThroughput - it->second) / it->second);
3261 std::cout <<
"Relative error (EIFS): " << 100 * relativeErrorEifs <<
"%"
3266 NS_FATAL_ERROR(
"No Bianchi results (EIFS) calculated for that number of stations!");
3269 if (!rateFound && validate)
3273 double relativeError = std::min(relativeErrorDifs, relativeErrorEifs);
3274 if (validate && (relativeError > maxRelativeError))
3280 for (
uint32_t i = 0; i < trials; ++i)
3282 stDev += pow(throughputArray[i] - averageThroughput, 2);
3284 stDev = sqrt(stDev / (trials - 1));
3285 dataset.
Add(n, averageThroughput, stDev);
3292 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3295 auto it = itDifs->second.find(i);
3296 if (it != itDifs->second.end())
3300 datasetBianchiDifs.
Add(i, value);
3305 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3307 datasetBianchiDifs.
Add(i, 0.0);
3314 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3317 auto it = itEifs->second.find(i);
3318 if (it != itEifs->second.end())
3322 datasetBianchiEifs.
Add(i, value);
3327 for (
uint32_t i = nMinStas; i <= nMaxStas; i += nStepSize)
3329 datasetBianchiEifs.
Add(i, 0.0);
3333 datasetBianchiEifs.
SetTitle(
"Bianchi (EIFS - lower bound)");
3334 datasetBianchiDifs.
SetTitle(
"Bianchi (DIFS - upper bound)");
3336 gnuplot.
SetTerminal(
"postscript eps color enh \"Times-BoldItalic\"");
3337 gnuplot.
SetLegend(
"Number of competing stations",
"Throughput (Mbps)");
3339 ss <<
"Frame size " <<
pktSize <<
" bytes";
3342 ss <<
"set xrange [" << nMinStas <<
":" << nMaxStas <<
"]\n"
3343 <<
"set xtics " << nStepSize <<
"\n"
3344 <<
"set grid xtics ytics\n"
3346 <<
"set style line 1 linewidth 5\n"
3347 <<
"set style line 2 linewidth 5\n"
3348 <<
"set style line 3 linewidth 5\n"
3349 <<
"set style line 4 linewidth 5\n"
3350 <<
"set style line 5 linewidth 5\n"
3351 <<
"set style line 6 linewidth 5\n"
3352 <<
"set style line 7 linewidth 5\n"
3353 <<
"set style line 8 linewidth 5\n"
3354 <<
"set style increment user";
3356 if (plotBianchiModel & 0x0001)
3358 datasetBianchiDifs.
SetTitle(
"Bianchi");
3361 if (plotBianchiModel & 0x0002)
3363 datasetBianchiEifs.
SetTitle(
"Bianchi");
3366 if (plotBianchiModel == 0x0003)
3368 datasetBianchiEifs.
SetTitle(
"Bianchi (EIFS - lower bound)");
3369 datasetBianchiDifs.
SetTitle(
"Bianchi (DIFS - upper bound)");
3372 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.