wifi: Transmit Ack, BlockAck, BlockAckReq as non-HT dup if appropriate
This commit is contained in:
@@ -32,6 +32,7 @@ This file is a best-effort approach to solving this issue; we will do our best b
|
||||
|
||||
* (docs) Models documentation format guidelines have been updated.
|
||||
* (zigbee) Adjust pedantic link cost requirement in ``NeighborTable::LookUpForBestParent``, a minimum link cost of 3 is not required now.
|
||||
* (wifi) Normal Ack, BlockAck and BlockAckReq frames are transmitted, if appropriate, as non-HT duplicate PPDUs on a bandwidth matching that of the data frame transmitted in the same frame exchange sequence.
|
||||
|
||||
## Changes from ns-3.43 to ns-3.44
|
||||
|
||||
|
||||
@@ -702,6 +702,32 @@ WifiRemoteStationManager::GetCtsToSelfTxVector()
|
||||
false);
|
||||
}
|
||||
|
||||
void
|
||||
WifiRemoteStationManager::AdjustTxVectorForCtlResponse(WifiTxVector& txVector,
|
||||
MHz_u allowedWidth) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this << txVector << allowedWidth);
|
||||
|
||||
auto modulation = txVector.GetModulationClass();
|
||||
|
||||
if (allowedWidth >= 40 &&
|
||||
(modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS))
|
||||
{
|
||||
// control frame must be sent in a non-HT duplicate PPDU because it must protect a frame
|
||||
// being transmitted on at least 40 MHz. Change the modulation class to ERP-OFDM and the
|
||||
// rate to 6 Mbps
|
||||
txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate6Mbps());
|
||||
modulation = txVector.GetModulationClass();
|
||||
}
|
||||
// do not set allowedWidth as the TX width if the modulation class is (HR-)DSSS (allowedWidth
|
||||
// may be 20 MHz) or allowedWidth is 22 MHz (the selected modulation class may be OFDM)
|
||||
if (modulation != WIFI_MOD_CLASS_DSSS && modulation != WIFI_MOD_CLASS_HR_DSSS &&
|
||||
allowedWidth != 22)
|
||||
{
|
||||
txVector.SetChannelWidth(allowedWidth);
|
||||
}
|
||||
}
|
||||
|
||||
WifiTxVector
|
||||
WifiRemoteStationManager::GetRtsTxVector(Mac48Address address, MHz_u allowedWidth)
|
||||
{
|
||||
@@ -724,24 +750,8 @@ WifiRemoteStationManager::GetRtsTxVector(Mac48Address address, MHz_u allowedWidt
|
||||
{
|
||||
v = DoGetRtsTxVector(Lookup(address));
|
||||
}
|
||||
auto modulation = v.GetModulationClass();
|
||||
|
||||
if (allowedWidth >= 40 &&
|
||||
(modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS))
|
||||
{
|
||||
// RTS must be sent in a non-HT duplicate PPDU because it must protect a frame being
|
||||
// transmitted on at least 40 MHz. Change the modulation class to ERP-OFDM and the rate
|
||||
// to 6 Mbps
|
||||
v.SetMode(ErpOfdmPhy::GetErpOfdmRate6Mbps());
|
||||
modulation = v.GetModulationClass();
|
||||
}
|
||||
// do not set allowedWidth as the TX width if the modulation class is (HR-)DSSS (allowedWidth
|
||||
// may be >= 40 MHz) or allowedWidth is 22 MHz (the selected modulation class may be OFDM)
|
||||
if (modulation != WIFI_MOD_CLASS_DSSS && modulation != WIFI_MOD_CLASS_HR_DSSS &&
|
||||
allowedWidth != 22)
|
||||
{
|
||||
v.SetChannelWidth(allowedWidth);
|
||||
}
|
||||
AdjustTxVectorForCtlResponse(v, allowedWidth);
|
||||
|
||||
return v;
|
||||
}
|
||||
@@ -810,6 +820,9 @@ WifiRemoteStationManager::GetAckTxVector(Mac48Address to, const WifiTxVector& da
|
||||
v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(ackMode));
|
||||
v.SetGuardInterval(GetGuardIntervalForMode(ackMode, m_wifiPhy->GetDevice()));
|
||||
v.SetNss(1);
|
||||
|
||||
AdjustTxVectorForCtlResponse(v, dataTxVector.GetChannelWidth());
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -827,6 +840,9 @@ WifiRemoteStationManager::GetBlockAckTxVector(Mac48Address to,
|
||||
v.SetChannelWidth(m_wifiPhy->GetTxBandwidth(blockAckMode));
|
||||
v.SetGuardInterval(GetGuardIntervalForMode(blockAckMode, m_wifiPhy->GetDevice()));
|
||||
v.SetNss(1);
|
||||
|
||||
AdjustTxVectorForCtlResponse(v, dataTxVector.GetChannelWidth());
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@@ -889,6 +889,16 @@ class WifiRemoteStationManager : public Object
|
||||
* transmission of the data packet itself.
|
||||
*/
|
||||
WifiTxVector GetCtsToSelfTxVector();
|
||||
/**
|
||||
* Adjust the TXVECTOR for a control response frame to ensure that, if appropriate, the non-HT
|
||||
* duplicate format is used and the TX width matches that of the data frame transmitted (in case
|
||||
* of, e.g., Ack or BlockAck) or to transmit (in case of, e.g., RTS or BlockAckReq) in the same
|
||||
* frame exchange sequence.
|
||||
*
|
||||
* @param txVector the TXVECTOR to adjust
|
||||
* @param allowedWidth the allowed width for the data frame in the same frame exchange sequence
|
||||
*/
|
||||
void AdjustTxVectorForCtlResponse(WifiTxVector& txVector, MHz_u allowedWidth) const;
|
||||
/**
|
||||
* Adjust the TXVECTOR for an initial Control frame to ensure that the modulation class
|
||||
* is non-HT and the rate is 6 Mbps, 12 Mbps or 24 Mbps.
|
||||
|
||||
@@ -66,6 +66,11 @@ NS_LOG_COMPONENT_DEFINE("WifiRetransmitTest");
|
||||
*
|
||||
* In case of multi-link devices, the first TXOP is carried out on link 0 and the second TXOP on
|
||||
* link 1. It is checked that QSRC and CW are updated on the link on which the TXOP is carried out.
|
||||
*
|
||||
* The TX width of transmitted frames is also checked, considering that the AP operates on a
|
||||
* 160 MHz channel and the non-AP STA does not support 160 MHz operations (hence the AP will use
|
||||
* its primary80 channel to transmit to the non-AP STA). In case of multi-link devices, the second
|
||||
* link is operated on a 40 MHz channel.
|
||||
*/
|
||||
class WifiRetransmitTest : public TestCase
|
||||
{
|
||||
@@ -190,12 +195,12 @@ WifiRetransmitTest::DoSetup()
|
||||
|
||||
SpectrumWifiPhyHelper phy(m_nLinks);
|
||||
phy.SetChannel(CreateObject<MultiModelSpectrumChannel>());
|
||||
// use default 20 MHz channel in 5 GHz band
|
||||
phy.Set(0, "ChannelSettings", StringValue("{0, 20, BAND_5GHZ, 0}"));
|
||||
// use default 80 MHz channel in 5 GHz band for the non-AP STA
|
||||
phy.Set(0, "ChannelSettings", StringValue("{0, 80, BAND_5GHZ, 0}"));
|
||||
if (m_nLinks > 1)
|
||||
{
|
||||
// use default 20 MHz channel in 6 GHz band
|
||||
phy.Set(1, "ChannelSettings", StringValue("{0, 20, BAND_6GHZ, 0}"));
|
||||
// use default 40 MHz channel in 6 GHz band
|
||||
phy.Set(1, "ChannelSettings", StringValue("{0, 40, BAND_6GHZ, 0}"));
|
||||
}
|
||||
|
||||
Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold",
|
||||
@@ -209,6 +214,7 @@ WifiRetransmitTest::DoSetup()
|
||||
|
||||
WifiHelper wifi;
|
||||
wifi.SetStandard(m_nLinks == 1 ? WIFI_STANDARD_80211ax : WIFI_STANDARD_80211be);
|
||||
wifi.ConfigVhtOptions("Support160MHzOperation", BooleanValue(false));
|
||||
wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
|
||||
"DataMode",
|
||||
WifiModeValue(HePhy::GetHeMcs8()),
|
||||
@@ -221,6 +227,10 @@ WifiRetransmitTest::DoSetup()
|
||||
NetDeviceContainer staDevice = wifi.Install(phy, mac, wifiStaNode);
|
||||
m_staMac = StaticCast<StaWifiMac>(StaticCast<WifiNetDevice>(staDevice.Get(0))->GetMac());
|
||||
|
||||
wifi.ConfigVhtOptions("Support160MHzOperation", BooleanValue(true));
|
||||
// use default 160 MHz channel in 5 GHz band for the AP
|
||||
phy.Set(0, "ChannelSettings", StringValue("{0, 160, BAND_5GHZ, 0}"));
|
||||
|
||||
mac.SetType("ns3::ApWifiMac");
|
||||
mac.SetEdca(AC_BE,
|
||||
"TxopLimits",
|
||||
@@ -383,6 +393,16 @@ WifiRetransmitTest::Transmit(uint8_t phyId,
|
||||
return;
|
||||
}
|
||||
|
||||
// check width of transmitted frames, except CTS because we do not support yet static/dynamic
|
||||
// bandwidth operation
|
||||
const auto expectedWidth = (phyId == 0 ? 80 : 40);
|
||||
if (!hdr.IsCts())
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ(txVector.GetChannelWidth(),
|
||||
expectedWidth,
|
||||
"Unexpected width for " << hdr.GetTypeString());
|
||||
}
|
||||
|
||||
if (m_eventIt != m_events.cend())
|
||||
{
|
||||
// check that the expected frame is being transmitted
|
||||
@@ -654,7 +674,7 @@ WifiRetransmitTest::DoRun()
|
||||
m_staMac->GetDevice()->GetNode(),
|
||||
GetApplication(2, m_pktSize));
|
||||
|
||||
Simulator::Stop(Seconds(1));
|
||||
Simulator::Stop(Seconds(0.550));
|
||||
Simulator::Run();
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ((m_eventIt == m_events.cend()), true, "Not all events took place");
|
||||
|
||||
@@ -1508,7 +1508,7 @@ Bug2222TestCase::DoRun()
|
||||
*
|
||||
* 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
|
||||
* to ensure that only 3 {starting frequency, channelWidth, Number of subbands
|
||||
* in SpectrumModel, modulation type} tuples are used.
|
||||
*
|
||||
* See \bugid{2843}
|
||||
@@ -1688,33 +1688,48 @@ Bug2843TestCase::DoRun()
|
||||
// {starting frequency, channelWidth, Number of subbands in SpectrumModel, modulation type}
|
||||
// tuples
|
||||
std::size_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]) - Hz_u{20e6},
|
||||
NS_TEST_ASSERT_MSG_EQ(numberTuples, 3, "Only three distinct tuples expected");
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<0>(m_distinctTuples[0]) - Hz_u{20e6},
|
||||
std::get<0>(m_distinctTuples[1]),
|
||||
"The starting frequency of the first tuple should be shifted 20 MHz to "
|
||||
"the right wrt second tuple");
|
||||
// Note that the first tuple should the one initiated by the beacon, i.e. non-HT OFDM (20 MHz)
|
||||
NS_TEST_ASSERT_MSG_EQ(std::get<1>(m_distinctTuples[0]),
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<1>(m_distinctTuples[0]),
|
||||
MHz_u{20},
|
||||
"First tuple's channel width should be 20 MHz");
|
||||
NS_TEST_ASSERT_MSG_EQ(std::get<2>(m_distinctTuples[0]),
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<2>(m_distinctTuples[0]),
|
||||
193,
|
||||
"First tuple should have 193 subbands (64+DC, 20MHz+DC, inband and 64*2 "
|
||||
"out-of-band, 20MHz on each side)");
|
||||
NS_TEST_ASSERT_MSG_EQ(std::get<3>(m_distinctTuples[0]),
|
||||
NS_TEST_EXPECT_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]),
|
||||
// Second tuple: data frames, VHT (40 MHz)
|
||||
NS_TEST_EXPECT_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]),
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<2>(m_distinctTuples[1]),
|
||||
385,
|
||||
"Second tuple should have 385 subbands (128+DC, 40MHz+DC, inband and "
|
||||
"128*2 out-of-band, 40MHz on each side)");
|
||||
NS_TEST_ASSERT_MSG_EQ(std::get<3>(m_distinctTuples[1]),
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<3>(m_distinctTuples[1]),
|
||||
WifiModulationClass::WIFI_MOD_CLASS_VHT,
|
||||
"Second tuple should be VHT_OFDM");
|
||||
// Third tuple: control response frames, non-HT (OFDM) duplicate (40 MHz)
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<0>(m_distinctTuples[1]),
|
||||
std::get<0>(m_distinctTuples[2]),
|
||||
"The starting frequency of the third tuple should be the same as the "
|
||||
"second tuple");
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<1>(m_distinctTuples[2]),
|
||||
channelWidth,
|
||||
"Third tuple's channel width should be 40 MHz");
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<2>(m_distinctTuples[2]),
|
||||
385,
|
||||
"Third tuple should have 385 subbands (128+DC, 40MHz+DC, inband and "
|
||||
"128*2 out-of-band, 40MHz on each side)");
|
||||
NS_TEST_EXPECT_MSG_EQ(std::get<3>(m_distinctTuples[2]),
|
||||
WifiModulationClass::WIFI_MOD_CLASS_OFDM,
|
||||
"Third tuple should be OFDM");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user