A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
lte-spectrum-phy.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009, 2011 CTTC
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: Nicola Baldo <nbaldo@cttc.es>
19  * Giuseppe Piro <g.piro@poliba.it>
20  * Marco Miozzo <marco.miozzo@cttc.es> (add physical error model)
21  */
22 
23 
24 #include <ns3/object-factory.h>
25 #include <ns3/log.h>
26 #include <math.h>
27 #include <ns3/simulator.h>
28 #include <ns3/trace-source-accessor.h>
29 #include <ns3/antenna-model.h>
30 #include "lte-spectrum-phy.h"
32 #include "lte-net-device.h"
33 #include "lte-radio-bearer-tag.h"
35 #include "lte-phy-tag.h"
36 #include <ns3/lte-mi-error-model.h>
37 #include <ns3/lte-radio-bearer-tag.h>
38 #include <ns3/boolean.h>
39 #include <ns3/double.h>
40 
41 NS_LOG_COMPONENT_DEFINE ("LteSpectrumPhy");
42 
43 namespace ns3 {
44 
45 
47 {
48 }
49 
50 TbId_t::TbId_t (const uint16_t a, const uint8_t b)
51 : m_rnti (a),
52  m_layer (b)
53 {
54 }
55 
56 bool
57 operator == (const TbId_t &a, const TbId_t &b)
58 {
59  return ( (a.m_rnti == b.m_rnti) && (a.m_layer == b.m_layer) );
60 }
61 
62 bool
63 operator < (const TbId_t& a, const TbId_t& b)
64 {
65  return ( (a.m_rnti < b.m_rnti) || ( (a.m_rnti == b.m_rnti) && (a.m_layer < b.m_layer) ) );
66 }
67 
68 NS_OBJECT_ENSURE_REGISTERED (LteSpectrumPhy);
69 
71  : m_state (IDLE),
72  m_transmissionMode (0)
73 {
74  NS_LOG_FUNCTION (this);
75  m_random = CreateObject<UniformRandomVariable> ();
76  m_random->SetAttribute ("Min", DoubleValue (0.0));
77  m_random->SetAttribute ("Max", DoubleValue (1.0));
78  m_interference = CreateObject<LteInterference> ();
79  for (uint8_t i = 0; i < 7; i++)
80  {
81  m_txModeGain.push_back (1.0);
82  }
83 }
84 
85 
87 {
88  NS_LOG_FUNCTION (this);
89  m_expectedTbs.clear ();
90  m_txModeGain.clear ();
91 }
92 
94 {
95  NS_LOG_FUNCTION (this);
96  m_channel = 0;
97  m_mobility = 0;
98  m_device = 0;
100  m_interference = 0;
101  m_genericPhyTxEndCallback = MakeNullCallback< void, Ptr<const Packet> > ();
102  m_genericPhyRxEndErrorCallback = MakeNullCallback< void > ();
103  m_genericPhyRxEndOkCallback = MakeNullCallback< void, Ptr<Packet> > ();
105 }
106 
107 std::ostream& operator<< (std::ostream& os, LteSpectrumPhy::State s)
108 {
109  switch (s)
110  {
112  os << "IDLE";
113  break;
114  case LteSpectrumPhy::RX:
115  os << "RX";
116  break;
117  case LteSpectrumPhy::TX:
118  os << "TX";
119  break;
120  default:
121  os << "UNKNOWN";
122  break;
123  }
124  return os;
125 }
126 
127 
128 TypeId
130 {
131  static TypeId tid = TypeId ("ns3::LteSpectrumPhy")
133  .AddTraceSource ("TxStart",
134  "Trace fired when a new transmission is started",
136  .AddTraceSource ("TxEnd",
137  "Trace fired when a previosuly started transmission is finished",
139  .AddTraceSource ("RxStart",
140  "Trace fired when the start of a signal is detected",
142  .AddTraceSource ("RxEndOk",
143  "Trace fired when a previosuly started RX terminates successfully",
145  .AddTraceSource ("RxEndError",
146  "Trace fired when a previosuly started RX terminates with an error",
148  .AddAttribute ("PemEnabled",
149  "Activate/Deactivate the error model (by default is active).",
150  BooleanValue (true),
151  MakeBooleanAccessor (&LteSpectrumPhy::m_pemEnabled),
152  MakeBooleanChecker ())
153  ;
154  return tid;
155 }
156 
157 
158 
161 {
162  NS_LOG_FUNCTION (this);
163  return m_device;
164 }
165 
166 
169 {
170  NS_LOG_FUNCTION (this);
171  return m_mobility;
172 }
173 
174 
175 void
177 {
178  NS_LOG_FUNCTION (this << d);
179  m_device = d;
180 }
181 
182 
183 void
185 {
186  NS_LOG_FUNCTION (this << m);
187  m_mobility = m;
188 }
189 
190 
191 void
193 {
194  NS_LOG_FUNCTION (this << c);
195  m_channel = c;
196 }
197 
200 {
201  return m_rxSpectrumModel;
202 }
203 
204 
205 void
207 {
208  NS_LOG_FUNCTION (this << txPsd);
209  NS_ASSERT (txPsd);
210  m_txPsd = txPsd;
211 }
212 
213 
214 void
216 {
217  NS_LOG_FUNCTION (this << noisePsd);
218  NS_ASSERT (noisePsd);
219  m_rxSpectrumModel = noisePsd->GetSpectrumModel ();
221 }
222 
223 
224 
225 void
227 {
228  NS_LOG_FUNCTION (this);
230 }
231 
232 
233 void
235 {
236  NS_LOG_FUNCTION (this);
238 }
239 
240 
241 void
243 {
244  NS_LOG_FUNCTION (this);
246 }
247 
250 {
251  return m_antenna;
252 }
253 
254 void
256 {
257  NS_LOG_FUNCTION (this << a);
258  m_antenna = a;
259 }
260 
261 void
263 {
264  ChangeState (newState);
265 }
266 
267 
268 void
270 {
271  NS_LOG_LOGIC (this << " state: " << m_state << " -> " << newState);
272  m_state = newState;
273 }
274 
275 
276 bool
278 {
279  NS_LOG_FUNCTION (this << pb);
280  NS_LOG_LOGIC (this << " state: " << m_state);
281 
282  m_phyTxStartTrace (pb);
283 
284  switch (m_state)
285  {
286  case RX:
287  NS_FATAL_ERROR ("cannot TX while RX: according to FDD channel acces, the physical layer for transmission cannot be used for reception");
288  break;
289 
290  case TX:
291  NS_FATAL_ERROR ("cannot TX while already TX: the MAC should avoid this");
292  break;
293 
294  case IDLE:
295  {
296  /*
297  m_txPsd must be setted by the device, according to
298  (i) the available subchannel for transmission
299  (ii) the power transmission
300  */
301  NS_ASSERT (m_txPsd);
302  m_txPacketBurst = pb;
303 
304  // we need to convey some PHY meta information to the receiver
305  // to be used for simulation purposes (e.g., the CellId). This
306  // is done by adding an LtePhyTag to the first packet in the
307  // burst.
308  NS_ASSERT (pb->Begin () != pb->End ());
309  LtePhyTag tag (m_cellId);
310  Ptr<Packet> firstPacketInBurst = *(pb->Begin ());
311  firstPacketInBurst->AddPacketTag (tag);
312 
313  ChangeState (TX);
315  double tti = 0.001;
316  Ptr<LteSpectrumSignalParameters> txParams = Create<LteSpectrumSignalParameters> ();
317  txParams->duration = Seconds (tti);
318  txParams->txPhy = GetObject<SpectrumPhy> ();
319  txParams->txAntenna = m_antenna;
320  txParams->psd = m_txPsd;
321  txParams->packetBurst = pb;
322  m_channel->StartTx (txParams);
324  }
325  return false;
326  break;
327 
328  default:
329  NS_FATAL_ERROR ("uknown state");
330  return true;
331  break;
332  }
333 }
334 
335 
336 void
338 {
339  NS_LOG_FUNCTION (this);
340  NS_LOG_LOGIC (this << " state: " << m_state);
341 
342  NS_ASSERT (m_state == TX);
343 
345 
347  {
348  for (std::list<Ptr<Packet> >::const_iterator iter = m_txPacketBurst->Begin (); iter
349  != m_txPacketBurst->End (); ++iter)
350  {
351  Ptr<Packet> packet = (*iter)->Copy ();
352  m_genericPhyTxEndCallback (packet);
353  }
354  }
355 
356  m_txPacketBurst = 0;
357  ChangeState (IDLE);
358 }
359 
360 
361 void
363 {
364  NS_LOG_FUNCTION (this << spectrumRxParams);
365  NS_LOG_LOGIC (this << " state: " << m_state);
366 
367  // interference will happen regardless of the type of the signal (could be 3G, GSM, whatever)
368  Ptr <const SpectrumValue> rxPsd = spectrumRxParams->psd;
369  Time duration = spectrumRxParams->duration;
370 
371  m_interference->AddSignal (rxPsd, duration);
372 
373  // the device might start RX only if the signal is of a type
374  // understood by this device - in this case, an LTE signal.
375  Ptr<LteSpectrumSignalParameters> lteRxParams = DynamicCast<LteSpectrumSignalParameters> (spectrumRxParams);
376  if (lteRxParams != 0)
377  {
378  switch (m_state)
379  {
380  case TX:
381  NS_FATAL_ERROR ("cannot RX while TX: according to FDD channel access, the physical layer for transmission cannot be used for reception");
382  break;
383 
384  case IDLE:
385  case RX:
386  // the behavior is similar when
387  // we're IDLE or RX because we can receive more signals
388  // simultaneously (e.g., at the eNB).
389  {
390  // To check if we're synchronized to this signal, we check
391  // for the CellId which is reported in the LtePhyTag
392  NS_ASSERT (lteRxParams->packetBurst->Begin () != lteRxParams->packetBurst->End ());
393  LtePhyTag tag;
394  Ptr<Packet> firstPacketInBurst = *(lteRxParams->packetBurst->Begin ());
395  firstPacketInBurst->RemovePacketTag (tag);
396  if (tag.GetCellId () == m_cellId)
397  {
398  NS_LOG_LOGIC (this << " synchronized with this signal (cellId=" << tag.GetCellId () << ")");
399  if (m_rxPacketBurstList.empty ())
400  {
401  NS_ASSERT (m_state == IDLE);
402  // first transmission, i.e., we're IDLE and we
403  // start RX
405  m_firstRxDuration = duration;
406  NS_LOG_LOGIC (this << " scheduling EndRx with delay " << duration);
407  Simulator::Schedule (duration, &LteSpectrumPhy::EndRx, this);
408  }
409  else
410  {
411  NS_ASSERT (m_state == RX);
412  // sanity check: if there are multiple RX events, they
413  // should occur at the same time and have the same
414  // duration, otherwise the interference calculation
415  // won't be correct
417  && (m_firstRxDuration == duration));
418  }
419 
420  ChangeState (RX);
421  m_interference->StartRx (rxPsd);
422 
423  m_phyRxStartTrace (lteRxParams->packetBurst);
424 
425  m_rxPacketBurstList.push_back (lteRxParams->packetBurst);
426 
427  NS_LOG_LOGIC (this << " numSimultaneousRxEvents = " << m_rxPacketBurstList.size ());
428  }
429  else
430  {
431  NS_LOG_LOGIC (this << " not in sync with this signal (cellId="
432  << tag.GetCellId () << ", m_cellId=" << m_cellId << ")");
433  }
434  }
435  break;
436 
437  default:
438  NS_FATAL_ERROR ("unknown state");
439  break;
440  }
441 
442  NS_LOG_LOGIC (this << " state: " << m_state);
443  }
444 }
445 
446 void
448 {
449  NS_LOG_FUNCTION (this << sinr);
450  m_sinrPerceived = sinr;
451 }
452 
453 
454 void
455 LteSpectrumPhy::AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std::vector<int> map, uint8_t layer)
456 {
457  NS_LOG_LOGIC (this << " rnti: " << rnti << " size " << size << " mcs " << (uint16_t)mcs << " layer " << (uint8_t)layer);
458  TbId_t tbId;
459  tbId.m_rnti = rnti;
460  tbId.m_layer = layer;
461  expectedTbs_t::iterator it;
462  it = m_expectedTbs.find (tbId);
463  if (it != m_expectedTbs.end ())
464  {
465  // migth be a TB of an unreceived packet (due to high progpalosses)
466  m_expectedTbs.erase (it);
467  }
468  // insert new entry
469  tbInfo_t tbInfo = {size, mcs, map, false};
470  m_expectedTbs.insert (std::pair<TbId_t, tbInfo_t> (tbId,tbInfo ));
471 }
472 
473 
474 void
476 {
477  NS_LOG_FUNCTION (this);
478  NS_LOG_LOGIC (this << " state: " << m_state);
479 
480  NS_ASSERT (m_state == RX);
481 
482  // this will trigger CQI calculation and Error Model evaluation
483  // as a side effect, the error model should update the error status of all TBs
484  m_interference->EndRx ();
485  NS_LOG_DEBUG (this << " No. of burts " << m_rxPacketBurstList.size ());
486  NS_LOG_DEBUG (this << " Expected TBs " << m_expectedTbs.size ());
487  expectedTbs_t::iterator itTb = m_expectedTbs.begin ();
488 
489  // apply transmission mode gain
490  NS_LOG_DEBUG (this << " txMode " << (uint16_t)m_transmissionMode << " gain " << m_txModeGain.at (m_transmissionMode));
493 
494  while (itTb!=m_expectedTbs.end ())
495  {
496  if (m_pemEnabled)
497  {
498  double errorRate = LteMiErrorModel::GetTbError (m_sinrPerceived, (*itTb).second.rbBitmap, (*itTb).second.size, (*itTb).second.mcs);
499  (*itTb).second.corrupt = m_random->GetValue () > errorRate ? false : true;
500  NS_LOG_DEBUG (this << "RNTI " << (*itTb).first.m_rnti << " size " << (*itTb).second.size << " mcs " << (uint32_t)(*itTb).second.mcs << " bitmap " << (*itTb).second.rbBitmap.size () << " layer " << (uint16_t)(*itTb).first.m_layer << " ErrorRate " << errorRate << " corrupted " << (*itTb).second.corrupt);
501  }
502 
503 // for (uint16_t i = 0; i < (*itTb).second.rbBitmap.size (); i++)
504 // {
505 // NS_LOG_DEBUG (this << " RB " << (*itTb).second.rbBitmap.at (i) << " SINR " << m_sinrPerceived[(*itTb).second.rbBitmap.at (i)]);
506 // }
507  itTb++;
508  }
509 
510  for (std::list<Ptr<PacketBurst> >::const_iterator i = m_rxPacketBurstList.begin ();
511  i != m_rxPacketBurstList.end (); ++i)
512  {
513  for (std::list<Ptr<Packet> >::const_iterator j = (*i)->Begin (); j != (*i)->End (); ++j)
514  {
515  // retrieve TB info of this packet
516  LteRadioBearerTag tag;
517  (*j)->PeekPacketTag (tag);
518  TbId_t tbId;
519  tbId.m_rnti = tag.GetRnti ();
520  tbId.m_layer = tag.GetLayer ();
521  itTb = m_expectedTbs.find (tbId);
522  NS_LOG_INFO (this << " Packet of " << tbId.m_rnti << " layer " << (uint8_t) tbId.m_layer);
523  if (itTb!=m_expectedTbs.end ())
524  {
525  if (!(*itTb).second.corrupt)
526  {
527  m_phyRxEndOkTrace (*j);
528 
530  {
532  }
533  }
534  else
535  {
536  // TB received with errors
538  }
539  }
540  }
541  }
542  ChangeState (IDLE);
543  m_rxPacketBurstList.clear ();
544  m_expectedTbs.clear ();
545 }
546 
547 void
548 LteSpectrumPhy::SetCellId (uint16_t cellId)
549 {
550  m_cellId = cellId;
551 }
552 
553 void
555 {
557 }
558 
559 void
561 {
562  NS_LOG_FUNCTION (this << (uint16_t) txMode);
563  NS_ASSERT_MSG (txMode < m_txModeGain.size (), "TransmissionMode not available: 1.." << m_txModeGain.size ());
564  m_transmissionMode = txMode;
565 }
566 
567 
568 void
569 LteSpectrumPhy::SetTxModeGain (uint8_t txMode, double gain)
570 {
571  NS_LOG_FUNCTION (this << " txmode " << (uint16_t)txMode << " gain " << gain);
572  // convert to linear
573  gain = pow (10.0, (gain / 10.0));
574  if (m_txModeGain.size () < txMode)
575  {
576  m_txModeGain.resize (txMode);
577  }
578  std::vector <double> temp;
579  temp = m_txModeGain;
580  m_txModeGain.clear ();
581  for (uint8_t i = 0; i < temp.size (); i++)
582  {
583  if (i==txMode-1)
584  {
585  m_txModeGain.push_back (gain);
586  }
587  else
588  {
589  m_txModeGain.push_back (temp.at (i));
590  }
591  }
592 }
593 
594 int64_t
596 {
597  NS_LOG_FUNCTION (this << stream);
598  m_random->SetStream (stream);
599  return 1;
600 }
601 
602 
603 
604 } // namespace ns3