A Discrete-Event Network Simulator
API
fdtbfq-ff-mac-scheduler.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Marco Miozzo <marco.miozzo@cttc.es>
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/fdtbfq-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 ("FdTbfqFfMacScheduler");
38 
39 static const int FdTbfqType0AllocationRbg[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 (FdTbfqFfMacScheduler);
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::FdTbfqFfMacScheduler")
256  .SetGroupName("Lte")
257  .AddConstructor<FdTbfqFfMacScheduler> ()
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, fdtbfqsFlowPerf_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  fdtbfqsFlowPerf_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, fdtbfqsFlowPerf_t> (params.m_rnti, flowStatsDl));
414  fdtbfqsFlowPerf_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, fdtbfqsFlowPerf_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 < FdTbfqType0AllocationRbg[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  // update token pool, counter and bank size
1121  std::map <uint16_t, fdtbfqsFlowPerf_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  std::set <uint16_t> allocatedRnti; // store UEs which are already assigned RBGs
1137  std::set <uint8_t> allocatedRbg; // store RBGs which are already allocated to UE
1138 
1139  int totalRbg = 0;
1140  while (totalRbg < rbgNum)
1141  {
1142  // select UE with largest metric
1143  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator it;
1144  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator itMax = m_flowStatsDl.end ();
1145  double metricMax = 0.0;
1146  bool firstRnti = true;
1147  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
1148  {
1149  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1150  if ((itRnti != rntiAllocated.end ())||(!HarqProcessAvailability ((*it).first)))
1151  {
1152  // UE already allocated for HARQ or without HARQ process available -> drop it
1153  if (itRnti != rntiAllocated.end ())
1154  {
1155  NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(*it).first);
1156  }
1157  if (!HarqProcessAvailability ((*it).first))
1158  {
1159  NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*it).first);
1160  }
1161  continue;
1162  }
1163 
1164  if (LcActivePerFlow ((*it).first) == 0)
1165  {
1166  continue;
1167  }
1168 
1169  std::set <uint16_t>::iterator rnti;
1170  rnti = allocatedRnti.find((*it).first);
1171  if (rnti != allocatedRnti.end ()) // already allocated RBGs to this UE
1172  {
1173  continue;
1174  }
1175 
1176  double metric = ( ( (double)(*it).second.counter ) / ( (double)(*it).second.tokenGenerationRate ) );
1177 
1178  if (firstRnti == true)
1179  {
1180  metricMax = metric;
1181  itMax = it;
1182  firstRnti = false;
1183  continue;
1184  }
1185  if (metric > metricMax)
1186  {
1187  metricMax = metric;
1188  itMax = it;
1189  }
1190  } // end for m_flowStatsDl
1191 
1192  if (itMax == m_flowStatsDl.end())
1193  {
1194  // all UEs are allocated RBG or all UEs already allocated for HARQ or without HARQ process available
1195  break;
1196  }
1197 
1198  // mark this UE as "allocated"
1199  allocatedRnti.insert((*itMax).first);
1200 
1201  // calculate the maximum number of byte that the scheduler can assigned to this UE
1202  uint32_t budget = 0;
1203  if ( bankSize > 0 )
1204  {
1205  budget = (*itMax).second.counter - (*itMax).second.debtLimit;
1206  if ( budget > (*itMax).second.burstCredit )
1207  budget = (*itMax).second.burstCredit;
1208  if ( budget > bankSize )
1209  budget = bankSize;
1210  }
1211  budget = budget + (*itMax).second.tokenPoolSize;
1212 
1213  // calcualte how much bytes this UE actally need
1214  if (budget == 0)
1215  {
1216  // there are no tokens for this UE
1217  continue;
1218  }
1219  else
1220  {
1221  // calculate rlc buffer size
1222  uint32_t rlcBufSize = 0;
1223  uint8_t lcid = 0;
1224  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itRlcBuf;
1225  for (itRlcBuf = m_rlcBufferReq.begin (); itRlcBuf != m_rlcBufferReq.end (); itRlcBuf++)
1226  {
1227  if ( (*itRlcBuf).first.m_rnti == (*itMax).first )
1228  lcid = (*itRlcBuf).first.m_lcId;
1229  }
1230  LteFlowId_t flow ((*itMax).first, lcid);
1231  itRlcBuf = m_rlcBufferReq.find (flow);
1232  if (itRlcBuf!=m_rlcBufferReq.end ())
1233  rlcBufSize = (*itRlcBuf).second.m_rlcTransmissionQueueSize + (*itRlcBuf).second.m_rlcRetransmissionQueueSize + (*itRlcBuf).second.m_rlcStatusPduSize;
1234  if ( budget > rlcBufSize )
1235  budget = rlcBufSize;
1236  }
1237 
1238  // assign RBGs to this UE
1239  uint32_t bytesTxed = 0;
1240  uint32_t bytesTxedTmp = 0;
1241  int rbgIndex = 0;
1242  while ( bytesTxed <= budget )
1243  {
1244  totalRbg++;
1245 
1246  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1247  itCqi = m_a30CqiRxed.find ((*itMax).first);
1248  std::map <uint16_t,uint8_t>::iterator itTxMode;
1249  itTxMode = m_uesTxMode.find ((*itMax).first);
1250  if (itTxMode == m_uesTxMode.end ())
1251  {
1252  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
1253  }
1254  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1255 
1256  // find RBG with largest achievableRate
1257  double achievableRateMax = 0.0;
1258  rbgIndex = rbgNum;
1259  for (int k = 0; k < rbgNum; k++)
1260  {
1261  std::set <uint8_t>::iterator rbg;
1262  rbg = allocatedRbg.find (k);
1263  if (rbg != allocatedRbg.end ()) // RBGs are already allocated to this UE
1264  continue;
1265 
1266  if ( rbgMap.at (k) == true) // this RBG is allocated in RACH procedure
1267  continue;
1268 
1269  if ((m_ffrSapProvider->IsDlRbgAvailableForUe (k, (*itMax).first)) == false)
1270  continue;
1271 
1272  std::vector <uint8_t> sbCqi;
1273  if (itCqi == m_a30CqiRxed.end ())
1274  {
1275  for (uint8_t k = 0; k < nLayer; k++)
1276  {
1277  sbCqi.push_back (1); // start with lowest value
1278  }
1279  }
1280  else
1281  {
1282  sbCqi = (*itCqi).second.m_higherLayerSelected.at (k).m_sbCqi;
1283  }
1284  uint8_t cqi1 = sbCqi.at (0);
1285  uint8_t cqi2 = 1;
1286  if (sbCqi.size () > 1)
1287  {
1288  cqi2 = sbCqi.at (1);
1289  }
1290 
1291  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1292  {
1293  if (LcActivePerFlow ((*itMax).first) > 0)
1294  {
1295  // this UE has data to transmit
1296  double achievableRate = 0.0;
1297  for (uint8_t j = 0; j < nLayer; j++)
1298  {
1299  uint8_t mcs = 0;
1300  if (sbCqi.size () > j)
1301  {
1302  mcs = m_amc->GetMcsFromCqi (sbCqi.at (j));
1303  }
1304  else
1305  {
1306  // no info on this subband -> worst MCS
1307  mcs = 0;
1308  }
1309  achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, rbgSize) / 8) / 0.001); // = TB size / TTI
1310  }
1311 
1312  if ( achievableRate > achievableRateMax )
1313  {
1314  achievableRateMax = achievableRate;
1315  rbgIndex = k;
1316  }
1317  } // end of LcActivePerFlow
1318  } // end of cqi
1319  } // end of for rbgNum
1320 
1321  if ( rbgIndex == rbgNum) // impossible
1322  {
1323  // all RBGs are already assigned
1324  totalRbg = rbgNum;
1325  break;
1326  }
1327  else
1328  {
1329  // mark this UE as "allocated"
1330  allocatedRbg.insert (rbgIndex);
1331  }
1332 
1333  // assign this RBG to UE
1334  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1335  itMap = allocationMap.find ((*itMax).first);
1336  uint16_t RbgPerRnti;
1337  if (itMap == allocationMap.end ())
1338  {
1339  // insert new element
1340  std::vector <uint16_t> tempMap;
1341  tempMap.push_back (rbgIndex);
1342  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
1343  itMap = allocationMap.find ((*itMax).first); // point itMap to the first RBGs assigned to this UE
1344  }
1345  else
1346  {
1347  (*itMap).second.push_back (rbgIndex);
1348  }
1349  rbgMap.at (rbgIndex) = true; // Mark this RBG as allocated
1350 
1351  RbgPerRnti = (*itMap).second.size();
1352 
1353  // calculate tb size
1354  std::vector <uint8_t> worstCqi (2, 15);
1355  if (itCqi != m_a30CqiRxed.end ())
1356  {
1357  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1358  {
1359  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
1360  {
1361  for (uint8_t j = 0; j < nLayer; j++)
1362  {
1363  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
1364  {
1365  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
1366  {
1367  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
1368  }
1369  }
1370  else
1371  {
1372  // no CQI for this layer of this suband -> worst one
1373  worstCqi.at (j) = 1;
1374  }
1375  }
1376  }
1377  else
1378  {
1379  for (uint8_t j = 0; j < nLayer; j++)
1380  {
1381  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1382  }
1383  }
1384  }
1385  }
1386  else
1387  {
1388  for (uint8_t j = 0; j < nLayer; j++)
1389  {
1390  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1391  }
1392  }
1393 
1394  bytesTxedTmp = bytesTxed;
1395  bytesTxed = 0;
1396  for (uint8_t j = 0; j < nLayer; j++)
1397  {
1398  int tbSize = (m_amc->GetTbSizeFromMcs (m_amc->GetMcsFromCqi (worstCqi.at (j)), RbgPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
1399  bytesTxed += tbSize;
1400  }
1401 
1402  } // end of while()
1403 
1404  // remove and unmark last RBG assigned to UE
1405  if ( bytesTxed > budget )
1406  {
1407  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1408  itMap = allocationMap.find ((*itMax).first);
1409  (*itMap).second.pop_back ();
1410  allocatedRbg.erase (rbgIndex);
1411  bytesTxed = bytesTxedTmp; // recovery bytesTxed
1412  totalRbg--;
1413  rbgMap.at (rbgIndex) = false; // unmark this RBG
1414  }
1415 
1416  // update UE stats
1417  if ( bytesTxed <= (*itMax).second.tokenPoolSize )
1418  {
1419  (*itMax).second.tokenPoolSize -= bytesTxed;
1420  }
1421  else
1422  {
1423  (*itMax).second.counter = (*itMax).second.counter - ( bytesTxed - (*itMax).second.tokenPoolSize );
1424  (*itMax).second.tokenPoolSize = 0;
1425  if (bankSize <= ( bytesTxed - (*itMax).second.tokenPoolSize ))
1426  bankSize = 0;
1427  else
1428  bankSize = bankSize - ( bytesTxed - (*itMax).second.tokenPoolSize );
1429  }
1430  } // end of RBGs
1431 
1432  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
1433  // creating the correspondent DCIs
1434  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
1435  while (itMap != allocationMap.end ())
1436  {
1437  // create new BuildDataListElement_s for this LC
1438  BuildDataListElement_s newEl;
1439  newEl.m_rnti = (*itMap).first;
1440  // create the DlDciListElement_s
1441  DlDciListElement_s newDci;
1442  newDci.m_rnti = (*itMap).first;
1443  newDci.m_harqProcess = UpdateHarqProcessId ((*itMap).first);
1444 
1445  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
1446  NS_LOG_INFO (this << "Allocate user " << newEl.m_rnti << " rbg " << lcActives);
1447  if (lcActives == 0)
1448  {
1449  // Set to max value, to avoid divide by 0 below
1450  lcActives = (uint16_t)65535; // UINT16_MAX;
1451  }
1452  uint16_t RgbPerRnti = (*itMap).second.size ();
1453  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1454  itCqi = m_a30CqiRxed.find ((*itMap).first);
1455  std::map <uint16_t,uint8_t>::iterator itTxMode;
1456  itTxMode = m_uesTxMode.find ((*itMap).first);
1457  if (itTxMode == m_uesTxMode.end ())
1458  {
1459  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
1460  }
1461  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1462  std::vector <uint8_t> worstCqi (2, 15);
1463  if (itCqi != m_a30CqiRxed.end ())
1464  {
1465  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1466  {
1467  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
1468  {
1469  NS_LOG_INFO (this << " RBG " << (*itMap).second.at (k) << " CQI " << (uint16_t)((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)) );
1470  for (uint8_t j = 0; j < nLayer; j++)
1471  {
1472  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
1473  {
1474  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
1475  {
1476  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
1477  }
1478  }
1479  else
1480  {
1481  // no CQI for this layer of this suband -> worst one
1482  worstCqi.at (j) = 1;
1483  }
1484  }
1485  }
1486  else
1487  {
1488  for (uint8_t j = 0; j < nLayer; j++)
1489  {
1490  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1491  }
1492  }
1493  }
1494  }
1495  else
1496  {
1497  for (uint8_t j = 0; j < nLayer; j++)
1498  {
1499  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1500  }
1501  }
1502  for (uint8_t j = 0; j < nLayer; j++)
1503  {
1504  NS_LOG_INFO (this << " Layer " << (uint16_t)j << " CQI selected " << (uint16_t)worstCqi.at (j));
1505  }
1506  uint32_t bytesTxed = 0;
1507  for (uint8_t j = 0; j < nLayer; j++)
1508  {
1509  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
1510  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)
1511  newDci.m_tbsSize.push_back (tbSize);
1512  NS_LOG_INFO (this << " Layer " << (uint16_t)j << " MCS selected" << m_amc->GetMcsFromCqi (worstCqi.at (j)));
1513  bytesTxed += tbSize;
1514  }
1515 
1516  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
1517  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
1518  uint32_t rbgMask = 0;
1519  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1520  {
1521  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
1522  NS_LOG_INFO (this << " Allocated RBG " << (*itMap).second.at (k));
1523  }
1524  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1525 
1526  // create the rlc PDUs -> equally divide resources among actives LCs
1527  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
1528  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
1529  {
1530  if (((*itBufReq).first.m_rnti == (*itMap).first)
1531  && (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
1532  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
1533  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
1534  {
1535  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1536  for (uint8_t j = 0; j < nLayer; j++)
1537  {
1538  RlcPduListElement_s newRlcEl;
1539  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
1540  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
1541  NS_LOG_INFO (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j);
1542  newRlcPduLe.push_back (newRlcEl);
1543  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
1544  if (m_harqOn == true)
1545  {
1546  // store RLC PDU list for HARQ
1547  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*itMap).first);
1548  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1549  {
1550  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*itMap).first);
1551  }
1552  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1553  }
1554  }
1555  newEl.m_rlcPduList.push_back (newRlcPduLe);
1556  }
1557  if ((*itBufReq).first.m_rnti > (*itMap).first)
1558  {
1559  break;
1560  }
1561  }
1562  for (uint8_t j = 0; j < nLayer; j++)
1563  {
1564  newDci.m_ndi.push_back (1);
1565  newDci.m_rv.push_back (0);
1566  }
1567 
1568  newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
1569 
1570  newEl.m_dci = newDci;
1571 
1572  if (m_harqOn == true)
1573  {
1574  // store DCI for HARQ
1575  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1576  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1577  {
1578  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1579  }
1580  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1581  // refresh timer
1582  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1583  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1584  {
1585  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1586  }
1587  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1588  }
1589 
1590  // ...more parameters -> ingored in this version
1591 
1592  ret.m_buildDataList.push_back (newEl);
1593 
1594  itMap++;
1595  } // end while allocation
1596  ret.m_nrOfPdcchOfdmSymbols = 1;
1597 
1599 
1600 
1601  return;
1602 }
1603 
1604 void
1606 {
1607  NS_LOG_FUNCTION (this);
1608 
1609  m_rachList = params.m_rachList;
1610 
1611  return;
1612 }
1613 
1614 void
1616 {
1617  NS_LOG_FUNCTION (this);
1619 
1620  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1621  {
1622  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1623  {
1624  NS_LOG_LOGIC ("wideband CQI " << (uint32_t) params.m_cqiList.at (i).m_wbCqi.at (0) << " reported");
1625  std::map <uint16_t,uint8_t>::iterator it;
1626  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1627  it = m_p10CqiRxed.find (rnti);
1628  if (it == m_p10CqiRxed.end ())
1629  {
1630  // create the new entry
1631  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)
1632  // generate correspondent timer
1633  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1634  }
1635  else
1636  {
1637  // update the CQI value and refresh correspondent timer
1638  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1639  // update correspondent timer
1640  std::map <uint16_t,uint32_t>::iterator itTimers;
1641  itTimers = m_p10CqiTimers.find (rnti);
1642  (*itTimers).second = m_cqiTimersThreshold;
1643  }
1644  }
1645  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1646  {
1647  // subband CQI reporting high layer configured
1648  std::map <uint16_t,SbMeasResult_s>::iterator it;
1649  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1650  it = m_a30CqiRxed.find (rnti);
1651  if (it == m_a30CqiRxed.end ())
1652  {
1653  // create the new entry
1654  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
1655  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1656  }
1657  else
1658  {
1659  // update the CQI value and refresh correspondent timer
1660  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
1661  std::map <uint16_t,uint32_t>::iterator itTimers;
1662  itTimers = m_a30CqiTimers.find (rnti);
1663  (*itTimers).second = m_cqiTimersThreshold;
1664  }
1665  }
1666  else
1667  {
1668  NS_LOG_ERROR (this << " CQI type unknown");
1669  }
1670  }
1671 
1672  return;
1673 }
1674 
1675 
1676 double
1677 FdTbfqFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
1678 {
1679  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
1680  if (itCqi == m_ueCqi.end ())
1681  {
1682  // no cqi info about this UE
1683  return (NO_SINR);
1684 
1685  }
1686  else
1687  {
1688  // take the average SINR value among the available
1689  double sinrSum = 0;
1690  unsigned int sinrNum = 0;
1691  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1692  {
1693  double sinr = (*itCqi).second.at (i);
1694  if (sinr != NO_SINR)
1695  {
1696  sinrSum += sinr;
1697  sinrNum++;
1698  }
1699  }
1700  double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
1701  // store the value
1702  (*itCqi).second.at (rb) = estimatedSinr;
1703  return (estimatedSinr);
1704  }
1705 }
1706 
1707 void
1709 {
1710  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1711 
1712  RefreshUlCqiMaps ();
1714 
1715  // Generate RBs map
1717  std::vector <bool> rbMap;
1718  uint16_t rbAllocatedNum = 0;
1719  std::set <uint16_t> rntiAllocated;
1720  std::vector <uint16_t> rbgAllocationMap;
1721  // update with RACH allocation map
1722  rbgAllocationMap = m_rachAllocationMap;
1723  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1724  m_rachAllocationMap.clear ();
1726 
1727  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1728 
1729  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
1730 
1731  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
1732  {
1733  if ((*it) == true )
1734  {
1735  rbAllocatedNum++;
1736  }
1737  }
1738 
1739  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
1740  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
1741 
1742  // remove RACH allocation
1743  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1744  {
1745  if (rbgAllocationMap.at (i) != 0)
1746  {
1747  rbMap.at (i) = true;
1748  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1749  }
1750  }
1751 
1752 
1753  if (m_harqOn == true)
1754  {
1755  // Process UL HARQ feedback
1756  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1757  {
1758  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1759  {
1760  // retx correspondent block: retrieve the UL-DCI
1761  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1762  std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1763  if (itProcId == m_ulHarqCurrentProcessId.end ())
1764  {
1765  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1766  }
1767  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1768  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId << " i " << i << " size " << params.m_ulInfoList.size ());
1769  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1770  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1771  {
1772  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1773  continue;
1774  }
1775  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1776  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1777  if (itStat == m_ulHarqProcessesStatus.end ())
1778  {
1779  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1780  }
1781  if ((*itStat).second.at (harqId) >= 3)
1782  {
1783  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1784  continue;
1785  }
1786  bool free = true;
1787  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1788  {
1789  if (rbMap.at (j) == true)
1790  {
1791  free = false;
1792  NS_LOG_INFO (this << " BUSY " << j);
1793  }
1794  }
1795  if (free)
1796  {
1797  // retx on the same RBs
1798  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1799  {
1800  rbMap.at (j) = true;
1801  rbgAllocationMap.at (j) = dci.m_rnti;
1802  NS_LOG_INFO ("\tRB " << j);
1803  rbAllocatedNum++;
1804  }
1805  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);
1806  }
1807  else
1808  {
1809  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1810  continue;
1811  }
1812  dci.m_ndi = 0;
1813  // Update HARQ buffers with new HarqId
1814  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1815  (*itStat).second.at (harqId) = 0;
1816  (*itHarq).second.at ((*itProcId).second) = dci;
1817  ret.m_dciList.push_back (dci);
1818  rntiAllocated.insert (dci.m_rnti);
1819  }
1820  else
1821  {
1822  NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
1823  }
1824  }
1825  }
1826 
1827  std::map <uint16_t,uint32_t>::iterator it;
1828  int nflows = 0;
1829 
1830  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1831  {
1832  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1833  // select UEs with queues not empty and not yet allocated for HARQ
1834  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1835  {
1836  nflows++;
1837  }
1838  }
1839 
1840  if (nflows == 0)
1841  {
1842  if (ret.m_dciList.size () > 0)
1843  {
1844  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1846  }
1847 
1848  return; // no flows to be scheduled
1849  }
1850 
1851 
1852  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1853  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
1854  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
1855 
1856  if (rbPerFlow < 3)
1857  {
1858  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1859  }
1860  int rbAllocated = 0;
1861 
1862  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator itStats;
1863  if (m_nextRntiUl != 0)
1864  {
1865  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1866  {
1867  if ((*it).first == m_nextRntiUl)
1868  {
1869  break;
1870  }
1871  }
1872  if (it == m_ceBsrRxed.end ())
1873  {
1874  NS_LOG_ERROR (this << " no user found");
1875  }
1876  }
1877  else
1878  {
1879  it = m_ceBsrRxed.begin ();
1880  m_nextRntiUl = (*it).first;
1881  }
1882  do
1883  {
1884  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1885  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1886  {
1887  // UE already allocated for UL-HARQ -> skip it
1888  NS_LOG_DEBUG (this << " UE already allocated in HARQ -> discared, RNTI " << (*it).first);
1889  it++;
1890  if (it == m_ceBsrRxed.end ())
1891  {
1892  // restart from the first
1893  it = m_ceBsrRxed.begin ();
1894  }
1895  continue;
1896  }
1897  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1898  {
1899  // limit to physical resources last resource assignment
1900  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1901  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1902  if (rbPerFlow < 3)
1903  {
1904  // terminate allocation
1905  rbPerFlow = 0;
1906  }
1907  }
1908 
1909  rbAllocated = 0;
1910  UlDciListElement_s uldci;
1911  uldci.m_rnti = (*it).first;
1912  uldci.m_rbLen = rbPerFlow;
1913  bool allocated = false;
1914  NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1915  while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
1916  {
1917  // check availability
1918  bool free = true;
1919  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1920  {
1921  if (rbMap.at (j) == true)
1922  {
1923  free = false;
1924  break;
1925  }
1926  if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
1927  {
1928  free = false;
1929  break;
1930  }
1931  }
1932  if (free)
1933  {
1934  NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1935  uldci.m_rbStart = rbAllocated;
1936 
1937  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1938  {
1939  rbMap.at (j) = true;
1940  // store info on allocation for managing ul-cqi interpretation
1941  rbgAllocationMap.at (j) = (*it).first;
1942  }
1943  rbAllocated += rbPerFlow;
1944  allocated = true;
1945  break;
1946  }
1947  rbAllocated++;
1948  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1949  {
1950  // limit to physical resources last resource assignment
1951  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1952  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1953  if (rbPerFlow < 3)
1954  {
1955  // terminate allocation
1956  rbPerFlow = 0;
1957  }
1958  }
1959  }
1960  if (!allocated)
1961  {
1962  // unable to allocate new resource: finish scheduling
1963 // m_nextRntiUl = (*it).first;
1964 // if (ret.m_dciList.size () > 0)
1965 // {
1966 // m_schedSapUser->SchedUlConfigInd (ret);
1967 // }
1968 // m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1969 // return;
1970  break;
1971  }
1972 
1973 
1974 
1975  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1976  int cqi = 0;
1977  if (itCqi == m_ueCqi.end ())
1978  {
1979  // no cqi info about this UE
1980  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1981  }
1982  else
1983  {
1984  // take the lowest CQI value (worst RB)
1985  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1986  if (minSinr == NO_SINR)
1987  {
1988  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
1989  }
1990  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1991  {
1992  double sinr = (*itCqi).second.at (i);
1993  if (sinr == NO_SINR)
1994  {
1995  sinr = EstimateUlSinr ((*it).first, i);
1996  }
1997  if ((*itCqi).second.at (i) < minSinr)
1998  {
1999  minSinr = (*itCqi).second.at (i);
2000  }
2001  }
2002 
2003  // translate SINR -> cqi: WILD ACK: same as DL
2004  double s = log2 ( 1 + (
2005  std::pow (10, minSinr / 10 ) /
2006  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
2007  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
2008  if (cqi == 0)
2009  {
2010  it++;
2011  if (it == m_ceBsrRxed.end ())
2012  {
2013  // restart from the first
2014  it = m_ceBsrRxed.begin ();
2015  }
2016  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
2017  // remove UE from allocation map
2018  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
2019  {
2020  rbgAllocationMap.at (i) = 0;
2021  }
2022  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
2023  }
2024  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
2025  }
2026 
2027  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
2028  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
2029  uldci.m_ndi = 1;
2030  uldci.m_cceIndex = 0;
2031  uldci.m_aggrLevel = 1;
2032  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
2033  uldci.m_hopping = false;
2034  uldci.m_n2Dmrs = 0;
2035  uldci.m_tpc = 0; // no power control
2036  uldci.m_cqiRequest = false; // only period CQI at this stage
2037  uldci.m_ulIndex = 0; // TDD parameter
2038  uldci.m_dai = 1; // TDD parameter
2039  uldci.m_freqHopping = 0;
2040  uldci.m_pdcchPowerOffset = 0; // not used
2041  ret.m_dciList.push_back (uldci);
2042  // store DCI for HARQ_PERIOD
2043  uint8_t harqId = 0;
2044  if (m_harqOn == true)
2045  {
2046  std::map <uint16_t, uint8_t>::iterator itProcId;
2047  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
2048  if (itProcId == m_ulHarqCurrentProcessId.end ())
2049  {
2050  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
2051  }
2052  harqId = (*itProcId).second;
2053  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
2054  if (itDci == m_ulHarqProcessesDciBuffer.end ())
2055  {
2056  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
2057  }
2058  (*itDci).second.at (harqId) = uldci;
2059  // Update HARQ process status (RV 0)
2060  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (uldci.m_rnti);
2061  if (itStat == m_ulHarqProcessesStatus.end ())
2062  {
2063  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << uldci.m_rnti);
2064  }
2065  (*itStat).second.at (harqId) = 0;
2066  }
2067 
2068  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);
2069 
2070  it++;
2071  if (it == m_ceBsrRxed.end ())
2072  {
2073  // restart from the first
2074  it = m_ceBsrRxed.begin ();
2075  }
2076  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
2077  {
2078  // Stop allocation: no more PRBs
2079  m_nextRntiUl = (*it).first;
2080  break;
2081  }
2082  }
2083  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
2084 
2085 
2086  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
2088 
2089  return;
2090 }
2091 
2092 void
2094 {
2095  NS_LOG_FUNCTION (this);
2096  return;
2097 }
2098 
2099 void
2101 {
2102  NS_LOG_FUNCTION (this);
2103  return;
2104 }
2105 
2106 void
2108 {
2109  NS_LOG_FUNCTION (this);
2110 
2111  std::map <uint16_t,uint32_t>::iterator it;
2112 
2113  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
2114  {
2115  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
2116  {
2117  // buffer status report
2118  // note that this scheduler does not differentiate the
2119  // allocation according to which LCGs have more/less bytes
2120  // to send.
2121  // Hence the BSR of different LCGs are just summed up to get
2122  // a total queue size that is used for allocation purposes.
2123 
2124  uint32_t buffer = 0;
2125  for (uint8_t lcg = 0; lcg < 4; ++lcg)
2126  {
2127  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
2128  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
2129  }
2130 
2131  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
2132  NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
2133  it = m_ceBsrRxed.find (rnti);
2134  if (it == m_ceBsrRxed.end ())
2135  {
2136  // create the new entry
2137  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
2138  }
2139  else
2140  {
2141  // update the buffer size value
2142  (*it).second = buffer;
2143  }
2144  }
2145  }
2146 
2147  return;
2148 }
2149 
2150 void
2152 {
2153  NS_LOG_FUNCTION (this);
2154 // retrieve the allocation for this subframe
2155  switch (m_ulCqiFilter)
2156  {
2158  {
2159  // filter all the CQIs that are not SRS based
2160  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
2161  {
2162  return;
2163  }
2164  }
2165  break;
2167  {
2168  // filter all the CQIs that are not SRS based
2169  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
2170  {
2171  return;
2172  }
2173  }
2175  break;
2176 
2177  default:
2178  NS_FATAL_ERROR ("Unknown UL CQI type");
2179  }
2180 
2181  switch (params.m_ulCqi.m_type)
2182  {
2183  case UlCqi_s::PUSCH:
2184  {
2185  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
2186  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2187  NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
2188  itMap = m_allocationMaps.find (params.m_sfnSf);
2189  if (itMap == m_allocationMaps.end ())
2190  {
2191  return;
2192  }
2193  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
2194  {
2195  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
2196  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
2197  itCqi = m_ueCqi.find ((*itMap).second.at (i));
2198  if (itCqi == m_ueCqi.end ())
2199  {
2200  // create a new entry
2201  std::vector <double> newCqi;
2202  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2203  {
2204  if (i == j)
2205  {
2206  newCqi.push_back (sinr);
2207  }
2208  else
2209  {
2210  // initialize with NO_SINR value.
2211  newCqi.push_back (NO_SINR);
2212  }
2213 
2214  }
2215  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
2216  // generate correspondent timer
2217  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
2218  }
2219  else
2220  {
2221  // update the value
2222  (*itCqi).second.at (i) = sinr;
2223  NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr);
2224  // update correspondent timer
2225  std::map <uint16_t, uint32_t>::iterator itTimers;
2226  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
2227  (*itTimers).second = m_cqiTimersThreshold;
2228 
2229  }
2230 
2231  }
2232  // remove obsolete info on allocation
2233  m_allocationMaps.erase (itMap);
2234  }
2235  break;
2236  case UlCqi_s::SRS:
2237  {
2238  // get the RNTI from vendor specific parameters
2239  uint16_t rnti = 0;
2240  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
2241  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
2242  {
2243  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
2244  {
2245  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
2246  rnti = vsp->GetRnti ();
2247  }
2248  }
2249  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2250  itCqi = m_ueCqi.find (rnti);
2251  if (itCqi == m_ueCqi.end ())
2252  {
2253  // create a new entry
2254  std::vector <double> newCqi;
2255  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2256  {
2257  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2258  newCqi.push_back (sinr);
2259  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
2260 
2261  }
2262  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
2263  // generate correspondent timer
2264  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
2265  }
2266  else
2267  {
2268  // update the values
2269  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2270  {
2271  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2272  (*itCqi).second.at (j) = sinr;
2273  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
2274  }
2275  // update correspondent timer
2276  std::map <uint16_t, uint32_t>::iterator itTimers;
2277  itTimers = m_ueCqiTimers.find (rnti);
2278  (*itTimers).second = m_cqiTimersThreshold;
2279 
2280  }
2281 
2282 
2283  }
2284  break;
2285  case UlCqi_s::PUCCH_1:
2286  case UlCqi_s::PUCCH_2:
2287  case UlCqi_s::PRACH:
2288  {
2289  NS_FATAL_ERROR ("FdTbfqFfMacScheduler supports only PUSCH and SRS UL-CQIs");
2290  }
2291  break;
2292  default:
2293  NS_FATAL_ERROR ("Unknown type of UL-CQI");
2294  }
2295  return;
2296 }
2297 
2298 void
2300 {
2301  // refresh DL CQI P01 Map
2302  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
2303  while (itP10 != m_p10CqiTimers.end ())
2304  {
2305  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2306  if ((*itP10).second == 0)
2307  {
2308  // delete correspondent entries
2309  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
2310  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
2311  NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first);
2312  m_p10CqiRxed.erase (itMap);
2313  std::map <uint16_t,uint32_t>::iterator temp = itP10;
2314  itP10++;
2315  m_p10CqiTimers.erase (temp);
2316  }
2317  else
2318  {
2319  (*itP10).second--;
2320  itP10++;
2321  }
2322  }
2323 
2324  // refresh DL CQI A30 Map
2325  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
2326  while (itA30 != m_a30CqiTimers.end ())
2327  {
2328  NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2329  if ((*itA30).second == 0)
2330  {
2331  // delete correspondent entries
2332  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
2333  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
2334  NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first);
2335  m_a30CqiRxed.erase (itMap);
2336  std::map <uint16_t,uint32_t>::iterator temp = itA30;
2337  itA30++;
2338  m_a30CqiTimers.erase (temp);
2339  }
2340  else
2341  {
2342  (*itA30).second--;
2343  itA30++;
2344  }
2345  }
2346 
2347  return;
2348 }
2349 
2350 
2351 void
2353 {
2354  // refresh UL CQI Map
2355  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
2356  while (itUl != m_ueCqiTimers.end ())
2357  {
2358  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2359  if ((*itUl).second == 0)
2360  {
2361  // delete correspondent entries
2362  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
2363  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
2364  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
2365  (*itMap).second.clear ();
2366  m_ueCqi.erase (itMap);
2367  std::map <uint16_t,uint32_t>::iterator temp = itUl;
2368  itUl++;
2369  m_ueCqiTimers.erase (temp);
2370  }
2371  else
2372  {
2373  (*itUl).second--;
2374  itUl++;
2375  }
2376  }
2377 
2378  return;
2379 }
2380 
2381 void
2382 FdTbfqFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
2383 {
2384  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
2385  LteFlowId_t flow (rnti, lcid);
2386  it = m_rlcBufferReq.find (flow);
2387  if (it != m_rlcBufferReq.end ())
2388  {
2389  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);
2390  // Update queues: RLC tx order Status, ReTx, Tx
2391  // Update status queue
2392  if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
2393  {
2394  (*it).second.m_rlcStatusPduSize = 0;
2395  }
2396  else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
2397  {
2398  (*it).second.m_rlcRetransmissionQueueSize = 0;
2399  }
2400  else if ((*it).second.m_rlcTransmissionQueueSize > 0)
2401  {
2402  uint32_t rlcOverhead;
2403  if (lcid == 1)
2404  {
2405  // for SRB1 (using RLC AM) it's better to
2406  // overestimate RLC overhead rather than
2407  // underestimate it and risk unneeded
2408  // segmentation which increases delay
2409  rlcOverhead = 4;
2410  }
2411  else
2412  {
2413  // minimum RLC overhead due to header
2414  rlcOverhead = 2;
2415  }
2416  // update transmission queue
2417  if ((*it).second.m_rlcTransmissionQueueSize <= size - rlcOverhead)
2418  {
2419  (*it).second.m_rlcTransmissionQueueSize = 0;
2420  }
2421  else
2422  {
2423  (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
2424  }
2425  }
2426  }
2427  else
2428  {
2429  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
2430  }
2431 }
2432 
2433 void
2434 FdTbfqFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
2435 {
2436 
2437  size = size - 2; // remove the minimum RLC overhead
2438  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
2439  if (it != m_ceBsrRxed.end ())
2440  {
2441  NS_LOG_INFO (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
2442  if ((*it).second >= size)
2443  {
2444  (*it).second -= size;
2445  }
2446  else
2447  {
2448  (*it).second = 0;
2449  }
2450  }
2451  else
2452  {
2453  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
2454  }
2455 
2456 }
2457 
2458 void
2460 {
2461  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
2463  params.m_rnti = rnti;
2464  params.m_transmissionMode = txMode;
2466 }
2467 
2468 
2469 }
std::vector< struct UlInfoListElement_s > m_ulInfoList
See section 4.3.1 dlDciListElement.
Definition: ff-mac-common.h:88
std::map< uint16_t, uint32_t > m_a30CqiTimers
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
set the user part of the FfMacCschedSap that this Scheduler will interact with.
void DoCschedCellConfigReq(const struct FfMacCschedSapProvider::CschedCellConfigReqParameters &params)
uint32_t creditableThreshold
counter threshold that the flow cannot further borrow tokens from bank
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 "...
std::map< uint16_t, uint8_t > m_uesTxMode
std::map< uint16_t, std::vector< double > > m_ueCqi
#define HARQ_PERIOD
Definition: lte-common.h:30
AttributeValue implementation for Boolean.
Definition: boolean.h:34
std::map< LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters > m_rlcBufferReq
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
virtual void ReportUlCqiInfo(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)=0
ReportUlCqiInfo.
std::map< uint16_t, SbMeasResult_s > m_a30CqiRxed
Parameters of the CSCHED_UE_CONFIG_CNF primitive.
Parameters of the CSCHED_UE_RELEASE_REQ primitive.
void DoSchedUlNoiseInterferenceReq(const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters &params)
void DoCschedLcConfigReq(const struct FfMacCschedSapProvider::CschedLcConfigReqParameters &params)
virtual bool IsDlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in DL.
virtual bool IsUlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in UL.
std::map< uint16_t, UlHarqProcessesDciBuffer_t > m_ulHarqProcessesDciBuffer
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
void DoSchedUlSrInfoReq(const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters &params)
std::vector< UlDciListElement_s > UlHarqProcessesDciBuffer_t
std::vector< struct LogicalChannelConfigListElement_s > m_logicalChannelConfigList
std::vector< uint16_t > m_sinr
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
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
Hold a signed integer type.
Definition: integer.h:44
int debtLimit
the maximum number of tokens connection i can borrow from the bank each time
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
std::vector< uint8_t > m_mcs
Definition: ff-mac-common.h:95
void DoSchedDlCqiInfoReq(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
See section 4.3.2 ulDciListElement.
Provides the CSCHED SAP.
bool m_harqOn
m_harqOn when false inhibit te HARQ mechanisms (by default active)
uint32_t tokenPoolSize
token generation rate ( byte/s )
std::vector< struct UlDciListElement_s > m_dciList
virtual void SchedDlRachInfoReq(const struct SchedDlRachInfoReqParameters &params)
virtual void CschedLcConfigReq(const struct CschedLcConfigReqParameters &params)
virtual void SchedDlCqiInfoReq(const struct SchedDlCqiInfoReqParameters &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.
virtual void SchedUlSrInfoReq(const struct SchedUlSrInfoReqParameters &params)
Parameters of the CSCHED_UE_CONFIG_UPDATE_IND primitive.
virtual void SchedUlNoiseInterferenceReq(const struct SchedUlNoiseInterferenceReqParameters &params)
std::map< uint16_t, fdtbfqsFlowPerf_t > m_flowStatsUl
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
Parameters of the CSCHED_LC_RELEASE_REQ primitive.
virtual uint8_t GetTpc(uint16_t rnti)=0
GetTpc.
virtual void SetLteFfrSapProvider(LteFfrSapProvider *s)
Set the Provider part of the LteFfrSap that this Scheduler will interact with.
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
Parameters of the SCHED_DL_TRIGGER_REQ primitive.
virtual ~FdTbfqFfMacScheduler()
Destructor.
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 CschedUeReleaseReq(const struct CschedUeReleaseReqParameters &params)
virtual void SchedUlTriggerReq(const struct SchedUlTriggerReqParameters &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
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
set the user part of the FfMacSchedSap that this Scheduler will interact with.
std::vector< struct RachListElement_s > m_rachList
std::vector< struct VendorSpecificListElement_s > m_vendorSpecificList
virtual void SchedDlRlcBufferReq(const struct SchedDlRlcBufferReqParameters &params)
std::map< uint16_t, std::vector< uint16_t > > m_allocationMaps
std::map< uint16_t, DlHarqProcessesDciBuffer_t > m_dlHarqProcessesDciBuffer
virtual void SchedDlTriggerReq(const struct SchedDlTriggerReqParameters &params)
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
friend class FdTbfqSchedulerMemberCschedSapProvider
std::map< uint16_t, DlHarqProcessesTimer_t > m_dlHarqProcessesTimer
void DoCschedLcReleaseReq(const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters &params)
std::map< uint16_t, fdtbfqsFlowPerf_t > m_flowStatsDl
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.
Hold an unsigned integer type.
Definition: uinteger.h:44
static uint8_t TxMode2LayerNum(uint8_t txMode)
Definition: lte-common.cc:169
std::vector< uint8_t > m_ndi
Definition: ff-mac-common.h:96
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
Provides the SCHED SAP.
LteFfrSapProvider * m_ffrSapProvider
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
virtual void CschedUeConfigCnf(const struct CschedUeConfigCnfParameters &params)=0
std::vector< uint16_t > m_rachAllocationMap
std::map< uint16_t, uint32_t > m_p10CqiTimers
#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::vector< struct DlInfoListElement_s > m_dlInfoList
void DoSchedDlRlcBufferReq(const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
std::map< uint16_t, uint32_t > m_ueCqiTimers
virtual void ReportDlCqiInfo(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)=0
ReportDlCqiInfo.
Implements the SCHED SAP and CSCHED SAP for a Frequency Domain Token Bank Fair Queue scheduler...
virtual void SchedDlConfigInd(const struct SchedDlConfigIndParameters &params)=0
std::vector< uint16_t > m_tbsSize
Definition: ff-mac-common.h:94
See section 4.3.9 rlcPDU_ListElement.
void DoSchedUlMacCtrlInfoReq(const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters &params)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
std::vector< DlDciListElement_s > DlHarqProcessesDciBuffer_t
Parameters of the CSCHED_LC_CONFIG_REQ primitive.
virtual void CschedCellConfigReq(const struct CschedCellConfigReqParameters &params)
CSCHED_CELL_CONFIG_REQ.
virtual void CschedLcReleaseReq(const struct CschedLcReleaseReqParameters &params)
std::vector< uint8_t > m_rv
Definition: ff-mac-common.h:97
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
std::map< uint16_t, uint8_t > m_dlHarqCurrentProcessId
virtual std::vector< bool > GetAvailableUlRbg()=0
Get vector of available RB in UL for this Cell.
FfMacCschedSapProvider * m_cschedSapProvider
virtual uint8_t GetMinContinuousUlBandwidth()=0
GetMinContinuousUlBandwidth.
uint64_t tokenGenerationRate
packet arrival rate( byte/s)
virtual void SchedUlConfigInd(const struct SchedUlConfigIndParameters &params)=0
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:224
double EstimateUlSinr(uint16_t rnti, uint16_t rb)
std::map< uint16_t, DlHarqRlcPduListBuffer_t > m_dlHarqProcessesRlcPduListBuffer
UlCqiFilter_t m_ulCqiFilter
#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 SchedDlMacBufferReq(const struct SchedDlMacBufferReqParameters &params)
#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
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct MacCeListElement_s > m_macCeList
uint32_t burstCredit
the number of token borrow or given to token bank
virtual LteFfrSapUser * GetLteFfrSapUser()
std::vector< struct RachListElement_s > m_rachList
static double fpS11dot3toDouble(uint16_t val)
Definition: lte-common.cc:113
int counter
maximum size of token pool (byte)
std::vector< uint8_t > UlHarqProcessesStatus_t
void DoSchedUlCqiInfoReq(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
std::vector< uint8_t > DlHarqProcessesStatus_t
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
virtual void DoDispose(void)
Destructor implementation.
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
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
FfMacSchedSapProvider * m_schedSapProvider
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
std::map< uint16_t, UlHarqProcessesStatus_t > m_ulHarqProcessesStatus
virtual std::vector< bool > GetAvailableDlRbg()=0
Get vector of available RBG in DL for this Cell.
void DoSchedDlMacBufferReq(const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters &params)
FfMacCschedSapUser * m_cschedSapUser
void DoSchedUlTriggerReq(const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters &params)
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
Parameters of the SCHED_UL_SR_INFO_REQ primitive.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:220
Parameters of the SCHED_DL_RACH_INFO_REQ primitive.
Parameters of the SCHED_UL_CONFIG_IND primitive.
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
Parameters of the CSCHED_UE_CONFIG_REQ primitive.
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
#define HARQ_DL_TIMEOUT
uint32_t maxTokenPoolSize
current size of token pool (byte)
#define NO_SINR
struct DlDciListElement_s m_dci
std::vector< struct BuildRarListElement_s > m_buildRarList
std::map< uint16_t, uint8_t > m_p10CqiRxed
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
virtual void SchedUlCqiInfoReq(const struct SchedUlCqiInfoReqParameters &params)
friend class FdTbfqSchedulerMemberSchedSapProvider
a unique identifier for an interface.
Definition: type-id.h:58
static const int FdTbfqType0AllocationRbg[4]
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
#define HARQ_PROC_NUM
virtual void SchedUlMacCtrlInfoReq(const struct SchedUlMacCtrlInfoReqParameters &params)
void DoCschedUeConfigReq(const struct FfMacCschedSapProvider::CschedUeConfigReqParameters &params)
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
std::map< uint16_t, uint32_t > m_ceBsrRxed
virtual void SchedDlPagingBufferReq(const struct SchedDlPagingBufferReqParameters &params)
void UpdateDlRlcBufferInfo(uint16_t rnti, uint8_t lcid, uint16_t size)
void TransmissionModeConfigurationUpdate(uint16_t rnti, uint8_t txMode)
std::vector< struct BuildDataListElement_s > m_buildDataList
virtual void CschedUeConfigReq(const struct CschedUeConfigReqParameters &params)
See section 4.3.8 builDataListElement.