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 "error-rate-model.h"
25 #include "ns3/simulator.h"
26 #include "ns3/log.h"
27 #include <algorithm>
28 
29 namespace ns3 {
30 
31 NS_LOG_COMPONENT_DEFINE ("InterferenceHelper");
32 
33 /****************************************************************
34  * Phy event class
35  ****************************************************************/
36 
38  enum WifiPreamble preamble,
39  Time duration, double rxPower)
40  : m_size (size),
41  m_txVector (txVector),
42  m_preamble (preamble),
43  m_startTime (Simulator::Now ()),
44  m_endTime (m_startTime + duration),
45  m_rxPowerW (rxPower)
46 {
47 }
48 
50 {
51 }
52 
53 Time
55 {
56  return m_endTime - m_startTime;
57 }
58 
59 Time
61 {
62  return m_startTime;
63 }
64 
65 Time
67 {
68  return m_endTime;
69 }
70 
71 double
73 {
74  return m_rxPowerW;
75 }
76 
77 uint32_t
79 {
80  return m_size;
81 }
82 
85 {
86  return m_txVector;
87 }
88 
91 {
92  return m_txVector.GetMode ();
93 }
94 
95 enum WifiPreamble
97 {
98  return m_preamble;
99 }
100 
101 
102 /****************************************************************
103  * Class which records SNIR change events for a
104  * short period of time.
105  ****************************************************************/
106 
108  : m_time (time),
109  m_delta (delta)
110 {
111 }
112 
113 Time
115 {
116  return m_time;
117 }
118 
119 double
121 {
122  return m_delta;
123 }
124 
125 bool
127 {
128  return (m_time < o.m_time);
129 }
130 
131 
132 /****************************************************************
133  * The actual InterferenceHelper
134  ****************************************************************/
135 
137  : m_errorRateModel (0),
138  m_firstPower (0.0),
139  m_rxing (false)
140 {
141 }
142 
144 {
145  EraseEvents ();
146  m_errorRateModel = 0;
147 }
148 
150 InterferenceHelper::Add (uint32_t size, WifiTxVector txVector,
151  enum WifiPreamble preamble,
152  Time duration, double rxPowerW)
153 {
155 
156  event = Create<InterferenceHelper::Event> (size,
157  txVector,
158  preamble,
159  duration,
160  rxPowerW);
161  AppendEvent (event);
162  return event;
163 }
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 Time
192 {
193  Time now = Simulator::Now ();
194  double noiseInterferenceW = 0.0;
195  Time end = now;
196  noiseInterferenceW = m_firstPower;
197  for (NiChanges::const_iterator i = m_niChanges.begin (); i != m_niChanges.end (); i++)
198  {
199  noiseInterferenceW += i->GetDelta ();
200  end = i->GetTime ();
201  if (end < now)
202  {
203  continue;
204  }
205  if (noiseInterferenceW < energyW)
206  {
207  break;
208  }
209  }
210  return end > now ? end - now : MicroSeconds (0);
211 }
212 
213 void
215 {
216  Time now = Simulator::Now ();
217  if (!m_rxing)
218  {
219  NiChanges::iterator nowIterator = GetPosition (now);
220  for (NiChanges::iterator i = m_niChanges.begin (); i != nowIterator; i++)
221  {
222  m_firstPower += i->GetDelta ();
223  }
224  m_niChanges.erase (m_niChanges.begin (), nowIterator);
225  m_niChanges.insert (m_niChanges.begin (), NiChange (event->GetStartTime (), event->GetRxPowerW ()));
226  }
227  else
228  {
229  AddNiChangeEvent (NiChange (event->GetStartTime (), event->GetRxPowerW ()));
230  }
231  AddNiChangeEvent (NiChange (event->GetEndTime (), -event->GetRxPowerW ()));
232 
233 }
234 
235 
236 double
237 InterferenceHelper::CalculateSnr (double signal, double noiseInterference, uint32_t channelWidth) const
238 {
239  //thermal noise at 290K in J/s = W
240  static const double BOLTZMANN = 1.3803e-23;
241  //Nt is the power of thermal noise in W
242  double Nt = BOLTZMANN * 290.0 * channelWidth * 1000000;
243  //receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
244  double noiseFloor = m_noiseFigure * Nt;
245  double noise = noiseFloor + noiseInterference;
246  double snr = signal / noise; //linear scale
247  NS_LOG_DEBUG ("bandwidth(MHz)=" << channelWidth << ", signal(W)= " << signal << ", noise(W)=" << noiseFloor << ", interference(W)=" << noiseInterference << ", snr(linear)=" << snr);
248  return snr;
249 }
250 
251 double
253 {
254  double noiseInterference = m_firstPower;
255  NS_ASSERT (m_rxing);
256  for (NiChanges::const_iterator i = m_niChanges.begin () + 1; i != m_niChanges.end (); i++)
257  {
258  if ((event->GetEndTime () == i->GetTime ()) && event->GetRxPowerW () == -i->GetDelta ())
259  {
260  break;
261  }
262  ni->push_back (*i);
263  }
264  ni->insert (ni->begin (), NiChange (event->GetStartTime (), noiseInterference));
265  ni->push_back (NiChange (event->GetEndTime (), 0));
266  return noiseInterference;
267 }
268 
269 double
270 InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, WifiTxVector txVector) const
271 {
272  if (duration == NanoSeconds (0))
273  {
274  return 1.0;
275  }
276  uint32_t rate = mode.GetPhyRate (txVector.GetChannelWidth (), txVector.IsShortGuardInterval (), 1);
277  uint64_t nbits = (uint64_t)(rate * duration.GetSeconds ());
278  double csr = m_errorRateModel->GetChunkSuccessRate (mode, txVector, snir, (uint32_t)nbits);
279  return csr;
280 }
281 
282 double
284 {
285  NS_LOG_FUNCTION (this);
286  double psr = 1.0; /* Packet Success Rate */
287  NiChanges::iterator j = ni->begin ();
288  Time previous = (*j).GetTime ();
289  WifiMode payloadMode = event->GetPayloadMode ();
290  WifiPreamble preamble = event->GetPreambleType ();
291  Time plcpHeaderStart = (*j).GetTime () + WifiPhy::GetPlcpPreambleDuration (event->GetTxVector (), preamble); //packet start time + preamble
292  Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (event->GetTxVector (), preamble); //packet start time + preamble + L-SIG
293  Time plcpHtTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpVhtSigA1Duration (preamble) + WifiPhy::GetPlcpVhtSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or VHT-SIG-A (A1 + A2)
294  Time plcpPayloadStart = plcpHtTrainingSymbolsStart + WifiPhy::GetPlcpHtTrainingSymbolDuration (preamble, event->GetTxVector ()) + WifiPhy::GetPlcpVhtSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or VHT-SIG-A (A1 + A2) + (V)HT Training + VHT-SIG-B
295  double noiseInterferenceW = (*j).GetDelta ();
296  double powerW = event->GetRxPowerW ();
297  j++;
298  while (ni->end () != j)
299  {
300  Time current = (*j).GetTime ();
301  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
302  NS_ASSERT (current >= previous);
303  //Case 1: Both previous and current point to the payload
304  if (previous >= plcpPayloadStart)
305  {
306  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
307  noiseInterferenceW,
308  event->GetTxVector ().GetChannelWidth ()),
309  current - previous,
310  payloadMode, event->GetTxVector ());
311 
312  NS_LOG_DEBUG ("Both previous and current point to the payload: mode=" << payloadMode << ", psr=" << psr);
313  }
314  //Case 2: previous is before payload and current is in the payload
315  else if (current >= plcpPayloadStart)
316  {
317  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
318  noiseInterferenceW,
319  event->GetTxVector ().GetChannelWidth ()),
320  current - plcpPayloadStart,
321  payloadMode, event->GetTxVector ());
322  NS_LOG_DEBUG ("previous is before payload and current is in the payload: mode=" << payloadMode << ", psr=" << psr);
323  }
324 
325  noiseInterferenceW += (*j).GetDelta ();
326  previous = (*j).GetTime ();
327  j++;
328  }
329 
330  double per = 1 - psr;
331  return per;
332 }
333 
334 double
336 {
337  NS_LOG_FUNCTION (this);
338  double psr = 1.0; /* Packet Success Rate */
339  NiChanges::iterator j = ni->begin ();
340  Time previous = (*j).GetTime ();
341  WifiMode payloadMode = event->GetPayloadMode ();
342  WifiPreamble preamble = event->GetPreambleType ();
343  WifiMode htHeaderMode;
344  if (preamble == WIFI_PREAMBLE_HT_MF)
345  {
346  //mode for PLCP header fields sent with HT modulation
347  htHeaderMode = WifiPhy::GetHtPlcpHeaderMode (payloadMode);
348  }
349  else if (preamble == WIFI_PREAMBLE_VHT)
350  {
351  //mode for PLCP header fields sent with VHT modulation
352  htHeaderMode = WifiPhy::GetVhtPlcpHeaderMode (payloadMode);
353  }
354  WifiMode headerMode = WifiPhy::GetPlcpHeaderMode (payloadMode, preamble, event->GetTxVector ());
355  Time plcpHeaderStart = (*j).GetTime () + WifiPhy::GetPlcpPreambleDuration (event->GetTxVector (), preamble); //packet start time + preamble
356  Time plcpHsigHeaderStart = plcpHeaderStart + WifiPhy::GetPlcpHeaderDuration (event->GetTxVector (), preamble); //packet start time + preamble + L-SIG
357  Time plcpHtTrainingSymbolsStart = plcpHsigHeaderStart + WifiPhy::GetPlcpHtSigHeaderDuration (preamble) + WifiPhy::GetPlcpVhtSigA1Duration (preamble) + WifiPhy::GetPlcpVhtSigA2Duration (preamble); //packet start time + preamble + L-SIG + HT-SIG or VHT-SIG-A (A1 + A2)
358  Time plcpPayloadStart = plcpHtTrainingSymbolsStart + WifiPhy::GetPlcpHtTrainingSymbolDuration (preamble, event->GetTxVector ()) + WifiPhy::GetPlcpVhtSigBDuration (preamble); //packet start time + preamble + L-SIG + HT-SIG or VHT-SIG-A (A1 + A2) + (V)HT Training + VHT-SIG-B
359  double noiseInterferenceW = (*j).GetDelta ();
360  double powerW = event->GetRxPowerW ();
361  j++;
362  while (ni->end () != j)
363  {
364  Time current = (*j).GetTime ();
365  NS_LOG_DEBUG ("previous= " << previous << ", current=" << current);
366  NS_ASSERT (current >= previous);
367  //Case 1: previous and current after playload start: nothing to do
368  if (previous >= plcpPayloadStart)
369  {
370  psr *= 1;
371  NS_LOG_DEBUG ("Case 1 - previous and current after playload start: nothing to do");
372  }
373  //Case 2: previous is in (V)HT training or in VHT-SIG-B: Non (V)HT will not enter here since it didn't enter in the last two and they are all the same for non (V)HT
374  else if (previous >= plcpHtTrainingSymbolsStart)
375  {
376  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
377  //Case 2a: current after payload start
378  if (current >= plcpPayloadStart)
379  {
380  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
381  noiseInterferenceW,
382  event->GetTxVector ().GetChannelWidth ()),
383  plcpPayloadStart - previous,
384  htHeaderMode, event->GetTxVector ());
385 
386  NS_LOG_DEBUG ("Case 2a - previous is in (V)HT training or in VHT-SIG-B and current after payload start: mode=" << htHeaderMode << ", psr=" << psr);
387  }
388  //Case 2b: current is in (V)HT training or in VHT-SIG-B
389  else
390  {
391  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
392  noiseInterferenceW,
393  event->GetTxVector ().GetChannelWidth ()),
394  current - previous,
395  htHeaderMode, event->GetTxVector ());
396 
397  NS_LOG_DEBUG ("Case 2b - previous is in (V)HT training or in VHT-SIG-B and current is in (V)HT training or in VHT-SIG-B: mode=" << htHeaderMode << ", psr=" << psr);
398  }
399  }
400  //Case 3: previous is in HT-SIG or VHT-SIG-A: Non (V)HT will not enter here since it didn't enter in the last two and they are all the same for non (V)HT
401  else if (previous >= plcpHsigHeaderStart)
402  {
403  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
404  //Case 3a: current after payload start
405  if (current >= plcpPayloadStart)
406  {
407  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
408  noiseInterferenceW,
409  event->GetTxVector ().GetChannelWidth ()),
410  plcpPayloadStart - plcpHtTrainingSymbolsStart,
411  htHeaderMode, event->GetTxVector ());
412 
413  //Case 3ai: VHT format
414  if (preamble == WIFI_PREAMBLE_VHT)
415  {
416  //VHT-SIG-A is sent using legacy OFDM modulation
417  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
418  noiseInterferenceW,
419  event->GetTxVector ().GetChannelWidth ()),
420  plcpHtTrainingSymbolsStart - previous,
421  headerMode, event->GetTxVector ());
422 
423  NS_LOG_DEBUG ("Case 3ai - previous is in VHT-SIG-A and current after payload start: VHT mode=" << htHeaderMode << ", non-VHT mode=" << headerMode << ", psr=" << psr);
424  }
425  //Case 3aii: HT mixed format of HT greenfield
426  else
427  {
428  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
429  noiseInterferenceW,
430  event->GetTxVector ().GetChannelWidth ()),
431  plcpHtTrainingSymbolsStart - previous,
432  htHeaderMode, event->GetTxVector ());
433 
434  NS_LOG_DEBUG ("Case 3aii - previous is in HT-SIG and current after payload start: mode=" << htHeaderMode << ", psr=" << psr);
435  }
436  }
437  //Case 3b: current is in (V)HT training or in VHT-SIG-B
438  else if (current >= plcpHtTrainingSymbolsStart)
439  {
440  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
441  noiseInterferenceW,
442  event->GetTxVector ().GetChannelWidth ()),
443  current - plcpHtTrainingSymbolsStart,
444  htHeaderMode, event->GetTxVector ());
445 
446  //Case 3bi: VHT format
447  if (preamble == WIFI_PREAMBLE_VHT)
448  {
449  //VHT-SIG-A is sent using legacy OFDM modulation
450  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
451  noiseInterferenceW,
452  event->GetTxVector ().GetChannelWidth ()),
453  plcpHtTrainingSymbolsStart - previous,
454  headerMode, event->GetTxVector ());
455 
456  NS_LOG_DEBUG ("Case 3bi - previous is in VHT-SIG-A and current is in VHT training or in VHT-SIG-B: VHT mode=" << htHeaderMode << ", non-VHT mode=" << headerMode << ", psr=" << psr);
457  }
458  //Case 3bii: HT mixed format of HT greenfield
459  else
460  {
461  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
462  noiseInterferenceW,
463  event->GetTxVector ().GetChannelWidth ()),
464  plcpHtTrainingSymbolsStart - previous,
465  htHeaderMode, event->GetTxVector ());
466 
467  NS_LOG_DEBUG ("Case 3bii - previous is in HT-SIG and current is in HT training: mode=" << htHeaderMode << ", psr=" << psr);
468  }
469  }
470  //Case 3c: current with previous in HT-SIG or VHT-SIG-A
471  else
472  {
473  //Case 3bi: VHT format
474  if (preamble == WIFI_PREAMBLE_VHT)
475  {
476  //VHT-SIG-A is sent using legacy OFDM modulation
477  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
478  noiseInterferenceW,
479  event->GetTxVector ().GetChannelWidth ()),
480  current - previous,
481  headerMode, event->GetTxVector ());
482 
483  NS_LOG_DEBUG ("Case 3ci - previous with current in VHT-SIG-A: VHT mode=" << htHeaderMode << ", non-VHT mode=" << headerMode << ", psr=" << psr);
484  }
485  //Case 3bii: HT mixed format of HT greenfield
486  else
487  {
488  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
489  noiseInterferenceW,
490  event->GetTxVector ().GetChannelWidth ()),
491  current - previous,
492  htHeaderMode, event->GetTxVector ());
493 
494  NS_LOG_DEBUG ("Case 3cii - previous with current in HT-SIG: mode=" << htHeaderMode << ", psr=" << psr);
495  }
496  }
497  }
498  //Case 4: previous in L-SIG: HT GF will not reach here because it will execute the previous if and exit
499  else if (previous >= plcpHeaderStart)
500  {
501  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
502  //Case 4a: current after payload start
503  if (current >= plcpPayloadStart)
504  {
505  //Case 4ai: Non (V)HT format
506  if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
507  {
508  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
509  noiseInterferenceW,
510  event->GetTxVector ().GetChannelWidth ()),
511  plcpPayloadStart - previous,
512  headerMode, event->GetTxVector ());
513 
514  NS_LOG_DEBUG ("Case 4ai - previous in L-SIG and current after payload start: mode=" << headerMode << ", psr=" << psr);
515  }
516  //Case 4aii: VHT format
517  else if (preamble == WIFI_PREAMBLE_VHT)
518  {
519  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
520  noiseInterferenceW,
521  event->GetTxVector ().GetChannelWidth ()),
522  plcpPayloadStart - plcpHtTrainingSymbolsStart,
523  htHeaderMode, event->GetTxVector ());
524 
525  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
526  noiseInterferenceW,
527  event->GetTxVector ().GetChannelWidth ()),
528  plcpHtTrainingSymbolsStart - previous,
529  headerMode, event->GetTxVector ());
530 
531  NS_LOG_DEBUG ("Case 4aii - previous is in L-SIG and current after payload start: VHT mode=" << htHeaderMode << ", non-VHT mode=" << headerMode << ", psr=" << psr);
532  }
533  //Case 4aiii: HT mixed format
534  else
535  {
536  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
537  noiseInterferenceW,
538  event->GetTxVector ().GetChannelWidth ()),
539  plcpPayloadStart - plcpHsigHeaderStart,
540  htHeaderMode, event->GetTxVector ());
541 
542  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
543  noiseInterferenceW,
544  event->GetTxVector ().GetChannelWidth ()),
545  plcpHsigHeaderStart - previous,
546  headerMode, event->GetTxVector ());
547 
548  NS_LOG_DEBUG ("Case 4aiii - previous in L-SIG and current after payload start: HT mode=" << htHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
549  }
550  }
551  //Case 4b: current is in (V)HT training or in VHT-SIG-B. Non (V)HT will not come here since it went in previous if or if the previous if is not true this will be not true
552  else if (current >= plcpHtTrainingSymbolsStart)
553  {
554  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
555 
556  //Case 4bi: VHT format
557  if (preamble == WIFI_PREAMBLE_VHT)
558  {
559  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
560  noiseInterferenceW,
561  event->GetTxVector ().GetChannelWidth ()),
562  current - plcpHtTrainingSymbolsStart,
563  htHeaderMode, event->GetTxVector ());
564 
565  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
566  noiseInterferenceW,
567  event->GetTxVector ().GetChannelWidth ()),
568  plcpHtTrainingSymbolsStart - previous,
569  headerMode, event->GetTxVector ());
570 
571  NS_LOG_DEBUG ("Case 4bi - previous is in L-SIG and current in VHT training or in VHT-SIG-B: VHT mode=" << htHeaderMode << ", non-VHT mode=" << headerMode << ", psr=" << psr);
572  }
573  //Case 4bii: HT mixed format
574  else
575  {
576  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
577  noiseInterferenceW,
578  event->GetTxVector ().GetChannelWidth ()),
579  current - plcpHsigHeaderStart,
580  htHeaderMode, event->GetTxVector ());
581 
582  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
583  noiseInterferenceW,
584  event->GetTxVector ().GetChannelWidth ()),
585  plcpHsigHeaderStart - previous,
586  headerMode, event->GetTxVector ());
587 
588  NS_LOG_DEBUG ("Case 4bii - previous in L-SIG and current in HT training: HT mode=" << htHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
589  }
590  }
591  //Case 4c: current in HT-SIG or in VHT-SIG-A. Non (V)HT will not come here since it went in previous if or if the previous if is not true this will be not true
592  else if (current >= plcpHsigHeaderStart)
593  {
594  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
595 
596  //Case 4ci: VHT format
597  if (preamble == WIFI_PREAMBLE_VHT)
598  {
599  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
600  noiseInterferenceW,
601  event->GetTxVector ().GetChannelWidth ()),
602  current - previous,
603  headerMode, event->GetTxVector ());
604 
605  NS_LOG_DEBUG ("Case 4ci - previous is in L-SIG and current in VHT-SIG-A: mode=" << headerMode << ", psr=" << psr);
606  }
607  //Case 4cii: HT mixed format
608  else
609  {
610  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
611  noiseInterferenceW,
612  event->GetTxVector ().GetChannelWidth ()),
613  current - plcpHsigHeaderStart,
614  htHeaderMode, event->GetTxVector ());
615 
616  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
617  noiseInterferenceW,
618  event->GetTxVector ().GetChannelWidth ()),
619  plcpHsigHeaderStart - previous,
620  headerMode, event->GetTxVector ());
621 
622  NS_LOG_DEBUG ("Case 4cii - previous in L-SIG and current in HT-SIG: HT mode=" << htHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
623  }
624  }
625  //Case 4d: current with previous in L-SIG
626  else
627  {
628  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
629  noiseInterferenceW,
630  event->GetTxVector ().GetChannelWidth ()),
631  current - previous,
632  headerMode, event->GetTxVector ());
633 
634  NS_LOG_DEBUG ("Case 3c - current with previous in L-SIG: mode=" << headerMode << ", psr=" << psr);
635  }
636  }
637  //Case 5: previous is in the preamble works for all cases
638  else
639  {
640  //Case 5a: current after payload start
641  if (current >= plcpPayloadStart)
642  {
643  //Case 5ai: Non HT format (No HT-SIG or Training Symbols)
644  if (preamble == WIFI_PREAMBLE_LONG || preamble == WIFI_PREAMBLE_SHORT)
645  {
646  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
647  noiseInterferenceW,
648  event->GetTxVector ().GetChannelWidth ()),
649  plcpPayloadStart - plcpHeaderStart,
650  headerMode, event->GetTxVector ());
651 
652  NS_LOG_DEBUG ("Case 5a - previous is in the preamble and current is after payload start: mode=" << headerMode << ", psr=" << psr);
653  }
654  //Case 5aii: VHT format
655  else if (preamble == WIFI_PREAMBLE_VHT)
656  {
657  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
658  noiseInterferenceW,
659  event->GetTxVector ().GetChannelWidth ()),
660  plcpPayloadStart - plcpHtTrainingSymbolsStart,
661  htHeaderMode, event->GetTxVector ());
662 
663  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
664  noiseInterferenceW,
665  event->GetTxVector ().GetChannelWidth ()),
666  plcpHtTrainingSymbolsStart - plcpHeaderStart,
667  headerMode, event->GetTxVector ());
668 
669  NS_LOG_DEBUG ("Case 5aii - previous is in the preamble and current is after payload start: VHT mode=" << htHeaderMode << ", non-VHT mode=" << headerMode << ", psr=" << psr);
670  }
671 
672  //Case 5aiii: HT format
673  else
674  {
675  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
676  noiseInterferenceW,
677  event->GetTxVector ().GetChannelWidth ()),
678  plcpPayloadStart - plcpHsigHeaderStart,
679  htHeaderMode, event->GetTxVector ());
680 
681  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
682  noiseInterferenceW,
683  event->GetTxVector ().GetChannelWidth ()),
684  plcpHsigHeaderStart - plcpHeaderStart, //HT GF: plcpHsigHeaderStart - plcpHeaderStart = 0
685  headerMode, event->GetTxVector ());
686 
687  NS_LOG_DEBUG ("Case 4a - previous is in the preamble and current is after payload start: HT mode=" << htHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
688  }
689  }
690  //Case 5b: current is in (V)HT training or in VHT-SIG-B. Non (V)HT will not come here since it went in previous if or if the previous if is not true this will be not true
691  else if (current >= plcpHtTrainingSymbolsStart)
692  {
693  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
694 
695  //Case 5bi: VHT format
696  if (preamble == WIFI_PREAMBLE_VHT)
697  {
698  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
699  noiseInterferenceW,
700  event->GetTxVector ().GetChannelWidth ()),
701  current - plcpHtTrainingSymbolsStart,
702  htHeaderMode, event->GetTxVector ());
703 
704  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
705  noiseInterferenceW,
706  event->GetTxVector ().GetChannelWidth ()),
707  plcpHtTrainingSymbolsStart - plcpHeaderStart,
708  headerMode, event->GetTxVector ());
709 
710  NS_LOG_DEBUG ("Case 5bi - previous is in the preamble and current in VHT training or in VHT-SIG-B: VHT mode=" << htHeaderMode << ", non-VHT mode=" << headerMode << ", psr=" << psr);
711  }
712  //Case 45ii: HT mixed format
713  else
714  {
715  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
716  noiseInterferenceW,
717  event->GetTxVector ().GetChannelWidth ()),
718  current - plcpHsigHeaderStart,
719  htHeaderMode, event->GetTxVector ());
720 
721  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
722  noiseInterferenceW,
723  event->GetTxVector ().GetChannelWidth ()),
724  plcpHsigHeaderStart - plcpHeaderStart,
725  headerMode, event->GetTxVector ());
726 
727  NS_LOG_DEBUG ("Case 5bii - previous is in the preamble and current in HT training: HT mode=" << htHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
728  }
729  }
730  //Case 5c: current in HT-SIG or in VHT-SIG-A. Non (V)HT will not come here since it went in previous if or if the previous if is not true this will be not true
731  else if (current >= plcpHsigHeaderStart)
732  {
733  NS_ASSERT ((preamble != WIFI_PREAMBLE_LONG) && (preamble != WIFI_PREAMBLE_SHORT));
734 
735  //Case 5ci: VHT format
736  if (preamble == WIFI_PREAMBLE_VHT)
737  {
738  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
739  noiseInterferenceW,
740  event->GetTxVector ().GetChannelWidth ()),
741  current - plcpHeaderStart,
742  headerMode, event->GetTxVector ());
743 
744  NS_LOG_DEBUG ("Case 5ci - previous is in preamble and current in VHT-SIG-A: mode=" << headerMode << ", psr=" << psr);
745  }
746  //Case 5cii: HT mixed format
747  else
748  {
749  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
750  noiseInterferenceW,
751  event->GetTxVector ().GetChannelWidth ()),
752  current - plcpHsigHeaderStart,
753  htHeaderMode, event->GetTxVector ());
754 
755  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
756  noiseInterferenceW,
757  event->GetTxVector ().GetChannelWidth ()),
758  plcpHsigHeaderStart - plcpHeaderStart, //HT GF: plcpHsigHeaderStart - plcpHeaderStart = 0
759  headerMode, event->GetTxVector ());
760 
761  NS_LOG_DEBUG ("Case 5cii - previous in preamble and current in HT-SIG: HT mode=" << htHeaderMode << ", non-HT mode=" << headerMode << ", psr=" << psr);
762  }
763  }
764  //Case 5d: current is in L-SIG. HT GF will not come here
765  else if (current >= plcpHeaderStart)
766  {
767  NS_ASSERT (preamble != WIFI_PREAMBLE_HT_GF);
768 
769  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
770  noiseInterferenceW,
771  event->GetTxVector ().GetChannelWidth ()),
772  current - plcpHeaderStart,
773  headerMode, event->GetTxVector ());
774 
775  NS_LOG_DEBUG ("Case 5d - previous is in the preamble and current is in L-SIG: mode=" << headerMode << ", psr=" << psr);
776  }
777  }
778 
779  noiseInterferenceW += (*j).GetDelta ();
780  previous = (*j).GetTime ();
781  j++;
782  }
783 
784  double per = 1 - psr;
785  return per;
786 }
787 
789 InterferenceHelper::CalculatePlcpPayloadSnrPer (Ptr<InterferenceHelper::Event> event)
790 {
791  NiChanges ni;
792  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
793  double snr = CalculateSnr (event->GetRxPowerW (),
794  noiseInterferenceW,
795  event->GetTxVector ().GetChannelWidth ());
796 
797  /* calculate the SNIR at the start of the packet and accumulate
798  * all SNIR changes in the snir vector.
799  */
800  double per = CalculatePlcpPayloadPer (event, &ni);
801 
802  struct SnrPer snrPer;
803  snrPer.snr = snr;
804  snrPer.per = per;
805  return snrPer;
806 }
807 
809 InterferenceHelper::CalculatePlcpHeaderSnrPer (Ptr<InterferenceHelper::Event> event)
810 {
811  NiChanges ni;
812  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
813  double snr = CalculateSnr (event->GetRxPowerW (),
814  noiseInterferenceW,
815  event->GetTxVector ().GetChannelWidth ());
816 
817  /* calculate the SNIR at the start of the plcp header and accumulate
818  * all SNIR changes in the snir vector.
819  */
820  double per = CalculatePlcpHeaderPer (event, &ni);
821 
822  struct SnrPer snrPer;
823  snrPer.snr = snr;
824  snrPer.per = per;
825  return snrPer;
826 }
827 
828 void
830 {
831  m_niChanges.clear ();
832  m_rxing = false;
833  m_firstPower = 0.0;
834 }
835 
836 InterferenceHelper::NiChanges::iterator
838 {
839  return std::upper_bound (m_niChanges.begin (), m_niChanges.end (), NiChange (moment, 0));
840 }
841 
842 void
844 {
845  m_niChanges.insert (GetPosition (change.GetTime ()), change);
846 }
847 
848 void
850 {
851  NS_LOG_FUNCTION (this);
852  m_rxing = true;
853 }
854 
855 void
857 {
858  NS_LOG_FUNCTION (this);
859  m_rxing = false;
860 }
861 
862 } //namespace ns3
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
A struct for both SNR and PER.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#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:70
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
static WifiMode GetHtPlcpHeaderMode(WifiMode payloadMode)
Definition: wifi-phy.cc:122
static Time GetPlcpHtSigHeaderDuration(WifiPreamble preamble)
Definition: wifi-phy.cc:180
#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
Time GetEnergyDuration(double energyW)
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
bool IsShortGuardInterval(void) const
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
NiChanges::iterator GetPosition(Time moment)
Returns an iterator to the first nichange, which is later than moment.
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
uint32_t GetSize(void) const
Return the size of the packet (bytes).
static WifiMode GetVhtPlcpHeaderMode(WifiMode payloadMode)
Definition: wifi-phy.cc:128
uint64_t GetPhyRate(uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
Definition: wifi-mode.cc:73
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
Definition: wifi-preamble.h:30
void SetErrorRateModel(Ptr< ErrorRateModel > rate)
Set the error rate model for this interference helper.
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.
WifiTxVector GetTxVector(void) const
Return the TXVECTOR of the packet.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:919
static WifiMode GetPlcpHeaderMode(WifiMode payloadMode, WifiPreamble preamble, WifiTxVector txVector)
Definition: wifi-phy.cc:237
NiChanges m_niChanges
Experimental: needed for energy duration calculation.
void AddNiChangeEvent(NiChange change)
Add NiChange to the list at the appropriate position.
uint32_t GetChannelWidth(void) const
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.
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.
Ptr< InterferenceHelper::Event > Add(uint32_t size, WifiTxVector txVector, enum WifiPreamble preamble, Time duration, double rxPower)
Add the packet-related signal to interference helper.
Event(uint32_t size, WifiTxVector txVector, enum WifiPreamble preamble, Time duration, double rxPower)
Create an Event with the given parameters.
double CalculatePlcpHeaderPer(Ptr< const Event > event, NiChanges *ni) const
Calculate the error rate of the plcp header.
double GetDelta(void) const
Return the power.
static Time GetPlcpVhtSigA1Duration(WifiPreamble preamble)
Definition: wifi-phy.cc:195
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
Time GetEndTime(void) const
Return the end time of the signal.
enum WifiPreamble GetPreambleType(void) const
Return the preamble type of the packet.
void NotifyRxEnd()
Notify that RX has ended.
NiChange(Time time, double delta)
Create a NiChange at the given time and the amount of NI change.
double CalculateSnr(double signal, double noiseInterference, uint32_t channelWidth) const
Calculate SNR (linear ratio) from the given signal power and noise+interference power.
Time GetDuration(void) const
Return the duration of the signal.
void SetNoiseFigure(double value)
Set the noise figure.
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:236
static Time GetPlcpHeaderDuration(WifiTxVector txVector, WifiPreamble preamble)
Definition: wifi-phy.cc:282
void AppendEvent(Ptr< Event > event)
Append the given Event.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:911
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:330
double GetNoiseFigure(void) const
Return the noise figure.
static Time GetPlcpHtTrainingSymbolDuration(WifiPreamble preamble, WifiTxVector txVector)
Definition: wifi-phy.cc:134
static Time GetPlcpVhtSigBDuration(WifiPreamble preamble)
Definition: wifi-phy.cc:223
static Time GetPlcpPreambleDuration(WifiTxVector txVector, WifiPreamble preamble)
Definition: wifi-phy.cc:346
static Time GetPlcpVhtSigA2Duration(WifiPreamble preamble)
Definition: wifi-phy.cc:209