wifi: Add support for IE_EXTENSION and fix 802.11ax information elements

This commit is contained in:
Sébastien Deronne
2018-09-02 22:39:12 +02:00
parent 534f28383b
commit 40b1dc2db8
6 changed files with 104 additions and 34 deletions

View File

@@ -93,7 +93,13 @@ HeCapabilities::HeCapabilities ()
WifiInformationElementId
HeCapabilities::ElementId () const
{
return IE_HE_CAPABILITIES;
return IE_EXTENSION;
}
WifiInformationElementId
HeCapabilities::ElementIdExt () const
{
return IE_EXT_HE_CAPABILITIES;
}
void
@@ -107,7 +113,7 @@ HeCapabilities::GetInformationFieldSize () const
{
//we should not be here if ht is not supported
NS_ASSERT (m_heSupported > 0);
return 16; //todo: variable length!
return 19; //todo: variable length!
}
Buffer::Iterator
@@ -140,8 +146,9 @@ HeCapabilities::SerializeInformationField (Buffer::Iterator start) const
start.WriteU8 (GetHeMacCapabilitiesInfo2 ());
start.WriteHtolsbU64 (GetHePhyCapabilitiesInfo1 ());
start.WriteU8 (GetHePhyCapabilitiesInfo2 ());
start.WriteU16 (GetSupportedMcsAndNss ()); //todo: variable length
//todo: optional PPE Threshold field
start.WriteHtolsbU32 (GetSupportedMcsAndNss ());
//todo: add another 32-bits field if 160 MHz channel is supported (variable length)
//todo: optional PPE Threshold field (variable length)
}
}
@@ -153,11 +160,12 @@ HeCapabilities::DeserializeInformationField (Buffer::Iterator start, uint8_t len
uint8_t macCapabilities2 = i.ReadU8 ();
uint64_t phyCapabilities1 = i.ReadLsbtohU64 ();
uint8_t phyCapabilities2 = i.ReadU8 ();
uint16_t mcsset = i.ReadU16 (); //todo: variable length
uint32_t mcsset = i.ReadU32 ();
SetHeMacCapabilitiesInfo (macCapabilities1, macCapabilities2);
SetHePhyCapabilitiesInfo (phyCapabilities1, phyCapabilities2);
SetSupportedMcsAndNss (mcsset);
//todo: optional PPE Threshold field
//todo: add another 32-bits field if 160 MHz channel is supported (variable length)
//todo: optional PPE Threshold field (variable length)
return length;
}

View File

