wifi: Add support for GCR BlockAck(Req) variant

This commit is contained in:
Stefano Avallone
2023-08-22 23:16:38 +02:00
committed by Sébastien Deronne
parent 7e242a89b3
commit a648a6e2e9
4 changed files with 162 additions and 65 deletions

View File

@@ -23,6 +23,7 @@ BlockAckType::BlockAckType(Variant v)
break;
case COMPRESSED:
case EXTENDED_COMPRESSED:
case GCR:
m_bitmapLen.push_back(8);
break;
case MULTI_TID:
@@ -53,6 +54,7 @@ BlockAckReqType::BlockAckReqType(Variant v)
case BASIC:
case COMPRESSED:
case EXTENDED_COMPRESSED:
case GCR:
m_nSeqControls = 1;
break;
case MULTI_TID:
@@ -91,6 +93,9 @@ operator<<(std::ostream& os, const BlockAckType& type)
case BlockAckType::MULTI_TID:
os << "multi-tid-block-ack[" << type.m_bitmapLen.size() << "]";
break;
case BlockAckType::GCR:
os << "gcr-block-ack";
break;
case BlockAckType::MULTI_STA:
os << "multi-sta-block-ack[" << type.m_bitmapLen.size() << "]";
break;
@@ -117,6 +122,9 @@ operator<<(std::ostream& os, const BlockAckReqType& type)
case BlockAckReqType::MULTI_TID:
os << "multi-tid-block-ack-req[" << type.m_nSeqControls << "]";
break;
case BlockAckReqType::GCR:
os << "gcr-block-ack-req";
break;
default:
NS_FATAL_ERROR("Unknown block ack request type");
}

View File

@@ -26,12 +26,13 @@ struct BlockAckType
* @enum Variant
* @brief The BlockAck variants
*/
enum Variant
enum Variant : uint8_t
{
BASIC,
COMPRESSED,
EXTENDED_COMPRESSED,
MULTI_TID,
GCR,
MULTI_STA
};
@@ -68,12 +69,13 @@ struct BlockAckReqType
* @enum Variant
* @brief The BlockAckReq variants
*/
enum Variant
enum Variant : uint8_t
{
BASIC,
COMPRESSED,
EXTENDED_COMPRESSED,
MULTI_TID
MULTI_TID,
GCR
};
Variant m_variant; //!< Block Ack Request variant

View File

