diff --git a/src/wifi/model/dsss-phy.cc b/src/wifi/model/dsss-phy.cc index 1420c010f..291c97414 100644 --- a/src/wifi/model/dsss-phy.cc +++ b/src/wifi/model/dsss-phy.cc @@ -285,8 +285,12 @@ DsssPhy::CreateDsssMode (std::string uniqueName, return WifiModeFactory::CreateWifiMode (uniqueName, modClass, true, - GetCodeRate (uniqueName), - GetConstellationSize (uniqueName)); + MakeBoundCallback (&GetCodeRate, uniqueName), + MakeBoundCallback (&GetConstellationSize, uniqueName), + MakeBoundCallback (&GetDataRate, uniqueName, modClass), + MakeBoundCallback (&GetDataRate, uniqueName, modClass), //PhyRate is equivalent to DataRate + MakeCallback (&GetDataRateFromTxVector), + MakeCallback (&IsModeAllowed)); } WifiCodeRate diff --git a/src/wifi/model/erp-ofdm-phy.cc b/src/wifi/model/erp-ofdm-phy.cc index 85a08c1e3..beb517f0a 100644 --- a/src/wifi/model/erp-ofdm-phy.cc +++ b/src/wifi/model/erp-ofdm-phy.cc @@ -163,8 +163,12 @@ ErpOfdmPhy::CreateErpOfdmMode (std::string uniqueName, bool isMandatory) return WifiModeFactory::CreateWifiMode (uniqueName, WIFI_MOD_CLASS_ERP_OFDM, isMandatory, - GetCodeRate (uniqueName), - GetConstellationSize (uniqueName)); + MakeBoundCallback (&GetCodeRate, uniqueName), + MakeBoundCallback (&GetConstellationSize, uniqueName), + MakeBoundCallback (&GetPhyRate, uniqueName), + MakeBoundCallback (&GetDataRate, uniqueName), + MakeCallback (&GetDataRateFromTxVector), + MakeCallback (&IsModeAllowed)); } WifiCodeRate diff --git a/src/wifi/model/he-phy.cc b/src/wifi/model/he-phy.cc index a058e5739..b3fbbaaef 100644 --- a/src/wifi/model/he-phy.cc +++ b/src/wifi/model/he-phy.cc @@ -999,7 +999,14 @@ HePhy::CreateHeMcs (uint8_t index) NS_ASSERT_MSG (index <= 11, "HeMcs index must be <= 11!"); return WifiModeFactory::CreateWifiMcs ("HeMcs" + std::to_string (index), index, - WIFI_MOD_CLASS_HE); + WIFI_MOD_CLASS_HE, + MakeBoundCallback (&GetCodeRate, index), + MakeBoundCallback (&GetConstellationSize, index), + MakeBoundCallback (&GetPhyRate, index), + MakeBoundCallback (&GetDataRate, index), + MakeCallback (&GetDataRateFromTxVector), + MakeBoundCallback (&GetNonHtReferenceRate, index), + MakeCallback (&IsModeAllowed)); } WifiCodeRate diff --git a/src/wifi/model/ht-phy.cc b/src/wifi/model/ht-phy.cc index 5ba39dbc0..1c725e41d 100644 --- a/src/wifi/model/ht-phy.cc +++ b/src/wifi/model/ht-phy.cc @@ -560,7 +560,14 @@ HtPhy::CreateHtMcs (uint8_t index) NS_ASSERT_MSG (index <= 31, "HtMcs index must be <= 31!"); return WifiModeFactory::CreateWifiMcs ("HtMcs" + std::to_string (index), index, - WIFI_MOD_CLASS_HT); + WIFI_MOD_CLASS_HT, + MakeBoundCallback (&GetHtCodeRate, index), + MakeBoundCallback (&GetHtConstellationSize, index), + MakeBoundCallback (&GetPhyRate, index), + MakeBoundCallback (&GetDataRate, index), + MakeCallback (&GetDataRateFromTxVector), + MakeBoundCallback (&GetNonHtReferenceRate, index), + MakeCallback (&IsModeAllowed)); } WifiCodeRate diff --git a/src/wifi/model/ofdm-phy.cc b/src/wifi/model/ofdm-phy.cc index ecbd963f0..95fde28ed 100644 --- a/src/wifi/model/ofdm-phy.cc +++ b/src/wifi/model/ofdm-phy.cc @@ -496,8 +496,12 @@ OfdmPhy::CreateOfdmMode (std::string uniqueName, bool isMandatory) return WifiModeFactory::CreateWifiMode (uniqueName, WIFI_MOD_CLASS_OFDM, isMandatory, - GetCodeRate (uniqueName), - GetConstellationSize (uniqueName)); + MakeBoundCallback (&GetCodeRate, uniqueName), + MakeBoundCallback (&GetConstellationSize, uniqueName), + MakeBoundCallback (&GetPhyRate, uniqueName), + MakeBoundCallback (&GetDataRate, uniqueName), + MakeCallback (&GetDataRateFromTxVector), + MakeCallback (&IsModeAllowed)); } WifiCodeRate diff --git a/src/wifi/model/vht-phy.cc b/src/wifi/model/vht-phy.cc index b1925d968..2080b3704 100644 --- a/src/wifi/model/vht-phy.cc +++ b/src/wifi/model/vht-phy.cc @@ -376,7 +376,14 @@ VhtPhy::CreateVhtMcs (uint8_t index) NS_ASSERT_MSG (index <= 9, "VhtMcs index must be <= 9!"); return WifiModeFactory::CreateWifiMcs ("VhtMcs" + std::to_string (index), index, - WIFI_MOD_CLASS_VHT); + WIFI_MOD_CLASS_VHT, + MakeBoundCallback (&GetCodeRate, index), + MakeBoundCallback (&GetConstellationSize, index), + MakeBoundCallback (&GetPhyRate, index), + MakeBoundCallback (&GetDataRate, index), + MakeCallback (&GetDataRateFromTxVector), + MakeBoundCallback (&GetNonHtReferenceRate, index), + MakeBoundCallback (&IsModeAllowed, index)); } WifiCodeRate diff --git a/src/wifi/model/wifi-mode.cc b/src/wifi/model/wifi-mode.cc index ff59be407..dba3efe04 100644 --- a/src/wifi/model/wifi-mode.cc +++ b/src/wifi/model/wifi-mode.cc @@ -55,45 +55,14 @@ bool WifiMode::IsAllowed (uint16_t channelWidth, uint8_t nss) const { WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid); - if (item->modClass == WIFI_MOD_CLASS_VHT) - { - if (item->mcsValue == 9 && channelWidth == 20 && nss != 3) - { - return false; - } - if (item->mcsValue == 6 && channelWidth == 80 && nss == 3) - { - return false; - } - } - return true; + return item->IsModeAllowedCallback (channelWidth, nss); } uint64_t WifiMode::GetPhyRate (uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const { - uint64_t dataRate, phyRate; - dataRate = GetDataRate (channelWidth, guardInterval, nss); - switch (GetCodeRate ()) - { - case WIFI_CODE_RATE_5_6: - phyRate = dataRate * 6 / 5; - break; - case WIFI_CODE_RATE_3_4: - phyRate = dataRate * 4 / 3; - break; - case WIFI_CODE_RATE_2_3: - phyRate = dataRate * 3 / 2; - break; - case WIFI_CODE_RATE_1_2: - phyRate = dataRate * 2 / 1; - break; - case WIFI_CODE_RATE_UNDEFINED: - default: - phyRate = dataRate; - break; - } - return phyRate; + WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid); + return item->GetPhyRateCallback (channelWidth, guardInterval, nss); } uint64_t @@ -111,13 +80,8 @@ WifiMode::GetDataRate (uint16_t channelWidth) const uint64_t WifiMode::GetDataRate (WifiTxVector txVector, uint16_t staId) const { - uint16_t bw = txVector.GetChannelWidth (); - uint8_t nss = txVector.GetNss (staId); - if (txVector.IsMu ()) - { - bw = HeRu::GetBandwidth (txVector.GetRu (staId).ruType); - } - return GetDataRate (bw, txVector.GetGuardInterval (), nss); + WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid); + return item->GetDataRateFromTxVectorCallback (txVector, staId); } uint64_t @@ -125,318 +89,21 @@ WifiMode::GetDataRate (uint16_t channelWidth, uint16_t guardInterval, uint8_t ns { NS_ASSERT (nss <= 8); WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid); - uint64_t dataRate = 0; - uint16_t usableSubCarriers = 0; - double symbolRate = 0; - double codingRate = 0; - uint16_t numberOfBitsPerSubcarrier = static_cast (log2 (GetConstellationSize ())); - if (item->modClass == WIFI_MOD_CLASS_DSSS) - { - dataRate = ((11000000 / 11) * numberOfBitsPerSubcarrier); - } - else if (item->modClass == WIFI_MOD_CLASS_HR_DSSS) - { - dataRate = ((11000000 / 8) * numberOfBitsPerSubcarrier); - } - else if (item->modClass == WIFI_MOD_CLASS_OFDM || item->modClass == WIFI_MOD_CLASS_ERP_OFDM) - { - usableSubCarriers = 48; - switch (channelWidth) - { - case 20: - default: - symbolRate = (1 / 4.0) * 1e6; - break; - case 10: - symbolRate = (1 / 8.0) * 1e6; - break; - case 5: - symbolRate = (1 / 16.0) * 1e6; - break; - } - - switch (GetCodeRate ()) - { - case WIFI_CODE_RATE_3_4: - codingRate = (3.0 / 4.0); - break; - case WIFI_CODE_RATE_2_3: - codingRate = (2.0 / 3.0); - break; - case WIFI_CODE_RATE_1_2: - codingRate = (1.0 / 2.0); - break; - case WIFI_CODE_RATE_UNDEFINED: - default: - NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined"); - break; - } - - dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate)); - } - else if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT) - { - if (item->modClass == WIFI_MOD_CLASS_VHT) - { - NS_ASSERT_MSG (IsAllowed (channelWidth, nss), "VHT MCS " << +item->mcsValue << " forbidden at " << channelWidth << " MHz when NSS is " << +nss); - } - else - { - NS_ASSERT (nss <= 4); - } - - NS_ASSERT (guardInterval == 800 || guardInterval == 400); - symbolRate = (1 / (3.2 + (static_cast (guardInterval) / 1000))) * 1e6; - - if (item->modClass == WIFI_MOD_CLASS_HT) - { - switch (channelWidth) - { - case 20: - default: - usableSubCarriers = 52; - break; - case 40: - case 80: - case 160: - usableSubCarriers = 108; - break; - } - } - else //WIFI_MOD_CLASS_VHT - { - switch (channelWidth) - { - case 20: - default: - usableSubCarriers = 52; - break; - case 40: - usableSubCarriers = 108; - break; - case 80: - usableSubCarriers = 234; - break; - case 160: - usableSubCarriers = 468; - break; - } - } - - switch (GetCodeRate ()) - { - case WIFI_CODE_RATE_5_6: - codingRate = (5.0 / 6.0); - break; - case WIFI_CODE_RATE_3_4: - codingRate = (3.0 / 4.0); - break; - case WIFI_CODE_RATE_2_3: - codingRate = (2.0 / 3.0); - break; - case WIFI_CODE_RATE_1_2: - codingRate = (1.0 / 2.0); - break; - case WIFI_CODE_RATE_UNDEFINED: - default: - NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined with nss: " << +nss); - break; - } - - dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate)); - } - else if (item->modClass == WIFI_MOD_CLASS_HE) - { - NS_ASSERT (guardInterval == 800 || guardInterval == 1600 || guardInterval == 3200); - symbolRate = (1 / (12.8 + (static_cast (guardInterval) / 1000))) * 1e6; - - switch (channelWidth) - { - case 2: //26-tone RU - usableSubCarriers = 24; - break; - case 4: //52-tone RU - usableSubCarriers = 48; - break; - case 8: //106-tone RU - usableSubCarriers = 102; - break; - case 20: - default: - usableSubCarriers = 234; - break; - case 40: - usableSubCarriers = 468; - break; - case 80: - usableSubCarriers = 980; - break; - case 160: - usableSubCarriers = 1960; - break; - } - - switch (GetCodeRate ()) - { - case WIFI_CODE_RATE_5_6: - codingRate = (5.0 / 6.0); - break; - case WIFI_CODE_RATE_3_4: - codingRate = (3.0 / 4.0); - break; - case WIFI_CODE_RATE_2_3: - codingRate = (2.0 / 3.0); - break; - case WIFI_CODE_RATE_1_2: - codingRate = (1.0 / 2.0); - break; - case WIFI_CODE_RATE_UNDEFINED: - default: - NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined with nss: " << +nss); - break; - } - - dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate)); - } - else - { - NS_ASSERT ("undefined datarate for the modulation class!"); - } - dataRate *= nss; // number of spatial streams - return dataRate; + return item->GetDataRateCallback (channelWidth, guardInterval, nss); } WifiCodeRate WifiMode::GetCodeRate (void) const { WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid); - if (item->modClass == WIFI_MOD_CLASS_HT) - { - switch (item->mcsValue % 8) - { - case 0: - case 1: - case 3: - return WIFI_CODE_RATE_1_2; - case 2: - case 4: - case 6: - return WIFI_CODE_RATE_3_4; - case 5: - return WIFI_CODE_RATE_2_3; - case 7: - return WIFI_CODE_RATE_5_6; - default: - return WIFI_CODE_RATE_UNDEFINED; - } - } - else if (item->modClass == WIFI_MOD_CLASS_VHT) - { - switch (item->mcsValue) - { - case 0: - case 1: - case 3: - return WIFI_CODE_RATE_1_2; - case 2: - case 4: - case 6: - case 8: - return WIFI_CODE_RATE_3_4; - case 5: - return WIFI_CODE_RATE_2_3; - case 7: - case 9: - return WIFI_CODE_RATE_5_6; - default: - return WIFI_CODE_RATE_UNDEFINED; - } - } - else if (item->modClass == WIFI_MOD_CLASS_HE) - { - switch (item->mcsValue) - { - case 0: - case 1: - case 3: - return WIFI_CODE_RATE_1_2; - case 2: - case 4: - case 6: - case 8: - case 10: - return WIFI_CODE_RATE_3_4; - case 5: - return WIFI_CODE_RATE_2_3; - case 7: - case 9: - case 11: - return WIFI_CODE_RATE_5_6; - default: - return WIFI_CODE_RATE_UNDEFINED; - } - } - else - { - return item->codingRate; - } + return item->GetCodeRateCallback (); } uint16_t WifiMode::GetConstellationSize (void) const { WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid); - if (item->modClass == WIFI_MOD_CLASS_HT) - { - switch (item->mcsValue % 8) - { - case 0: - return 2; - case 1: - case 2: - return 4; - case 3: - case 4: - return 16; - case 5: - case 6: - case 7: - return 64; - default: - return 0; - } - } - else if (item->modClass == WIFI_MOD_CLASS_VHT || item->modClass == WIFI_MOD_CLASS_HE) - { - switch (item->mcsValue) - { - case 0: - return 2; - case 1: - case 2: - return 4; - case 3: - case 4: - return 16; - case 5: - case 6: - case 7: - return 64; - case 8: - case 9: - return 256; - case 10: - case 11: - NS_ASSERT (item->modClass != WIFI_MOD_CLASS_VHT); - return 1024; - default: - return 0; - } - } - else - { - return item->constellationSize; - } + return item->GetConstellationSizeCallback (); } std::string @@ -486,89 +153,9 @@ WifiMode::GetModulationClass () const uint64_t WifiMode::GetNonHtReferenceRate (void) const { - uint64_t dataRate; WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid); - if (item->modClass >= WIFI_MOD_CLASS_HT) - { - WifiCodeRate codeRate = GetCodeRate (); - switch (GetConstellationSize ()) - { - case 2: - if (codeRate == WIFI_CODE_RATE_1_2) - { - dataRate = 6000000; - } - else if (codeRate == WIFI_CODE_RATE_3_4) - { - dataRate = 9000000; - } - else - { - NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation"); - } - break; - case 4: - if (codeRate == WIFI_CODE_RATE_1_2) - { - dataRate = 12000000; - } - else if (codeRate == WIFI_CODE_RATE_3_4) - { - dataRate = 18000000; - } - else - { - NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation"); - } - break; - case 16: - if (codeRate == WIFI_CODE_RATE_1_2) - { - dataRate = 24000000; - } - else if (codeRate == WIFI_CODE_RATE_3_4) - { - dataRate = 36000000; - } - else - { - NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation"); - } - break; - case 64: - if (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3) - { - dataRate = 48000000; - } - else if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6) - { - dataRate = 54000000; - } - else - { - NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation"); - } - break; - case 256: - case 1024: - if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6) - { - dataRate = 54000000; - } - else - { - NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation"); - } - break; - default: - NS_FATAL_ERROR ("Wrong constellation size"); - } - } - else - { - NS_FATAL_ERROR ("Trying to get reference rate for a non-HT rate"); - } - return dataRate; + NS_ASSERT_MSG (!item->GetNonHtReferenceRateCallback.IsNull (), "Trying to get HT reference rate for a non-HT rate"); + return item->GetNonHtReferenceRateCallback (); } bool @@ -674,8 +261,12 @@ WifiMode WifiModeFactory::CreateWifiMode (std::string uniqueName, WifiModulationClass modClass, bool isMandatory, - WifiCodeRate codingRate, - uint16_t constellationSize) + CodeRateCallback codeRateCallback, + ConstellationSizeCallback constellationSizeCallback, + PhyRateCallback phyRateCallback, + DataRateCallback dataRateCallback, + DataRateFromTxVectorCallback dataRateFromTxVectorCallback, + ModeAllowedCallback isModeAllowedCallback) { WifiModeFactory *factory = GetFactory (); uint32_t uid = factory->AllocateUid (uniqueName); @@ -684,7 +275,6 @@ WifiModeFactory::CreateWifiMode (std::string uniqueName, item->modClass = modClass; //The modulation class for this WifiMode must be valid. NS_ASSERT (modClass != WIFI_MOD_CLASS_UNKNOWN); - item->codingRate = codingRate; //Check for compatibility between modulation class and coding //rate. If modulation class is DSSS then coding rate must be @@ -692,14 +282,20 @@ WifiModeFactory::CreateWifiMode (std::string uniqueName, //assertion, but it seems better to always give the error (i.e., //not only in non-optimised builds) and the cycles that extra test //here costs are only suffered at simulation setup. - if ((codingRate == WIFI_CODE_RATE_UNDEFINED) && modClass != WIFI_MOD_CLASS_DSSS && modClass != WIFI_MOD_CLASS_HR_DSSS) + if ((codeRateCallback () == WIFI_CODE_RATE_UNDEFINED) && modClass != WIFI_MOD_CLASS_DSSS && modClass != WIFI_MOD_CLASS_HR_DSSS) { NS_FATAL_ERROR ("Error in creation of WifiMode named " << uniqueName << std::endl << "Code rate must be WIFI_CODE_RATE_UNDEFINED iff Modulation Class is WIFI_MOD_CLASS_DSSS or WIFI_MOD_CLASS_HR_DSSS"); } - item->constellationSize = constellationSize; item->isMandatory = isMandatory; + item->GetCodeRateCallback = codeRateCallback; + item->GetConstellationSizeCallback = constellationSizeCallback; + item->GetPhyRateCallback = phyRateCallback; + item->GetDataRateCallback = dataRateCallback; + item->GetDataRateFromTxVectorCallback = dataRateFromTxVectorCallback; + item->GetNonHtReferenceRateCallback = MakeNullCallback (); + item->IsModeAllowedCallback = isModeAllowedCallback; NS_ASSERT (modClass < WIFI_MOD_CLASS_HT); //fill unused MCS item with a dummy value @@ -711,7 +307,14 @@ WifiModeFactory::CreateWifiMode (std::string uniqueName, WifiMode WifiModeFactory::CreateWifiMcs (std::string uniqueName, uint8_t mcsValue, - WifiModulationClass modClass) + WifiModulationClass modClass, + CodeRateCallback codeRateCallback, + ConstellationSizeCallback constellationSizeCallback, + PhyRateCallback phyRateCallback, + DataRateCallback dataRateCallback, + DataRateFromTxVectorCallback dataRateFromTxVectorCallback, + NonHtReferenceRateCallback nonHtReferenceRateCallback, + ModeAllowedCallback isModeAllowedCallback) { WifiModeFactory *factory = GetFactory (); uint32_t uid = factory->AllocateUid (uniqueName); @@ -722,9 +325,15 @@ WifiModeFactory::CreateWifiMcs (std::string uniqueName, NS_ASSERT (modClass >= WIFI_MOD_CLASS_HT); item->mcsValue = mcsValue; + item->GetCodeRateCallback = codeRateCallback; + item->GetConstellationSizeCallback = constellationSizeCallback; + item->GetPhyRateCallback = phyRateCallback; + item->GetDataRateCallback = dataRateCallback; + item->GetDataRateFromTxVectorCallback = dataRateFromTxVectorCallback; + item->GetNonHtReferenceRateCallback = nonHtReferenceRateCallback; + item->IsModeAllowedCallback = isModeAllowedCallback; + //fill unused items with dummy values - item->constellationSize = 0; - item->codingRate = WIFI_CODE_RATE_UNDEFINED; item->isMandatory = false; return WifiMode (uid); @@ -801,10 +410,15 @@ WifiModeFactory::GetFactory (void) WifiModeItem *item = factory.Get (uid); item->uniqueUid = "Invalid-WifiMode"; item->modClass = WIFI_MOD_CLASS_UNKNOWN; - item->constellationSize = 0; - item->codingRate = WIFI_CODE_RATE_UNDEFINED; item->isMandatory = false; item->mcsValue = 0; + item->GetCodeRateCallback = MakeNullCallback (); + item->GetConstellationSizeCallback = MakeNullCallback (); + item->GetPhyRateCallback = MakeNullCallback (); + item->GetDataRateCallback = MakeNullCallback (); + item->GetDataRateFromTxVectorCallback = MakeNullCallback (); + item->GetNonHtReferenceRateCallback = MakeNullCallback (); + item->IsModeAllowedCallback = MakeNullCallback (); isFirstTime = false; } return &factory; diff --git a/src/wifi/model/wifi-mode.h b/src/wifi/model/wifi-mode.h index 8e659fa6a..7fa57c088 100644 --- a/src/wifi/model/wifi-mode.h +++ b/src/wifi/model/wifi-mode.h @@ -24,6 +24,7 @@ #include "wifi-phy-common.h" #include "ns3/attribute-helper.h" +#include "ns3/callback.h" #include namespace ns3 { @@ -266,17 +267,84 @@ typedef WifiModeList::const_iterator WifiModeListIterator; class WifiModeFactory { public: + // Typedefs for callbacks used by WifiModeItem + /** + * Typedef for callback used to retrieve code rate of a WifiMode + * \return the code rate of the WifiMode. + */ + typedef Callback CodeRateCallback; + /** + * Typedef for callback used to retrieve constellation size of a WifiMode + * \return the size of modulation constellation of the WifiMode. + */ + typedef Callback ConstellationSizeCallback; + /** + * Typedef for callback used to calculate PHY rate of a WifiMode + * + * \param channelWidth the channel width in MHz + * \param guardInterval the guard interval duration in nanoseconds + * \param nss the number of streams + * \return the physical bit rate of the signal in bps. + */ + typedef Callback PhyRateCallback; + /** + * Typedef for callback used to calculate data rate of a WifiMode + * + * \param channelWidth the channel width in MHz + * \param guardInterval the guard interval duration in nanoseconds + * \param nss the number of streams + * \return the data rate of the signal in bps. + */ + typedef Callback DataRateCallback; + /** + * Typedef for callback used to calculate data rate of a WifiMode + * from a TXVECTOR. This is mostly useful in HE or later amendments. + * For the others it's a simple wrapper of \see DataRateCallback. + * + * \param txVector the TXVECTOR used for the transmission + * \param staId the station ID + * \return the data rate of the signal in bps. + */ + typedef Callback DataRateFromTxVectorCallback; + /** + * Typedef for callback used to calculate Non-HT Reference Rate of + * an MCS defined in HT or later amendment. For Non-HT modes (DSSS, OFDM, + * etc) this should be defined as null. + * + * \return the rate (in bps) of the non-HT Reference Rate. + */ + typedef Callback NonHtReferenceRateCallback; + /** + * Typedef for callback used to check whether the combination of is allowed + * + * \param channelWidth the channel width in MHz + * \param nss the number of streams + * \return true if combination of current WifiMode and supplied parameters is allowed. + */ + typedef Callback ModeAllowedCallback; + /** * \param uniqueName the name of the associated WifiMode. This name * must be unique across _all_ instances. * \param modClass the class of modulation * \param isMandatory true if this WifiMode is mandatory, false otherwise. - * \param codingRate if convolutional coding is used for this rate - * then this parameter specifies the convolutional coding rate - * used. If there is no explicit convolutional coding step (e.g., - * for DSSS rates) then the caller should set this parameter to - * WIFI_CODE_RATE_UNCODED. - * \param constellationSize the order of the constellation used. + * \param codeRateCallback a callback function to retrieve coding rate of + * this WifiMode. If convolutional coding is used for this rate + * then the callback returns the convolutional coding rate used. If + * there is no explicit convolutional coding step (e.g., for DSSS + * rates) then the callback should returns WIFI_CODE_RATE_UNDEFINED. + * \param constellationSizeCallback a callback function that returns the + * order of the constellation used. + * \param phyRateCallback a callback function to calculate the PHY rate (in + * bps) of this WifiMode. + * \param dataRateCallback a callback function to calculate the data rate + * (in bps) of this WifiMode. + * \param dataRateFromTxVectorCallback a callback function to calculate the data rate + * (in bps) of this WifiMode using a TXVECTOR as input. + * \param isModeAllowedCallback a callback function to check whether a + * specific combination of this WifiMode, channel width (MHz), and + * NSS are allowed. * * \return WifiMode * @@ -285,22 +353,48 @@ public: static WifiMode CreateWifiMode (std::string uniqueName, WifiModulationClass modClass, bool isMandatory, - WifiCodeRate codingRate, - uint16_t constellationSize); + CodeRateCallback codeRateCallback, + ConstellationSizeCallback constellationSizeCallback, + PhyRateCallback phyRateCallback, + DataRateCallback dataRateCallback, + DataRateFromTxVectorCallback dataRateFromTxVectorCallback, + ModeAllowedCallback isModeAllowedCallback); /** * \param uniqueName the name of the associated WifiMode. This name * must be unique across _all_ instances. * \param mcsValue the MCS value * \param modClass the class of modulation + * \param codeRateCallback a callback function that returns the coding rate + * of this WifiMode. + * \param constellationSizeCallback a callback function that returns the size + * of modulation constellation of this WifiMode. + * \param phyRateCallback a callback function to calculate the PHY rate (in + * bps) of this WifiMode. + * \param dataRateCallback a callback function to calculate the data rate (in + * bps) of this WifiMode. + * \param dataRateFromTxVectorCallback a callback function to calculate the data rate + * (in bps) of this WifiMode using a TXVECTOR as input. + * \param nonHtReferenceRateCallback a callback function to calculate the rate + * (in bps) of the non-HT Reference Rate of this WifiMode. + * \param isModeAllowedCallback a callback function to calculate whether a + * combination of is allowed for this WifiMode. * * \return WifiMode * - * Create a HT WifiMode. + * Create a HT or later WifiMode. */ static WifiMode CreateWifiMcs (std::string uniqueName, uint8_t mcsValue, - WifiModulationClass modClass); + WifiModulationClass modClass, + CodeRateCallback codeRateCallback, + ConstellationSizeCallback constellationSizeCallback, + PhyRateCallback phyRateCallback, + DataRateCallback dataRateCallback, + DataRateFromTxVectorCallback dataRateFromTxVectorCallback, + NonHtReferenceRateCallback nonHtReferenceRateCallback, + ModeAllowedCallback isModeAllowedCallback); private: @@ -323,12 +417,17 @@ private: */ struct WifiModeItem { - std::string uniqueUid; ///< unique UID + std::string uniqueUid; ///< unique UID WifiModulationClass modClass; ///< modulation class - uint16_t constellationSize; ///< constellation size - WifiCodeRate codingRate; ///< coding rate - bool isMandatory; ///< flag to indicate whether this mode is mandatory - uint8_t mcsValue; ///< MCS value + bool isMandatory; ///< flag to indicate whether this mode is mandatory + uint8_t mcsValue; ///< MCS value + CodeRateCallback GetCodeRateCallback; ///< Callback to retrieve code rate of this WifiModeItem + ConstellationSizeCallback GetConstellationSizeCallback; ///< Callback to retrieve constellation size of this WifiModeItem + PhyRateCallback GetPhyRateCallback; ///< Callback to calculate PHY rate in bps of this WifiModeItem + DataRateCallback GetDataRateCallback; ///< Callback to calculate data rate in bps of this WifiModeItem + DataRateFromTxVectorCallback GetDataRateFromTxVectorCallback; ///< Callback to calculate data rate in bps of this WifiModeItem using a TXVECTOR as input + NonHtReferenceRateCallback GetNonHtReferenceRateCallback; ///< Callback to calculate non-HT reference rate of this WifiModeItem + ModeAllowedCallback IsModeAllowedCallback; ///< Callback to check whether the combination of is allowed }; /**