A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
rr-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/lte-amc.h>
29 #include <ns3/rr-ff-mac-scheduler.h>
30 #include <ns3/simulator.h>
31 #include <ns3/lte-common.h>
32 
33 NS_LOG_COMPONENT_DEFINE ("RrFfMacScheduler");
34 
35 namespace ns3 {
36 
38  10, // RGB size 1
39  26, // RGB size 2
40  63, // RGB size 3
41  110 // RGB size 4
42 }; // see table 7.1.6.1-1 of 36.213
43 
44 
45 
46 
47 NS_OBJECT_ENSURE_REGISTERED (RrFfMacScheduler);
48 
49 
51 {
52 public:
54 
55  // inherited from FfMacCschedSapProvider
56  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
57  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
58  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
59  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
60  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
61 
62 private:
65 };
66 
68 {
69 }
70 
72 {
73 }
74 
75 
76 void
78 {
80 }
81 
82 void
84 {
86 }
87 
88 
89 void
91 {
93 }
94 
95 void
97 {
99 }
100 
101 void
103 {
105 }
106 
107 
108 
109 
111 {
112 public:
114 
115  // inherited from FfMacSchedSapProvider
116  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
117  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
118  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
119  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
120  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
121  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
122  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
123  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
124  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
125  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
126  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
127 
128 
129 private:
132 };
133 
134 
135 
137 {
138 }
139 
140 
142  : m_scheduler (scheduler)
143 {
144 }
145 
146 void
148 {
150 }
151 
152 void
154 {
156 }
157 
158 void
160 {
162 }
163 
164 void
166 {
168 }
169 
170 void
172 {
174 }
175 
176 void
178 {
180 }
181 
182 void
184 {
186 }
187 
188 void
190 {
192 }
193 
194 void
196 {
198 }
199 
200 void
202 {
204 }
205 
206 void
208 {
210 }
211 
212 
213 
214 
215 
217  : m_cschedSapUser (0),
218  m_schedSapUser (0),
219  m_nextRntiDl (0),
220  m_nextRntiUl (0)
221 {
222  m_amc = CreateObject <LteAmc> ();
225 }
226 
228 {
229  NS_LOG_FUNCTION (this);
230 }
231 
232 void
234 {
235  NS_LOG_FUNCTION (this);
236  delete m_cschedSapProvider;
237  delete m_schedSapProvider;
238 }
239 
240 TypeId
242 {
243  static TypeId tid = TypeId ("ns3::RrFfMacScheduler")
245  .AddConstructor<RrFfMacScheduler> ()
246  .AddAttribute ("CqiTimerThreshold",
247  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
248  UintegerValue (1000),
249  MakeUintegerAccessor (&RrFfMacScheduler::m_cqiTimersThreshold),
250  MakeUintegerChecker<uint32_t> ())
251  ;
252  return tid;
253 }
254 
255 
256 
257 void
259 {
260  m_cschedSapUser = s;
261 }
262 
263 void
265 {
266  m_schedSapUser = s;
267 }
268 
271 {
272  return m_cschedSapProvider;
273 }
274 
277 {
278  return m_schedSapProvider;
279 }
280 
281 void
283 {
284  NS_LOG_FUNCTION (this);
285  // Read the subset of parameters used
286  m_cschedCellConfig = params;
288  cnf.m_result = SUCCESS;
290  return;
291 }
292 
293 void
295 {
296  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
297  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
298  if (it==m_uesTxMode.end ())
299  {
300  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
301  }
302  else
303  {
304  (*it).second = params.m_transmissionMode;
305  }
306  return;
307 }
308 
309 void
311 {
312  NS_LOG_FUNCTION (this);
313  // Not used at this stage
314  return;
315 }
316 
317 void
319 {
320  NS_LOG_FUNCTION (this);
321  // TODO: Implementation of the API
322  return;
323 }
324 
325 void
327 {
328  NS_LOG_FUNCTION (this);
329  // TODO: Implementation of the API
330  return;
331 }
332 
333 
334 void
336 {
337  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
338  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
339  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
340  bool newLc = true;
341  while (it != m_rlcBufferReq.end ())
342  {
343  // remove old entries of this UE-LC
344  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity))
345  {
346  it = m_rlcBufferReq.erase (it);
347  newLc = false;
348  }
349  else
350  {
351  ++it;
352  }
353  }
354  // add the new parameters
355  m_rlcBufferReq.insert (it, params);
356  // initialize statistics of the flow in case of new flows
357  if (newLc == true)
358  {
359  m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (params.m_rnti, 1)); // only codeword 0 at this stage (SISO)
360  // initialized to 1 (i.e., the lowest value for transmitting a signal)
361  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (params.m_rnti, m_cqiTimersThreshold));
362  }
363 
364  return;
365 }
366 
367 void
369 {
370  NS_LOG_FUNCTION (this);
371  // TODO: Implementation of the API
372  return;
373 }
374 
375 void
377 {
378  NS_LOG_FUNCTION (this);
379  // TODO: Implementation of the API
380  return;
381 }
382 
383 int
385 {
386  for (int i = 0; i < 4; i++)
387  {
388  if (dlbandwidth < Type0AllocationRbg[i])
389  {
390  return (i + 1);
391  }
392  }
393 
394  return (-1);
395 }
396 
397 bool
399 {
400  return (i.m_rnti<j.m_rnti);
401 }
402 
403 
404 void
406 {
407  NS_LOG_FUNCTION (this << " DL Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
408  // API generated by RLC for triggering the scheduling of a DL subframe
409 
410  RefreshDlCqiMaps ();
411 
412  // Get the actual active flows (queue!=0)
413  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
415  int nflows = 0;
416  int nTbs = 0;
417  std::map <uint16_t,uint8_t> lcActivesPerRnti;
418  std::map <uint16_t,uint8_t>::iterator itLcRnti;
419  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
420  {
421 // NS_LOG_INFO (this << " User " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
422  // remove old entries of this UE-LC
423  if ( ((*it).m_rlcTransmissionQueueSize > 0)
424  || ((*it).m_rlcRetransmissionQueueSize > 0)
425  || ((*it).m_rlcStatusPduSize > 0) )
426  {
427  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find ((*it).m_rnti);
428  uint8_t cqi = 0;
429  if (itCqi != m_p10CqiRxed.end ())
430  {
431  cqi = (*itCqi).second;
432  }
433  else
434  {
435  cqi = 1; // lowest value fro trying a transmission
436  }
437  if (cqi != 0)
438  {
439  // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
440  nflows++;
441  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
442  if (itLcRnti != lcActivesPerRnti.end ())
443  {
444  (*itLcRnti).second++;
445  }
446  else
447  {
448  lcActivesPerRnti.insert (std::pair<uint16_t, uint8_t > ((*it).m_rnti, 1));
449  nTbs++;
450  }
451 
452  }
453  }
454  }
455 
456  if (nflows == 0)
457  {
458  return;
459  }
460  // Divide the resource equally among the active users according to
461  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
463  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
464  int rbgPerTb = rbgNum / nTbs;
465  if (rbgPerTb == 0)
466  {
467  rbgPerTb = 1; // at least 1 rbg per TB (till available resource)
468  }
469  int rbgAllocated = 0;
470 
472  // round robin assignment to all UE-LC registered starting from the subsequent of the one
473  // served last scheduling trigger
474  //NS_LOG_DEBUG (this << " next to be served " << m_nextRntiDl << " nflows " << nflows);
475  if (m_nextRntiDl != 0)
476  {
477  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
478  {
479  if ((*it).m_rnti == m_nextRntiDl)
480  {
481  break;
482  }
483  }
484 
485  if (it == m_rlcBufferReq.end ())
486  {
487  NS_LOG_ERROR (this << " no user found");
488  }
489  }
490  else
491  {
492  it = m_rlcBufferReq.begin ();
493  m_nextRntiDl = (*it).m_rnti;
494  }
495  std::map <uint16_t,uint8_t>::iterator itTxMode;
496  do
497  {
498  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
499  if (itLcRnti == lcActivesPerRnti.end ())
500  {
501  // skip this entry
502  it++;
503  if (it == m_rlcBufferReq.end ())
504  {
505  // restart from the first
506  it = m_rlcBufferReq.begin ();
507  }
508  continue;
509  }
510  itTxMode = m_uesTxMode.find ((*it).m_rnti);
511  if (itTxMode == m_uesTxMode.end())
512  {
513  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).m_rnti);
514  }
515  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
516  int lcNum = (*itLcRnti).second;
517  // create new BuildDataListElement_s for this RNTI
519  newEl.m_rnti = (*it).m_rnti;
520  // create the DlDciListElement_s
521  DlDciListElement_s newDci;
522  newDci.m_rnti = (*it).m_rnti;
523  newDci.m_resAlloc = 0;
524  newDci.m_rbBitmap = 0;
525  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find (newEl.m_rnti);
526  for (uint8_t i = 0; i < nLayer; i++)
527  {
528  if (itCqi == m_p10CqiRxed.end ())
529  {
530  newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS
531  }
532  else
533  {
534  newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) );
535  }
536  }
537  // group the LCs of this RNTI
538  std::vector <struct RlcPduListElement_s> newRlcPduLe;
539 // int totRbg = lcNum * rbgPerFlow;
540 // totRbg = rbgNum / nTbs;
541  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
542  NS_LOG_DEBUG (this << "Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " PRBs " << rbgAllocated * rbgSize << "..." << (rbgAllocated* rbgSize) + (rbgPerTb * rbgSize) - 1 << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " layers " << nLayer);
543  uint16_t rlcPduSize = tbSize / lcNum;
544  for (int i = 0; i < lcNum ; i++)
545  {
546  for (uint8_t j = 0; j < nLayer; j++)
547  {
548  RlcPduListElement_s newRlcEl;
549  newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
550 // NS_LOG_DEBUG (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
551  newRlcEl.m_size = rlcPduSize;
552  UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
553  newRlcPduLe.push_back (newRlcEl);
554  }
555  it++;
556  if (it == m_rlcBufferReq.end ())
557  {
558  // restart from the first
559  it = m_rlcBufferReq.begin ();
560  }
561  }
562  uint32_t rbgMask = 0;
563  for (int i = 0; i < rbgPerTb; i++)
564  {
565  rbgMask = rbgMask + (0x1 << rbgAllocated);
566  rbgAllocated++;
567  }
568  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
569 
570  for (int i = 0; i < nLayer; i++)
571  {
572  newDci.m_tbsSize.push_back (tbSize);
573  newDci.m_ndi.push_back (1); // TBD (new data indicator)
574  newDci.m_rv.push_back (0); // TBD (redundancy version)
575  }
576  newEl.m_dci = newDci;
577  // ...more parameters -> ignored in this version
578 
579 
580 
581 
582  newEl.m_rlcPduList.push_back (newRlcPduLe);
583  ret.m_buildDataList.push_back (newEl);
584  if (rbgAllocated == rbgNum)
585  {
586  //NS_LOG_DEBUG (this << " FULL " << (*it).m_rnti);
587  m_nextRntiDl = (*it).m_rnti; // store last RNTI served
588  break; // no more RGB to be allocated
589  }
590  }
591  while ((*it).m_rnti != m_nextRntiDl);
592 
593  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
594 
596  return;
597 }
598 
599 void
601 {
602  NS_LOG_FUNCTION (this);
603  // TODO: Implementation of the API
604  return;
605 }
606 
607 void
609 {
610  NS_LOG_FUNCTION (this);
611 
612  std::map <uint16_t,uint8_t>::iterator it;
613  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
614  {
615  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
616  {
617  // wideband CQI reporting
618  std::map <uint16_t,uint8_t>::iterator it;
619  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
620  it = m_p10CqiRxed.find (rnti);
621  if (it == m_p10CqiRxed.end ())
622  {
623  // create the new entry
624  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)
625  // generate correspondent timer
626  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
627  }
628  else
629  {
630  // update the CQI value
631  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
632  // update correspondent timer
633  std::map <uint16_t,uint32_t>::iterator itTimers;
634  itTimers = m_p10CqiTimers.find (rnti);
635  (*itTimers).second = m_cqiTimersThreshold;
636  }
637  }
638  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
639  {
640  // subband CQI reporting high layer configured
641  // Not used by RR Scheduler
642  }
643  else
644  {
645  NS_LOG_ERROR (this << " CQI type unknown");
646  }
647  }
648 
649  return;
650 }
651 
652 void
654 {
655  NS_LOG_FUNCTION (this << " Ul - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
656 
657 
658  RefreshUlCqiMaps ();
659 
660  std::map <uint16_t,uint32_t>::iterator it;
661  int nflows = 0;
662 
663  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
664  {
665  // remove old entries of this UE-LC
666  if ((*it).second > 0)
667  {
668  nflows++;
669  }
670  }
671 
672  if (nflows == 0)
673  {
674  return ; // no flows to be scheduled
675  }
676 
677 
678  // Divide the resource equally among the active users starting from the subsequent one served last scheduling trigger
679  int rbPerFlow = m_cschedCellConfig.m_ulBandwidth / nflows;
680  if (rbPerFlow == 0)
681  {
682  rbPerFlow = 1; // at least 1 rbg per flow (till available resource)
683  }
684  int rbAllocated = 0;
685 
687  std::vector <uint16_t> rbgAllocationMap;
688  if (m_nextRntiUl != 0)
689  {
690  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
691  {
692  if ((*it).first == m_nextRntiUl)
693  {
694  break;
695  }
696  }
697  if (it == m_ceBsrRxed.end ())
698  {
699  NS_LOG_ERROR (this << " no user found");
700  }
701  }
702  else
703  {
704  it = m_ceBsrRxed.begin ();
705  m_nextRntiUl = (*it).first;
706  }
707  do
708  {
709  if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth)
710  {
711  // limit to physical resources last resource assignment
712  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
713  }
714 
715  UlDciListElement_s uldci;
716  uldci.m_rnti = (*it).first;
717  uldci.m_rbStart = rbAllocated;
718  uldci.m_rbLen = rbPerFlow;
719  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
720  int cqi = 0;
721  if (itCqi == m_ueCqi.end ())
722  {
723  // no cqi info about this UE
724  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
725  NS_LOG_DEBUG (this << " UE does not have ULCQI " << (*it).first );
726  }
727  else
728  {
729  // take the lowest CQI value (worst RB)
730  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
731  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
732  {
733  if ((*itCqi).second.at (i) < minSinr)
734  {
735  minSinr = (*itCqi).second.at (i);
736  }
737  }
738  // translate SINR -> cqi: WILD ACK: same as DL
739  double s = log2 ( 1 + (
740  pow (10, minSinr / 10 ) /
741  ( (-log (5.0 * 0.00005 )) / 1.5) ));
742 
743 
745  if (cqi == 0)
746  {
747  it++;
748  if (it == m_ceBsrRxed.end ())
749  {
750  // restart from the first
751  it = m_ceBsrRxed.begin ();
752  }
753  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
754  }
755  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
756 // NS_LOG_DEBUG (this << " UE " << (*it).first << " minsinr " << minSinr << " -> mcs " << (uint16_t)uldci.m_mcs);
757 
758  }
759 
760  rbAllocated += rbPerFlow;
761  // store info on allocation for managing ul-cqi interpretation
762  for (int i = 0; i < rbPerFlow; i++)
763  {
764  rbgAllocationMap.push_back ((*it).first);
765  }
766 
767  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD
768  NS_LOG_DEBUG (this << " UL - 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);
769  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
770  uldci.m_ndi = 1;
771  uldci.m_cceIndex = 0;
772  uldci.m_aggrLevel = 1;
773  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
774  uldci.m_hopping = false;
775  uldci.m_n2Dmrs = 0;
776  uldci.m_tpc = 0; // no power control
777  uldci.m_cqiRequest = false; // only period CQI at this stage
778  uldci.m_ulIndex = 0; // TDD parameter
779  uldci.m_dai = 1; // TDD parameter
780  uldci.m_freqHopping = 0;
781  uldci.m_pdcchPowerOffset = 0; // not used
782  ret.m_dciList.push_back (uldci);
783  it++;
784  if (it == m_ceBsrRxed.end ())
785  {
786  // restart from the first
787  it = m_ceBsrRxed.begin ();
788  }
789  if (rbAllocated == m_cschedCellConfig.m_ulBandwidth)
790  {
791  // Stop allocation: no more PRBs
792  m_nextRntiUl = (*it).first;
793  break;
794  }
795  }
796  while ((*it).first != m_nextRntiUl);
797  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
799  return;
800 }
801 
802 void
804 {
805  NS_LOG_FUNCTION (this);
806  // TODO: Implementation of the API
807  return;
808 }
809 
810 void
812 {
813  NS_LOG_FUNCTION (this);
814  // TODO: Implementation of the API
815  return;
816 }
817 
818 void
820 {
821  NS_LOG_FUNCTION (this);
822 
823  std::map <uint16_t,uint32_t>::iterator it;
824 
825  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
826  {
827  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
828  {
829  // buffer status report
830  // note that we only consider LCG 0, the other three LCGs are neglected
831  // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
832  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
833  it = m_ceBsrRxed.find (rnti);
834  if (it == m_ceBsrRxed.end ())
835  {
836  // create the new entry
837  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
838  int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
839  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
840  }
841  else
842  {
843  // update the buffer size value
844  (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
845  }
846  }
847  }
848 
849  return;
850 }
851 
852 void
854 {
855  NS_LOG_FUNCTION (this);
856  NS_LOG_DEBUG (this << " RX SFNID " << params.m_sfnSf);
857 // NS_LOG_DEBUG (this << " Actual sfn " << frameNo << " sbfn " << subframeNo << " sfnSf " << sfnSf);
858  // retrieve the allocation for this subframe
859  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
860  std::map <uint16_t, std::vector <double> >::iterator itCqi;
861  itMap = m_allocationMaps.find (params.m_sfnSf);
862  if (itMap == m_allocationMaps.end ())
863  {
864  NS_LOG_DEBUG (this << " Does not find info on allocation");
865  return;
866  }
867  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
868  {
869  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
870  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
871 // NS_LOG_DEBUG (this << " RB " << i << "UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr);
872  itCqi = m_ueCqi.find ((*itMap).second.at (i));
873  if (itCqi == m_ueCqi.end ())
874  {
875  // create a new entry
876  std::vector <double> newCqi;
877  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
878  {
879  if (i == j)
880  {
881  newCqi.push_back (sinr);
882  }
883  else
884  {
885  // initialize with maximum value according to the fixed point notation
886  newCqi.push_back (30.0);
887  }
888 
889  }
890  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
891  // generate correspondent timer
892  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
893  }
894  else
895  {
896  // update the value
897  (*itCqi).second.at (i) = sinr;
898  // update correspondent timer
899  std::map <uint16_t, uint32_t>::iterator itTimers;
900  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
901  (*itTimers).second = m_cqiTimersThreshold;
902  }
903 
904  }
905  // remove obsolete info on allocation
906  m_allocationMaps.erase (itMap);
907 
908  return;
909 }
910 
911 
912 void
914 {
915  NS_LOG_FUNCTION (this << m_p10CqiTimers.size ());
916  // refresh DL CQI P01 Map
917  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
918  while (itP10!=m_p10CqiTimers.end ())
919  {
920  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
921  if ((*itP10).second == 0)
922  {
923  // delete correspondent entries
924  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
925  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
926  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
927  m_p10CqiRxed.erase (itMap);
928  std::map <uint16_t,uint32_t>::iterator temp = itP10;
929  itP10++;
930  m_p10CqiTimers.erase (temp);
931  }
932  else
933  {
934  (*itP10).second--;
935  itP10++;
936  }
937  }
938 
939  return;
940 }
941 
942 
943 void
945 {
946  // refresh UL CQI Map
947  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
948  while (itUl!=m_ueCqiTimers.end ())
949  {
950  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
951  if ((*itUl).second == 0)
952  {
953  // delete correspondent entries
954  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
955  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
956  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
957  (*itMap).second.clear ();
958  m_ueCqi.erase (itMap);
959  std::map <uint16_t,uint32_t>::iterator temp = itUl;
960  itUl++;
961  m_ueCqiTimers.erase (temp);
962  }
963  else
964  {
965  (*itUl).second--;
966  itUl++;
967  }
968  }
969 
970  return;
971 }
972 
973 void
974 RrFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
975 {
976  size = size - 2; // remove the minimum RLC overhead
977  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
978  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
979  {
980  if (((*it).m_rnti == rnti) && ((*it).m_logicalChannelIdentity))
981  {
982 // NS_LOG_DEBUG (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).m_rlcTransmissionQueueSize << " retxqueue " << (*it).m_rlcRetransmissionQueueSize << " status " << (*it).m_rlcStatusPduSize << " decrease " << size);
983  // Update queues: RLC tx order Status, ReTx, Tx
984  // Update status queue
985  if ((*it).m_rlcStatusPduSize <= size)
986  {
987  size -= (*it).m_rlcStatusPduSize;
988  (*it).m_rlcStatusPduSize = 0;
989  }
990  else
991  {
992  (*it).m_rlcStatusPduSize -= size;
993  return;
994  }
995  // update retransmission queue
996  if ((*it).m_rlcRetransmissionQueueSize <= size)
997  {
998  size -= (*it).m_rlcRetransmissionQueueSize;
999  (*it).m_rlcRetransmissionQueueSize = 0;
1000  }
1001  else
1002  {
1003  (*it).m_rlcRetransmissionQueueSize -= size;
1004  return;
1005  }
1006  // update transmission queue
1007  if ((*it).m_rlcTransmissionQueueSize <= size)
1008  {
1009  size -= (*it).m_rlcTransmissionQueueSize;
1010  (*it).m_rlcTransmissionQueueSize = 0;
1011  }
1012  else
1013  {
1014  (*it).m_rlcTransmissionQueueSize -= size;
1015  return;
1016  }
1017  return;
1018  }
1019  }
1020 }
1021 
1022 void
1023 RrFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1024 {
1025 
1026  size = size - 2; // remove the minimum RLC overhead
1027  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1028  if (it!=m_ceBsrRxed.end ())
1029  {
1030 // NS_LOG_DEBUG (this << " Update RLC BSR UE " << rnti << " size " << size << " BSR " << (*it).second);
1031  if ((*it).second >= size)
1032  {
1033  (*it).second -= size;
1034  }
1035  else
1036  {
1037  (*it).second = 0;
1038  }
1039  }
1040  else
1041  {
1042  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1043  }
1044 
1045 }
1046 
1047 
1048 void
1050 {
1051  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1053  params.m_rnti = rnti;
1054  params.m_transmissionMode = txMode;
1056 }
1057 
1058 
1059 
1060 }