A Discrete-Event Network Simulator
API
interference-helper.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  * Sébastien Deronne <sebastien.deronne@gmail.com>
20  */
21 
22 #include "ns3/packet.h"
23 #include "ns3/simulator.h"
24 #include "ns3/log.h"
25 #include "interference-helper.h"
26 #include "wifi-phy.h"
27 #include "error-rate-model.h"
28 
29 namespace ns3 {
30 
31 NS_LOG_COMPONENT_DEFINE ("InterferenceHelper");
32 
33 /****************************************************************
34  * Phy event class
35  ****************************************************************/
36 
37 Event::Event (Ptr<const Packet> packet, WifiTxVector txVector, Time duration, double rxPower)
38  : m_packet (packet),
39  m_txVector (txVector),
40  m_startTime (Simulator::Now ()),
41  m_endTime (m_startTime + duration),
42  m_rxPowerW (rxPower)
43 {
44 }
45 
47 {
48 }
49 
51 Event::GetPacket (void) const
52 {
53  return m_packet;
54 }
55 
56 Time
57 Event::GetStartTime (void) const
58 {
59  return m_startTime;
60 }
61 
62 Time
63 Event::GetEndTime (void) const
64 {
65  return m_endTime;
66 }
67 
68 double
69 Event::GetRxPowerW (void) const
70 {
71  return m_rxPowerW;
72 }
73 
75 Event::GetTxVector (void) const
76 {
77  return m_txVector;
78 }
79 
82 {
83  return m_txVector.GetMode ();
84 }
85 
86 
87 /****************************************************************
88  * Class which records SNIR change events for a
89  * short period of time.
90  ****************************************************************/
91 
93  : m_power (power),
94  m_event (event)
95 {
96 }
97 
98 double
100 {
101  return m_power;
102 }
103 
104 void
106 {
107  m_power += power;
108 }
109 
112 {
113  return m_event;
114 }
115 
116 
117 /****************************************************************
118  * The actual InterferenceHelper
119  ****************************************************************/
120 
122  : m_errorRateModel (0),
123  m_numRxAntennas (1),
124  m_firstPower (0),
125  m_rxing (false)
126 {
127  // Always have a zero power noise event in the list
128  AddNiChangeEvent (Time (0), NiChange (0.0, 0));
129 }
130 
132 {
133  EraseEvents ();
134  m_errorRateModel = 0;
135 }
136 
138 InterferenceHelper::Add (Ptr<const Packet> packet, WifiTxVector txVector, Time duration, double rxPowerW)
139 {
140  Ptr<Event> event = Create<Event> (packet, txVector, duration, rxPowerW);
141  AppendEvent (event);
142  return event;
143 }
144 
145 void
146 InterferenceHelper::AddForeignSignal (Time duration, double rxPowerW)
147 {
148  // Parameters other than duration and rxPowerW are unused for this type
149  // of signal, so we provide dummy versions
150  WifiTxVector fakeTxVector;
151  Ptr<const Packet> packet (0);
152  Add (packet, fakeTxVector, duration, rxPowerW);
153 }
154 
155 void
157 {
158  m_noiseFigure = value;
159 }
160 
161 void
163 {
164  m_errorRateModel = rate;
165 }
166 
169 {
170  return m_errorRateModel;
171 }
172 
173 void
175 {
176  m_numRxAntennas = rx;
177 }
178 
179 Time
181 {
182  Time now = Simulator::Now ();
183  auto i = GetPreviousPosition (now);
184  Time end = i->first;
185  for (; i != m_niChanges.end (); ++i)
186  {
187  double noiseInterferenceW = i->second.GetPower ();
188  end = i->first;
189  if (noiseInterferenceW < energyW)
190  {
191  break;
192  }
193  }
194  return end > now ? end - now : MicroSeconds (0);
195 }
196 
197 void
199 {
200  NS_LOG_FUNCTION (this);
201  double previousPowerStart = 0;
202  double previousPowerEnd = 0;
203  previousPowerStart = GetPreviousPosition (event->GetStartTime ())->second.GetPower ();
204  previousPowerEnd = GetPreviousPosition (event->GetEndTime ())->second.GetPower ();
205 
206  if (!m_rxing)
207  {
208  m_firstPower = previousPowerStart;
209  // Always leave the first zero power noise event in the list
210  m_niChanges.erase (++(m_niChanges.begin ()),
211  GetNextPosition (event->GetStartTime ()));
212  }
213  auto first = AddNiChangeEvent (event->GetStartTime (), NiChange (previousPowerStart, event));
214  auto last = AddNiChangeEvent (event->GetEndTime (), NiChange (previousPowerEnd, event));
215  for (auto i = first; i != last; ++i)
216  {
217  i->second.AddPower (event->GetRxPowerW ());
218  }
219 }
220 
221 double
222 InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint16_t channelWidth) const
223 {
224  //thermal noise at 290K in J/s = W
225  static const double BOLTZMANN = 1.3803e-23;
226  //Nt is the power of thermal noise in W
227  double Nt = BOLTZMANN * 290 * channelWidth * 1e6;
228  //receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
229  double noiseFloor = m_noiseFigure * Nt;
230  double noise = noiseFloor + noiseInterference;
231  double snr = signal / noise; //linear scale
232  NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr(linear)=" << snr);
233  return snr;
234 }
235 
236 double
238 {
239  double noiseInterference = m_firstPower;
240  auto it = m_niChanges.find (event->GetStartTime ());
241  for (; it != m_niChanges.end () && it->second.GetEvent () != event; ++it)
242  {
243  noiseInterference = it->second.GetPower ();
244  }
245  ni->emplace (event->GetStartTime (), NiChange (0, event));
246  while (++it != m_niChanges.end () && it->second.GetEvent () != event)
247  {
248  ni->insert (*it);
249  }
250  ni->emplace (event->GetEndTime (), NiChange (0, event));
251  return noiseInterference;
252 }
253 
254 double
255 InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, WifiTxVector txVector) const
256 {
257  if (duration.IsZero ())
258  {
259  return 1.0;
260  }
261  uint64_t rate = mode.GetPhyRate (txVector);
262  uint64_t nbits = static_cast<uint64_t> (rate * duration.GetSeconds ());
264  {
265  nbits /= txVector.GetNss (); //divide effective number of bits by NSS to achieve same chunk error rate as SISO for AWGN
266  double gain = (txVector.GetNTx () * m_numRxAntennas); //compute gain offered by MIMO, SIMO or MISO compared to SISO for AWGN
267  NS_LOG_DEBUG ("TX=" << +txVector.GetNTx () <<
268  ", RX=" << +m_numRxAntennas <<
269  ", SNIR improvement=+" << 10 * std::log10 (gain) << "dB");
270  snir *= gain;
271  }
272  double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, nbits);
273  return csr;
274 }
275 
276 double
278 {
279  NS_LOG_FUNCTION (this);
280  const WifiTxVector txVector = event->GetTxVector ();
281  double psr = 1.0; /* Packet Success Rate */
282  auto j = ni->begin ();
283  Time previous = j->first;
284  WifiMode payloadMode = event->GetPayloadMode ();
285  WifiPreamble preamble = txVector.GetPreambleType ();
286  Time plcpHeaderStart = j->first + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble
287  Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (txVector); //packet start time + preamble + L-SIG
288  Time plcpTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpSigA1Duration (preamble) + WifiPhy::GetPlcpSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A
289  Time plcpPayloadStart = plcpTrainingSymbolsStart + WifiPhy::GetPlcpTrainingSymbolDuration (txVector) + WifiPhy::GetPlcpSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
290  double noiseInterferenceW = m_firstPower;
291  double powerW = event->GetRxPowerW ();
292  while (++j != ni->end ())
293  {
294  Time current = j->first;
295  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
296  NS_ASSERT (current >= previous);
297  //Case 1: Both previous and current point to the payload
298  if (previous >= plcpPayloadStart)
299  {
300  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
301  noiseInterferenceW,
302  txVector.GetChannelWidth ()),
303  current - previous,
304  payloadMode, txVector);
305  NS_LOG_DEBUG ("Both previous and current point to the payload: mode=" << payloadMode << ", psr=" << psr);
306  }
307  //Case 2: previous is before payload and current is in the payload
308  else if (current >= plcpPayloadStart)
309  {
310  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
311  noiseInterferenceW,
312  txVector.GetChannelWidth ()),
313  current - plcpPayloadStart,
314  payloadMode, txVector);
315  NS_LOG_DEBUG ("previous is before payload and current is in the payload: mode=" << payloadMode << ", psr=" << psr);
316  }
317  noiseInterferenceW = j->second.GetPower () - powerW;
318  previous = j->first;
319  }
320  double per = 1 - psr;
321  return per;
322 }
323 
324 double
326 {
327  NS_LOG_FUNCTION (this);
328  const WifiTxVector txVector = event->GetTxVector ();
329  double psr = 1.0; /* Packet Success Rate */
330  auto j = ni->begin ();
331  Time previous = j->first;
332  WifiPreamble preamble = txVector.GetPreambleType ();
333  WifiMode mcsHeaderMode;
334  if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF)
335  {
336  //mode for PLCP header fields sent with HT modulation
337  mcsHeaderMode = WifiPhy::GetHtPlcpHeaderMode ();
338  }
339  else if (preamble == WIFI_PREAMBLE_VHT)
340  {
341  //mode for PLCP header fields sent with VHT modulation
342  mcsHeaderMode = WifiPhy::GetVhtPlcpHeaderMode ();
343  }
344  else if (preamble == WIFI_PREAMBLE_HE_SU)
345  {
346  //mode for PLCP header fields sent with HE modulation
347  mcsHeaderMode = WifiPhy::GetHePlcpHeaderMode ();
348  }
349  WifiMode headerMode = WifiPhy::GetPlcpHeaderMode (txVector);
350  Time plcpHeaderStart = j->first + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble
351  Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (txVector); //packet start time + preamble + L-SIG
352  Time plcpTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpSigA1Duration (preamble) + WifiPhy::GetPlcpSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A
353  Time plcpPayloadStart = plcpTrainingSymbolsStart + WifiPhy::GetPlcpTrainingSymbolDuration (txVector) + WifiPhy::GetPlcpSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
354  double noiseInterferenceW = m_firstPower;
355  double powerW = event->GetRxPowerW ();
356  while (++j != ni->end ())
357  {
358  Time current = j->first;
359  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
360  NS_ASSERT (current >= previous);
361  //Case 1: previous and current after playload start: nothing to do
362  if (previous >= plcpPayloadStart)
363  {
364  psr *= 1;
365  NS_LOG_DEBUG ("Case 1 - previous and current after playload start: nothing to do");
366  }
367  //Case 2: previous is in training or in SIG-B: legacy will not enter here since it didn't enter in the last two and they are all the same for legacy
368  else if (previous >= plcpTrainingSymbolsStart)
369  {
370  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
371  //Case 2a: current after payload start
372  if (current >= plcpPayloadStart)
373  {
374  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
375  noiseInterferenceW,
376  txVector.GetChannelWidth ()),
377  plcpPayloadStart - previous,
378  mcsHeaderMode, txVector);
379  NS_LOG_DEBUG ("Case 2a - previous is in training or in SIG-B and current after payload start: mode=" << mcsHeaderMode << ", psr=" << psr);
380  }
381  //Case 2b: current is in training or in SIG-B
382  else
383  {
384  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
385  noiseInterferenceW,
386  txVector.GetChannelWidth ()),
387  current - previous,
388  mcsHeaderMode, txVector);
389  NS_LOG_DEBUG ("Case 2b - previous is in training or in SIG-B and current is in training or in SIG-B: mode=" << mcsHeaderMode << ", psr=" << psr);
390  }
391  }
392  //Case 3: previous is in HT-SIG or SIG-A: legacy will not enter here since it didn't enter in the last two and they are all the same for legacy
393  else if (previous >= plcpHsigHeaderStart)
394  {
395  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
396  //Case 3a: current after payload start
397  if (current >= plcpPayloadStart)
398  {
399  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
400  noiseInterferenceW,
401  txVector.GetChannelWidth ()),
402  plcpPayloadStart - plcpTrainingSymbolsStart,
403  mcsHeaderMode, txVector);
404  //Case 3ai: VHT or HE format
405  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
406  {
407  //SIG-A is sent using legacy OFDM modulation
408  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
409  noiseInterferenceW,
410  txVector.GetChannelWidth ()),
411  plcpTrainingSymbolsStart - previous,
412  headerMode, txVector);
413  NS_LOG_DEBUG ("Case 3ai - previous is in SIG-A and current after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
414  }
415  //Case 3aii: HT formats
416  else
417  {
418  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
419  noiseInterferenceW,
420  txVector.GetChannelWidth ()),
421  plcpTrainingSymbolsStart - previous,
422  mcsHeaderMode, txVector);
423  NS_LOG_DEBUG ("Case 3aii - previous is in HT-SIG and current after payload start: mode=" << mcsHeaderMode << ", psr=" << psr);
424  }
425  }
426  //Case 3b: current is in training or in SIG-B
427  else if (current >= plcpTrainingSymbolsStart)
428  {
429  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
430  noiseInterferenceW,
431  txVector.GetChannelWidth ()),
432  current - plcpTrainingSymbolsStart,
433  mcsHeaderMode, txVector);
434  //Case 3bi: VHT or HE format
435  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
436  {
437  //SIG-A is sent using legacy OFDM modulation
438  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
439  noiseInterferenceW,
440  txVector.GetChannelWidth ()),
441  plcpTrainingSymbolsStart - previous,
442  headerMode, txVector);
443  NS_LOG_DEBUG ("Case 3bi - previous is in SIG-A and current is in training or in SIG-B: mode=" << headerMode << ", psr=" << psr);
444  }
445  //Case 3bii: HT formats
446  else
447  {
448  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
449  noiseInterferenceW,
450  txVector.GetChannelWidth ()),
451  plcpTrainingSymbolsStart - previous,
452  mcsHeaderMode, txVector);
453  NS_LOG_DEBUG ("Case 3bii - previous is in HT-SIG and current is in HT training: mode=" << mcsHeaderMode << ", psr=" << psr);
454  }
455  }
456  //Case 3c: current with previous in HT-SIG or SIG-A
457  else
458  {
459  //Case 3ci: VHT or HE format
460  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
461  {
462  //SIG-A is sent using legacy OFDM modulation
463  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
464  noiseInterferenceW,
465  txVector.GetChannelWidth ()),
466  current - previous,
467  headerMode, txVector);
468  NS_LOG_DEBUG ("Case 3ci - previous with current in SIG-A: mode=" << headerMode << ", psr=" << psr);
469  }
470  //Case 3cii: HT mixed format or HT greenfield
471  else
472  {
473  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
474  noiseInterferenceW,
475  txVector.GetChannelWidth ()),
476  current - previous,
477  mcsHeaderMode, txVector);
478  NS_LOG_DEBUG ("Case 3cii - previous with current in HT-SIG: mode=" << mcsHeaderMode << ", psr=" << psr);
479  }
480  }
481  }
482  //Case 4: previous in L-SIG: HT GF will not reach here because it will execute the previous if and exit
483  else if (previous >= plcpHeaderStart)
484  {
485  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
486  //Case 4a: current after payload start
487  if (current >= plcpPayloadStart)
488  {
489  //Case 4ai: legacy format
490  if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
491  {
492  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
493  noiseInterferenceW,
494  txVector.GetChannelWidth ()),
495  plcpPayloadStart - previous,
496  headerMode, txVector);
497  NS_LOG_DEBUG ("Case 4ai - previous in L-SIG and current after payload start: mode=" << headerMode << ", psr=" << psr);
498  }
499  //Case 4aii: VHT or HE format
500  else if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
501  {
502  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
503  noiseInterferenceW,
504  txVector.GetChannelWidth ()),
505  plcpPayloadStart - plcpTrainingSymbolsStart,
506  mcsHeaderMode, txVector);
507  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
508  noiseInterferenceW,
509  txVector.GetChannelWidth ()),
510  plcpTrainingSymbolsStart - previous,
511  headerMode, txVector);
512  NS_LOG_DEBUG ("Case 4aii - previous is in L-SIG and current after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
513  }
514  //Case 4aiii: HT mixed format
515  else
516  {
517  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
518  noiseInterferenceW,
519  txVector.GetChannelWidth ()),
520  plcpPayloadStart - plcpHsigHeaderStart,
521  mcsHeaderMode, txVector);
522  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
523  noiseInterferenceW,
524  txVector.GetChannelWidth ()),
525  plcpHsigHeaderStart - previous,
526  headerMode, txVector);
527  NS_LOG_DEBUG ("Case 4aiii - previous in L-SIG and current after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
528  }
529  }
530  //Case 4b: current is in training or in SIG-B. legacy will not come here since it went in previous if or if the previous if is not true this will be not true
531  else if (current >= plcpTrainingSymbolsStart)
532  {
533  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
534  //Case 4bi: VHT or HE format
535  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
536  {
537  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
538  noiseInterferenceW,
539  txVector.GetChannelWidth ()),
540  current - plcpTrainingSymbolsStart,
541  mcsHeaderMode, txVector);
542  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
543  noiseInterferenceW,
544  txVector.GetChannelWidth ()),
545  plcpTrainingSymbolsStart - previous,
546  headerMode, txVector);
547  NS_LOG_DEBUG ("Case 4bi - previous is in L-SIG and current in training or in SIG-B: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
548  }
549  //Case 4bii: HT mixed format
550  else
551  {
552  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
553  noiseInterferenceW,
554  txVector.GetChannelWidth ()),
555  current - plcpHsigHeaderStart,
556  mcsHeaderMode, txVector);
557  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
558  noiseInterferenceW,
559  txVector.GetChannelWidth ()),
560  plcpHsigHeaderStart - previous,
561  headerMode, txVector);
562  NS_LOG_DEBUG ("Case 4bii - previous in L-SIG and current in HT training: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
563  }
564  }
565  //Case 4c: current in HT-SIG or in SIG-A. Legacy will not come here since it went in previous if or if the previous if is not true this will be not true
566  else if (current >= plcpHsigHeaderStart)
567  {
568  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
569  //Case 4ci: VHT format
570  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
571  {
572  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
573  noiseInterferenceW,
574  txVector.GetChannelWidth ()),
575  current - previous,
576  headerMode, txVector);
577  NS_LOG_DEBUG ("Case 4ci - previous is in L-SIG and current in SIG-A: mode=" << headerMode << ", psr=" << psr);
578  }
579  //Case 4cii: HT mixed format
580  else
581  {
582  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
583  noiseInterferenceW,
584  txVector.GetChannelWidth ()),
585  current - plcpHsigHeaderStart,
586  mcsHeaderMode, txVector);
587  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
588  noiseInterferenceW,
589  txVector.GetChannelWidth ()),
590  plcpHsigHeaderStart - previous,
591  headerMode, txVector);
592  NS_LOG_DEBUG ("Case 4cii - previous in L-SIG and current in HT-SIG: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
593  }
594  }
595  //Case 4d: current with previous in L-SIG
596  else
597  {
598  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
599  noiseInterferenceW,
600  txVector.GetChannelWidth ()),
601  current - previous,
602  headerMode, txVector);
603  NS_LOG_DEBUG ("Case 4d - current with previous in L-SIG: mode=" << headerMode << ", psr=" << psr);
604  }
605  }
606  //Case 5: previous is in the preamble works for all cases
607  else
608  {
609  //Case 5a: current after payload start
610  if (current >= plcpPayloadStart)
611  {
612  //Case 5ai: legacy format (No HT-SIG or Training Symbols)
613  if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
614  {
615  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
616  noiseInterferenceW,
617  txVector.GetChannelWidth ()),
618  plcpPayloadStart - plcpHeaderStart,
619  headerMode, txVector);
620  NS_LOG_DEBUG ("Case 5a - previous is in the preamble and current is after payload start: mode=" << headerMode << ", psr=" << psr);
621  }
622  //Case 5aii: VHT or HE format
623  else if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
624  {
625  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
626  noiseInterferenceW,
627  txVector.GetChannelWidth ()),
628  plcpPayloadStart - plcpTrainingSymbolsStart,
629  mcsHeaderMode, txVector);
630  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
631  noiseInterferenceW,
632  txVector.GetChannelWidth ()),
633  plcpTrainingSymbolsStart - plcpHeaderStart,
634  headerMode, txVector);
635  NS_LOG_DEBUG ("Case 5aii - previous is in the preamble and current is after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
636  }
637  //Case 5aiii: HT formats
638  else
639  {
640  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
641  noiseInterferenceW,
642  txVector.GetChannelWidth ()),
643  plcpPayloadStart - plcpHsigHeaderStart,
644  mcsHeaderMode, txVector);
645  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
646  noiseInterferenceW,
647  txVector.GetChannelWidth ()),
648  plcpHsigHeaderStart - plcpHeaderStart, //HT GF: plcpHsigHeaderStart - plcpHeaderStart = 0
649  headerMode, txVector);
650  NS_LOG_DEBUG ("Case 5aiii - previous is in the preamble and current is after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
651  }
652  }
653  //Case 5b: current is in training or in SIG-B. Legacy will not come here since it went in previous if or if the previous if is not true this will be not true
654  else if (current >= plcpTrainingSymbolsStart)
655  {
656  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
657  //Case 5bi: VHT or HE format
658  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
659  {
660  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
661  noiseInterferenceW,
662  txVector.GetChannelWidth ()),
663  current - plcpTrainingSymbolsStart,
664  mcsHeaderMode, txVector);
665  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
666  noiseInterferenceW,
667  txVector.GetChannelWidth ()),
668  plcpTrainingSymbolsStart - plcpHeaderStart,
669  headerMode, txVector);
670  NS_LOG_DEBUG ("Case 5bi - previous is in the preamble and current in training or in SIG-B: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
671  }
672  //Case 5bii: HT mixed format
673  else
674  {
675  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
676  noiseInterferenceW,
677  txVector.GetChannelWidth ()),
678  current - plcpHsigHeaderStart,
679  mcsHeaderMode, txVector);
680  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
681  noiseInterferenceW,
682  txVector.GetChannelWidth ()),
683  plcpHsigHeaderStart - plcpHeaderStart,
684  headerMode, txVector);
685  NS_LOG_DEBUG ("Case 5bii - previous is in the preamble and current in HT training: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
686  }
687  }
688  //Case 5c: current in HT-SIG or in SIG-A. Legacy will not come here since it went in previous if or if the previous if is not true this will be not true
689  else if (current >= plcpHsigHeaderStart)
690  {
691  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
692  //Case 5ci: VHT or HE format
693  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
694  {
695  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
696  noiseInterferenceW,
697  txVector.GetChannelWidth ()),
698  current - plcpHeaderStart,
699  headerMode, txVector);
700  NS_LOG_DEBUG ("Case 5ci - previous is in preamble and current in SIG-A: mode=" << headerMode << ", psr=" << psr);
701  }
702  //Case 5cii: HT formats
703  else
704  {
705  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
706  noiseInterferenceW,
707  txVector.GetChannelWidth ()),
708  current - plcpHsigHeaderStart,
709  mcsHeaderMode, txVector);
710  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
711  noiseInterferenceW,
712  txVector.GetChannelWidth ()),
713  plcpHsigHeaderStart - plcpHeaderStart, //HT-GF: plcpHsigHeaderStart - plcpHeaderStart = 0
714  headerMode, txVector);
715  NS_LOG_DEBUG ("Case 5cii - previous in preamble and current in HT-SIG: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
716  }
717  }
718  //Case 5d: current is in L-SIG. HT-GF will not come here
719  else if (current >= plcpHeaderStart)
720  {
721  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
722  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
723  noiseInterferenceW,
724  txVector.GetChannelWidth ()),
725  current - plcpHeaderStart,
726  headerMode, txVector);
727  NS_LOG_DEBUG ("Case 5d - previous is in the preamble and current is in L-SIG: mode=" << headerMode << ", psr=" << psr);
728  }
729  }
730 
731  noiseInterferenceW = j->second.GetPower () - powerW;
732  previous = j->first;
733  }
734 
735  double per = 1 - psr;
736  return per;
737 }
738 
740 InterferenceHelper::CalculatePlcpPayloadSnrPer (Ptr<Event> event) const
741 {
742  NiChanges ni;
743  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
744  double snr = CalculateSnr (event->GetRxPowerW (),
745  noiseInterferenceW,
746  event->GetTxVector ().GetChannelWidth ());
747 
748  /* calculate the SNIR at the start of the packet and accumulate
749  * all SNIR changes in the snir vector.
750  */
751  double per = CalculatePlcpPayloadPer (event, &ni);
752 
753  struct SnrPer snrPer;
754  snrPer.snr = snr;
755  snrPer.per = per;
756  return snrPer;
757 }
758 
760 InterferenceHelper::CalculatePlcpHeaderSnrPer (Ptr<Event> event) const
761 {
762  NiChanges ni;
763  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
764  double snr = CalculateSnr (event->GetRxPowerW (),
765  noiseInterferenceW,
766  event->GetTxVector ().GetChannelWidth ());
767 
768  /* calculate the SNIR at the start of the plcp header and accumulate
769  * all SNIR changes in the snir vector.
770  */
771  double per = CalculatePlcpHeaderPer (event, &ni);
772 
773  struct SnrPer snrPer;
774  snrPer.snr = snr;
775  snrPer.per = per;
776  return snrPer;
777 }
778 
779 void
781 {
782  m_niChanges.clear ();
783  // Always have a zero power noise event in the list
784  AddNiChangeEvent (Time (0), NiChange (0.0, 0));
785  m_rxing = false;
786  m_firstPower = 0;
787 }
788 
789 InterferenceHelper::NiChanges::const_iterator
791 {
792  return m_niChanges.upper_bound (moment);
793 }
794 
795 InterferenceHelper::NiChanges::const_iterator
797 {
798  auto it = GetNextPosition (moment);
799  // This is safe since there is always an NiChange at time 0,
800  // before moment.
801  --it;
802  return it;
803 }
804 
805 InterferenceHelper::NiChanges::iterator
807 {
808  return m_niChanges.insert (GetNextPosition (moment), std::make_pair (moment, change));
809 }
810 
811 void
813 {
814  NS_LOG_FUNCTION (this);
815  m_rxing = true;
816 }
817 
818 void
820 {
821  NS_LOG_FUNCTION (this);
822  m_rxing = false;
823  //Update m_firstPower for frame capture
824  auto it = m_niChanges.find (Simulator::Now ());
825  it--;
826  m_firstPower = it->second.GetPower ();
827 }
828 
829 } //namespace ns3
double GetRxPowerW(void) const
Return the receive power (w).
void AddPower(double power)
Add a given amount of power.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
void AddForeignSignal(Time duration, double rxPower)
Add a non-Wifi signal to interference helper.
Signal event for a packet.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
NiChanges::iterator AddNiChangeEvent(Time moment, NiChange change)
Add NiChange to the list at the appropriate position and return the iterator of the new event...
Control the scheduling of simulation events.
Definition: simulator.h:68
void SetNumberOfReceiveAntennas(uint8_t rx)
Set the number of RX antennas in the receiver corresponding to this interference helper.
double m_rxPowerW
receive power in watts
Definition: second.py:1
Ptr< ErrorRateModel > GetErrorRateModel(void) const
Return the error rate model.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
Time GetEndTime(void) const
Return the end time of the signal.
double CalculatePlcpPayloadPer(Ptr< const Event > event, NiChanges *ni) const
Calculate the error rate of the given plcp payload.
handles interference calculations
static Time GetPlcpHtSigHeaderDuration(WifiPreamble preamble)
Definition: wifi-phy.cc:1705
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:355
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
void SetErrorRateModel(const Ptr< ErrorRateModel > rate)
Set the error rate model for this interference helper.
Time GetStartTime(void) const
Return the start time of the signal.
Ptr< Event > GetEvent(void) const
Return the event causes the corresponding NI change.
VHT PHY (Clause 22)
Definition: wifi-mode.h:60
Ptr< ErrorRateModel > m_errorRateModel
error rate model
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
static Time GetPlcpSigA1Duration(WifiPreamble preamble)
Definition: wifi-phy.cc:1720
Event(Ptr< const Packet > packet, WifiTxVector txVector, Time duration, double rxPower)
Create an Event with the given parameters.
WifiMode GetPayloadMode(void) const
Return the Wi-Fi mode used for the payload.
double CalculateChunkSuccessRate(double snir, Time duration, WifiMode mode, WifiTxVector txVector) const
Calculate the success rate of the chunk given the SINR, duration, and Wi-Fi mode. ...
WifiPreamble GetPreambleType(void) const
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
Definition: wifi-preamble.h:30
static Time GetPlcpSigA2Duration(WifiPreamble preamble)
Definition: wifi-phy.cc:1735
double CalculateSnr(double signal, double noiseInterference, uint16_t channelWidth) const
Calculate SNR (linear ratio) from the given signal power and noise+interference power.
bool IsZero(void) const
Definition: nstime.h:288
static Time GetPlcpPreambleDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:1882
Time GetEnergyDuration(double energyW) const
Ptr< Event > Add(Ptr< const Packet > packet, WifiTxVector txVector, Time duration, double rxPower)
Add the packet-related signal to interference helper.
static Time GetPlcpSigBDuration(WifiPreamble preamble)
Definition: wifi-phy.cc:1750
NiChanges m_niChanges
Experimental: needed for energy duration calculation.
WifiMode GetMode(void) const
HT PHY (Clause 20)
Definition: wifi-mode.h:58
Ptr< const Packet > GetPacket(void) const
Return the packet.
uint8_t GetNTx(void) const
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:500
double CalculateNoiseInterferenceW(Ptr< Event > event, NiChanges *ni) const
Calculate noise and interference power in W.
WifiTxVector GetTxVector(void) const
Return the TXVECTOR of the packet.
double m_noiseFigure
noise figure (linear)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void NotifyRxStart()
Notify that RX has started.
Noise and Interference (thus Ni) event.
void EraseEvents(void)
Erase all events.
uint8_t m_numRxAntennas
the number of RX antennas in the corresponding receiver
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
void NotifyRxEnd()
Notify that RX has ended.
void SetNoiseFigure(double value)
Set the noise figure.
double m_firstPower
first power
NiChange(double power, Ptr< Event > event)
Create a NiChange at the given time and the amount of NI change.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:270
static WifiMode GetVhtPlcpHeaderMode()
Definition: wifi-phy.cc:1646
uint64_t GetPhyRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:109
WifiTxVector m_txVector
TXVECTOR.
static WifiMode GetHePlcpHeaderMode()
Definition: wifi-phy.cc:1652
void AppendEvent(Ptr< Event > event)
Append the given Event.
Time m_endTime
end time
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1030
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:365
NiChanges::const_iterator GetNextPosition(Time moment) const
Returns an iterator to the first nichange that is later than moment.
double GetPower(void) const
Return the power.
uint16_t GetChannelWidth(void) const
double CalculatePlcpHeaderPer(Ptr< const Event > event, NiChanges *ni) const
Calculate the error rate of the plcp header.
Ptr< const Packet > m_packet
packet
static WifiMode GetPlcpHeaderMode(WifiTxVector txVector)
Definition: wifi-phy.cc:1767
Definition: first.py:1
static Time GetPlcpTrainingSymbolDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:1658
static Time GetPlcpHeaderDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:1813
HE PHY (Clause 26)
Definition: wifi-mode.h:62
static WifiMode GetHtPlcpHeaderMode()
Definition: wifi-phy.cc:1640
NiChanges::const_iterator GetPreviousPosition(Time moment) const
Returns an iterator to the first nichange that is later than moment.
uint8_t GetNss(void) const
std::multimap< Time, NiChange > NiChanges
typedef for a multimap of NiChanges
bool m_rxing
flag whether it is in receiving state
Time m_startTime
start time