A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
fdtbfq-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> // original version
19  * Modification: Dizhi Zhou <dizhi.zhou@gmail.com> // modify codes related to downlink scheduler
20  */
21 
22 #include <ns3/log.h>
23 #include <ns3/pointer.h>
24 #include <ns3/integer.h>
25 
26 #include <ns3/simulator.h>
27 #include <ns3/lte-amc.h>
28 #include <ns3/fdtbfq-ff-mac-scheduler.h>
29 #include <ns3/lte-vendor-specific-parameters.h>
30 
31 NS_LOG_COMPONENT_DEFINE ("FdTbfqFfMacScheduler");
32 
33 // value for SINR outside the range defined by LTE, used to indicate that there
34 // is no CQI for this element
35 #define NO_SINR -5000
36 
37 namespace ns3 {
38 
40  10, // RGB size 1
41  26, // RGB size 2
42  63, // RGB size 3
43  110 // RGB size 4
44 }; // see table 7.1.6.1-1 of 36.213
45 
46 NS_OBJECT_ENSURE_REGISTERED (FdTbfqFfMacScheduler);
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  bankSize (0)
220 {
221  m_amc = CreateObject <LteAmc> ();
224 }
225 
227 {
228  NS_LOG_FUNCTION (this);
229 }
230 
231 void
233 {
234  NS_LOG_FUNCTION (this);
235  delete m_cschedSapProvider;
236  delete m_schedSapProvider;
237 }
238 
239 TypeId
241 {
242  static TypeId tid = TypeId ("ns3::FdTbfqFfMacScheduler")
244  .AddConstructor<FdTbfqFfMacScheduler> ()
245  .AddAttribute ("CqiTimerThreshold",
246  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
247  UintegerValue (1000),
248  MakeUintegerAccessor (&FdTbfqFfMacScheduler::m_cqiTimersThreshold),
249  MakeUintegerChecker<uint32_t> ())
250  .AddAttribute ("DebtLimit",
251  "Flow debt limit (default -625000 bytes)",
252  IntegerValue (-625000),
253  MakeIntegerAccessor (&FdTbfqFfMacScheduler::m_debtLimit),
254  MakeIntegerChecker<int> ())
255  .AddAttribute ("CreditLimit",
256  "Flow credit limit (default 625000 bytes)",
257  UintegerValue (625000),
258  MakeUintegerAccessor (&FdTbfqFfMacScheduler::m_creditLimit),
259  MakeUintegerChecker<uint32_t> ())
260  .AddAttribute ("TokenPoolSize",
261  "The maximum value of flow token pool (default 1 bytes)",
262  UintegerValue (1),
263  MakeUintegerAccessor (&FdTbfqFfMacScheduler::m_tokenPoolSize),
264  MakeUintegerChecker<uint32_t> ())
265  .AddAttribute ("CreditableThreshold",
266  "Threshold of flow credit (default 0 bytes)",
267  UintegerValue (0),
268  MakeUintegerAccessor (&FdTbfqFfMacScheduler::m_creditableThreshold),
269  MakeUintegerChecker<uint32_t> ())
270  ;
271  return tid;
272 }
273 
274 
275 
276 void
278 {
279  m_cschedSapUser = s;
280 }
281 
282 void
284 {
285  m_schedSapUser = s;
286 }
287 
290 {
291  return m_cschedSapProvider;
292 }
293 
296 {
297  return m_schedSapProvider;
298 }
299 
300 void
302 {
303  NS_LOG_FUNCTION (this);
304  // Read the subset of parameters used
305  m_cschedCellConfig = params;
307  cnf.m_result = SUCCESS;
309  return;
310 }
311 
312 void
314 {
315  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
316  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
317  if (it == m_uesTxMode.end ())
318  {
319  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
320  }
321  else
322  {
323  (*it).second = params.m_transmissionMode;
324  }
325  return;
326 }
327 
328 void
330 {
331  NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti);
332 
333  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator it;
334  for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++)
335  {
336  it = m_flowStatsDl.find (params.m_rnti);
337 
338  if (it == m_flowStatsDl.end ())
339  {
340  uint64_t mbrDlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateDl / 8; // byte/s
341  uint64_t mbrUlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateUl / 8; // byte/s
342 
343  fdtbfqsFlowPerf_t flowStatsDl;
344  flowStatsDl.flowStart = Simulator::Now ();
345  flowStatsDl.packetArrivalRate = 0;
346  flowStatsDl.tokenGenerationRate = mbrDlInBytes;
347  flowStatsDl.tokenPoolSize = 0;
348  flowStatsDl.maxTokenPoolSize = m_tokenPoolSize;
349  flowStatsDl.counter = 0;
350  flowStatsDl.burstCredit = m_creditLimit; // bytes
351  flowStatsDl.debtLimit = m_debtLimit; // bytes
353  m_flowStatsDl.insert (std::pair<uint16_t, fdtbfqsFlowPerf_t> (params.m_rnti, flowStatsDl));
354  fdtbfqsFlowPerf_t flowStatsUl;
355  flowStatsUl.flowStart = Simulator::Now ();
356  flowStatsUl.packetArrivalRate = 0;
357  flowStatsUl.tokenGenerationRate = mbrUlInBytes;
358  flowStatsUl.tokenPoolSize = 0;
359  flowStatsUl.maxTokenPoolSize = m_tokenPoolSize;
360  flowStatsUl.counter = 0;
361  flowStatsUl.burstCredit = m_creditLimit; // bytes
362  flowStatsUl.debtLimit = m_debtLimit; // bytes
364  m_flowStatsUl.insert (std::pair<uint16_t, fdtbfqsFlowPerf_t> (params.m_rnti, flowStatsUl));
365  }
366  else
367  {
368  NS_LOG_ERROR ("RNTI already exists");
369  }
370  }
371 
372  return;
373 }
374 
375 
376 void
378 {
379  NS_FATAL_ERROR ("unimplemented");
380  return;
381 }
382 
383 void
385 {
386  NS_FATAL_ERROR ("unimplemented");
387  return;
388 }
389 
390 
391 void
393 {
394  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
395  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
396 
397  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
398 
399  LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity);
400 
401  it = m_rlcBufferReq.find (flow);
402 
403  if (it == m_rlcBufferReq.end ())
404  {
405  m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters> (flow, params));
406  }
407  else
408  {
409  (*it).second = params;
410  }
411 
412  return;
413 }
414 
415 void
417 {
418  NS_FATAL_ERROR ("unimplemented");
419  return;
420 }
421 
422 void
424 {
425  NS_FATAL_ERROR ("unimplemented");
426  return;
427 }
428 
429 int
431 {
432  for (int i = 0; i < 4; i++)
433  {
434  if (dlbandwidth < FdTbfqType0AllocationRbg[i])
435  {
436  return (i + 1);
437  }
438  }
439 
440  return (-1);
441 }
442 
443 
444 int
446 {
447  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
448  int lcActive = 0;
449  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
450  {
451  if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueSize > 0)
452  || ((*it).second.m_rlcRetransmissionQueueSize > 0)
453  || ((*it).second.m_rlcStatusPduSize > 0) ))
454  {
455  lcActive++;
456  }
457  if ((*it).first.m_rnti > rnti)
458  {
459  break;
460  }
461  }
462  return (lcActive);
463 
464 }
465 
466 void
468 {
469  NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
470  // API generated by RLC for triggering the scheduling of a DL subframe
471 
472 
473  // evaluate the relative channel quality indicator for each UE per each RBG
474  // (since we are using allocation type 0 the small unit of allocation is RBG)
475  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
476  RefreshDlCqiMaps ();
477 
478  // update token pool, counter and bank size
479  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator itStats;
480  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
481  {
482  if ( (*itStats).second.tokenGenerationRate / 1000 + (*itStats).second.tokenPoolSize > (*itStats).second.maxTokenPoolSize )
483  {
484  (*itStats).second.counter += (*itStats).second.tokenGenerationRate / 1000 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );
485  (*itStats).second.tokenPoolSize = (*itStats).second.maxTokenPoolSize;
486  bankSize += (*itStats).second.tokenGenerationRate / 1000 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );
487  }
488  else
489  {
490  (*itStats).second.tokenPoolSize += (*itStats).second.tokenGenerationRate / 1000;
491  }
492  }
493 
495  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
496  std::map <uint16_t, std::vector <uint16_t> > allocationMap;
497  std::set <uint16_t> allocatedRnti; // store UEs which are already assigned RBGs
498  std::set <uint8_t> allocatedRbg; // store RBGs which are already allocated to UE
499 
500  int totalRbg = 0;
501  while (totalRbg < rbgNum)
502  {
503  // select UE with largest metric
504  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator it;
505  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator itMax = m_flowStatsDl.end ();
506  double metricMax = 0.0;
507  bool firstRnti = true;
508  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
509  {
510  if (LcActivePerFlow ((*it).first) == 0)
511  {
512  continue;
513  }
514 
515  std::set <uint16_t>::iterator rnti;
516  rnti = allocatedRnti.find((*it).first);
517  if (rnti != allocatedRnti.end ()) // already allocated RBGs to this UE
518  {
519  continue;
520  }
521 
522  double metric = ( ( (double)(*it).second.counter ) / ( (double)(*it).second.tokenGenerationRate ) );
523 
524  if (firstRnti == true)
525  {
526  metricMax = metric;
527  itMax = it;
528  firstRnti = false;
529  continue;
530  }
531  if (metric > metricMax)
532  {
533  metricMax = metric;
534  itMax = it;
535  }
536  } // end for m_flowStatsDl
537 
538  if (itMax == m_flowStatsDl.end())
539  {
540  // all UEs are allocated RBG
541  break;
542  }
543 
544  // mark this UE as "allocated"
545  allocatedRnti.insert((*itMax).first);
546 
547  // calculate the maximum number of byte that the scheduler can assigned to this UE
548  uint32_t budget = 0;
549  if ( bankSize > 0 )
550  {
551  budget = (*itMax).second.counter - (*itMax).second.debtLimit;
552  if ( budget > (*itMax).second.burstCredit )
553  budget = (*itMax).second.burstCredit;
554  if ( budget > bankSize )
555  budget = bankSize;
556  }
557  budget = budget + (*itMax).second.tokenPoolSize;
558 
559  // calcualte how much bytes this UE actally need
560  if (budget == 0)
561  {
562  // there are no tokens for this UE
563  continue;
564  }
565  else
566  {
567  // calculate rlc buffer size
568  uint32_t rlcBufSize = 0;
569  uint8_t lcid = 0;
570  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itRlcBuf;
571  for (itRlcBuf = m_rlcBufferReq.begin (); itRlcBuf != m_rlcBufferReq.end (); itRlcBuf++)
572  {
573  if ( (*itRlcBuf).first.m_rnti == (*itMax).first )
574  lcid = (*itRlcBuf).first.m_lcId;
575  }
576  LteFlowId_t flow ((*itMax).first, lcid);
577  itRlcBuf = m_rlcBufferReq.find (flow);
578  if (itRlcBuf!=m_rlcBufferReq.end ())
579  rlcBufSize = (*itRlcBuf).second.m_rlcTransmissionQueueSize + (*itRlcBuf).second.m_rlcRetransmissionQueueSize + (*itRlcBuf).second.m_rlcStatusPduSize;
580  if ( budget > rlcBufSize )
581  budget = rlcBufSize;
582  }
583 
584  // assign RBGs to this UE
585  uint32_t bytesTxed = 0;
586  uint32_t bytesTxedTmp = 0;
587  int rbgIndex = 0;
588  while ( bytesTxed <= budget )
589  {
590  totalRbg++;
591 
592  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
593  itCqi = m_a30CqiRxed.find ((*itMax).first);
594  std::map <uint16_t,uint8_t>::iterator itTxMode;
595  itTxMode = m_uesTxMode.find ((*itMax).first);
596  if (itTxMode == m_uesTxMode.end ())
597  {
598  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
599  }
600  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
601 
602  // find RBG with largest achievableRate
603  double achievableRateMax = 0.0;
604  rbgIndex = rbgNum;
605  for (int k = 0; k < rbgNum; k++)
606  {
607  std::set <uint8_t>::iterator rbg;
608  rbg = allocatedRbg.find (k);
609  if (rbg != allocatedRbg.end ()) // RBGs are already allocated to this UE
610  continue;
611 
612  std::vector <uint8_t> sbCqi;
613  if (itCqi == m_a30CqiRxed.end ())
614  {
615  for (uint8_t k = 0; k < nLayer; k++)
616  {
617  sbCqi.push_back (1); // start with lowest value
618  }
619  }
620  else
621  {
622  sbCqi = (*itCqi).second.m_higherLayerSelected.at (k).m_sbCqi;
623  }
624  uint8_t cqi1 = sbCqi.at (0);
625  uint8_t cqi2 = 1;
626  if (sbCqi.size () > 1)
627  {
628  cqi2 = sbCqi.at (1);
629  }
630 
631  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
632  {
633  if (LcActivePerFlow ((*itMax).first) > 0)
634  {
635  // this UE has data to transmit
636  double achievableRate = 0.0;
637  for (uint8_t j = 0; j < nLayer; j++)
638  {
639  uint8_t mcs = 0;
640  if (sbCqi.size () > j)
641  {
642  mcs = m_amc->GetMcsFromCqi (sbCqi.at (j));
643  }
644  else
645  {
646  // no info on this subband -> worst MCS
647  mcs = 0;
648  }
649  achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, rbgSize) / 8) / 0.001); // = TB size / TTI
650  }
651 
652  if ( achievableRate > achievableRateMax )
653  {
654  achievableRateMax = achievableRate;
655  rbgIndex = k;
656  }
657  } // end of LcActivePerFlow
658  } // end of cqi
659  } // end of for rbgNum
660 
661  if ( rbgIndex == rbgNum) // impossible
662  {
663  // all RBGs are already assigned
664  totalRbg = rbgNum;
665  break;
666  }
667  else
668  {
669  // mark this UE as "allocated"
670  allocatedRbg.insert (rbgIndex);
671  }
672 
673  // assign this RBG to UE
674  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
675  itMap = allocationMap.find ((*itMax).first);
676  uint16_t RbgPerRnti;
677  if (itMap == allocationMap.end ())
678  {
679  // insert new element
680  std::vector <uint16_t> tempMap;
681  tempMap.push_back (rbgIndex);
682  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
683  itMap = allocationMap.find ((*itMax).first); // point itMap to the first RBGs assigned to this UE
684  }
685  else
686  {
687  (*itMap).second.push_back (rbgIndex);
688  }
689 
690  RbgPerRnti = (*itMap).second.size();
691 
692  // calculate tb size
693  std::vector <uint8_t> worstCqi (2, 15);
694  if (itCqi != m_a30CqiRxed.end ())
695  {
696  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
697  {
698  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
699  {
700  for (uint8_t j = 0; j < nLayer; j++)
701  {
702  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
703  {
704  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
705  {
706  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
707  }
708  }
709  else
710  {
711  // no CQI for this layer of this suband -> worst one
712  worstCqi.at (j) = 1;
713  }
714  }
715  }
716  else
717  {
718  for (uint8_t j = 0; j < nLayer; j++)
719  {
720  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
721  }
722  }
723  }
724  }
725  else
726  {
727  for (uint8_t j = 0; j < nLayer; j++)
728  {
729  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
730  }
731  }
732 
733  bytesTxedTmp = bytesTxed;
734  bytesTxed = 0;
735  for (uint8_t j = 0; j < nLayer; j++)
736  {
737  int tbSize = (m_amc->GetTbSizeFromMcs (m_amc->GetMcsFromCqi (worstCqi.at (j)), RbgPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
738  bytesTxed += tbSize;
739  }
740 
741  } // end of while()
742 
743  // remove and unmark last RBG assigned to UE
744  if ( bytesTxed > budget )
745  {
746  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
747  itMap = allocationMap.find ((*itMax).first);
748  (*itMap).second.pop_back ();
749  allocatedRbg.erase (rbgIndex);
750  bytesTxed = bytesTxedTmp; // recovery bytesTxed
751  totalRbg--;
752  }
753 
754  // update UE stats
755  if ( bytesTxed <= (*itMax).second.tokenPoolSize )
756  {
757  (*itMax).second.tokenPoolSize -= bytesTxed;
758  }
759  else
760  {
761  (*itMax).second.counter = (*itMax).second.counter - ( bytesTxed - (*itMax).second.tokenPoolSize );
762  (*itMax).second.tokenPoolSize = 0;
763  if (bankSize <= ( bytesTxed - (*itMax).second.tokenPoolSize ))
764  bankSize = 0;
765  else
766  bankSize = bankSize - ( bytesTxed - (*itMax).second.tokenPoolSize );
767  }
768  } // end of RBGs
769 
770  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
771  // creating the correspondent DCIs
773  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
774  while (itMap != allocationMap.end ())
775  {
776  // create new BuildDataListElement_s for this LC
778  newEl.m_rnti = (*itMap).first;
779  // create the DlDciListElement_s
780  DlDciListElement_s newDci;
781  std::vector <struct RlcPduListElement_s> newRlcPduLe;
782  newDci.m_rnti = (*itMap).first;
783 
784  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
785  uint16_t RgbPerRnti = (*itMap).second.size ();
786  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
787  itCqi = m_a30CqiRxed.find ((*itMap).first);
788  std::map <uint16_t,uint8_t>::iterator itTxMode;
789  itTxMode = m_uesTxMode.find ((*itMap).first);
790  if (itTxMode == m_uesTxMode.end ())
791  {
792  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
793  }
794  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
795  std::vector <uint8_t> worstCqi (2, 15);
796  if (itCqi != m_a30CqiRxed.end ())
797  {
798  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
799  {
800  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
801  {
802  for (uint8_t j = 0; j < nLayer; j++)
803  {
804  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
805  {
806  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
807  {
808  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
809  }
810  }
811  else
812  {
813  // no CQI for this layer of this suband -> worst one
814  worstCqi.at (j) = 1;
815  }
816  }
817  }
818  else
819  {
820  for (uint8_t j = 0; j < nLayer; j++)
821  {
822  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
823  }
824  }
825  }
826  }
827  else
828  {
829  for (uint8_t j = 0; j < nLayer; j++)
830  {
831  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
832  }
833  }
834  uint32_t bytesTxed = 0;
835  for (uint8_t j = 0; j < nLayer; j++)
836  {
837  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
838  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)
839  newDci.m_tbsSize.push_back (tbSize);
840  bytesTxed += tbSize;
841  }
842 
843  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
844  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
845  uint32_t rbgMask = 0;
846  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
847  {
848  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
849  }
850  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
851 
852  // create the rlc PDUs -> equally divide resources among actives LCs
853  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
854  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
855  {
856  if (((*itBufReq).first.m_rnti == (*itMap).first) &&
857  (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
858  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
859  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
860  {
861  for (uint8_t j = 0; j < nLayer; j++)
862  {
863  RlcPduListElement_s newRlcEl;
864  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
865  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
866  newRlcPduLe.push_back (newRlcEl);
867  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
868  }
869  }
870  if ((*itBufReq).first.m_rnti > (*itMap).first)
871  {
872  break;
873  }
874  }
875  newDci.m_ndi.push_back (1); // TBD (new data indicator)
876  newDci.m_rv.push_back (0); // TBD (redundancy version)
877 
878  newEl.m_dci = newDci;
879  // ...more parameters -> ingored in this version
880 
881  newEl.m_rlcPduList.push_back (newRlcPduLe);
882  ret.m_buildDataList.push_back (newEl);
883 
884  itMap++;
885  } // end while allocation
886  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
887 
889 
890  return;
891 }
892 
893 void
895 {
896  NS_FATAL_ERROR ("unimplemented");
897  return;
898 }
899 
900 void
902 {
903  NS_LOG_FUNCTION (this);
904 
905  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
906  {
907  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
908  {
909  // wideband CQI reporting
910  std::map <uint16_t,uint8_t>::iterator it;
911  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
912  it = m_p10CqiRxed.find (rnti);
913  if (it == m_p10CqiRxed.end ())
914  {
915  // create the new entry
916  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)
917  // generate correspondent timer
918  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
919  }
920  else
921  {
922  // update the CQI value and refresh correspondent timer
923  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
924  // update correspondent timer
925  std::map <uint16_t,uint32_t>::iterator itTimers;
926  itTimers = m_p10CqiTimers.find (rnti);
927  (*itTimers).second = m_cqiTimersThreshold;
928  }
929  }
930  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
931  {
932  // subband CQI reporting high layer configured
933  std::map <uint16_t,SbMeasResult_s>::iterator it;
934  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
935  it = m_a30CqiRxed.find (rnti);
936  if (it == m_a30CqiRxed.end ())
937  {
938  // create the new entry
939  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
940  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
941  }
942  else
943  {
944  // update the CQI value and refresh correspondent timer
945  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
946  std::map <uint16_t,uint32_t>::iterator itTimers;
947  itTimers = m_a30CqiTimers.find (rnti);
948  (*itTimers).second = m_cqiTimersThreshold;
949  }
950  }
951  else
952  {
953  NS_LOG_ERROR (this << " CQI type unknown");
954  }
955  }
956 
957  return;
958 }
959 
960 
961 double
962 FdTbfqFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
963 {
964  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
965  if (itCqi == m_ueCqi.end ())
966  {
967  // no cqi info about this UE
968  return (NO_SINR);
969 
970  }
971  else
972  {
973  // take the average SINR value among the available
974  double sinrSum = 0;
975  int sinrNum = 0;
976  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
977  {
978  double sinr = (*itCqi).second.at (i);
979  if (sinr != NO_SINR)
980  {
981  sinrSum += sinr;
982  sinrNum++;
983  }
984  }
985  double estimatedSinr = sinrSum / (double)sinrNum;
986  // store the value
987  (*itCqi).second.at (rb) = estimatedSinr;
988  return (estimatedSinr);
989  }
990 }
991 
992 void
994 {
995  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
996 
997  RefreshUlCqiMaps ();
998 
999  std::map <uint16_t,uint32_t>::iterator it;
1000  int nflows = 0;
1001 
1002  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1003  {
1004  // remove old entries of this UE-LC
1005  if ((*it).second > 0)
1006  {
1007  nflows++;
1008  }
1009  }
1010 
1011  if (nflows == 0)
1012  {
1013  return ; // no flows to be scheduled
1014  }
1015 
1016 
1017  // Divide the resource equally among the active users
1018  int rbPerFlow = m_cschedCellConfig.m_ulBandwidth / nflows;
1019  if (rbPerFlow == 0)
1020  {
1021  rbPerFlow = 1; // at least 1 rbg per flow (till available resource)
1022  }
1023  int rbAllocated = 0;
1024 
1026  std::vector <uint16_t> rbgAllocationMap;
1027  if (m_nextRntiUl != 0)
1028  {
1029  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1030  {
1031  if ((*it).first == m_nextRntiUl)
1032  {
1033  break;
1034  }
1035  }
1036  if (it == m_ceBsrRxed.end ())
1037  {
1038  NS_LOG_ERROR (this << " no user found");
1039  }
1040  }
1041  else
1042  {
1043  it = m_ceBsrRxed.begin ();
1044  m_nextRntiUl = (*it).first;
1045  }
1046  do
1047  {
1048  if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth)
1049  {
1050  // limit to physical resources last resource assignment
1051  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1052  }
1053 
1054  UlDciListElement_s uldci;
1055  uldci.m_rnti = (*it).first;
1056  uldci.m_rbStart = rbAllocated;
1057  uldci.m_rbLen = rbPerFlow;
1058  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1059  int cqi = 0;
1060  if (itCqi == m_ueCqi.end ())
1061  {
1062  // no cqi info about this UE
1063  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1064  }
1065  else
1066  {
1067  // take the lowest CQI value (worst RB)
1068  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1069  if (minSinr == NO_SINR)
1070  {
1071  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
1072  }
1073  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1074  {
1075  double sinr = (*itCqi).second.at (i);
1076  if (sinr == NO_SINR)
1077  {
1078  sinr = EstimateUlSinr ((*it).first, i);
1079  }
1080  if ((*itCqi).second.at (i) < minSinr)
1081  {
1082  minSinr = (*itCqi).second.at (i);
1083  }
1084  }
1085 
1086  // translate SINR -> cqi: WILD ACK: same as DL
1087  double s = log2 ( 1 + (
1088  std::pow (10, minSinr / 10 ) /
1089  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1091  if (cqi == 0)
1092  {
1093  it++;
1094  if (it == m_ceBsrRxed.end ())
1095  {
1096  // restart from the first
1097  it = m_ceBsrRxed.begin ();
1098  }
1099  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1100  }
1101  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1102 
1103  }
1104 
1105  rbAllocated += rbPerFlow;
1106  // store info on allocation for managing ul-cqi interpretation
1107  for (int i = 0; i < rbPerFlow; i++)
1108  {
1109  rbgAllocationMap.push_back ((*it).first);
1110  }
1111  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
1112  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);
1113  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1114  uldci.m_ndi = 1;
1115  uldci.m_cceIndex = 0;
1116  uldci.m_aggrLevel = 1;
1117  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1118  uldci.m_hopping = false;
1119  uldci.m_n2Dmrs = 0;
1120  uldci.m_tpc = 0; // no power control
1121  uldci.m_cqiRequest = false; // only period CQI at this stage
1122  uldci.m_ulIndex = 0; // TDD parameter
1123  uldci.m_dai = 1; // TDD parameter
1124  uldci.m_freqHopping = 0;
1125  uldci.m_pdcchPowerOffset = 0; // not used
1126  ret.m_dciList.push_back (uldci);
1127 
1128 
1129  it++;
1130  if (it == m_ceBsrRxed.end ())
1131  {
1132  // restart from the first
1133  it = m_ceBsrRxed.begin ();
1134  }
1135  if (rbAllocated == m_cschedCellConfig.m_ulBandwidth)
1136  {
1137  // Stop allocation: no more PRBs
1138  m_nextRntiUl = (*it).first;
1139  break;
1140  }
1141  }
1142  while ((*it).first != m_nextRntiUl);
1143 
1144  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1146  return;
1147 }
1148 
1149 void
1151 {
1152  NS_FATAL_ERROR ("unimplemented");
1153  return;
1154 }
1155 
1156 void
1158 {
1159  NS_FATAL_ERROR ("unimplemented");
1160  return;
1161 }
1162 
1163 void
1165 {
1166  NS_LOG_FUNCTION (this);
1167 
1168  std::map <uint16_t,uint32_t>::iterator it;
1169 
1170  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1171  {
1172  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1173  {
1174  // buffer status report
1175  // note that we only consider LCG 0, the other three LCGs are neglected
1176  // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
1177  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1178  it = m_ceBsrRxed.find (rnti);
1179  if (it == m_ceBsrRxed.end ())
1180  {
1181  // create the new entry
1182  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
1183  int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1184  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1185  }
1186  else
1187  {
1188  // update the buffer size value
1189  (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
1190  }
1191  }
1192  }
1193 
1194  return;
1195 }
1196 
1197 void
1199 {
1200  NS_LOG_FUNCTION (this);
1201  // retrieve the allocation for this subframe
1202  switch (m_ulCqiFilter)
1203  {
1205  {
1206  // filter all the CQIs that are not SRS based
1207  if (params.m_ulCqi.m_type!=UlCqi_s::SRS)
1208  {
1209  return;
1210  }
1211  }
1212  break;
1214  {
1215  // filter all the CQIs that are not SRS based
1216  if (params.m_ulCqi.m_type!=UlCqi_s::PUSCH)
1217  {
1218  return;
1219  }
1220  }
1222  break;
1223 
1224  default:
1225  NS_FATAL_ERROR ("Unknown UL CQI type");
1226  }
1227 
1228  switch (params.m_ulCqi.m_type)
1229  {
1230  case UlCqi_s::PUSCH:
1231  {
1232  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1233  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1234  itMap = m_allocationMaps.find (params.m_sfnSf);
1235  if (itMap == m_allocationMaps.end ())
1236  {
1237  NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1238  return;
1239  }
1240  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1241  {
1242  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1243  // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
1244  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1245  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1246  if (itCqi == m_ueCqi.end ())
1247  {
1248  // create a new entry
1249  std::vector <double> newCqi;
1250  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1251  {
1252  if (i == j)
1253  {
1254  newCqi.push_back (sinr);
1255  }
1256  else
1257  {
1258  // initialize with NO_SINR value.
1259  newCqi.push_back (NO_SINR);
1260  }
1261 
1262  }
1263  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1264  // generate correspondent timer
1265  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1266  }
1267  else
1268  {
1269  // update the value
1270  (*itCqi).second.at (i) = sinr;
1271  // update correspondent timer
1272  std::map <uint16_t, uint32_t>::iterator itTimers;
1273  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1274  (*itTimers).second = m_cqiTimersThreshold;
1275 
1276  }
1277 
1278  }
1279  // remove obsolete info on allocation
1280  m_allocationMaps.erase (itMap);
1281  }
1282  break;
1283  case UlCqi_s::SRS:
1284  {
1285  // get the RNTI from vendor specific parameters
1286  uint16_t rnti = 0;
1287  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1288  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1289  {
1290  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1291  {
1292  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1293  rnti = vsp->GetRnti ();
1294  }
1295  }
1296  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1297  itCqi = m_ueCqi.find (rnti);
1298  if (itCqi == m_ueCqi.end ())
1299  {
1300  // create a new entry
1301  std::vector <double> newCqi;
1302  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1303  {
1304  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1305  newCqi.push_back (sinr);
1306  NS_LOG_DEBUG (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1307 
1308  }
1309  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1310  // generate correspondent timer
1311  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1312  }
1313  else
1314  {
1315  // update the values
1316  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1317  {
1318  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1319  (*itCqi).second.at (j) = sinr;
1320  NS_LOG_DEBUG (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1321  }
1322  // update correspondent timer
1323  std::map <uint16_t, uint32_t>::iterator itTimers;
1324  itTimers = m_ueCqiTimers.find (rnti);
1325  (*itTimers).second = m_cqiTimersThreshold;
1326 
1327  }
1328 
1329 
1330  }
1331  break;
1332  case UlCqi_s::PUCCH_1:
1333  case UlCqi_s::PUCCH_2:
1334  case UlCqi_s::PRACH:
1335  {
1336  NS_FATAL_ERROR ("FdTbfqFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1337  }
1338  break;
1339  default:
1340  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1341  }
1342  return;
1343 }
1344 
1345 void
1347 {
1348  // refresh DL CQI P01 Map
1349  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1350  while (itP10!=m_p10CqiTimers.end ())
1351  {
1352 // NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1353  if ((*itP10).second == 0)
1354  {
1355  // delete correspondent entries
1356  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1357  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1358  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1359  m_p10CqiRxed.erase (itMap);
1360  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1361  itP10++;
1362  m_p10CqiTimers.erase (temp);
1363  }
1364  else
1365  {
1366  (*itP10).second--;
1367  itP10++;
1368  }
1369  }
1370 
1371  // refresh DL CQI A30 Map
1372  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
1373  while (itA30!=m_a30CqiTimers.end ())
1374  {
1375 // NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1376  if ((*itA30).second == 0)
1377  {
1378  // delete correspondent entries
1379  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
1380  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
1381  NS_LOG_INFO (this << " A30-CQI exired for user " << (*itA30).first);
1382  m_a30CqiRxed.erase (itMap);
1383  std::map <uint16_t,uint32_t>::iterator temp = itA30;
1384  itA30++;
1385  m_a30CqiTimers.erase (temp);
1386  }
1387  else
1388  {
1389  (*itA30).second--;
1390  itA30++;
1391  }
1392  }
1393 
1394  return;
1395 }
1396 
1397 
1398 void
1400 {
1401  // refresh UL CQI Map
1402  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1403  while (itUl!=m_ueCqiTimers.end ())
1404  {
1405 // NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1406  if ((*itUl).second == 0)
1407  {
1408  // delete correspondent entries
1409  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1410  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1411  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1412  (*itMap).second.clear ();
1413  m_ueCqi.erase (itMap);
1414  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1415  itUl++;
1416  m_ueCqiTimers.erase (temp);
1417  }
1418  else
1419  {
1420  (*itUl).second--;
1421  itUl++;
1422  }
1423  }
1424 
1425  return;
1426 }
1427 
1428 void
1429 FdTbfqFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1430 {
1431  size = size - 2; // remove the minimum RLC overhead
1432  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1433  LteFlowId_t flow (rnti, lcid);
1434  it = m_rlcBufferReq.find (flow);
1435  if (it!=m_rlcBufferReq.end ())
1436  {
1437  // Update queues: RLC tx order Status, ReTx, Tx
1438  // Update status queue
1439  if ((*it).second.m_rlcStatusPduSize <= size)
1440  {
1441  size -= (*it).second.m_rlcStatusPduSize;
1442  (*it).second.m_rlcStatusPduSize = 0;
1443  }
1444  else
1445  {
1446  (*it).second.m_rlcStatusPduSize -= size;
1447  return;
1448  }
1449  // update retransmission queue
1450  if ((*it).second.m_rlcRetransmissionQueueSize <= size)
1451  {
1452  size -= (*it).second.m_rlcRetransmissionQueueSize;
1453  (*it).second.m_rlcRetransmissionQueueSize = 0;
1454  }
1455  else
1456  {
1457  (*it).second.m_rlcRetransmissionQueueSize -= size;
1458  return;
1459  }
1460  // update transmission queue
1461  if ((*it).second.m_rlcTransmissionQueueSize <= size)
1462  {
1463  size -= (*it).second.m_rlcTransmissionQueueSize;
1464  (*it).second.m_rlcTransmissionQueueSize = 0;
1465  }
1466  else
1467  {
1468  (*it).second.m_rlcTransmissionQueueSize -= size;
1469  return;
1470  }
1471  }
1472  else
1473  {
1474  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
1475  }
1476 }
1477 
1478 void
1479 FdTbfqFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1480 {
1481 
1482  size = size - 2; // remove the minimum RLC overhead
1483  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1484  if (it!=m_ceBsrRxed.end ())
1485  {
1486  if ((*it).second >= size)
1487  {
1488  (*it).second -= size;
1489  }
1490  else
1491  {
1492  (*it).second = 0;
1493  }
1494  }
1495  else
1496  {
1497  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1498  }
1499 
1500 }
1501 
1502 void
1504 {
1505  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1507  params.m_rnti = rnti;
1508  params.m_transmissionMode = txMode;
1510 }
1511 
1512 
1513 }