diff --git a/examples/wireless/wifi-spectrum-saturation-example.cc b/examples/wireless/wifi-spectrum-saturation-example.cc index 8d72a2d..b88e109 100644 --- a/examples/wireless/wifi-spectrum-saturation-example.cc +++ b/examples/wireless/wifi-spectrum-saturation-example.cc @@ -198,8 +198,8 @@ int main (int argc, char *argv[]) //Bug 2460: CcaMode1Threshold default should be set to -62 dBm when using Spectrum Config::SetDefault ("ns3::WifiPhy::CcaMode1Threshold", DoubleValue (-62.0)); - Ptr spectrumChannel - = CreateObject (); + Ptr spectrumChannel + = CreateObject (); Ptr lossModel = CreateObject (); spectrumChannel->AddPropagationLossModel (lossModel); diff --git a/src/spectrum/model/multi-model-spectrum-channel.cc b/src/spectrum/model/multi-model-spectrum-channel.cc index 6f40d96..11d5b66 100644 --- a/src/spectrum/model/multi-model-spectrum-channel.cc +++ b/src/spectrum/model/multi-model-spectrum-channel.cc @@ -134,6 +134,12 @@ MultiModelSpectrumChannel::GetTypeId (void) "reported in this trace. ", MakeTraceSourceAccessor (&MultiModelSpectrumChannel::m_pathLossTrace), "ns3::SpectrumChannel::LossTracedCallback") + .AddTraceSource ("TxSigParams", + "This trace is fired whenever a signal is transmitted. " + "The sole parameter is a pointer to a copy of the " + "SpectrumSignalParameters provided by the transmitter.", + MakeTraceSourceAccessor (&MultiModelSpectrumChannel::m_txSigParamsTrace), + "ns3::MultiModelSpectrumChannel::SignalParametersTracedCallback") ; return tid; } @@ -261,7 +267,8 @@ MultiModelSpectrumChannel::StartTx (Ptr txParams) NS_ASSERT (txParams->txPhy); NS_ASSERT (txParams->psd); - + Ptr txParamsTrace = txParams->Copy (); // copy it since traced value cannot be const (because of potential underlying DynamicCasts) + m_txSigParamsTrace (txParamsTrace); Ptr txMobility = txParams->txPhy->GetMobility (); SpectrumModelUid_t txSpectrumModelUid = txParams->psd->GetSpectrumModelUid (); diff --git a/src/spectrum/model/multi-model-spectrum-channel.h b/src/spectrum/model/multi-model-spectrum-channel.h index 07a4841..84fcd87 100644 --- a/src/spectrum/model/multi-model-spectrum-channel.h +++ b/src/spectrum/model/multi-model-spectrum-channel.h @@ -133,6 +133,12 @@ public: */ virtual Ptr GetSpectrumPropagationLossModel (void); + /** + * TracedCallback signature for Ptr. + * + * \param [in] params SpectrumSignalParameters instance. + */ + typedef void (* SignalParametersTracedCallback) (Ptr params); protected: void DoDispose (); @@ -207,6 +213,10 @@ private: * in a future release. */ TracedCallback, Ptr, double > m_pathLossTrace; + /** + * Traced callback for SpectrumSignalParameters in StartTx requests + */ + TracedCallback > m_txSigParamsTrace; }; diff --git a/src/spectrum/model/wifi-spectrum-value-helper.cc b/src/spectrum/model/wifi-spectrum-value-helper.cc index 5e2d603..10db345 100644 --- a/src/spectrum/model/wifi-spectrum-value-helper.cc +++ b/src/spectrum/model/wifi-spectrum-value-helper.cc @@ -164,7 +164,6 @@ WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (uint32_t centerFreque switch (channelWidth) { case 20: - default: // 52 subcarriers (48 data + 4 pilot) // skip guard band and 6 subbands, then place power in 26 subbands, then // skip the center subband, then place power in 26 subbands, then skip @@ -197,6 +196,9 @@ WifiSpectrumValueHelper::CreateOfdmTxPowerSpectralDensity (uint32_t centerFreque start2 = stop1 + 2; stop2 = start2 + 8 - 1; break; + default: + NS_FATAL_ERROR ("Channel width should be correctly set."); + return 0; } NS_LOG_DEBUG ("Power per band " << txPowerPerBand); Values::iterator vit = c->ValuesBegin (); diff --git a/src/wifi/model/constant-rate-wifi-manager.cc b/src/wifi/model/constant-rate-wifi-manager.cc index a5ccf79..b7b8db5 100644 --- a/src/wifi/model/constant-rate-wifi-manager.cc +++ b/src/wifi/model/constant-rate-wifi-manager.cc @@ -117,14 +117,14 @@ WifiTxVector ConstantRateWifiManager::DoGetDataTxVector (WifiRemoteStation *st) { NS_LOG_FUNCTION (this << st); - return WifiTxVector (m_dataMode, GetDefaultTxPowerLevel (), GetLongRetryCount (st), GetPreambleForTransmission (m_dataMode, GetAddress (st)), ConvertGuardIntervalToNanoSeconds (m_dataMode, GetShortGuardInterval (st), NanoSeconds (GetGuardInterval (st))), GetNumberOfAntennas (), Min (GetMaxNumberOfTransmitStreams (), GetNumberOfSupportedStreams (st)), 0, GetChannelWidth (st), GetAggregation (st), false); + return WifiTxVector (m_dataMode, GetDefaultTxPowerLevel (), GetLongRetryCount (st), GetPreambleForTransmission (m_dataMode, GetAddress (st)), ConvertGuardIntervalToNanoSeconds (m_dataMode, GetShortGuardInterval (st), NanoSeconds (GetGuardInterval (st))), GetNumberOfAntennas (), Min (GetMaxNumberOfTransmitStreams (), GetNumberOfSupportedStreams (st)), 0, GetChannelWidthForTransmission (m_dataMode, GetChannelWidth (st)), GetAggregation (st), false); } WifiTxVector ConstantRateWifiManager::DoGetRtsTxVector (WifiRemoteStation *st) { NS_LOG_FUNCTION (this << st); - return WifiTxVector (m_ctlMode, GetDefaultTxPowerLevel (), GetShortRetryCount (st), GetPreambleForTransmission (m_ctlMode, GetAddress (st)), ConvertGuardIntervalToNanoSeconds (m_ctlMode, GetShortGuardInterval (st), NanoSeconds (GetGuardInterval (st))), 1, 1, 0, GetChannelWidth (st), GetAggregation (st), false); + return WifiTxVector (m_ctlMode, GetDefaultTxPowerLevel (), GetShortRetryCount (st), GetPreambleForTransmission (m_ctlMode, GetAddress (st)), ConvertGuardIntervalToNanoSeconds (m_ctlMode, GetShortGuardInterval (st), NanoSeconds (GetGuardInterval (st))), 1, 1, 0, GetChannelWidthForTransmission (m_ctlMode, GetChannelWidth (st)), GetAggregation (st), false); } bool diff --git a/src/wifi/model/ideal-wifi-manager.cc b/src/wifi/model/ideal-wifi-manager.cc index bb6db64..34dfea6 100644 --- a/src/wifi/model/ideal-wifi-manager.cc +++ b/src/wifi/model/ideal-wifi-manager.cc @@ -488,7 +488,7 @@ IdealWifiManager::DoGetDataTxVector (WifiRemoteStation *st) NS_LOG_DEBUG ("New datarate: " << maxMode.GetDataRate (channelWidth, guardInterval, selectedNss)); m_currentRate = maxMode.GetDataRate (channelWidth, guardInterval, selectedNss); } - return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetPreambleForTransmission (maxMode, GetAddress (station)), guardInterval, GetNumberOfAntennas (), selectedNss, 0, channelWidth, GetAggregation (station), false); + return WifiTxVector (maxMode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), GetPreambleForTransmission (maxMode, GetAddress (station)), guardInterval, GetNumberOfAntennas (), selectedNss, 0, GetChannelWidthForTransmission (maxMode, channelWidth), GetAggregation (station), false); } WifiTxVector diff --git a/src/wifi/model/minstrel-ht-wifi-manager.cc b/src/wifi/model/minstrel-ht-wifi-manager.cc index 13df0dc..78eab3b 100644 --- a/src/wifi/model/minstrel-ht-wifi-manager.cc +++ b/src/wifi/model/minstrel-ht-wifi-manager.cc @@ -931,7 +931,7 @@ MinstrelHtWifiManager::DoGetDataTxVector (WifiRemoteStation *st) } WifiMode mode = GetMcsSupported (station, mcsIndex); return WifiTxVector (mode, GetDefaultTxPowerLevel (), GetLongRetryCount (station), - GetPreambleForTransmission (mode, GetAddress (station)), group.sgi ? 400 : 800, GetNumberOfAntennas (), group.streams, GetNess (station), group.chWidth, GetAggregation (station) && !station->m_isSampling, false); + GetPreambleForTransmission (mode, GetAddress (station)), group.sgi ? 400 : 800, GetNumberOfAntennas (), group.streams, GetNess (station), GetChannelWidthForTransmission (mode, group.chWidth), GetAggregation (station) && !station->m_isSampling, false); } } @@ -1007,7 +1007,7 @@ MinstrelHtWifiManager::DoGetRtsTxVector (WifiRemoteStation *st) NS_ASSERT (rateFound); return WifiTxVector (rtsRate, GetDefaultTxPowerLevel (), GetShortRetryCount (station), GetPreambleForTransmission (rtsRate, GetAddress (station)), - 800, 1, 1, 0, GetChannelWidth (station), GetAggregation (station), false); + 800, 1, 1, 0, GetChannelWidthForTransmission (rtsRate, GetChannelWidth (station)), GetAggregation (station), false); } } diff --git a/src/wifi/model/spectrum-wifi-phy.cc b/src/wifi/model/spectrum-wifi-phy.cc index e383fae..175c4f7 100644 --- a/src/wifi/model/spectrum-wifi-phy.cc +++ b/src/wifi/model/spectrum-wifi-phy.cc @@ -312,12 +312,27 @@ SpectrumWifiPhy::GetTxPowerSpectralDensity (uint16_t centerFrequency, uint8_t ch return v; } +uint32_t +SpectrumWifiPhy::GetCenterFrequencyForChannelWidth (WifiTxVector txVector) const +{ + NS_LOG_FUNCTION (txVector); + uint32_t centerFrequencyForSupportedWidth = GetFrequency (); + uint32_t supportedWidth = static_cast (GetChannelWidth ()); + uint32_t currentWidth = static_cast (txVector.GetChannelWidth ()); + if (currentWidth != supportedWidth) + { + uint32_t startingFrequency = centerFrequencyForSupportedWidth - (supportedWidth / 2); + return startingFrequency + (currentWidth / 2); // primary channel is in the lower part (for the time being) + } + return centerFrequencyForSupportedWidth; +} + void SpectrumWifiPhy::StartTx (Ptr packet, WifiTxVector txVector, Time txDuration) { NS_LOG_DEBUG ("Start transmission: signal power before antenna gain=" << GetPowerDbm (txVector.GetTxPowerLevel ()) << "dBm"); double txPowerWatts = DbmToW (GetPowerDbm (txVector.GetTxPowerLevel ()) + GetTxGain ()); - Ptr txPowerSpectrum = GetTxPowerSpectralDensity (GetFrequency (), GetChannelWidth (), txPowerWatts, txVector.GetMode ().GetModulationClass ()); + Ptr txPowerSpectrum = GetTxPowerSpectralDensity (GetCenterFrequencyForChannelWidth (txVector), txVector.GetChannelWidth (), txPowerWatts, txVector.GetMode ().GetModulationClass ()); Ptr txParams = Create (); txParams->duration = txDuration; txParams->psd = txPowerSpectrum; diff --git a/src/wifi/model/spectrum-wifi-phy.h b/src/wifi/model/spectrum-wifi-phy.h index 03deb9c..e497a81 100644 --- a/src/wifi/model/spectrum-wifi-phy.h +++ b/src/wifi/model/spectrum-wifi-phy.h @@ -100,6 +100,15 @@ public: * \param txDuration duration of the transmission. */ void StartTx (Ptr packet, WifiTxVector txVector, Time txDuration); + /** + * Get the center frequency of the channel corresponding the current TxVector rather than + * that of the supported channel width. + * Consider that this "primary channel" is on the lower part for the time being. + * + * \param txVector the TXVECTOR that has the channel width that is to be used + * \return the center frequency corresponding to the channel width to be used + */ + uint32_t GetCenterFrequencyForChannelWidth (WifiTxVector txVector) const; /** * Method to encapsulate the creation of the WifiSpectrumPhyInterface diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index 99e5191..13d6b2d 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -813,6 +813,21 @@ WifiRemoteStationManager::PrepareForQueue (Mac48Address address, const WifiMacHe packet->AddPacketTag (ctstoselftag); } +uint8_t +WifiRemoteStationManager::GetChannelWidthForTransmission (WifiMode mode, uint8_t maxSupportedChannelWidth) +{ + NS_LOG_FUNCTION (mode << (uint16_t)maxSupportedChannelWidth); + WifiModulationClass modulationClass = mode.GetModulationClass (); + if (maxSupportedChannelWidth > 20 && + (modulationClass == WifiModulationClass::WIFI_MOD_CLASS_OFDM || // all non-HT OFDM control and management frames + modulationClass == WifiModulationClass::WIFI_MOD_CLASS_ERP_OFDM)) // special case of beacons at 2.4 GHz + { + NS_LOG_LOGIC ("Channel width reduced to 20 MHz"); + return 20; + } + return maxSupportedChannelWidth; +} + WifiTxVector WifiRemoteStationManager::GetDataTxVector (Mac48Address address, const WifiMacHeader *header, Ptr packet) { @@ -824,7 +839,7 @@ WifiRemoteStationManager::GetDataTxVector (Mac48Address address, const WifiMacHe v.SetMode (mode); v.SetPreambleType (GetPreambleForTransmission (mode, address)); v.SetTxPowerLevel (m_defaultTxPowerLevel); - v.SetChannelWidth (m_wifiPhy->GetChannelWidth ()); + v.SetChannelWidth (GetChannelWidthForTransmission (mode, m_wifiPhy->GetChannelWidth ())); v.SetGuardInterval (ConvertGuardIntervalToNanoSeconds (mode, m_wifiPhy->GetShortGuardInterval (), m_wifiPhy->GetGuardInterval ())); v.SetNss (1); v.SetNess (0); @@ -894,7 +909,7 @@ WifiRemoteStationManager::DoGetCtsToSelfTxVector (void) GetNumberOfAntennas (), GetMaxNumberOfTransmitStreams (), 0, - m_wifiPhy->GetChannelWidth (), + GetChannelWidthForTransmission (defaultMode, m_wifiPhy->GetChannelWidth ()), false, false); } @@ -1464,7 +1479,7 @@ WifiRemoteStationManager::GetCtsTxVector (Mac48Address address, WifiMode rtsMode v.SetMode (ctsMode); v.SetPreambleType (GetPreambleForTransmission (ctsMode, address)); v.SetTxPowerLevel (DoGetCtsTxPowerLevel (address, ctsMode)); - v.SetChannelWidth (DoGetCtsTxChannelWidth (address, ctsMode)); + v.SetChannelWidth (GetChannelWidthForTransmission (ctsMode, DoGetCtsTxChannelWidth (address, ctsMode))); v.SetGuardInterval (DoGetCtsTxGuardInterval (address, ctsMode)); v.SetNss (DoGetCtsTxNss (address, ctsMode)); v.SetNess (DoGetCtsTxNess (address, ctsMode)); @@ -1481,7 +1496,7 @@ WifiRemoteStationManager::GetAckTxVector (Mac48Address address, WifiMode dataMod v.SetMode (ackMode); v.SetPreambleType (GetPreambleForTransmission (ackMode, address)); v.SetTxPowerLevel (DoGetAckTxPowerLevel (address, ackMode)); - v.SetChannelWidth (DoGetAckTxChannelWidth (address, ackMode)); + v.SetChannelWidth (GetChannelWidthForTransmission (ackMode, DoGetAckTxChannelWidth (address, ackMode))); v.SetGuardInterval (DoGetAckTxGuardInterval (address, ackMode)); v.SetNss (DoGetAckTxNss (address, ackMode)); v.SetNess (DoGetAckTxNess (address, ackMode)); @@ -1498,7 +1513,7 @@ WifiRemoteStationManager::GetBlockAckTxVector (Mac48Address address, WifiMode bl v.SetMode (blockAckMode); v.SetPreambleType (GetPreambleForTransmission (blockAckMode, address)); v.SetTxPowerLevel (DoGetBlockAckTxPowerLevel (address, blockAckMode)); - v.SetChannelWidth (DoGetBlockAckTxChannelWidth (address, blockAckMode)); + v.SetChannelWidth (GetChannelWidthForTransmission (blockAckMode, DoGetBlockAckTxChannelWidth (address, blockAckMode))); v.SetGuardInterval (DoGetBlockAckTxGuardInterval (address, blockAckMode)); v.SetNss (DoGetBlockAckTxNss (address, blockAckMode)); v.SetNess (DoGetBlockAckTxNess (address, blockAckMode)); diff --git a/src/wifi/model/wifi-remote-station-manager.h b/src/wifi/model/wifi-remote-station-manager.h index 8189b5b..5c61308 100644 --- a/src/wifi/model/wifi-remote-station-manager.h +++ b/src/wifi/model/wifi-remote-station-manager.h @@ -1093,6 +1093,16 @@ protected: * \return the preamble to be used for the transmission */ WifiPreamble GetPreambleForTransmission (WifiMode mode, Mac48Address dest); + /** + * Return the channel width that corresponds to the selected mode (instead of + * letting the PHY's default channel width). This is especially useful when using + * non-HT modes with HT/VHT/HE capable stations (with default width above 20 MHz). + * + * \param mode selected WifiMode + * \param maxSupportedChannelWidth maximum channel width supported by the PHY layer + * \return channel width adapted to the selected mode + */ + static uint8_t GetChannelWidthForTransmission (WifiMode mode, uint8_t maxSupportedChannelWidth); /** * Return the WifiPhy. diff --git a/src/wifi/test/wifi-test.cc b/src/wifi/test/wifi-test.cc index 1e10c6a..b59cbc6 100644 --- a/src/wifi/test/wifi-test.cc +++ b/src/wifi/test/wifi-test.cc @@ -37,6 +37,13 @@ #include "ns3/packet-socket-server.h" #include "ns3/packet-socket-client.h" #include "ns3/packet-socket-helper.h" +#include "ns3/spectrum-wifi-helper.h" +#include "ns3/spectrum-value.h" +#include "ns3/multi-model-spectrum-channel.h" +#include "ns3/wifi-spectrum-signal-parameters.h" +#include "ns3/wifi-phy-tag.h" +#include +#include using namespace ns3; @@ -1154,6 +1161,187 @@ Bug2222TestCase::DoRun (void) NS_TEST_ASSERT_MSG_EQ (m_countInternalCollisions, 1, "unexpected number of internal collisions!"); } +//----------------------------------------------------------------------------- +/** + * Make sure that the correct channel width and center frequency have been set + * for OFDM basic rate transmissions and BSS channel widths larger than 20 MHz. + * + * The scenario considers a UDP transmission between a 40 MHz 802.11ac station and a + * 40 MHz 802.11ac access point. All transmission parameters are checked so as + * to ensure that only 2 {starting frequency, channelWidth, Number of subbands + * in SpectrumModel, modulation type} tuples are used. + * + * See \bugid{2483} + */ + +class Bug2483TestCase : public TestCase +{ +public: + Bug2483TestCase (); + virtual ~Bug2483TestCase (); + virtual void DoRun (void); + +private: + /** + * A tuple of {starting frequency, channelWidth, Number of subbands in SpectrumModel, modulation type} + */ + typedef std::tuple FreqWidthSubbandModulationTuple; + std::vector m_distinctTuples; ///< vector of distinct {starting frequency, channelWidth, Number of subbands in SpectrumModel, modulation type} tuples + + /** + * Stores the distinct {starting frequency, channelWidth, Number of subbands in SpectrumModel, modulation type} tuples + * that have been used during the testcase run. + * \param txParams spectrum signal parameters set by transmitter + */ + void StoreDistinctTuple (std::string context, Ptr txParams); + /** + * Triggers the arrival of a burst of 1000 Byte-long packets in the source device + * \param numPackets number of packets in burst (maximum: 255) + * \param sourceDevice pointer to the source NetDevice + * \param destination address of the destination device + */ + void SendPacketBurst (uint8_t numPackets, Ptr sourceDevice, Address& destination) const; +}; + +Bug2483TestCase::Bug2483TestCase () + : TestCase ("Test case for Bug 2483") +{ +} + +Bug2483TestCase::~Bug2483TestCase () +{ +} + +void +Bug2483TestCase::StoreDistinctTuple (std::string context, Ptr txParams) +{ + // Extract starting frequency and number of subbands + Ptr c = txParams->psd->GetSpectrumModel (); + uint32_t numBands = c->GetNumBands (); + double startingFreq = c->Begin ()->fl; + + // Get channel bandwidth and modulation class + Ptr wifiTxParams = DynamicCast (txParams); + Ptr packet = wifiTxParams->packet->Copy (); + WifiPhyTag tag; + if (!packet->RemovePacketTag (tag)) + { + NS_FATAL_ERROR ("Received Wi-Fi Signal with no WifiPhyTag"); + return; + } + WifiTxVector txVector = tag.GetWifiTxVector (); + uint8_t channelWidth = txVector.GetChannelWidth (); + WifiModulationClass modulationClass = txVector.GetMode ().GetModulationClass (); + + // Build a tuple and check if seen before (if so store it) + FreqWidthSubbandModulationTuple tupleForCurrentTx = std::make_tuple (startingFreq, channelWidth, + numBands, modulationClass); + bool found = false; + for (std::vector::const_iterator it = m_distinctTuples.begin (); it != m_distinctTuples.end (); it++) + { + if (*it == tupleForCurrentTx) + { + found = true; + } + } + if (!found) + { + m_distinctTuples.push_back (tupleForCurrentTx); + } +} + +void +Bug2483TestCase::SendPacketBurst (uint8_t numPackets, Ptr sourceDevice, + Address& destination) const +{ + for (uint8_t i = 0; i < numPackets; i++) + { + Ptr pkt = Create (1000); // 1000 dummy bytes of data + sourceDevice->Send (pkt, destination, 0); + } +} + +void +Bug2483TestCase::DoRun (void) +{ + Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("500")); // so as to force RTS/CTS for data frames + Config::SetDefault ("ns3::WifiPhy::CcaMode1Threshold", DoubleValue (-62.0)); + + uint8_t channelWidth = 40; // at least 40 MHz expected here + + NodeContainer wifiStaNode; + wifiStaNode.Create (1); + + NodeContainer wifiApNode; + wifiApNode.Create (1); + + SpectrumWifiPhyHelper spectrumPhy = SpectrumWifiPhyHelper::Default (); + Ptr spectrumChannel = CreateObject (); + Ptr lossModel = CreateObject (); + lossModel->SetFrequency (5.180e9); + spectrumChannel->AddPropagationLossModel (lossModel); + + Ptr delayModel + = CreateObject (); + spectrumChannel->SetPropagationDelayModel (delayModel); + + spectrumPhy.SetChannel (spectrumChannel); + spectrumPhy.SetErrorRateModel ("ns3::NistErrorRateModel"); + spectrumPhy.Set ("Frequency", UintegerValue (5180)); + spectrumPhy.Set ("ChannelWidth", UintegerValue (channelWidth)); + spectrumPhy.Set ("TxPowerStart", DoubleValue (10)); + spectrumPhy.Set ("TxPowerEnd", DoubleValue (10)); + + WifiHelper wifi; + wifi.SetStandard (WIFI_PHY_STANDARD_80211ac); + wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", + "DataMode", StringValue ("VhtMcs8"), + "ControlMode", StringValue ("VhtMcs8")); + + WifiMacHelper mac; + mac.SetType ("ns3::StaWifiMac"); + NetDeviceContainer staDevice; + staDevice = wifi.Install (spectrumPhy, mac, wifiStaNode); + + mac.SetType ("ns3::ApWifiMac"); + NetDeviceContainer apDevice; + apDevice = wifi.Install (spectrumPhy, mac, wifiApNode); + + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (1.0, 0.0, 0.0)); // put close enough in order to use MCS + mobility.SetPositionAllocator (positionAlloc); + + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (wifiApNode); + mobility.Install (wifiStaNode); + + // Send two 5 packet-bursts + Simulator::Schedule (Seconds (0.5), &Bug2483TestCase::SendPacketBurst, this, 5, apDevice.Get (0), staDevice.Get (0)->GetAddress ()); + Simulator::Schedule (Seconds (0.6), &Bug2483TestCase::SendPacketBurst, this, 5, apDevice.Get (0), staDevice.Get (0)->GetAddress ()); + + Config::Connect ("/ChannelList/*/$ns3::MultiModelSpectrumChannel/TxSigParams", MakeCallback (&Bug2483TestCase::StoreDistinctTuple, this)); + + Simulator::Stop (Seconds (0.8)); + Simulator::Run (); + + Simulator::Destroy (); + + // {starting frequency, channelWidth, Number of subbands in SpectrumModel, modulation type} tuples + uint8_t numberTuples = m_distinctTuples.size (); + NS_TEST_ASSERT_MSG_EQ (numberTuples, 2, "Only two distinct tuples expected"); + NS_TEST_ASSERT_MSG_EQ (std::get<0> (m_distinctTuples[0]), std::get<0> (m_distinctTuples[1]), "Both tuples should have same starting frequency"); + // Note that the first tuple should the one initiated by the beacon, i.e. legacy OFDM (20 MHz) + NS_TEST_ASSERT_MSG_EQ (std::get<1> (m_distinctTuples[0]), 20, "First tuple's channel width should be 20 MHz"); + NS_TEST_ASSERT_MSG_EQ (std::get<2> (m_distinctTuples[0]), 129, "First tuple should have 129 subbands (64+DC, 20MHz+DC, inband and 32*2 out-of-band, 10MHz on each side)"); + NS_TEST_ASSERT_MSG_EQ (std::get<3> (m_distinctTuples[0]), WifiModulationClass::WIFI_MOD_CLASS_OFDM, "First tuple should be OFDM"); + // Second tuple + NS_TEST_ASSERT_MSG_EQ (std::get<1> (m_distinctTuples[1]), channelWidth, "Second tuple's channel width should be 40 MHz"); + NS_TEST_ASSERT_MSG_EQ (std::get<2> (m_distinctTuples[1]), 193, "Second tuple should have 193 subbands (128+DC, 40MHz+DC, inband and 32*2 out-of-band, 10MHz on each side)"); + NS_TEST_ASSERT_MSG_EQ (std::get<3> (m_distinctTuples[1]), WifiModulationClass::WIFI_MOD_CLASS_VHT, "Second tuple should be VHT_OFDM"); +} + /** * \ingroup wifi-test * \ingroup tests @@ -1176,6 +1364,7 @@ WifiTestSuite::WifiTestSuite () AddTestCase (new Bug730TestCase, TestCase::QUICK); //Bug 730 AddTestCase (new SetChannelFrequencyTest, TestCase::QUICK); AddTestCase (new Bug2222TestCase, TestCase::QUICK); //Bug 2222 + AddTestCase (new Bug2483TestCase, TestCase::QUICK); //Bug 2483 } static WifiTestSuite g_wifiTestSuite; ///< the test suite