A Discrete-Event Network Simulator
API
tdtbfq-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  * 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/math.h>
25 
26 #include <ns3/simulator.h>
27 #include <ns3/lte-amc.h>
28 #include <ns3/tdtbfq-ff-mac-scheduler.h>
29 #include <ns3/lte-vendor-specific-parameters.h>
30 #include <ns3/boolean.h>
31 #include <ns3/integer.h>
32 #include <set>
33 #include <cfloat>
34 
35 namespace ns3 {
36 
37 NS_LOG_COMPONENT_DEFINE ("TdTbfqFfMacScheduler");
38 
39 static const int TdTbfqType0AllocationRbg[4] = {
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 
47 NS_OBJECT_ENSURE_REGISTERED (TdTbfqFfMacScheduler);
48 
49 
50 
52 {
53 public:
55 
56  // inherited from FfMacCschedSapProvider
57  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
58  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
59  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
60  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
61  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
62 
63 private:
66 };
67 
69 {
70 }
71 
73 {
74 }
75 
76 
77 void
79 {
81 }
82 
83 void
85 {
87 }
88 
89 
90 void
92 {
94 }
95 
96 void
98 {
100 }
101 
102 void
104 {
106 }
107 
108 
109 
110 
112 {
113 public:
115 
116  // inherited from FfMacSchedSapProvider
117  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
118  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
119  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
120  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
121  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
122  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
123  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
124  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
125  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
126  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
127  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
128 
129 
130 private:
133 };
134 
135 
136 
138 {
139 }
140 
141 
143  : m_scheduler (scheduler)
144 {
145 }
146 
147 void
149 {
151 }
152 
153 void
155 {
157 }
158 
159 void
161 {
163 }
164 
165 void
167 {
169 }
170 
171 void
173 {
175 }
176 
177 void
179 {
181 }
182 
183 void
185 {
187 }
188 
189 void
191 {
193 }
194 
195 void
197 {
199 }
200 
201 void
203 {
205 }
206 
207 void
209 {
211 }
212 
213 
214 
215 
216 
218  : m_cschedSapUser (0),
219  m_schedSapUser (0),
220  m_nextRntiUl (0),
221  bankSize (0)
222 {
223  m_amc = CreateObject <LteAmc> ();
226  m_ffrSapProvider = 0;
228 }
229 
231 {
232  NS_LOG_FUNCTION (this);
233 }
234 
235 void
237 {
238  NS_LOG_FUNCTION (this);
240  m_dlHarqProcessesTimer.clear ();
242  m_dlInfoListBuffered.clear ();
243  m_ulHarqCurrentProcessId.clear ();
244  m_ulHarqProcessesStatus.clear ();
246  delete m_cschedSapProvider;
247  delete m_schedSapProvider;
248  delete m_ffrSapUser;
249 }
250 
251 TypeId
253 {
254  static TypeId tid = TypeId ("ns3::TdTbfqFfMacScheduler")
256  .SetGroupName("Lte")
257  .AddConstructor<TdTbfqFfMacScheduler> ()
258  .AddAttribute ("CqiTimerThreshold",
259  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
260  UintegerValue (1000),
262  MakeUintegerChecker<uint32_t> ())
263  .AddAttribute ("DebtLimit",
264  "Flow debt limit (default -625000 bytes)",
265  IntegerValue (-625000),
267  MakeIntegerChecker<int> ())
268  .AddAttribute ("CreditLimit",
269  "Flow credit limit (default 625000 bytes)",
270  UintegerValue (625000),
272  MakeUintegerChecker<uint32_t> ())
273  .AddAttribute ("TokenPoolSize",
274  "The maximum value of flow token pool (default 1 bytes)",
275  UintegerValue (1),
277  MakeUintegerChecker<uint32_t> ())
278  .AddAttribute ("CreditableThreshold",
279  "Threshold of flow credit (default 0 bytes)",
280  UintegerValue (0),
282  MakeUintegerChecker<uint32_t> ())
283 
284  .AddAttribute ("HarqEnabled",
285  "Activate/Deactivate the HARQ [by default is active].",
286  BooleanValue (true),
289  .AddAttribute ("UlGrantMcs",
290  "The MCS of the UL grant, must be [0..15] (default 0)",
291  UintegerValue (0),
293  MakeUintegerChecker<uint8_t> ())
294  ;
295  return tid;
296 }
297 
298 
299 
300 void
302 {
303  m_cschedSapUser = s;
304 }
305 
306 void
308 {
309  m_schedSapUser = s;
310 }
311 
314 {
315  return m_cschedSapProvider;
316 }
317 
320 {
321  return m_schedSapProvider;
322 }
323 
324 void
326 {
327  m_ffrSapProvider = s;
328 }
329 
332 {
333  return m_ffrSapUser;
334 }
335 
336 void
338 {
339  NS_LOG_FUNCTION (this);
340  // Read the subset of parameters used
341  m_cschedCellConfig = params;
344  cnf.m_result = SUCCESS;
346  return;
347 }
348 
349 void
351 {
352  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
353  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
354  if (it == m_uesTxMode.end ())
355  {
356  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
357  // generate HARQ buffers
358  m_dlHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
359  DlHarqProcessesStatus_t dlHarqPrcStatus;
360  dlHarqPrcStatus.resize (8,0);
361  m_dlHarqProcessesStatus.insert (std::pair <uint16_t, DlHarqProcessesStatus_t> (params.m_rnti, dlHarqPrcStatus));
362  DlHarqProcessesTimer_t dlHarqProcessesTimer;
363  dlHarqProcessesTimer.resize (8,0);
364  m_dlHarqProcessesTimer.insert (std::pair <uint16_t, DlHarqProcessesTimer_t> (params.m_rnti, dlHarqProcessesTimer));
365  DlHarqProcessesDciBuffer_t dlHarqdci;
366  dlHarqdci.resize (8);
367  m_dlHarqProcessesDciBuffer.insert (std::pair <uint16_t, DlHarqProcessesDciBuffer_t> (params.m_rnti, dlHarqdci));
368  DlHarqRlcPduListBuffer_t dlHarqRlcPdu;
369  dlHarqRlcPdu.resize (2);
370  dlHarqRlcPdu.at (0).resize (8);
371  dlHarqRlcPdu.at (1).resize (8);
372  m_dlHarqProcessesRlcPduListBuffer.insert (std::pair <uint16_t, DlHarqRlcPduListBuffer_t> (params.m_rnti, dlHarqRlcPdu));
373  m_ulHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
374  UlHarqProcessesStatus_t ulHarqPrcStatus;
375  ulHarqPrcStatus.resize (8,0);
376  m_ulHarqProcessesStatus.insert (std::pair <uint16_t, UlHarqProcessesStatus_t> (params.m_rnti, ulHarqPrcStatus));
377  UlHarqProcessesDciBuffer_t ulHarqdci;
378  ulHarqdci.resize (8);
379  m_ulHarqProcessesDciBuffer.insert (std::pair <uint16_t, UlHarqProcessesDciBuffer_t> (params.m_rnti, ulHarqdci));
380  }
381  else
382  {
383  (*it).second = params.m_transmissionMode;
384  }
385  return;
386 }
387 
388 void
390 {
391  NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti);
392 
393  std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator it;
394  for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++)
395  {
396  it = m_flowStatsDl.find (params.m_rnti);
397 
398  if (it == m_flowStatsDl.end ())
399  {
400  uint64_t mbrDlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateDl / 8; // byte/s
401  uint64_t mbrUlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateUl / 8; // byte/s
402 
403  tdtbfqsFlowPerf_t flowStatsDl;
404  flowStatsDl.flowStart = Simulator::Now ();
405  flowStatsDl.packetArrivalRate = 0;
406  flowStatsDl.tokenGenerationRate = mbrDlInBytes;
407  flowStatsDl.tokenPoolSize = 0;
408  flowStatsDl.maxTokenPoolSize = m_tokenPoolSize;
409  flowStatsDl.counter = 0;
410  flowStatsDl.burstCredit = m_creditLimit; // bytes
411  flowStatsDl.debtLimit = m_debtLimit; // bytes
413  m_flowStatsDl.insert (std::pair<uint16_t, tdtbfqsFlowPerf_t> (params.m_rnti, flowStatsDl));
414  tdtbfqsFlowPerf_t flowStatsUl;
415  flowStatsUl.flowStart = Simulator::Now ();
416  flowStatsUl.packetArrivalRate = 0;
417  flowStatsUl.tokenGenerationRate = mbrUlInBytes;
418  flowStatsUl.tokenPoolSize = 0;
419  flowStatsUl.maxTokenPoolSize = m_tokenPoolSize;
420  flowStatsUl.counter = 0;
421  flowStatsUl.burstCredit = m_creditLimit; // bytes
422  flowStatsUl.debtLimit = m_debtLimit; // bytes
424  m_flowStatsUl.insert (std::pair<uint16_t, tdtbfqsFlowPerf_t> (params.m_rnti, flowStatsUl));
425  }
426  else
427  {
428  // update MBR and GBR from UeManager::SetupDataRadioBearer ()
429  uint64_t mbrDlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateDl / 8; // byte/s
430  uint64_t mbrUlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabMaximulBitrateUl / 8; // byte/s
431  m_flowStatsDl[(*it).first].tokenGenerationRate = mbrDlInBytes;
432  m_flowStatsUl[(*it).first].tokenGenerationRate = mbrUlInBytes;
433 
434  }
435  }
436 
437  return;
438 }
439 
440 void
442 {
443  NS_LOG_FUNCTION (this);
444  for (uint16_t i = 0; i < params.m_logicalChannelIdentity.size (); i++)
445  {
446  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
447  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator temp;
448  while (it!=m_rlcBufferReq.end ())
449  {
450  if (((*it).first.m_rnti == params.m_rnti) && ((*it).first.m_lcId == params.m_logicalChannelIdentity.at (i)))
451  {
452  temp = it;
453  it++;
454  m_rlcBufferReq.erase (temp);
455  }
456  else
457  {
458  it++;
459  }
460  }
461  }
462  return;
463 }
464 
465 void
467 {
468  NS_LOG_FUNCTION (this);
469 
470  m_uesTxMode.erase (params.m_rnti);
471  m_dlHarqCurrentProcessId.erase (params.m_rnti);
472  m_dlHarqProcessesStatus.erase (params.m_rnti);
473  m_dlHarqProcessesTimer.erase (params.m_rnti);
474  m_dlHarqProcessesDciBuffer.erase (params.m_rnti);
476  m_ulHarqCurrentProcessId.erase (params.m_rnti);
477  m_ulHarqProcessesStatus.erase (params.m_rnti);
478  m_ulHarqProcessesDciBuffer.erase (params.m_rnti);
479  m_flowStatsDl.erase (params.m_rnti);
480  m_flowStatsUl.erase (params.m_rnti);
481  m_ceBsrRxed.erase (params.m_rnti);
482  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
483  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator temp;
484  while (it!=m_rlcBufferReq.end ())
485  {
486  if ((*it).first.m_rnti == params.m_rnti)
487  {
488  temp = it;
489  it++;
490  m_rlcBufferReq.erase (temp);
491  }
492  else
493  {
494  it++;
495  }
496  }
497  if (m_nextRntiUl == params.m_rnti)
498  {
499  m_nextRntiUl = 0;
500  }
501 
502  return;
503 }
504 
505 
506 void
508 {
509  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
510  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
511 
512  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
513 
514  LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity);
515 
516  it = m_rlcBufferReq.find (flow);
517 
518  if (it == m_rlcBufferReq.end ())
519  {
520  m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters> (flow, params));
521  }
522  else
523  {
524  (*it).second = params;
525  }
526 
527  return;
528 }
529 
530 void
532 {
533  NS_LOG_FUNCTION (this);
534  NS_FATAL_ERROR ("method not implemented");
535  return;
536 }
537 
538 void
540 {
541  NS_LOG_FUNCTION (this);
542  NS_FATAL_ERROR ("method not implemented");
543  return;
544 }
545 
546 int
548 {
549  for (int i = 0; i < 4; i++)
550  {
551  if (dlbandwidth < TdTbfqType0AllocationRbg[i])
552  {
553  return (i + 1);
554  }
555  }
556 
557  return (-1);
558 }
559 
560 
561 int
563 {
564  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
565  int lcActive = 0;
566  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
567  {
568  if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueSize > 0)
569  || ((*it).second.m_rlcRetransmissionQueueSize > 0)
570  || ((*it).second.m_rlcStatusPduSize > 0) ))
571  {
572  lcActive++;
573  }
574  if ((*it).first.m_rnti > rnti)
575  {
576  break;
577  }
578  }
579  return (lcActive);
580 
581 }
582 
583 
584 uint8_t
586 {
587  NS_LOG_FUNCTION (this << rnti);
588 
589  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
590  if (it == m_dlHarqCurrentProcessId.end ())
591  {
592  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
593  }
594  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
595  if (itStat == m_dlHarqProcessesStatus.end ())
596  {
597  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
598  }
599  uint8_t i = (*it).second;
600  do
601  {
602  i = (i + 1) % HARQ_PROC_NUM;
603  }
604  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
605  if ((*itStat).second.at (i) == 0)
606  {
607  return (true);
608  }
609  else
610  {
611  return (false); // return a not valid harq proc id
612  }
613 }
614 
615 
616 
617 uint8_t
619 {
620  NS_LOG_FUNCTION (this << rnti);
621 
622  if (m_harqOn == false)
623  {
624  return (0);
625  }
626 
627 
628  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
629  if (it == m_dlHarqCurrentProcessId.end ())
630  {
631  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
632  }
633  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
634  if (itStat == m_dlHarqProcessesStatus.end ())
635  {
636  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
637  }
638  uint8_t i = (*it).second;
639  do
640  {
641  i = (i + 1) % HARQ_PROC_NUM;
642  }
643  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
644  if ((*itStat).second.at (i) == 0)
645  {
646  (*it).second = i;
647  (*itStat).second.at (i) = 1;
648  }
649  else
650  {
651  NS_FATAL_ERROR ("No HARQ process available for RNTI " << rnti << " check before update with HarqProcessAvailability");
652  }
653 
654  return ((*it).second);
655 }
656 
657 
658 void
660 {
661  NS_LOG_FUNCTION (this);
662 
663  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
664  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers ++)
665  {
666  for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
667  {
668  if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
669  {
670  // reset HARQ process
671 
672  NS_LOG_DEBUG (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
673  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
674  if (itStat == m_dlHarqProcessesStatus.end ())
675  {
676  NS_FATAL_ERROR ("No Process Id Status found for this RNTI " << (*itTimers).first);
677  }
678  (*itStat).second.at (i) = 0;
679  (*itTimers).second.at (i) = 0;
680  }
681  else
682  {
683  (*itTimers).second.at (i)++;
684  }
685  }
686  }
687 
688 }
689 
690 
691 void
693 {
694  NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
695  // API generated by RLC for triggering the scheduling of a DL subframe
696 
697 
698  // evaluate the relative channel quality indicator for each UE per each RBG
699  // (since we are using allocation type 0 the small unit of allocation is RBG)
700  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
701 
702  RefreshDlCqiMaps ();
703 
705  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
706  std::map <uint16_t, std::vector <uint16_t> > allocationMap; // RBs map per RNTI
707  std::vector <bool> rbgMap; // global RBGs map
708  uint16_t rbgAllocatedNum = 0;
709  std::set <uint16_t> rntiAllocated;
710  rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
711 
712  rbgMap = m_ffrSapProvider->GetAvailableDlRbg ();
713  for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
714  {
715  if ((*it) == true )
716  {
717  rbgAllocatedNum++;
718  }
719  }
720 
722 
723  // update UL HARQ proc id
724  std::map <uint16_t, uint8_t>::iterator itProcId;
725  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
726  {
727  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
728  }
729 
730  // RACH Allocation
731  uint16_t rbAllocatedNum = 0;
732  std::vector <bool> ulRbMap;
733  ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
734  ulRbMap = m_ffrSapProvider->GetAvailableUlRbg ();
735  uint8_t maxContinuousUlBandwidth = 0;
736  uint8_t tmpMinBandwidth = 0;
737  uint16_t ffrRbStartOffset = 0;
738  uint16_t tmpFfrRbStartOffset = 0;
739  uint16_t index = 0;
740 
741  for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
742  {
743  if ((*it) == true )
744  {
745  rbAllocatedNum++;
746  if (tmpMinBandwidth > maxContinuousUlBandwidth)
747  {
748  maxContinuousUlBandwidth = tmpMinBandwidth;
749  ffrRbStartOffset = tmpFfrRbStartOffset;
750  }
751  tmpMinBandwidth = 0;
752  }
753  else
754  {
755  if (tmpMinBandwidth == 0)
756  {
757  tmpFfrRbStartOffset = index;
758  }
759  tmpMinBandwidth++;
760  }
761  index++;
762  }
763 
764  if (tmpMinBandwidth > maxContinuousUlBandwidth)
765  {
766  maxContinuousUlBandwidth = tmpMinBandwidth;
767  ffrRbStartOffset = tmpFfrRbStartOffset;
768  }
769 
771  uint16_t rbStart = 0;
772  rbStart = ffrRbStartOffset;
773  std::vector <struct RachListElement_s>::iterator itRach;
774  for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
775  {
776  NS_ASSERT_MSG (m_amc->GetTbSizeFromMcs (m_ulGrantMcs, m_cschedCellConfig.m_ulBandwidth) > (*itRach).m_estimatedSize, " Default UL Grant MCS does not allow to send RACH messages");
777  BuildRarListElement_s newRar;
778  newRar.m_rnti = (*itRach).m_rnti;
779  // DL-RACH Allocation
780  // Ideal: no needs of configuring m_dci
781  // UL-RACH Allocation
782  newRar.m_grant.m_rnti = newRar.m_rnti;
783  newRar.m_grant.m_mcs = m_ulGrantMcs;
784  uint16_t rbLen = 1;
785  uint16_t tbSizeBits = 0;
786  // find lowest TB size that fits UL grant estimated size
787  while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
788  {
789  rbLen++;
790  tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
791  }
792  if (tbSizeBits < (*itRach).m_estimatedSize)
793  {
794  // no more allocation space: finish allocation
795  break;
796  }
797  newRar.m_grant.m_rbStart = rbStart;
798  newRar.m_grant.m_rbLen = rbLen;
799  newRar.m_grant.m_tbSize = tbSizeBits / 8;
800  newRar.m_grant.m_hopping = false;
801  newRar.m_grant.m_tpc = 0;
802  newRar.m_grant.m_cqiRequest = false;
803  newRar.m_grant.m_ulDelay = false;
804  NS_LOG_INFO (this << " UL grant allocated to RNTI " << (*itRach).m_rnti << " rbStart " << rbStart << " rbLen " << rbLen << " MCS " << m_ulGrantMcs << " tbSize " << newRar.m_grant.m_tbSize);
805  for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
806  {
807  m_rachAllocationMap.at (i) = (*itRach).m_rnti;
808  }
809 
810  if (m_harqOn == true)
811  {
812  // generate UL-DCI for HARQ retransmissions
813  UlDciListElement_s uldci;
814  uldci.m_rnti = newRar.m_rnti;
815  uldci.m_rbLen = rbLen;
816  uldci.m_rbStart = rbStart;
817  uldci.m_mcs = m_ulGrantMcs;
818  uldci.m_tbSize = tbSizeBits / 8;
819  uldci.m_ndi = 1;
820  uldci.m_cceIndex = 0;
821  uldci.m_aggrLevel = 1;
822  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
823  uldci.m_hopping = false;
824  uldci.m_n2Dmrs = 0;
825  uldci.m_tpc = 0; // no power control
826  uldci.m_cqiRequest = false; // only period CQI at this stage
827  uldci.m_ulIndex = 0; // TDD parameter
828  uldci.m_dai = 1; // TDD parameter
829  uldci.m_freqHopping = 0;
830  uldci.m_pdcchPowerOffset = 0; // not used
831 
832  uint8_t harqId = 0;
833  std::map <uint16_t, uint8_t>::iterator itProcId;
834  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
835  if (itProcId == m_ulHarqCurrentProcessId.end ())
836  {
837  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
838  }
839  harqId = (*itProcId).second;
840  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
841  if (itDci == m_ulHarqProcessesDciBuffer.end ())
842  {
843  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
844  }
845  (*itDci).second.at (harqId) = uldci;
846  }
847 
848  rbStart = rbStart + rbLen;
849  ret.m_buildRarList.push_back (newRar);
850  }
851  m_rachList.clear ();
852 
853 
854  // Process DL HARQ feedback
856  // retrieve past HARQ retx buffered
857  if (m_dlInfoListBuffered.size () > 0)
858  {
859  if (params.m_dlInfoList.size () > 0)
860  {
861  NS_LOG_INFO (this << " Received DL-HARQ feedback");
862  m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
863  }
864  }
865  else
866  {
867  if (params.m_dlInfoList.size () > 0)
868  {
870  }
871  }
872  if (m_harqOn == false)
873  {
874  // Ignore HARQ feedback
875  m_dlInfoListBuffered.clear ();
876  }
877  std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
878  for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
879  {
880  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
881  if (itRnti != rntiAllocated.end ())
882  {
883  // RNTI already allocated for retx
884  continue;
885  }
886  uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
887  std::vector <bool> retx;
888  NS_LOG_INFO (this << " Processing DLHARQ feedback");
889  if (nLayers == 1)
890  {
891  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
892  retx.push_back (false);
893  }
894  else
895  {
896  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
897  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
898  }
899  if (retx.at (0) || retx.at (1))
900  {
901  // retrieve HARQ process information
902  uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
903  uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
904  NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
905  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
906  if (itHarq == m_dlHarqProcessesDciBuffer.end ())
907  {
908  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
909  }
910 
911  DlDciListElement_s dci = (*itHarq).second.at (harqId);
912  int rv = 0;
913  if (dci.m_rv.size () == 1)
914  {
915  rv = dci.m_rv.at (0);
916  }
917  else
918  {
919  rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
920  }
921 
922  if (rv == 3)
923  {
924  // maximum number of retx reached -> drop process
925  NS_LOG_INFO ("Maximum number of retransmissions reached -> drop process");
926  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
927  if (it == m_dlHarqProcessesStatus.end ())
928  {
929  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
930  }
931  (*it).second.at (harqId) = 0;
932  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
933  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
934  {
935  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
936  }
937  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
938  {
939  (*itRlcPdu).second.at (k).at (harqId).clear ();
940  }
941  continue;
942  }
943  // check the feasibility of retransmitting on the same RBGs
944  // translate the DCI to Spectrum framework
945  std::vector <int> dciRbg;
946  uint32_t mask = 0x1;
947  NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
948  for (int j = 0; j < 32; j++)
949  {
950  if (((dci.m_rbBitmap & mask) >> j) == 1)
951  {
952  dciRbg.push_back (j);
953  NS_LOG_INFO ("\t" << j);
954  }
955  mask = (mask << 1);
956  }
957  bool free = true;
958  for (uint8_t j = 0; j < dciRbg.size (); j++)
959  {
960  if (rbgMap.at (dciRbg.at (j)) == true)
961  {
962  free = false;
963  break;
964  }
965  }
966  if (free)
967  {
968  // use the same RBGs for the retx
969  // reserve RBGs
970  for (uint8_t j = 0; j < dciRbg.size (); j++)
971  {
972  rbgMap.at (dciRbg.at (j)) = true;
973  NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
974  rbgAllocatedNum++;
975  }
976 
977  NS_LOG_INFO (this << " Send retx in the same RBGs");
978  }
979  else
980  {
981  // find RBGs for sending HARQ retx
982  uint8_t j = 0;
983  uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % rbgNum;
984  uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
985  std::vector <bool> rbgMapCopy = rbgMap;
986  while ((j < dciRbg.size ())&&(startRbg != rbgId))
987  {
988  if (rbgMapCopy.at (rbgId) == false)
989  {
990  rbgMapCopy.at (rbgId) = true;
991  dciRbg.at (j) = rbgId;
992  j++;
993  }
994  rbgId = (rbgId + 1) % rbgNum;
995  }
996  if (j == dciRbg.size ())
997  {
998  // find new RBGs -> update DCI map
999  uint32_t rbgMask = 0;
1000  for (uint16_t k = 0; k < dciRbg.size (); k++)
1001  {
1002  rbgMask = rbgMask + (0x1 << dciRbg.at (k));
1003  rbgAllocatedNum++;
1004  }
1005  dci.m_rbBitmap = rbgMask;
1006  rbgMap = rbgMapCopy;
1007  NS_LOG_INFO (this << " Move retx in RBGs " << dciRbg.size ());
1008  }
1009  else
1010  {
1011  // HARQ retx cannot be performed on this TTI -> store it
1012  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
1013  NS_LOG_INFO (this << " No resource for this retx -> buffer it");
1014  }
1015  }
1016  // retrieve RLC PDU list for retx TBsize and update DCI
1017  BuildDataListElement_s newEl;
1018  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
1019  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1020  {
1021  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
1022  }
1023  for (uint8_t j = 0; j < nLayers; j++)
1024  {
1025  if (retx.at (j))
1026  {
1027  if (j >= dci.m_ndi.size ())
1028  {
1029  // for avoiding errors in MIMO transient phases
1030  dci.m_ndi.push_back (0);
1031  dci.m_rv.push_back (0);
1032  dci.m_mcs.push_back (0);
1033  dci.m_tbsSize.push_back (0);
1034  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
1035  }
1036  else
1037  {
1038  dci.m_ndi.at (j) = 0;
1039  dci.m_rv.at (j)++;
1040  (*itHarq).second.at (harqId).m_rv.at (j)++;
1041  NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
1042  }
1043  }
1044  else
1045  {
1046  // empty TB of layer j
1047  dci.m_ndi.at (j) = 0;
1048  dci.m_rv.at (j) = 0;
1049  dci.m_mcs.at (j) = 0;
1050  dci.m_tbsSize.at (j) = 0;
1051  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
1052  }
1053  }
1054  for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
1055  {
1056  std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
1057  for (uint8_t j = 0; j < nLayers; j++)
1058  {
1059  if (retx.at (j))
1060  {
1061  if (j < dci.m_ndi.size ())
1062  {
1063  rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
1064  }
1065  }
1066  }
1067 
1068  if (rlcPduListPerLc.size () > 0)
1069  {
1070  newEl.m_rlcPduList.push_back (rlcPduListPerLc);
1071  }
1072  }
1073  newEl.m_rnti = rnti;
1074  newEl.m_dci = dci;
1075  (*itHarq).second.at (harqId).m_rv = dci.m_rv;
1076  // refresh timer
1077  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
1078  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1079  {
1080  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
1081  }
1082  (*itHarqTimer).second.at (harqId) = 0;
1083  ret.m_buildDataList.push_back (newEl);
1084  rntiAllocated.insert (rnti);
1085  }
1086  else
1087  {
1088  // update HARQ process status
1089  NS_LOG_INFO (this << " HARQ received ACK for UE " << m_dlInfoListBuffered.at (i).m_rnti);
1090  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
1091  if (it == m_dlHarqProcessesStatus.end ())
1092  {
1093  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
1094  }
1095  (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
1096  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
1097  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1098  {
1099  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
1100  }
1101  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
1102  {
1103  (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
1104  }
1105  }
1106  }
1107  m_dlInfoListBuffered.clear ();
1108  m_dlInfoListBuffered = dlInfoListUntxed;
1109 
1110  if (rbgAllocatedNum == rbgNum)
1111  {
1112  // all the RBGs are already allocated -> exit
1113  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
1114  {
1116  }
1117  return;
1118  }
1119 
1120 
1121  // update token pool, counter and bank size
1122  std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itStats;
1123  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
1124  {
1125  if ( (*itStats).second.tokenGenerationRate / 1000 + (*itStats).second.tokenPoolSize > (*itStats).second.maxTokenPoolSize )
1126  {
1127  (*itStats).second.counter += (*itStats).second.tokenGenerationRate / 1000 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );
1128  (*itStats).second.tokenPoolSize = (*itStats).second.maxTokenPoolSize;
1129  bankSize += (*itStats).second.tokenGenerationRate / 1000 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );
1130  }
1131  else
1132  {
1133  (*itStats).second.tokenPoolSize += (*itStats).second.tokenGenerationRate / 1000;
1134  }
1135  }
1136 
1137 
1138  // select UE with largest metric
1139  std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator it;
1140  std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itMax = m_flowStatsDl.end ();
1141  double metricMax = 0.0;
1142  bool firstRnti = true;
1143  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
1144  {
1145  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1146  if ((itRnti != rntiAllocated.end ())||(!HarqProcessAvailability ((*it).first)))
1147  {
1148  // UE already allocated for HARQ or without HARQ process available -> drop it
1149  if (itRnti != rntiAllocated.end ())
1150  {
1151  NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(*it).first);
1152  }
1153  if (!HarqProcessAvailability ((*it).first))
1154  {
1155  NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*it).first);
1156  }
1157  continue;
1158  }
1159 
1160  /*
1161  if (LcActivePerFlow ((*it).first) == 0)
1162  {
1163  continue;
1164  }
1165  */
1166 
1167  double metric = ( ( (double)(*it).second.counter ) / ( (double)(*it).second.tokenGenerationRate ) );
1168 
1169  if (firstRnti == true)
1170  {
1171  metricMax = metric;
1172  itMax = it;
1173  firstRnti = false;
1174  continue;
1175  }
1176  if (metric > metricMax)
1177  {
1178  metricMax = metric;
1179  itMax = it;
1180  }
1181  } // end for m_flowStatsDl
1182 
1183  if (itMax == m_flowStatsDl.end ())
1184  {
1185  // all UEs are allocated RBG or all UEs already allocated for HARQ or without HARQ process available
1186  return;
1187  }
1188  else
1189  {
1190  // assign all RBGs to this UE
1191  std::vector <uint16_t> tempMap;
1192  for (int i = 0; i < rbgNum; i++)
1193  {
1194  if ( rbgMap.at (i) == true) // this RBG is allocated in RACH procedure
1195  continue;
1196 
1197  if ((m_ffrSapProvider->IsDlRbgAvailableForUe (i, (*itMax).first)) == false)
1198  continue;
1199 
1200  tempMap.push_back (i);
1201  rbgMap.at (i) = true;
1202  }
1203  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
1204  }
1205 
1206 
1207 
1208  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
1209  // creating the correspondent DCIs
1210  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
1211  while (itMap != allocationMap.end ())
1212  {
1213  // create new BuildDataListElement_s for this LC
1214  BuildDataListElement_s newEl;
1215  newEl.m_rnti = (*itMap).first;
1216  // create the DlDciListElement_s
1217  DlDciListElement_s newDci;
1218  newDci.m_rnti = (*itMap).first;
1219  newDci.m_harqProcess = UpdateHarqProcessId ((*itMap).first);
1220 
1221  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
1222  NS_LOG_INFO (this << "Allocate user " << newEl.m_rnti << " rbg " << lcActives);
1223  if (lcActives == 0)
1224  {
1225  // Set to max value, to avoid divide by 0 below
1226  lcActives = (uint16_t)65535; // UINT16_MAX;
1227  }
1228  uint16_t RgbPerRnti = (*itMap).second.size ();
1229  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1230  itCqi = m_a30CqiRxed.find ((*itMap).first);
1231  std::map <uint16_t,uint8_t>::iterator itTxMode;
1232  itTxMode = m_uesTxMode.find ((*itMap).first);
1233  if (itTxMode == m_uesTxMode.end ())
1234  {
1235  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
1236  }
1237  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1238  std::vector <uint8_t> worstCqi (2, 15);
1239  if (itCqi != m_a30CqiRxed.end ())
1240  {
1241  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1242  {
1243  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
1244  {
1245  for (uint8_t j = 0; j < nLayer; j++)
1246  {
1247  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
1248  {
1249  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
1250  {
1251  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
1252  }
1253  }
1254  else
1255  {
1256  // no CQI for this layer of this suband -> worst one
1257  worstCqi.at (j) = 1;
1258  }
1259  }
1260  }
1261  else
1262  {
1263  for (uint8_t j = 0; j < nLayer; j++)
1264  {
1265  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1266  }
1267  }
1268  }
1269  }
1270  else
1271  {
1272  for (uint8_t j = 0; j < nLayer; j++)
1273  {
1274  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1275  }
1276  }
1277  uint32_t bytesTxed = 0;
1278  for (uint8_t j = 0; j < nLayer; j++)
1279  {
1280  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
1281  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)
1282  newDci.m_tbsSize.push_back (tbSize);
1283  bytesTxed += tbSize;
1284  }
1285 
1286  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
1287  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
1288  uint32_t rbgMask = 0;
1289  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1290  {
1291  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
1292  NS_LOG_INFO (this << " Allocated RBG " << (*itMap).second.at (k));
1293  }
1294  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1295 
1296  // create the rlc PDUs -> equally divide resources among actives LCs
1297  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
1298  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
1299  {
1300  if (((*itBufReq).first.m_rnti == (*itMap).first)
1301  && (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
1302  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
1303  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
1304  {
1305  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1306  for (uint8_t j = 0; j < nLayer; j++)
1307  {
1308  RlcPduListElement_s newRlcEl;
1309  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
1310  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
1311  NS_LOG_INFO (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j);
1312  newRlcPduLe.push_back (newRlcEl);
1313  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
1314  if (m_harqOn == true)
1315  {
1316  // store RLC PDU list for HARQ
1317  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*itMap).first);
1318  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1319  {
1320  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*itMap).first);
1321  }
1322  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1323  }
1324  }
1325  newEl.m_rlcPduList.push_back (newRlcPduLe);
1326  }
1327  if ((*itBufReq).first.m_rnti > (*itMap).first)
1328  {
1329  break;
1330  }
1331  }
1332  for (uint8_t j = 0; j < nLayer; j++)
1333  {
1334  newDci.m_ndi.push_back (1);
1335  newDci.m_rv.push_back (0);
1336  }
1337 
1338  newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
1339 
1340  newEl.m_dci = newDci;
1341 
1342  if (m_harqOn == true)
1343  {
1344  // store DCI for HARQ
1345  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1346  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1347  {
1348  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1349  }
1350  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1351  // refresh timer
1352  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1353  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1354  {
1355  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1356  }
1357  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1358  }
1359 
1360 
1361  // update UE stats
1362  if ( bytesTxed <= (*itMax).second.tokenPoolSize )
1363  {
1364  (*itMax).second.tokenPoolSize -= bytesTxed;
1365  }
1366  else
1367  {
1368  (*itMax).second.counter = (*itMax).second.counter - ( bytesTxed - (*itMax).second.tokenPoolSize );
1369  (*itMax).second.tokenPoolSize = 0;
1370  if (bankSize <= ( bytesTxed - (*itMax).second.tokenPoolSize ))
1371  bankSize = 0;
1372  else
1373  bankSize = bankSize - ( bytesTxed - (*itMax).second.tokenPoolSize );
1374  }
1375 
1376 
1377  // ...more parameters -> ingored in this version
1378 
1379  ret.m_buildDataList.push_back (newEl);
1380 
1381  itMap++;
1382  } // end while allocation
1383  ret.m_nrOfPdcchOfdmSymbols = 1;
1384 
1386 
1387 
1388  return;
1389 }
1390 
1391 void
1393 {
1394  NS_LOG_FUNCTION (this);
1395 
1396  m_rachList = params.m_rachList;
1397 
1398  return;
1399 }
1400 
1401 void
1403 {
1404  NS_LOG_FUNCTION (this);
1406 
1407  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1408  {
1409  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1410  {
1411  NS_LOG_LOGIC ("wideband CQI " << (uint32_t) params.m_cqiList.at (i).m_wbCqi.at (0) << " reported");
1412  std::map <uint16_t,uint8_t>::iterator it;
1413  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1414  it = m_p10CqiRxed.find (rnti);
1415  if (it == m_p10CqiRxed.end ())
1416  {
1417  // create the new entry
1418  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)
1419  // generate correspondent timer
1420  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1421  }
1422  else
1423  {
1424  // update the CQI value and refresh correspondent timer
1425  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1426  // update correspondent timer
1427  std::map <uint16_t,uint32_t>::iterator itTimers;
1428  itTimers = m_p10CqiTimers.find (rnti);
1429  (*itTimers).second = m_cqiTimersThreshold;
1430  }
1431  }
1432  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1433  {
1434  // subband CQI reporting high layer configured
1435  std::map <uint16_t,SbMeasResult_s>::iterator it;
1436  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1437  it = m_a30CqiRxed.find (rnti);
1438  if (it == m_a30CqiRxed.end ())
1439  {
1440  // create the new entry
1441  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
1442  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1443  }
1444  else
1445  {
1446  // update the CQI value and refresh correspondent timer
1447  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
1448  std::map <uint16_t,uint32_t>::iterator itTimers;
1449  itTimers = m_a30CqiTimers.find (rnti);
1450  (*itTimers).second = m_cqiTimersThreshold;
1451  }
1452  }
1453  else
1454  {
1455  NS_LOG_ERROR (this << " CQI type unknown");
1456  }
1457  }
1458 
1459  return;
1460 }
1461 
1462 
1463 double
1464 TdTbfqFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
1465 {
1466  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
1467  if (itCqi == m_ueCqi.end ())
1468  {
1469  // no cqi info about this UE
1470  return (NO_SINR);
1471 
1472  }
1473  else
1474  {
1475  // take the average SINR value among the available
1476  double sinrSum = 0;
1477  unsigned int sinrNum = 0;
1478  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1479  {
1480  double sinr = (*itCqi).second.at (i);
1481  if (sinr != NO_SINR)
1482  {
1483  sinrSum += sinr;
1484  sinrNum++;
1485  }
1486  }
1487  double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
1488  // store the value
1489  (*itCqi).second.at (rb) = estimatedSinr;
1490  return (estimatedSinr);
1491  }
1492 }
1493 
1494 void
1496 {
1497  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1498 
1499  RefreshUlCqiMaps ();
1501 
1502  // Generate RBs map
1504  std::vector <bool> rbMap;
1505  uint16_t rbAllocatedNum = 0;
1506  std::set <uint16_t> rntiAllocated;
1507  std::vector <uint16_t> rbgAllocationMap;
1508  // update with RACH allocation map
1509  rbgAllocationMap = m_rachAllocationMap;
1510  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1511  m_rachAllocationMap.clear ();
1513 
1514  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1515 
1516  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
1517 
1518  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
1519  {
1520  if ((*it) == true )
1521  {
1522  rbAllocatedNum++;
1523  }
1524  }
1525 
1526  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
1527  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
1528 
1529  // remove RACH allocation
1530  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1531  {
1532  if (rbgAllocationMap.at (i) != 0)
1533  {
1534  rbMap.at (i) = true;
1535  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1536  }
1537  }
1538 
1539 
1540  if (m_harqOn == true)
1541  {
1542  // Process UL HARQ feedback
1543  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1544  {
1545  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1546  {
1547  // retx correspondent block: retrieve the UL-DCI
1548  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1549  std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1550  if (itProcId == m_ulHarqCurrentProcessId.end ())
1551  {
1552  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1553  }
1554  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1555  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId << " i " << i << " size " << params.m_ulInfoList.size ());
1556  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1557  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1558  {
1559  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1560  continue;
1561  }
1562  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1563  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1564  if (itStat == m_ulHarqProcessesStatus.end ())
1565  {
1566  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1567  }
1568  if ((*itStat).second.at (harqId) >= 3)
1569  {
1570  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1571  continue;
1572  }
1573  bool free = true;
1574  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1575  {
1576  if (rbMap.at (j) == true)
1577  {
1578  free = false;
1579  NS_LOG_INFO (this << " BUSY " << j);
1580  }
1581  }
1582  if (free)
1583  {
1584  // retx on the same RBs
1585  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1586  {
1587  rbMap.at (j) = true;
1588  rbgAllocationMap.at (j) = dci.m_rnti;
1589  NS_LOG_INFO ("\tRB " << j);
1590  rbAllocatedNum++;
1591  }
1592  NS_LOG_INFO (this << " Send retx in the same RBs " << (uint16_t)dci.m_rbStart << " to " << dci.m_rbStart + dci.m_rbLen << " RV " << (*itStat).second.at (harqId) + 1);
1593  }
1594  else
1595  {
1596  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1597  continue;
1598  }
1599  dci.m_ndi = 0;
1600  // Update HARQ buffers with new HarqId
1601  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1602  (*itStat).second.at (harqId) = 0;
1603  (*itHarq).second.at ((*itProcId).second) = dci;
1604  ret.m_dciList.push_back (dci);
1605  rntiAllocated.insert (dci.m_rnti);
1606  }
1607  else
1608  {
1609  NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
1610  }
1611  }
1612  }
1613 
1614  std::map <uint16_t,uint32_t>::iterator it;
1615  int nflows = 0;
1616 
1617  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1618  {
1619  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1620  // select UEs with queues not empty and not yet allocated for HARQ
1621  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1622  {
1623  nflows++;
1624  }
1625  }
1626 
1627  if (nflows == 0)
1628  {
1629  if (ret.m_dciList.size () > 0)
1630  {
1631  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1633  }
1634 
1635  return; // no flows to be scheduled
1636  }
1637 
1638 
1639  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1640  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
1641  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
1642 
1643  if (rbPerFlow < 3)
1644  {
1645  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1646  }
1647  int rbAllocated = 0;
1648 
1649  std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itStats;
1650  if (m_nextRntiUl != 0)
1651  {
1652  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1653  {
1654  if ((*it).first == m_nextRntiUl)
1655  {
1656  break;
1657  }
1658  }
1659  if (it == m_ceBsrRxed.end ())
1660  {
1661  NS_LOG_ERROR (this << " no user found");
1662  }
1663  }
1664  else
1665  {
1666  it = m_ceBsrRxed.begin ();
1667  m_nextRntiUl = (*it).first;
1668  }
1669  do
1670  {
1671  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1672  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1673  {
1674  // UE already allocated for UL-HARQ -> skip it
1675  NS_LOG_DEBUG (this << " UE already allocated in HARQ -> discared, RNTI " << (*it).first);
1676  it++;
1677  if (it == m_ceBsrRxed.end ())
1678  {
1679  // restart from the first
1680  it = m_ceBsrRxed.begin ();
1681  }
1682  continue;
1683  }
1684  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1685  {
1686  // limit to physical resources last resource assignment
1687  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1688  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1689  if (rbPerFlow < 3)
1690  {
1691  // terminate allocation
1692  rbPerFlow = 0;
1693  }
1694  }
1695 
1696  rbAllocated = 0;
1697  UlDciListElement_s uldci;
1698  uldci.m_rnti = (*it).first;
1699  uldci.m_rbLen = rbPerFlow;
1700  bool allocated = false;
1701  NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1702  while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
1703  {
1704  // check availability
1705  bool free = true;
1706  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1707  {
1708  if (rbMap.at (j) == true)
1709  {
1710  free = false;
1711  break;
1712  }
1713  if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
1714  {
1715  free = false;
1716  break;
1717  }
1718  }
1719  if (free)
1720  {
1721  NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1722  uldci.m_rbStart = rbAllocated;
1723 
1724  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1725  {
1726  rbMap.at (j) = true;
1727  // store info on allocation for managing ul-cqi interpretation
1728  rbgAllocationMap.at (j) = (*it).first;
1729  }
1730  rbAllocated += rbPerFlow;
1731  allocated = true;
1732  break;
1733  }
1734  rbAllocated++;
1735  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1736  {
1737  // limit to physical resources last resource assignment
1738  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1739  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1740  if (rbPerFlow < 3)
1741  {
1742  // terminate allocation
1743  rbPerFlow = 0;
1744  }
1745  }
1746  }
1747  if (!allocated)
1748  {
1749  // unable to allocate new resource: finish scheduling
1750 // m_nextRntiUl = (*it).first;
1751 // if (ret.m_dciList.size () > 0)
1752 // {
1753 // m_schedSapUser->SchedUlConfigInd (ret);
1754 // }
1755 // m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1756 // return;
1757  break;
1758  }
1759 
1760 
1761 
1762  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1763  int cqi = 0;
1764  if (itCqi == m_ueCqi.end ())
1765  {
1766  // no cqi info about this UE
1767  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1768  }
1769  else
1770  {
1771  // take the lowest CQI value (worst RB)
1772  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1773  if (minSinr == NO_SINR)
1774  {
1775  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
1776  }
1777  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1778  {
1779  double sinr = (*itCqi).second.at (i);
1780  if (sinr == NO_SINR)
1781  {
1782  sinr = EstimateUlSinr ((*it).first, i);
1783  }
1784  if ((*itCqi).second.at (i) < minSinr)
1785  {
1786  minSinr = (*itCqi).second.at (i);
1787  }
1788  }
1789 
1790  // translate SINR -> cqi: WILD ACK: same as DL
1791  double s = log2 ( 1 + (
1792  std::pow (10, minSinr / 10 ) /
1793  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1794  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1795  if (cqi == 0)
1796  {
1797  it++;
1798  if (it == m_ceBsrRxed.end ())
1799  {
1800  // restart from the first
1801  it = m_ceBsrRxed.begin ();
1802  }
1803  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
1804  // remove UE from allocation map
1805  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1806  {
1807  rbgAllocationMap.at (i) = 0;
1808  }
1809  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1810  }
1811  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1812  }
1813 
1814  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
1815  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1816  uldci.m_ndi = 1;
1817  uldci.m_cceIndex = 0;
1818  uldci.m_aggrLevel = 1;
1819  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1820  uldci.m_hopping = false;
1821  uldci.m_n2Dmrs = 0;
1822  uldci.m_tpc = 0; // no power control
1823  uldci.m_cqiRequest = false; // only period CQI at this stage
1824  uldci.m_ulIndex = 0; // TDD parameter
1825  uldci.m_dai = 1; // TDD parameter
1826  uldci.m_freqHopping = 0;
1827  uldci.m_pdcchPowerOffset = 0; // not used
1828  ret.m_dciList.push_back (uldci);
1829  // store DCI for HARQ_PERIOD
1830  uint8_t harqId = 0;
1831  if (m_harqOn == true)
1832  {
1833  std::map <uint16_t, uint8_t>::iterator itProcId;
1834  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1835  if (itProcId == m_ulHarqCurrentProcessId.end ())
1836  {
1837  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1838  }
1839  harqId = (*itProcId).second;
1840  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1841  if (itDci == m_ulHarqProcessesDciBuffer.end ())
1842  {
1843  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1844  }
1845  (*itDci).second.at (harqId) = uldci;
1846  // Update HARQ process status (RV 0)
1847  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (uldci.m_rnti);
1848  if (itStat == m_ulHarqProcessesStatus.end ())
1849  {
1850  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << uldci.m_rnti);
1851  }
1852  (*itStat).second.at (harqId) = 0;
1853  }
1854 
1855  NS_LOG_INFO (this << " UE Allocation RNTI " << (*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 << " harqId " << (uint16_t)harqId);
1856 
1857  it++;
1858  if (it == m_ceBsrRxed.end ())
1859  {
1860  // restart from the first
1861  it = m_ceBsrRxed.begin ();
1862  }
1863  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1864  {
1865  // Stop allocation: no more PRBs
1866  m_nextRntiUl = (*it).first;
1867  break;
1868  }
1869  }
1870  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1871 
1872 
1873  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1875 
1876  return;
1877 }
1878 
1879 void
1881 {
1882  NS_LOG_FUNCTION (this);
1883  return;
1884 }
1885 
1886 void
1888 {
1889  NS_LOG_FUNCTION (this);
1890  return;
1891 }
1892 
1893 void
1895 {
1896  NS_LOG_FUNCTION (this);
1897 
1898  std::map <uint16_t,uint32_t>::iterator it;
1899 
1900  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1901  {
1902  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1903  {
1904  // buffer status report
1905  // note that this scheduler does not differentiate the
1906  // allocation according to which LCGs have more/less bytes
1907  // to send.
1908  // Hence the BSR of different LCGs are just summed up to get
1909  // a total queue size that is used for allocation purposes.
1910 
1911  uint32_t buffer = 0;
1912  for (uint8_t lcg = 0; lcg < 4; ++lcg)
1913  {
1914  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1915  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1916  }
1917 
1918  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1919  NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
1920  it = m_ceBsrRxed.find (rnti);
1921  if (it == m_ceBsrRxed.end ())
1922  {
1923  // create the new entry
1924  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1925  }
1926  else
1927  {
1928  // update the buffer size value
1929  (*it).second = buffer;
1930  }
1931  }
1932  }
1933 
1934  return;
1935 }
1936 
1937 void
1939 {
1940  NS_LOG_FUNCTION (this);
1941 // retrieve the allocation for this subframe
1942  switch (m_ulCqiFilter)
1943  {
1945  {
1946  // filter all the CQIs that are not SRS based
1947  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
1948  {
1949  return;
1950  }
1951  }
1952  break;
1954  {
1955  // filter all the CQIs that are not SRS based
1956  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
1957  {
1958  return;
1959  }
1960  }
1962  break;
1963 
1964  default:
1965  NS_FATAL_ERROR ("Unknown UL CQI type");
1966  }
1967 
1968  switch (params.m_ulCqi.m_type)
1969  {
1970  case UlCqi_s::PUSCH:
1971  {
1972  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1973  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1974  NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
1975  itMap = m_allocationMaps.find (params.m_sfnSf);
1976  if (itMap == m_allocationMaps.end ())
1977  {
1978  return;
1979  }
1980  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1981  {
1982  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1983  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1984  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1985  if (itCqi == m_ueCqi.end ())
1986  {
1987  // create a new entry
1988  std::vector <double> newCqi;
1989  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1990  {
1991  if (i == j)
1992  {
1993  newCqi.push_back (sinr);
1994  }
1995  else
1996  {
1997  // initialize with NO_SINR value.
1998  newCqi.push_back (NO_SINR);
1999  }
2000 
2001  }
2002  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
2003  // generate correspondent timer
2004  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
2005  }
2006  else
2007  {
2008  // update the value
2009  (*itCqi).second.at (i) = sinr;
2010  NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr);
2011  // update correspondent timer
2012  std::map <uint16_t, uint32_t>::iterator itTimers;
2013  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
2014  (*itTimers).second = m_cqiTimersThreshold;
2015 
2016  }
2017 
2018  }
2019  // remove obsolete info on allocation
2020  m_allocationMaps.erase (itMap);
2021  }
2022  break;
2023  case UlCqi_s::SRS:
2024  {
2025  // get the RNTI from vendor specific parameters
2026  uint16_t rnti = 0;
2027  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
2028  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
2029  {
2030  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
2031  {
2032  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
2033  rnti = vsp->GetRnti ();
2034  }
2035  }
2036  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2037  itCqi = m_ueCqi.find (rnti);
2038  if (itCqi == m_ueCqi.end ())
2039  {
2040  // create a new entry
2041  std::vector <double> newCqi;
2042  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2043  {
2044  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2045  newCqi.push_back (sinr);
2046  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
2047 
2048  }
2049  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
2050  // generate correspondent timer
2051  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
2052  }
2053  else
2054  {
2055  // update the values
2056  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2057  {
2058  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2059  (*itCqi).second.at (j) = sinr;
2060  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
2061  }
2062  // update correspondent timer
2063  std::map <uint16_t, uint32_t>::iterator itTimers;
2064  itTimers = m_ueCqiTimers.find (rnti);
2065  (*itTimers).second = m_cqiTimersThreshold;
2066 
2067  }
2068 
2069 
2070  }
2071  break;
2072  case UlCqi_s::PUCCH_1:
2073  case UlCqi_s::PUCCH_2:
2074  case UlCqi_s::PRACH:
2075  {
2076  NS_FATAL_ERROR ("TdTbfqFfMacScheduler supports only PUSCH and SRS UL-CQIs");
2077  }
2078  break;
2079  default:
2080  NS_FATAL_ERROR ("Unknown type of UL-CQI");
2081  }
2082  return;
2083 }
2084 
2085 void
2087 {
2088  // refresh DL CQI P01 Map
2089  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
2090  while (itP10 != m_p10CqiTimers.end ())
2091  {
2092  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2093  if ((*itP10).second == 0)
2094  {
2095  // delete correspondent entries
2096  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
2097  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
2098  NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first);
2099  m_p10CqiRxed.erase (itMap);
2100  std::map <uint16_t,uint32_t>::iterator temp = itP10;
2101  itP10++;
2102  m_p10CqiTimers.erase (temp);
2103  }
2104  else
2105  {
2106  (*itP10).second--;
2107  itP10++;
2108  }
2109  }
2110 
2111  // refresh DL CQI A30 Map
2112  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
2113  while (itA30 != m_a30CqiTimers.end ())
2114  {
2115  NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2116  if ((*itA30).second == 0)
2117  {
2118  // delete correspondent entries
2119  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
2120  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
2121  NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first);
2122  m_a30CqiRxed.erase (itMap);
2123  std::map <uint16_t,uint32_t>::iterator temp = itA30;
2124  itA30++;
2125  m_a30CqiTimers.erase (temp);
2126  }
2127  else
2128  {
2129  (*itA30).second--;
2130  itA30++;
2131  }
2132  }
2133 
2134  return;
2135 }
2136 
2137 
2138 void
2140 {
2141  // refresh UL CQI Map
2142  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
2143  while (itUl != m_ueCqiTimers.end ())
2144  {
2145  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2146  if ((*itUl).second == 0)
2147  {
2148  // delete correspondent entries
2149  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
2150  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
2151  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
2152  (*itMap).second.clear ();
2153  m_ueCqi.erase (itMap);
2154  std::map <uint16_t,uint32_t>::iterator temp = itUl;
2155  itUl++;
2156  m_ueCqiTimers.erase (temp);
2157  }
2158  else
2159  {
2160  (*itUl).second--;
2161  itUl++;
2162  }
2163  }
2164 
2165  return;
2166 }
2167 
2168 void
2169 TdTbfqFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
2170 {
2171  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
2172  LteFlowId_t flow (rnti, lcid);
2173  it = m_rlcBufferReq.find (flow);
2174  if (it != m_rlcBufferReq.end ())
2175  {
2176  NS_LOG_INFO (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).second.m_rlcTransmissionQueueSize << " retxqueue " << (*it).second.m_rlcRetransmissionQueueSize << " status " << (*it).second.m_rlcStatusPduSize << " decrease " << size);
2177  // Update queues: RLC tx order Status, ReTx, Tx
2178  // Update status queue
2179  if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
2180  {
2181  (*it).second.m_rlcStatusPduSize = 0;
2182  }
2183  else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
2184  {
2185  (*it).second.m_rlcRetransmissionQueueSize = 0;
2186  }
2187  else if ((*it).second.m_rlcTransmissionQueueSize > 0)
2188  {
2189  uint32_t rlcOverhead;
2190  if (lcid == 1)
2191  {
2192  // for SRB1 (using RLC AM) it's better to
2193  // overestimate RLC overhead rather than
2194  // underestimate it and risk unneeded
2195  // segmentation which increases delay
2196  rlcOverhead = 4;
2197  }
2198  else
2199  {
2200  // minimum RLC overhead due to header
2201  rlcOverhead = 2;
2202  }
2203  // update transmission queue
2204  if ((*it).second.m_rlcTransmissionQueueSize <= size - rlcOverhead)
2205  {
2206  (*it).second.m_rlcTransmissionQueueSize = 0;
2207  }
2208  else
2209  {
2210  (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
2211  }
2212  }
2213  }
2214  else
2215  {
2216  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
2217  }
2218 }
2219 
2220 void
2221 TdTbfqFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
2222 {
2223 
2224  size = size - 2; // remove the minimum RLC overhead
2225  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
2226  if (it != m_ceBsrRxed.end ())
2227  {
2228  NS_LOG_INFO (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
2229  if ((*it).second >= size)
2230  {
2231  (*it).second -= size;
2232  }
2233  else
2234  {
2235  (*it).second = 0;
2236  }
2237  }
2238  else
2239  {
2240  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
2241  }
2242 
2243 }
2244 
2245 void
2247 {
2248  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
2250  params.m_rnti = rnti;
2251  params.m_transmissionMode = txMode;
2253 }
2254 
2255 
2256 }
void DoSchedUlNoiseInterferenceReq(const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters &params)
std::vector< struct UlInfoListElement_s > m_ulInfoList
See section 4.3.1 dlDciListElement.
Definition: ff-mac-common.h:88
void DoCschedLcReleaseReq(const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters &params)
std::map< uint16_t, uint8_t > m_dlHarqCurrentProcessId
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
Service Access Point (SAP) offered by the eNodeB RRC instance to the Frequency Reuse algorithm instan...
Definition: lte-ffr-sap.h:132
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
virtual void DoDispose(void)
Destructor implementation.
void DoSchedDlRlcBufferReq(const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
#define HARQ_PERIOD
Definition: lte-common.h:30
AttributeValue implementation for Boolean.
Definition: boolean.h:34
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
void DoCschedUeConfigReq(const struct FfMacCschedSapProvider::CschedUeConfigReqParameters &params)
virtual void ReportUlCqiInfo(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)=0
ReportUlCqiInfo.
Parameters of the CSCHED_UE_CONFIG_CNF primitive.
Parameters of the CSCHED_UE_RELEASE_REQ primitive.
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
friend class TdTbfqSchedulerMemberCschedSapProvider
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
virtual bool IsDlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in DL.
uint32_t burstCredit
the number of token borrow or given to token bank
virtual bool IsUlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in UL.
FfMacSchedSapProvider * m_schedSapProvider
enum ns3::UlCqi_s::Type_e m_type
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:81
friend class TdTbfqSchedulerMemberSchedSapProvider
std::vector< UlDciListElement_s > UlHarqProcessesDciBuffer_t
uint32_t maxTokenPoolSize
current size of token pool (byte)
std::vector< struct LogicalChannelConfigListElement_s > m_logicalChannelConfigList
std::vector< uint16_t > m_sinr
double EstimateUlSinr(uint16_t rnti, uint16_t rb)
std::vector< uint8_t > DlHarqProcessesTimer_t
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
virtual ~TdTbfqFfMacScheduler()
Destructor.
Hold a signed integer type.
Definition: integer.h:44
virtual void CschedLcReleaseReq(const struct CschedLcReleaseReqParameters &params)
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
std::vector< uint8_t > m_mcs
Definition: ff-mac-common.h:95
See section 4.3.2 ulDciListElement.
Provides the CSCHED SAP.
std::vector< struct UlDciListElement_s > m_dciList
void DoCschedLcConfigReq(const struct FfMacCschedSapProvider::CschedLcConfigReqParameters &params)
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
See section 4.3.10 buildRARListElement.
Parameters of the CSCHED_UE_CONFIG_UPDATE_IND primitive.
Parameters of the CSCHED_LC_RELEASE_REQ primitive.
int counter
maximum size of token pool (byte)
void TransmissionModeConfigurationUpdate(uint16_t rnti, uint8_t txMode)
virtual uint8_t GetTpc(uint16_t rnti)=0
GetTpc.
virtual void CschedLcConfigReq(const struct CschedLcConfigReqParameters &params)
std::map< LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters > m_rlcBufferReq
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
Implements the SCHED SAP and CSCHED SAP for a Time Domain Token Bank Fair Queue scheduler.
std::vector< struct RachListElement_s > m_rachList
Parameters of the SCHED_DL_TRIGGER_REQ primitive.
FfMacCschedSapUser * m_cschedSapUser
void DoSchedUlTriggerReq(const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters &params)
virtual void SchedUlNoiseInterferenceReq(const struct SchedUlNoiseInterferenceReqParameters &params)
std::map< uint16_t, DlHarqProcessesTimer_t > m_dlHarqProcessesTimer
Ptr< const AttributeAccessor > MakeIntegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: integer.h:45
virtual void SchedUlMacCtrlInfoReq(const struct SchedUlMacCtrlInfoReqParameters &params)
std::vector< RlcPduList_t > DlHarqRlcPduListBuffer_t
Parameters of the SCHED_DL_MAC_BUFFER_REQ primitive.
Parameters of the SCHED_DL_PAGING_BUFFER_REQ primitive.
virtual void CschedUeConfigUpdateInd(const struct CschedUeConfigUpdateIndParameters &params)=0
void DoSchedUlSrInfoReq(const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters &params)
std::vector< struct VendorSpecificListElement_s > m_vendorSpecificList
std::map< uint16_t, std::vector< uint16_t > > m_allocationMaps
Service Access Point (SAP) offered by the Frequency Reuse algorithm instance to the MAC Scheduler ins...
Definition: lte-ffr-sap.h:39
Parameters of the SCHED_UL_TRIGGER_REQ primitive.
int debtLimit
the maximum number of tokens connection i can borrow from the bank each time
Hold an unsigned integer type.
Definition: uinteger.h:44
virtual void SetLteFfrSapProvider(LteFfrSapProvider *s)
Set the Provider part of the LteFfrSap that this Scheduler will interact with.
static uint8_t TxMode2LayerNum(uint8_t txMode)
Definition: lte-common.cc:169
std::map< uint16_t, uint32_t > m_a30CqiTimers
virtual void SchedDlCqiInfoReq(const struct SchedDlCqiInfoReqParameters &params)
void UpdateDlRlcBufferInfo(uint16_t rnti, uint8_t lcid, uint16_t size)
std::vector< uint8_t > m_ndi
Definition: ff-mac-common.h:96
virtual void SchedDlTriggerReq(const struct SchedDlTriggerReqParameters &params)
Provides the SCHED SAP.
void DoSchedDlCqiInfoReq(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
void DoSchedDlMacBufferReq(const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters &params)
virtual void CschedUeConfigCnf(const struct CschedUeConfigCnfParameters &params)=0
std::map< uint16_t, UlHarqProcessesDciBuffer_t > m_ulHarqProcessesDciBuffer
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
Parameters of the SCHED_UL_NOISE_INTERFERENCE_REQ primitive.
std::vector< struct CqiListElement_s > m_cqiList
std::map< uint16_t, DlHarqRlcPduListBuffer_t > m_dlHarqProcessesRlcPduListBuffer
std::vector< struct DlInfoListElement_s > m_dlInfoList
virtual void ReportDlCqiInfo(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)=0
ReportDlCqiInfo.
virtual LteFfrSapUser * GetLteFfrSapUser()
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
virtual void SchedDlConfigInd(const struct SchedDlConfigIndParameters &params)=0
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
set the user part of the FfMacSchedSap that this Scheduler will interact with.
std::vector< uint16_t > m_tbsSize
Definition: ff-mac-common.h:94
See section 4.3.9 rlcPDU_ListElement.
uint64_t tokenGenerationRate
packet arrival rate( byte/s)
virtual void SchedDlPagingBufferReq(const struct SchedDlPagingBufferReqParameters &params)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::map< uint16_t, std::vector< double > > m_ueCqi
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
virtual void SchedDlRachInfoReq(const struct SchedDlRachInfoReqParameters &params)
std::vector< DlDciListElement_s > DlHarqProcessesDciBuffer_t
virtual void SchedDlRlcBufferReq(const struct SchedDlRlcBufferReqParameters &params)
Parameters of the CSCHED_LC_CONFIG_REQ primitive.
std::vector< uint8_t > m_rv
Definition: ff-mac-common.h:97
std::map< uint16_t, SbMeasResult_s > m_a30CqiRxed
std::map< uint16_t, uint8_t > m_p10CqiRxed
virtual std::vector< bool > GetAvailableUlRbg()=0
Get vector of available RB in UL for this Cell.
virtual uint8_t GetMinContinuousUlBandwidth()=0
GetMinContinuousUlBandwidth.
virtual void SchedUlConfigInd(const struct SchedUlConfigIndParameters &params)=0
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:224
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
uint32_t creditableThreshold
counter threshold that the flow cannot further borrow tokens from bank
UlCqiFilter_t m_ulCqiFilter
uint32_t tokenPoolSize
token generation rate ( byte/s )
#define SRS_CQI_RNTI_VSP
This abstract base class identifies the interface by means of which the helper object can plug on the...
virtual void CschedCellConfigReq(const struct CschedCellConfigReqParameters &params)
CSCHED_CELL_CONFIG_REQ.
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
set the user part of the FfMacCschedSap that this Scheduler will interact with.
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
virtual void CschedUeConfigReq(const struct CschedUeConfigReqParameters &params)
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct MacCeListElement_s > m_macCeList
std::map< uint16_t, tdtbfqsFlowPerf_t > m_flowStatsDl
std::vector< struct RachListElement_s > m_rachList
static double fpS11dot3toDouble(uint16_t val)
Definition: lte-common.cc:113
bool m_harqOn
m_harqOn when false inhibit te HARQ mechanisms (by default active)
static const int TdTbfqType0AllocationRbg[4]
virtual void SchedUlSrInfoReq(const struct SchedUlSrInfoReqParameters &params)
std::map< uint16_t, uint8_t > m_uesTxMode
std::vector< uint8_t > UlHarqProcessesStatus_t
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
std::map< uint16_t, uint32_t > m_ueCqiTimers
std::vector< uint8_t > DlHarqProcessesStatus_t
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
static uint32_t BsrId2BufferSize(uint8_t val)
Definition: lte-common.cc:141
Template for the implementation of the LteFfrSapUser as a member of an owner class of type C to which...
Definition: lte-ffr-sap.h:244
virtual void SchedDlMacBufferReq(const struct SchedDlMacBufferReqParameters &params)
Parameters of the SCHED_UL_MAC_CTRL_INFO_REQ primitive.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
virtual std::vector< bool > GetAvailableDlRbg()=0
Get vector of available RBG in DL for this Cell.
virtual void CschedUeReleaseReq(const struct CschedUeReleaseReqParameters &params)
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
Parameters of the SCHED_UL_SR_INFO_REQ primitive.
void DoSchedUlCqiInfoReq(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
void DoCschedCellConfigReq(const struct FfMacCschedSapProvider::CschedCellConfigReqParameters &params)
virtual void SchedUlTriggerReq(const struct SchedUlTriggerReqParameters &params)
FfMacCschedSapProvider * m_cschedSapProvider
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:220
std::map< uint16_t, DlHarqProcessesDciBuffer_t > m_dlHarqProcessesDciBuffer
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
Parameters of the SCHED_DL_RACH_INFO_REQ primitive.
Parameters of the SCHED_UL_CONFIG_IND primitive.
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
Parameters of the CSCHED_UE_CONFIG_REQ primitive.
virtual void SchedUlCqiInfoReq(const struct SchedUlCqiInfoReqParameters &params)
#define HARQ_DL_TIMEOUT
LteFfrSapProvider * m_ffrSapProvider
#define NO_SINR
void DoSchedUlMacCtrlInfoReq(const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters &params)
std::vector< uint16_t > m_rachAllocationMap
struct DlDciListElement_s m_dci
std::vector< struct BuildRarListElement_s > m_buildRarList
std::map< uint16_t, UlHarqProcessesStatus_t > m_ulHarqProcessesStatus
std::map< uint16_t, uint32_t > m_ceBsrRxed
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
a unique identifier for an interface.
Definition: type-id.h:58
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
std::map< uint16_t, uint32_t > m_p10CqiTimers
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
#define HARQ_PROC_NUM
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
std::vector< struct BuildDataListElement_s > m_buildDataList
std::map< uint16_t, tdtbfqsFlowPerf_t > m_flowStatsUl
See section 4.3.8 builDataListElement.