wifi: Get all the 20 MHz channel indices in a given primary or secondary channel

This commit is contained in:
Stefano Avallone
2021-04-02 11:24:18 +02:00
committed by Stefano Avallone
parent d7c4c676f5
commit 258920c0d6
3 changed files with 229 additions and 0 deletions

View File

@@ -449,4 +449,67 @@ WifiPhyOperatingChannel::GetPrimaryChannelNumber (uint16_t primaryChannelWid
return std::get<0> (*primaryChanIt);
}
std::set<uint8_t>
WifiPhyOperatingChannel::GetAll20MHzChannelIndicesInPrimary (uint16_t width) const
{
if (width > GetWidth ())
{
// a primary channel of the given width does not exist
return {};
}
uint16_t currWidth = 20; // MHz
std::set<uint8_t> indices;
indices.insert (m_primary20Index);
while (currWidth < width)
{
indices.merge (GetAll20MHzChannelIndicesInSecondary (indices));
currWidth <<= 1;
}
return indices;
}
std::set<uint8_t>
WifiPhyOperatingChannel::GetAll20MHzChannelIndicesInSecondary (uint16_t width) const
{
return GetAll20MHzChannelIndicesInSecondary (GetAll20MHzChannelIndicesInPrimary (width));
}
std::set<uint8_t>
WifiPhyOperatingChannel::GetAll20MHzChannelIndicesInSecondary (const std::set<uint8_t>& primaryIndices) const
{
if (primaryIndices.empty () || GetWidth () == 20)
{
return {};
}
uint8_t size = 1;
uint16_t primaryWidth = 20; // MHz
// find the width of the primary channel corresponding to the size of the given set
while (size != primaryIndices.size ())
{
size <<= 1;
primaryWidth <<= 1;
if (primaryWidth >= GetWidth ())
{
// the width of the primary channel resulting from the given indices
// exceeds the width of the operating channel
return {};
}
}
std::set<uint8_t> secondaryIndices;
for (const auto& index : primaryIndices)
{
secondaryIndices.insert (index ^ size);
}
return secondaryIndices;
}
} //namespace ns3

View File

@@ -138,6 +138,41 @@ public:
*/
uint16_t GetPrimaryChannelCenterFrequency (uint16_t primaryChannelWidth) const;
/**
* Get the channel indices of all the 20 MHz channels included in the primary
* channel of the given width, if such primary channel exists, or an empty set,
* otherwise.
*
* \param width the width in MHz of the primary channel
* \return the channel indices of all the 20 MHz channels included in the primary
* channel of the given width, if such primary channel exists, or an empty set,
* otherwise
*/
std::set<uint8_t> GetAll20MHzChannelIndicesInPrimary (uint16_t width) const;
/**
* Get the channel indices of all the 20 MHz channels included in the secondary
* channel of the given width, if such secondary channel exists, or an empty set,
* otherwise.
*
* \param width the width in MHz of the secondary channel
* \return the channel indices of all the 20 MHz channels included in the secondary
* channel of the given width, if such secondary channel exists, or an empty set,
* otherwise
*/
std::set<uint8_t> GetAll20MHzChannelIndicesInSecondary (uint16_t width) const;
/**
* Get the channel indices of all the 20 MHz channels included in the secondary
* channel corresponding to the given primary channel, if such secondary channel
* exists, or an empty set, otherwise.
*
* \param primaryIndices the channel indices of all the 20 MHz channels included
* in the primary channel
* \return the channel indices of all the 20 MHz channels included in the secondary
* channel corresponding to the given primary channel, if such secondary channel
* exists, or an empty set, otherwise
*/
std::set<uint8_t> GetAll20MHzChannelIndicesInSecondary (const std::set<uint8_t>& primaryIndices) const;
/// Typedef for a const iterator pointing to a channel in the set of available channels
typedef std::set<FrequencyChannelInfo>::const_iterator ConstIterator;

View File

