From 054be933b88e3200ec701f54e6e999b3e3e0b099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Fri, 8 Mar 2024 07:50:34 +0100 Subject: [PATCH] examples: Also allow to select channel width and guard interval duration in wifi network examples --- examples/wireless/wifi-eht-network.cc | 48 +++++++++++++++++++-------- examples/wireless/wifi-he-network.cc | 48 +++++++++++++++++++-------- examples/wireless/wifi-ht-network.cc | 43 +++++++++++++++++++----- examples/wireless/wifi-vht-network.cc | 48 ++++++++++++++++++++------- 4 files changed, 138 insertions(+), 49 deletions(-) diff --git a/examples/wireless/wifi-eht-network.cc b/examples/wireless/wifi-eht-network.cc index d4e39f918..2fa514884 100644 --- a/examples/wireless/wifi-eht-network.cc +++ b/examples/wireless/wifi-eht-network.cc @@ -158,11 +158,13 @@ main(int argc, char* argv[]) bool enableBsrp{false}; std::string mcsStr; std::vector mcsValues; + int channelWidth{-1}; // in MHz, -1 indicates an unset value + int guardInterval{-1}; // in nanoseconds, -1 indicates an unset value uint32_t payloadSize = 700; // must fit in the max TX duration when transmitting at MCS 0 over an RU of 26 tones Time tputInterval{0}; // interval for detailed throughput measurement - double minExpectedThroughput{0}; - double maxExpectedThroughput{0}; + double minExpectedThroughput{0.0}; + double maxExpectedThroughput{0.0}; Time accessReqInterval{0}; CommandLine cmd(__FILE__); @@ -233,6 +235,14 @@ main(int argc, char* argv[]) "mcs", "list of comma separated MCS values to test; if unset, all MCS values (0-13) are tested", mcsStr); + cmd.AddValue("channelWidth", + "if set, limit testing to a specific channel width expressed in MHz (20, 40, 80 " + "or 160 MHz)", + channelWidth); + cmd.AddValue("guardInterval", + "if set, limit testing to a specific guard interval duration expressed in " + "nanoseconds (800, 1600 or 3200 ns)", + guardInterval); cmd.AddValue("payloadSize", "The application payload size in bytes", payloadSize); cmd.AddValue("tputInterval", "duration of intervals for throughput measurement", tputInterval); cmd.AddValue("minExpectedThroughput", @@ -299,19 +309,31 @@ main(int argc, char* argv[]) std::sort(mcsValues.begin(), mcsValues.end()); } + int minChannelWidth = 20; + int maxChannelWidth = (frequency != 2.4 && frequency2 != 2.4 && frequency3 != 2.4) ? 160 : 40; + if (channelWidth >= minChannelWidth && channelWidth <= maxChannelWidth) + { + minChannelWidth = channelWidth; + maxChannelWidth = channelWidth; + } + int minGi = enableUlOfdma ? 1600 : 800; + int maxGi = 3200; + if (guardInterval >= minGi && guardInterval <= maxGi) + { + minGi = guardInterval; + maxGi = guardInterval; + } + for (const auto mcs : mcsValues) { uint8_t index = 0; double previous = 0; - uint16_t maxChannelWidth = - (frequency != 2.4 && frequency2 != 2.4 && frequency3 != 2.4) ? 160 : 40; - int minGi = enableUlOfdma ? 1600 : 800; - for (int channelWidth = 20; channelWidth <= maxChannelWidth;) // MHz + for (int width = minChannelWidth; width <= maxChannelWidth; width *= 2) // MHz { - const auto is80Plus80 = (use80Plus80 && (channelWidth == 160)); - const std::string widthStr = is80Plus80 ? "80+80" : std::to_string(channelWidth); + const auto is80Plus80 = (use80Plus80 && (width == 160)); + const std::string widthStr = is80Plus80 ? "80+80" : std::to_string(width); const auto segmentWidthStr = is80Plus80 ? "80" : widthStr; - for (int gi = 3200; gi >= minGi;) // Nanoseconds + for (int gi = maxGi; gi >= minGi; gi /= 2) // Nanoseconds { if (!udp) { @@ -506,7 +528,7 @@ main(int argc, char* argv[]) } const auto maxLoad = - nLinks * EhtPhy::GetDataRate(mcs, channelWidth, NanoSeconds(gi), 1) / nStations; + nLinks * EhtPhy::GetDataRate(mcs, width, NanoSeconds(gi), 1) / nStations; if (udp) { // UDP flow @@ -598,7 +620,7 @@ main(int argc, char* argv[]) << " Mbit/s" << std::endl; // test first element - if (mcs == minMcs && channelWidth == 20 && gi == 3200) + if (mcs == minMcs && width == 20 && gi == 3200) { if (throughput * (1 + tolerance) < minExpectedThroughput) { @@ -607,7 +629,7 @@ main(int argc, char* argv[]) } } // test last element - if (mcs == maxMcs && channelWidth == maxChannelWidth && gi == 800) + if (mcs == maxMcs && width == maxChannelWidth && gi == 800) { if (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput * (1 + tolerance)) @@ -637,9 +659,7 @@ main(int argc, char* argv[]) exit(1); } index++; - gi /= 2; } - channelWidth *= 2; } } return 0; diff --git a/examples/wireless/wifi-he-network.cc b/examples/wireless/wifi-he-network.cc index 3fd9dcbc1..cf9ba7786 100644 --- a/examples/wireless/wifi-he-network.cc +++ b/examples/wireless/wifi-he-network.cc @@ -74,11 +74,13 @@ main(int argc, char* argv[]) bool enableBsrp{false}; std::string mcsStr; std::vector mcsValues; + int channelWidth{-1}; // in MHz, -1 indicates an unset value + int guardInterval{-1}; // in nanoseconds, -1 indicates an unset value uint32_t payloadSize = 700; // must fit in the max TX duration when transmitting at MCS 0 over an RU of 26 tones std::string phyModel{"Yans"}; - double minExpectedThroughput{0}; - double maxExpectedThroughput{0}; + double minExpectedThroughput{0.0}; + double maxExpectedThroughput{0.0}; Time accessReqInterval{0}; CommandLine cmd(__FILE__); @@ -114,6 +116,14 @@ main(int argc, char* argv[]) "mcs", "list of comma separated MCS values to test; if unset, all MCS values (0-11) are tested", mcsStr); + cmd.AddValue("channelWidth", + "if set, limit testing to a specific channel width expressed in MHz (20, 40, 80 " + "or 160 MHz)", + channelWidth); + cmd.AddValue("guardInterval", + "if set, limit testing to a specific guard interval duration expressed in " + "nanoseconds (800, 1600 or 3200 ns)", + guardInterval); cmd.AddValue("payloadSize", "The application payload size in bytes", payloadSize); cmd.AddValue("phyModel", "PHY model to use when OFDMA is disabled (Yans or Spectrum). If 80+80 MHz or " @@ -194,18 +204,31 @@ main(int argc, char* argv[]) std::sort(mcsValues.begin(), mcsValues.end()); } + int minChannelWidth = 20; + int maxChannelWidth = frequency == 2.4 ? 40 : 160; + if (channelWidth >= minChannelWidth && channelWidth <= maxChannelWidth) + { + minChannelWidth = channelWidth; + maxChannelWidth = channelWidth; + } + int minGi = enableUlOfdma ? 1600 : 800; + int maxGi = 3200; + if (guardInterval >= minGi && guardInterval <= maxGi) + { + minGi = guardInterval; + maxGi = guardInterval; + } + for (const auto mcs : mcsValues) { uint8_t index = 0; double previous = 0; - uint8_t maxChannelWidth = frequency == 2.4 ? 40 : 160; - int minGi = enableUlOfdma ? 1600 : 800; - for (int channelWidth = 20; channelWidth <= maxChannelWidth;) // MHz + for (int width = minChannelWidth; width <= maxChannelWidth; width *= 2) // MHz { - const auto is80Plus80 = (use80Plus80 && (channelWidth == 160)); - const std::string widthStr = is80Plus80 ? "80+80" : std::to_string(channelWidth); + const auto is80Plus80 = (use80Plus80 && (width == 160)); + const std::string widthStr = is80Plus80 ? "80+80" : std::to_string(width); const auto segmentWidthStr = is80Plus80 ? "80" : widthStr; - for (int gi = 3200; gi >= minGi;) // Nanoseconds + for (int gi = maxGi; gi >= minGi; gi /= 2) // Nanoseconds { if (!udp) { @@ -375,8 +398,7 @@ main(int argc, char* argv[]) clientNodes.Add(downlink ? wifiApNode.Get(0) : wifiStaNodes.Get(i)); } - const auto maxLoad = - HePhy::GetDataRate(mcs, channelWidth, NanoSeconds(gi), 1) / nStations; + const auto maxLoad = HePhy::GetDataRate(mcs, width, NanoSeconds(gi), 1) / nStations; if (udp) { // UDP flow @@ -469,7 +491,7 @@ main(int argc, char* argv[]) << " Mbit/s" << std::endl; // test first element - if (mcs == minMcs && channelWidth == 20 && gi == 3200) + if (mcs == minMcs && width == 20 && gi == 3200) { if (throughput * (1 + tolerance) < minExpectedThroughput) { @@ -478,7 +500,7 @@ main(int argc, char* argv[]) } } // test last element - if (mcs == maxMcs && channelWidth == maxChannelWidth && gi == 800) + if (mcs == maxMcs && width == maxChannelWidth && gi == 800) { if (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput * (1 + tolerance)) @@ -514,9 +536,7 @@ main(int argc, char* argv[]) } } index++; - gi /= 2; } - channelWidth *= 2; } } return 0; diff --git a/examples/wireless/wifi-ht-network.cc b/examples/wireless/wifi-ht-network.cc index 2cd7e8202..37a625ec1 100644 --- a/examples/wireless/wifi-ht-network.cc +++ b/examples/wireless/wifi-ht-network.cc @@ -64,6 +64,8 @@ main(int argc, char* argv[]) double frequency{5}; // whether 2.4 or 5 GHz std::string mcsStr; std::vector mcsValues; + int channelWidth{-1}; // in MHz, -1 indicates an unset value + int guardInterval{-1}; // in nanoseconds, -1 indicates an unset value double minExpectedThroughput{0.0}; double maxExpectedThroughput{0.0}; @@ -81,6 +83,14 @@ main(int argc, char* argv[]) "mcs", "list of comma separated MCS values to test; if unset, all MCS values (0-7) are tested", mcsStr); + cmd.AddValue( + "channelWidth", + "if set, limit testing to a specific channel width expressed in MHz (20 or 40 MHz)", + channelWidth); + cmd.AddValue("guardInterval", + "if set, limit testing to a specific guard interval duration expressed in " + "nanoseconds (800 or 400 ns)", + guardInterval); cmd.AddValue("minExpectedThroughput", "if set, simulation fails if the lowest throughput is below this value", minExpectedThroughput); @@ -123,14 +133,30 @@ main(int argc, char* argv[]) std::sort(mcsValues.begin(), mcsValues.end()); } + int minChannelWidth = 20; + int maxChannelWidth = 40; + if (channelWidth >= minChannelWidth && channelWidth <= maxChannelWidth) + { + minChannelWidth = channelWidth; + maxChannelWidth = channelWidth; + } + int minGi = 400; + int maxGi = 800; + if (guardInterval >= minGi && guardInterval <= maxGi) + { + minGi = guardInterval; + maxGi = guardInterval; + } + for (const auto mcs : mcsValues) { uint8_t index = 0; double previous = 0; - for (int channelWidth = 20; channelWidth <= 40;) + for (int width = minChannelWidth; width <= maxChannelWidth; width *= 2) // MHz { - for (auto sgi : {false, true}) + for (int gi = maxGi; gi >= minGi; gi /= 2) // Nanoseconds { + const auto sgi = (gi == 400); uint32_t payloadSize; // 1500 byte IP packet if (udp) { @@ -191,7 +217,7 @@ main(int argc, char* argv[]) ';'> channelValue; WifiPhyBand band = (frequency == 5.0 ? WIFI_PHY_BAND_5GHZ : WIFI_PHY_BAND_2_4GHZ); - channelValue.Set(WifiPhy::ChannelSegments{{0, channelWidth, band, 0}}); + channelValue.Set(WifiPhy::ChannelSegments{{0, width, band, 0}}); mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid)); phy.Set("ChannelSettings", channelValue); @@ -242,7 +268,7 @@ main(int argc, char* argv[]) /* Setting applications */ const auto maxLoad = - HtPhy::GetDataRate(mcs, channelWidth, NanoSeconds(sgi ? 400 : 800), 1); + HtPhy::GetDataRate(mcs, width, NanoSeconds(sgi ? 400 : 800), 1); ApplicationContainer serverApp; if (udp) { @@ -314,11 +340,11 @@ main(int argc, char* argv[]) Simulator::Destroy(); - std::cout << mcs << "\t\t\t" << channelWidth << " MHz\t\t\t" << std::boolalpha - << sgi << "\t\t\t" << throughput << " Mbit/s" << std::endl; + std::cout << mcs << "\t\t\t" << width << " MHz\t\t\t" << std::boolalpha << sgi + << "\t\t\t" << throughput << " Mbit/s" << std::endl; // test first element - if (mcs == minMcs && channelWidth == 20 && !sgi) + if (mcs == minMcs && width == 20 && !sgi) { if (throughput < minExpectedThroughput) { @@ -326,7 +352,7 @@ main(int argc, char* argv[]) } } // test last element - if (mcs == maxMcs && channelWidth == 40 && sgi) + if (mcs == maxMcs && width == 40 && sgi) { if (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput) { @@ -353,7 +379,6 @@ main(int argc, char* argv[]) } index++; } - channelWidth *= 2; } } return 0; diff --git a/examples/wireless/wifi-vht-network.cc b/examples/wireless/wifi-vht-network.cc index 8827779fe..8babedc69 100644 --- a/examples/wireless/wifi-vht-network.cc +++ b/examples/wireless/wifi-vht-network.cc @@ -65,6 +65,8 @@ main(int argc, char* argv[]) std::string mcsStr; std::vector mcsValues; std::string phyModel{"Yans"}; + int channelWidth{-1}; // in MHz, -1 indicates an unset value + int guardInterval{-1}; // in nanoseconds, -1 indicates an unset value double minExpectedThroughput{0.0}; double maxExpectedThroughput{0.0}; @@ -84,6 +86,14 @@ main(int argc, char* argv[]) "PHY model to use (Yans or Spectrum). If 80+80 MHz is enabled, then Spectrum is " "automatically selected", phyModel); + cmd.AddValue("channelWidth", + "if set, limit testing to a specific channel width expressed in MHz (20, 40, 80 " + "or 160 MHz)", + channelWidth); + cmd.AddValue("guardInterval", + "if set, limit testing to a specific guard interval duration expressed in " + "nanoseconds (800 or 400 ns)", + guardInterval); cmd.AddValue("minExpectedThroughput", "if set, simulation fails if the lowest throughput is below this value", minExpectedThroughput); @@ -136,22 +146,37 @@ main(int argc, char* argv[]) std::sort(mcsValues.begin(), mcsValues.end()); } + int minChannelWidth = 20; + int maxChannelWidth = 160; + if (channelWidth >= minChannelWidth && channelWidth <= maxChannelWidth) + { + minChannelWidth = channelWidth; + maxChannelWidth = channelWidth; + } + int minGi = 400; + int maxGi = 800; + if (guardInterval >= minGi && guardInterval <= maxGi) + { + minGi = guardInterval; + maxGi = guardInterval; + } + for (const auto mcs : mcsValues) { uint8_t index = 0; double previous = 0; - for (int channelWidth = 20; channelWidth <= 160;) + for (int width = minChannelWidth; width <= maxChannelWidth; width *= 2) // MHz { - if (mcs == 9 && channelWidth == 20) + if (mcs == 9 && width == 20) { - channelWidth *= 2; continue; } - const auto is80Plus80 = (use80Plus80 && (channelWidth == 160)); - const std::string widthStr = is80Plus80 ? "80+80" : std::to_string(channelWidth); + const auto is80Plus80 = (use80Plus80 && (width == 160)); + const std::string widthStr = is80Plus80 ? "80+80" : std::to_string(width); const auto segmentWidthStr = is80Plus80 ? "80" : widthStr; - for (auto sgi : {false, true}) + for (int gi = maxGi; gi >= minGi; gi /= 2) // Nanoseconds { + const auto sgi = (gi == 400); uint32_t payloadSize; // 1500 byte IP packet if (udp) { @@ -209,7 +234,7 @@ main(int argc, char* argv[]) phy.SetChannel(spectrumChannel); phy.Set("ChannelSettings", - StringValue("{0, " + std::to_string(channelWidth) + ", BAND_5GHZ, 0}")); + StringValue("{0, " + std::to_string(width) + ", BAND_5GHZ, 0}")); mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid)); staDevice = wifi.Install(phy, mac, wifiStaNode); @@ -229,7 +254,7 @@ main(int argc, char* argv[]) phy.SetChannel(channel.Create()); phy.Set("ChannelSettings", - StringValue("{0, " + std::to_string(channelWidth) + ", BAND_5GHZ, 0}")); + StringValue("{0, " + std::to_string(width) + ", BAND_5GHZ, 0}")); mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid)); staDevice = wifi.Install(phy, mac, wifiStaNode); @@ -276,7 +301,7 @@ main(int argc, char* argv[]) /* Setting applications */ const auto maxLoad = - VhtPhy::GetDataRate(mcs, channelWidth, NanoSeconds(sgi ? 400 : 800), 1); + VhtPhy::GetDataRate(mcs, width, NanoSeconds(sgi ? 400 : 800), 1); ApplicationContainer serverApp; if (udp) { @@ -353,7 +378,7 @@ main(int argc, char* argv[]) << "\t\t\t" << throughput << " Mbit/s" << std::endl; // test first element - if (mcs == minMcs && channelWidth == 20 && !sgi) + if (mcs == minMcs && width == 20 && !sgi) { if (throughput < minExpectedThroughput) { @@ -362,7 +387,7 @@ main(int argc, char* argv[]) } } // test last element - if (mcs == maxMcs && channelWidth == 160 && sgi) + if (mcs == maxMcs && width == 160 && sgi) { if (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput) { @@ -392,7 +417,6 @@ main(int argc, char* argv[]) } index++; } - channelWidth *= 2; } } return 0;