A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
pf-ff-mac-scheduler.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (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: Marco Miozzo <marco.miozzo@cttc.es>
19  */
20 
21 #ifdef __FreeBSD__
22 #define log2(x) (log(x) / M_LN2)
23 #endif /* __FreeBSD__ */
24 
25 #include <ns3/log.h>
26 #include <ns3/pointer.h>
27 
28 #include <ns3/simulator.h>
29 #include <ns3/lte-amc.h>
30 #include <ns3/pf-ff-mac-scheduler.h>
31 
32 NS_LOG_COMPONENT_DEFINE ("PfFfMacScheduler");
33 
34 namespace ns3 {
35 
37  10, // RGB size 1
38  26, // RGB size 2
39  63, // RGB size 3
40  110 // RGB size 4
41 }; // see table 7.1.6.1-1 of 36.213
42 
43 
44 NS_OBJECT_ENSURE_REGISTERED (PfFfMacScheduler);
45 
46 
47 
49 {
50 public:
52 
53  // inherited from FfMacCschedSapProvider
54  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
55  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
56  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
57  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
58  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
59 
60 private:
63 };
64 
66 {
67 }
68 
70 {
71 }
72 
73 
74 void
76 {
78 }
79 
80 void
82 {
84 }
85 
86 
87 void
89 {
91 }
92 
93 void
95 {
97 }
98 
99 void
101 {
103 }
104 
105 
106 
107 
109 {
110 public:
112 
113  // inherited from FfMacSchedSapProvider
114  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
115  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
116  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
117  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
118  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
119  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
120  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
121  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
122  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
123  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
124  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
125 
126 
127 private:
130 };
131 
132 
133 
135 {
136 }
137 
138 
140  : m_scheduler (scheduler)
141 {
142 }
143 
144 void
146 {
148 }
149 
150 void
152 {
154 }
155 
156 void
158 {
160 }
161 
162 void
164 {
166 }
167 
168 void
170 {
172 }
173 
174 void
176 {
178 }
179 
180 void
182 {
184 }
185 
186 void
188 {
190 }
191 
192 void
194 {
196 }
197 
198 void
200 {
202 }
203 
204 void
206 {
208 }
209 
210 
211 
212 
213 
215  : m_cschedSapUser (0),
216  m_schedSapUser (0),
217  m_timeWindow (99.0),
218  m_nextRntiUl (0)
219 {
220  m_amc = CreateObject <LteAmc> ();
223 }
224 
226 {
227  NS_LOG_FUNCTION (this);
228 }
229 
230 void
232 {
233  NS_LOG_FUNCTION (this);
234  delete m_cschedSapProvider;
235  delete m_schedSapProvider;
236 }
237 
238 TypeId
240 {
241  static TypeId tid = TypeId ("ns3::PfFfMacScheduler")
243  .AddConstructor<PfFfMacScheduler> ()
244  .AddAttribute ("CqiTimerThreshold",
245  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
246  UintegerValue (1000),
247  MakeUintegerAccessor (&PfFfMacScheduler::m_cqiTimersThreshold),
248  MakeUintegerChecker<uint32_t> ())
249  ;
250  return tid;
251 }
252 
253 
254 
255 void
257 {
258  m_cschedSapUser = s;
259 }
260 
261 void
263 {
264  m_schedSapUser = s;
265 }
266 
269 {
270  return m_cschedSapProvider;
271 }
272 
275 {
276  return m_schedSapProvider;
277 }
278 
279 void
281 {
282  NS_LOG_FUNCTION (this);
283  // Read the subset of parameters used
284  m_cschedCellConfig = params;
286  cnf.m_result = SUCCESS;
288  return;
289 }
290 
291 void
293 {
294  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
295  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
296  if (it==m_uesTxMode.end ())
297  {
298  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
299  }
300  else
301  {
302  (*it).second = params.m_transmissionMode;
303  }
304  return;
305  return;
306 }
307 
308 void
310 {
311  NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti);
312 
313  std::map <uint16_t, pfsFlowPerf_t>::iterator it;
314  for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++)
315  {
316  it = m_flowStatsDl.find (params.m_rnti);
317 
318  if (it == m_flowStatsDl.end ())
319  {
320  pfsFlowPerf_t flowStatsDl;
321  flowStatsDl.flowStart = Simulator::Now ();
322  flowStatsDl.totalBytesTransmitted = 0;
323  flowStatsDl.lastTtiBytesTrasmitted = 0;
324  flowStatsDl.lastAveragedThroughput = 1;
325  m_flowStatsDl.insert (std::pair<uint16_t, pfsFlowPerf_t> (params.m_rnti, flowStatsDl));
326  pfsFlowPerf_t flowStatsUl;
327  flowStatsUl.flowStart = Simulator::Now ();
328  flowStatsUl.totalBytesTransmitted = 0;
329  flowStatsUl.lastTtiBytesTrasmitted = 0;
330  flowStatsUl.lastAveragedThroughput = 1;
331  m_flowStatsUl.insert (std::pair<uint16_t, pfsFlowPerf_t> (params.m_rnti, flowStatsUl));
332  }
333  else
334  {
335  NS_LOG_ERROR ("RNTI already exists");
336  }
337  }
338 
339  return;
340 }
341 
342 void
344 {
345  NS_LOG_FUNCTION (this);
346  // TODO: Implementation of the API
347  return;
348 }
349 
350 void
352 {
353  NS_LOG_FUNCTION (this);
354  // TODO: Implementation of the API
355  return;
356 }
357 
358 
359 void
361 {
362  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
363  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
364 
365  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
366 
367  LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity);
368 
369  it = m_rlcBufferReq.find (flow);
370 
371  if (it == m_rlcBufferReq.end ())
372  {
373  m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters> (flow, params));
374  }
375  else
376  {
377  (*it).second = params;
378  }
379 
380  return;
381 }
382 
383 void
385 {
386  NS_LOG_FUNCTION (this);
387  // TODO: Implementation of the API
388  return;
389 }
390 
391 void
393 {
394  NS_LOG_FUNCTION (this);
395  // TODO: Implementation of the API
396  return;
397 }
398 
399 int
401 {
402  for (int i = 0; i < 4; i++)
403  {
404  if (dlbandwidth < PfType0AllocationRbg[i])
405  {
406  return (i + 1);
407  }
408  }
409 
410  return (-1);
411 }
412 
413 
414 int
416 {
417  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
418  int lcActive = 0;
419  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
420  {
421  if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueSize > 0)
422  || ((*it).second.m_rlcRetransmissionQueueSize > 0)
423  || ((*it).second.m_rlcStatusPduSize > 0) ))
424  {
425  lcActive++;
426  }
427  if ((*it).first.m_rnti > rnti)
428  {
429  break;
430  }
431  }
432  return (lcActive);
433 
434 }
435 
436 
437 void
439 {
440  NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
441  // API generated by RLC for triggering the scheduling of a DL subframe
442 
443 
444  // evaluate the relative channel quality indicator for each UE per each RBG
445  // (since we are using allocation type 0 the small unit of allocation is RBG)
446  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
447 
448  RefreshDlCqiMaps ();
449 
451  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
452  std::map <uint16_t, std::vector <uint16_t> > allocationMap;
453  for (int i = 0; i < rbgNum; i++)
454  {
455 // NS_LOG_DEBUG (this << " ALLOCATION for RBG " << i << " of " << rbgNum);
456  std::map <uint16_t, pfsFlowPerf_t>::iterator it;
457  std::map <uint16_t, pfsFlowPerf_t>::iterator itMax = m_flowStatsDl.end ();
458  double rcqiMax = 0.0;
459  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
460  {
461  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
462  itCqi = m_a30CqiRxed.find ((*it).first);
463  std::map <uint16_t,uint8_t>::iterator itTxMode;
464  itTxMode = m_uesTxMode.find ((*it).first);
465  if (itTxMode == m_uesTxMode.end())
466  {
467  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
468  }
469  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
470  std::vector <uint8_t> sbCqi;
471  if (itCqi == m_a30CqiRxed.end ())
472  {
473 // NS_LOG_DEBUG (this << " No DL-CQI for this UE " << (*it).first);
474  for (uint8_t k = 0; k < nLayer; k++)
475  {
476  sbCqi.push_back (1); // start with lowest value
477  }
478  }
479  else
480  {
481  sbCqi = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi;
482 // NS_LOG_INFO (this << " CQI " << (uint32_t)cqi);
483  }
484  uint8_t cqi1 = sbCqi.at(0);
485  uint8_t cqi2 = 1;
486  if (sbCqi.size () > 1)
487  {
488  cqi2 = sbCqi.at(1);
489  }
490 
491  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
492  {
493 // NS_LOG_DEBUG (this << " LC active " << LcActivePerFlow ((*it).first));
494  if (LcActivePerFlow ((*it).first) > 0)
495  {
496  // this UE has data to transmit
497  double achievableRate = 0.0;
498  for (uint8_t k = 0; k < nLayer; k++)
499  {
500  uint8_t mcs = 0;
501  if (sbCqi.size () > k)
502  {
503  mcs = m_amc->GetMcsFromCqi (sbCqi.at (k));
504  }
505  else
506  {
507  // no info on this subband -> worst MCS
508  mcs = 0;
509  }
510  achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, rbgSize) / 8) / 0.001); // = TB size / TTI
511  }
512 
513  double rcqi = achievableRate / (*it).second.lastAveragedThroughput;
514 // NS_LOG_DEBUG (this << " RNTI " << (*it).first << " MCS " << (uint32_t)mcs << " achievableRate " << achievableRate << " avgThr " << (*it).second.lastAveragedThroughput << " RCQI " << rcqi);
515 
516  if (rcqi > rcqiMax)
517  {
518  rcqiMax = rcqi;
519  itMax = it;
520  }
521  }
522  } // end if cqi
523  } // end for m_rlcBufferReq
524 
525  if (itMax == m_flowStatsDl.end ())
526  {
527  // no UE available for this RB
528  NS_LOG_DEBUG (this << " no UE found");
529  }
530  else
531  {
532  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
533  itMap = allocationMap.find ((*itMax).first);
534  if (itMap == allocationMap.end ())
535  {
536  // insert new element
537  std::vector <uint16_t> tempMap;
538  tempMap.push_back (i);
539  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
540  }
541  else
542  {
543  (*itMap).second.push_back (i);
544  }
545 // NS_LOG_DEBUG (this << " UE assigned " << (*itMax).first);
546  }
547  } // end for RBGs
548 
549  // reset TTI stats of users
550  std::map <uint16_t, pfsFlowPerf_t>::iterator itStats;
551  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
552  {
553  (*itStats).second.lastTtiBytesTrasmitted = 0;
554  }
555 
556  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
557  // creating the correspondent DCIs
559  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
560  while (itMap != allocationMap.end ())
561  {
562  // create new BuildDataListElement_s for this LC
564  newEl.m_rnti = (*itMap).first;
565  // create the DlDciListElement_s
566  DlDciListElement_s newDci;
567  std::vector <struct RlcPduListElement_s> newRlcPduLe;
568  newDci.m_rnti = (*itMap).first;
569 
570  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
571 // NS_LOG_DEBUG (this << "Allocate user " << newEl.m_rnti << " rbg " << lcActives);
572  uint16_t RgbPerRnti = (*itMap).second.size ();
573  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
574  itCqi = m_a30CqiRxed.find ((*itMap).first);
575  std::map <uint16_t,uint8_t>::iterator itTxMode;
576  itTxMode = m_uesTxMode.find ((*itMap).first);
577  if (itTxMode == m_uesTxMode.end())
578  {
579  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
580  }
581  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
582  std::vector <uint8_t> worstCqi (2, 15);
583  if (itCqi != m_a30CqiRxed.end ())
584  {
585  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
586  {
587  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
588  {
589 // NS_LOG_DEBUG (this << " RBG " << (*itMap).second.at (k) << " CQI " << (uint16_t)((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)) );
590  for (uint8_t j = 0; j < nLayer; j++)
591  {
592  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size ()> j)
593  {
594  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
595  {
596  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
597  }
598  }
599  else
600  {
601  // no CQI for this layer of this suband -> worst one
602  worstCqi.at (j) = 1;
603  }
604  }
605  }
606  else
607  {
608  for (uint8_t j = 0; j < nLayer; j++)
609  {
610  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
611  }
612  }
613  }
614  }
615  else
616  {
617  for (uint8_t j = 0; j < nLayer; j++)
618  {
619  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
620  }
621  }
622 // NS_LOG_DEBUG (this << " CQI " << (uint16_t)worstCqi);
623  uint32_t bytesTxed = 0;
624  for (uint8_t j = 0; j < nLayer; j++)
625  {
626  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
627  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (j), RgbPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
628  newDci.m_tbsSize.push_back (tbSize);
629  NS_LOG_DEBUG (this << " MCS " << m_amc->GetMcsFromCqi (worstCqi.at (j)));
630  bytesTxed += tbSize;
631  }
632 
633  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
634  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
635  uint32_t rbgMask = 0;
636  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
637  {
638  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
639 // NS_LOG_DEBUG (this << " Allocated PRB " << (*itMap).second.at (k));
640  }
641  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
642 
643  // create the rlc PDUs -> equally divide resources among actives LCs
644  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
645  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
646  {
647  if (((*itBufReq).first.m_rnti == (*itMap).first) &&
648  (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
649  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
650  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
651  {
652  for (uint8_t j = 0; j < nLayer; j++)
653  {
654  RlcPduListElement_s newRlcEl;
655  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
656  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
657  NS_LOG_DEBUG (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j);
658  newRlcPduLe.push_back (newRlcEl);
659  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
660  }
661  }
662  if ((*itBufReq).first.m_rnti > (*itMap).first)
663  {
664  break;
665  }
666  }
667  newDci.m_ndi.push_back (1); // TBD (new data indicator)
668  newDci.m_rv.push_back (0); // TBD (redundancy version)
669 
670  newEl.m_dci = newDci;
671  // ...more parameters -> ingored in this version
672 
673  newEl.m_rlcPduList.push_back (newRlcPduLe);
674  ret.m_buildDataList.push_back (newEl);
675 
676  // update UE stats
677  std::map <uint16_t, pfsFlowPerf_t>::iterator it;
678  it = m_flowStatsDl.find ((*itMap).first);
679  if (it != m_flowStatsDl.end ())
680  {
681  (*it).second.lastTtiBytesTrasmitted = bytesTxed;
682 // NS_LOG_DEBUG (this << " UE bytes txed " << (*it).second.lastTtiBytesTrasmitted);
683 
684 
685  }
686  else
687  {
688  NS_LOG_DEBUG (this << " No Stats for this allocated UE");
689  }
690 
691  itMap++;
692  } // end while allocation
693  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
694 
695 
696  // update UEs stats
697  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
698  {
699  (*itStats).second.totalBytesTransmitted += (*itStats).second.lastTtiBytesTrasmitted;
700  // update average throughput (see eq. 12.3 of Sec 12.3.1.2 of LTE – The UMTS Long Term Evolution, Ed Wiley)
701  (*itStats).second.lastAveragedThroughput = ((1.0 - (1.0 / m_timeWindow)) * (*itStats).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTrasmitted / 0.001));
702 // NS_LOG_DEBUG (this << " UE tot bytes " << (*itStats).second.totalBytesTransmitted);
703 // NS_LOG_DEBUG (this << " UE avg thr " << (*itStats).second.lastAveragedThroughput);
704  (*itStats).second.lastTtiBytesTrasmitted = 0;
705  }
706 
708 
709 
710  return;
711 }
712 
713 void
715 {
716  NS_LOG_FUNCTION (this);
717  // TODO: Implementation of the API
718  return;
719 }
720 
721 void
723 {
724  NS_LOG_FUNCTION (this);
725 
726  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
727  {
728  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
729  {
730  // wideband CQI reporting
731  std::map <uint16_t,uint8_t>::iterator it;
732  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
733  it = m_p10CqiRxed.find (rnti);
734  if (it == m_p10CqiRxed.end ())
735  {
736  // create the new entry
737  m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (rnti, params.m_cqiList.at (i).m_wbCqi.at (0)) ); // only codeword 0 at this stage (SISO)
738  // generate correspondent timer
739  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
740  }
741  else
742  {
743  // update the CQI value and refresh correspondent timer
744  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
745  // update correspondent timer
746  std::map <uint16_t,uint32_t>::iterator itTimers;
747  itTimers = m_p10CqiTimers.find (rnti);
748  (*itTimers).second = m_cqiTimersThreshold;
749  }
750  }
751  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
752  {
753  // subband CQI reporting high layer configured
754  std::map <uint16_t,SbMeasResult_s>::iterator it;
755  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
756  it = m_a30CqiRxed.find (rnti);
757  if (it == m_a30CqiRxed.end ())
758  {
759  // create the new entry
760  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
761  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
762  }
763  else
764  {
765  // update the CQI value and refresh correspondent timer
766  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
767  std::map <uint16_t,uint32_t>::iterator itTimers;
768  itTimers = m_a30CqiTimers.find (rnti);
769  (*itTimers).second = m_cqiTimersThreshold;
770  }
771  }
772  else
773  {
774  NS_LOG_ERROR (this << " CQI type unknown");
775  }
776  }
777 
778  return;
779 }
780 
781 
782 double
783 PfFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
784 {
785  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
786  if (itCqi == m_ueCqi.end ())
787  {
788  // no cqi info about this UE
789  return (NO_SINR);
790 
791  }
792  else
793  {
794  // take the average SINR value among the available
795  double sinrSum = 0;
796  int sinrNum = 0;
797  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
798  {
799  double sinr = (*itCqi).second.at (i);
800  if (sinr != NO_SINR)
801  {
802  sinrSum += sinr;
803  sinrNum++;
804  }
805  }
806  double estimatedSinr = sinrSum / (double)sinrNum;
807  // store the value
808  (*itCqi).second.at (rb) = estimatedSinr;
809  return (estimatedSinr);
810  }
811 }
812 
813 void
815 {
816  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
817 
818  RefreshUlCqiMaps ();
819 
820  std::map <uint16_t,uint32_t>::iterator it;
821  int nflows = 0;
822 
823  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
824  {
825  // remove old entries of this UE-LC
826  if ((*it).second > 0)
827  {
828  nflows++;
829  }
830  }
831 
832  if (nflows == 0)
833  {
834  return ; // no flows to be scheduled
835  }
836 
837 
838  // Divide the resource equally among the active users
839  int rbPerFlow = m_cschedCellConfig.m_ulBandwidth / nflows;
840  if (rbPerFlow == 0)
841  {
842  rbPerFlow = 1; // at least 1 rbg per flow (till available resource)
843  }
844  int rbAllocated = 0;
845 
847  std::vector <uint16_t> rbgAllocationMap;
848  std::map <uint16_t, pfsFlowPerf_t>::iterator itStats;
849  if (m_nextRntiUl != 0)
850  {
851  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
852  {
853  if ((*it).first == m_nextRntiUl)
854  {
855  break;
856  }
857  }
858  if (it == m_ceBsrRxed.end ())
859  {
860  NS_LOG_ERROR (this << " no user found");
861  }
862  }
863  else
864  {
865  it = m_ceBsrRxed.begin ();
866  m_nextRntiUl = (*it).first;
867  }
868  do
869  {
870  if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth)
871  {
872  // limit to physical resources last resource assignment
873  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
874  }
875 
876  UlDciListElement_s uldci;
877  uldci.m_rnti = (*it).first;
878  uldci.m_rbStart = rbAllocated;
879  uldci.m_rbLen = rbPerFlow;
880  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
881  int cqi = 0;
882  if (itCqi == m_ueCqi.end ())
883  {
884  // no cqi info about this UE
885  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
886 // NS_LOG_DEBUG (this << " UE does not have ULCQI " << (*it).first );
887  }
888  else
889  {
890  // take the lowest CQI value (worst RB)
891  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
892  if (minSinr == NO_SINR)
893  {
894  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
895  }
896  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
897  {
898 // NS_LOG_DEBUG (this << " UE " << (*it).first << " has SINR " << (*itCqi).second.at(i));
899  double sinr = (*itCqi).second.at (i);
900  if (sinr == NO_SINR)
901  {
902  sinr = EstimateUlSinr ((*it).first, i);
903  }
904  if ((*itCqi).second.at (i) < minSinr)
905  {
906  minSinr = (*itCqi).second.at (i);
907  }
908  }
909 
910  // translate SINR -> cqi: WILD ACK: same as DL
911  double s = log2 ( 1 + (
912  pow (10, minSinr / 10 ) /
913  ( (-log (5.0 * 0.00005 )) / 1.5) ));
915  if (cqi == 0)
916  {
917  it++;
918  if (it == m_ceBsrRxed.end ())
919  {
920  // restart from the first
921  it = m_ceBsrRxed.begin ();
922  }
923  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
924  }
925  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
926 // NS_LOG_DEBUG (this << " UE " << (*it).first << " minsinr " << minSinr << " -> mcs " << (uint16_t)uldci.m_mcs);
927 
928  }
929 
930  rbAllocated += rbPerFlow;
931  // store info on allocation for managing ul-cqi interpretation
932  for (int i = 0; i < rbPerFlow; i++)
933  {
934  rbgAllocationMap.push_back ((*it).first);
935  }
936  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
937 // NS_LOG_DEBUG (this << " UE " << (*it).first << " startPRB " << (uint32_t)uldci.m_rbStart << " nPRB " << (uint32_t)uldci.m_rbLen << " CQI " << cqi << " MCS " << (uint32_t)uldci.m_mcs << " TBsize " << uldci.m_tbSize << " RbAlloc " << rbAllocated);
938  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
939  uldci.m_ndi = 1;
940  uldci.m_cceIndex = 0;
941  uldci.m_aggrLevel = 1;
942  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
943  uldci.m_hopping = false;
944  uldci.m_n2Dmrs = 0;
945  uldci.m_tpc = 0; // no power control
946  uldci.m_cqiRequest = false; // only period CQI at this stage
947  uldci.m_ulIndex = 0; // TDD parameter
948  uldci.m_dai = 1; // TDD parameter
949  uldci.m_freqHopping = 0;
950  uldci.m_pdcchPowerOffset = 0; // not used
951  ret.m_dciList.push_back (uldci);
952 
953  // update TTI UE stats
954  itStats = m_flowStatsUl.find ((*it).first);
955  if (itStats != m_flowStatsUl.end ())
956  {
957  (*itStats).second.lastTtiBytesTrasmitted = uldci.m_tbSize;
958 // NS_LOG_DEBUG (this << " UE bytes txed " << (*it).second.lastTtiBytesTrasmitted);
959 
960 
961  }
962  else
963  {
964  NS_LOG_DEBUG (this << " No Stats for this allocated UE");
965  }
966 
967 
968  it++;
969  if (it == m_ceBsrRxed.end ())
970  {
971  // restart from the first
972  it = m_ceBsrRxed.begin ();
973  }
974  if (rbAllocated == m_cschedCellConfig.m_ulBandwidth)
975  {
976  // Stop allocation: no more PRBs
977  m_nextRntiUl = (*it).first;
978  break;
979  }
980  }
981  while ((*it).first != m_nextRntiUl);
982 
983 
984  // Update global UE stats
985  // update UEs stats
986  for (itStats = m_flowStatsUl.begin (); itStats != m_flowStatsUl.end (); itStats++)
987  {
988  (*itStats).second.totalBytesTransmitted += (*itStats).second.lastTtiBytesTrasmitted;
989  // update average throughput (see eq. 12.3 of Sec 12.3.1.2 of LTE – The UMTS Long Term Evolution, Ed Wiley)
990  (*itStats).second.lastAveragedThroughput = ((1.0 - (1.0 / m_timeWindow)) * (*itStats).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTrasmitted / 0.001));
991  // NS_LOG_DEBUG (this << " UE tot bytes " << (*itStats).second.totalBytesTransmitted);
992  // NS_LOG_DEBUG (this << " UE avg thr " << (*itStats).second.lastAveragedThroughput);
993  (*itStats).second.lastTtiBytesTrasmitted = 0;
994  }
995  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
997  return;
998 }
999 
1000 void
1002 {
1003  NS_LOG_FUNCTION (this);
1004  // TODO: Implementation of the API
1005  return;
1006 }
1007 
1008 void
1010 {
1011  NS_LOG_FUNCTION (this);
1012  // TODO: Implementation of the API
1013  return;
1014 }
1015 
1016 void
1018 {
1019  NS_LOG_FUNCTION (this);
1020 
1021  std::map <uint16_t,uint32_t>::iterator it;
1022 
1023  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1024  {
1025  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1026  {
1027  // buffer status report
1028  // note that we only consider LCG 0, the other three LCGs are neglected
1029  // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
1030  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1031  it = m_ceBsrRxed.find (rnti);
1032  if (it == m_ceBsrRxed.end ())
1033  {
1034  // create the new entry
1035  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
1036  int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1037  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1038  }
1039  else
1040  {
1041  // update the buffer size value
1042  (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
1043  }
1044  }
1045  }
1046 
1047  return;
1048 }
1049 
1050 void
1052 {
1053  NS_LOG_FUNCTION (this);
1054 // NS_LOG_DEBUG (this << " RX SFNID " << params.m_sfnSf);
1055  // retrieve the allocation for this subframe
1056  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1057  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1058  itMap = m_allocationMaps.find (params.m_sfnSf);
1059  if (itMap == m_allocationMaps.end ())
1060  {
1061  NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1062  return;
1063  }
1064  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1065  {
1066  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1067 // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
1068  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1069  //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr);
1070  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1071  if (itCqi == m_ueCqi.end ())
1072  {
1073  // create a new entry
1074  std::vector <double> newCqi;
1075  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1076  {
1077  if (i == j)
1078  {
1079  newCqi.push_back (sinr);
1080  }
1081  else
1082  {
1083  // initialize with NO_SINR value.
1084  newCqi.push_back (NO_SINR);
1085  }
1086 
1087  }
1088  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1089  // generate correspondent timer
1090  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1091  }
1092  else
1093  {
1094  // update the value
1095  (*itCqi).second.at (i) = sinr;
1096  // update correspondent timer
1097  std::map <uint16_t, uint32_t>::iterator itTimers;
1098  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1099  (*itTimers).second = m_cqiTimersThreshold;
1100 
1101  }
1102 
1103  }
1104  // remove obsolete info on allocation
1105  m_allocationMaps.erase (itMap);
1106 
1107  return;
1108 }
1109 
1110 void
1112 {
1113  // refresh DL CQI P01 Map
1114  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1115  while (itP10!=m_p10CqiTimers.end ())
1116  {
1117 // NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1118  if ((*itP10).second == 0)
1119  {
1120  // delete correspondent entries
1121  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1122  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1123  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1124  m_p10CqiRxed.erase (itMap);
1125  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1126  itP10++;
1127  m_p10CqiTimers.erase (temp);
1128  }
1129  else
1130  {
1131  (*itP10).second--;
1132  itP10++;
1133  }
1134  }
1135 
1136  // refresh DL CQI A30 Map
1137  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
1138  while (itA30!=m_a30CqiTimers.end ())
1139  {
1140 // NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1141  if ((*itA30).second == 0)
1142  {
1143  // delete correspondent entries
1144  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
1145  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
1146  NS_LOG_INFO (this << " A30-CQI exired for user " << (*itA30).first);
1147  m_a30CqiRxed.erase (itMap);
1148  std::map <uint16_t,uint32_t>::iterator temp = itA30;
1149  itA30++;
1150  m_a30CqiTimers.erase (temp);
1151  }
1152  else
1153  {
1154  (*itA30).second--;
1155  itA30++;
1156  }
1157  }
1158 
1159  return;
1160 }
1161 
1162 
1163 void
1165 {
1166  // refresh UL CQI Map
1167  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1168  while (itUl!=m_ueCqiTimers.end ())
1169  {
1170 // NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1171  if ((*itUl).second == 0)
1172  {
1173  // delete correspondent entries
1174  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1175  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1176  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1177  (*itMap).second.clear ();
1178  m_ueCqi.erase (itMap);
1179  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1180  itUl++;
1181  m_ueCqiTimers.erase (temp);
1182  }
1183  else
1184  {
1185  (*itUl).second--;
1186  itUl++;
1187  }
1188  }
1189 
1190  return;
1191 }
1192 
1193 void
1194 PfFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1195 {
1196  size = size - 2; // remove the minimum RLC overhead
1197  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1198  LteFlowId_t flow (rnti, lcid);
1199  it = m_rlcBufferReq.find (flow);
1200  if (it!=m_rlcBufferReq.end ())
1201  {
1202 // NS_LOG_DEBUG (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).second.m_rlcTransmissionQueueSize << " retxqueue " << (*it).second.m_rlcRetransmissionQueueSize << " status " << (*it).second.m_rlcStatusPduSize << " decrease " << size);
1203  // Update queues: RLC tx order Status, ReTx, Tx
1204  // Update status queue
1205  if ((*it).second.m_rlcStatusPduSize <= size)
1206  {
1207  size -= (*it).second.m_rlcStatusPduSize;
1208  (*it).second.m_rlcStatusPduSize = 0;
1209  }
1210  else
1211  {
1212  (*it).second.m_rlcStatusPduSize -= size;
1213  return;
1214  }
1215  // update retransmission queue
1216  if ((*it).second.m_rlcRetransmissionQueueSize <= size)
1217  {
1218  size -= (*it).second.m_rlcRetransmissionQueueSize;
1219  (*it).second.m_rlcRetransmissionQueueSize = 0;
1220  }
1221  else
1222  {
1223  (*it).second.m_rlcRetransmissionQueueSize -= size;
1224  return;
1225  }
1226  // update transmission queue
1227  if ((*it).second.m_rlcTransmissionQueueSize <= size)
1228  {
1229  size -= (*it).second.m_rlcTransmissionQueueSize;
1230  (*it).second.m_rlcTransmissionQueueSize = 0;
1231  }
1232  else
1233  {
1234  (*it).second.m_rlcTransmissionQueueSize -= size;
1235  return;
1236  }
1237  }
1238  else
1239  {
1240  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
1241  }
1242 }
1243 
1244 void
1245 PfFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1246 {
1247 
1248  size = size - 2; // remove the minimum RLC overhead
1249  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1250  if (it!=m_ceBsrRxed.end ())
1251  {
1252 // NS_LOG_DEBUG (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
1253  if ((*it).second >= size)
1254  {
1255  (*it).second -= size;
1256  }
1257  else
1258  {
1259  (*it).second = 0;
1260  }
1261  }
1262  else
1263  {
1264  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1265  }
1266 
1267 }
1268 
1269 void
1271 {
1272  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1274  params.m_rnti = rnti;
1275  params.m_transmissionMode = txMode;
1277 }
1278 
1279 
1280 }