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