A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
lte-enb-phy.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 TELEMATICS LAB, DEE - Politecnico di Bari
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: Giuseppe Piro <g.piro@poliba.it>
19  * Marco Miozzo <mmiozzo@cttc.es>
20  */
21 
22 #include <ns3/object-factory.h>
23 #include <ns3/log.h>
24 #include <cmath>
25 #include <ns3/simulator.h>
26 #include <ns3/attribute-accessor-helper.h>
27 #include <ns3/double.h>
28 
29 
30 #include "lte-enb-phy.h"
31 #include "lte-net-device.h"
33 #include "lte-control-messages.h"
34 #include "lte-enb-net-device.h"
35 #include "lte-enb-mac.h"
36 #include <ns3/lte-common.h>
37 #include <ns3/lte-vendor-specific-parameters.h>
38 
39 
40 NS_LOG_COMPONENT_DEFINE ("LteEnbPhy");
41 
42 namespace ns3 {
43 
44 
45 // duration of the data part of a subframe in DL
46 // = 0.001 / 14 * 11 (fixed to 11 symbols) -1ns as margin to avoid overlapping simulator events
47 static const Time DL_DATA_DURATION = NanoSeconds (785714 -1);
48 
49 // delay from subframe start to transmission of the data in DL
50 // = 0.001 / 14 * 3 (ctrl fixed to 3 symbols)
52 
54 // member SAP forwarders
56 
57 
59 {
60 public:
62 
63  // inherited from LteEnbPhySapProvider
64  virtual void SendMacPdu (Ptr<Packet> p);
65  virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
66  virtual void SetCellId (uint16_t cellId);
68  virtual uint8_t GetMacChTtiDelay ();
69  virtual void SetTransmissionMode (uint16_t rnti, uint8_t txMode);
70  virtual void SetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi);
71 
72 
73 private:
75 };
76 
78 {
79 
80 }
81 
82 
83 void
85 {
86  m_phy->DoSendMacPdu (p);
87 }
88 
89 void
90 EnbMemberLteEnbPhySapProvider::SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth)
91 {
92  m_phy->DoSetBandwidth (ulBandwidth, dlBandwidth);
93 }
94 
95 void
97 {
98  m_phy->DoSetCellId (cellId);
99 }
100 
101 void
103 {
105 }
106 
107 uint8_t
109 {
110  return (m_phy->DoGetMacChTtiDelay ());
111 }
112 
113 void
115 {
116  m_phy->DoSetTransmissionMode (rnti, txMode);
117 }
118 
119 void
121 {
122  m_phy->DoSetSrsConfigurationIndex (rnti, srcCi);
123 }
124 
125 
127 // generic LteEnbPhy methods
129 
130 
131 
133 
134 
136 {
137  NS_LOG_FUNCTION (this);
138  NS_FATAL_ERROR ("This constructor should not be called");
139 }
140 
142  : LtePhy (dlPhy, ulPhy),
143  m_nrFrames (0),
144  m_nrSubFrames (0),
145  m_srsPeriodicity (0),
146  m_currentSrsOffset (0)
147 {
150 }
151 
152 TypeId
154 {
155  static TypeId tid = TypeId ("ns3::LteEnbPhy")
156  .SetParent<LtePhy> ()
157  .AddConstructor<LteEnbPhy> ()
158  .AddAttribute ("TxPower",
159  "Transmission power in dBm",
160  DoubleValue (30.0),
161  MakeDoubleAccessor (&LteEnbPhy::SetTxPower,
163  MakeDoubleChecker<double> ())
164  .AddAttribute ("NoiseFigure",
165  "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
166  " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
167  "\"the difference in decibels (dB) between"
168  " the noise output of the actual receiver to the noise output of an "
169  " ideal receiver with the same overall gain and bandwidth when the receivers "
170  " are connected to sources at the standard noise temperature T0.\" "
171  "In this model, we consider T0 = 290K.",
172  DoubleValue (5.0),
173  MakeDoubleAccessor (&LteEnbPhy::SetNoiseFigure,
175  MakeDoubleChecker<double> ())
176  .AddAttribute ("MacToChannelDelay",
177  "The delay in TTI units that occurs between a scheduling decision in the MAC and the actual start of the transmission by the PHY. This is intended to be used to model the latency of real PHY and MAC implementations.",
178  UintegerValue (2),
179  MakeUintegerAccessor (&LteEnbPhy::SetMacChDelay,
181  MakeUintegerChecker<uint8_t> ())
182  ;
183  return tid;
184 }
185 
186 
188 {
189 }
190 
191 void
193 {
194  NS_LOG_FUNCTION (this);
195  m_ueAttached.clear ();
196  m_srsUeOffset.clear ();
197  delete m_enbPhySapProvider;
199 }
200 
201 void
203 {
204  NS_LOG_FUNCTION (this);
207  LtePhy::DoStart ();
208 }
209 
210 
211 void
213 {
214  m_enbPhySapUser = s;
215 }
216 
219 {
220  return (m_enbPhySapProvider);
221 }
222 
223 void
225 {
226  NS_LOG_FUNCTION (this << pow);
227  m_txPower = pow;
228 }
229 
230 double
232 {
233  NS_LOG_FUNCTION (this);
234  return m_txPower;
235 }
236 
237 void
239 {
240  NS_LOG_FUNCTION (this << nf);
241  m_noiseFigure = nf;
242 }
243 
244 double
246 {
247  NS_LOG_FUNCTION (this);
248  return m_noiseFigure;
249 }
250 
251 void
253 {
254  m_macChTtiDelay = delay;
255  for (int i = 0; i < m_macChTtiDelay; i++)
256  {
257  Ptr<PacketBurst> pb = CreateObject <PacketBurst> ();
258  m_packetBurstQueue.push_back (pb);
259  std::list<Ptr<LteControlMessage> > l;
260  m_controlMessagesQueue.push_back (l);
261  std::list<UlDciLteControlMessage> l1;
262  m_ulDciQueue.push_back (l1);
263  }
264  for (int i = 0; i < UL_PUSCH_TTIS_DELAY; i++)
265  {
266  std::list<UlDciLteControlMessage> l1;
267  m_ulDciQueue.push_back (l1);
268  }
269 }
270 
271 uint8_t
273 {
274  return (m_macChTtiDelay);
275 }
276 
277 bool
278 LteEnbPhy::AddUePhy (uint16_t rnti)
279 {
280  std::set <uint16_t>::iterator it;
281  it = m_ueAttached.find (rnti);
282  if (it == m_ueAttached.end ())
283  {
284  m_ueAttached.insert (rnti);
285  return (true);
286  }
287  else
288  {
289  NS_LOG_ERROR ("UE already attached");
290  return (false);
291  }
292 }
293 
294 bool
295 LteEnbPhy::DeleteUePhy (uint16_t rnti)
296 {
297  std::set <uint16_t>::iterator it;
298  it = m_ueAttached.find (rnti);
299  if (it == m_ueAttached.end ())
300  {
301  NS_LOG_ERROR ("UE not attached");
302  return (false);
303  }
304  else
305  {
306  m_ueAttached.erase (it);
307  return (true);
308  }
309 }
310 
311 
312 
313 void
315 {
316  NS_LOG_FUNCTION (this);
317  SetMacPdu (p);
318 }
319 
320 uint8_t
322 {
323  return (m_macChTtiDelay);
324 }
325 
326 
327 void
329 {
330  NS_LOG_FUNCTION (this);
332 }
333 
334 void
335 LteEnbPhy::SetDownlinkSubChannels (std::vector<int> mask)
336 {
337  NS_LOG_FUNCTION (this);
341 }
342 
343 std::vector<int>
345 {
346  NS_LOG_FUNCTION (this);
348 }
349 
352 {
353  NS_LOG_FUNCTION (this);
354 
356 
357  return psd;
358 }
359 
360 
361 void
363 {
364  NS_LOG_FUNCTION (this);
365 }
366 
367 
368 void
370 {
371  NS_LOG_FUNCTION (this << msg);
372  // queues the message (wait for MAC-PHY delay)
373  SetControlMessages (msg);
374 }
375 
376 
377 
378 void
380 {
381  NS_FATAL_ERROR ("Obsolete function");
382  NS_LOG_FUNCTION (this << msg);
384 }
385 
386 void
388 {
389  NS_LOG_FUNCTION (this);
390  std::list<Ptr<LteControlMessage> >::iterator it;
391  for (it = msgList.begin (); it != msgList.end(); it++)
392  {
394  }
395 
396 }
397 
398 
399 
400 void
402 {
403  NS_LOG_FUNCTION (this);
404 
405  ++m_nrFrames;
406  NS_LOG_INFO ("-----frame " << m_nrFrames << "-----");
407  m_nrSubFrames = 0;
408  StartSubFrame ();
409 }
410 
411 
412 void
414 {
415  NS_LOG_FUNCTION (this);
416 
417  ++m_nrSubFrames;
418  if (m_srsPeriodicity>0)
419  {
420  // might be 0 in case the eNB has no UEs attached
422  }
423  NS_LOG_INFO ("-----sub frame " << m_nrSubFrames << "-----");
424 
425 
426  // update info on TB to be received
427  std::list<UlDciLteControlMessage> uldcilist = DequeueUlDci ();
428  std::list<UlDciLteControlMessage>::iterator dciIt = uldcilist.begin ();
429  m_ulRntiRxed.clear ();
430  NS_LOG_DEBUG (this << " eNB Expected TBs " << uldcilist.size ());
431  for (dciIt = uldcilist.begin (); dciIt!=uldcilist.end (); dciIt++)
432  {
433  std::set <uint16_t>::iterator it2;
434  it2 = m_ueAttached.find ((*dciIt).GetDci ().m_rnti);
435 
436  if (it2 == m_ueAttached.end ())
437  {
438  NS_LOG_ERROR ("UE not attached");
439  }
440  else
441  {
442  // send info of TB to LteSpectrumPhy
443  // translate to allocation map
444  std::vector <int> rbMap;
445  for (int i = (*dciIt).GetDci ().m_rbStart; i < (*dciIt).GetDci ().m_rbStart + (*dciIt).GetDci ().m_rbLen; i++)
446  {
447  rbMap.push_back (i);
448  }
449  m_uplinkSpectrumPhy->AddExpectedTb ((*dciIt).GetDci ().m_rnti, (*dciIt).GetDci ().m_tbSize, (*dciIt).GetDci ().m_mcs, rbMap, 0 /* always SISO*/);
450  m_ulRntiRxed.push_back ((*dciIt).GetDci ().m_rnti);
451  }
452  }
453 
454  // process the current burst of control messages
455  std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
456  std::list<DlDciListElement_s> dlDci;
457  std::list<UlDciListElement_s> ulDci;
458 // std::vector <int> dlRb;
459  m_dlDataRbMap.clear ();
460  if (ctrlMsg.size () > 0)
461  {
462  std::list<Ptr<LteControlMessage> >::iterator it;
463  it = ctrlMsg.begin ();
464  while (it != ctrlMsg.end ())
465  {
466  Ptr<LteControlMessage> msg = (*it);
468  {
469  Ptr<DlDciLteControlMessage> dci = DynamicCast<DlDciLteControlMessage> (msg);
470  dlDci.push_back (dci->GetDci ());
471  // get the tx power spectral density according to DL-DCI(s)
472  // translate the DCI to Spectrum framework
473  uint32_t mask = 0x1;
474  for (int i = 0; i < 32; i++)
475  {
476  if (((dci->GetDci ().m_rbBitmap & mask) >> i) == 1)
477  {
478  for (int k = 0; k < GetRbgSize (); k++)
479  {
480  m_dlDataRbMap.push_back ((i * GetRbgSize ()) + k);
481  //NS_LOG_DEBUG(this << " [enb]DL-DCI allocated PRB " << (i*GetRbgSize()) + k);
482  }
483  }
484  mask = (mask << 1);
485  }
486  }
487  else if (msg->GetMessageType () == LteControlMessage::UL_DCI)
488  {
489  Ptr<UlDciLteControlMessage> dci = DynamicCast<UlDciLteControlMessage> (msg);
490  QueueUlDci (*dci);
491  ulDci.push_back (dci->GetDci ());
492  }
493  it++;
494 
495  }
496  }
497 
498  SendControlChannels (ctrlMsg);
499 
500  // send data frame
502  if (pb)
503  {
504  Simulator::Schedule (DL_CTRL_DELAY_FROM_SUBFRAME_START, // ctrl frame fixed to 3 symbols
506  this,pb);
507  }
508 
509  // trigger the MAC
511 
514  this);
515 
516 }
517 
518 void
520 {
521  NS_LOG_FUNCTION (this << " eNB " << m_cellId << " start tx ctrl frame");
522  // set the current tx power spectral density (full bandwidth)
523  std::vector <int> dlRb;
524  for (uint8_t i = 0; i < m_dlBandwidth; i++)
525  {
526  dlRb.push_back (i);
527  }
528  SetDownlinkSubChannels (dlRb);
529  NS_LOG_LOGIC (this << " eNB start TX CTRL");
531 
532 }
533 
534 void
536 {
537  // set the current tx power spectral density
539  // send the current burts of packets
540  NS_LOG_LOGIC (this << " eNB start TX DATA");
541  std::list<Ptr<LteControlMessage> > ctrlMsgList;
542  ctrlMsgList.clear ();
544 }
545 
546 
547 void
549 {
550  NS_LOG_FUNCTION (this << Simulator::Now ().GetSeconds ());
551  if (m_nrSubFrames == 10)
552  {
554  }
555  else
556  {
558  }
559 }
560 
561 
562 void
564 {
565  NS_LOG_FUNCTION (this << Simulator::Now ().GetSeconds ());
567 }
568 
569 
570 void
572 {
573  NS_LOG_FUNCTION (this << sinr);
575  m_enbPhySapUser->UlCqiReport (ulcqi);
576 }
577 
578 void
580 {
581  NS_LOG_FUNCTION (this << sinr);
583  m_enbPhySapUser->UlCqiReport (ulcqi);
584 }
585 
586 
587 
590 {
591  NS_LOG_FUNCTION (this << sinr);
592  Values::const_iterator it;
594  ulcqi.m_ulCqi.m_type = UlCqi_s::PUSCH;
595  int i = 0;
596  for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++)
597  {
598  double sinrdb = 10 * std::log10 ((*it));
599 // NS_LOG_DEBUG ("ULCQI RB " << i << " value " << sinrdb);
600  // convert from double to fixed point notation Sxxxxxxxxxxx.xxx
601  int16_t sinrFp = LteFfConverter::double2fpS11dot3 (sinrdb);
602  ulcqi.m_ulCqi.m_sinr.push_back (sinrFp);
603  i++;
604  }
605  return (ulcqi);
606 
607 }
608 
609 
612 {
613  NS_LOG_FUNCTION (this << sinr);
614  Values::const_iterator it;
616  ulcqi.m_ulCqi.m_type = UlCqi_s::SRS;
617  int i = 0;
618  for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++)
619  {
620  double sinrdb = 10 * log10 ((*it));
621  // NS_LOG_DEBUG ("ULCQI RB " << i << " value " << sinrdb);
622  // convert from double to fixed point notation Sxxxxxxxxxxx.xxx
623  int16_t sinrFp = LteFfConverter::double2fpS11dot3 (sinrdb);
624  ulcqi.m_ulCqi.m_sinr.push_back (sinrFp);
625  i++;
626  }
627  // Insert the user generated the srs as a vendor specific parameter
628  NS_LOG_DEBUG (this << " ENB RX UL-CQI of " << m_srsUeOffset.at (m_currentSrsOffset));
630  vsp.m_type = SRS_CQI_RNTI_VSP;
631  vsp.m_length = sizeof(SrsCqiRntiVsp);
632  Ptr<SrsCqiRntiVsp> rnti = Create <SrsCqiRntiVsp> (m_srsUeOffset.at (m_currentSrsOffset));
633  vsp.m_value = rnti;
634  ulcqi.m_vendorSpecificList.push_back (vsp);
635  return (ulcqi);
636 
637 }
638 
639 void
640 LteEnbPhy::DoSetTransmissionMode (uint16_t rnti, uint8_t txMode)
641 {
642  NS_LOG_FUNCTION (this << rnti << (uint16_t)txMode);
643  // UL supports only SISO MODE
644 }
645 
646 void
648 {
649  NS_LOG_FUNCTION (this);
650  m_ulDciQueue.at (UL_PUSCH_TTIS_DELAY - 1).push_back (m);
651 }
652 
653 std::list<UlDciLteControlMessage>
655 {
656  NS_LOG_FUNCTION (this);
657  if (m_ulDciQueue.at (0).size ()>0)
658  {
659  std::list<UlDciLteControlMessage> ret = m_ulDciQueue.at (0);
660  m_ulDciQueue.erase (m_ulDciQueue.begin ());
661  std::list<UlDciLteControlMessage> l;
662  m_ulDciQueue.push_back (l);
663  return (ret);
664  }
665  else
666  {
667  m_ulDciQueue.erase (m_ulDciQueue.begin ());
668  std::list<UlDciLteControlMessage> l;
669  m_ulDciQueue.push_back (l);
670  std::list<UlDciLteControlMessage> emptylist;
671  return (emptylist);
672  }
673 }
674 
675 void
676 LteEnbPhy::DoSetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi)
677 {
678  NS_LOG_FUNCTION (this);
679  uint16_t p = GetSrsPeriodicity (srcCi);
680  if (p!=m_srsPeriodicity)
681  {
682  // resize the array of offset -> re-initialize variables
683  m_srsUeOffset.clear ();
684  m_srsUeOffset.resize (p, 0);
685  m_srsPeriodicity = p;
686  m_currentSrsOffset = p - 1; // for starting from 0 next subframe
687  }
688 
689  NS_LOG_DEBUG (this << " ENB SRS P " << m_srsPeriodicity << " RNTI " << rnti << " offset " << GetSrsSubframeOffset (srcCi) << " CI " << srcCi);
690  std::map <uint16_t,uint16_t>::iterator it = m_srsCounter.find (rnti);
691  if (it != m_srsCounter.end ())
692  {
693  (*it).second = GetSrsSubframeOffset (srcCi) + 1;
694  }
695  else
696  {
697  m_srsCounter.insert (std::pair<uint16_t, uint16_t> (rnti, GetSrsSubframeOffset (srcCi) + 1));
698  }
699  m_srsUeOffset.at (GetSrsSubframeOffset (srcCi)) = rnti;
700 
701 }
702 
703 
704 };