@@ -72,6 +72,9 @@ CtrlBAckRequestHeader::GetSerializedSize() const
case BlockAckReqType::MULTI_TID:
size += (2 + 2) * (m_tidInfo + 1);
break;
case BlockAckReqType::GCR:
size += (2 + 6); // SSC plus GCR Group Address
break;
default:
NS_FATAL_ERROR("Invalid BA type");
break;
@@ -94,6 +97,10 @@ CtrlBAckRequestHeader::Serialize(Buffer::Iterator start) const
case BlockAckReqType::MULTI_TID:
NS_FATAL_ERROR("Multi-tid block ack is not supported.");
break;
case BlockAckReqType::GCR:
i.WriteHtolsbU16(GetStartingSequenceControl());
WriteTo(i, m_gcrAddress);
break;
default:
NS_FATAL_ERROR("Invalid BA type");
break;
@@ -115,6 +122,10 @@ CtrlBAckRequestHeader::Deserialize(Buffer::Iterator start)
case BlockAckReqType::MULTI_TID:
NS_FATAL_ERROR("Multi-tid block ack is not supported.");
break;
case BlockAckReqType::GCR:
SetStartingSequenceControl(i.ReadLsbtohU16());
ReadFrom(i, m_gcrAddress);
break;
default:
NS_FATAL_ERROR("Invalid BA type");
break;
@@ -139,6 +150,9 @@ CtrlBAckRequestHeader::GetBarControl() const
case BlockAckReqType::MULTI_TID:
res |= (0x03 << 1);
break;
case BlockAckReqType::GCR:
res |= (0x06 << 1);
break;
default:
NS_FATAL_ERROR("Invalid BA type");
break;
@@ -151,7 +165,11 @@ void
CtrlBAckRequestHeader::SetBarControl(uint16_t bar)
{
m_barAckPolicy = ((bar & 0x01) == 1);
if (((bar >> 1) & 0x0f) == 0x03)
if (((bar >> 1) & 0x0f) == 0x06)
{
m_barType.m_variant = BlockAckReqType::GCR;
}
else if (((bar >> 1) & 0x0f) == 0x03)
{
m_barType.m_variant = BlockAckReqType::MULTI_TID;
}
@@ -231,6 +249,20 @@ CtrlBAckRequestHeader::GetStartingSequence() const
return m_startingSeq;
}
void
CtrlBAckRequestHeader::SetGcrGroupAddress(const Mac48Address& address)
{
NS_ASSERT(IsGcr());
m_gcrAddress = address;
}
Mac48Address
CtrlBAckRequestHeader::GetGcrGroupAddress() const
{
NS_ASSERT(IsGcr());
return m_gcrAddress;
}
bool
CtrlBAckRequestHeader::IsBasic() const
{
@@ -255,6 +287,12 @@ CtrlBAckRequestHeader::IsMultiTid() const
return m_barType.m_variant == BlockAckReqType::MULTI_TID;
}
bool
CtrlBAckRequestHeader::IsGcr() const
{
return m_barType.m_variant == BlockAckReqType::GCR;
}
/***********************************
* Block ack response
***********************************/
@@ -323,6 +361,9 @@ CtrlBAckResponseHeader::GetSerializedSize() const
case BlockAckType::MULTI_TID:
size += (2 + 2 + 8) * (m_tidInfo + 1); // Multi-TID block ack
break;
case BlockAckType::GCR:
size += (2 + 6 + m_baType.m_bitmapLen[0]);
break;
case BlockAckType::MULTI_STA:
for (auto& bitmapLen : m_baType.m_bitmapLen)
{
@@ -349,6 +390,11 @@ CtrlBAckResponseHeader::Serialize(Buffer::Iterator start) const
i.WriteHtolsbU16(GetStartingSequenceControl());
i = SerializeBitmap(i);
break;
case BlockAckType::GCR:
i.WriteHtolsbU16(GetStartingSequenceControl());
WriteTo(i, m_baInfo[0].m_address);
i = SerializeBitmap(i);
break;
case BlockAckType::MULTI_STA:
for (std::size_t index = 0; index < m_baInfo.size(); index++)
{
@@ -365,7 +411,7 @@ CtrlBAckResponseHeader::Serialize(Buffer::Iterator start) const
{
uint32_t reserved = 0;
i.WriteHtolsbU32(reserved);
WriteTo(i, m_baInfo[index].m_ra);
WriteTo(i, m_baInfo[index].m_address);
}
}
break;
@@ -391,6 +437,11 @@ CtrlBAckResponseHeader::Deserialize(Buffer::Iterator start)
SetStartingSequenceControl(i.ReadLsbtohU16());
i = DeserializeBitmap(i);
break;
case BlockAckType::GCR:
SetStartingSequenceControl(i.ReadLsbtohU16());
ReadFrom(i, m_baInfo[0].m_address);
i = DeserializeBitmap(i);
break;
case BlockAckType::MULTI_STA: {
std::size_t index = 0;
while (i.GetRemainingSize() > 0)
@@ -414,7 +465,7 @@ CtrlBAckResponseHeader::Deserialize(Buffer::Iterator start)
else
{
i.ReadLsbtohU32(); // next 4 bytes are reserved
ReadFrom(i, m_baInfo.back().m_ra);
ReadFrom(i, m_baInfo.back().m_address);
// the length of this Per AID TID Info subfield is 12, so set
// the bitmap length to 8 to simulate the correct size
m_baType.m_bitmapLen.back() = 8;
@@ -450,7 +501,7 @@ CtrlBAckResponseHeader::SetType(BlockAckType type)
BaInfoInstance baInfoInstance{.m_aidTidInfo = 0,
.m_startingSeq = 0,
.m_bitmap = std::vector<uint8_t>(bitmapLen, 0),
.m_ra = Mac48Address()};
.m_address = Mac48Address()};
m_baInfo.emplace_back(baInfoInstance);
}
@@ -555,6 +606,12 @@ CtrlBAckResponseHeader::IsMultiSta() const
return m_baType.m_variant == BlockAckType::MULTI_STA;
}
bool
CtrlBAckResponseHeader::IsGcr() const
{
return m_baType.m_variant == BlockAckType::GCR;
}
void
CtrlBAckResponseHeader::SetAid11(uint16_t aid, std::size_t index)
{
@@ -595,7 +652,7 @@ CtrlBAckResponseHeader::SetUnassociatedStaAddress(const Mac48Address& ra, std::s
{
NS_ASSERT(GetAid11(index) == 2045);
m_baInfo[index].m_ra = ra;
m_baInfo[index].m_address = ra;
}
Mac48Address
@@ -603,7 +660,7 @@ CtrlBAckResponseHeader::GetUnassociatedStaAddress(std::size_t index) const
{
NS_ASSERT(GetAid11(index) == 2045);
return m_baInfo[index].m_ra;
return m_baInfo[index].m_address;
}
std::size_t
@@ -630,6 +687,20 @@ CtrlBAckResponseHeader::FindPerAidTidInfoWithAid(uint16_t aid) const
return ret;
}
void
CtrlBAckResponseHeader::SetGcrGroupAddress(const Mac48Address& address)
{
NS_ASSERT(IsGcr());
m_baInfo[0].m_address = address;
}
Mac48Address
CtrlBAckResponseHeader::GetGcrGroupAddress() const
{
NS_ASSERT(IsGcr());
return m_baInfo[0].m_address;
}
uint16_t
CtrlBAckResponseHeader::GetBaControl() const
{
@@ -651,6 +722,9 @@ CtrlBAckResponseHeader::GetBaControl() const
case BlockAckType::MULTI_TID:
res |= (0x03 << 1);
break;
case BlockAckType::GCR:
res |= (0x06 << 1);
break;
case BlockAckType::MULTI_STA:
res |= (0x0b << 1);
break;
@@ -669,7 +743,11 @@ void
CtrlBAckResponseHeader::SetBaControl(uint16_t ba)
{
m_baAckPolicy = ((ba & 0x01) == 1);
if (((ba >> 1) & 0x0f) == 0x03)
if (((ba >> 1) & 0x0f) == 0x06)
{
SetType(BlockAckType::GCR);
}
else if (((ba >> 1) & 0x0f) == 0x03)
{
SetType(BlockAckType::MULTI_TID);
}
@@ -711,7 +789,7 @@ CtrlBAckResponseHeader::GetStartingSequenceControl(std::size_t index) const
// The Fragment Number subfield encodes the length of the bitmap for Compressed and Multi-STA
// variants (see sections 9.3.1.8.2 and 9.3.1.8.7 of 802.11ax-2021 and 802.11be Draft 4.0).
// Note that Fragmentation Level 3 is not supported.
if (m_baType.m_variant == BlockAckType::COMPRESSED)
if (m_baType.m_variant == BlockAckType::COMPRESSED || m_baType.m_variant == BlockAckType::GCR)
{
switch (m_baType.m_bitmapLen[0])
{
@@ -774,7 +852,7 @@ CtrlBAckResponseHeader::SetStartingSequenceControl(uint16_t seqControl, std::siz
// The Fragment Number subfield encodes the length of the bitmap for Compressed and Multi-STA
// variants (see sections 9.3.1.8.2 and 9.3.1.8.7 of 802.11ax-2021 and 802.11be Draft 4.0).
// Note that Fragmentation Level 3 is not supported.
if (m_baType.m_variant == BlockAckType::COMPRESSED)
if (m_baType.m_variant == BlockAckType::COMPRESSED || m_baType.m_variant == BlockAckType::GCR)
{
uint16_t fragNumber = seqControl & 0x000f;
@@ -785,16 +863,16 @@ CtrlBAckResponseHeader::SetStartingSequenceControl(uint16_t seqControl, std::siz
switch (fragNumber)
{
case 0:
SetType({BlockAckType::COMPRESSED, {8}});
SetType({m_baType.m_variant, {8}});
break;
case 4:
SetType({BlockAckType::COMPRESSED, {32}});
SetType({m_baType.m_variant, {32}});
break;
case 8:
SetType({BlockAckType::COMPRESSED, {64}});
SetType({m_baType.m_variant, {64}});
break;
case 10:
SetType({BlockAckType::COMPRESSED, {128}});
SetType({m_baType.m_variant, {128}});
break;
default:
NS_ABORT_MSG("Unsupported fragment number: " << fragNumber);
@@ -852,6 +930,7 @@ CtrlBAckResponseHeader::SerializeBitmap(Buffer::Iterator start, std::size_t inde
case BlockAckType::BASIC:
case BlockAckType::COMPRESSED:
case BlockAckType::EXTENDED_COMPRESSED:
case BlockAckType::GCR:
case BlockAckType::MULTI_STA:
for (const auto& byte : m_baInfo[index].m_bitmap)
{
@@ -881,6 +960,7 @@ CtrlBAckResponseHeader::DeserializeBitmap(Buffer::Iterator start, std::size_t in
case BlockAckType::BASIC:
case BlockAckType::COMPRESSED:
case BlockAckType::EXTENDED_COMPRESSED:
case BlockAckType::GCR:
case BlockAckType::MULTI_STA:
for (uint8_t j = 0; j < m_baType.m_bitmapLen[index]; j++)
{
@@ -917,6 +997,7 @@ CtrlBAckResponseHeader::SetReceivedPacket(uint16_t seq, std::size_t index)
break;
case BlockAckType::COMPRESSED:
case BlockAckType::EXTENDED_COMPRESSED:
case BlockAckType::GCR:
case BlockAckType::MULTI_STA: {
uint16_t i = IndexInBitmap(seq, index);
m_baInfo[index].m_bitmap[i / 8] |= (uint8_t(0x01) << (i % 8));
@@ -946,6 +1027,7 @@ CtrlBAckResponseHeader::SetReceivedFragment(uint16_t seq, uint8_t frag)
break;
case BlockAckType::COMPRESSED:
case BlockAckType::EXTENDED_COMPRESSED:
case BlockAckType::GCR:
case BlockAckType::MULTI_STA:
/* We can ignore this...compressed block ack doesn't support
acknowledgment of single fragments */
@@ -983,6 +1065,7 @@ CtrlBAckResponseHeader::IsPacketReceived(uint16_t seq, std::size_t index) const
return false;
case BlockAckType::COMPRESSED:
case BlockAckType::EXTENDED_COMPRESSED:
case BlockAckType::GCR:
case BlockAckType::MULTI_STA: {
uint16_t i = IndexInBitmap(seq, index);
uint8_t mask = uint8_t(0x01) << (i % 8);
@@ -1013,6 +1096,7 @@ CtrlBAckResponseHeader::IsFragmentReceived(uint16_t seq, uint8_t frag) const
0;
case BlockAckType::COMPRESSED:
case BlockAckType::EXTENDED_COMPRESSED:
case BlockAckType::GCR:
case BlockAckType::MULTI_STA:
/* We can ignore this...compressed block ack doesn't support
acknowledgement of single fragments */

View File

@@ -29,13 +29,13 @@ enum AcIndex : uint8_t;
* @ingroup wifi
* @brief Headers for BlockAckRequest.
*
* 802.11n standard includes three types of BlockAck:
* - Basic BlockAck (unique type in 802.11e)
* - Compressed BlockAck
* - Multi-TID BlockAck
* For now only basic BlockAck and compressed BlockAck
* are supported.
* Basic BlockAck is also default variant.
* 802.11 standard includes multiple BlockAckReq variants:
* - Basic BlockAckReq (unique type in 802.11e)
* - Compressed BlockAckReq
* - Multi-TID BlockAckReq
* - GCR BlockAckReq
* For now only basic BlockAckReq, compressed BlockAckReq and GCR BlockAckReq are supported.
* Basic BlockAckReq is the default variant.
*/
class CtrlBAckRequestHeader : public Header
{
@@ -79,6 +79,12 @@ class CtrlBAckRequestHeader : public Header
* @param seq the raw sequence control
*/
void SetStartingSequence(uint16_t seq);
/**
* Set the GCR Group address (GCR variant only).
*
* @param address the GCR Group Address
*/
void SetGcrGroupAddress(const Mac48Address& address);
/**
* Check if the current Ack Policy is immediate.
@@ -106,35 +112,29 @@ class CtrlBAckRequestHeader : public Header
*/
uint16_t GetStartingSequence() const;
/**
* Check if the current Ack Policy is Basic Block Ack
* (i.e. not multi-TID nor compressed).
*
* @return true if the current Ack Policy is Basic Block Ack,
* false otherwise
* @return the GCR Group Address (GCR variant only)
*/
Mac48Address GetGcrGroupAddress() const;
/**
* @return whether the variant of this BlockAckReq is Basic
*/
bool IsBasic() const;
/**
* Check if the current Ack Policy is Compressed Block Ack
* and not multi-TID.
*
* @return true if the current Ack Policy is Compressed Block Ack,
* false otherwise
* @return whether the variant of this BlockAckReq is Compressed
*/
bool IsCompressed() const;
/**
* Check if the current Ack Policy is Extended Compressed Block Ack.
*
* @return true if the current Ack Policy is Extended Compressed Block Ack,
* false otherwise
* @return whether the variant of this BlockAckReq is Extended Compressed
*/
bool IsExtendedCompressed() const;
/**
* Check if the current Ack Policy has Multi-TID Block Ack.
*
* @return true if the current Ack Policy has Multi-TID Block Ack,
* false otherwise
* @return whether the variant of this BlockAckReq is Multi-TID
*/
bool IsMultiTid() const;
/**
* @return whether the variant of this BlockAckReq is GCR
*/
bool IsGcr() const;
/**
* Return the starting sequence control.
@@ -174,17 +174,20 @@ class CtrlBAckRequestHeader : public Header
BlockAckReqType m_barType; ///< BAR type
uint16_t m_tidInfo; ///< TID info
uint16_t m_startingSeq; ///< starting seq
Mac48Address m_gcrAddress; ///< GCR Group Address (GCR variant only)
};
/**
* @ingroup wifi
* @brief Headers for BlockAck response.
*
* 802.11n standard includes three types of BlockAck:
* 802.11 standard includes multiple BlockAck variants:
* - Basic BlockAck (unique type in 802.11e)
* - Compressed BlockAck
* - Multi-TID BlockAck
* For now only basic BlockAck and compressed BlockAck
* - GCR BlockAck
* - Multi-STA BlockAck
* For now only basic BlockAck, compressed BlockAck, GCR BlockAck and Multi-STA BlockAck
* are supported.
* Basic BlockAck is also default variant.
*/
@@ -236,6 +239,12 @@ class CtrlBAckResponseHeader : public Header
* @param index the index of the Per AID TID Info subfield (Multi-STA Block Ack only)
*/
void SetStartingSequence(uint16_t seq, std::size_t index = 0);
/**
* Set the GCR Group address (GCR variant only).
*
* @param address the GCR Group Address
*/
void SetGcrGroupAddress(const Mac48Address& address);
/**
* Check if the current Ack Policy is immediate.
@@ -270,38 +279,31 @@ class CtrlBAckResponseHeader : public Header
*/
uint16_t GetStartingSequence(std::size_t index = 0) const;
/**
* Check if the current BA policy is Basic Block Ack.
*
* @return true if the current BA policy is Basic Block Ack,
* false otherwise
* @return the GCR Group Address (GCR variant only)
*/
Mac48Address GetGcrGroupAddress() const;
/**
* @return whether the variant of this BlockAckReq is Basic
*/
bool IsBasic() const;
/**
* Check if the current BA policy is Compressed Block Ack.
*
* @return true if the current BA policy is Compressed Block Ack,
* false otherwise
* @return whether the variant of this BlockAckReq is Compressed
*/
bool IsCompressed() const;
/**
* Check if the current BA policy is Extended Compressed Block Ack.
*
* @return true if the current BA policy is Extended Compressed Block Ack,
* false otherwise
* @return whether the variant of this BlockAckReq is Extended Compressed
*/
bool IsExtendedCompressed() const;
/**
* Check if the current BA policy is Multi-TID Block Ack.
*
* @return true if the current BA policy is Multi-TID Block Ack,
* false otherwise
* @return whether the variant of this BlockAckReq is Multi-TID
*/
bool IsMultiTid() const;
/**
* Check if the BlockAck frame variant is Multi-STA Block Ack.
*
* @return true if the BlockAck frame variant is Multi-STA Block Ack,
* false otherwise
* @return whether the variant of this BlockAckReq is GCR
*/
bool IsGcr() const;
/**
* @return whether the variant of this BlockAckReq is Multi-STA
*/
bool IsMultiSta() const;
@@ -534,8 +536,9 @@ class CtrlBAckResponseHeader : public Header
//!< AID TID Info subfield for Multi-STA
uint16_t m_startingSeq; //!< Block Ack Starting Sequence Control subfield
std::vector<uint8_t> m_bitmap; //!< block ack bitmap
Mac48Address m_ra; //!< RA subfield (address of an unassociated station)
//!< for Multi-STA; reserved for other variants
Mac48Address m_address; //!< RA subfield (address of an unassociated station) for
//!< Multi-STA variant; GCR Group Address subfield for GCR
//!< variant; reserved for other variants
};
std::vector<BaInfoInstance> m_baInfo; //!< BA Information field