diff --git a/src/mesh/model/dot11s/airtime-metric.cc b/src/mesh/model/dot11s/airtime-metric.cc index c7a08a98a..9384701cd 100644 --- a/src/mesh/model/dot11s/airtime-metric.cc +++ b/src/mesh/model/dot11s/airtime-metric.cc @@ -95,7 +95,7 @@ AirtimeLinkMetricCalculator::CalculateMetric (Mac48Address peerAddress, PtrGetPifs () + mac->GetSlot () + mac->GetEifsNoDifs () + //DIFS + SIFS + AckTxTime = PIFS + SLOT + EifsNoDifs - mac->GetWifiPhy ()->CalculateTxDuration (m_testFrame->GetSize (), txVector, WIFI_PREAMBLE_LONG) + mac->GetWifiPhy ()->CalculateTxDuration (m_testFrame->GetSize (), txVector, WIFI_PREAMBLE_LONG, mac->GetWifiPhy ()->GetFrequency()) ).GetMicroSeconds () / (10.24 * (1.0 - failAvg))); return metric; } diff --git a/src/wifi/model/mac-low.cc b/src/wifi/model/mac-low.cc index 5c5f60780..5546e6412 100644 --- a/src/wifi/model/mac-low.cc +++ b/src/wifi/model/mac-low.cc @@ -982,7 +982,7 @@ MacLow::GetAckDuration (WifiTxVector ackTxVector) const preamble= WIFI_PREAMBLE_HT_MF; else preamble=WIFI_PREAMBLE_LONG; - return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble); + return m_phy->CalculateTxDuration (GetAckSize (), ackTxVector, preamble, m_phy->GetFrequency()); } Time MacLow::GetBlockAckDuration (Mac48Address to, WifiTxVector blockAckReqTxVector, enum BlockAckType type) const @@ -1000,7 +1000,7 @@ MacLow::GetBlockAckDuration (Mac48Address to, WifiTxVector blockAckReqTxVector, preamble= WIFI_PREAMBLE_HT_MF; else preamble=WIFI_PREAMBLE_LONG; - return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble); + return m_phy->CalculateTxDuration (GetBlockAckSize (type), blockAckReqTxVector, preamble, m_phy->GetFrequency()); } Time MacLow::GetCtsDuration (Mac48Address to, WifiTxVector rtsTxVector) const @@ -1017,7 +1017,7 @@ MacLow::GetCtsDuration (WifiTxVector ctsTxVector) const preamble= WIFI_PREAMBLE_HT_MF; else preamble=WIFI_PREAMBLE_LONG; - return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble); + return m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency()); } uint32_t MacLow::GetCtsSize (void) const @@ -1105,7 +1105,7 @@ MacLow::CalculateOverallTxTime (Ptr packet, { preamble = WIFI_PREAMBLE_LONG; } - txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble); + txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency()); txTime += GetCtsDuration (hdr->GetAddr1 (), rtsTxVector); txTime += Time (GetSifs () * 2); } @@ -1118,7 +1118,7 @@ MacLow::CalculateOverallTxTime (Ptr packet, else preamble=WIFI_PREAMBLE_LONG; uint32_t dataSize = GetSize (packet, hdr); - txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble); + txTime += m_phy->CalculateTxDuration (dataSize, dataTxVector, preamble, m_phy->GetFrequency()); if (params.MustWaitAck ()) { txTime += GetSifs (); @@ -1145,7 +1145,7 @@ MacLow::CalculateTransmissionTime (Ptr packet, else preamble=WIFI_PREAMBLE_LONG; txTime += GetSifs (); - txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble); + txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataTxVector, preamble, m_phy->GetFrequency()); } return txTime; } @@ -1183,7 +1183,7 @@ MacLow::NotifyNav (Ptr packet,const WifiMacHeader &hdr, WifiMode t cts.SetType (WIFI_MAC_CTL_CTS); WifiTxVector txVector=GetRtsTxVector (packet, &hdr); Time navCounterResetCtsMissedDelay = - m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble) + + m_phy->CalculateTxDuration (cts.GetSerializedSize (), txVector, preamble, m_phy->GetFrequency()) + Time (2 * GetSifs ()) + Time (2 * GetSlotTime ()); m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay, &MacLow::NavCounterResetCtsMissed, this, @@ -1385,13 +1385,13 @@ MacLow::SendRtsForPacket (void) duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxVector); duration += GetSifs (); duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), - dataTxVector, preamble); + dataTxVector, preamble, m_phy->GetFrequency()); duration += GetSifs (); duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector); } rts.SetDuration (duration); - Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble); + Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxVector, preamble, m_phy->GetFrequency()); Time timerDelay = txDuration + GetCtsTimeout (); NS_ASSERT (m_ctsTimeoutEvent.IsExpired ()); @@ -1419,7 +1419,7 @@ MacLow::StartDataTxTimers (WifiTxVector dataTxVector) else preamble=WIFI_PREAMBLE_LONG; - Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble); + Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxVector, preamble, m_phy->GetFrequency()); if (m_txParams.MustWaitNormalAck ()) { Time timerDelay = txDuration + GetAckTimeout (); @@ -1522,7 +1522,7 @@ MacLow::SendDataPacket (void) { duration += GetSifs (); duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), - dataTxVector, preamble); + dataTxVector, preamble, m_phy->GetFrequency()); if (m_txParams.MustWaitAck ()) { duration += GetSifs (); @@ -1582,7 +1582,7 @@ MacLow::SendCtsToSelf (void) WifiTxVector dataTxVector = GetDataTxVector (m_currentPacket, &m_currentHdr); duration += GetSifs (); duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket,&m_currentHdr), - dataTxVector, preamble); + dataTxVector, preamble, m_phy->GetFrequency()); if (m_txParams.MustWaitBasicBlockAck ()) { @@ -1603,7 +1603,7 @@ MacLow::SendCtsToSelf (void) { duration += GetSifs (); duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), - dataTxVector, preamble); + dataTxVector, preamble, m_phy->GetFrequency()); if (m_txParams.MustWaitCompressedBlockAck ()) { duration += GetSifs (); @@ -1626,7 +1626,7 @@ MacLow::SendCtsToSelf (void) ForwardDown (packet, &cts, ctsTxVector,preamble); - Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble); + Time txDuration = m_phy->CalculateTxDuration (GetCtsSize (), ctsTxVector, preamble, m_phy->GetFrequency()); txDuration += GetSifs (); NS_ASSERT (m_sendDataEvent.IsExpired ()); @@ -1697,7 +1697,7 @@ MacLow::SendDataAfterCts (Mac48Address source, Time duration, WifiMode txMode) newDuration += GetSifs (); newDuration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxVector); Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), - dataTxVector, preamble); + dataTxVector, preamble, m_phy->GetFrequency()); duration -= txDuration; duration -= GetSifs (); diff --git a/src/wifi/model/minstrel-wifi-manager.cc b/src/wifi/model/minstrel-wifi-manager.cc index 51a631476..9702ca1bd 100644 --- a/src/wifi/model/minstrel-wifi-manager.cc +++ b/src/wifi/model/minstrel-wifi-manager.cc @@ -139,7 +139,7 @@ MinstrelWifiManager::SetupPhy (Ptr phy) WifiMode mode = phy->GetMode (i); WifiTxVector txVector; txVector.SetMode(mode); - AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, txVector, WIFI_PREAMBLE_LONG)); + AddCalcTxTime (mode, phy->CalculateTxDuration (m_pktLen, txVector, WIFI_PREAMBLE_LONG, phy->GetFrequency())); } WifiRemoteStationManager::SetupPhy (phy); } diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index 42339e690..969b33f85 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -329,7 +329,7 @@ WifiPhy::GetPlcpPreambleDurationMicroSeconds (WifiMode payloadMode, WifiPreamble } double -WifiPhy::GetPayloadDurationMicroSeconds (uint32_t size, WifiTxVector txvector) +WifiPhy::GetPayloadDurationMicroSeconds (uint32_t size, WifiTxVector txvector, double frequency) { WifiMode payloadMode=txvector.GetMode(); @@ -418,9 +418,15 @@ WifiPhy::GetPayloadDurationMicroSeconds (uint32_t size, WifiTxVector txvector) double Nes=1; // IEEE Std 802.11n, section 20.3.11, equation (20-32) uint32_t numSymbols = lrint (m_Stbc*ceil ((16 + size * 8.0 + 6.0*Nes) / (m_Stbc* numDataBitsPerSymbol))); - - return numSymbols * symbolDurationUs; - + + if (frequency >= 2400 && frequency <= 2500) //at 2.4 GHz + { + return (numSymbols * symbolDurationUs) + 6; + } + else //at 5 GHz + { + return (numSymbols * symbolDurationUs); + } } case WIFI_MOD_CLASS_DSSS: // (Section 17.2.3.6 "Long PLCP LENGTH field"; IEEE Std 802.11-2012) @@ -436,14 +442,14 @@ WifiPhy::GetPayloadDurationMicroSeconds (uint32_t size, WifiTxVector txvector) } Time -WifiPhy::CalculateTxDuration (uint32_t size, WifiTxVector txvector, WifiPreamble preamble) +WifiPhy::CalculateTxDuration (uint32_t size, WifiTxVector txvector, WifiPreamble preamble, double frequency) { WifiMode payloadMode=txvector.GetMode(); double duration = GetPlcpPreambleDurationMicroSeconds (payloadMode, preamble) + GetPlcpHeaderDurationMicroSeconds (payloadMode, preamble) + GetPlcpHtSigHeaderDurationMicroSeconds (payloadMode, preamble) + GetPlcpHtTrainingSymbolDurationMicroSeconds (payloadMode, preamble,txvector) - + GetPayloadDurationMicroSeconds (size, txvector); + + GetPayloadDurationMicroSeconds (size, txvector, frequency); return MicroSeconds (duration); } diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 0027e7508..8f000fb36 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -281,10 +281,11 @@ public: * \param size the number of bytes in the packet to send * \param txvector the transmission parameters used for this packet * \param preamble the type of preamble to use for this packet. + * \param frequency the channel center frequency (MHz) * \return the total amount of time this PHY will stay busy for * the transmission of these bytes. */ - static Time CalculateTxDuration (uint32_t size, WifiTxVector txvector, enum WifiPreamble preamble); + static Time CalculateTxDuration (uint32_t size, WifiTxVector txvector, enum WifiPreamble preamble, double frequency); /** * \param payloadMode the WifiMode use for the transmission of the payload @@ -337,10 +338,11 @@ public: /** * \param size the number of bytes in the packet to send * \param txvector the transmission parameters used for this packet + * \param frequency the channel center frequency (MHz) * * \return the duration of the payload in microseconds */ - static double GetPayloadDurationMicroSeconds (uint32_t size, WifiTxVector txvector); + static double GetPayloadDurationMicroSeconds (uint32_t size, WifiTxVector txvector, double frequency); /** * The WifiPhy::GetNModes() and WifiPhy::GetMode() methods are used diff --git a/src/wifi/model/yans-wifi-phy.cc b/src/wifi/model/yans-wifi-phy.cc index f2aeb6079..af394a2b0 100644 --- a/src/wifi/model/yans-wifi-phy.cc +++ b/src/wifi/model/yans-wifi-phy.cc @@ -506,7 +506,7 @@ YansWifiPhy::StartReceivePacket (Ptr packet, NS_LOG_FUNCTION (this << packet << rxPowerDbm << txVector.GetMode()<< preamble); rxPowerDbm += m_rxGainDb; double rxPowerW = DbmToW (rxPowerDbm); - Time rxDuration = CalculateTxDuration (packet->GetSize (), txVector, preamble); + Time rxDuration = CalculateTxDuration (packet->GetSize (), txVector, preamble, GetFrequency()); WifiMode txMode = txVector.GetMode(); Time endRx = Simulator::Now () + rxDuration; @@ -631,7 +631,7 @@ YansWifiPhy::SendPacket (Ptr packet, WifiTxVector txVector, WifiPr return; } - Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, preamble); + Time txDuration = CalculateTxDuration (packet->GetSize (), txVector, preamble, GetFrequency()); if (m_state->IsStateRx ()) { m_endRxEvent.Cancel (); diff --git a/src/wifi/test/tx-duration-test.cc b/src/wifi/test/tx-duration-test.cc index fa443475a..d3ddab2f6 100644 --- a/src/wifi/test/tx-duration-test.cc +++ b/src/wifi/test/tx-duration-test.cc @@ -29,6 +29,9 @@ using namespace ns3; NS_LOG_COMPONENT_DEFINE ("InterferenceHelperTxDurationTest"); +static const double CHANNEL_1_MHZ = 2412.0; // a 2.4 GHz center frequency (MHz) +static const double CHANNEL_36_MHZ = 5180.0; // a 5 GHz center frequency (MHz) + class TxDurationTest : public TestCase { public: @@ -80,7 +83,13 @@ TxDurationTest::CheckPayloadDuration (uint32_t size, WifiMode payloadMode, uint3 { WifiTxVector txVector; txVector.SetMode (payloadMode); - uint32_t calculatedDurationMicroSeconds = WifiPhy::GetPayloadDurationMicroSeconds (size, txVector); + double testedFrequency = CHANNEL_1_MHZ; + if (payloadMode.GetModulationClass () == WIFI_MOD_CLASS_OFDM || + payloadMode.GetModulationClass () == WIFI_MOD_CLASS_HT) + { + testedFrequency = CHANNEL_36_MHZ; + } + uint32_t calculatedDurationMicroSeconds = WifiPhy::GetPayloadDurationMicroSeconds (size, txVector, testedFrequency); if (calculatedDurationMicroSeconds != knownDurationMicroSeconds) { std::cerr << " size=" << size @@ -90,6 +99,21 @@ TxDurationTest::CheckPayloadDuration (uint32_t size, WifiMode payloadMode, uint3 << std::endl; return false; } + if (payloadMode.GetModulationClass () == WIFI_MOD_CLASS_HT) + { + // Durations vary depending on frequency; test also 2.4 GHz (bug 1971) + testedFrequency = CHANNEL_1_MHZ; + calculatedDurationMicroSeconds = WifiPhy::GetPayloadDurationMicroSeconds (size, txVector, testedFrequency); + if (calculatedDurationMicroSeconds != knownDurationMicroSeconds + 6) + { + std::cerr << " size=" << size + << " mode=" << payloadMode + << " known=" << knownDurationMicroSeconds + << " calculated=" << calculatedDurationMicroSeconds + << std::endl; + return false; + } + } return true; } @@ -101,7 +125,13 @@ TxDurationTest::CheckTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamb txVector.SetNss(1); txVector.SetStbc(0); txVector.SetNess(0); - double calculatedDurationMicroSeconds = WifiPhy::CalculateTxDuration (size, txVector, preamble).GetMicroSeconds (); + double testedFrequency = CHANNEL_1_MHZ; + if (payloadMode.GetModulationClass () == WIFI_MOD_CLASS_OFDM || + payloadMode.GetModulationClass () == WIFI_MOD_CLASS_HT) + { + testedFrequency = CHANNEL_36_MHZ; + } + double calculatedDurationMicroSeconds = WifiPhy::CalculateTxDuration (size, txVector, preamble, testedFrequency).GetMicroSeconds (); if (calculatedDurationMicroSeconds != knownDurationMicroSeconds) { std::cerr << " size=" << size @@ -112,6 +142,22 @@ TxDurationTest::CheckTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamb << std::endl; return false; } + if (payloadMode.GetModulationClass () == WIFI_MOD_CLASS_HT) + { + // Durations vary depending on frequency; test also 2.4 GHz (bug 1971) + testedFrequency = CHANNEL_1_MHZ; + calculatedDurationMicroSeconds = WifiPhy::CalculateTxDuration (size, txVector, preamble, testedFrequency).GetMicroSeconds (); + if (calculatedDurationMicroSeconds != knownDurationMicroSeconds + 6) + { + std::cerr << " size=" << size + << " mode=" << payloadMode + << " preamble=" << preamble + << " known=" << knownDurationMicroSeconds + << " calculated=" << calculatedDurationMicroSeconds + << std::endl; + return false; + } + } return true; } @@ -128,6 +174,7 @@ TxDurationTest::DoRun (void) && CheckPayloadDuration (1025, WifiPhy::GetDsssRate11Mbps (), 746) && CheckPayloadDuration (1026, WifiPhy::GetDsssRate11Mbps (), 747); + NS_TEST_EXPECT_MSG_EQ (retval, true, "an 802.11b CCK duration failed"); // Similar, but we add PLCP preamble and header durations // and we test different rates. @@ -167,9 +214,12 @@ TxDurationTest::DoRun (void) && CheckTxDuration (1025, WifiPhy::GetDsssRate1Mbps (), WIFI_PREAMBLE_LONG, 8200 + 192) && CheckTxDuration (1026, WifiPhy::GetDsssRate1Mbps (), WIFI_PREAMBLE_LONG, 8208 + 192); + // values from http://mailman.isi.edu/pipermail/ns-developers/2009-July/006226.html retval = retval && CheckTxDuration (14, WifiPhy::GetDsssRate1Mbps (), WIFI_PREAMBLE_LONG, 304); + NS_TEST_EXPECT_MSG_EQ (retval, true, "an 802.11b duration failed"); + // values from // http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html retval = retval @@ -180,12 +230,16 @@ TxDurationTest::DoRun (void) && CheckTxDuration (76, WifiPhy::GetOfdmRate54Mbps (), WIFI_PREAMBLE_LONG, 32) && CheckTxDuration (14, WifiPhy::GetOfdmRate54Mbps (), WIFI_PREAMBLE_LONG, 24); + NS_TEST_EXPECT_MSG_EQ (retval, true, "an 802.11a duration failed"); + // 802.11g durations are same as 802.11a durations but with 6 us signal extension retval = retval && CheckTxDuration (1536, WifiPhy::GetErpOfdmRate54Mbps (), WIFI_PREAMBLE_LONG, 254) && CheckTxDuration (76, WifiPhy::GetErpOfdmRate54Mbps (), WIFI_PREAMBLE_LONG, 38) && CheckTxDuration (14, WifiPhy::GetErpOfdmRate54Mbps (), WIFI_PREAMBLE_LONG, 30); + NS_TEST_EXPECT_MSG_EQ (retval, true, "an 802.11g duration failed"); + //802.11n durations retval = retval && CheckTxDuration (1536,WifiPhy::GetOfdmRate65MbpsBW20MHz (), WIFI_PREAMBLE_HT_MF,228) @@ -195,6 +249,8 @@ TxDurationTest::DoRun (void) && CheckTxDuration (1536, WifiPhy::GetOfdmRate65MbpsBW20MHzShGi (), WIFI_PREAMBLE_HT_GF,218) && CheckTxDuration (76, WifiPhy::GetOfdmRate65MbpsBW20MHzShGi (), WIFI_PREAMBLE_HT_GF,38) && CheckTxDuration (14, WifiPhy::GetOfdmRate65MbpsBW20MHzShGi (), WIFI_PREAMBLE_HT_GF,31); + + NS_TEST_EXPECT_MSG_EQ (retval, true, "an 802.11n duration failed"); } class TxDurationTestSuite : public TestSuite