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