wifi: Compute correct HE-SIG-B duration for HE MU

This commit is contained in:
Rediet
2019-06-25 09:57:38 +02:00
committed by Sébastien Deronne
parent f4093b3097
commit fb875b768c
2 changed files with 163 additions and 7 deletions

View File

@@ -2054,12 +2054,59 @@ WifiPhy::GetPhySigA2Duration (WifiPreamble preamble)
Time
WifiPhy::GetPhySigBDuration (WifiTxVector txVector)
{
switch (txVector.GetPreambleType ())
if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_MU) //See section 27.3.10.8 of IEEE 802.11ax draft 4.0.
{
/*
* Compute the number of bits used by common field.
* Assume that compression bit in HE-SIG-A is not set (i.e. not
* full band MU-MIMO); the field is present.
*/
uint16_t bw = txVector.GetChannelWidth ();
std::size_t commonFieldSize = 4 /* CRC */ + 6 /* tail */;
if (bw <= 40)
{
commonFieldSize += 8; //only one allocation subfield
}
else
{
commonFieldSize += 8 * (bw / 40) /* one allocation field per 40 MHz */ + 1 /* center RU */;
}
/*
* Compute the number of bits used by user-specific field.
* MU-MIMO is not supported; only one station per RU.
* The user-specific field is composed of N user block fields
* spread over each corresponding HE-SIG-B content channel.
* Each user block field contains either two or one users' data
* (the latter being for odd number of stations per content channel).
* Padding will be handled further down in the code.
*/
std::pair<std::size_t, std::size_t> numStaPerContentChannel = txVector.GetNumRusPerHeSigBContentChannel ();
std::size_t maxNumStaPerContentChannel = std::max (numStaPerContentChannel.first, numStaPerContentChannel.second);
std::size_t maxNumUserBlockFields = maxNumStaPerContentChannel / 2; //handle last user block with single user, if any, further down
std::size_t userSpecificFieldSize = maxNumUserBlockFields * (2 * 21 /* user fields (2 users) */ + 4 /* tail */ + 6 /* CRC */);
if (maxNumStaPerContentChannel % 2 != 0)
{
userSpecificFieldSize += 21 /* last user field */ + 4 /* CRC */ + 6 /* tail */;
}
/*
* Compute duration of HE-SIG-B considering that padding
* is added up to the next OFDM symbol.
* Nss = 1 and GI = 800 ns for HE-SIG-B.
*/
Time symbolDuration = MicroSeconds (4);
double numDataBitsPerSymbol = GetHeSigBMode (txVector).GetDataRate (20, 800, 1) * symbolDuration.GetNanoSeconds () / 1e9;
double numSymbols = ceil ((commonFieldSize + userSpecificFieldSize) / numDataBitsPerSymbol);
return FemtoSeconds (static_cast<uint64_t> (numSymbols * symbolDuration.GetFemtoSeconds ()));
}
else if (txVector.GetPreambleType () == WIFI_PREAMBLE_VHT_MU)
{
case WIFI_PREAMBLE_VHT_MU:
case WIFI_PREAMBLE_HE_MU:
return MicroSeconds (4);
default:
}
else
{
// no SIG-B
return MicroSeconds (0);
}

View File