@@ -44,6 +44,11 @@ public:
* \returns the wifi information element ID
*/
WifiInformationElementId ElementId () const;
/**
* Get the wifi information element ID extension
* \returns the wifi information element ID extension
*/
WifiInformationElementId ElementIdExt () const;
/**
* Get information field size
* \returns the information field size
@@ -175,14 +180,14 @@ public:
void SetHighestNssSupported (uint8_t nss);
/**
* Is transmit MCS supported.
* Is RX MCS supported.
*
* \param mcs the MCS
* \returns true if MCS transmit supported
*/
bool IsSupportedTxMcs (uint8_t mcs) const;
/**
* Is reeive MCS supported.
* Is RX MCS supported.
*
* \param mcs the MCS
* \returns true if MCS receive supported

View File

@@ -40,7 +40,13 @@ HeOperation::HeOperation ()
WifiInformationElementId
HeOperation::ElementId () const
{
return IE_HE_OPERATION;
return IE_EXTENSION;
}
WifiInformationElementId
HeOperation::ElementIdExt () const
{
return IE_EXT_HE_OPERATION;
}
void
@@ -54,7 +60,7 @@ HeOperation::GetInformationFieldSize () const
{
//we should not be here if he is not supported
NS_ASSERT (m_heSupported > 0);
return 10;
return 7;
}
void
@@ -91,10 +97,23 @@ void
HeOperation::SetMaxHeMcsPerNss (uint8_t nss, uint8_t maxHeMcs)
{
NS_ASSERT ((maxHeMcs >= 7 && maxHeMcs <= 11) && (nss >= 1 && nss <= 8));
m_basicHeMcsAndNssSet |= (((maxHeMcs - 7) & 0x07) << ((nss - 1) * 3));
uint8_t val = 3; //3 means not supported
if (maxHeMcs > 9) //MCS 0 - 11
{
val = 2;
}
else if (maxHeMcs > 7) //MCS 0 - 9
{
val = 1;
}
else if (maxHeMcs == 7) //MCS 0 - 7
{
val = 0;
}
m_basicHeMcsAndNssSet |= ((val & 0x03) << ((nss - 1) * 2));
}
uint32_t
uint16_t
HeOperation::GetBasicHeMcsAndNssSet (void) const
{
return m_basicHeMcsAndNssSet;
@@ -127,11 +146,8 @@ HeOperation::SerializeInformationField (Buffer::Iterator start) const
{
//write the corresponding value for each bit
start.WriteHtolsbU32 (GetHeOperationParameters ());
uint32_t mcsset = GetBasicHeMcsAndNssSet ();
start.WriteU16 (mcsset & 0xffff);
start.WriteU8 ((mcsset >> 16) & 0xff);
start.WriteU16 (0); //todo: VHT Operation Information
start.WriteU8 (0); //todo: VHT Operation Information
start.WriteU16 (GetBasicHeMcsAndNssSet ());
//todo: VHT Operation Information (variable)
}
}
@@ -140,13 +156,9 @@ HeOperation::DeserializeInformationField (Buffer::Iterator start, uint8_t length
{
Buffer::Iterator i = start;
uint32_t heOperationParameters = i.ReadLsbtohU32 ();
uint16_t mcsset_1 = i.ReadU16 ();
uint8_t mcsset_2 = i.ReadU8 ();
i.ReadU16 (); //todo: VHT Operation Information
i.ReadU8 (); //todo: VHT Operation Information
m_basicHeMcsAndNssSet = i.ReadU16 ();
SetHeOperationParameters (heOperationParameters);
m_basicHeMcsAndNssSet |= mcsset_1 & 0xffff;
m_basicHeMcsAndNssSet |= (mcsset_2 & 0xff) << 16;
//todo: VHT Operation Information (variable)
return length;
}

View File

@@ -71,7 +71,7 @@ public:
*
* \return the Basic HE-MCS And Nss field in the HE Operation information element
*/
uint32_t GetBasicHeMcsAndNssSet (void) const;
uint16_t GetBasicHeMcsAndNssSet (void) const;
/**
* Return the element ID.
@@ -79,6 +79,11 @@ public:
* \returns the element ID
*/
WifiInformationElementId ElementId () const;
/**
* Get the wifi information element ID extension
* \returns the wifi information element ID extension
*/
WifiInformationElementId ElementIdExt () const;
/**
* Return the information field size.
*
@@ -131,7 +136,7 @@ private:
uint8_t m_dualBeacon; //!< Dual Beacon
//Basic HE-MCS and NSS Set
uint32_t m_basicHeMcsAndNssSet; ///< basic HE MCS NSS set
uint16_t m_basicHeMcsAndNssSet; ///< basic HE MCS NSS set
//TODO: VHT Operation Information subfields not defined in the standard yet.

View File

@@ -37,13 +37,28 @@ WifiInformationElement::GetSerializedSize () const
return (2 + GetInformationFieldSize ());
}
WifiInformationElementId
WifiInformationElement::ElementIdExt () const
{
return 0;
}
Buffer::Iterator
WifiInformationElement::Serialize (Buffer::Iterator i) const
{
i.WriteU8 (ElementId ());
i.WriteU8 (GetInformationFieldSize ());
SerializeInformationField (i);
i.Next (GetInformationFieldSize ());
if (ElementId () == IE_EXTENSION)
{
i.WriteU8 (ElementIdExt ());
SerializeInformationField (i);
i.Next (GetInformationFieldSize () - 1);
}
else
{
SerializeInformationField (i);
i.Next (GetInformationFieldSize ());
}
return i;
}
@@ -77,10 +92,24 @@ WifiInformationElement::DeserializeIfPresent (Buffer::Iterator i)
}
uint8_t length = i.ReadU8 ();
DeserializeInformationField (i, length);
i.Next (length);
if (ElementId () == IE_EXTENSION)
{
uint8_t elementIdExt = i.ReadU8 ();
//If the element here isn't the one we're after then we immediately
//return the iterator we were passed indicating that we haven't
//taken anything from the buffer.
if (elementIdExt != ElementIdExt ())
{
return start;
}
DeserializeInformationField (i, length - 1);
i.Next (length - 1);
}
else
{
DeserializeInformationField (i, length);
i.Next (length);
}
return i;
}
@@ -97,6 +126,11 @@ WifiInformationElement::operator== (WifiInformationElement const & a) const
return false;
}
if (ElementIdExt () != a.ElementIdExt ())
{
return false;
}
uint32_t ieSize = GetInformationFieldSize ();
Buffer myIe, hisIe;

View File

@@ -185,10 +185,11 @@ typedef uint8_t WifiInformationElementId;
#define IE_OPERATING_MODE_NOTIFICATION ((WifiInformationElementId)199)
// 200 to 220 are reserved
#define IE_VENDOR_SPECIFIC ((WifiInformationElementId)221)
// 222 to 255 are reserved
#define IE_HE_CAPABILITIES ((WifiInformationElementId)255) //todo: not defined yet in the standard!
#define IE_HE_OPERATION ((WifiInformationElementId)255) //todo: not defined yet in the standard!
// 222 to 254 are reserved
#define IE_EXTENSION ((WifiInformationElementId)255)
#define IE_EXT_HE_CAPABILITIES ((WifiInformationElementId)35)
#define IE_EXT_HE_OPERATION ((WifiInformationElementId)36)
/**
* \brief Information element, as defined in 802.11-2007 standard
@@ -303,6 +304,11 @@ public:
virtual uint8_t DeserializeInformationField (Buffer::Iterator start,
uint8_t length) = 0;
/**
* \returns Own unique Element ID Extension
*/
virtual WifiInformationElementId ElementIdExt () const;
// In addition, a subclass may optionally override the following...
/**
* Generate human-readable form of IE