wifi: Add support for VhtOperation

This commit is contained in:
Sébastien Deronne
2016-12-28 13:31:42 +01:00
parent 53ad38c9dd
commit fe5d3ebdd0
10 changed files with 510 additions and 11 deletions

View File

@@ -242,6 +242,29 @@ ApWifiMac::IsNonGfHtStasPresent (void) const
return false;
}
uint32_t
ApWifiMac::GetVhtOperationalChannelWidth (void) const
{
uint32_t channelWidth = 160;
bool hasVht = false;
for (std::list<Mac48Address>::const_iterator i = m_staList.begin (); i != m_staList.end (); i++)
{
if (m_stationManager->GetVhtSupported (*i))
{
hasVht = true;
if (m_stationManager->GetChannelWidthSupported (*i) < channelWidth)
{
channelWidth = m_stationManager->GetChannelWidthSupported (*i);
}
}
}
if (!hasVht)
{
channelWidth = m_phy->GetChannelWidth ();
}
return channelWidth;
}
void
ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from,
Mac48Address to)
@@ -499,6 +522,44 @@ ApWifiMac::GetHtOperation (void) const
return operation;
}
VhtOperation
ApWifiMac::GetVhtOperation (void) const
{
VhtOperation operation;
operation.SetVhtSupported (1);
if (m_vhtSupported)
{
uint32_t channelWidth = GetVhtOperationalChannelWidth ();
if (channelWidth == 160)
{
operation.SetChannelWidth (2);
}
else if (channelWidth == 80)
{
operation.SetChannelWidth (1);
}
else
{
operation.SetChannelWidth (0);
}
for (uint8_t nss = 1; nss <= 8; nss++)
{
uint8_t maxMcs;
if (nss <= m_phy->GetMaxSupportedRxSpatialStreams ())
{
maxMcs = 9; //TBD: hardcode to 9 for now since we assume all MCS values are supported
}
else
{
maxMcs = 0;
}
operation.SetMaxVhtMcsPerNss (nss, maxMcs);
}
}
return operation;
}
void
ApWifiMac::SendProbeResp (Mac48Address to)
{
@@ -539,6 +600,7 @@ ApWifiMac::SendProbeResp (Mac48Address to)
if (m_vhtSupported)
{
probe.SetVhtCapabilities (GetVhtCapabilities ());
probe.SetVhtOperation (GetVhtOperation ());
}
packet->AddHeader (probe);
@@ -592,6 +654,7 @@ ApWifiMac::SendAssocResp (Mac48Address to, bool success)
if (m_vhtSupported)
{
assoc.SetVhtCapabilities (GetVhtCapabilities ());
assoc.SetVhtOperation (GetVhtOperation ());
}
packet->AddHeader (assoc);
@@ -642,6 +705,7 @@ ApWifiMac::SendOneBeacon (void)
if (m_vhtSupported)
{
beacon.SetVhtCapabilities (GetVhtCapabilities ());
beacon.SetVhtOperation (GetVhtOperation ());
}
packet->AddHeader (beacon);

View File

@@ -117,7 +117,10 @@ public:
* Determine whether non-Greenfield HT stations are present or not.
*/
bool IsNonGfHtStasPresent (void) const;
/**
* Determine the VHT operational channel width.
*/
uint32_t GetVhtOperationalChannelWidth (void) const;
/**
* Assign a fixed random variable stream number to the random variables
@@ -224,6 +227,12 @@ private:
* \return the HT operation that we support
*/
HtOperation GetHtOperation (void) const;
/**
* Return the VHT operation of the current AP.
*
* \return the VHT operation that we support
*/
VhtOperation GetVhtOperation (void) const;
/**
* Return an instance of SupportedRates that contains all rates that we support
* including HT rates.

View File

@@ -118,7 +118,7 @@ MgtProbeRequestHeader::Print (std::ostream &os) const
os << "ssid=" << m_ssid << ", "
<< "rates=" << m_rates << ", "
<< "HT Capabilities=" << m_htCapability << " , "
<< "VHT Capabilities= " << m_vhtCapability;
<< "VHT Capabilities=" << m_vhtCapability;
}
void
@@ -231,6 +231,18 @@ MgtProbeResponseHeader::GetVhtCapabilities (void) const
return m_vhtCapability;
}
void
MgtProbeResponseHeader::SetVhtOperation (VhtOperation vhtoperation)
{
m_vhtOperation = vhtoperation;
}
VhtOperation
MgtProbeResponseHeader::GetVhtOperation (void) const
{
return m_vhtOperation;
}
void
MgtProbeResponseHeader::SetSsid (Ssid ssid)
{
@@ -318,6 +330,7 @@ MgtProbeResponseHeader::GetSerializedSize (void) const
size += m_htCapability.GetSerializedSize ();
size += m_htOperation.GetSerializedSize ();
size += m_vhtCapability.GetSerializedSize ();
size += m_vhtOperation.GetSerializedSize ();
return size;
}
@@ -330,7 +343,8 @@ MgtProbeResponseHeader::Print (std::ostream &os) const
<< "ERP information=" << m_erpInformation << ", "
<< "HT Capabilities=" << m_htCapability << " , "
<< "HT Operation=" << m_htOperation << " , "
<< "VHT Capabilities= " << m_vhtCapability;
<< "VHT Capabilities=" << m_vhtCapability << " , "
<< "VHT Operation=" << m_vhtOperation;
}
void
@@ -358,6 +372,7 @@ MgtProbeResponseHeader::Serialize (Buffer::Iterator start) const
i = m_htCapability.Serialize (i);
i = m_htOperation.Serialize (i);
i = m_vhtCapability.Serialize (i);
i = m_vhtOperation.Serialize (i);
}
uint32_t
@@ -377,6 +392,7 @@ MgtProbeResponseHeader::Deserialize (Buffer::Iterator start)
i = m_htCapability.DeserializeIfPresent (i);
i = m_htOperation.DeserializeIfPresent (i);
i = m_vhtCapability.DeserializeIfPresent (i);
i = m_vhtOperation.DeserializeIfPresent (i);
return i.GetDistanceFrom (start);
}
@@ -524,7 +540,7 @@ MgtAssocRequestHeader::Print (std::ostream &os) const
os << "ssid=" << m_ssid << ", "
<< "rates=" << m_rates << ", "
<< "HT Capabilities=" << m_htCapability << " , "
<< "VHT Capabilities= " << m_vhtCapability;
<< "VHT Capabilities=" << m_vhtCapability;
}
void
@@ -642,6 +658,18 @@ MgtAssocResponseHeader::GetVhtCapabilities (void) const
return m_vhtCapability;
}
void
MgtAssocResponseHeader::SetVhtOperation (VhtOperation vhtoperation)
{
m_vhtOperation = vhtoperation;
}
VhtOperation
MgtAssocResponseHeader::GetVhtOperation (void) const
{
return m_vhtOperation;
}
void
MgtAssocResponseHeader::SetErpInformation (ErpInformation erpInformation)
{
@@ -697,6 +725,7 @@ MgtAssocResponseHeader::GetSerializedSize (void) const
size += m_htCapability.GetSerializedSize ();
size += m_htOperation.GetSerializedSize ();
size += m_vhtCapability.GetSerializedSize ();
size += m_vhtOperation.GetSerializedSize ();
return size;
}
@@ -708,7 +737,8 @@ MgtAssocResponseHeader::Print (std::ostream &os) const
<< "ERP information=" << m_erpInformation << ", "
<< "HT Capabilities=" << m_htCapability << " , "
<< "HT Operation=" << m_htOperation << " , "
<< "VHT Capabilities= " << m_vhtCapability;
<< "VHT Capabilities=" << m_vhtCapability << " , "
<< "VHT Operation=" << m_vhtOperation;
}
void
@@ -725,6 +755,7 @@ MgtAssocResponseHeader::Serialize (Buffer::Iterator start) const
i = m_htCapability.Serialize (i);
i = m_htOperation.Serialize (i);
i = m_vhtCapability.Serialize (i);
i = m_vhtOperation.Serialize (i);
}
uint32_t
@@ -741,6 +772,7 @@ MgtAssocResponseHeader::Deserialize (Buffer::Iterator start)
i = m_htCapability.DeserializeIfPresent (i);
i = m_htOperation.DeserializeIfPresent (i);
i = m_vhtCapability.DeserializeIfPresent (i);
i = m_vhtOperation.DeserializeIfPresent (i);
return i.GetDistanceFrom (start);
}

View File

@@ -31,6 +31,7 @@
#include "ht-capabilities.h"
#include "ht-operation.h"
#include "vht-capabilities.h"
#include "vht-operation.h"
#include "erp-information.h"
#include "edca-parameter-set.h"
@@ -187,6 +188,18 @@ public:
* \return HT operation
*/
HtOperation GetHtOperation (void) const;
/**
* Return the VHT capabilities.
*
* \return VHT capabilities
*/
VhtCapabilities GetVhtCapabilities (void) const;
/**
* Return the VHT operation.
*
* \return VHT operation
*/
VhtOperation GetVhtOperation (void) const;
/**
* Return the ERP information.
*
@@ -199,18 +212,18 @@ public:
* \return the EDCA Parameter Set
*/
EdcaParameterSet GetEdcaParameterSet (void) const;
/**
* Set the VHT operation.
*
* \param vhtoperation VHT operation
*/
void SetVhtOperation (VhtOperation vhtoperation);
/**
* Set the VHT capabilities.
*
* \param vhtcapabilities VHT capabilities
*/
void SetVhtCapabilities (VhtCapabilities vhtcapabilities);
/**
* Return the VHT capabilities.
*
* \return VHT capabilities
*/
VhtCapabilities GetVhtCapabilities (void) const;
/**
* Set the HT capabilities.
*
@@ -268,6 +281,7 @@ private:
HtCapabilities m_htCapability; //!< HT capabilities
HtOperation m_htOperation; //!< HT operation
VhtCapabilities m_vhtCapability; //!< VHT capabilities
VhtOperation m_vhtOperation; //!< VHT operation
ErpInformation m_erpInformation; //!< ERP information
EdcaParameterSet m_edcaParameterSet; //!< EDCA Parameter Set
};
@@ -409,6 +423,12 @@ public:
* \return VHT capabilities
*/
VhtCapabilities GetVhtCapabilities (void) const;
/**
* Return the VHT operation.
*
* \return VHT operation
*/
VhtOperation GetVhtOperation (void) const;
/**
* Return the ERP information.
*
@@ -445,6 +465,12 @@ public:
* \param vhtcapabilities VHT capabilities
*/
void SetVhtCapabilities (VhtCapabilities vhtcapabilities);
/**
* Set the VHT operation.
*
* \param vhtoperation VHT operation
*/
void SetVhtOperation (VhtOperation vhtoperation);
/**
* Set the Service Set Identifier (SSID).
*
@@ -510,6 +536,7 @@ private:
HtCapabilities m_htCapability; //!< HT capabilities
HtOperation m_htOperation; //!< HT operation
VhtCapabilities m_vhtCapability; //!< VHT capabilities
VhtOperation m_vhtOperation; //!< VHT operation
ErpInformation m_erpInformation; //!< ERP information
EdcaParameterSet m_edcaParameterSet; //!< EDCA Parameter Set
};

View File

@@ -719,6 +719,7 @@ StaWifiMac::Receive (Ptr<Packet> packet, const WifiMacHeader *hdr)
if (m_vhtSupported)
{
VhtCapabilities vhtcapabilities = assocResp.GetVhtCapabilities ();
VhtOperation vhtOperation = assocResp.GetVhtOperation ();
m_stationManager->AddStationVhtCapabilities (hdr->GetAddr2 (), vhtcapabilities);
}

View File

@@ -0,0 +1,191 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016 Sébastien Deronne
*
* 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: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
#include "vht-operation.h"
#include "ns3/log.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("VhtOperation");
VhtOperation::VhtOperation ()
: m_channelWidth (0),
m_channelCenterFrequencySegment0 (0),
m_channelCenterFrequencySegment1 (0),
m_basicVhtMcsAndNssSet (0),
m_vhtSupported (0)
{
}
WifiInformationElementId
VhtOperation::ElementId () const
{
return IE_VHT_OPERATION;
}
void
VhtOperation::SetVhtSupported (uint8_t vhtsupported)
{
m_vhtSupported = vhtsupported;
}
uint8_t
VhtOperation::GetInformationFieldSize () const
{
//we should not be here if ht is not supported
NS_ASSERT (m_vhtSupported > 0);
return 5;
}
void
VhtOperation::SetChannelWidth (uint8_t channelWidth)
{
m_channelWidth = channelWidth;
}
void
VhtOperation::SetChannelCenterFrequencySegment0 (uint8_t channelCenterFrequencySegment0)
{
m_channelCenterFrequencySegment0 = channelCenterFrequencySegment0;
}
void
VhtOperation::SetChannelCenterFrequencySegment1 (uint8_t channelCenterFrequencySegment1)
{
m_channelCenterFrequencySegment1 = channelCenterFrequencySegment1;
}
void
VhtOperation::SetMaxVhtMcsPerNss (uint8_t nss, uint8_t maxVhtMcs)
{
NS_ASSERT ((maxVhtMcs == 0 || (maxVhtMcs >= 7 && maxVhtMcs <= 9)) && (nss >= 1 && nss <= 8));
if (maxVhtMcs != 0)
{
m_basicVhtMcsAndNssSet |= (((maxVhtMcs - 7) & 0x03) << ((nss - 1) * 2));
}
else
{
m_basicVhtMcsAndNssSet |= (3 << ((nss - 1) * 2));
}
}
void
VhtOperation::SetBasicVhtMcsAndNssSet (uint16_t basicVhtMcsAndNssSet)
{
m_basicVhtMcsAndNssSet = basicVhtMcsAndNssSet;
}
uint8_t
VhtOperation::GetChannelWidth (void) const
{
return m_channelWidth;
}
uint8_t
VhtOperation::GetChannelCenterFrequencySegment0 (void) const
{
return m_channelCenterFrequencySegment0;
}
uint8_t
VhtOperation::GetChannelCenterFrequencySegment1 (void) const
{
return m_channelCenterFrequencySegment1;
}
uint16_t
VhtOperation::GetBasicVhtMcsAndNssSet (void) const
{
return m_basicVhtMcsAndNssSet;
}
Buffer::Iterator
VhtOperation::Serialize (Buffer::Iterator i) const
{
if (m_vhtSupported < 1)
{
return i;
}
return WifiInformationElement::Serialize (i);
}
uint16_t
VhtOperation::GetSerializedSize () const
{
if (m_vhtSupported < 1)
{
return 0;
}
return WifiInformationElement::GetSerializedSize ();
}
void
VhtOperation::SerializeInformationField (Buffer::Iterator start) const
{
if (m_vhtSupported == 1)
{
//write the corresponding value for each bit
start.WriteU8 (GetChannelWidth ());
start.WriteU8 (GetChannelCenterFrequencySegment0 ());
start.WriteU8 (GetChannelCenterFrequencySegment1 ());
start.WriteU16 (GetBasicVhtMcsAndNssSet ());
}
}
uint8_t
VhtOperation::DeserializeInformationField (Buffer::Iterator start, uint8_t length)
{
Buffer::Iterator i = start;
uint8_t channelWidth = i.ReadU8 ();
uint8_t channelCenterFrequencySegment0 = i.ReadU8 ();
uint8_t channelCenterFrequencySegment1 = i.ReadU8 ();
uint16_t basicVhtMcsAndNssSet = i.ReadU16 ();
SetChannelWidth (channelWidth);
SetChannelCenterFrequencySegment0 (channelCenterFrequencySegment0);
SetChannelCenterFrequencySegment1 (channelCenterFrequencySegment1);
SetBasicVhtMcsAndNssSet (basicVhtMcsAndNssSet);
return length;
}
ATTRIBUTE_HELPER_CPP (VhtOperation);
std::ostream &
operator << (std::ostream &os, const VhtOperation &VhtOperation)
{
os << VhtOperation.GetChannelWidth () << "|"
<< VhtOperation.GetChannelCenterFrequencySegment0 () << "|"
<< VhtOperation.GetChannelCenterFrequencySegment1 () << "|"
<< VhtOperation.GetBasicVhtMcsAndNssSet ();
return os;
}
std::istream &operator >> (std::istream &is, VhtOperation &VhtOperation)
{
uint8_t c1, c2, c3;
uint16_t c4;
is >> c1 >> c2 >> c3 >> c4;
VhtOperation.SetChannelWidth (c1);
VhtOperation.SetChannelCenterFrequencySegment0 (c2);
VhtOperation.SetChannelCenterFrequencySegment1 (c3);
VhtOperation.SetBasicVhtMcsAndNssSet (c4);
return is;
}
} //namespace ns3

View File

@@ -0,0 +1,144 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2016 Sébastien Deronne
*
* 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: Sébastien Deronne <sebastien.deronne@gmail.com>
*/
#ifndef VHT_OPERATION_H
#define VHT_OPERATION_H
#include "wifi-information-element.h"
namespace ns3 {
/**
* \brief The VHT Operation Information Element
* \ingroup wifi
*
* This class knows how to serialise and deserialise
* the VHT Operation Information Element
*
* \see attribute_VhtOperation
*/
class VhtOperation: public WifiInformationElement
{
public:
VhtOperation ();
void SetVhtSupported (uint8_t vhtsupported);
/**
* Set the Channel Width field in the VHT Operation information element.
*
* \param channelWidth the Channel Width field in the VHT Operation information element
*/
void SetChannelWidth (uint8_t channelWidth);
/**
* Set the Channel Center Frequency Segment 0 field in the VHT Operation information element.
*
* \param channelCenterFrequencySegment0 the Channel Center Frequency Segment 0 field in the VHT Operation information element
*/
void SetChannelCenterFrequencySegment0 (uint8_t channelCenterFrequencySegment0);
/**
* Set the Channel Center Frequency Segment 1 field in the VHT Operation information element.
*
* \param channelCenterFrequencySegment1 the Channel Center Frequency Segment 1 field in the VHT Operation information element
*/
void SetChannelCenterFrequencySegment1 (uint8_t channelCenterFrequencySegment1);
/**
* Set the Basic VHT-MCS and NSS field in the VHT Operation information element.
*
* \param basicVhtMcsAndNssSet the Basic VHT-MCS and NSS field in the VHT Operation information element
*/
void SetBasicVhtMcsAndNssSet (uint16_t basicVhtMcsAndNssSet);
/**
* Set the Basic VHT-MCS and NSS field in the VHT Operation information element
* by specifying the tuple (nss, maxMcs).
*
* \param nss the NSS
* \param maxMcs the maximum supported MCS value corresponding to that NSS
*/
void SetMaxVhtMcsPerNss (uint8_t nss, uint8_t maxVhtMcs);
/*
* Return the Channel Width field in the VHT Operation information element.
*
* \return the Channel Width field in the VHT Operation information element
*/
uint8_t GetChannelWidth (void) const;
/*
* Return the Channel Center Frequency Segment 0 field in the VHT Operation information element.
*
* \return the Channel Center Frequency Segment 0 field in the VHT Operation information element
*/
uint8_t GetChannelCenterFrequencySegment0 (void) const;
/*
* Return the Channel Center Frequency Segment 1 field in the VHT Operation information element.
*
* \return the Channel Center Frequency Segment 1 field in the VHT Operation information element
*/
uint8_t GetChannelCenterFrequencySegment1 (void) const;
/*
* Return the Basic VHT-MCS And Nss field in the VHT Operation information element.
*
* \return the Basic VHT-MCS And Nss field in the VHT Operation information element
*/
uint16_t GetBasicVhtMcsAndNssSet (void) const;
WifiInformationElementId ElementId () const;
uint8_t GetInformationFieldSize () const;
void SerializeInformationField (Buffer::Iterator start) const;
uint8_t DeserializeInformationField (Buffer::Iterator start, uint8_t length);
/**
* This information element is a bit special in that it is only
* included if the STA is an HT STA. To support this we
* override the Serialize and GetSerializedSize methods of
* WifiInformationElement.
*
* \param start
*
* \return an iterator
*/
Buffer::Iterator Serialize (Buffer::Iterator start) const;
/**
* Return the serialized size of this HT Operations IE.
*
* \return the serialized size of this HT Operations IE
*/
uint16_t GetSerializedSize () const;
private:
//VHT Operation Information
uint8_t m_channelWidth;
uint8_t m_channelCenterFrequencySegment0;
uint8_t m_channelCenterFrequencySegment1;
//Basic VHT-MCSS and NSS Set
uint16_t m_basicVhtMcsAndNssSet;
//This is used to decide whether this element should be added to the frame or not
uint8_t m_vhtSupported;
};
std::ostream &operator << (std::ostream &os, const VhtOperation &VhtOperation);
std::istream &operator >> (std::istream &is, VhtOperation &VhtOperation);
ATTRIBUTE_HELPER_HEADER (VhtOperation);
} //namespace ns3
#endif /* VHT_OPERATION_H */

View File

@@ -1911,6 +1911,18 @@ WifiRemoteStationManager::GetNNonErpSupported (const WifiRemoteStation *station)
return size;
}
uint32_t
WifiRemoteStationManager::GetChannelWidthSupported (Mac48Address address) const
{
return LookupState (address)->m_channelWidth;
}
bool
WifiRemoteStationManager::GetVhtSupported (Mac48Address address) const
{
return LookupState (address)->m_vhtSupported;
}
void
WifiRemoteStationManager::SetDefaultTxPowerLevel (uint8_t txPower)
{

View File

@@ -362,6 +362,23 @@ public:
* \param mcs the WifiMode supported by the station
*/
void AddSupportedMcs (Mac48Address address, WifiMode mcs);
/**
* Return the channel width supported by the station.
*
* \param address the address of the station
*
* \return he channel width supported by the station
*/
uint32_t GetChannelWidthSupported (Mac48Address address) const;
/**
* Return whether the station supports VHT or not.
*
* \param address the address of the station
*
* \return true if VHT is supported by the station,
* false otherwise
*/
bool GetVhtSupported (Mac48Address address) const;
/**
* Return a mode for non-unicast packets.

View File

@@ -79,6 +79,7 @@ def build(bld):
'model/vht-capabilities.cc',
'model/erp-information.cc',
'model/ht-operation.cc',
'model/vht-operation.cc',
'model/dsss-parameter-set.cc',
'model/edca-parameter-set.cc',
'helper/wifi-radio-energy-model-helper.cc',
@@ -184,6 +185,7 @@ def build(bld):
'model/vht-capabilities.h',
'model/erp-information.h',
'model/ht-operation.h',
'model/vht-operation.h',
'model/dsss-parameter-set.h',
'model/edca-parameter-set.h',
'helper/wifi-radio-energy-model-helper.h',