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_endTime - m_startTime;
59 }
60 
61 Time
63 {
64  return m_startTime;
65 }
66 
67 Time
69 {
70  return m_endTime;
71 }
72 
73 double
75 {
76  return m_rxPowerW;
77 }
78 
81 {
82  return m_txVector;
83 }
84 
87 {
88  return m_txVector.GetMode ();
89 }
90 
91 
92 /****************************************************************
93  * Class which records SNIR change events for a
94  * short period of time.
95  ****************************************************************/
96 
98  : m_time (time),
99  m_delta (delta),
100  m_event (event)
101 {
102 }
103 
104 Time
106 {
107  return m_time;
108 }
109 
110 double
112 {
113  return m_delta;
114 }
115 
118 {
119  return m_event;
120 }
121 
122 bool
124 {
125  return (m_time < o.m_time);
126 }
127 
128 
129 /****************************************************************
130  * The actual InterferenceHelper
131  ****************************************************************/
132 
134  : m_errorRateModel (0),
135  m_numRxAntennas (1),
136  m_firstPower (0.0),
137  m_rxing (false)
138 {
139 }
140 
142 {
143  EraseEvents ();
144  m_errorRateModel = 0;
145 }
146 
148 InterferenceHelper::Add (Ptr<const Packet> packet, WifiTxVector txVector, Time duration, double rxPowerW)
149 {
151  event = Create<InterferenceHelper::Event> (packet, txVector, duration, rxPowerW);
152  AppendEvent (event);
153  return event;
154 }
155 
156 void
157 InterferenceHelper::AddForeignSignal (Time duration, double rxPowerW)
158 {
159  // Parameters other than duration and rxPowerW are unused for this type
160  // of signal, so we provide dummy versions
161  WifiTxVector fakeTxVector;
162  Ptr<const Packet> packet (0);
163  Add (packet, fakeTxVector, duration, rxPowerW);
164 }
165 
166 void
168 {
169  m_noiseFigure = value;
170 }
171 
172 double
174 {
175  return m_noiseFigure;
176 }
177 
178 void
180 {
181  m_errorRateModel = rate;
182 }
183 
186 {
187  return m_errorRateModel;
188 }
189 
190 void
192 {
193  m_numRxAntennas = rx;
194 }
195 
196 Time
198 {
199  Time now = Simulator::Now ();
200  double noiseInterferenceW = 0.0;
201  Time end = now;
202  noiseInterferenceW = m_firstPower;
203  for (NiChanges::const_iterator i = m_niChanges.begin (); i != m_niChanges.end (); i++)
204  {
205  noiseInterferenceW += i->GetDelta ();
206  end = i->GetTime ();
207  if (end < now)
208  {
209  continue;
210  }
211  if (noiseInterferenceW < energyW)
212  {
213  break;
214  }
215  }
216  return end > now ? end - now : MicroSeconds (0);
217 }
218 
219 void
221 {
222  Time now = Simulator::Now ();
223  if (!m_rxing)
224  {
225  NiChanges::const_iterator nowIterator = GetPosition (now);
226  for (NiChanges::const_iterator i = m_niChanges.begin (); i != nowIterator; i++)
227  {
228  m_firstPower += i->GetDelta ();
229  }
230  m_niChanges.erase (m_niChanges.begin (), nowIterator);
231  m_niChanges.insert (m_niChanges.begin (), NiChange (event->GetStartTime (), event->GetRxPowerW (), event));
232  }
233  else
234  {
235  AddNiChangeEvent (NiChange (event->GetStartTime (), event->GetRxPowerW (), event));
236  }
237  AddNiChangeEvent (NiChange (event->GetEndTime (), -event->GetRxPowerW (), event));
238 
239 }
240 
241 
242 double
243 InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint8_t channelWidth) const
244 {
245  //thermal noise at 290K in J/s = W
246  static const double BOLTZMANN = 1.3803e-23;
247  //Nt is the power of thermal noise in W
248  double Nt = BOLTZMANN * 290.0 * channelWidth * 1000000;
249  //receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
250  double noiseFloor = m_noiseFigure * Nt;
251  double noise = noiseFloor + noiseInterference;
252  double snr = signal / noise; //linear scale
253  NS_LOG_DEBUG ("bandwidth(MHz)=" << (uint16_t)channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr(linear)=" << snr);
254  return snr;
255 }
256 
257 double
259 {
260  double noiseInterference = m_firstPower;
261  NiChanges::const_iterator eventIterator = m_niChanges.begin ();
262  while (eventIterator != m_niChanges.end ())
263  {
264  // Iterate the NI change list from the beginning to the end
265  // until find the position of the event in the NI change list
266  // The reason of using the event that causes the NI change to identify
267  // different NI changes is because in some special cases
268  // different NI changes happen at the same time with the same delta
269  // value. Therefore, it may be impossible to identify a NI change that belongs
270  // to which event based on just the NI time and NI delta value
271  if (eventIterator->GetEvent () != event)
272  {
273  // The NI changes which happen before the event should be considered
274  // as the interference. This considers the case that the receiving event
275  // arrives while another receiving event is going on. The SINR of
276  // the newly arrived event is calculated for checking the possibility of frame capture
277  noiseInterference += eventIterator->GetDelta ();
278  }
279  else
280  {
281  break;
282  }
283  ++eventIterator;
284  }
285 
286  for (NiChanges::const_iterator i = eventIterator + 1; i != m_niChanges.end (); ++i)
287  {
288  if (event->GetEndTime () == i->GetTime () && event == i->GetEvent ())
289  {
290  break;
291  }
292  ni->push_back (*i);
293  }
294  ni->insert (ni->begin (), NiChange (event->GetStartTime (), noiseInterference, event));
295  ni->push_back (NiChange (event->GetEndTime (), 0, event));
296  return noiseInterference;
297 }
298 
299 double
300 InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, WifiTxVector txVector) const
301 {
302  if (duration.IsZero ())
303  {
304  return 1.0;
305  }
306  uint64_t rate = mode.GetPhyRate (txVector);
307  uint64_t nbits = (uint64_t)(rate * duration.GetSeconds ());
309  {
310  nbits /= txVector.GetNss (); //divide effective number of bits by NSS to achieve same chunk error rate as SISO for AWGN
311  double gain = (txVector.GetNTx () * m_numRxAntennas); //compute gain offered by MIMO, SIMO or MISO compared to SISO for AWGN
312  NS_LOG_DEBUG ("TX=" << (uint16_t)txVector.GetNTx () << ", RX=" << (uint16_t)m_numRxAntennas << ", SNIR improvement=+" << 10.0 * std::log10 (gain) << "dB");
313  snir *= gain;
314  }
315  double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, (uint32_t)nbits);
316  return csr;
317 }
318 
319 double
321 {
322  NS_LOG_FUNCTION (this);
323  const WifiTxVector txVector = event->GetTxVector ();
324  double psr = 1.0; /* Packet Success Rate */
325  NiChanges::const_iterator j = ni->begin ();
326  Time previous = (*j).GetTime ();
327  WifiMode payloadMode = event->GetPayloadMode ();
328  WifiPreamble preamble = txVector.GetPreambleType ();
329  Time plcpHeaderStart = (*j).GetTime () + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble
330  Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (txVector); //packet start time + preamble + L-SIG
331  Time plcpTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpSigA1Duration (preamble) + WifiPhy::GetPlcpSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A
332  Time plcpPayloadStart = plcpTrainingSymbolsStart + WifiPhy::GetPlcpTrainingSymbolDuration (txVector) + WifiPhy::GetPlcpSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
333  double noiseInterferenceW = (*j).GetDelta ();
334  double powerW = event->GetRxPowerW ();
335  j++;
336  while (ni->end () != j)
337  {
338  Time current = (*j).GetTime ();
339  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
340  NS_ASSERT (current >= previous);
341  //Case 1: Both previous and current point to the payload
342  if (previous >= plcpPayloadStart)
343  {
344  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
345  noiseInterferenceW,
346  txVector.GetChannelWidth ()),
347  current - previous,
348  payloadMode, txVector);
349 
350  NS_LOG_DEBUG ("Both previous and current point to the payload: mode=" << payloadMode << ", psr=" << psr);
351  }
352  //Case 2: previous is before payload and current is in the payload
353  else if (current >= plcpPayloadStart)
354  {
355  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
356  noiseInterferenceW,
357  txVector.GetChannelWidth ()),
358  current - plcpPayloadStart,
359  payloadMode, txVector);
360  NS_LOG_DEBUG ("previous is before payload and current is in the payload: mode=" << payloadMode << ", psr=" << psr);
361  }
362 
363  noiseInterferenceW += (*j).GetDelta ();
364  previous = (*j).GetTime ();
365  j++;
366  }
367 
368  double per = 1 - psr;
369  return per;
370 }
371 
372 double
374 {
375  NS_LOG_FUNCTION (this);
376  const WifiTxVector txVector = event->GetTxVector ();
377  double psr = 1.0; /* Packet Success Rate */
378  NiChanges::const_iterator j = ni->begin ();
379  Time previous = (*j).GetTime ();
380  WifiPreamble preamble = txVector.GetPreambleType ();
381  WifiMode mcsHeaderMode;
382  if (preamble == WIFI_PREAMBLE_HT_MF || preamble == WIFI_PREAMBLE_HT_GF)
383  {
384  //mode for PLCP header fields sent with HT modulation
385  mcsHeaderMode = WifiPhy::GetHtPlcpHeaderMode ();
386  }
387  else if (preamble == WIFI_PREAMBLE_VHT)
388  {
389  //mode for PLCP header fields sent with VHT modulation
390  mcsHeaderMode = WifiPhy::GetVhtPlcpHeaderMode ();
391  }
392  else if (preamble == WIFI_PREAMBLE_HE_SU)
393  {
394  //mode for PLCP header fields sent with HE modulation
395  mcsHeaderMode = WifiPhy::GetHePlcpHeaderMode ();
396  }
397  WifiMode headerMode = WifiPhy::GetPlcpHeaderMode (txVector);
398  Time plcpHeaderStart = (*j).GetTime () + WifiPhy::GetPlcpPreambleDuration (txVector); //packet start time + preamble
399  Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (txVector); //packet start time + preamble + L-SIG
400  Time plcpTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpSigA1Duration (preamble) + WifiPhy::GetPlcpSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A
401  Time plcpPayloadStart = plcpTrainingSymbolsStart + WifiPhy::GetPlcpTrainingSymbolDuration (txVector) + WifiPhy::GetPlcpSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or SIG-A + Training + SIG-B
402  double noiseInterferenceW = (*j).GetDelta ();
403  double powerW = event->GetRxPowerW ();
404  j++;
405  while (ni->end () != j)
406  {
407  Time current = (*j).GetTime ();
408  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
409  NS_ASSERT (current >= previous);
410  //Case 1: previous and current after playload start: nothing to do
411  if (previous >= plcpPayloadStart)
412  {
413  psr *= 1;
414  NS_LOG_DEBUG ("Case 1 - previous and current after playload start: nothing to do");
415  }
416  //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
417  else if (previous >= plcpTrainingSymbolsStart)
418  {
419  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
420  //Case 2a: current after payload start
421  if (current >= plcpPayloadStart)
422  {
423  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
424  noiseInterferenceW,
425  txVector.GetChannelWidth ()),
426  plcpPayloadStart - previous,
427  mcsHeaderMode, txVector);
428 
429  NS_LOG_DEBUG ("Case 2a - previous is in training or in SIG-B and current after payload start: mode=" << mcsHeaderMode << ", psr=" << psr);
430  }
431  //Case 2b: current is in training or in SIG-B
432  else
433  {
434  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
435  noiseInterferenceW,
436  txVector.GetChannelWidth ()),
437  current - previous,
438  mcsHeaderMode, txVector);
439 
440  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);
441  }
442  }
443  //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
444  else if (previous >= plcpHsigHeaderStart)
445  {
446  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
447  //Case 3a: current after payload start
448  if (current >= plcpPayloadStart)
449  {
450  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
451  noiseInterferenceW,
452  txVector.GetChannelWidth ()),
453  plcpPayloadStart - plcpTrainingSymbolsStart,
454  mcsHeaderMode, txVector);
455 
456  //Case 3ai: VHT or HE format
457  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
458  {
459  //SIG-A is sent using legacy OFDM modulation
460  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
461  noiseInterferenceW,
462  txVector.GetChannelWidth ()),
463  plcpTrainingSymbolsStart - previous,
464  headerMode, txVector);
465 
466  NS_LOG_DEBUG ("Case 3ai - previous is in SIG-A and current after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
467  }
468  //Case 3aii: HT formats
469  else
470  {
471  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
472  noiseInterferenceW,
473  txVector.GetChannelWidth ()),
474  plcpTrainingSymbolsStart - previous,
475  mcsHeaderMode, txVector);
476 
477  NS_LOG_DEBUG ("Case 3aii - previous is in HT-SIG and current after payload start: mode=" << mcsHeaderMode << ", psr=" << psr);
478  }
479  }
480  //Case 3b: current is in training or in SIG-B
481  else if (current >= plcpTrainingSymbolsStart)
482  {
483  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
484  noiseInterferenceW,
485  txVector.GetChannelWidth ()),
486  current - plcpTrainingSymbolsStart,
487  mcsHeaderMode, txVector);
488 
489  //Case 3bi: VHT or HE format
490  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
491  {
492  //SIG-A is sent using legacy OFDM modulation
493  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
494  noiseInterferenceW,
495  txVector.GetChannelWidth ()),
496  plcpTrainingSymbolsStart - previous,
497  headerMode, txVector);
498 
499  NS_LOG_DEBUG ("Case 3bi - previous is in SIG-A and current is in training or in SIG-B: mode=" << headerMode << ", psr=" << psr);
500  }
501  //Case 3bii: HT formats
502  else
503  {
504  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
505  noiseInterferenceW,
506  txVector.GetChannelWidth ()),
507  plcpTrainingSymbolsStart - previous,
508  mcsHeaderMode, txVector);
509 
510  NS_LOG_DEBUG ("Case 3bii - previous is in HT-SIG and current is in HT training: mode=" << mcsHeaderMode << ", psr=" << psr);
511  }
512  }
513  //Case 3c: current with previous in HT-SIG or SIG-A
514  else
515  {
516  //Case 3bi: VHT or HE format
517  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
518  {
519  //SIG-A is sent using legacy OFDM modulation
520  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
521  noiseInterferenceW,
522  txVector.GetChannelWidth ()),
523  current - previous,
524  headerMode, txVector);
525 
526  NS_LOG_DEBUG ("Case 3ci - previous with current in SIG-A: mode=" << headerMode << ", psr=" << psr);
527  }
528  //Case 3bii: HT mixed format or HT greenfield
529  else
530  {
531  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
532  noiseInterferenceW,
533  txVector.GetChannelWidth ()),
534  current - previous,
535  mcsHeaderMode, txVector);
536 
537  NS_LOG_DEBUG ("Case 3cii - previous with current in HT-SIG: mode=" << mcsHeaderMode << ", psr=" << psr);
538  }
539  }
540  }
541  //Case 4: previous in L-SIG: HT GF will not reach here because it will execute the previous if and exit
542  else if (previous >= plcpHeaderStart)
543  {
544  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
545  //Case 4a: current after payload start
546  if (current >= plcpPayloadStart)
547  {
548  //Case 4ai: legacy format
549  if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
550  {
551  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
552  noiseInterferenceW,
553  txVector.GetChannelWidth ()),
554  plcpPayloadStart - previous,
555  headerMode, txVector);
556 
557  NS_LOG_DEBUG ("Case 4ai - previous in L-SIG and current after payload start: mode=" << headerMode << ", psr=" << psr);
558  }
559  //Case 4aii: VHT or HE format
560  else if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
561  {
562  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
563  noiseInterferenceW,
564  txVector.GetChannelWidth ()),
565  plcpPayloadStart - plcpTrainingSymbolsStart,
566  mcsHeaderMode, txVector);
567 
568  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
569  noiseInterferenceW,
570  txVector.GetChannelWidth ()),
571  plcpTrainingSymbolsStart - previous,
572  headerMode, txVector);
573 
574  NS_LOG_DEBUG ("Case 4aii - previous is in L-SIG and current after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
575  }
576  //Case 4aiii: HT mixed format
577  else
578  {
579  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
580  noiseInterferenceW,
581  txVector.GetChannelWidth ()),
582  plcpPayloadStart - plcpHsigHeaderStart,
583  mcsHeaderMode, txVector);
584 
585  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
586  noiseInterferenceW,
587  txVector.GetChannelWidth ()),
588  plcpHsigHeaderStart - previous,
589  headerMode, txVector);
590 
591  NS_LOG_DEBUG ("Case 4aiii - previous in L-SIG and current after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
592  }
593  }
594  //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
595  else if (current >= plcpTrainingSymbolsStart)
596  {
597  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
598 
599  //Case 4bi: VHT or HE format
600  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
601  {
602  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
603  noiseInterferenceW,
604  txVector.GetChannelWidth ()),
605  current - plcpTrainingSymbolsStart,
606  mcsHeaderMode, txVector);
607  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
608  noiseInterferenceW,
609  txVector.GetChannelWidth ()),
610  plcpTrainingSymbolsStart - previous,
611  headerMode, txVector);
612 
613  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);
614  }
615  //Case 4bii: HT mixed format
616  else
617  {
618  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
619  noiseInterferenceW,
620  txVector.GetChannelWidth ()),
621  current - plcpHsigHeaderStart,
622  mcsHeaderMode, txVector);
623 
624  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
625  noiseInterferenceW,
626  txVector.GetChannelWidth ()),
627  plcpHsigHeaderStart - previous,
628  headerMode, txVector);
629 
630  NS_LOG_DEBUG ("Case 4bii - previous in L-SIG and current in HT training: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
631  }
632  }
633  //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
634  else if (current >= plcpHsigHeaderStart)
635  {
636  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
637 
638  //Case 4ci: VHT format
639  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
640  {
641  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
642  noiseInterferenceW,
643  txVector.GetChannelWidth ()),
644  current - previous,
645  headerMode, txVector);
646 
647  NS_LOG_DEBUG ("Case 4ci - previous is in L-SIG and current in SIG-A: mode=" << headerMode << ", psr=" << psr);
648  }
649  //Case 4cii: HT mixed format
650  else
651  {
652  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
653  noiseInterferenceW,
654  txVector.GetChannelWidth ()),
655  current - plcpHsigHeaderStart,
656  mcsHeaderMode, txVector);
657 
658  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
659  noiseInterferenceW,
660  txVector.GetChannelWidth ()),
661  plcpHsigHeaderStart - previous,
662  headerMode, txVector);
663 
664  NS_LOG_DEBUG ("Case 4cii - previous in L-SIG and current in HT-SIG: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
665  }
666  }
667  //Case 4d: current with previous in L-SIG
668  else
669  {
670  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
671  noiseInterferenceW,
672  txVector.GetChannelWidth ()),
673  current - previous,
674  headerMode, txVector);
675 
676  NS_LOG_DEBUG ("Case 3c - current with previous in L-SIG: mode=" << headerMode << ", psr=" << psr);
677  }
678  }
679  //Case 5: previous is in the preamble works for all cases
680  else
681  {
682  //Case 5a: current after payload start
683  if (current >= plcpPayloadStart)
684  {
685  //Case 5ai: legacy format (No HT-SIG or Training Symbols)
686  if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
687  {
688  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
689  noiseInterferenceW,
690  txVector.GetChannelWidth ()),
691  plcpPayloadStart - plcpHeaderStart,
692  headerMode, txVector);
693 
694  NS_LOG_DEBUG ("Case 5a - previous is in the preamble and current is after payload start: mode=" << headerMode << ", psr=" << psr);
695  }
696  //Case 5aii: VHT or HE format
697  else if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
698  {
699  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
700  noiseInterferenceW,
701  txVector.GetChannelWidth ()),
702  plcpPayloadStart - plcpTrainingSymbolsStart,
703  mcsHeaderMode, txVector);
704 
705  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
706  noiseInterferenceW,
707  txVector.GetChannelWidth ()),
708  plcpTrainingSymbolsStart - plcpHeaderStart,
709  headerMode, txVector);
710 
711  NS_LOG_DEBUG ("Case 5aii - previous is in the preamble and current is after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
712  }
713 
714  //Case 5aiii: HT formats
715  else
716  {
717  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
718  noiseInterferenceW,
719  txVector.GetChannelWidth ()),
720  plcpPayloadStart - plcpHsigHeaderStart,
721  mcsHeaderMode, txVector);
722 
723  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
724  noiseInterferenceW,
725  txVector.GetChannelWidth ()),
726  plcpHsigHeaderStart - plcpHeaderStart, //HT GF: plcpHsigHeaderStart - plcpHeaderStart = 0
727  headerMode, txVector);
728 
729  NS_LOG_DEBUG ("Case 5aiii - previous is in the preamble and current is after payload start: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
730  }
731  }
732  //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
733  else if (current >= plcpTrainingSymbolsStart)
734  {
735  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
736 
737  //Case 5bi: VHT or HE format
738  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
739  {
740  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
741  noiseInterferenceW,
742  txVector.GetChannelWidth ()),
743  current - plcpTrainingSymbolsStart,
744  mcsHeaderMode, txVector);
745 
746  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
747  noiseInterferenceW,
748  txVector.GetChannelWidth ()),
749  plcpTrainingSymbolsStart - plcpHeaderStart,
750  headerMode, txVector);
751 
752  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);
753  }
754  //Case 5bii: HT mixed format
755  else
756  {
757  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
758  noiseInterferenceW,
759  txVector.GetChannelWidth ()),
760  current - plcpHsigHeaderStart,
761  mcsHeaderMode, txVector);
762 
763  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
764  noiseInterferenceW,
765  txVector.GetChannelWidth ()),
766  plcpHsigHeaderStart - plcpHeaderStart,
767  headerMode, txVector);
768 
769  NS_LOG_DEBUG ("Case 5bii - previous is in the preamble and current in HT training: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
770  }
771  }
772  //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
773  else if (current >= plcpHsigHeaderStart)
774  {
775  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
776 
777  //Case 5ci: VHT or HE format
778  if (preamble == WIFI_PREAMBLE_VHT || preamble == WIFI_PREAMBLE_HE_SU)
779  {
780  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
781  noiseInterferenceW,
782  txVector.GetChannelWidth ()),
783  current - plcpHeaderStart,
784  headerMode, txVector);
785 
786  NS_LOG_DEBUG ("Case 5ci - previous is in preamble and current in SIG-A: mode=" << headerMode << ", psr=" << psr);
787  }
788  //Case 5cii: HT formats
789  else
790  {
791  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
792  noiseInterferenceW,
793  txVector.GetChannelWidth ()),
794  current - plcpHsigHeaderStart,
795  mcsHeaderMode, txVector);
796 
797  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
798  noiseInterferenceW,
799  txVector.GetChannelWidth ()),
800  plcpHsigHeaderStart - plcpHeaderStart, //HT-GF: plcpHsigHeaderStart - plcpHeaderStart = 0
801  headerMode, txVector);
802 
803  NS_LOG_DEBUG ("Case 5cii - previous in preamble and current in HT-SIG: mcs mode=" << mcsHeaderMode << ", legacy mode=" << headerMode << ", psr=" << psr);
804  }
805  }
806  //Case 5d: current is in L-SIG. HT-GF will not come here
807  else if (current >= plcpHeaderStart)
808  {
809  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
810 
811  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
812  noiseInterferenceW,
813  txVector.GetChannelWidth ()),
814  current - plcpHeaderStart,
815  headerMode, txVector);
816 
817  NS_LOG_DEBUG ("Case 5d - previous is in the preamble and current is in L-SIG: mode=" << headerMode << ", psr=" << psr);
818  }
819  }
820 
821  noiseInterferenceW += (*j).GetDelta ();
822  previous = (*j).GetTime ();
823  j++;
824  }
825 
826  double per = 1 - psr;
827  return per;
828 }
829 
831 InterferenceHelper::CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> event)
832 {
833  NiChanges ni;
834  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
835  double snr = CalculateSnr (event->GetRxPowerW (),
836  noiseInterferenceW,
837  event->GetTxVector ().GetChannelWidth ());
838 
839  /* calculate the SNIR at the start of the packet and accumulate
840  * all SNIR changes in the snir vector.
841  */
842  double per = CalculatePlcpPayloadPer (event, &ni);
843 
844  struct SnrPer snrPer;
845  snrPer.snr = snr;
846  snrPer.per = per;
847  return snrPer;
848 }
849 
851 InterferenceHelper::CalculatePlcpHeaderSnrPer (Ptr<InterferenceHelper::Event> event)
852 {
853  NiChanges ni;
854  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
855  double snr = CalculateSnr (event->GetRxPowerW (),
856  noiseInterferenceW,
857  event->GetTxVector ().GetChannelWidth ());
858 
859  /* calculate the SNIR at the start of the plcp header and accumulate
860  * all SNIR changes in the snir vector.
861  */
862  double per = CalculatePlcpHeaderPer (event, &ni);
863 
864  struct SnrPer snrPer;
865  snrPer.snr = snr;
866  snrPer.per = per;
867  return snrPer;
868 }
869 
870 void
872 {
873  m_niChanges.clear ();
874  m_rxing = false;
875  m_firstPower = 0.0;
876 }
877 
878 InterferenceHelper::NiChanges::const_iterator
880 {
881  return std::upper_bound (m_niChanges.begin (), m_niChanges.end (), NiChange (moment, 0, NULL));
882 }
883 
884 void
886 {
887  m_niChanges.insert (GetPosition (change.GetTime ()), change);
888 }
889 
890 void
892 {
893  NS_LOG_FUNCTION (this);
894  m_rxing = true;
895 }
896 
897 void
899 {
900  NS_LOG_FUNCTION (this);
901  m_rxing = false;
902 }
903 
904 } //namespace ns3
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 "...
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.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
bool operator<(const NiChange &o) const
Compare the event time of two NiChange objects (a < o).
std::vector< NiChange > NiChanges
typedef for a vector of NiChanges
handles interference calculations
bool IsZero(void) const
Definition: nstime.h:274
static Time GetPlcpHtSigHeaderDuration(WifiPreamble preamble)
Definition: wifi-phy.cc:1733
#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
static Time GetPlcpSigA1Duration(WifiPreamble preamble)
Definition: wifi-phy.cc:1748
uint8_t GetChannelWidth(void) const
Ptr< const Packet > GetPacket(void) const
Return the packet.
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:341
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:1763
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.
NiChange(Time time, double delta, Ptr< InterferenceHelper::Event > event)
Create a NiChange at the given time and the amount of NI change.
static Time GetPlcpPreambleDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:1910
static Time GetPlcpSigBDuration(WifiPreamble preamble)
Definition: wifi-phy.cc:1778
NiChanges m_niChanges
Experimental: needed for energy duration calculation.
void AddNiChangeEvent(NiChange change)
Add NiChange to the list at the appropriate position.
HT PHY (Clause 20)
Definition: wifi-mode.h:58
Time GetTime(void) const
Return the event time.
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.
double GetDelta(void) const
Return the power.
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
Time GetDuration(void) const
Return the duration of the signal.
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:1674
NiChanges::const_iterator GetPosition(Time moment)
Returns a const iterator to the first nichange, which is later than moment.
uint8_t GetNTx(void) const
static WifiMode GetHePlcpHeaderMode()
Definition: wifi-phy.cc:1680
void AppendEvent(Ptr< Event > event)
Append the given Event.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1009
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:365
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:1795
static Time GetPlcpTrainingSymbolDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:1686
static Time GetPlcpHeaderDuration(WifiTxVector txVector)
Definition: wifi-phy.cc:1841
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:1668
bool m_rxing
flag whether it is in receiving state