A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
pss-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/string.h>
29 #include <ns3/pss-ff-mac-scheduler.h>
30 #include <ns3/lte-vendor-specific-parameters.h>
31 
32 NS_LOG_COMPONENT_DEFINE ("PssFfMacScheduler");
33 
34 // value for SINR outside the range defined by LTE, used to indicate that there
35 // is no CQI for this element
36 #define NO_SINR -5000
37 
38 namespace ns3 {
39 
41  10, // RGB size 1
42  26, // RGB size 2
43  63, // RGB size 3
44  110 // RGB size 4
45 }; // see table 7.1.6.1-1 of 36.213
46 
47 NS_OBJECT_ENSURE_REGISTERED (PssFfMacScheduler);
48 
50 {
51 public:
53 
54  // inherited from FfMacCschedSapProvider
55  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
56  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
57  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
58  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
59  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
60 
61 private:
64 };
65 
67 {
68 }
69 
71 {
72 }
73 
74 
75 void
77 {
79 }
80 
81 void
83 {
85 }
86 
87 
88 void
90 {
92 }
93 
94 void
96 {
98 }
99 
100 void
102 {
104 }
105 
106 
107 
108 
110 {
111 public:
113 
114  // inherited from FfMacSchedSapProvider
115  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
116  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
117  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
118  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
119  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
120  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
121  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
122  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
123  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
124  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
125  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
126 
127 
128 private:
131 };
132 
133 
134 
136 {
137 }
138 
139 
141  : m_scheduler (scheduler)
142 {
143 }
144 
145 void
147 {
149 }
150 
151 void
153 {
155 }
156 
157 void
159 {
161 }
162 
163 void
165 {
167 }
168 
169 void
171 {
173 }
174 
175 void
177 {
179 }
180 
181 void
183 {
185 }
186 
187 void
189 {
191 }
192 
193 void
195 {
197 }
198 
199 void
201 {
203 }
204 
205 void
207 {
209 }
210 
211 
212 
213 
214 
216  : m_cschedSapUser (0),
217  m_schedSapUser (0),
218  m_timeWindow (99.0),
219  m_nextRntiUl (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::PssFfMacScheduler")
244  .AddConstructor<PssFfMacScheduler> ()
245  .AddAttribute ("CqiTimerThreshold",
246  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
247  UintegerValue (1000),
248  MakeUintegerAccessor (&PssFfMacScheduler::m_cqiTimersThreshold),
249  MakeUintegerChecker<uint32_t> ())
250  .AddAttribute ("PssFdSchedulerType",
251  "FD scheduler in PSS (default value is PFsch)",
252  StringValue ("PFsch"),
253  MakeStringAccessor (&PssFfMacScheduler::m_fdSchedulerType),
254  MakeStringChecker ())
255  .AddAttribute ("nMux",
256  "The number of UE selected by TD scheduler (default value is 0)",
257  UintegerValue (0),
258  MakeUintegerAccessor (&PssFfMacScheduler::m_nMux),
259  MakeUintegerChecker<uint32_t> ())
260  ;
261  return tid;
262 }
263 
264 
265 
266 void
268 {
269  m_cschedSapUser = s;
270 }
271 
272 void
274 {
275  m_schedSapUser = s;
276 }
277 
280 {
281  return m_cschedSapProvider;
282 }
283 
286 {
287  return m_schedSapProvider;
288 }
289 
290 void
292 {
293  NS_LOG_FUNCTION (this);
294  // Read the subset of parameters used
295  m_cschedCellConfig = params;
297  cnf.m_result = SUCCESS;
299  return;
300 }
301 
302 void
304 {
305  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
306  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
307  if (it == m_uesTxMode.end ())
308  {
309  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
310  }
311  else
312  {
313  (*it).second = params.m_transmissionMode;
314  }
315  return;
316 }
317 
318 void
320 {
321  NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti);
322 
323  std::map <uint16_t, pssFlowPerf_t>::iterator it;
324  for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++)
325  {
326  it = m_flowStatsDl.find (params.m_rnti);
327 
328  if (it == m_flowStatsDl.end ())
329  {
330  double tbrDlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabGuaranteedBitrateDl / 8; // byte/s
331  double tbrUlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabGuaranteedBitrateUl / 8; // byte/s
332 
333  pssFlowPerf_t flowStatsDl;
334  flowStatsDl.flowStart = Simulator::Now ();
335  flowStatsDl.totalBytesTransmitted = 0;
336  flowStatsDl.lastTtiBytesTransmitted = 0;
337  flowStatsDl.lastAveragedThroughput = 1;
338  flowStatsDl.secondLastAveragedThroughput = 1;
339  flowStatsDl.targetThroughput = tbrDlInBytes;
340  m_flowStatsDl.insert (std::pair<uint16_t, pssFlowPerf_t> (params.m_rnti, flowStatsDl));
341  pssFlowPerf_t flowStatsUl;
342  flowStatsUl.flowStart = Simulator::Now ();
343  flowStatsUl.totalBytesTransmitted = 0;
344  flowStatsUl.lastTtiBytesTransmitted = 0;
345  flowStatsUl.lastAveragedThroughput = 1;
346  flowStatsUl.secondLastAveragedThroughput = 1;
347  flowStatsUl.targetThroughput = tbrUlInBytes;
348  m_flowStatsUl.insert (std::pair<uint16_t, pssFlowPerf_t> (params.m_rnti, flowStatsUl));
349  }
350  else
351  {
352  NS_LOG_ERROR ("RNTI already exists");
353  }
354  }
355 
356  return;
357 }
358 
359 
360 void
362 {
363  NS_FATAL_ERROR ("unimplemented");
364  return;
365 }
366 
367 void
369 {
370  NS_FATAL_ERROR ("unimplemented");
371  return;
372 }
373 
374 
375 void
377 {
378  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
379  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
380 
381  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
382 
383  LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity);
384 
385  it = m_rlcBufferReq.find (flow);
386 
387  if (it == m_rlcBufferReq.end ())
388  {
389  m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters> (flow, params));
390  }
391  else
392  {
393  (*it).second = params;
394  }
395 
396  return;
397 }
398 
399 void
401 {
402  NS_FATAL_ERROR ("unimplemented");
403  return;
404 }
405 
406 void
408 {
409  NS_FATAL_ERROR ("unimplemented");
410  return;
411 }
412 
413 int
415 {
416  for (int i = 0; i < 4; i++)
417  {
418  if (dlbandwidth < PssType0AllocationRbg[i])
419  {
420  return (i + 1);
421  }
422  }
423 
424  return (-1);
425 }
426 
427 
428 int
430 {
431  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
432  int lcActive = 0;
433  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
434  {
435  if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueSize > 0)
436  || ((*it).second.m_rlcRetransmissionQueueSize > 0)
437  || ((*it).second.m_rlcStatusPduSize > 0) ))
438  {
439  lcActive++;
440  }
441  if ((*it).first.m_rnti > rnti)
442  {
443  break;
444  }
445  }
446  return (lcActive);
447 
448 }
449 
450 void
452 {
453  NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
454  // API generated by RLC for triggering the scheduling of a DL subframe
455 
456  // evaluate the relative channel quality indicator for each UE per each RBG
457  // (since we are using allocation type 0 the small unit of allocation is RBG)
458  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
459 
460  RefreshDlCqiMaps ();
461 
463  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
464  std::map <uint16_t, std::vector <uint16_t> > allocationMap;
465  std::map <uint16_t, pssFlowPerf_t>::iterator it;
466 
467  // schedulability check
468  std::map <uint16_t, pssFlowPerf_t> ueSet;
469  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
470  {
471  if( LcActivePerFlow ((*it).first) > 0 )
472  {
473  ueSet.insert(std::pair <uint16_t, pssFlowPerf_t> ((*it).first, (*it).second));
474  }
475  }
476 
477  if (ueSet.size() == 0)
478  {
479  // no data in RLC buffer
480  return;
481  }
482 
483  // Time Domain scheduler
484  std::vector <std::pair<double, uint16_t> > ueSet1;
485  std::vector <std::pair<double,uint16_t> > ueSet2;
486  for (it = ueSet.begin (); it != ueSet.end (); it++)
487  {
488  double metric = 0.0;
489  if ((*it).second.lastAveragedThroughput < (*it).second.targetThroughput )
490  {
491  // calculate TD BET metric
492  metric = 1 / (*it).second.lastAveragedThroughput;
493  ueSet1.push_back(std::pair<double, uint16_t> (metric, (*it).first));
494  }
495  else
496  {
497  // calculate TD PF metric
498  std::map <uint16_t,uint8_t>::iterator itCqi;
499  itCqi = m_p10CqiRxed.find ((*it).first);
500  std::map <uint16_t,uint8_t>::iterator itTxMode;
501  itTxMode = m_uesTxMode.find ((*it).first);
502  if (itTxMode == m_uesTxMode.end())
503  {
504  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
505  }
506  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
507  uint8_t wbCqi = 0;
508  if (itCqi == m_p10CqiRxed.end())
509  {
510  wbCqi = 1; // start with lowest value
511  }
512  else
513  {
514  wbCqi = (*itCqi).second;
515  }
516 
517  if (wbCqi > 0)
518  {
519  if (LcActivePerFlow ((*it).first) > 0)
520  {
521  // this UE has data to transmit
522  double achievableRate = 0.0;
523  for (uint8_t k = 0; k < nLayer; k++)
524  {
525  uint8_t mcs = 0;
526  mcs = m_amc->GetMcsFromCqi (wbCqi);
527  achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, rbgSize) / 8) / 0.001); // = TB size / TTI
528  }
529 
530  metric = achievableRate / (*it).second.lastAveragedThroughput;
531  }
532  } // end of wbCqi
533 
534  ueSet2.push_back(std::pair<double, uint16_t> (metric, (*it).first));
535  }
536  }// end of ueSet
537 
538  // sorting UE in ueSet1 and ueSet1 in descending order based on their metric value
539  std::sort (ueSet1.rbegin (), ueSet1.rend ());
540  std::sort (ueSet2.rbegin (), ueSet2.rend ());
541 
542  std::map <uint16_t, pssFlowPerf_t> tdUeSet;
543  uint32_t nMux;
544  if ( m_nMux > 0)
545  nMux = m_nMux;
546  else
547  {
548  // select half number of UE
549  if (ueSet1.size() + ueSet2.size() <=2 )
550  nMux = 1;
551  else
552  nMux = (int)((ueSet1.size() + ueSet2.size()) / 2) ; // TD scheduler only transfers half selected UE per RTT to TD scheduler
553  }
554  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it--)
555  {
556  std::vector <std::pair<double, uint16_t> >::iterator itSet;
557  for (itSet = ueSet1.begin (); itSet != ueSet1.end () && nMux != 0; itSet++)
558  {
559  std::map <uint16_t, pssFlowPerf_t>::iterator itUe;
560  itUe = m_flowStatsDl.find((*itSet).second);
561  tdUeSet.insert(std::pair<uint16_t, pssFlowPerf_t> ( (*itUe).first, (*itUe).second ) );
562  nMux--;
563  }
564 
565  if (nMux == 0)
566  break;
567 
568  for (itSet = ueSet2.begin (); itSet != ueSet2.end () && nMux != 0; itSet++)
569  {
570  std::map <uint16_t, pssFlowPerf_t>::iterator itUe;
571  itUe = m_flowStatsDl.find((*itSet).second);
572  tdUeSet.insert(std::pair<uint16_t, pssFlowPerf_t> ( (*itUe).first, (*itUe).second ) );
573  nMux--;
574  }
575 
576  if (nMux == 0)
577  break;
578 
579  } // end of m_flowStatsDl
580 
581  if ( m_fdSchedulerType.compare("CoItA") == 0)
582  {
583  // FD scheduler: Carrier over Interference to Average (CoItA)
584  std::map < uint16_t, uint8_t > sbCqiSum;
585  for (it = tdUeSet.begin (); it != tdUeSet.end (); it++)
586  {
587  uint8_t sum = 0;
588  for (int i = 0; i < rbgNum; i++)
589  {
590  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
591  itCqi = m_a30CqiRxed.find ((*it).first);
592  std::map <uint16_t,uint8_t>::iterator itTxMode;
593  itTxMode = m_uesTxMode.find ((*it).first);
594  if (itTxMode == m_uesTxMode.end ())
595  {
596  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
597  }
598  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
599  std::vector <uint8_t> sbCqis;
600  if (itCqi == m_a30CqiRxed.end ())
601  {
602  for (uint8_t k = 0; k < nLayer; k++)
603  {
604  sbCqis.push_back (1); // start with lowest value
605  }
606  }
607  else
608  {
609  sbCqis = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi;
610  }
611 
612  uint8_t cqi1 = sbCqis.at (0);
613  uint8_t cqi2 = 1;
614  if (sbCqis.size () > 1)
615  {
616  cqi2 = sbCqis.at (1);
617  }
618 
619  uint8_t sbCqi;
620  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
621  {
622  for (uint8_t k = 0; k < nLayer; k++)
623  {
624  if (sbCqis.size () > k)
625  {
626  sbCqi = sbCqis.at(k);
627  }
628  else
629  {
630  // no info on this subband
631  sbCqi = 0;
632  }
633  sum += sbCqi;
634  }
635  } // end if cqi
636  }// end of rbgNum
637 
638  sbCqiSum.insert (std::pair<uint16_t, uint8_t> ((*it).first, sum));
639  }// end tdUeSet
640 
641  for (int i = 0; i < rbgNum; i++)
642  {
643  std::map <uint16_t, pssFlowPerf_t>::iterator itMax = tdUeSet.end ();
644  double metricMax = 0.0;
645  for (it = tdUeSet.begin (); it != tdUeSet.end (); it++)
646  {
647  // calculate PF weigth
648  double weight = (*it).second.targetThroughput / (*it).second.lastAveragedThroughput;
649  if (weight < 1.0)
650  weight = 1.0;
651 
652  std::map < uint16_t, uint8_t>::iterator itSbCqiSum;
653  itSbCqiSum = sbCqiSum.find((*it).first);
654 
655  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
656  itCqi = m_a30CqiRxed.find ((*it).first);
657  std::map <uint16_t,uint8_t>::iterator itTxMode;
658  itTxMode = m_uesTxMode.find ((*it).first);
659  if (itTxMode == m_uesTxMode.end())
660  {
661  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
662  }
663  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
664  std::vector <uint8_t> sbCqis;
665  if (itCqi == m_a30CqiRxed.end ())
666  {
667  for (uint8_t k = 0; k < nLayer; k++)
668  {
669  sbCqis.push_back (1); // start with lowest value
670  }
671  }
672  else
673  {
674  sbCqis = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi;
675  }
676 
677  uint8_t cqi1 = sbCqis.at( 0);
678  uint8_t cqi2 = 1;
679  if (sbCqis.size () > 1)
680  {
681  cqi2 = sbCqis.at(1);
682  }
683 
684  uint8_t sbCqi;
685  double colMetric = 0.0;
686  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
687  {
688  for (uint8_t k = 0; k < nLayer; k++)
689  {
690  if (sbCqis.size () > k)
691  {
692  sbCqi = sbCqis.at(k);
693  }
694  else
695  {
696  // no info on this subband
697  sbCqi = 0;
698  }
699  colMetric += (double)sbCqi / (double)(*itSbCqiSum).second;
700  }
701  } // end if cqi
702 
703  double metric = 0.0;
704  if (colMetric != 0)
705  metric= weight * colMetric;
706  else
707  metric = 1;
708 
709  if (metric > metricMax )
710  {
711  metricMax = metric;
712  itMax = it;
713  }
714  } // end of tdUeSet
715 
716  if (itMax == m_flowStatsDl.end ())
717  {
718  // no UE available for downlink
719  return;
720  }
721  else
722  {
723  // assign all RBGs to this UE
724  std::vector <uint16_t> tempMap;
725  for (int i = 0; i < rbgNum; i++)
726  {
727  tempMap.push_back (i);
728  }
729  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
730  }
731  }// end of rbgNum
732 
733  }// end of CoIta
734 
735  if ( m_fdSchedulerType.compare("PFsch") == 0)
736  {
737  // FD scheduler: Proportional Fair scheduled (PFsch)
738  for (int i = 0; i < rbgNum; i++)
739  {
740  std::map <uint16_t, pssFlowPerf_t>::iterator itMax = tdUeSet.end ();
741  double metricMax = 0.0;
742  for (it = tdUeSet.begin (); it != tdUeSet.end (); it++)
743  {
744  // calculate PF weigth
745  double weight = (*it).second.targetThroughput / (*it).second.lastAveragedThroughput;
746  if (weight < 1.0)
747  weight = 1.0;
748 
749  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
750  itCqi = m_a30CqiRxed.find ((*it).first);
751  std::map <uint16_t,uint8_t>::iterator itTxMode;
752  itTxMode = m_uesTxMode.find ((*it).first);
753  if (itTxMode == m_uesTxMode.end())
754  {
755  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
756  }
757  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
758  std::vector <uint8_t> sbCqis;
759  if (itCqi == m_a30CqiRxed.end ())
760  {
761  for (uint8_t k = 0; k < nLayer; k++)
762  {
763  sbCqis.push_back (1); // start with lowest value
764  }
765  }
766  else
767  {
768  sbCqis = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi;
769  }
770 
771  uint8_t cqi1 = sbCqis.at(0);
772  uint8_t cqi2 = 1;
773  if (sbCqis.size () > 1)
774  {
775  cqi2 = sbCqis.at(1);
776  }
777 
778  double schMetric = 0.0;
779  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
780  {
781  double achievableRate = 0.0;
782  for (uint8_t k = 0; k < nLayer; k++)
783  {
784  uint8_t mcs = 0;
785  if (sbCqis.size () > k)
786  {
787  mcs = m_amc->GetMcsFromCqi (sbCqis.at (k));
788  }
789  else
790  {
791  // no info on this subband -> worst MCS
792  mcs = 0;
793  }
794  achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, rbgSize) / 8) / 0.001); // = TB size / TTI
795  }
796  schMetric = achievableRate / (*it).second.secondLastAveragedThroughput;
797  } // end if cqi
798 
799  double metric = 0.0;
800  metric= weight * schMetric;
801 
802  if (metric > metricMax )
803  {
804  metricMax = metric;
805  itMax = it;
806  }
807  } // end of tdUeSet
808 
809  if (itMax == m_flowStatsDl.end ())
810  {
811  // no UE available for downlink
812  return;
813  }
814  else
815  {
816  // assign all RBGs to this UE
817  std::vector <uint16_t> tempMap;
818  for (int i = 0; i < rbgNum; i++)
819  {
820  tempMap.push_back (i);
821  }
822  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
823  }
824 
825  }// end of rbgNum
826 
827  } // end of PFsch
828 
829 
830  // reset TTI stats of users
831  std::map <uint16_t, pssFlowPerf_t>::iterator itStats;
832  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
833  {
834  (*itStats).second.lastTtiBytesTransmitted = 0;
835  }
836 
837  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
838  // creating the correspondent DCIs
840  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
841  while (itMap != allocationMap.end ())
842  {
843  // create new BuildDataListElement_s for this LC
845  newEl.m_rnti = (*itMap).first;
846  // create the DlDciListElement_s
847  DlDciListElement_s newDci;
848  std::vector <struct RlcPduListElement_s> newRlcPduLe;
849  newDci.m_rnti = (*itMap).first;
850 
851  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
852  uint16_t rbgPerRnti = (*itMap).second.size ();
853  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
854  itCqi = m_a30CqiRxed.find ((*itMap).first);
855  std::map <uint16_t,uint8_t>::iterator itTxMode;
856  itTxMode = m_uesTxMode.find ((*itMap).first);
857  if (itTxMode == m_uesTxMode.end ())
858  {
859  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
860  }
861  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
862  std::vector <uint8_t> worstCqi (2, 15);
863  if (itCqi != m_a30CqiRxed.end ())
864  {
865  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
866  {
867  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
868  {
869  for (uint8_t j = 0; j < nLayer; j++)
870  {
871  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
872  {
873  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
874  {
875  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
876  }
877  }
878  else
879  {
880  // no CQI for this layer of this suband -> worst one
881  worstCqi.at (j) = 1;
882  }
883  }
884  }
885  else
886  {
887  for (uint8_t j = 0; j < nLayer; j++)
888  {
889  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
890  }
891  }
892  }
893  }
894  else
895  {
896  for (uint8_t j = 0; j < nLayer; j++)
897  {
898  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
899  }
900  }
901  uint32_t bytesTxed = 0;
902  for (uint8_t j = 0; j < nLayer; j++)
903  {
904  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
905  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (j), rbgPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
906  newDci.m_tbsSize.push_back (tbSize);
907  bytesTxed += tbSize;
908  }
909 
910  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
911  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
912  uint32_t rbgMask = 0;
913  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
914  {
915  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
916  }
917  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
918 
919  // create the rlc PDUs -> equally divide resources among actives LCs
920  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
921  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
922  {
923  if (((*itBufReq).first.m_rnti == (*itMap).first) &&
924  (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
925  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
926  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
927  {
928  for (uint8_t j = 0; j < nLayer; j++)
929  {
930  RlcPduListElement_s newRlcEl;
931  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
932  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
933  newRlcPduLe.push_back (newRlcEl);
934  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
935  }
936  }
937  if ((*itBufReq).first.m_rnti > (*itMap).first)
938  {
939  break;
940  }
941  }
942  newDci.m_ndi.push_back (1); // TBD (new data indicator)
943  newDci.m_rv.push_back (0); // TBD (redundancy version)
944 
945  newEl.m_dci = newDci;
946  // ...more parameters -> ingored in this version
947 
948  newEl.m_rlcPduList.push_back (newRlcPduLe);
949  ret.m_buildDataList.push_back (newEl);
950 
951  // update UE stats
952  std::map <uint16_t, pssFlowPerf_t>::iterator it;
953  it = m_flowStatsDl.find ((*itMap).first);
954  if (it != m_flowStatsDl.end ())
955  {
956  (*it).second.lastTtiBytesTransmitted = bytesTxed;
957  }
958  else
959  {
960  NS_LOG_DEBUG (this << " No Stats for this allocated UE");
961  }
962 
963  itMap++;
964  } // end while allocation
965  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
966 
967 
968  // update UEs stats
969  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
970  {
971  std::map <uint16_t, pssFlowPerf_t>::iterator itUeScheduleted = tdUeSet.end();
972  itUeScheduleted = tdUeSet.find((*itStats).first);
973  if (itUeScheduleted != tdUeSet.end())
974  {
975  (*itStats).second.secondLastAveragedThroughput = ((1.0 - (1 / m_timeWindow)) * (*itStats).second.secondLastAveragedThroughput) + ((1 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTransmitted / 0.001));
976  }
977 
978  (*itStats).second.totalBytesTransmitted += (*itStats).second.lastTtiBytesTransmitted;
979  // update average throughput (see eq. 12.3 of Sec 12.3.1.2 of LTE – The UMTS Long Term Evolution, Ed Wiley)
980  (*itStats).second.lastAveragedThroughput = ((1.0 - (1.0 / m_timeWindow)) * (*itStats).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTransmitted / 0.001));
981  (*itStats).second.lastTtiBytesTransmitted = 0;
982  }
983 
985 
986 
987  return;
988 }
989 
990 void
992 {
993  NS_FATAL_ERROR ("unimplemented");
994  return;
995 }
996 
997 void
999 {
1000  NS_LOG_FUNCTION (this);
1001 
1002  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1003  {
1004  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1005  {
1006  // wideband CQI reporting
1007  std::map <uint16_t,uint8_t>::iterator it;
1008  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1009  it = m_p10CqiRxed.find (rnti);
1010  if (it == m_p10CqiRxed.end ())
1011  {
1012  // create the new entry
1013  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)
1014  // generate correspondent timer
1015  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1016  }
1017  else
1018  {
1019  // update the CQI value and refresh correspondent timer
1020  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1021  // update correspondent timer
1022  std::map <uint16_t,uint32_t>::iterator itTimers;
1023  itTimers = m_p10CqiTimers.find (rnti);
1024  (*itTimers).second = m_cqiTimersThreshold;
1025  }
1026  }
1027  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1028  {
1029  // subband CQI reporting high layer configured
1030  std::map <uint16_t,SbMeasResult_s>::iterator it;
1031  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1032  it = m_a30CqiRxed.find (rnti);
1033  if (it == m_a30CqiRxed.end ())
1034  {
1035  // create the new entry
1036  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
1037  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1038  }
1039  else
1040  {
1041  // update the CQI value and refresh correspondent timer
1042  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
1043  std::map <uint16_t,uint32_t>::iterator itTimers;
1044  itTimers = m_a30CqiTimers.find (rnti);
1045  (*itTimers).second = m_cqiTimersThreshold;
1046  }
1047  }
1048  else
1049  {
1050  NS_LOG_ERROR (this << " CQI type unknown");
1051  }
1052  }
1053 
1054  return;
1055 }
1056 
1057 
1058 double
1059 PssFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
1060 {
1061  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
1062  if (itCqi == m_ueCqi.end ())
1063  {
1064  // no cqi info about this UE
1065  return (NO_SINR);
1066 
1067  }
1068  else
1069  {
1070  // take the average SINR value among the available
1071  double sinrSum = 0;
1072  int sinrNum = 0;
1073  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1074  {
1075  double sinr = (*itCqi).second.at (i);
1076  if (sinr != NO_SINR)
1077  {
1078  sinrSum += sinr;
1079  sinrNum++;
1080  }
1081  }
1082  double estimatedSinr = sinrSum / (double)sinrNum;
1083  // store the value
1084  (*itCqi).second.at (rb) = estimatedSinr;
1085  return (estimatedSinr);
1086  }
1087 }
1088 
1089 void
1091 {
1092  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
1093 
1094  RefreshUlCqiMaps ();
1095 
1096  std::map <uint16_t,uint32_t>::iterator it;
1097  int nflows = 0;
1098 
1099  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1100  {
1101  // remove old entries of this UE-LC
1102  if ((*it).second > 0)
1103  {
1104  nflows++;
1105  }
1106  }
1107 
1108  if (nflows == 0)
1109  {
1110  return ; // no flows to be scheduled
1111  }
1112 
1113 
1114  // Divide the resource equally among the active users
1115  int rbPerFlow = m_cschedCellConfig.m_ulBandwidth / nflows;
1116  if (rbPerFlow == 0)
1117  {
1118  rbPerFlow = 1; // at least 1 rbg per flow (till available resource)
1119  }
1120  int rbAllocated = 0;
1121 
1123  std::vector <uint16_t> rbgAllocationMap;
1124  if (m_nextRntiUl != 0)
1125  {
1126  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1127  {
1128  if ((*it).first == m_nextRntiUl)
1129  {
1130  break;
1131  }
1132  }
1133  if (it == m_ceBsrRxed.end ())
1134  {
1135  NS_LOG_ERROR (this << " no user found");
1136  }
1137  }
1138  else
1139  {
1140  it = m_ceBsrRxed.begin ();
1141  m_nextRntiUl = (*it).first;
1142  }
1143  do
1144  {
1145  if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth)
1146  {
1147  // limit to physical resources last resource assignment
1148  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1149  }
1150 
1151  UlDciListElement_s uldci;
1152  uldci.m_rnti = (*it).first;
1153  uldci.m_rbStart = rbAllocated;
1154  uldci.m_rbLen = rbPerFlow;
1155  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1156  int cqi = 0;
1157  if (itCqi == m_ueCqi.end ())
1158  {
1159  // no cqi info about this UE
1160  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1161  }
1162  else
1163  {
1164  // take the lowest CQI value (worst RB)
1165  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1166  if (minSinr == NO_SINR)
1167  {
1168  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
1169  }
1170  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1171  {
1172  double sinr = (*itCqi).second.at (i);
1173  if (sinr == NO_SINR)
1174  {
1175  sinr = EstimateUlSinr ((*it).first, i);
1176  }
1177  if ((*itCqi).second.at (i) < minSinr)
1178  {
1179  minSinr = (*itCqi).second.at (i);
1180  }
1181  }
1182 
1183  // translate SINR -> cqi: WILD ACK: same as DL
1184  double s = log2 ( 1 + (
1185  std::pow (10, minSinr / 10 ) /
1186  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1188  if (cqi == 0)
1189  {
1190  it++;
1191  if (it == m_ceBsrRxed.end ())
1192  {
1193  // restart from the first
1194  it = m_ceBsrRxed.begin ();
1195  }
1196  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1197  }
1198  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1199  }
1200 
1201  rbAllocated += rbPerFlow;
1202  // store info on allocation for managing ul-cqi interpretation
1203  for (int i = 0; i < rbPerFlow; i++)
1204  {
1205  rbgAllocationMap.push_back ((*it).first);
1206  }
1207  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
1208  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);
1209  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1210  uldci.m_ndi = 1;
1211  uldci.m_cceIndex = 0;
1212  uldci.m_aggrLevel = 1;
1213  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1214  uldci.m_hopping = false;
1215  uldci.m_n2Dmrs = 0;
1216  uldci.m_tpc = 0; // no power control
1217  uldci.m_cqiRequest = false; // only period CQI at this stage
1218  uldci.m_ulIndex = 0; // TDD parameter
1219  uldci.m_dai = 1; // TDD parameter
1220  uldci.m_freqHopping = 0;
1221  uldci.m_pdcchPowerOffset = 0; // not used
1222  ret.m_dciList.push_back (uldci);
1223 
1224 
1225  it++;
1226  if (it == m_ceBsrRxed.end ())
1227  {
1228  // restart from the first
1229  it = m_ceBsrRxed.begin ();
1230  }
1231  if (rbAllocated == m_cschedCellConfig.m_ulBandwidth)
1232  {
1233  // Stop allocation: no more PRBs
1234  m_nextRntiUl = (*it).first;
1235  break;
1236  }
1237  }
1238  while ((*it).first != m_nextRntiUl);
1239 
1240  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1242  return;
1243 }
1244 
1245 void
1247 {
1248  NS_FATAL_ERROR ("unimplemented");
1249  return;
1250 }
1251 
1252 void
1254 {
1255  NS_FATAL_ERROR ("unimplemented");
1256  return;
1257 }
1258 
1259 void
1261 {
1262  NS_LOG_FUNCTION (this);
1263 
1264  std::map <uint16_t,uint32_t>::iterator it;
1265 
1266  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1267  {
1268  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1269  {
1270  // buffer status report
1271  // note that we only consider LCG 0, the other three LCGs are neglected
1272  // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
1273  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1274  it = m_ceBsrRxed.find (rnti);
1275  if (it == m_ceBsrRxed.end ())
1276  {
1277  // create the new entry
1278  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
1279  int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1280  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1281  }
1282  else
1283  {
1284  // update the buffer size value
1285  (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
1286  }
1287  }
1288  }
1289 
1290  return;
1291 }
1292 
1293 void
1295 {
1296  NS_LOG_FUNCTION (this);
1297  // retrieve the allocation for this subframe
1298  switch (m_ulCqiFilter)
1299  {
1301  {
1302  // filter all the CQIs that are not SRS based
1303  if (params.m_ulCqi.m_type!=UlCqi_s::SRS)
1304  {
1305  return;
1306  }
1307  }
1308  break;
1310  {
1311  // filter all the CQIs that are not SRS based
1312  if (params.m_ulCqi.m_type!=UlCqi_s::PUSCH)
1313  {
1314  return;
1315  }
1316  }
1318  break;
1319 
1320  default:
1321  NS_FATAL_ERROR ("Unknown UL CQI type");
1322  }
1323 
1324  switch (params.m_ulCqi.m_type)
1325  {
1326  case UlCqi_s::PUSCH:
1327  {
1328  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1329  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1330  itMap = m_allocationMaps.find (params.m_sfnSf);
1331  if (itMap == m_allocationMaps.end ())
1332  {
1333  NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1334  return;
1335  }
1336  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1337  {
1338  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1339  // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
1340  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1341  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1342  if (itCqi == m_ueCqi.end ())
1343  {
1344  // create a new entry
1345  std::vector <double> newCqi;
1346  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1347  {
1348  if (i == j)
1349  {
1350  newCqi.push_back (sinr);
1351  }
1352  else
1353  {
1354  // initialize with NO_SINR value.
1355  newCqi.push_back (NO_SINR);
1356  }
1357 
1358  }
1359  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1360  // generate correspondent timer
1361  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1362  }
1363  else
1364  {
1365  // update the value
1366  (*itCqi).second.at (i) = sinr;
1367  // update correspondent timer
1368  std::map <uint16_t, uint32_t>::iterator itTimers;
1369  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1370  (*itTimers).second = m_cqiTimersThreshold;
1371 
1372  }
1373 
1374  }
1375  // remove obsolete info on allocation
1376  m_allocationMaps.erase (itMap);
1377  }
1378  break;
1379  case UlCqi_s::SRS:
1380  {
1381  // get the RNTI from vendor specific parameters
1382  uint16_t rnti = 0;
1383  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1384  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1385  {
1386  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1387  {
1388  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1389  rnti = vsp->GetRnti ();
1390  }
1391  }
1392  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1393  itCqi = m_ueCqi.find (rnti);
1394  if (itCqi == m_ueCqi.end ())
1395  {
1396  // create a new entry
1397  std::vector <double> newCqi;
1398  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1399  {
1400  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1401  newCqi.push_back (sinr);
1402  NS_LOG_DEBUG (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1403 
1404  }
1405  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1406  // generate correspondent timer
1407  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1408  }
1409  else
1410  {
1411  // update the values
1412  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1413  {
1414  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1415  (*itCqi).second.at (j) = sinr;
1416  NS_LOG_DEBUG (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1417  }
1418  // update correspondent timer
1419  std::map <uint16_t, uint32_t>::iterator itTimers;
1420  itTimers = m_ueCqiTimers.find (rnti);
1421  (*itTimers).second = m_cqiTimersThreshold;
1422 
1423  }
1424 
1425 
1426  }
1427  break;
1428  case UlCqi_s::PUCCH_1:
1429  case UlCqi_s::PUCCH_2:
1430  case UlCqi_s::PRACH:
1431  {
1432  NS_FATAL_ERROR ("PssFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1433  }
1434  break;
1435  default:
1436  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1437  }
1438  return;
1439 }
1440 
1441 void
1443 {
1444  // refresh DL CQI P01 Map
1445  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1446  while (itP10!=m_p10CqiTimers.end ())
1447  {
1448 // NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1449  if ((*itP10).second == 0)
1450  {
1451  // delete correspondent entries
1452  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1453  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1454  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1455  m_p10CqiRxed.erase (itMap);
1456  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1457  itP10++;
1458  m_p10CqiTimers.erase (temp);
1459  }
1460  else
1461  {
1462  (*itP10).second--;
1463  itP10++;
1464  }
1465  }
1466 
1467  // refresh DL CQI A30 Map
1468  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
1469  while (itA30!=m_a30CqiTimers.end ())
1470  {
1471 // NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1472  if ((*itA30).second == 0)
1473  {
1474  // delete correspondent entries
1475  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
1476  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
1477  NS_LOG_INFO (this << " A30-CQI exired for user " << (*itA30).first);
1478  m_a30CqiRxed.erase (itMap);
1479  std::map <uint16_t,uint32_t>::iterator temp = itA30;
1480  itA30++;
1481  m_a30CqiTimers.erase (temp);
1482  }
1483  else
1484  {
1485  (*itA30).second--;
1486  itA30++;
1487  }
1488  }
1489 
1490  return;
1491 }
1492 
1493 
1494 void
1496 {
1497  // refresh UL CQI Map
1498  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1499  while (itUl!=m_ueCqiTimers.end ())
1500  {
1501 // NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1502  if ((*itUl).second == 0)
1503  {
1504  // delete correspondent entries
1505  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1506  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1507  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1508  (*itMap).second.clear ();
1509  m_ueCqi.erase (itMap);
1510  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1511  itUl++;
1512  m_ueCqiTimers.erase (temp);
1513  }
1514  else
1515  {
1516  (*itUl).second--;
1517  itUl++;
1518  }
1519  }
1520 
1521  return;
1522 }
1523 
1524 void
1525 PssFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1526 {
1527  size = size - 2; // remove the minimum RLC overhead
1528  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1529  LteFlowId_t flow (rnti, lcid);
1530  it = m_rlcBufferReq.find (flow);
1531  if (it!=m_rlcBufferReq.end ())
1532  {
1533  // Update queues: RLC tx order Status, ReTx, Tx
1534  // Update status queue
1535  if ((*it).second.m_rlcStatusPduSize <= size)
1536  {
1537  size -= (*it).second.m_rlcStatusPduSize;
1538  (*it).second.m_rlcStatusPduSize = 0;
1539  }
1540  else
1541  {
1542  (*it).second.m_rlcStatusPduSize -= size;
1543  return;
1544  }
1545  // update retransmission queue
1546  if ((*it).second.m_rlcRetransmissionQueueSize <= size)
1547  {
1548  size -= (*it).second.m_rlcRetransmissionQueueSize;
1549  (*it).second.m_rlcRetransmissionQueueSize = 0;
1550  }
1551  else
1552  {
1553  (*it).second.m_rlcRetransmissionQueueSize -= size;
1554  return;
1555  }
1556  // update transmission queue
1557  if ((*it).second.m_rlcTransmissionQueueSize <= size)
1558  {
1559  size -= (*it).second.m_rlcTransmissionQueueSize;
1560  (*it).second.m_rlcTransmissionQueueSize = 0;
1561  }
1562  else
1563  {
1564  (*it).second.m_rlcTransmissionQueueSize -= size;
1565  return;
1566  }
1567  }
1568  else
1569  {
1570  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
1571  }
1572 }
1573 
1574 void
1575 PssFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1576 {
1577 
1578  size = size - 2; // remove the minimum RLC overhead
1579  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1580  if (it!=m_ceBsrRxed.end ())
1581  {
1582  if ((*it).second >= size)
1583  {
1584  (*it).second -= size;
1585  }
1586  else
1587  {
1588  (*it).second = 0;
1589  }
1590  }
1591  else
1592  {
1593  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1594  }
1595 
1596 }
1597 
1598 void
1600 {
1601  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1603  params.m_rnti = rnti;
1604  params.m_transmissionMode = txMode;
1606 }
1607 
1608 
1609 }