@@ -1015,6 +1015,136 @@ WifiPrimaryChannelsTest::CheckReceivedTriggerFrames (std::set<uint8_t> txBss, ui
}
/**
* \ingroup wifi-test
* \ingroup tests
*
* \brief Test functions returning the indices of primary and secondary channels
* of different width.
*/
class Wifi20MHzChannelIndicesTest : public TestCase
{
public:
/**
* Constructor
*/
Wifi20MHzChannelIndicesTest ();
virtual ~Wifi20MHzChannelIndicesTest () = default;
/**
* Check that the indices of the 20 MHz channels included in all the primary
* and secondary channels are correct when setting the given primary20 channel.
*
* \param primary20 the index of the primary20 channel to configure
* \param secondary20 the expected index of the secondary20 channel
* \param primary40 the expected indices of the 20 MHz channels in the primary40 channel
* \param secondary40 the expected indices of the 20 MHz channels in the secondary40 channel
* \param primary80 the expected indices of the 20 MHz channels in the primary80 channel
* \param secondary80 the expected indices of the 20 MHz channels in the secondary80 channel
*/
void RunOne (uint8_t primary20, const std::set<uint8_t>& secondary20,
const std::set<uint8_t>& primary40, const std::set<uint8_t>& secondary40,
const std::set<uint8_t>& primary80, const std::set<uint8_t>& secondary80);
private:
void DoRun (void) override;
WifiPhyOperatingChannel m_channel; //!< operating channel
};
Wifi20MHzChannelIndicesTest::Wifi20MHzChannelIndicesTest ()
: TestCase ("Check computation of primary and secondary channel indices")
{
}
void
Wifi20MHzChannelIndicesTest::RunOne (uint8_t primary20,
const std::set<uint8_t>& secondary20,
const std::set<uint8_t>& primary40,
const std::set<uint8_t>& secondary40,
const std::set<uint8_t>& primary80,
const std::set<uint8_t>& secondary80)
{
auto printToStr = [](const std::set<uint8_t>& s)
{
std::stringstream ss;
ss << "{";
for (const auto& index : s) ss << +index << " ";
ss << "}";
return ss.str ();
};
m_channel.SetPrimary20Index (primary20);
auto actualPrimary20 = m_channel.GetAll20MHzChannelIndicesInPrimary (20);
NS_TEST_ASSERT_MSG_EQ ((actualPrimary20 == std::set<uint8_t> {primary20}),
true,
"Expected Primary20 {" << +primary20 << "}"
<< " differs from actual " << printToStr (actualPrimary20));
auto actualSecondary20 = m_channel.GetAll20MHzChannelIndicesInSecondary (actualPrimary20);
NS_TEST_ASSERT_MSG_EQ ((actualSecondary20 == secondary20),
true,
"Expected Secondary20 " << printToStr (secondary20)
<< " differs from actual " << printToStr (actualSecondary20));
auto actualPrimary40 = m_channel.GetAll20MHzChannelIndicesInPrimary (40);
NS_TEST_ASSERT_MSG_EQ ((actualPrimary40 == primary40),
true,
"Expected Primary40 " << printToStr (primary40)
<< " differs from actual " << printToStr (actualPrimary40));
auto actualSecondary40 = m_channel.GetAll20MHzChannelIndicesInSecondary (primary40);
NS_TEST_ASSERT_MSG_EQ ((actualSecondary40 == secondary40),
true,
"Expected Secondary40 " << printToStr (secondary40)
<< " differs from actual " << printToStr (actualSecondary40));
auto actualPrimary80 = m_channel.GetAll20MHzChannelIndicesInPrimary (80);
NS_TEST_ASSERT_MSG_EQ ((actualPrimary80 == primary80),
true,
"Expected Primary80 " << printToStr (primary80)
<< " differs from actual " << printToStr (actualPrimary80));
auto actualSecondary80 = m_channel.GetAll20MHzChannelIndicesInSecondary (primary80);
NS_TEST_ASSERT_MSG_EQ ((actualSecondary80 == secondary80),
true,
"Expected Secondary80 " << printToStr (secondary80)
<< " differs from actual " << printToStr (actualSecondary80));
}
void
Wifi20MHzChannelIndicesTest::DoRun ()
{
/* 20 MHz channel */
m_channel.SetDefault (20, WIFI_STANDARD_80211ax, WIFI_PHY_BAND_5GHZ);
RunOne (0, {}, {}, {}, {}, {});
/* 40 MHz channel */
m_channel.SetDefault (40, WIFI_STANDARD_80211ax, WIFI_PHY_BAND_5GHZ);
RunOne (0, {1}, {0, 1}, {}, {}, {});
RunOne (1, {0}, {0, 1}, {}, {}, {});
/* 80 MHz channel */
m_channel.SetDefault (80, WIFI_STANDARD_80211ax, WIFI_PHY_BAND_5GHZ);
RunOne (0, {1}, {0, 1}, {2, 3}, {0, 1, 2, 3}, {});
RunOne (1, {0}, {0, 1}, {2, 3}, {0, 1, 2, 3}, {});
RunOne (2, {3}, {2, 3}, {0, 1}, {0, 1, 2, 3}, {});
RunOne (3, {2}, {2, 3}, {0, 1}, {0, 1, 2, 3}, {});
/* 160 MHz channel */
m_channel.SetDefault (160, WIFI_STANDARD_80211ax, WIFI_PHY_BAND_5GHZ);
RunOne (0, {1}, {0, 1}, {2, 3}, {0, 1, 2, 3}, {4, 5, 6, 7});
RunOne (1, {0}, {0, 1}, {2, 3}, {0, 1, 2, 3}, {4, 5, 6, 7});
RunOne (2, {3}, {2, 3}, {0, 1}, {0, 1, 2, 3}, {4, 5, 6, 7});
RunOne (3, {2}, {2, 3}, {0, 1}, {0, 1, 2, 3}, {4, 5, 6, 7});
RunOne (4, {5}, {4, 5}, {6, 7}, {4, 5, 6, 7}, {0, 1, 2, 3});
RunOne (5, {4}, {4, 5}, {6, 7}, {4, 5, 6, 7}, {0, 1, 2, 3});
RunOne (6, {7}, {6, 7}, {4, 5}, {4, 5, 6, 7}, {0, 1, 2, 3});
RunOne (7, {6}, {6, 7}, {4, 5}, {4, 5, 6, 7}, {0, 1, 2, 3});
}
/**
* \ingroup wifi-test
* \ingroup tests
@@ -1037,6 +1167,7 @@ WifiPrimaryChannelsTestSuite::WifiPrimaryChannelsTestSuite ()
AddTestCase (new WifiPrimaryChannelsTest (80, false), TestCase::EXTENSIVE);
AddTestCase (new WifiPrimaryChannelsTest (160, true), TestCase::TAKES_FOREVER);
AddTestCase (new WifiPrimaryChannelsTest (160, false), TestCase::TAKES_FOREVER);
AddTestCase (new Wifi20MHzChannelIndicesTest (), TestCase::QUICK);
}
static WifiPrimaryChannelsTestSuite g_wifiPrimaryChannelsTestSuite; ///< the test suite