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