diff --git a/src/wifi/examples/test-frame-capture.cc b/src/wifi/examples/test-frame-capture.cc new file mode 100644 index 0000000..7ba22ec --- /dev/null +++ b/src/wifi/examples/test-frame-capture.cc @@ -0,0 +1,291 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Sébastien Deronne + */ + +// +// This script is used to verify the behavior of InterferenceHelper. +// +// The scenario consists of two IEEE 802.11 hidden stations and an access point. +// The two stations have both a packet to transmit to the access point. +// +// +// (xA,0,0) (0,0,0) (xB,0,0) +// +// * -----> * <----- * +// | | | +// STA A AP STA B +// +// +// The program can be configured at run-time by passing command-line arguments. +// It enables to configure the delay between the transmission from station A +// and the transmission from station B (--delay option). It is also possible to +// select the tx power level (--txPowerA and --txPowerB options), the packet size +// (--packetSizeA and --packetSizeB options) and the modulation (--txModeA and +// --txModeB options) used for the respective transmissions. +// +// By default, IEEE 802.11a with long preamble type is considered, but those +// parameters can be also picked among other IEEE 802.11 flavors and preamble +// types available in the simulator (--standard and --preamble options). +// Note that the program checks the consistency between the selected standard +// the selected preamble type. +// +// The output of the program displays InterfenceHelper and YansWifiPhy trace +// logs associated to the chosen scenario. +// + +#include "ns3/core-module.h" +#include "ns3/yans-wifi-channel.h" +#include "ns3/propagation-loss-model.h" +#include "ns3/propagation-delay-model.h" +#include "ns3/nist-error-rate-model.h" +#include "ns3/constant-position-mobility-model.h" + +using namespace ns3; + +class FrameCaptureExperiment +{ +public: + struct Input + { + Input (); + Time interval; + double xA; + double xB; + std::string txModeA; + std::string txModeB; + uint32_t txPowerLevelA; + uint32_t txPowerLevelB; + double txPowerA; + double txPowerB; + uint32_t packetSizeA; + uint32_t packetSizeB; + WifiPhyStandard standard; + WifiPreamble preamble; + }; + FrameCaptureExperiment (); + void Run (struct FrameCaptureExperiment::Input input); + +private: + void SendA (void) const; + void SendB (void) const; + Ptr m_txA; + Ptr m_txB; + struct Input m_input; +}; + +void +FrameCaptureExperiment::SendA (void) const +{ + Ptr p = Create (m_input.packetSizeA); + WifiTxVector txVector; + txVector.SetTxPowerLevel (m_input.txPowerLevelA); + txVector.SetMode (WifiMode (m_input.txModeA)); + txVector.SetPreambleType (m_input.preamble); + m_txA->SetTxPowerStart(m_input.txPowerA); + m_txA->SetTxPowerEnd(m_input.txPowerA); + m_txA->SendPacket (p, txVector); +} + +void +FrameCaptureExperiment::SendB (void) const +{ + Ptr p = Create (m_input.packetSizeB); + WifiTxVector txVector; + txVector.SetTxPowerLevel (m_input.txPowerLevelB); + txVector.SetMode (WifiMode (m_input.txModeB)); + txVector.SetPreambleType (m_input.preamble); + m_txB->SetTxPowerStart(m_input.txPowerB); + m_txB->SetTxPowerEnd(m_input.txPowerB); + m_txB->SendPacket (p, txVector); +} + +FrameCaptureExperiment::FrameCaptureExperiment () +{ +} +FrameCaptureExperiment::Input::Input () + : interval (MicroSeconds (0)), + xA (-5), + xB (5), + txModeA ("OfdmRate12Mbps"), + txModeB ("OfdmRate12Mbps"), + txPowerLevelA (0), + txPowerLevelB (0), + txPowerA (20), + txPowerB (20), + packetSizeA (1500), + packetSizeB (1500), + standard (WIFI_PHY_STANDARD_80211a), + preamble (WIFI_PREAMBLE_LONG) +{ +} + +void +FrameCaptureExperiment::Run (struct FrameCaptureExperiment::Input input) +{ + m_input = input; + + double range = std::max (std::abs (input.xA), input.xB); + Config::SetDefault ("ns3::RangePropagationLossModel::MaxRange", DoubleValue (range)); + + Ptr channel = CreateObject (); + channel->SetPropagationDelayModel (CreateObject ()); + Ptr loss = CreateObject (); + channel->SetPropagationLossModel (loss); + + Ptr posTxA = CreateObject (); + posTxA->SetPosition (Vector (input.xA, 0.0, 0.0)); + Ptr posTxB = CreateObject (); + posTxB->SetPosition (Vector (input.xB, 0.0, 0.0)); + Ptr posRx = CreateObject (); + posRx->SetPosition (Vector (0.0, 0.0, 0.0)); + + m_txA = CreateObject (); + m_txB = CreateObject (); + Ptr rx = CreateObject (); + + Ptr error = CreateObject (); + m_txA->SetErrorRateModel (error); + m_txB->SetErrorRateModel (error); + rx->SetErrorRateModel (error); + m_txA->SetChannel (channel); + m_txB->SetChannel (channel); + rx->SetChannel (channel); + m_txA->SetMobility (posTxA); + m_txB->SetMobility (posTxB); + rx->SetMobility (posRx); + + m_txA->ConfigureStandard (input.standard); + m_txB->ConfigureStandard (input.standard); + rx->ConfigureStandard (input.standard); + + for (int n = 0; n < 1000; ++n) + { + Simulator::Schedule (Seconds (double(n * 0.1)), &FrameCaptureExperiment::SendA, this); + Simulator::Schedule (Seconds (double(n * 0.1)) + input.interval, &FrameCaptureExperiment::SendB, this); + } + + Simulator::Run (); + Simulator::Destroy (); +} + + +int main (int argc, char *argv[]) +{ + FrameCaptureExperiment::Input input; + std::string str_standard = "WIFI_PHY_STANDARD_80211a"; + std::string str_preamble = "WIFI_PREAMBLE_LONG"; + double delay = 10; //microseconds + + CommandLine cmd; + cmd.AddValue ("delay", "Delay in microseconds between frame transmission from sender A and frame transmission from sender B", delay); + cmd.AddValue ("xA", "The position of transmitter A (< 0)", input.xA); + cmd.AddValue ("xB", "The position of transmitter B (> 0)", input.xB); + cmd.AddValue ("packetSizeA", "Packet size in bytes of transmitter A", input.packetSizeA); + cmd.AddValue ("packetSizeB", "Packet size in bytes of transmitter B", input.packetSizeB); + cmd.AddValue ("txPowerA", "TX power level of transmitter A", input.txPowerLevelA); + cmd.AddValue ("txPowerB", "TX power level of transmitter B", input.txPowerLevelB); + cmd.AddValue ("txPowerA", "TX power of transmitter A", input.txPowerA); + cmd.AddValue ("txPowerB", "TX power of transmitter B", input.txPowerB); + cmd.AddValue ("txModeA", "Wifi mode used for payload transmission of sender A", input.txModeA); + cmd.AddValue ("txModeB", "Wifi mode used for payload transmission of sender B", input.txModeB); + cmd.AddValue ("standard", "IEEE 802.11 flavor", str_standard); + cmd.AddValue ("preamble", "Type of preamble", str_preamble); + cmd.Parse (argc, argv); + +// LogComponentEnable ("YansWifiPhy", LOG_LEVEL_ALL); +// LogComponentEnable ("WifiPhy", LOG_LEVEL_ALL); +// LogComponentEnable ("InterferenceHelper", LOG_LEVEL_ALL); + + input.interval = MicroSeconds (delay); + + if (input.xA >= 0 || input.xB <= 0) + { + std::cout << "Value of xA must be smaller than 0 and value of xB must be bigger than 0!" << std::endl; + return 0; + } + + if (str_standard == "WIFI_PHY_STANDARD_80211a") + { + input.standard = WIFI_PHY_STANDARD_80211a; + } + else if (str_standard == "WIFI_PHY_STANDARD_80211b") + { + input.standard = WIFI_PHY_STANDARD_80211b; + } + else if (str_standard == "WIFI_PHY_STANDARD_80211g") + { + input.standard = WIFI_PHY_STANDARD_80211g; + } + else if (str_standard == "WIFI_PHY_STANDARD_80211n_2_4GHZ") + { + input.standard = WIFI_PHY_STANDARD_80211n_2_4GHZ; + } + else if (str_standard == "WIFI_PHY_STANDARD_80211n_5GHZ") + { + input.standard = WIFI_PHY_STANDARD_80211n_5GHZ; + } + else if (str_standard == "WIFI_PHY_STANDARD_80211ac") + { + input.standard = WIFI_PHY_STANDARD_80211ac; + } + + if (str_preamble == "WIFI_PREAMBLE_LONG" && (input.standard == WIFI_PHY_STANDARD_80211a || input.standard == WIFI_PHY_STANDARD_80211b || input.standard == WIFI_PHY_STANDARD_80211g)) + { + input.preamble = WIFI_PREAMBLE_LONG; + } + else if (str_preamble == "WIFI_PREAMBLE_SHORT" && (input.standard == WIFI_PHY_STANDARD_80211b || input.standard == WIFI_PHY_STANDARD_80211g)) + { + input.preamble = WIFI_PREAMBLE_SHORT; + } + else if (str_preamble == "WIFI_PREAMBLE_HT_MF" && (input.standard == WIFI_PHY_STANDARD_80211n_2_4GHZ || input.standard == WIFI_PHY_STANDARD_80211n_5GHZ)) + { + input.preamble = WIFI_PREAMBLE_HT_MF; + } + else if (str_preamble == "WIFI_PREAMBLE_HT_GF" && (input.standard == WIFI_PHY_STANDARD_80211n_2_4GHZ || input.standard == WIFI_PHY_STANDARD_80211n_5GHZ)) + { + input.preamble = WIFI_PREAMBLE_HT_GF; + } + else if (str_preamble == "WIFI_PREAMBLE_VHT" && input.standard == WIFI_PHY_STANDARD_80211ac) + { + input.preamble = WIFI_PREAMBLE_VHT; + } + else + { + std::cout << "Preamble does not exist or is not compatible with the selected standard!" << std::endl; + return 0; + } + + FrameCaptureExperiment experiment; + double sinrRange = 15; + double stepSize = 0.2; + int stepBound = (int)(sinrRange / stepSize); + double powerBase = 10; + + for (int numSteps = 0; numSteps < stepBound; ++numSteps) + { + double power = powerBase + stepSize * numSteps; + input.txPowerA = power; + input.txPowerB = powerBase; + experiment.Run(input); + } + +// experiment.Run (input); + + return 0; +} diff --git a/src/wifi/examples/wscript b/src/wifi/examples/wscript index 6d41f2a..1070a97 100644 --- a/src/wifi/examples/wscript +++ b/src/wifi/examples/wscript @@ -11,6 +11,10 @@ def build(bld): obj = bld.create_ns3_program('test-interference-helper', ['core', 'mobility', 'network', 'wifi']) obj.source = 'test-interference-helper.cc' + + obj = bld.create_ns3_program('test-frame-capture', + ['core', 'mobility', 'network', 'wifi']) + obj.source = 'test-frame-capture.cc' obj = bld.create_ns3_program('ideal-wifi-manager-example', ['core', 'network', 'wifi', 'stats', 'mobility', 'propagation']) diff --git a/src/wifi/model/frame-capture-model.cc b/src/wifi/model/frame-capture-model.cc new file mode 100644 index 0000000..4344608 --- /dev/null +++ b/src/wifi/model/frame-capture-model.cc @@ -0,0 +1,67 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +#include "frame-capture-model.h" +#include +#include + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (FrameCaptureModel); + +TypeId +FrameCaptureModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::FrameCaptureModel") + .SetParent () + .SetGroupName ("Wifi") + .AddConstructor () + ; + return tid; +} + +FrameCaptureModel::FrameCaptureModel() +{ +} + +double +FrameCaptureModel::CalculatePreambleCaptureProbability (double sinr) +{ + double z = std::sqrt (sinr / 4.0); + double p = 0.5 * erfc(z); + if (p == 0.0) + { + return 1.0; + } + double pe = CalculatePe (p); + pe = std::min(pe, 1.0); + double prob = std::pow (1 - pe, 240); + return prob; +} + +double +FrameCaptureModel::CalculatePayloadCaptureProbability (double sinr) +{ + double sinrDb = 10 * std::log10(sinr); + double prob = 0.4989 * erf((sinrDb - 9.356) / 0.8722) + 0.4989; + prob = std::max(prob, 0.0); + prob = std::min(prob, 1.0); + return prob; +} + +double +FrameCaptureModel::CalculatePe(double p) +{ + double D = std::sqrt (4.0 * p * (1.0 - p)); + double pe = 1.0; + pe = 0.5 * (36.0 * std::pow (D, 10) + + 211.0 * std::pow (D, 12) + + 1404.0 * std::pow (D, 14) + + 11633.0 * std::pow (D, 16) + + 77433.0 * std::pow (D, 18) + + 502690.0 * std::pow (D, 20) + + 3322763.0 * std::pow (D, 22) + + 21292910.0 * std::pow (D, 24) + + 134365911.0 * std::pow (D, 26)); + return pe; +} + +} // //namespace ns3 diff --git a/src/wifi/model/frame-capture-model.h b/src/wifi/model/frame-capture-model.h new file mode 100644 index 0000000..9bfb579 --- /dev/null +++ b/src/wifi/model/frame-capture-model.h @@ -0,0 +1,23 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ + +#ifndef FRAME_CAPTURE_MODEL_H +#define FRAME_CAPTURE_MODEL_H + +#include "ns3/object.h" + +namespace ns3 { + +class FrameCaptureModel : public Object +{ +public: + static TypeId GetTypeId (void); + FrameCaptureModel (); + double CalculatePreambleCaptureProbability (double sinr); + double CalculatePayloadCaptureProbability (double sinr); +private: + double CalculatePe (double p); +}; + +} //namespace ns3 + +#endif /* FRAME_CAPTURE_MODEL_H */ diff --git a/src/wifi/model/interference-helper.cc b/src/wifi/model/interference-helper.cc index feae109..6e5a22a 100644 --- a/src/wifi/model/interference-helper.cc +++ b/src/wifi/model/interference-helper.cc @@ -251,14 +251,20 @@ double InterferenceHelper::CalculateNoiseInterferenceW (Ptr event, NiChanges *ni) const { double noiseInterference = m_firstPower; - NS_ASSERT (m_rxing); - for (NiChanges::const_iterator i = m_niChanges.begin () + 1; i != m_niChanges.end (); i++) + for (NiChanges::const_iterator i = m_niChanges.begin (); i != m_niChanges.end (); ++i) { - if ((event->GetEndTime () == i->GetTime ()) && event->GetRxPowerW () == -i->GetDelta ()) - { - break; - } - ni->push_back (*i); + if (i->GetTime () < event->GetStartTime ()) + { + noiseInterference += i->GetDelta (); + } + else if (i->GetTime () > event->GetStartTime () && i->GetTime () < event->GetEndTime ()) + { + ni->push_back(*i); + } + else if (event->GetEndTime () == i->GetTime () && event->GetRxPowerW () == -i->GetDelta ()) + { + break; + } } ni->insert (ni->begin (), NiChange (event->GetStartTime (), noiseInterference)); ni->push_back (NiChange (event->GetEndTime (), 0)); @@ -865,4 +871,16 @@ InterferenceHelper::NotifyRxEnd () m_rxing = false; } +double +InterferenceHelper::CalculatePreambleCaptureProbability (double sinr) +{ + return m_frameCaptureModel->CalculatePreambleCaptureProbability(sinr); +} + +double +InterferenceHelper::CalculatePayloadCaptureProbability (double sinr) +{ + return m_frameCaptureModel->CalculatePayloadCaptureProbability(sinr); +} + } //namespace ns3 diff --git a/src/wifi/model/interference-helper.h b/src/wifi/model/interference-helper.h index 8629d80..4c1a261 100644 --- a/src/wifi/model/interference-helper.h +++ b/src/wifi/model/interference-helper.h @@ -24,6 +24,7 @@ #include "ns3/nstime.h" #include "wifi-tx-vector.h" #include "error-rate-model.h" +#include "frame-capture-model.h" namespace ns3 { @@ -206,7 +207,17 @@ private: * Erase all events. */ void EraseEvents (void); - + // following methods used to support frame capture capability + /** + * Calculate the successful probability for preamble capture + * \param sinr the sinr value at the current time + */ + double CalculatePreambleCaptureProbability (double sinr); + /** + * Calculate the successful probability for payload capture + * \param sinr the sinr value at the current time + */ + double CalculatePayloadCaptureProbability (double sinr); private: /** @@ -322,6 +333,9 @@ private: NiChanges m_niChanges; double m_firstPower; bool m_rxing; + // following variables used for frame capture capability + Ptr m_frameCaptureModel; + /// Returns an iterator to the first nichange, which is later than moment NiChanges::iterator GetPosition (Time moment); /** diff --git a/src/wifi/model/wifi-phy-state-helper.cc b/src/wifi/model/wifi-phy-state-helper.cc index 7d5d296..acde826 100644 --- a/src/wifi/model/wifi-phy-state-helper.cc +++ b/src/wifi/model/wifi-phy-state-helper.cc @@ -541,4 +541,14 @@ WifiPhyStateHelper::SwitchFromSleep (Time duration) } } +void +WifiPhyStateHelper::SwitchFromRxAbort () +{ + NS_ASSERT (IsStateRx ()); + NS_ASSERT (m_rxing); + NotifyRxEndError (); + m_endRx = Simulator::Now (); + DoSwitchFromRx (); + NS_ASSERT (!IsStateRx ()); +} } //namespace ns3 diff --git a/src/wifi/model/wifi-phy-state-helper.h b/src/wifi/model/wifi-phy-state-helper.h index d9ca56b..67a8f9d 100644 --- a/src/wifi/model/wifi-phy-state-helper.h +++ b/src/wifi/model/wifi-phy-state-helper.h @@ -181,7 +181,10 @@ public: * \param duration the duration of CCA busy state */ void SwitchFromSleep (Time duration); - + /** + * Abort current reception + */ + void SwitchFromRxAbort (void); /** \todo Why is this public? */ TracedCallback m_stateLogger; diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index 654e092..d92ae0b 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -29,6 +29,7 @@ #include "ns3/pointer.h" #include "wifi-phy-tag.h" #include "ampdu-tag.h" +#include "wifi-phy-tag.h" #include "wifi-utils.h" namespace ns3 { @@ -191,13 +192,13 @@ WifiPhy::GetTypeId (void) MakeDoubleChecker ()) .AddAttribute ("TxGain", "Transmission gain (dB).", - DoubleValue (1.0), + DoubleValue (0.0), MakeDoubleAccessor (&WifiPhy::SetTxGain, &WifiPhy::GetTxGain), MakeDoubleChecker ()) .AddAttribute ("RxGain", "Reception gain (dB).", - DoubleValue (1.0), + DoubleValue (0.0), MakeDoubleAccessor (&WifiPhy::SetRxGain, &WifiPhy::GetRxGain), MakeDoubleChecker ()) @@ -308,6 +309,18 @@ WifiPhy::GetTypeId (void) MakeBooleanAccessor (&WifiPhy::GetShortPlcpPreambleSupported, &WifiPhy::SetShortPlcpPreambleSupported), MakeBooleanChecker ()) + .AddAttribute ("PreambleCaptureEnabled", + "Whether or not to enable capture at the preamble portion of the packet.", + BooleanValue (true), + MakeBooleanAccessor (&WifiPhy::GetPreambleCapture, + &WifiPhy::SetPreambleCapture), + MakeBooleanChecker ()) + .AddAttribute ("PayloadCaptureEnabled", + "Whether or not to enable cautpure at the payload(data) portion of the packet", + BooleanValue (true), + MakeBooleanAccessor (&WifiPhy::GetPayloadCapture, + &WifiPhy::SetPayloadCapture), + MakeBooleanChecker ()) .AddTraceSource ("PhyTxBegin", "Trace source indicating a packet " "has begun transmitting over the channel medium", @@ -372,7 +385,9 @@ WifiPhy::WifiPhy () m_channelNumber (0), m_initialChannelNumber (0), m_totalAmpduSize (0), - m_totalAmpduNumSymbols (0) + m_totalAmpduNumSymbols (0), + m_doPreambleCapture (true), + m_doPayloadCapture (true) { NS_LOG_FUNCTION (this); NS_UNUSED (m_numberOfTransmitters); @@ -706,6 +721,32 @@ WifiPhy::GetChannelSwitchDelay (void) const return m_channelSwitchDelay; } +void +WifiPhy::SetPreambleCapture (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_doPreambleCapture = enable; +} + +bool +WifiPhy::GetPreambleCapture (void) const +{ + return m_doPreambleCapture; +} + +void +WifiPhy::SetPayloadCapture (bool enable) +{ + NS_LOG_FUNCTION (this << enable); + m_doPayloadCapture = enable; +} + +bool +WifiPhy::GetPayloadCapture (void) const +{ + return m_doPayloadCapture; +} + double WifiPhy::CalculateSnr (WifiTxVector txVector, double ber) const { @@ -2296,6 +2337,7 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim txVector, rxDuration, rxPowerW); + Time currentRxStage = Seconds (0); switch (m_state->GetState ()) { @@ -2315,20 +2357,29 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim { //that packet will be noise _after_ the completion of the //channel switching. - goto maybeCcaBusy; + CalculateCcaBusyDuration (); } break; case WifiPhy::RX: - NS_LOG_DEBUG ("drop packet because already in Rx (power=" << - rxPowerW << "W)"); - NotifyRxDrop (packet); - if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ()) - { - //that packet will be noise _after_ the reception of the - //currently-received packet. - goto maybeCcaBusy; - } - break; + { + NS_ASSERT (m_rxPacketEvent != NULL); + currentRxStage = Simulator::Now() - m_rxPacketEvent->GetStartTime(); + bool doReceptionSwitch = false; + if (currentRxStage <= preambleAndHeaderDuration) // still receiving the preamble and plcp header portion of the old packet + { + doReceptionSwitch = CheckPreambleCapture (packet, event); + } + else + { + doReceptionSwitch = CheckPayloadCapture (packet, event); + } + if (doReceptionSwitch) + { + m_endPlcpRxEvent = Simulator::Schedule (preambleAndHeaderDuration, &WifiPhy::StartReceivePacket, this, + packet, txVector, mpdutype, event); + } + break; + } case WifiPhy::TX: NS_LOG_DEBUG ("drop packet because already in Tx (power=" << rxPowerW << "W)"); @@ -2337,7 +2388,7 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim { //that packet will be noise _after_ the transmission of the //currently-transmitted packet. - goto maybeCcaBusy; + CalculateCcaBusyDuration (); } break; case WifiPhy::CCA_BUSY: @@ -2350,7 +2401,7 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim m_mpdusNum = 0; NS_LOG_DEBUG ("drop packet because no PLCP preamble/header has been received"); NotifyRxDrop (packet); - goto maybeCcaBusy; + CalculateCcaBusyDuration (); } else if (preamble != WIFI_PREAMBLE_NONE && packet->PeekPacketTag (ampduTag) && m_mpdusNum == 0) { @@ -2388,6 +2439,8 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim NS_ASSERT (m_endPlcpRxEvent.IsExpired ()); NotifyRxBegin (packet); m_interference.NotifyRxStart (); + m_rxPacket = packet; + m_rxPacketEvent = event; if (preamble != WIFI_PREAMBLE_NONE) { @@ -2395,10 +2448,6 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim m_endPlcpRxEvent = Simulator::Schedule (preambleAndHeaderDuration, &WifiPhy::StartReceivePacket, this, packet, txVector, mpdutype, event); } - - NS_ASSERT (m_endRxEvent.IsExpired ()); - m_endRxEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndReceive, this, - packet, preamble, mpdutype, event); } else { @@ -2406,7 +2455,7 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim rxPowerW << "<" << GetEdThresholdW () << ")"); NotifyRxDrop (packet); m_plcpSuccess = false; - goto maybeCcaBusy; + CalculateCcaBusyDuration (); } break; case WifiPhy::SLEEP: @@ -2417,8 +2466,12 @@ WifiPhy::StartReceivePreambleAndHeader (Ptr packet, double rxPowerW, Tim } return; +} -maybeCcaBusy: +void +WifiPhy::CalculateCcaBusyDuration () +{ +// maybeCcaBusy: //We are here because we have received the first bit of a packet and we are //not going to be able to synchronize on it //In this model, CCA becomes busy when the aggregation of all signals as @@ -2431,6 +2484,159 @@ maybeCcaBusy: } } +bool +WifiPhy::CheckPreambleCapture (Ptr packet, Ptr event) +{ + NS_LOG_DEBUG (Simulator::Now() << ", preamble capture check: old reception event start at " + << m_rxPacketEvent->GetStartTime() + << ", end at " << m_rxPacketEvent->GetEndTime() + << ", old rxPower "<< m_rxPacketEvent->GetRxPowerW()); + bool result = false; + Time endRx = event->GetEndTime(); + InterferenceHelper::SnrPer snrPer; + snrPer = m_interference.CalculatePlcpHeaderSnrPer (m_rxPacketEvent); // check whether the plcp header can still decoded + NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per); + if (m_random->GetValue () > snrPer.per) // the reception of the old packet can be continued + { + NS_ASSERT (m_endPlcpRxEvent.IsRunning()); + NS_LOG_INFO (Simulator::Now() << " preamble capture check: dropping newly arrived packet" + << ", because already sync to a stronger enough signal"); + NotifyRxDrop (packet); + if (endRx > Simulator::Now() + m_state->GetDelayUntilIdle()) + { + CalculateCcaBusyDuration (); + } + } + else // the reception of the old packet cannot be continued + { + NS_LOG_INFO (Simulator::Now() << " preamble capture check: dropping currently received packet"); + AbortCurrentReception (); + if (m_doPreambleCapture) // if the frame capture capability at preamble is enabled, check whether can + // switch to the new packet + { + NS_ASSERT (m_endPlcpRxEvent.IsExpired() && m_endRxEvent.IsExpired()); + NS_LOG_INFO (Simulator::Now()<< " preamble capture check: switch to new packet"); + InterferenceHelper::SnrPer snrPerForNewPkt; + snrPerForNewPkt = m_interference.CalculatePlcpHeaderSnrPer (event); + double prob = m_interference.CalculatePreambleCaptureProbability(snrPerForNewPkt.snr); + if (m_random->GetValue () < prob) + { + SwitchReception (packet, event); + result = true; + } + else + { + NS_LOG_INFO (Simulator::Now()<<" preamble capture: signal is too low for capture"); + NotifyRxDrop (packet); + if (endRx > Simulator::Now() + m_state->GetDelayUntilIdle()) + { + CalculateCcaBusyDuration (); + } + } + } + else // if the frame capture is not enabled, drop the packet + { + NS_LOG_INFO (Simulator::Now()<<" preamble capture check: drop packet because already receiving"); + NotifyRxDrop (packet); + if (endRx > Simulator::Now() + m_state->GetDelayUntilIdle()) + { + CalculateCcaBusyDuration (); + } + } + } + return result; +} + +bool +WifiPhy::CheckPayloadCapture (Ptr packet, Ptr event) +{ + NS_LOG_DEBUG (Simulator::Now() << ", payload capture check: old reception event start at " + << m_rxPacketEvent->GetStartTime() + << ", end at " << m_rxPacketEvent->GetEndTime() + << ", old rxPower "<< m_rxPacketEvent->GetRxPowerW()); + bool result = false; + Time endRx = event->GetEndTime(); + InterferenceHelper::SnrPer snrPer; + snrPer = m_interference.CalculatePlcpPayloadSnrPer(m_rxPacketEvent); // check whether the plcp header can still decoded + NS_LOG_DEBUG ("snr(dB)=" << RatioToDb (snrPer.snr) << ", per=" << snrPer.per); + if (m_random->GetValue () > snrPer.per) // the reception of the old packet can be continued + { + NS_ASSERT (m_endRxEvent.IsRunning()); + NS_LOG_INFO (Simulator::Now() << " payload capture check: dropping newly arrived packet" + << ", because already sync to a stronger enough signal"); + NotifyRxDrop (packet); + if (endRx > Simulator::Now() + m_state->GetDelayUntilIdle()) + { + CalculateCcaBusyDuration (); + } + } + else // the reception of the old packet cannot be continued + { + NS_LOG_INFO (Simulator::Now() << " preamble capture check: dropping currently received packet"); + AbortCurrentReception (); + if (m_doPayloadCapture) // if the frame capture capability at preamble is enabled, check whether can + // switch to the new packet + { + NS_ASSERT (m_endPlcpRxEvent.IsExpired() && m_endRxEvent.IsExpired()); + NS_LOG_INFO (Simulator::Now()<< " payload capture check: switch to new packet"); + InterferenceHelper::SnrPer snrPerForNewPkt; + snrPerForNewPkt = m_interference.CalculatePlcpPayloadSnrPer (event); + double prob = m_interference.CalculatePayloadCaptureProbability (snrPerForNewPkt.snr); + if (m_random->GetValue () < prob) + { + SwitchReception (packet, event); + result = true; + } + else + { + NS_LOG_INFO (Simulator::Now()<<" payload capture: signal is too low for capture"); + NotifyRxDrop (packet); + if (endRx > Simulator::Now() + m_state->GetDelayUntilIdle()) + { + CalculateCcaBusyDuration (); + } + } + } + else // if the frame capture is not enabled, drop the packet + { + NS_LOG_INFO (Simulator::Now()<<" payload capture check: drop packet because already receiving"); + NotifyRxDrop (packet); + if (endRx > Simulator::Now() + m_state->GetDelayUntilIdle()) + { + CalculateCcaBusyDuration (); + } + } + } + return result; +} + +void +WifiPhy::AbortCurrentReception () +{ + if (m_endPlcpRxEvent.IsRunning()) + { + m_endPlcpRxEvent.Cancel(); + } + if (m_endRxEvent.IsRunning()) + { + m_endRxEvent.Cancel(); + } + m_interference.NotifyRxEnd(); + m_state->SwitchFromRxAbort(); + m_rxPacket = NULL; + m_rxPacketEvent = NULL; +} + +void +WifiPhy::SwitchReception (Ptr packet, Ptr event) +{ + m_rxPacket = packet; + m_rxPacketEvent = event; + m_state->SwitchToRx (event->GetDuration()); + NotifyRxBegin (packet); + m_interference.NotifyRxStart(); +} + void WifiPhy::StartReceivePacket (Ptr packet, WifiTxVector txVector, @@ -2453,12 +2659,18 @@ WifiPhy::StartReceivePacket (Ptr packet, { NS_LOG_DEBUG ("receiving plcp payload"); //endReceive is already scheduled m_plcpSuccess = true; + WifiPreamble preamble = txVector.GetPreambleType (); + Time preambleAndHeaderDuration = CalculatePlcpPreambleAndHeaderDuration (txVector); + m_endRxEvent = Simulator::Schedule (event->GetDuration() - preambleAndHeaderDuration, &WifiPhy::EndReceive, this, + packet, preamble, mpdutype, event); } else //mode is not allowed { NS_LOG_DEBUG ("drop packet because it was sent using an unsupported mode (" << txMode << ")"); NotifyRxDrop (packet); m_plcpSuccess = false; + AbortCurrentReception (); + CalculateCcaBusyDuration (); } } else //plcp reception failed @@ -2466,6 +2678,8 @@ WifiPhy::StartReceivePacket (Ptr packet, NS_LOG_DEBUG ("drop packet because plcp preamble/header reception failed"); NotifyRxDrop (packet); m_plcpSuccess = false; + AbortCurrentReception (); + CalculateCcaBusyDuration (); } } diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 17a1f45..5e5c2b3 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -1524,6 +1524,25 @@ public: */ virtual std::vector GetSupportedChannelWidthSet (void) const; +// following method is used to support frame capture capability + + /** + * \param enable boolean value to indicate whether preamble capture is enabled or not + */ + void SetPreambleCapture (bool enable); + /** + * \return boolean value to indicate whether preamble capture is enable or not + */ + bool GetPreambleCapture (void) const; + /** + * \param enable boolean value to indicate whether payload capture is enabled or not + */ + void SetPayloadCapture (bool enable); + /** + * \return boolean value to indicate whether payload capture is enable or not + */ + bool GetPayloadCapture (void) const; + protected: // Inherited @@ -1741,7 +1760,35 @@ private: * of its size. */ TracedCallback, uint16_t, uint16_t, WifiTxVector, MpduInfo> m_phyMonitorSniffTxTrace; - + + // following methods used to support frame capture capability + /** + * Due to newly arrived signal, the old reception cannot be continued and has to be abort + */ + void AbortCurrentReception (void); + /** + * Calculate the duration of CCA busy + */ + void CalculateCcaBusyDuration (void); + /** + * Check whether preamble capture can be triggered + * \param packet the newly arrived packet which needs to be check for capture + * \param event the receiving event associated with the receiving packet + * \param txVector + * \param mpdutype + */ + bool CheckPreambleCapture (Ptr packet, Ptr event); + /** + * Check whether payload capture can be triggered + * \param packet the newly arrived packet which needs to be check for capture + * \param event the receiving event associated with the receiving packet + * \param tag + */ + bool CheckPayloadCapture (Ptr packet, Ptr event); + /** + * The new packet passes the check and the receiver is going to switch to the new packet + */ + void SwitchReception (Ptr packet, Ptr event); /** * This vector holds the set of transmission modes that this * WifiPhy(-derived class) can support. In conversation we call this @@ -1824,6 +1871,12 @@ private: Ptr m_device; //!< Pointer to the device Ptr m_mobility; //!< Pointer to the mobility model + + // following variables used to support frame capture capability + Ptr m_rxPacket; // The packet that is currently being received by the receiver + Ptr m_rxPacketEvent; // The event that indicates the current receiving event + bool m_doPreambleCapture; // The flag indicates whether the capture at the preamble portion of the packet is enabled or not + bool m_doPayloadCapture; // The flag indicates whether the capture at the payload(data) portion of the packet is enabled or not }; /** diff --git a/src/wifi/wscript b/src/wifi/wscript index 3b07f77..b0895f1 100644 --- a/src/wifi/wscript +++ b/src/wifi/wscript @@ -81,6 +81,7 @@ def build(bld): 'model/ht-operations.cc', 'model/dsss-parameter-set.cc', 'model/edca-parameter-set.cc', + 'model/frame-capture-model.cc', 'helper/wifi-radio-energy-model-helper.cc', 'helper/vht-wifi-mac-helper.cc', 'helper/ht-wifi-mac-helper.cc', @@ -186,6 +187,7 @@ def build(bld): 'model/ht-operations.h', 'model/dsss-parameter-set.h', 'model/edca-parameter-set.h', + 'model/frame-capture-model.h', 'helper/wifi-radio-energy-model-helper.h', 'helper/vht-wifi-mac-helper.h', 'helper/ht-wifi-mac-helper.h',