wifi: Add TIM Information Element and tests for PS
This commit is contained in:
committed by
Stefano Avallone
parent
cc51f7a2f9
commit
fe4cd3b362
@@ -111,6 +111,7 @@ set(source_files
|
||||
model/supported-rates.cc
|
||||
model/table-based-error-rate-model.cc
|
||||
model/threshold-preamble-detection-model.cc
|
||||
model/tim.cc
|
||||
model/txop.cc
|
||||
model/vht/vht-capabilities.cc
|
||||
model/vht/vht-configuration.cc
|
||||
@@ -265,6 +266,7 @@ set(header_files
|
||||
model/supported-rates.h
|
||||
model/table-based-error-rate-model.h
|
||||
model/threshold-preamble-detection-model.h
|
||||
model/tim.h
|
||||
model/txop.h
|
||||
model/vht/vht-capabilities.h
|
||||
model/vht/vht-configuration.h
|
||||
@@ -333,6 +335,7 @@ build_lib(
|
||||
test/channel-access-manager-test.cc
|
||||
test/inter-bss-test-suite.cc
|
||||
test/power-rate-adaptation-test.cc
|
||||
test/power-save-test.cc
|
||||
test/spectrum-wifi-phy-test.cc
|
||||
test/tx-duration-test.cc
|
||||
test/wifi-aggregation-test.cc
|
||||
|
||||
231
src/wifi/model/tim.cc
Normal file
231
src/wifi/model/tim.cc
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Davide Magrin <davide@magr.in>
|
||||
*/
|
||||
|
||||
#include "tim.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
WifiInformationElementId
|
||||
Tim::ElementId() const
|
||||
{
|
||||
return IE_TIM;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Tim::GetInformationFieldSize() const
|
||||
{
|
||||
// When the TIM is carried in a non-S1G PPDU, in the event that all bits other than bit 0 in
|
||||
// the traffic indication virtual bitmap are 0, the Partial Virtual Bitmap field is encoded as
|
||||
// a single octet equal to 0, the Bitmap Offset subfield is 0, and the Length field is 4.
|
||||
// (Sec. 9.4.2.5.1 of 802.11-2020)
|
||||
// The size of the information field is the size of the Partial Virtual Bitmap field,
|
||||
// plus one octet each for the DTIM Count, DTIM Period, and Bitmap Control fields
|
||||
uint16_t partialVirtualBitmapSize =
|
||||
GetLastNonZeroOctetIndex() - GetPartialVirtualBitmapOffset() + 1;
|
||||
return partialVirtualBitmapSize + 3;
|
||||
}
|
||||
|
||||
void
|
||||
Tim::AddAid(uint16_t aid)
|
||||
{
|
||||
NS_ABORT_IF(aid > 2007);
|
||||
|
||||
m_aidValues.insert(aid);
|
||||
}
|
||||
|
||||
bool
|
||||
Tim::HasAid(uint16_t aid) const
|
||||
{
|
||||
return m_aidValues.find(aid) != m_aidValues.end();
|
||||
}
|
||||
|
||||
std::set<uint16_t>
|
||||
Tim::GetAidSet(uint16_t aid) const
|
||||
{
|
||||
auto start = m_aidValues.upper_bound(aid);
|
||||
return std::set<uint16_t>(start, m_aidValues.cend());
|
||||
}
|
||||
|
||||
void
|
||||
Tim::SerializeInformationField(Buffer::Iterator start) const
|
||||
{
|
||||
start.WriteU8(m_dtimCount);
|
||||
start.WriteU8(m_dtimPeriod);
|
||||
|
||||
// the Bitmap Control field is optional if the TIM is carried in an S1G PPDU, while
|
||||
// it is always present when the TIM is carried in a non-S1G PPDU
|
||||
start.WriteU8(GetBitmapControl());
|
||||
auto partialVirtualBitmap = GetPartialVirtualBitmap();
|
||||
for (auto byte : partialVirtualBitmap)
|
||||
{
|
||||
start.WriteU8(byte);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Tim::DeserializeInformationField(Buffer::Iterator start, uint16_t length)
|
||||
{
|
||||
NS_ABORT_MSG_IF(length < 2, "Invalid length: " << length);
|
||||
|
||||
m_dtimCount = start.ReadU8();
|
||||
m_dtimPeriod = start.ReadU8();
|
||||
|
||||
if (length == 2)
|
||||
{
|
||||
// no Bitmap Control field nor Partial Virtual Bitmap field
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Bitmap control field: here we determine the presence of multicast traffic and the offset
|
||||
auto bitmapControl = start.ReadU8();
|
||||
// Least significant bit is the Traffic Indication field
|
||||
m_hasMulticastPending = bitmapControl & 0x01;
|
||||
// Other bits are the Bitmap Offset
|
||||
uint8_t partialVirtualBitmapOffset = bitmapControl & 0xFE;
|
||||
// Next, deserialize the partial virtual bitmap
|
||||
uint16_t octetIndex;
|
||||
// length is the length of the information fields, so we need to
|
||||
// subtract 3 to get the length of the Partial Virtual Bitmap
|
||||
for (octetIndex = partialVirtualBitmapOffset;
|
||||
octetIndex < static_cast<uint16_t>(partialVirtualBitmapOffset + length - 3);
|
||||
++octetIndex)
|
||||
{
|
||||
if (auto octet = start.ReadU8(); octet > 0)
|
||||
{
|
||||
// Look for bits set to 1
|
||||
for (uint8_t position = 0; position < 8; position++)
|
||||
{
|
||||
if ((octet >> position) & 0x1)
|
||||
{
|
||||
m_aidValues.insert(GetAidFromOctetIndexAndBitPosition(octetIndex, position));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 3 + octetIndex - partialVirtualBitmapOffset;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Tim::GetAidOctetIndex(uint16_t aid) const
|
||||
{
|
||||
// bit number N (0 <= N <= 2007) in the bitmap corresponds to bit number (N mod 8) in octet
|
||||
// number |_N / 8_| where the low order bit of each octet is bit number 0, and the high order
|
||||
// bit is bit number 7 (Sec. 9.4.2.5.1 of 802.11-2020)
|
||||
return (aid >> 3) & 0xff;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Tim::GetAidBit(uint16_t aid) const
|
||||
{
|
||||
// bit number N (0 <= N <= 2007) in the bitmap corresponds to bit number (N mod 8) in octet
|
||||
// number |_N / 8_| where the low order bit of each octet is bit number 0, and the high order
|
||||
// bit is bit number 7 (Sec. 9.4.2.5.1 of 802.11-2020)
|
||||
return 0x01 << (aid & 0x07);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Tim::GetAidFromOctetIndexAndBitPosition(uint16_t octet, uint8_t position) const
|
||||
{
|
||||
return (octet << 3) + position;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Tim::GetPartialVirtualBitmapOffset() const
|
||||
{
|
||||
if (m_aidValues.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// N1 is the largest even number such that bits numbered 1 to (N1 * 8) – 1 in the traffic
|
||||
// indication virtual bitmap are all 0 (Sec. 9.4.2.5.1 of 802.11-2020).
|
||||
// Examples:
|
||||
// first bit set = 53, which belongs to octet 53 / 8 = 6 -> N1 = 6 (all bits 1 - 47 are zero)
|
||||
// first bit set = 61, which belongs to octet 61 / 8 = 7 -> N1 = 6 (all bits 1 - 47 are zero)
|
||||
return GetAidOctetIndex(*m_aidValues.cbegin()) & 0xFE;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Tim::GetLastNonZeroOctetIndex() const
|
||||
{
|
||||
if (m_aidValues.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// N2 is the smallest number such that bits numbered (N2 + 1) * 8 to 2007 in the traffic
|
||||
// indication virtual bitmap are all 0 (Sec. 9.4.2.5.1 of 802.11-2020).
|
||||
// Examples:
|
||||
// last bit set = 53, which belongs to octet 53 / 8 = 6 -> N2 = 6 (all bits 56 - 2007 are zero)
|
||||
// last bit set = 61, which belongs to octet 61 / 8 = 7 -> N2 = 7 (all bits 64 - 2007 are zero)
|
||||
return GetAidOctetIndex(*m_aidValues.rbegin());
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Tim::GetBitmapControl() const
|
||||
{
|
||||
// Note that setting the bitmapControl directly as the offset can be done because the least
|
||||
// significant bit of the output of GetPartialVirtualBitmapOffset will always be zero, so we
|
||||
// are already putting the relevant information in the appropriate part of the byte.
|
||||
auto bitmapControl = GetPartialVirtualBitmapOffset();
|
||||
|
||||
// Set the multicast indication bit, if this is a DTIM
|
||||
if ((m_dtimCount == 0) && m_hasMulticastPending)
|
||||
{
|
||||
bitmapControl |= 0x01;
|
||||
}
|
||||
|
||||
return bitmapControl;
|
||||
}
|
||||
|
||||
std::vector<uint8_t>
|
||||
Tim::GetPartialVirtualBitmap() const
|
||||
{
|
||||
auto offset = GetPartialVirtualBitmapOffset(); // N1
|
||||
|
||||
// the Partial Virtual Bitmap field consists of octets numbered N1 to N2 of the traffic
|
||||
// indication virtual bitmap (Sec. 9.4.2.5.1 of 802.11-2020)
|
||||
std::vector<uint8_t> partialVirtualBitmap(GetLastNonZeroOctetIndex() - offset + 1, 0);
|
||||
|
||||
for (auto aid : m_aidValues)
|
||||
{
|
||||
partialVirtualBitmap.at(GetAidOctetIndex(aid) - offset) |= GetAidBit(aid);
|
||||
}
|
||||
|
||||
return partialVirtualBitmap;
|
||||
}
|
||||
|
||||
void
|
||||
Tim::Print(std::ostream& os) const
|
||||
{
|
||||
os << "DTIM Count: " << +m_dtimCount << ", "
|
||||
<< "DTIM Period: " << +m_dtimPeriod << ", "
|
||||
<< "Has Multicast Pending: " << m_hasMulticastPending << ", AID values:";
|
||||
for (uint16_t aid = 0; aid < 2008; ++aid)
|
||||
{
|
||||
if (HasAid(aid))
|
||||
{
|
||||
os << aid << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
161
src/wifi/model/tim.h
Normal file
161
src/wifi/model/tim.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Davide Magrin <davide@magr.in>
|
||||
*/
|
||||
|
||||
#ifndef TIM_H
|
||||
#define TIM_H
|
||||
|
||||
#include "wifi-information-element.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief The Traffic Indication Map Information Element
|
||||
* \ingroup wifi
|
||||
*
|
||||
* The 802.11 Traffic Indication Map (see section 9.4.2.5 of 802.11-2020)
|
||||
*
|
||||
* Note: The current implementation does not support S1G operation, or
|
||||
* multiple BSSID.
|
||||
*/
|
||||
class Tim : public WifiInformationElement
|
||||
{
|
||||
public:
|
||||
WifiInformationElementId ElementId() const override;
|
||||
void Print(std::ostream& os) const override;
|
||||
|
||||
/**
|
||||
* Add the provided AID value to the list contained in the Virtual Bitmap
|
||||
*
|
||||
* \param aid the AID value to add to this TIM's Virtual Bitmap
|
||||
*/
|
||||
void AddAid(uint16_t aid);
|
||||
|
||||
/**
|
||||
* Add the AID values in the provided iterator range to the list contained
|
||||
* in the Virtual Bitmap
|
||||
*
|
||||
* \tparam Iterator Type of iterator
|
||||
* \param begin Starting position of the iterator range
|
||||
* \param end Ending position of the iterator range
|
||||
*/
|
||||
template <typename Iterator>
|
||||
void AddAid(Iterator begin, Iterator end);
|
||||
|
||||
/**
|
||||
* Check whether the bit corresponding to the provided AID is set in the
|
||||
* Virtual Bitmap included in this TIM
|
||||
*
|
||||
* \param aid The AID value to look for
|
||||
* \return True if the AID value is found in the Virtual Bitmap, false otherwise
|
||||
*/
|
||||
bool HasAid(uint16_t aid) const;
|
||||
|
||||
/**
|
||||
* Return the AID values, greater than the given AID value, whose corresponding bits are set
|
||||
* in the virtual bitmap.
|
||||
*
|
||||
* \param aid the given AID value
|
||||
* \return the AID values, greater than the given AID value, whose corresponding bits are set
|
||||
* in the virtual bitmap
|
||||
*/
|
||||
std::set<uint16_t> GetAidSet(uint16_t aid = 0) const;
|
||||
|
||||
/**
|
||||
* Get the Partial Virtual Bitmap offset, i.e., the number (denoted as N1 by the specs) of
|
||||
* the first octet included in the Partial Virtual Bitmap. Note that the Bitmap Offset
|
||||
* subfield contains the number N1/2.
|
||||
*
|
||||
* \return the Partial Virtual Bitmap offset
|
||||
*/
|
||||
uint8_t GetPartialVirtualBitmapOffset() const;
|
||||
|
||||
/**
|
||||
* \return the last non-zero octet in the virtual bitmap (denoted as N2 by the specs)
|
||||
*/
|
||||
uint8_t GetLastNonZeroOctetIndex() const;
|
||||
|
||||
uint8_t m_dtimCount{0}; //!< The DTIM Count field
|
||||
uint8_t m_dtimPeriod{0}; //!< The DTIM Period field
|
||||
bool m_hasMulticastPending{false}; //!< Whether there is Multicast / Broadcast data
|
||||
|
||||
private:
|
||||
uint16_t GetInformationFieldSize() const override;
|
||||
void SerializeInformationField(Buffer::Iterator start) const override;
|
||||
uint16_t DeserializeInformationField(Buffer::Iterator start, uint16_t length) override;
|
||||
|
||||
/**
|
||||
* Obtain the index of the octet where the provided AID value should be
|
||||
* set in the Virtual Bitmap
|
||||
*
|
||||
* \param aid the provided AID value
|
||||
* \return the index of the octet where the provided AID value should be
|
||||
* set in the Virtual Bitmap
|
||||
*/
|
||||
uint8_t GetAidOctetIndex(uint16_t aid) const;
|
||||
|
||||
/**
|
||||
* Obtain an octet with a set bit, corresponding to the provided AID value
|
||||
*
|
||||
* \param aid the provided AID value
|
||||
* \return an octet with a set bit, corresponding to the provided AID value
|
||||
*/
|
||||
uint8_t GetAidBit(uint16_t aid) const;
|
||||
|
||||
/**
|
||||
* Obtain the AID value represented by a certain octet index and bit
|
||||
* position inside the Virtual Bitmap
|
||||
*
|
||||
* \param octet the octet index in the Virtual Bitmap
|
||||
* \param position the bit position in the octet of the Virtual Bitmap
|
||||
* \return the corresponding AID value
|
||||
*/
|
||||
uint16_t GetAidFromOctetIndexAndBitPosition(uint16_t octet, uint8_t position) const;
|
||||
|
||||
/**
|
||||
* The Bitmap Control field is optional if the TIM is carried in an S1G PPDU, while
|
||||
* it is always present when the TIM is carried in a non-S1G PPDU.
|
||||
*
|
||||
* \return the value of the Bitmap Control field
|
||||
*/
|
||||
uint8_t GetBitmapControl() const;
|
||||
|
||||
/**
|
||||
* \return a vector containing the Partial Virtual Bitmap octets
|
||||
*/
|
||||
std::vector<uint8_t> GetPartialVirtualBitmap() const;
|
||||
|
||||
std::set<uint16_t> m_aidValues; //!< List of AID values included in this TIM
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
void
|
||||
Tim::AddAid(Iterator begin, Iterator end)
|
||||
{
|
||||
for (auto& it = begin; it != end; it++)
|
||||
{
|
||||
AddAid(*it);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* TIM_H */
|
||||
277
src/wifi/test/power-save-test.cc
Normal file
277
src/wifi/test/power-save-test.cc
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Davide Magrin <davide@magr.in>
|
||||
*/
|
||||
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/header-serialization-test.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/tim.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("PowerSaveTest");
|
||||
|
||||
/**
|
||||
* \ingroup wifi-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief Test TIM Information element serialization and deserialization
|
||||
*/
|
||||
class TimInformationElementTest : public HeaderSerializationTestCase
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Constructor
|
||||
*/
|
||||
TimInformationElementTest();
|
||||
|
||||
void DoRun() override;
|
||||
/**
|
||||
* Reset the passed TIM to have the provided parameters.
|
||||
*
|
||||
* \param tim the TIM element to set
|
||||
* \param dtimCount the DTIM count value
|
||||
* \param dtimPeriod the DTIM period value
|
||||
* \param multicastPending whether group addressed frames are queued
|
||||
* \param aidValues the AID values to set
|
||||
*/
|
||||
void SetTim(Tim& tim,
|
||||
uint8_t dtimCount,
|
||||
uint8_t dtimPeriod,
|
||||
bool multicastPending,
|
||||
const std::list<uint16_t>& aidValues);
|
||||
|
||||
/**
|
||||
* Test that the Bitmap Control and the Partial Virtual Bitmap
|
||||
* fields of the provided TIM match the passed bufferContents.
|
||||
*
|
||||
* \param tim the provided TIM
|
||||
* \param bufferContents the expected content of the buffer
|
||||
*/
|
||||
void CheckSerializationAgainstBuffer(Tim& tim, const std::vector<uint8_t>& bufferContents);
|
||||
|
||||
/**
|
||||
* Test that the GetAidSet() method return the expected set of AID values.
|
||||
*
|
||||
* \param tim the TIM element
|
||||
* \param aid the AID value passed to GetAidSet()
|
||||
* \param expectedSet the expected set of AID values returned by GetAidSet()
|
||||
*/
|
||||
void CheckAidSet(const Tim& tim, uint16_t aid, const std::set<uint16_t>& expectedSet);
|
||||
};
|
||||
|
||||
TimInformationElementTest::TimInformationElementTest()
|
||||
: HeaderSerializationTestCase("Test for the TIM Information Element implementation")
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TimInformationElementTest::SetTim(Tim& tim,
|
||||
uint8_t dtimCount,
|
||||
uint8_t dtimPeriod,
|
||||
bool multicastPending,
|
||||
const std::list<uint16_t>& aidValues)
|
||||
{
|
||||
tim = Tim();
|
||||
tim.m_dtimCount = dtimCount;
|
||||
tim.m_dtimPeriod = dtimPeriod;
|
||||
tim.m_hasMulticastPending = multicastPending;
|
||||
tim.AddAid(aidValues.begin(), aidValues.end());
|
||||
}
|
||||
|
||||
void
|
||||
TimInformationElementTest::CheckSerializationAgainstBuffer(
|
||||
Tim& tim,
|
||||
const std::vector<uint8_t>& bufferContents)
|
||||
{
|
||||
// Serialize the TIM
|
||||
Buffer buffer;
|
||||
buffer.AddAtStart(tim.GetSerializedSize());
|
||||
tim.Serialize(buffer.Begin());
|
||||
|
||||
// Check the two Buffer instances
|
||||
Buffer::Iterator bufferIterator = buffer.Begin();
|
||||
for (uint32_t j = 0; j < buffer.GetSize(); j++)
|
||||
{
|
||||
// We skip the first four bytes, since they contain known information
|
||||
if (j > 3)
|
||||
{
|
||||
NS_TEST_EXPECT_MSG_EQ(bufferIterator.ReadU8(),
|
||||
bufferContents.at(j - 4),
|
||||
"Serialization is different than provided known serialization");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Advance the serialized buffer, which also contains
|
||||
// the Element ID, Length, DTIM Count, DTIM Period fields
|
||||
bufferIterator.ReadU8();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimInformationElementTest::CheckAidSet(const Tim& tim,
|
||||
uint16_t aid,
|
||||
const std::set<uint16_t>& expectedSet)
|
||||
{
|
||||
auto ret = tim.GetAidSet(aid);
|
||||
|
||||
{
|
||||
std::vector<uint16_t> diff;
|
||||
|
||||
// Expected set minus returned set provides expected elements that are not returned
|
||||
std::set_difference(expectedSet.cbegin(),
|
||||
expectedSet.cend(),
|
||||
ret.cbegin(),
|
||||
ret.cend(),
|
||||
std::back_inserter(diff));
|
||||
|
||||
std::stringstream ss;
|
||||
std::copy(diff.cbegin(), diff.cend(), std::ostream_iterator<uint16_t>(ss, " "));
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ(diff.size(),
|
||||
0,
|
||||
"Expected elements not returned by GetAidSet(): " << ss.str());
|
||||
}
|
||||
{
|
||||
std::vector<uint16_t> diff;
|
||||
|
||||
// Returned set minus expected set provides returned elements that are not expected
|
||||
std::set_difference(ret.cbegin(),
|
||||
ret.cend(),
|
||||
expectedSet.cbegin(),
|
||||
expectedSet.cend(),
|
||||
std::back_inserter(diff));
|
||||
|
||||
std::stringstream ss;
|
||||
std::copy(diff.cbegin(), diff.cend(), std::ostream_iterator<uint16_t>(ss, " "));
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ(diff.size(),
|
||||
0,
|
||||
"Returned elements not expected by GetAidSet(): " << ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimInformationElementTest::DoRun()
|
||||
{
|
||||
Tim tim;
|
||||
|
||||
// The first three examples from 802.11-2020, Annex L
|
||||
//
|
||||
// 1. No group addressed MSDUs, but there is traffic for STAs with AID 2 and AID 7
|
||||
SetTim(tim, 0, 3, false, {2, 7});
|
||||
TestHeaderSerialization(tim);
|
||||
CheckSerializationAgainstBuffer(tim, {0b00000000, 0b10000100});
|
||||
CheckAidSet(tim, 0, {2, 7});
|
||||
CheckAidSet(tim, 1, {2, 7});
|
||||
CheckAidSet(tim, 2, {7});
|
||||
CheckAidSet(tim, 7, {});
|
||||
//
|
||||
// 2. There are group addressed MSDUs, DTIM count = 0, the nodes
|
||||
// with AID 2, 7, 22, and 24 have data buffered in the AP
|
||||
SetTim(tim, 0, 3, true, {2, 7, 22, 24});
|
||||
TestHeaderSerialization(tim);
|
||||
CheckSerializationAgainstBuffer(tim,
|
||||
{
|
||||
0b00000001,
|
||||
// NOTE The following byte is different from the example
|
||||
// in the standard. This is because the example sets the
|
||||
// AID 0 bit in the partial virtual bitmap to 1. Our code
|
||||
// and the example code provided in the Annex, instead, do
|
||||
// not set this bit. Relevant Note from 802.11-2020,
|
||||
// Section 9.4.2.5.1: "The bit numbered 0 in the traffic
|
||||
// indication virtual bitmap need not be included in the
|
||||
// Partial Virtual Bitmap field even if that bit is set."
|
||||
0b10000100,
|
||||
0b00000000,
|
||||
0b01000000,
|
||||
0b00000001,
|
||||
});
|
||||
CheckAidSet(tim, 0, {2, 7, 22, 24});
|
||||
CheckAidSet(tim, 2, {7, 22, 24});
|
||||
CheckAidSet(tim, 7, {22, 24});
|
||||
CheckAidSet(tim, 22, {24});
|
||||
CheckAidSet(tim, 24, {});
|
||||
//
|
||||
// 3. There are group addressed MSDUs, DTIM count = 0, only the node
|
||||
// with AID 24 has data buffered in the AP
|
||||
SetTim(tim, 0, 3, true, {24});
|
||||
TestHeaderSerialization(tim);
|
||||
CheckSerializationAgainstBuffer(tim, {0b00000011, 0b00000000, 0b00000001});
|
||||
|
||||
// Other arbitrary examples just to make sure
|
||||
// Serialization -> Deserialization -> Serialization works
|
||||
SetTim(tim, 0, 3, false, {2000});
|
||||
TestHeaderSerialization(tim);
|
||||
SetTim(tim, 1, 3, true, {1, 134});
|
||||
TestHeaderSerialization(tim);
|
||||
SetTim(tim, 1, 3, false, {1, 2});
|
||||
TestHeaderSerialization(tim);
|
||||
|
||||
// Edge cases
|
||||
//
|
||||
// What if there is group addressed data only?
|
||||
//
|
||||
// In this case, we should still have an empty byte in the Partial Virtual Bitmap.
|
||||
// From 802.11-2020: in the event that all bits other than bit 0 in the traffic indication
|
||||
// virtual bitmap are 0, the Partial Virtual Bitmap field is encoded as a single octet
|
||||
// equal to 0, the Bitmap Offset subfield is 0, and the Length field is 4.
|
||||
SetTim(tim, 0, 3, true, {});
|
||||
TestHeaderSerialization(tim);
|
||||
CheckSerializationAgainstBuffer(tim, {0b00000001, 0b00000000});
|
||||
NS_TEST_EXPECT_MSG_EQ(tim.GetSerializedSize() - 2, 4, "Unexpected TIM Length");
|
||||
//
|
||||
// What if there is no group addressed data and no unicast data?
|
||||
//
|
||||
// From 802.11-2020: When the TIM is carried in a non-S1G PPDU, in the event that all bits
|
||||
// other than bit 0 in the traffic indication virtual bitmap are 0, the Partial Virtual Bitmap
|
||||
// field is encoded as a single octet equal to 0, the Bitmap Offset subfield is 0, and the
|
||||
// Length field is 4.
|
||||
SetTim(tim, 0, 3, false, {});
|
||||
TestHeaderSerialization(tim);
|
||||
CheckSerializationAgainstBuffer(tim, {0b00000000, 0b00000000});
|
||||
NS_TEST_EXPECT_MSG_EQ(tim.GetSerializedSize() - 2, 4, "Unexpected TIM Length");
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup wifi-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief Power Save Test Suite
|
||||
*/
|
||||
class PowerSaveTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
PowerSaveTestSuite();
|
||||
};
|
||||
|
||||
PowerSaveTestSuite::PowerSaveTestSuite()
|
||||
: TestSuite("wifi-power-save", Type::UNIT)
|
||||
{
|
||||
AddTestCase(new TimInformationElementTest, TestCase::Duration::QUICK);
|
||||
}
|
||||
|
||||
static PowerSaveTestSuite g_powerSaveTestSuite; ///< the test suite
|
||||
Reference in New Issue
Block a user