@@ -554,23 +554,131 @@ TxDurationTest::DoRun (void)
1536},
std::list<HeMuUserInfo> { {{true, HeRu::RU_242_TONE, 1}, WifiPhy::GetHeMcs0 (), 1},
{{true, HeRu::RU_242_TONE, 2}, WifiPhy::GetHeMcs0 (), 1} },
40, 800, NanoSeconds (1489600)) //equivalent to HE_SU for 20 MHz with extra HE-SIG-B (i.e. 4 us)
40, 800, NanoSeconds (1493600)) //equivalent to HE_SU for 20 MHz with 2 extra HE-SIG-B (i.e. 8 us)
&& CheckHeMuTxDuration (std::list<uint32_t> {1536,
1536},
std::list<HeMuUserInfo> { {{true, HeRu::RU_242_TONE, 1}, WifiPhy::GetHeMcs1 (), 1},
{{true, HeRu::RU_242_TONE, 2}, WifiPhy::GetHeMcs0 (), 1} },
40, 800, NanoSeconds (1489600)) //shouldn't change if first PSDU is shorter
40, 800, NanoSeconds (1493600)) //shouldn't change if first PSDU is shorter
&& CheckHeMuTxDuration (std::list<uint32_t> {1536,
76},
std::list<HeMuUserInfo> { {{true, HeRu::RU_242_TONE, 1}, WifiPhy::GetHeMcs0 (), 1},
{{true, HeRu::RU_242_TONE, 2}, WifiPhy::GetHeMcs0 (), 1} },
40, 800, NanoSeconds (1489600));
40, 800, NanoSeconds (1493600));
NS_TEST_EXPECT_MSG_EQ (retval, true, "an 802.11ax MU duration failed");
Simulator::Destroy ();
}
/**
* \ingroup wifi-test
* \ingroup tests
*
* \brief HE-SIG-B duration test
*/
class HeSigBDurationTest : public TestCase
{
public:
HeSigBDurationTest ();
virtual ~HeSigBDurationTest ();
virtual void DoRun (void);
private:
/**
* Build a TXVECTOR for HE MU with the given bandwith and user informations.
*
* \param bw the channel width of the PPDU in MHz
* \param userInfos the list of HE MU specific user transmission parameters
*
* \return the configured HE MU TXVECTOR
*/
static WifiTxVector BuildTxVector (uint16_t bw, std::list <HeMuUserInfo> userInfos);
};
HeSigBDurationTest::HeSigBDurationTest ()
: TestCase ("Check HE-SIG-B duration computation")
{
}
HeSigBDurationTest::~HeSigBDurationTest ()
{
}
WifiTxVector
HeSigBDurationTest::BuildTxVector (uint16_t bw, std::list <HeMuUserInfo> userInfos)
{
WifiTxVector txVector;
txVector.SetPreambleType (WIFI_PREAMBLE_HE_MU);
txVector.SetChannelWidth (bw);
txVector.SetGuardInterval (3200);
txVector.SetStbc (0);
txVector.SetNess (0);
std::list<uint16_t> staIds;
uint16_t staId = 1;
for (const auto & userInfo : userInfos)
{
txVector.SetHeMuUserInfo (staId, userInfo);
staIds.push_back (staId++);
}
return txVector;
}
void
HeSigBDurationTest::DoRun (void)
{
//20 MHz band
std::list<HeMuUserInfo> userInfos;
userInfos.push_back ({{true, HeRu::RU_106_TONE, 1}, WifiPhy::GetHeMcs11 (), 1});
userInfos.push_back ({{true, HeRu::RU_106_TONE, 2}, WifiPhy::GetHeMcs10 (), 4});
WifiTxVector txVector = BuildTxVector (20, userInfos);
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetHeSigBMode (txVector), WifiPhy::GetVhtMcs5 (), "HE-SIG-B should be sent at MCS 5");
std::pair<std::size_t, std::size_t> numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel ();
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.first, 2, "Both users should be on HE-SIG-B content channel 1");
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 0, "Both users should be on HE-SIG-B content channel 2");
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetPhySigBDuration (txVector), MicroSeconds (4), "HE-SIG-B should only last one OFDM symbol");
//40 MHz band, even number of users per HE-SIG-B content channel
userInfos.push_back ({{true, HeRu::RU_52_TONE, 5}, WifiPhy::GetHeMcs4 (), 1});
userInfos.push_back ({{true, HeRu::RU_52_TONE, 6}, WifiPhy::GetHeMcs6 (), 2});
userInfos.push_back ({{true, HeRu::RU_52_TONE, 7}, WifiPhy::GetHeMcs5 (), 3});
userInfos.push_back ({{true, HeRu::RU_52_TONE, 8}, WifiPhy::GetHeMcs6 (), 2});
txVector = BuildTxVector (40, userInfos);
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetHeSigBMode (txVector), WifiPhy::GetVhtMcs4 (), "HE-SIG-B should be sent at MCS 4");
numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel ();
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.first, 2, "Two users should be on HE-SIG-B content channel 1");
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 4, "Four users should be on HE-SIG-B content channel 2");
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetPhySigBDuration (txVector), MicroSeconds (4), "HE-SIG-B should only last one OFDM symbol");
//40 MHz band, odd number of users per HE-SIG-B content channel
userInfos.push_back ({{true, HeRu::RU_26_TONE, 13}, WifiPhy::GetHeMcs3 (), 1});
txVector = BuildTxVector (40, userInfos);
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetHeSigBMode (txVector), WifiPhy::GetVhtMcs3 (), "HE-SIG-B should be sent at MCS 3");
numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel ();
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.first, 2, "Two users should be on HE-SIG-B content channel 1");
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 5, "Five users should be on HE-SIG-B content channel 2");
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetPhySigBDuration (txVector), MicroSeconds (8), "HE-SIG-B should last two OFDM symbols");
//80 MHz band
userInfos.push_back ({{true, HeRu::RU_242_TONE, 3}, WifiPhy::GetHeMcs1 (), 1});
userInfos.push_back ({{true, HeRu::RU_242_TONE, 4}, WifiPhy::GetHeMcs4 (), 1});
txVector = BuildTxVector (80, userInfos);
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetHeSigBMode (txVector), WifiPhy::GetVhtMcs1 (), "HE-SIG-B should be sent at MCS 1");
numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel ();
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.first, 3, "Three users should be on HE-SIG-B content channel 1");
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 6, "Six users should be on HE-SIG-B content channel 2");
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetPhySigBDuration (txVector), MicroSeconds (16), "HE-SIG-B should last four OFDM symbols");
//160 MHz band
userInfos.push_back ({{false, HeRu::RU_996_TONE, 1}, WifiPhy::GetHeMcs1 (), 1});
txVector = BuildTxVector (160, userInfos);
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetHeSigBMode (txVector), WifiPhy::GetVhtMcs1 (), "HE-SIG-B should be sent at MCS 1");
numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel ();
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.first, 4, "Four users should be on HE-SIG-B content channel 1");
NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 7, "Seven users should be on HE-SIG-B content channel 2");
NS_TEST_EXPECT_MSG_EQ (WifiPhy::GetPhySigBDuration (txVector), MicroSeconds (20), "HE-SIG-B should last five OFDM symbols");
}
/**
* \ingroup wifi-test
* \ingroup tests
@@ -586,6 +694,7 @@ public:
TxDurationTestSuite::TxDurationTestSuite ()
: TestSuite ("wifi-devices-tx-duration", UNIT)
{
AddTestCase (new HeSigBDurationTest, TestCase::QUICK);
AddTestCase (new TxDurationTest, TestCase::QUICK);
}