diff --git a/examples/mixed-wireless.cc b/examples/mixed-wireless.cc index bf6ac9215..5e38ee577 100644 --- a/examples/mixed-wireless.cc +++ b/examples/mixed-wireless.cc @@ -137,7 +137,7 @@ main (int argc, char *argv[]) // WifiHelper wifi; wifi.SetMac ("ns3::AdhocWifiMac"); - wifi.SetPhy ("ns3::WifiPhy"); + wifi.SetPhy ("ns3::YansWifiPhy"); NetDeviceContainer backboneDevices = wifi.Install (backbone); // // Add the IPv4 protocol stack to the nodes in our container @@ -246,7 +246,7 @@ main (int argc, char *argv[]) // WifiHelper wifiInfra; wifiInfra.SetMac ("ns3::AdhocWifiMac"); - wifiInfra.SetPhy ("ns3::WifiPhy"); + wifiInfra.SetPhy ("ns3::YansWifiPhy"); NetDeviceContainer infraDevices = wifiInfra.Install (infra); // Add the IPv4 protocol stack to the nodes in our container diff --git a/examples/wifi-adhoc.cc b/examples/wifi-adhoc.cc index 09cded9f0..a506571c8 100644 --- a/examples/wifi-adhoc.cc +++ b/examples/wifi-adhoc.cc @@ -172,7 +172,7 @@ int main (int argc, char *argv[]) GnuplotDataset dataset; wifi.SetMac ("ns3::AdhocWifiMac"); - wifi.SetPhy ("ns3::WifiPhy"); + wifi.SetPhy ("ns3::YansWifiPhy"); NS_LOG_DEBUG ("54"); experiment = Experiment ("54mb"); @@ -234,7 +234,7 @@ int main (int argc, char *argv[]) gnuplot = Gnuplot ("rate-control.png"); - Config::SetDefault ("ns3::WifiPhy::Standard", StringValue ("holland")); + Config::SetDefault ("ns3::YansWifiPhy::Standard", StringValue ("holland")); NS_LOG_DEBUG ("arf"); diff --git a/examples/wifi-ap.cc b/examples/wifi-ap.cc index c2445f16b..b4a30d6fd 100644 --- a/examples/wifi-ap.cc +++ b/examples/wifi-ap.cc @@ -138,7 +138,7 @@ int main (int argc, char *argv[]) channel->SetPropagationLossModel (log); Ssid ssid = Ssid ("wifi-default"); - wifi.SetPhy ("ns3::WifiPhy"); + wifi.SetPhy ("ns3::YansWifiPhy"); wifi.SetRemoteStationManager ("ns3::ArfWifiManager"); // setup stas. wifi.SetMac ("ns3::NqstaWifiMac", diff --git a/src/devices/wifi/wifi-channel.cc b/src/devices/wifi/wifi-channel.cc index 57532aade..400b2714f 100644 --- a/src/devices/wifi/wifi-channel.cc +++ b/src/devices/wifi/wifi-channel.cc @@ -25,6 +25,7 @@ #include "ns3/log.h" #include "ns3/pointer.h" #include "wifi-channel.h" +#include "wifi-phy.h" #include "propagation-loss-model.h" #include "propagation-delay-model.h" diff --git a/src/devices/wifi/wifi-channel.h b/src/devices/wifi/wifi-channel.h index 12181a646..071f7f8ae 100644 --- a/src/devices/wifi/wifi-channel.h +++ b/src/devices/wifi/wifi-channel.h @@ -27,13 +27,13 @@ #include "ns3/net-device.h" #include "wifi-mode.h" #include "wifi-preamble.h" -#include "wifi-phy.h" namespace ns3 { class NetDevice; class PropagationLossModel; class PropagationDelayModel; +class WifiPhy; /** * \brief A 802.11 Channel diff --git a/src/devices/wifi/wifi-phy-test.cc b/src/devices/wifi/wifi-phy-test.cc index 85174d0bc..c618f6b29 100644 --- a/src/devices/wifi/wifi-phy-test.cc +++ b/src/devices/wifi/wifi-phy-test.cc @@ -1,5 +1,6 @@ #include "wifi-phy.h" #include "wifi-channel.h" +#include "yans-wifi-phy.h" #include "propagation-loss-model.h" #include "propagation-delay-model.h" #include "ns3/ptr.h" @@ -77,8 +78,8 @@ PsrExperiment::Run (struct PsrExperiment::Input input) Ptr posRx = CreateObject (); posRx->SetPosition (Vector (m_input.distance, 0.0, 0.0)); - Ptr tx = CreateObject (); - Ptr rx = CreateObject (); + Ptr tx = CreateObject (); + Ptr rx = CreateObject (); rx->SetReceiveOkCallback (MakeCallback (&PsrExperiment::Receive, this)); Ptr channel = CreateObject (); @@ -204,9 +205,9 @@ CollisionExperiment::Run (struct CollisionExperiment::Input input) Ptr posRx = CreateObject (); posRx->SetPosition (Vector (0, 0.0, 0.0)); - Ptr txA = CreateObject (); - Ptr txB = CreateObject (); - Ptr rx = CreateObject (); + Ptr txA = CreateObject (); + Ptr txB = CreateObject (); + Ptr rx = CreateObject (); rx->SetReceiveOkCallback (MakeCallback (&CollisionExperiment::Receive, this)); Ptr channel = CreateObject (); diff --git a/src/devices/wifi/wifi-phy.cc b/src/devices/wifi/wifi-phy.cc index 9120466db..7e145e83d 100644 --- a/src/devices/wifi/wifi-phy.cc +++ b/src/devices/wifi/wifi-phy.cc @@ -37,32 +37,32 @@ NS_LOG_COMPONENT_DEFINE ("WifiPhy"); namespace ns3 { - // Define all the WifiMode needed for 802.11a -static WifiMode g_6mba = WifiModeFactory::CreateBpsk ("wifia-6mbs", - true, - 20000000, 6000000, 12000000); -static WifiMode g_9mba = WifiModeFactory::CreateBpsk ("wifia-9mbs", - false, - 20000000, 9000000, 12000000); +// Define all the WifiMode needed for 802.11a +WifiMode WifiPhy::g_6mba = WifiModeFactory::CreateBpsk ("wifia-6mbs", + true, + 20000000, 6000000, 12000000); +WifiMode WifiPhy::g_9mba = WifiModeFactory::CreateBpsk ("wifia-9mbs", + false, + 20000000, 9000000, 12000000); // XXX explain why Bpsk rather than Qpsk -static WifiMode g_12mba = WifiModeFactory::CreateBpsk ("wifia-12mbs", - true, - 20000000, 12000000, 24000000); -static WifiMode g_18mba = WifiModeFactory::CreateBpsk ("wifia-18mbs", - false, - 20000000, 18000000, 24000000); -static WifiMode g_24mba = WifiModeFactory::CreateBpsk ("wifia-24mbs", - true, - 20000000, 24000000, 48000000); -static WifiMode g_36mba = WifiModeFactory::CreateBpsk ("wifia-36mbs", - false, - 20000000, 36000000, 48000000); -static WifiMode g_48mba = WifiModeFactory::CreateBpsk ("wifia-48mbs", - false, - 20000000, 48000000, 72000000); -static WifiMode g_54mba = WifiModeFactory::CreateBpsk ("wifia-54mbs", - false, - 20000000, 54000000, 72000000); +WifiMode WifiPhy::g_12mba = WifiModeFactory::CreateBpsk ("wifia-12mbs", + true, + 20000000, 12000000, 24000000); +WifiMode WifiPhy::g_18mba = WifiModeFactory::CreateBpsk ("wifia-18mbs", + false, + 20000000, 18000000, 24000000); +WifiMode WifiPhy::g_24mba = WifiModeFactory::CreateBpsk ("wifia-24mbs", + true, + 20000000, 24000000, 48000000); +WifiMode WifiPhy::g_36mba = WifiModeFactory::CreateBpsk ("wifia-36mbs", + false, + 20000000, 36000000, 48000000); +WifiMode WifiPhy::g_48mba = WifiModeFactory::CreateBpsk ("wifia-48mbs", + false, + 20000000, 48000000, 72000000); +WifiMode WifiPhy::g_54mba = WifiModeFactory::CreateBpsk ("wifia-54mbs", + false, + 20000000, 54000000, 72000000); /**************************************************************** @@ -72,106 +72,6 @@ static WifiMode g_54mba = WifiModeFactory::CreateBpsk ("wifia-54mbs", WifiPhyListener::~WifiPhyListener () {} - -/**************************************************************** - * Phy event class - ****************************************************************/ - -class RxEvent -{ -public: - RxEvent (uint32_t size, WifiMode payloadMode, - enum WifiPreamble preamble, - Time duration, double rxPower) - : m_size (size), - m_payloadMode (payloadMode), - m_preamble (preamble), - m_startTime (Simulator::Now ()), - m_endTime (m_startTime + duration), - m_rxPowerW (rxPower), - m_refCount (1) - {} - ~RxEvent () - { - NS_ASSERT (m_refCount == 0); - } - - void Ref (void) const { - m_refCount++; - } - void Unref (void) const { - m_refCount--; - if (m_refCount == 0) { - delete this; - } - } - Time GetDuration (void) const { - return m_endTime - m_startTime; - } - Time GetStartTime (void) const { - return m_startTime; - } - Time GetEndTime (void) const { - return m_endTime; - } - bool Overlaps (Time time) const { - if (m_startTime <= time && - m_endTime >= time) { - return true; - } else { - return false; - } - } - double GetRxPowerW (void) const { - return m_rxPowerW; - } - uint32_t GetSize (void) const { - return m_size; - } - WifiMode GetPayloadMode (void) const { - return m_payloadMode; - } - enum WifiPreamble GetPreambleType (void) const { - return m_preamble; - } - -private: - uint32_t m_size; - WifiMode m_payloadMode; - enum WifiPreamble m_preamble; - Time m_startTime; - Time m_endTime; - double m_rxPowerW; - mutable int m_refCount; -}; - - -/**************************************************************** - * Class which records SNIR change events for a - * short period of time. - ****************************************************************/ - -WifiPhy::NiChange::NiChange (Time time, double delta) - : m_time (time), m_delta (delta) -{} -Time -WifiPhy::NiChange::GetTime (void) const -{ - return m_time; -} -double -WifiPhy::NiChange::GetDelta (void) const -{ - return m_delta; -} -bool -WifiPhy::NiChange::operator < (WifiPhy::NiChange const &o) const -{ - return (m_time < o.m_time)?true:false; -} - - - /**************************************************************** * The actual WifiPhy class ****************************************************************/ @@ -183,82 +83,11 @@ WifiPhy::GetTypeId (void) { static TypeId tid = TypeId ("ns3::WifiPhy") .SetParent () - .AddConstructor () - .AddAttribute ("EnergyDetectionThreshold", - "The energy of a received signal should be higher than " - "this threshold (dbm) to allow the PHY layer to detect the signal.", - DoubleValue (-140.0), - MakeDoubleAccessor (&WifiPhy::SetEdThreshold, - &WifiPhy::GetEdThreshold), - MakeDoubleChecker ()) - .AddAttribute ("TxGain", - "Transmission gain (dB).", - DoubleValue (1.0), - MakeDoubleAccessor (&WifiPhy::SetTxGain, - &WifiPhy::GetTxGain), - MakeDoubleChecker ()) - .AddAttribute ("RxGain", - "Reception gain (dB).", - DoubleValue (1.0), - MakeDoubleAccessor (&WifiPhy::SetRxGain, - &WifiPhy::GetRxGain), - MakeDoubleChecker ()) - .AddAttribute ("TxPowerLevels", - "Number of transmission power levels available between " - "TxPowerBase and TxPowerEnd included.", - UintegerValue (1), - MakeUintegerAccessor (&WifiPhy::m_nTxPower), - MakeUintegerChecker ()) - .AddAttribute ("TxPowerEnd", - "Maximum available transmission level (dbm).", - DoubleValue (16.0206), - MakeDoubleAccessor (&WifiPhy::SetTxPowerEnd, - &WifiPhy::GetTxPowerEnd), - MakeDoubleChecker ()) - .AddAttribute ("TxPowerStart", - "Minimum available transmission level (dbm).", - DoubleValue (16.0206), - MakeDoubleAccessor (&WifiPhy::SetTxPowerStart, - &WifiPhy::GetTxPowerStart), - MakeDoubleChecker ()) - .AddAttribute ("RxNoise", - "Ratio of energy lost by receiver (dB).", - DoubleValue (7), - MakeDoubleAccessor (&WifiPhy::SetRxNoise, - &WifiPhy::GetRxNoise), - MakeDoubleChecker ()) - .AddAttribute ("Standard", "The standard chosen configures a set of transmission modes" - " and some PHY-specific constants.", - EnumValue (WIFI_PHY_STANDARD_80211a), - MakeEnumAccessor (&WifiPhy::SetStandard), - MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a", - WIFI_PHY_STANDARD_holland, "holland")) - .AddTraceSource ("State", - "The WifiPhy state", - MakeTraceSourceAccessor (&WifiPhy::m_stateLogger)) - .AddTraceSource ("RxOk", - "A packet has been received successfully.", - MakeTraceSourceAccessor (&WifiPhy::m_rxOkTrace)) - .AddTraceSource ("RxError", - "A packet has been received unsuccessfully.", - MakeTraceSourceAccessor (&WifiPhy::m_rxErrorTrace)) - .AddTraceSource ("Tx", "Packet transmission is starting.", - MakeTraceSourceAccessor (&WifiPhy::m_txTrace)) ; return tid; } WifiPhy::WifiPhy () - : m_syncing (false), - m_endTx (Seconds (0)), - m_endSync (Seconds (0)), - m_endCcaBusy (Seconds (0)), - m_startTx (Seconds (0)), - m_startSync (Seconds (0)), - m_startCcaBusy (Seconds (0)), - m_previousStateChangeTime (Seconds (0)), - m_endSyncEvent (), - m_random (0.0, 1.0) { NS_LOG_FUNCTION (this); } @@ -268,1130 +97,4 @@ WifiPhy::~WifiPhy () NS_LOG_FUNCTION (this); } -void -WifiPhy::DoDispose (void) -{ - NS_LOG_FUNCTION (this); - m_channel = 0; - m_events.clear (); - m_modes.clear (); -} - -void -WifiPhy::SetStandard (enum WifiPhyStandard standard) -{ - NS_LOG_FUNCTION (this << standard); - m_standard = standard; - switch (standard) { - case WIFI_PHY_STANDARD_80211a: - Configure80211a (); - break; - case WIFI_PHY_STANDARD_holland: - ConfigureHolland (); - break; - default: - NS_ASSERT (false); - break; - } -} - - -void -WifiPhy::SetRxNoise (double db) -{ - NS_LOG_FUNCTION (this << db); - m_rxNoiseRatio = DbToRatio (db); -} -void -WifiPhy::SetTxPowerStart (double start) -{ - NS_LOG_FUNCTION (this << start); - m_txPowerBaseDbm = start; -} -void -WifiPhy::SetTxPowerEnd (double end) -{ - NS_LOG_FUNCTION (this << end); - m_txPowerEndDbm = end; -} -void -WifiPhy::SetNTxPower (uint32_t n) -{ - NS_LOG_FUNCTION (this << n); - m_nTxPower = n; -} -void -WifiPhy::SetTxGain (double gain) -{ - NS_LOG_FUNCTION (this << gain); - m_txGainDb = gain; -} -void -WifiPhy::SetRxGain (double gain) -{ - NS_LOG_FUNCTION (this << gain); - m_rxGainDb = gain; -} -void -WifiPhy::SetEdThreshold (double threshold) -{ - NS_LOG_FUNCTION (this << threshold); - m_edThresholdW = DbmToW (threshold); -} -double -WifiPhy::GetRxNoise (void) const -{ - return RatioToDb (m_rxNoiseRatio); -} -double -WifiPhy::GetTxPowerStart (void) const -{ - return m_txPowerBaseDbm; -} -double -WifiPhy::GetTxPowerEnd (void) const -{ - return m_txPowerEndDbm; -} -double -WifiPhy::GetTxGain (void) const -{ - return m_txGainDb; -} -double -WifiPhy::GetRxGain (void) const -{ - return m_rxGainDb; -} - -double -WifiPhy::GetEdThreshold (void) const -{ - return WToDbm (m_edThresholdW); -} - -Ptr -WifiPhy::GetChannel (void) const -{ - return m_channel; -} - -void -WifiPhy::SetChannel (Ptr channel) -{ - m_channel = channel; -} - -void -WifiPhy::SetReceiveOkCallback (SyncOkCallback callback) -{ - m_syncOkCallback = callback; -} -void -WifiPhy::SetReceiveErrorCallback (SyncErrorCallback callback) -{ - m_syncErrorCallback = callback; -} -void -WifiPhy::StartReceivePacket (Ptr packet, - double rxPowerDbm, - WifiMode txMode, - enum WifiPreamble preamble) -{ - NS_LOG_FUNCTION (this << packet << rxPowerDbm << txMode << preamble); - rxPowerDbm += m_rxGainDb; - double rxPowerW = DbmToW (rxPowerDbm); - Time rxDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble); - Time endRx = Simulator::Now () + rxDuration; - - Ptr event = Create (packet->GetSize (), - txMode, - preamble, - rxDuration, - rxPowerW); - AppendEvent (event); - - switch (GetState ()) { - case WifiPhy::SYNC: - NS_LOG_DEBUG ("drop packet because already in Sync (power="<< - rxPowerW<<"W)"); - if (endRx > m_endSync) - { - goto maybeCcaBusy; - } - break; - case WifiPhy::TX: - NS_LOG_DEBUG ("drop packet because already in Tx (power="<< - rxPowerW<<"W)"); - if (endRx > m_endTx) - { - goto maybeCcaBusy; - } - break; - case WifiPhy::CCA_BUSY: - case WifiPhy::IDLE: - if (rxPowerW > m_edThresholdW) - { - NS_LOG_DEBUG ("sync (power="< m_edThresholdW) - { - SwitchMaybeToCcaBusy (rxDuration); - NotifyCcaBusyStart (rxDuration); - } - else - { - double threshold = m_edThresholdW - rxPowerW; - NiChanges ni; - CalculateNoiseInterferenceW (event, &ni); - double noiseInterferenceW = 0.0; - Time end = Simulator::Now (); - for (NiChanges::const_iterator i = ni.begin (); i != ni.end (); i++) - { - noiseInterferenceW += i->GetDelta (); - if (noiseInterferenceW < threshold) - { - break; - } - end = i->GetTime (); - } - if (end > Simulator::Now ()) - { - Time delta = end - Simulator::Now (); - SwitchMaybeToCcaBusy (delta); - NotifyCcaBusyStart (delta); - } - } - -} -void -WifiPhy::SendPacket (Ptr packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower) -{ - NS_LOG_FUNCTION (this << packet << txMode << preamble << (uint32_t)txPower); - /* Transmission can happen if: - * - we are syncing on a packet. It is the responsability of the - * MAC layer to avoid doing this but the PHY does nothing to - * prevent it. - * - we are idle - */ - NS_ASSERT (!IsStateTx ()); - - m_txTrace (packet, txMode, preamble, txPower); - Time txDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble); - NotifyTxStart (txDuration); - SwitchToTx (txDuration); - m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble); -} - -uint32_t -WifiPhy::GetNModes (void) const -{ - return m_modes.size (); -} -WifiMode -WifiPhy::GetMode (uint32_t mode) const -{ - return m_modes[mode]; -} -uint32_t -WifiPhy::GetNTxPower (void) const -{ - return m_nTxPower; -} - -double -WifiPhy::CalculateSnr (WifiMode txMode, double ber) const -{ - double low, high, precision; - low = 1e-25; - high = 1e25; - precision = 1e-12; - while (high - low > precision) - { - NS_ASSERT (high >= low); - double middle = low + (high - low) / 2; - if ((1 - GetChunkSuccessRate (txMode, middle, 1)) > ber) - { - low = middle; - } - else - { - high = middle; - } - } - return low; -} - -void -WifiPhy::Configure80211aParameters (void) -{ - NS_LOG_FUNCTION (this); - m_plcpLongPreambleDelayUs = 16; - m_plcpShortPreambleDelayUs = 16; - m_longPlcpHeaderMode = g_6mba; - m_shortPlcpHeaderMode = g_6mba; - m_plcpHeaderLength = 4 + 1 + 12 + 1 + 6; - /* 4095 bytes at a 6Mb/s rate with a 1/2 coding rate. */ - m_maxPacketDuration = CalculateTxDuration (4095, g_6mba, WIFI_PREAMBLE_LONG); -} - -void -WifiPhy::PrintModes (void) const -{ -#if 0 - for (double db = -10; db < 30; db+= 0.5) { - double snr = DbToRatio (db); - std::cout < Simulator::Now ()) - { - return WifiPhy::TX; - } - else if (m_syncing) - { - return WifiPhy::SYNC; - } - else if (m_endCcaBusy > Simulator::Now ()) - { - return WifiPhy::CCA_BUSY; - } - else - { - return WifiPhy::IDLE; - } -} - -double -WifiPhy::DbToRatio (double dB) const -{ - double ratio = pow(10.0,dB/10.0); - return ratio; -} - -double -WifiPhy::DbmToW (double dBm) const -{ - double mW = pow(10.0,dBm/10.0); - return mW / 1000.0; -} - -double -WifiPhy::WToDbm (double w) const -{ - return 10.0 * log10(w * 1000.0); -} - -double -WifiPhy::RatioToDb (double ratio) const -{ - return 10.0 * log10(ratio); -} - -double -WifiPhy::GetEdThresholdW (void) const -{ - return m_edThresholdW; -} - -Time -WifiPhy::GetMaxPacketDuration (void) const -{ - return m_maxPacketDuration; -} - -double -WifiPhy::GetPowerDbm (uint8_t power) const -{ - NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm); - NS_ASSERT (m_nTxPower > 0); - double dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / m_nTxPower; - return dbm; -} - -void -WifiPhy::NotifyTxStart (Time duration) -{ - for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { - (*i)->NotifyTxStart (duration); - } -} -void -WifiPhy::NotifySyncStart (Time duration) -{ - for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { - (*i)->NotifyRxStart (duration); - } -} -void -WifiPhy::NotifySyncEndOk (void) -{ - for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { - (*i)->NotifyRxEndOk (); - } -} -void -WifiPhy::NotifySyncEndError (void) -{ - for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { - (*i)->NotifyRxEndError (); - } -} -void -WifiPhy::NotifyCcaBusyStart (Time duration) -{ - for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { - (*i)->NotifyCcaBusyStart (duration); - } -} - -void -WifiPhy::LogPreviousIdleAndCcaBusyStates (void) -{ - Time now = Simulator::Now (); - Time idleStart = Max (m_endCcaBusy, m_endSync); - idleStart = Max (idleStart, m_endTx); - NS_ASSERT (idleStart <= now); - if (m_endCcaBusy > m_endSync && - m_endCcaBusy > m_endTx) { - Time ccaBusyStart = Max (m_endTx, m_endSync); - ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy); - m_stateLogger (ccaBusyStart, idleStart - ccaBusyStart, WifiPhy::CCA_BUSY); - } - m_stateLogger (idleStart, now - idleStart, WifiPhy::IDLE); -} - -void -WifiPhy::SwitchToTx (Time txDuration) -{ - Time now = Simulator::Now (); - switch (GetState ()) { - case WifiPhy::SYNC: - /* The packet which is being received as well - * as its endSync event are cancelled by the caller. - */ - m_syncing = false; - m_stateLogger (m_startSync, now - m_startSync, WifiPhy::SYNC); - m_endSyncEvent.Cancel (); - m_endSync = now; - break; - case WifiPhy::CCA_BUSY: { - Time ccaStart = Max (m_endSync, m_endTx); - ccaStart = Max (ccaStart, m_startCcaBusy); - m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY); - } break; - case WifiPhy::IDLE: - LogPreviousIdleAndCcaBusyStates (); - break; - default: - NS_ASSERT (false); - break; - } - m_stateLogger (now, txDuration, WifiPhy::TX); - m_previousStateChangeTime = now; - m_endTx = now + txDuration; - m_startTx = now; -} -void -WifiPhy::SwitchToSync (Time rxDuration) -{ - NS_ASSERT (IsStateIdle () || IsStateCcaBusy ()); - NS_ASSERT (!m_syncing); - Time now = Simulator::Now (); - switch (GetState ()) { - case WifiPhy::IDLE: - LogPreviousIdleAndCcaBusyStates (); - break; - case WifiPhy::CCA_BUSY: { - Time ccaStart = Max (m_endSync, m_endTx); - ccaStart = Max (ccaStart, m_startCcaBusy); - m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY); - } break; - case WifiPhy::SYNC: - case WifiPhy::TX: - NS_ASSERT (false); - break; - } - m_previousStateChangeTime = now; - m_syncing = true; - m_startSync = now; - m_endSync = now + rxDuration; - NS_ASSERT (IsStateSync ()); -} -void -WifiPhy::SwitchFromSync (void) -{ - NS_ASSERT (IsStateSync ()); - NS_ASSERT (m_syncing); - - Time now = Simulator::Now (); - m_stateLogger (m_startSync, now - m_startSync, WifiPhy::SYNC); - m_previousStateChangeTime = now; - m_syncing = false; - - NS_ASSERT (IsStateIdle () || IsStateCcaBusy ()); -} -void -WifiPhy::SwitchMaybeToCcaBusy (Time duration) -{ - Time now = Simulator::Now (); - switch (GetState ()) { - case WifiPhy::IDLE: - LogPreviousIdleAndCcaBusyStates (); - break; - case WifiPhy::CCA_BUSY: - break; - case WifiPhy::SYNC: - break; - case WifiPhy::TX: - break; - } - m_startCcaBusy = now; - m_endCcaBusy = Max (m_endCcaBusy, now + duration); -} - -void -WifiPhy::AppendEvent (Ptr event) -{ - /* attempt to remove the events which are - * not useful anymore. - * i.e.: all events which end _before_ - * now - m_maxPacketDuration - */ - - if (Simulator::Now () > GetMaxPacketDuration ()) - { - Time end = Simulator::Now () - GetMaxPacketDuration (); - Events::iterator i = m_events.begin (); - while (i != m_events.end () && - (*i)->GetEndTime () <= end) - { - i++; - } - m_events.erase (m_events.begin (), i); - } - m_events.push_back (event); -} - - - -/** - * Stuff specific to the BER model here. - */ -double -WifiPhy::Log2 (double val) const -{ - return log(val) / log(2.0); -} -double -WifiPhy::GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const -{ - double EbNo = snr * signalSpread / phyRate; - double z = sqrt(EbNo); - double ber = 0.5 * erfc(z); - NS_LOG_INFO ("bpsk snr="< channel); + virtual void SetChannel (Ptr channel) = 0; /** * \param callback the callback to invoke * upon successful packet reception. */ - void SetReceiveOkCallback (SyncOkCallback callback); + virtual void SetReceiveOkCallback (SyncOkCallback callback) = 0; /** * \param callback the callback to invoke * upon erronous packet reception. */ - void SetReceiveErrorCallback (SyncErrorCallback callback); + virtual void SetReceiveErrorCallback (SyncErrorCallback callback) = 0; /** * \param packet the packet to send @@ -189,7 +163,7 @@ public: * \param txPowerLevel a power level to use to send this packet. The real * transmission power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels */ - void SendPacket (Ptr packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel); + virtual void SendPacket (Ptr packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel) = 0; /** * \param listener the new listener @@ -197,41 +171,41 @@ public: * Add the input listener to the list of objects to be notified of * PHY-level events. */ - void RegisterListener (WifiPhyListener *listener); + virtual void RegisterListener (WifiPhyListener *listener) = 0; /** * \returns true of the current state of the PHY layer is WifiPhy:LCCA_BUSY, false otherwise. */ - bool IsStateCcaBusy (void); + virtual bool IsStateCcaBusy (void) = 0; /** * \returns true of the current state of the PHY layer is WifiPhy::IDLE, false otherwise. */ - bool IsStateIdle (void); + virtual bool IsStateIdle (void) = 0; /** * \returns true of the current state of the PHY layer is not WifiPhy::IDLE, false otherwise. */ - bool IsStateBusy (void); + virtual bool IsStateBusy (void) = 0; /** * \returns true of the current state of the PHY layer is WifiPhy::SYNC, false otherwise. */ - bool IsStateSync (void); + virtual bool IsStateSync (void) = 0; /** * \returns true of the current state of the PHY layer is WifiPhy::TX, false otherwise. */ - bool IsStateTx (void); + virtual bool IsStateTx (void) = 0; /** * \returns the amount of time since the current state has started. */ - Time GetStateDuration (void); + virtual Time GetStateDuration (void) = 0; /** * \returns the predicted delay until this PHY can become WifiPhy::IDLE. * * The PHY will never become WifiPhy::IDLE _before_ the delay returned by * this method but it could become really idle later. */ - Time GetDelayUntilIdle (void); + virtual Time GetDelayUntilIdle (void) = 0; - Time GetLastRxStartTime (void) const; + virtual Time GetLastRxStartTime (void) const = 0; /** * \param size the number of bytes in the packet to send @@ -240,17 +214,17 @@ public: * \returns the total amount of time this PHY will stay busy for * the transmission of these bytes. */ - Time CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const; + virtual Time CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const = 0; /** * \returns the number of transmission modes supported by this PHY. */ - uint32_t GetNModes (void) const; + virtual uint32_t GetNModes (void) const = 0; /** * \param mode index in array of supported modes * \returns the mode whose index is specified. */ - WifiMode GetMode (uint32_t mode) const; + virtual WifiMode GetMode (uint32_t mode) const = 0; /* return snr: W/W */ /** * \param txMode the transmission mode @@ -258,122 +232,24 @@ public: * \returns the minimum snr which is required to achieve * the requested ber for the specified transmission mode. */ - double CalculateSnr (WifiMode txMode, double ber) const; + virtual double CalculateSnr (WifiMode txMode, double ber) const = 0; /* rxPower unit is Watt */ - void StartReceivePacket (Ptr packet, - double rxPowerDbm, - WifiMode mode, - WifiPreamble preamble); + virtual void StartReceivePacket (Ptr packet, + double rxPowerDbm, + WifiMode mode, + WifiPreamble preamble) = 0; - Ptr GetChannel (void) const; + virtual Ptr GetChannel (void) const = 0; -private: - class NiChange { - public: - NiChange (Time time, double delta); - Time GetTime (void) const; - double GetDelta (void) const; - bool operator < (NiChange const &o) const; - private: - Time m_time; - double m_delta; - }; - typedef std::vector Modes; - typedef std::list Listeners; - typedef std::list > Events; - typedef std::vector NiChanges; - -private: - virtual void DoDispose (void); - void Configure80211aParameters (void); - void PrintModes (void) const; - void Configure80211a (void); - void ConfigureHolland (void); - char const *StateToString (enum State state); - enum WifiPhy::State GetState (void); - double GetEdThresholdW (void) const; - double DbmToW (double dbm) const; - double DbToRatio (double db) const; - double WToDbm (double w) const; - double RatioToDb (double ratio) const; - Time GetMaxPacketDuration (void) const; - void CancelRx (void); - double GetPowerDbm (uint8_t power) const; - void NotifyTxStart (Time duration); - void NotifyWakeup (void); - void NotifySyncStart (Time duration); - void NotifySyncEndOk (void); - void NotifySyncEndError (void); - void NotifyCcaBusyStart (Time duration); - void LogPreviousIdleAndCcaBusyStates (void); - void SwitchToTx (Time txDuration); - void SwitchToSync (Time syncDuration); - void SwitchFromSync (void); - void SwitchMaybeToCcaBusy (Time duration); - void AppendEvent (Ptr event); - double CalculateNoiseInterferenceW (Ptr event, NiChanges *ni) const; - double CalculateSnr (double signal, double noiseInterference, WifiMode mode) const; - double CalculateChunkSuccessRate (double snir, Time delay, WifiMode mode) const; - double CalculatePer (Ptr event, NiChanges *ni) const; - void EndSync (Ptr packet, Ptr event); - double Log2 (double val) const; - double GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const; - double GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const; - uint32_t Factorial (uint32_t k) const; - double Binomial (uint32_t k, double p, uint32_t n) const; - double CalculatePdOdd (double ber, unsigned int d) const; - double CalculatePdEven (double ber, unsigned int d) const; - double CalculatePd (double ber, unsigned int d) const; - double GetFecBpskBer (double snr, double nbits, - uint32_t signalSpread, uint32_t phyRate, - uint32_t dFree, uint32_t adFree) const; - double GetFecQamBer (double snr, uint32_t nbits, - uint32_t signalSpread, - uint32_t phyRate, - uint32_t m, uint32_t dfree, - uint32_t adFree, uint32_t adFreePlusOne) const; - double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const; -private: - uint64_t m_txPrepareDelayUs; - uint64_t m_plcpLongPreambleDelayUs; - uint64_t m_plcpShortPreambleDelayUs; - WifiMode m_longPlcpHeaderMode; - WifiMode m_shortPlcpHeaderMode; - uint32_t m_plcpHeaderLength; - Time m_maxPacketDuration; - - double m_edThresholdW; /* unit: W */ - double m_txGainDb; - double m_rxGainDb; - double m_rxNoiseRatio; - double m_txPowerBaseDbm; - double m_txPowerEndDbm; - uint32_t m_nTxPower; - - - bool m_syncing; - Time m_endTx; - Time m_endSync; - Time m_endCcaBusy; - Time m_startTx; - Time m_startSync; - Time m_startCcaBusy; - Time m_previousStateChangeTime; - - Ptr m_channel; - SyncOkCallback m_syncOkCallback; - SyncErrorCallback m_syncErrorCallback; - TracedCallback, double, WifiMode, enum WifiPreamble> m_rxOkTrace; - TracedCallback, double> m_rxErrorTrace; - TracedCallback,WifiMode,WifiPreamble,uint8_t> m_txTrace; - Modes m_modes; - Listeners m_listeners; - EventId m_endSyncEvent; - Events m_events; - UniformVariable m_random; - TracedCallback m_stateLogger; - WifiPhyStandard m_standard; + static WifiMode g_6mba; + static WifiMode g_9mba; + static WifiMode g_12mba; + static WifiMode g_18mba; + static WifiMode g_24mba; + static WifiMode g_36mba; + static WifiMode g_48mba; + static WifiMode g_54mba; }; } // namespace ns3 diff --git a/src/devices/wifi/wifi-test.cc b/src/devices/wifi/wifi-test.cc index dbab90c63..37cb35989 100644 --- a/src/devices/wifi/wifi-test.cc +++ b/src/devices/wifi/wifi-test.cc @@ -3,7 +3,7 @@ #include "wifi-net-device.h" #include "wifi-channel.h" #include "adhoc-wifi-mac.h" -#include "wifi-phy.h" +#include "yans-wifi-phy.h" #include "arf-wifi-manager.h" #include "propagation-delay-model.h" #include "propagation-loss-model.h" @@ -50,7 +50,7 @@ WifiTest::CreateOne (Vector pos, Ptr channel) Ptr mac = m_mac.Create (); Ptr mobility = CreateObject (); - Ptr phy = CreateObject (); + Ptr phy = CreateObject (); Ptr manager = m_manager.Create (); mobility->SetPosition (pos); diff --git a/src/devices/wifi/wscript b/src/devices/wifi/wscript index 535938434..eb0a863bc 100644 --- a/src/devices/wifi/wscript +++ b/src/devices/wifi/wscript @@ -11,6 +11,7 @@ def build(bld): 'wifi-mode.cc', 'ssid.cc', 'wifi-phy.cc', + 'yans-wifi-phy.cc', 'wifi-mac-header.cc', 'wifi-mac-trailer.cc', 'mac-low.cc', @@ -53,6 +54,7 @@ def build(bld): 'ssid.h', 'wifi-preamble.h', 'wifi-phy-standard.h', + 'yans-wifi-phy.h', 'wifi-phy.h', 'wifi-remote-station-manager.h', 'arf-wifi-manager.h', diff --git a/src/devices/wifi/yans-wifi-phy.cc b/src/devices/wifi/yans-wifi-phy.cc new file mode 100644 index 000000000..a1fd6206f --- /dev/null +++ b/src/devices/wifi/yans-wifi-phy.cc @@ -0,0 +1,1361 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006 INRIA + * + * 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: Mathieu Lacage + */ + +#include "yans-wifi-phy.h" +#include "wifi-mode.h" +#include "wifi-channel.h" +#include "wifi-preamble.h" +#include "ns3/simulator.h" +#include "ns3/packet.h" +#include "ns3/random-variable.h" +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/double.h" +#include "ns3/uinteger.h" +#include "ns3/enum.h" +#include "ns3/trace-source-accessor.h" +#include + +NS_LOG_COMPONENT_DEFINE ("YansWifiPhy"); + +namespace ns3 { + +/**************************************************************** + * Phy event class + ****************************************************************/ + +class RxEvent +{ +public: + RxEvent (uint32_t size, WifiMode payloadMode, + enum WifiPreamble preamble, + Time duration, double rxPower) + : m_size (size), + m_payloadMode (payloadMode), + m_preamble (preamble), + m_startTime (Simulator::Now ()), + m_endTime (m_startTime + duration), + m_rxPowerW (rxPower), + m_refCount (1) + {} + ~RxEvent () + { + NS_ASSERT (m_refCount == 0); + } + + void Ref (void) const { + m_refCount++; + } + void Unref (void) const { + m_refCount--; + if (m_refCount == 0) { + delete this; + } + } + Time GetDuration (void) const { + return m_endTime - m_startTime; + } + Time GetStartTime (void) const { + return m_startTime; + } + Time GetEndTime (void) const { + return m_endTime; + } + bool Overlaps (Time time) const { + if (m_startTime <= time && + m_endTime >= time) { + return true; + } else { + return false; + } + } + double GetRxPowerW (void) const { + return m_rxPowerW; + } + uint32_t GetSize (void) const { + return m_size; + } + WifiMode GetPayloadMode (void) const { + return m_payloadMode; + } + enum WifiPreamble GetPreambleType (void) const { + return m_preamble; + } + +private: + uint32_t m_size; + WifiMode m_payloadMode; + enum WifiPreamble m_preamble; + Time m_startTime; + Time m_endTime; + double m_rxPowerW; + mutable int m_refCount; +}; + + +/**************************************************************** + * Class which records SNIR change events for a + * short period of time. + ****************************************************************/ + +YansWifiPhy::NiChange::NiChange (Time time, double delta) + : m_time (time), m_delta (delta) +{} +Time +YansWifiPhy::NiChange::GetTime (void) const +{ + return m_time; +} +double +YansWifiPhy::NiChange::GetDelta (void) const +{ + return m_delta; +} +bool +YansWifiPhy::NiChange::operator < (YansWifiPhy::NiChange const &o) const +{ + return (m_time < o.m_time)?true:false; +} + + + +/**************************************************************** + * The actual YansWifiPhy class + ****************************************************************/ + +NS_OBJECT_ENSURE_REGISTERED (YansWifiPhy); + +TypeId +YansWifiPhy::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::YansWifiPhy") + .SetParent () + .AddConstructor () + .AddAttribute ("EnergyDetectionThreshold", + "The energy of a received signal should be higher than " + "this threshold (dbm) to allow the PHY layer to detect the signal.", + DoubleValue (-140.0), + MakeDoubleAccessor (&YansWifiPhy::SetEdThreshold, + &YansWifiPhy::GetEdThreshold), + MakeDoubleChecker ()) + .AddAttribute ("TxGain", + "Transmission gain (dB).", + DoubleValue (1.0), + MakeDoubleAccessor (&YansWifiPhy::SetTxGain, + &YansWifiPhy::GetTxGain), + MakeDoubleChecker ()) + .AddAttribute ("RxGain", + "Reception gain (dB).", + DoubleValue (1.0), + MakeDoubleAccessor (&YansWifiPhy::SetRxGain, + &YansWifiPhy::GetRxGain), + MakeDoubleChecker ()) + .AddAttribute ("TxPowerLevels", + "Number of transmission power levels available between " + "TxPowerBase and TxPowerEnd included.", + UintegerValue (1), + MakeUintegerAccessor (&YansWifiPhy::m_nTxPower), + MakeUintegerChecker ()) + .AddAttribute ("TxPowerEnd", + "Maximum available transmission level (dbm).", + DoubleValue (16.0206), + MakeDoubleAccessor (&YansWifiPhy::SetTxPowerEnd, + &YansWifiPhy::GetTxPowerEnd), + MakeDoubleChecker ()) + .AddAttribute ("TxPowerStart", + "Minimum available transmission level (dbm).", + DoubleValue (16.0206), + MakeDoubleAccessor (&YansWifiPhy::SetTxPowerStart, + &YansWifiPhy::GetTxPowerStart), + MakeDoubleChecker ()) + .AddAttribute ("RxNoise", + "Ratio of energy lost by receiver (dB).", + DoubleValue (7), + MakeDoubleAccessor (&YansWifiPhy::SetRxNoise, + &YansWifiPhy::GetRxNoise), + MakeDoubleChecker ()) + .AddAttribute ("Standard", "The standard chosen configures a set of transmission modes" + " and some PHY-specific constants.", + EnumValue (WIFI_PHY_STANDARD_80211a), + MakeEnumAccessor (&YansWifiPhy::SetStandard), + MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a", + WIFI_PHY_STANDARD_holland, "holland")) + .AddTraceSource ("State", + "The YansWifiPhy state", + MakeTraceSourceAccessor (&YansWifiPhy::m_stateLogger)) + .AddTraceSource ("RxOk", + "A packet has been received successfully.", + MakeTraceSourceAccessor (&YansWifiPhy::m_rxOkTrace)) + .AddTraceSource ("RxError", + "A packet has been received unsuccessfully.", + MakeTraceSourceAccessor (&YansWifiPhy::m_rxErrorTrace)) + .AddTraceSource ("Tx", "Packet transmission is starting.", + MakeTraceSourceAccessor (&YansWifiPhy::m_txTrace)) + ; + return tid; +} + +YansWifiPhy::YansWifiPhy () + : m_syncing (false), + m_endTx (Seconds (0)), + m_endSync (Seconds (0)), + m_endCcaBusy (Seconds (0)), + m_startTx (Seconds (0)), + m_startSync (Seconds (0)), + m_startCcaBusy (Seconds (0)), + m_previousStateChangeTime (Seconds (0)), + m_endSyncEvent (), + m_random (0.0, 1.0) +{ + NS_LOG_FUNCTION (this); +} + +YansWifiPhy::~YansWifiPhy () +{ + NS_LOG_FUNCTION (this); +} + +void +YansWifiPhy::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + m_channel = 0; + m_events.clear (); + m_modes.clear (); +} + +void +YansWifiPhy::SetStandard (enum WifiPhyStandard standard) +{ + NS_LOG_FUNCTION (this << standard); + m_standard = standard; + switch (standard) { + case WIFI_PHY_STANDARD_80211a: + Configure80211a (); + break; + case WIFI_PHY_STANDARD_holland: + ConfigureHolland (); + break; + default: + NS_ASSERT (false); + break; + } +} + + +void +YansWifiPhy::SetRxNoise (double db) +{ + NS_LOG_FUNCTION (this << db); + m_rxNoiseRatio = DbToRatio (db); +} +void +YansWifiPhy::SetTxPowerStart (double start) +{ + NS_LOG_FUNCTION (this << start); + m_txPowerBaseDbm = start; +} +void +YansWifiPhy::SetTxPowerEnd (double end) +{ + NS_LOG_FUNCTION (this << end); + m_txPowerEndDbm = end; +} +void +YansWifiPhy::SetNTxPower (uint32_t n) +{ + NS_LOG_FUNCTION (this << n); + m_nTxPower = n; +} +void +YansWifiPhy::SetTxGain (double gain) +{ + NS_LOG_FUNCTION (this << gain); + m_txGainDb = gain; +} +void +YansWifiPhy::SetRxGain (double gain) +{ + NS_LOG_FUNCTION (this << gain); + m_rxGainDb = gain; +} +void +YansWifiPhy::SetEdThreshold (double threshold) +{ + NS_LOG_FUNCTION (this << threshold); + m_edThresholdW = DbmToW (threshold); +} +double +YansWifiPhy::GetRxNoise (void) const +{ + return RatioToDb (m_rxNoiseRatio); +} +double +YansWifiPhy::GetTxPowerStart (void) const +{ + return m_txPowerBaseDbm; +} +double +YansWifiPhy::GetTxPowerEnd (void) const +{ + return m_txPowerEndDbm; +} +double +YansWifiPhy::GetTxGain (void) const +{ + return m_txGainDb; +} +double +YansWifiPhy::GetRxGain (void) const +{ + return m_rxGainDb; +} + +double +YansWifiPhy::GetEdThreshold (void) const +{ + return WToDbm (m_edThresholdW); +} + +Ptr +YansWifiPhy::GetChannel (void) const +{ + return m_channel; +} + +void +YansWifiPhy::SetChannel (Ptr channel) +{ + m_channel = channel; +} + +void +YansWifiPhy::SetReceiveOkCallback (SyncOkCallback callback) +{ + m_syncOkCallback = callback; +} +void +YansWifiPhy::SetReceiveErrorCallback (SyncErrorCallback callback) +{ + m_syncErrorCallback = callback; +} +void +YansWifiPhy::StartReceivePacket (Ptr packet, + double rxPowerDbm, + WifiMode txMode, + enum WifiPreamble preamble) +{ + NS_LOG_FUNCTION (this << packet << rxPowerDbm << txMode << preamble); + rxPowerDbm += m_rxGainDb; + double rxPowerW = DbmToW (rxPowerDbm); + Time rxDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble); + Time endRx = Simulator::Now () + rxDuration; + + Ptr event = Create (packet->GetSize (), + txMode, + preamble, + rxDuration, + rxPowerW); + AppendEvent (event); + + switch (GetState ()) { + case YansWifiPhy::SYNC: + NS_LOG_DEBUG ("drop packet because already in Sync (power="<< + rxPowerW<<"W)"); + if (endRx > m_endSync) + { + goto maybeCcaBusy; + } + break; + case YansWifiPhy::TX: + NS_LOG_DEBUG ("drop packet because already in Tx (power="<< + rxPowerW<<"W)"); + if (endRx > m_endTx) + { + goto maybeCcaBusy; + } + break; + case YansWifiPhy::CCA_BUSY: + case YansWifiPhy::IDLE: + if (rxPowerW > m_edThresholdW) + { + NS_LOG_DEBUG ("sync (power="< m_edThresholdW) + { + SwitchMaybeToCcaBusy (rxDuration); + NotifyCcaBusyStart (rxDuration); + } + else + { + double threshold = m_edThresholdW - rxPowerW; + NiChanges ni; + CalculateNoiseInterferenceW (event, &ni); + double noiseInterferenceW = 0.0; + Time end = Simulator::Now (); + for (NiChanges::const_iterator i = ni.begin (); i != ni.end (); i++) + { + noiseInterferenceW += i->GetDelta (); + if (noiseInterferenceW < threshold) + { + break; + } + end = i->GetTime (); + } + if (end > Simulator::Now ()) + { + Time delta = end - Simulator::Now (); + SwitchMaybeToCcaBusy (delta); + NotifyCcaBusyStart (delta); + } + } + +} +void +YansWifiPhy::SendPacket (Ptr packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower) +{ + NS_LOG_FUNCTION (this << packet << txMode << preamble << (uint32_t)txPower); + /* Transmission can happen if: + * - we are syncing on a packet. It is the responsability of the + * MAC layer to avoid doing this but the PHY does nothing to + * prevent it. + * - we are idle + */ + NS_ASSERT (!IsStateTx ()); + + m_txTrace (packet, txMode, preamble, txPower); + Time txDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble); + NotifyTxStart (txDuration); + SwitchToTx (txDuration); + m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble); +} + +uint32_t +YansWifiPhy::GetNModes (void) const +{ + return m_modes.size (); +} +WifiMode +YansWifiPhy::GetMode (uint32_t mode) const +{ + return m_modes[mode]; +} +uint32_t +YansWifiPhy::GetNTxPower (void) const +{ + return m_nTxPower; +} + +double +YansWifiPhy::CalculateSnr (WifiMode txMode, double ber) const +{ + double low, high, precision; + low = 1e-25; + high = 1e25; + precision = 1e-12; + while (high - low > precision) + { + NS_ASSERT (high >= low); + double middle = low + (high - low) / 2; + if ((1 - GetChunkSuccessRate (txMode, middle, 1)) > ber) + { + low = middle; + } + else + { + high = middle; + } + } + return low; +} + +void +YansWifiPhy::Configure80211aParameters (void) +{ + NS_LOG_FUNCTION (this); + m_plcpLongPreambleDelayUs = 16; + m_plcpShortPreambleDelayUs = 16; + m_longPlcpHeaderMode = g_6mba; + m_shortPlcpHeaderMode = g_6mba; + m_plcpHeaderLength = 4 + 1 + 12 + 1 + 6; + /* 4095 bytes at a 6Mb/s rate with a 1/2 coding rate. */ + m_maxPacketDuration = CalculateTxDuration (4095, g_6mba, WIFI_PREAMBLE_LONG); +} + +void +YansWifiPhy::PrintModes (void) const +{ +#if 0 + for (double db = -10; db < 30; db+= 0.5) { + double snr = DbToRatio (db); + std::cout < Simulator::Now ()) + { + return YansWifiPhy::TX; + } + else if (m_syncing) + { + return YansWifiPhy::SYNC; + } + else if (m_endCcaBusy > Simulator::Now ()) + { + return YansWifiPhy::CCA_BUSY; + } + else + { + return YansWifiPhy::IDLE; + } +} + +double +YansWifiPhy::DbToRatio (double dB) const +{ + double ratio = pow(10.0,dB/10.0); + return ratio; +} + +double +YansWifiPhy::DbmToW (double dBm) const +{ + double mW = pow(10.0,dBm/10.0); + return mW / 1000.0; +} + +double +YansWifiPhy::WToDbm (double w) const +{ + return 10.0 * log10(w * 1000.0); +} + +double +YansWifiPhy::RatioToDb (double ratio) const +{ + return 10.0 * log10(ratio); +} + +double +YansWifiPhy::GetEdThresholdW (void) const +{ + return m_edThresholdW; +} + +Time +YansWifiPhy::GetMaxPacketDuration (void) const +{ + return m_maxPacketDuration; +} + +double +YansWifiPhy::GetPowerDbm (uint8_t power) const +{ + NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm); + NS_ASSERT (m_nTxPower > 0); + double dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / m_nTxPower; + return dbm; +} + +void +YansWifiPhy::NotifyTxStart (Time duration) +{ + for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { + (*i)->NotifyTxStart (duration); + } +} +void +YansWifiPhy::NotifySyncStart (Time duration) +{ + for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { + (*i)->NotifyRxStart (duration); + } +} +void +YansWifiPhy::NotifySyncEndOk (void) +{ + for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { + (*i)->NotifyRxEndOk (); + } +} +void +YansWifiPhy::NotifySyncEndError (void) +{ + for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { + (*i)->NotifyRxEndError (); + } +} +void +YansWifiPhy::NotifyCcaBusyStart (Time duration) +{ + for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) { + (*i)->NotifyCcaBusyStart (duration); + } +} + +void +YansWifiPhy::LogPreviousIdleAndCcaBusyStates (void) +{ + Time now = Simulator::Now (); + Time idleStart = Max (m_endCcaBusy, m_endSync); + idleStart = Max (idleStart, m_endTx); + NS_ASSERT (idleStart <= now); + if (m_endCcaBusy > m_endSync && + m_endCcaBusy > m_endTx) { + Time ccaBusyStart = Max (m_endTx, m_endSync); + ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy); + m_stateLogger (ccaBusyStart, idleStart - ccaBusyStart, YansWifiPhy::CCA_BUSY); + } + m_stateLogger (idleStart, now - idleStart, YansWifiPhy::IDLE); +} + +void +YansWifiPhy::SwitchToTx (Time txDuration) +{ + Time now = Simulator::Now (); + switch (GetState ()) { + case YansWifiPhy::SYNC: + /* The packet which is being received as well + * as its endSync event are cancelled by the caller. + */ + m_syncing = false; + m_stateLogger (m_startSync, now - m_startSync, YansWifiPhy::SYNC); + m_endSyncEvent.Cancel (); + m_endSync = now; + break; + case YansWifiPhy::CCA_BUSY: { + Time ccaStart = Max (m_endSync, m_endTx); + ccaStart = Max (ccaStart, m_startCcaBusy); + m_stateLogger (ccaStart, now - ccaStart, YansWifiPhy::CCA_BUSY); + } break; + case YansWifiPhy::IDLE: + LogPreviousIdleAndCcaBusyStates (); + break; + default: + NS_ASSERT (false); + break; + } + m_stateLogger (now, txDuration, YansWifiPhy::TX); + m_previousStateChangeTime = now; + m_endTx = now + txDuration; + m_startTx = now; +} +void +YansWifiPhy::SwitchToSync (Time rxDuration) +{ + NS_ASSERT (IsStateIdle () || IsStateCcaBusy ()); + NS_ASSERT (!m_syncing); + Time now = Simulator::Now (); + switch (GetState ()) { + case YansWifiPhy::IDLE: + LogPreviousIdleAndCcaBusyStates (); + break; + case YansWifiPhy::CCA_BUSY: { + Time ccaStart = Max (m_endSync, m_endTx); + ccaStart = Max (ccaStart, m_startCcaBusy); + m_stateLogger (ccaStart, now - ccaStart, YansWifiPhy::CCA_BUSY); + } break; + case YansWifiPhy::SYNC: + case YansWifiPhy::TX: + NS_ASSERT (false); + break; + } + m_previousStateChangeTime = now; + m_syncing = true; + m_startSync = now; + m_endSync = now + rxDuration; + NS_ASSERT (IsStateSync ()); +} +void +YansWifiPhy::SwitchFromSync (void) +{ + NS_ASSERT (IsStateSync ()); + NS_ASSERT (m_syncing); + + Time now = Simulator::Now (); + m_stateLogger (m_startSync, now - m_startSync, YansWifiPhy::SYNC); + m_previousStateChangeTime = now; + m_syncing = false; + + NS_ASSERT (IsStateIdle () || IsStateCcaBusy ()); +} +void +YansWifiPhy::SwitchMaybeToCcaBusy (Time duration) +{ + Time now = Simulator::Now (); + switch (GetState ()) { + case YansWifiPhy::IDLE: + LogPreviousIdleAndCcaBusyStates (); + break; + case YansWifiPhy::CCA_BUSY: + break; + case YansWifiPhy::SYNC: + break; + case YansWifiPhy::TX: + break; + } + m_startCcaBusy = now; + m_endCcaBusy = Max (m_endCcaBusy, now + duration); +} + +void +YansWifiPhy::AppendEvent (Ptr event) +{ + /* attempt to remove the events which are + * not useful anymore. + * i.e.: all events which end _before_ + * now - m_maxPacketDuration + */ + + if (Simulator::Now () > GetMaxPacketDuration ()) + { + Time end = Simulator::Now () - GetMaxPacketDuration (); + Events::iterator i = m_events.begin (); + while (i != m_events.end () && + (*i)->GetEndTime () <= end) + { + i++; + } + m_events.erase (m_events.begin (), i); + } + m_events.push_back (event); +} + + + +/** + * Stuff specific to the BER model here. + */ +double +YansWifiPhy::Log2 (double val) const +{ + return log(val) / log(2.0); +} +double +YansWifiPhy::GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const +{ + double EbNo = snr * signalSpread / phyRate; + double z = sqrt(EbNo); + double ber = 0.5 * erfc(z); + NS_LOG_INFO ("bpsk snr="< + */ + +#ifndef YANS_WIFI_PHY_H +#define YANS_WIFI_PHY_H + +#include +#include +#include +#include "ns3/callback.h" +#include "ns3/event-id.h" +#include "ns3/packet.h" +#include "ns3/object.h" +#include "ns3/traced-callback.h" +#include "ns3/nstime.h" +#include "ns3/ptr.h" +#include "ns3/random-variable.h" +#include "wifi-phy.h" +#include "wifi-mode.h" +#include "wifi-preamble.h" +#include "wifi-phy-standard.h" + + +namespace ns3 { + +class RandomUniform; +class RxEvent; +class WifiChannel; + + +/** + * \brief 802.11 PHY layer model + * + * This PHY implements a model of 802.11a. The model + * implemented here is based on the model described + * in "Yet Another Network Simulator", + * (http://cutebugs.net/files/wns2-yans.pdf). + * + * + * This PHY model depends on a channel loss and delay + * model as provided by the ns3::PropagationLossModel + * and ns3::PropagationDelayModel classes, both of which are + * members of the ns3::WifiChannel class. + */ +class YansWifiPhy : public WifiPhy +{ +public: + + static TypeId GetTypeId (void); + + YansWifiPhy (); + virtual ~YansWifiPhy (); + + void SetStandard (enum WifiPhyStandard standard); + void SetRxNoise (double ratio); + void SetTxPowerStart (double start); + void SetTxPowerEnd (double end); + void SetNTxPower (uint32_t n); + void SetTxGain (double gain); + void SetRxGain (double gain); + void SetEdThreshold (double threshold); + double GetRxNoise (void) const; + double GetTxGain (void) const; + double GetRxGain (void) const; + double GetEdThreshold (void) const; + + + virtual double GetTxPowerStart (void) const; + virtual double GetTxPowerEnd (void) const; + virtual uint32_t GetNTxPower (void) const; + virtual void SetChannel (Ptr channel); + virtual void SetReceiveOkCallback (WifiPhy::SyncOkCallback callback); + virtual void SetReceiveErrorCallback (WifiPhy::SyncErrorCallback callback); + virtual void SendPacket (Ptr packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel); + virtual void RegisterListener (WifiPhyListener *listener); + virtual bool IsStateCcaBusy (void); + virtual bool IsStateIdle (void); + virtual bool IsStateBusy (void); + virtual bool IsStateSync (void); + virtual bool IsStateTx (void); + virtual Time GetStateDuration (void); + virtual Time GetDelayUntilIdle (void); + virtual Time GetLastRxStartTime (void) const; + virtual Time CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const; + virtual uint32_t GetNModes (void) const; + virtual WifiMode GetMode (uint32_t mode) const; + virtual double CalculateSnr (WifiMode txMode, double ber) const; + virtual void StartReceivePacket (Ptr packet, + double rxPowerDbm, + WifiMode mode, + WifiPreamble preamble); + virtual Ptr GetChannel (void) const; + +private: + class NiChange { + public: + NiChange (Time time, double delta); + Time GetTime (void) const; + double GetDelta (void) const; + bool operator < (NiChange const &o) const; + private: + Time m_time; + double m_delta; + }; + typedef std::vector Modes; + typedef std::list Listeners; + typedef std::list > Events; + typedef std::vector NiChanges; + +private: + virtual void DoDispose (void); + void Configure80211aParameters (void); + void PrintModes (void) const; + void Configure80211a (void); + void ConfigureHolland (void); + char const *StateToString (enum State state); + enum YansWifiPhy::State GetState (void); + double GetEdThresholdW (void) const; + double DbmToW (double dbm) const; + double DbToRatio (double db) const; + double WToDbm (double w) const; + double RatioToDb (double ratio) const; + Time GetMaxPacketDuration (void) const; + void CancelRx (void); + double GetPowerDbm (uint8_t power) const; + void NotifyTxStart (Time duration); + void NotifyWakeup (void); + void NotifySyncStart (Time duration); + void NotifySyncEndOk (void); + void NotifySyncEndError (void); + void NotifyCcaBusyStart (Time duration); + void LogPreviousIdleAndCcaBusyStates (void); + void SwitchToTx (Time txDuration); + void SwitchToSync (Time syncDuration); + void SwitchFromSync (void); + void SwitchMaybeToCcaBusy (Time duration); + void AppendEvent (Ptr event); + double CalculateNoiseInterferenceW (Ptr event, NiChanges *ni) const; + double CalculateSnr (double signal, double noiseInterference, WifiMode mode) const; + double CalculateChunkSuccessRate (double snir, Time delay, WifiMode mode) const; + double CalculatePer (Ptr event, NiChanges *ni) const; + void EndSync (Ptr packet, Ptr event); + double Log2 (double val) const; + double GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const; + double GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const; + uint32_t Factorial (uint32_t k) const; + double Binomial (uint32_t k, double p, uint32_t n) const; + double CalculatePdOdd (double ber, unsigned int d) const; + double CalculatePdEven (double ber, unsigned int d) const; + double CalculatePd (double ber, unsigned int d) const; + double GetFecBpskBer (double snr, double nbits, + uint32_t signalSpread, uint32_t phyRate, + uint32_t dFree, uint32_t adFree) const; + double GetFecQamBer (double snr, uint32_t nbits, + uint32_t signalSpread, + uint32_t phyRate, + uint32_t m, uint32_t dfree, + uint32_t adFree, uint32_t adFreePlusOne) const; + double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const; +private: + uint64_t m_txPrepareDelayUs; + uint64_t m_plcpLongPreambleDelayUs; + uint64_t m_plcpShortPreambleDelayUs; + WifiMode m_longPlcpHeaderMode; + WifiMode m_shortPlcpHeaderMode; + uint32_t m_plcpHeaderLength; + Time m_maxPacketDuration; + + double m_edThresholdW; /* unit: W */ + double m_txGainDb; + double m_rxGainDb; + double m_rxNoiseRatio; + double m_txPowerBaseDbm; + double m_txPowerEndDbm; + uint32_t m_nTxPower; + + + bool m_syncing; + Time m_endTx; + Time m_endSync; + Time m_endCcaBusy; + Time m_startTx; + Time m_startSync; + Time m_startCcaBusy; + Time m_previousStateChangeTime; + + Ptr m_channel; + SyncOkCallback m_syncOkCallback; + SyncErrorCallback m_syncErrorCallback; + TracedCallback, double, WifiMode, enum WifiPreamble> m_rxOkTrace; + TracedCallback, double> m_rxErrorTrace; + TracedCallback,WifiMode,WifiPreamble,uint8_t> m_txTrace; + Modes m_modes; + Listeners m_listeners; + EventId m_endSyncEvent; + Events m_events; + UniformVariable m_random; + TracedCallback m_stateLogger; + WifiPhyStandard m_standard; +}; + +} // namespace ns3 + + +#endif /* YANS_WIFI_PHY_H */