A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
interference-helper.cc
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  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "interference-helper.h"
21 #include "wifi-phy.h"
22 #include "error-rate-model.h"
23 #include "ns3/simulator.h"
24 #include "ns3/log.h"
25 #include <algorithm>
26 
27 NS_LOG_COMPONENT_DEFINE ("InterferenceHelper");
28 
29 namespace ns3 {
30 
31 /****************************************************************
32  * Phy event class
33  ****************************************************************/
34 
35 InterferenceHelper::Event::Event (uint32_t size, WifiMode payloadMode,
36  enum WifiPreamble preamble,
37  Time duration, double rxPower)
38  : m_size (size),
39  m_payloadMode (payloadMode),
40  m_preamble (preamble),
41  m_startTime (Simulator::Now ()),
42  m_endTime (m_startTime + duration),
43  m_rxPowerW (rxPower)
44 {
45 }
46 InterferenceHelper::Event::~Event ()
47 {
48 }
49 
50 Time
51 InterferenceHelper::Event::GetDuration (void) const
52 {
53  return m_endTime - m_startTime;
54 }
55 Time
56 InterferenceHelper::Event::GetStartTime (void) const
57 {
58  return m_startTime;
59 }
60 Time
61 InterferenceHelper::Event::GetEndTime (void) const
62 {
63  return m_endTime;
64 }
65 double
66 InterferenceHelper::Event::GetRxPowerW (void) const
67 {
68  return m_rxPowerW;
69 }
70 uint32_t
71 InterferenceHelper::Event::GetSize (void) const
72 {
73  return m_size;
74 }
75 WifiMode
76 InterferenceHelper::Event::GetPayloadMode (void) const
77 {
78  return m_payloadMode;
79 }
80 enum WifiPreamble
81 InterferenceHelper::Event::GetPreambleType (void) const
82 {
83  return m_preamble;
84 }
85 
86 /****************************************************************
87  * Class which records SNIR change events for a
88  * short period of time.
89  ****************************************************************/
90 
91 InterferenceHelper::NiChange::NiChange (Time time, double delta)
92  : m_time (time),
93  m_delta (delta)
94 {
95 }
96 Time
97 InterferenceHelper::NiChange::GetTime (void) const
98 {
99  return m_time;
100 }
101 double
102 InterferenceHelper::NiChange::GetDelta (void) const
103 {
104  return m_delta;
105 }
106 bool
107 InterferenceHelper::NiChange::operator < (const InterferenceHelper::NiChange& o) const
108 {
109  return (m_time < o.m_time);
110 }
111 
112 /****************************************************************
113  * The actual InterferenceHelper
114  ****************************************************************/
115 
116 InterferenceHelper::InterferenceHelper ()
117  : m_errorRateModel (0),
118  m_firstPower (0.0),
119  m_rxing (false)
120 {
121 }
122 InterferenceHelper::~InterferenceHelper ()
123 {
124  EraseEvents ();
125  m_errorRateModel = 0;
126 }
127 
128 Ptr<InterferenceHelper::Event>
129 InterferenceHelper::Add (uint32_t size, WifiMode payloadMode,
130  enum WifiPreamble preamble,
131  Time duration, double rxPowerW)
132 {
133  Ptr<InterferenceHelper::Event> event;
134 
135  event = Create<InterferenceHelper::Event> (size,
136  payloadMode,
137  preamble,
138  duration,
139  rxPowerW);
140  AppendEvent (event);
141  return event;
142 }
143 
144 
145 void
146 InterferenceHelper::SetNoiseFigure (double value)
147 {
148  m_noiseFigure = value;
149 }
150 
151 double
152 InterferenceHelper::GetNoiseFigure (void) const
153 {
154  return m_noiseFigure;
155 }
156 
157 void
158 InterferenceHelper::SetErrorRateModel (Ptr<ErrorRateModel> rate)
159 {
160  m_errorRateModel = rate;
161 }
162 
163 Ptr<ErrorRateModel>
164 InterferenceHelper::GetErrorRateModel (void) const
165 {
166  return m_errorRateModel;
167 }
168 
169 Time
171 {
172  Time now = Simulator::Now ();
173  double noiseInterferenceW = 0.0;
174  Time end = now;
175  noiseInterferenceW = m_firstPower;
176  for (NiChanges::const_iterator i = m_niChanges.begin (); i != m_niChanges.end (); i++)
177  {
178  noiseInterferenceW += i->GetDelta ();
179  end = i->GetTime ();
180  if (end < now)
181  {
182  continue;
183  }
184  if (noiseInterferenceW < energyW)
185  {
186  break;
187  }
188  }
189  return end > now ? end - now : MicroSeconds (0);
190 }
191 
192 void
193 InterferenceHelper::AppendEvent (Ptr<InterferenceHelper::Event> event)
194 {
195  Time now = Simulator::Now ();
196  if (!m_rxing)
197  {
198  NiChanges::iterator nowIterator = GetPosition (now);
199  for (NiChanges::iterator i = m_niChanges.begin (); i != nowIterator; i++)
200  {
201  m_firstPower += i->GetDelta ();
202  }
203  m_niChanges.erase (m_niChanges.begin (), nowIterator);
204  m_niChanges.insert (m_niChanges.begin (), NiChange (event->GetStartTime (), event->GetRxPowerW ()));
205  }
206  else
207  {
208  AddNiChangeEvent (NiChange (event->GetStartTime (), event->GetRxPowerW ()));
209  }
210  AddNiChangeEvent (NiChange (event->GetEndTime (), -event->GetRxPowerW ()));
211 
212 }
213 
214 
215 double
216 InterferenceHelper::CalculateSnr (double signal, double noiseInterference, WifiMode mode) const
217 {
218  // thermal noise at 290K in J/s = W
219  static const double BOLTZMANN = 1.3803e-23;
220  // Nt is the power of thermal noise in W
221  double Nt = BOLTZMANN * 290.0 * mode.GetBandwidth ();
222  // receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
223  double noiseFloor = m_noiseFigure * Nt;
224  double noise = noiseFloor + noiseInterference;
225  double snr = signal / noise;
226  return snr;
227 }
228 
229 double
230 InterferenceHelper::CalculateNoiseInterferenceW (Ptr<InterferenceHelper::Event> event, NiChanges *ni) const
231 {
232  double noiseInterference = m_firstPower;
233  NS_ASSERT (m_rxing);
234  for (NiChanges::const_iterator i = m_niChanges.begin () + 1; i != m_niChanges.end (); i++)
235  {
236  if ((event->GetEndTime () == i->GetTime ()) && event->GetRxPowerW () == -i->GetDelta ())
237  {
238  break;
239  }
240  ni->push_back (*i);
241  }
242  ni->insert (ni->begin (), NiChange (event->GetStartTime (), noiseInterference));
243  ni->push_back (NiChange (event->GetEndTime (), 0));
244  return noiseInterference;
245 }
246 
247 double
248 InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode) const
249 {
250  if (duration == NanoSeconds (0))
251  {
252  return 1.0;
253  }
254  uint32_t rate = mode.GetPhyRate ();
255  uint64_t nbits = (uint64_t)(rate * duration.GetSeconds ());
256  double csr = m_errorRateModel->GetChunkSuccessRate (mode, snir, (uint32_t)nbits);
257  return csr;
258 }
259 
260 double
261 InterferenceHelper::CalculatePer (Ptr<const InterferenceHelper::Event> event, NiChanges *ni) const
262 {
263  double psr = 1.0; /* Packet Success Rate */
264  NiChanges::iterator j = ni->begin ();
265  Time previous = (*j).GetTime ();
266  WifiMode payloadMode = event->GetPayloadMode ();
267  WifiPreamble preamble = event->GetPreambleType ();
268  WifiMode headerMode = WifiPhy::GetPlcpHeaderMode (payloadMode, preamble);
269  Time plcpHeaderStart = (*j).GetTime () + MicroSeconds (WifiPhy::GetPlcpPreambleDurationMicroSeconds (payloadMode, preamble));
270  Time plcpPayloadStart = plcpHeaderStart + MicroSeconds (WifiPhy::GetPlcpHeaderDurationMicroSeconds (payloadMode, preamble));
271  double noiseInterferenceW = (*j).GetDelta ();
272  double powerW = event->GetRxPowerW ();
273 
274  j++;
275  while (ni->end () != j)
276  {
277  Time current = (*j).GetTime ();
278  NS_ASSERT (current >= previous);
279 
280  if (previous >= plcpPayloadStart)
281  {
282  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
283  noiseInterferenceW,
284  payloadMode),
285  current - previous,
286  payloadMode);
287  }
288  else if (previous >= plcpHeaderStart)
289  {
290  if (current >= plcpPayloadStart)
291  {
292  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
293  noiseInterferenceW,
294  headerMode),
295  plcpPayloadStart - previous,
296  headerMode);
297  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
298  noiseInterferenceW,
299  payloadMode),
300  current - plcpPayloadStart,
301  payloadMode);
302  }
303  else
304  {
305  NS_ASSERT (current >= plcpHeaderStart);
306  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
307  noiseInterferenceW,
308  headerMode),
309  current - previous,
310  headerMode);
311  }
312  }
313  else
314  {
315  if (current >= plcpPayloadStart)
316  {
317  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
318  noiseInterferenceW,
319  headerMode),
320  plcpPayloadStart - plcpHeaderStart,
321  headerMode);
322  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
323  noiseInterferenceW,
324  payloadMode),
325  current - plcpPayloadStart,
326  payloadMode);
327  }
328  else if (current >= plcpHeaderStart)
329  {
330  psr *= CalculateChunkSuccessRate (CalculateSnr (powerW,
331  noiseInterferenceW,
332  headerMode),
333  current - plcpHeaderStart,
334  headerMode);
335  }
336  }
337 
338  noiseInterferenceW += (*j).GetDelta ();
339  previous = (*j).GetTime ();
340  j++;
341  }
342 
343  double per = 1 - psr;
344  return per;
345 }
346 
347 
348 struct InterferenceHelper::SnrPer
349 InterferenceHelper::CalculateSnrPer (Ptr<InterferenceHelper::Event> event)
350 {
351  NiChanges ni;
352  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
353  double snr = CalculateSnr (event->GetRxPowerW (),
354  noiseInterferenceW,
355  event->GetPayloadMode ());
356 
357  /* calculate the SNIR at the start of the packet and accumulate
358  * all SNIR changes in the snir vector.
359  */
360  double per = CalculatePer (event, &ni);
361 
362  struct SnrPer snrPer;
363  snrPer.snr = snr;
364  snrPer.per = per;
365  return snrPer;
366 }
367 
368 void
369 InterferenceHelper::EraseEvents (void)
370 {
371  m_niChanges.clear ();
372  m_rxing = false;
373  m_firstPower = 0.0;
374 }
375 InterferenceHelper::NiChanges::iterator
377 {
378  return std::upper_bound (m_niChanges.begin (), m_niChanges.end (), NiChange (moment, 0));
379 
380 }
381 void
382 InterferenceHelper::AddNiChangeEvent (NiChange change)
383 {
384  m_niChanges.insert (GetPosition (change.GetTime ()), change);
385 }
386 void
387 InterferenceHelper::NotifyRxStart ()
388 {
389  m_rxing = true;
390 }
391 void
392 InterferenceHelper::NotifyRxEnd ()
393 {
394  m_rxing = false;
395 }
396 } // namespace ns3
Time NanoSeconds(uint64_t ns)
create ns3::Time instances in units of nanoseconds.
Definition: nstime.h:629
static uint32_t GetPlcpHeaderDurationMicroSeconds(WifiMode payloadMode, WifiPreamble preamble)
Definition: wifi-phy.cc:141
keep track of time unit.
Definition: nstime.h:149
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_ASSERT(condition)
Definition: assert.h:64
Time GetEnergyDuration(double energyW)
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
NiChanges::iterator GetPosition(Time moment)
Returns an iterator to the first nichange, which is later than moment.
WifiPreamble
Definition: wifi-preamble.h:29
NiChanges m_niChanges
Experimental: needed for energy duration calculation.
static WifiMode GetPlcpHeaderMode(WifiMode payloadMode, WifiPreamble preamble)
Definition: wifi-phy.cc:98
static Time Now(void)
Definition: simulator.cc:179
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:286
static uint32_t GetPlcpPreambleDurationMicroSeconds(WifiMode payloadMode, WifiPreamble preamble)
Definition: wifi-phy.cc:189
Time MicroSeconds(uint64_t us)
create ns3::Time instances in units of microseconds.
Definition: nstime.h:615