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 
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  // RACH Allocation
699  uint16_t rbStart = 0;
700  std::vector <struct RachListElement_s>::iterator itRach;
701  for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
702  {
703  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");
704  BuildRarListElement_s newRar;
705  newRar.m_rnti = (*itRach).m_rnti;
706  // DL-RACH Allocation
707  // Ideal: no needs of configuring m_dci
708  // UL-RACH Allocation
709  newRar.m_grant.m_rnti = newRar.m_rnti;
710  newRar.m_grant.m_mcs = m_ulGrantMcs;
711  uint16_t rbLen = 1;
712  uint16_t tbSizeBits = 0;
713  // find lowest TB size that fits UL grant estimated size
714  while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
715  {
716  rbLen++;
717  tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
718  }
719  if (tbSizeBits < (*itRach).m_estimatedSize)
720  {
721  // no more allocation space: finish allocation
722  break;
723  }
724  newRar.m_grant.m_rbStart = rbStart;
725  newRar.m_grant.m_rbLen = rbLen;
726  newRar.m_grant.m_tbSize = tbSizeBits / 8;
727  newRar.m_grant.m_hopping = false;
728  newRar.m_grant.m_tpc = 0;
729  newRar.m_grant.m_cqiRequest = false;
730  newRar.m_grant.m_ulDelay = false;
731  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);
732  for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
733  {
734  m_rachAllocationMap.at (i) = (*itRach).m_rnti;
735  }
736  rbStart = rbStart + rbLen;
737 
738  ret.m_buildRarList.push_back (newRar);
739  }
740  m_rachList.clear ();
741 
742 
743  // Process DL HARQ feedback
745  // retrieve past HARQ retx buffered
746  if (m_dlInfoListBuffered.size () > 0)
747  {
748  if (params.m_dlInfoList.size () > 0)
749  {
750  NS_LOG_INFO (this << " Received DL-HARQ feedback");
751  m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
752  }
753  }
754  else
755  {
756  if (params.m_dlInfoList.size () > 0)
757  {
759  }
760  }
761  if (m_harqOn == false)
762  {
763  // Ignore HARQ feedback
764  m_dlInfoListBuffered.clear ();
765  }
766  std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
767  for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
768  {
769  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
770  if (itRnti != rntiAllocated.end ())
771  {
772  // RNTI already allocated for retx
773  continue;
774  }
775  uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
776  std::vector <bool> retx;
777  NS_LOG_INFO (this << " Processing DLHARQ feedback");
778  if (nLayers == 1)
779  {
780  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
781  retx.push_back (false);
782  }
783  else
784  {
785  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
786  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
787  }
788  if (retx.at (0) || retx.at (1))
789  {
790  // retrieve HARQ process information
791  uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
792  uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
793  NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
794  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
795  if (itHarq == m_dlHarqProcessesDciBuffer.end ())
796  {
797  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
798  }
799 
800  DlDciListElement_s dci = (*itHarq).second.at (harqId);
801  int rv = 0;
802  if (dci.m_rv.size () == 1)
803  {
804  rv = dci.m_rv.at (0);
805  }
806  else
807  {
808  rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
809  }
810 
811  if (rv == 3)
812  {
813  // maximum number of retx reached -> drop process
814  NS_LOG_INFO ("Maximum number of retransmissions reached -> drop process");
815  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
816  if (it == m_dlHarqProcessesStatus.end ())
817  {
818  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
819  }
820  (*it).second.at (harqId) = 0;
821  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
822  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
823  {
824  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
825  }
826  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
827  {
828  (*itRlcPdu).second.at (k).at (harqId).clear ();
829  }
830  continue;
831  }
832  // check the feasibility of retransmitting on the same RBGs
833  // translate the DCI to Spectrum framework
834  std::vector <int> dciRbg;
835  uint32_t mask = 0x1;
836  NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
837  for (int j = 0; j < 32; j++)
838  {
839  if (((dci.m_rbBitmap & mask) >> j) == 1)
840  {
841  dciRbg.push_back (j);
842  NS_LOG_INFO ("\t" << j);
843  }
844  mask = (mask << 1);
845  }
846  bool free = true;
847  for (uint8_t j = 0; j < dciRbg.size (); j++)
848  {
849  if (rbgMap.at (dciRbg.at (j)) == true)
850  {
851  free = false;
852  break;
853  }
854  }
855  if (free)
856  {
857  // use the same RBGs for the retx
858  // reserve RBGs
859  for (uint8_t j = 0; j < dciRbg.size (); j++)
860  {
861  rbgMap.at (dciRbg.at (j)) = true;
862  NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
863  rbgAllocatedNum++;
864  }
865 
866  NS_LOG_INFO (this << " Send retx in the same RBGs");
867  }
868  else
869  {
870  // find RBGs for sending HARQ retx
871  uint8_t j = 0;
872  uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % rbgNum;
873  uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
874  std::vector <bool> rbgMapCopy = rbgMap;
875  while ((j < dciRbg.size ())&&(startRbg != rbgId))
876  {
877  if (rbgMapCopy.at (rbgId) == false)
878  {
879  rbgMapCopy.at (rbgId) = true;
880  dciRbg.at (j) = rbgId;
881  j++;
882  }
883  rbgId++;
884  }
885  if (j == dciRbg.size ())
886  {
887  // find new RBGs -> update DCI map
888  uint32_t rbgMask = 0;
889  for (uint16_t k = 0; k < dciRbg.size (); k++)
890  {
891  rbgMask = rbgMask + (0x1 << dciRbg.at (k));
892  rbgAllocatedNum++;
893  }
894  dci.m_rbBitmap = rbgMask;
895  rbgMap = rbgMapCopy;
896  NS_LOG_INFO (this << " Move retx in RBGs " << dciRbg.size ());
897  }
898  else
899  {
900  // HARQ retx cannot be performed on this TTI -> store it
901  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
902  NS_LOG_INFO (this << " No resource for this retx -> buffer it");
903  }
904  }
905  // retrieve RLC PDU list for retx TBsize and update DCI
907  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
908  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
909  {
910  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
911  }
912  for (uint8_t j = 0; j < nLayers; j++)
913  {
914  if (retx.at (j))
915  {
916  if (j >= dci.m_ndi.size ())
917  {
918  // for avoiding errors in MIMO transient phases
919  dci.m_ndi.push_back (0);
920  dci.m_rv.push_back (0);
921  dci.m_mcs.push_back (0);
922  dci.m_tbsSize.push_back (0);
923  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
924  }
925  else
926  {
927  dci.m_ndi.at (j) = 0;
928  dci.m_rv.at (j)++;
929  (*itHarq).second.at (harqId).m_rv.at (j)++;
930  NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
931  }
932  }
933  else
934  {
935  // empty TB of layer j
936  dci.m_ndi.at (j) = 0;
937  dci.m_rv.at (j) = 0;
938  dci.m_mcs.at (j) = 0;
939  dci.m_tbsSize.at (j) = 0;
940  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
941  }
942  }
943  for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
944  {
945  std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
946  for (uint8_t j = 0; j < nLayers; j++)
947  {
948  if (retx.at (j))
949  {
950  if (j < dci.m_ndi.size ())
951  {
952  rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
953  }
954  }
955  }
956 
957  if (rlcPduListPerLc.size () > 0)
958  {
959  newEl.m_rlcPduList.push_back (rlcPduListPerLc);
960  }
961  }
962  newEl.m_rnti = rnti;
963  newEl.m_dci = dci;
964  (*itHarq).second.at (harqId).m_rv = dci.m_rv;
965  // refresh timer
966  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
967  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
968  {
969  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
970  }
971  (*itHarqTimer).second.at (harqId) = 0;
972  ret.m_buildDataList.push_back (newEl);
973  rntiAllocated.insert (rnti);
974  }
975  else
976  {
977  // update HARQ process status
978  NS_LOG_INFO (this << " HARQ received ACK for UE " << m_dlInfoListBuffered.at (i).m_rnti);
979  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
980  if (it == m_dlHarqProcessesStatus.end ())
981  {
982  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
983  }
984  (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
985  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
986  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
987  {
988  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
989  }
990  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
991  {
992  (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
993  }
994  }
995  }
996  m_dlInfoListBuffered.clear ();
997  m_dlInfoListBuffered = dlInfoListUntxed;
998 
999 
1000  // update token pool, counter and bank size
1001  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator itStats;
1002  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
1003  {
1004  if ( (*itStats).second.tokenGenerationRate / 1000 + (*itStats).second.tokenPoolSize > (*itStats).second.maxTokenPoolSize )
1005  {
1006  (*itStats).second.counter += (*itStats).second.tokenGenerationRate / 1000 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );
1007  (*itStats).second.tokenPoolSize = (*itStats).second.maxTokenPoolSize;
1008  bankSize += (*itStats).second.tokenGenerationRate / 1000 - ( (*itStats).second.maxTokenPoolSize - (*itStats).second.tokenPoolSize );
1009  }
1010  else
1011  {
1012  (*itStats).second.tokenPoolSize += (*itStats).second.tokenGenerationRate / 1000;
1013  }
1014  }
1015 
1016  std::set <uint16_t> allocatedRnti; // store UEs which are already assigned RBGs
1017  std::set <uint8_t> allocatedRbg; // store RBGs which are already allocated to UE
1018 
1019  int totalRbg = 0;
1020  while (totalRbg < rbgNum)
1021  {
1022  // select UE with largest metric
1023  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator it;
1024  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator itMax = m_flowStatsDl.end ();
1025  double metricMax = 0.0;
1026  bool firstRnti = true;
1027  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
1028  {
1029  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1030  if ((itRnti != rntiAllocated.end ())||(!HarqProcessAvailability ((*it).first)))
1031  {
1032  // UE already allocated for HARQ or without HARQ process available -> drop it
1033  if (itRnti != rntiAllocated.end ())
1034  {
1035  NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(*it).first);
1036  }
1037  if (!HarqProcessAvailability ((*it).first))
1038  {
1039  NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*it).first);
1040  }
1041  continue;
1042  }
1043 
1044  if (LcActivePerFlow ((*it).first) == 0)
1045  {
1046  continue;
1047  }
1048 
1049  std::set <uint16_t>::iterator rnti;
1050  rnti = allocatedRnti.find((*it).first);
1051  if (rnti != allocatedRnti.end ()) // already allocated RBGs to this UE
1052  {
1053  continue;
1054  }
1055 
1056  double metric = ( ( (double)(*it).second.counter ) / ( (double)(*it).second.tokenGenerationRate ) );
1057 
1058  if (firstRnti == true)
1059  {
1060  metricMax = metric;
1061  itMax = it;
1062  firstRnti = false;
1063  continue;
1064  }
1065  if (metric > metricMax)
1066  {
1067  metricMax = metric;
1068  itMax = it;
1069  }
1070  } // end for m_flowStatsDl
1071 
1072  if (itMax == m_flowStatsDl.end())
1073  {
1074  // all UEs are allocated RBG or all UEs already allocated for HARQ or without HARQ process available
1075  break;
1076  }
1077 
1078  // mark this UE as "allocated"
1079  allocatedRnti.insert((*itMax).first);
1080 
1081  // calculate the maximum number of byte that the scheduler can assigned to this UE
1082  uint32_t budget = 0;
1083  if ( bankSize > 0 )
1084  {
1085  budget = (*itMax).second.counter - (*itMax).second.debtLimit;
1086  if ( budget > (*itMax).second.burstCredit )
1087  budget = (*itMax).second.burstCredit;
1088  if ( budget > bankSize )
1089  budget = bankSize;
1090  }
1091  budget = budget + (*itMax).second.tokenPoolSize;
1092 
1093  // calcualte how much bytes this UE actally need
1094  if (budget == 0)
1095  {
1096  // there are no tokens for this UE
1097  continue;
1098  }
1099  else
1100  {
1101  // calculate rlc buffer size
1102  uint32_t rlcBufSize = 0;
1103  uint8_t lcid = 0;
1104  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itRlcBuf;
1105  for (itRlcBuf = m_rlcBufferReq.begin (); itRlcBuf != m_rlcBufferReq.end (); itRlcBuf++)
1106  {
1107  if ( (*itRlcBuf).first.m_rnti == (*itMax).first )
1108  lcid = (*itRlcBuf).first.m_lcId;
1109  }
1110  LteFlowId_t flow ((*itMax).first, lcid);
1111  itRlcBuf = m_rlcBufferReq.find (flow);
1112  if (itRlcBuf!=m_rlcBufferReq.end ())
1113  rlcBufSize = (*itRlcBuf).second.m_rlcTransmissionQueueSize + (*itRlcBuf).second.m_rlcRetransmissionQueueSize + (*itRlcBuf).second.m_rlcStatusPduSize;
1114  if ( budget > rlcBufSize )
1115  budget = rlcBufSize;
1116  }
1117 
1118  // assign RBGs to this UE
1119  uint32_t bytesTxed = 0;
1120  uint32_t bytesTxedTmp = 0;
1121  int rbgIndex = 0;
1122  while ( bytesTxed <= budget )
1123  {
1124  totalRbg++;
1125 
1126  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1127  itCqi = m_a30CqiRxed.find ((*itMax).first);
1128  std::map <uint16_t,uint8_t>::iterator itTxMode;
1129  itTxMode = m_uesTxMode.find ((*itMax).first);
1130  if (itTxMode == m_uesTxMode.end ())
1131  {
1132  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
1133  }
1134  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1135 
1136  // find RBG with largest achievableRate
1137  double achievableRateMax = 0.0;
1138  rbgIndex = rbgNum;
1139  for (int k = 0; k < rbgNum; k++)
1140  {
1141  std::set <uint8_t>::iterator rbg;
1142  rbg = allocatedRbg.find (k);
1143  if (rbg != allocatedRbg.end ()) // RBGs are already allocated to this UE
1144  continue;
1145 
1146  if ( rbgMap.at (k) == true) // this RBG is allocated in RACH procedure
1147  continue;
1148 
1149  std::vector <uint8_t> sbCqi;
1150  if (itCqi == m_a30CqiRxed.end ())
1151  {
1152  for (uint8_t k = 0; k < nLayer; k++)
1153  {
1154  sbCqi.push_back (1); // start with lowest value
1155  }
1156  }
1157  else
1158  {
1159  sbCqi = (*itCqi).second.m_higherLayerSelected.at (k).m_sbCqi;
1160  }
1161  uint8_t cqi1 = sbCqi.at (0);
1162  uint8_t cqi2 = 1;
1163  if (sbCqi.size () > 1)
1164  {
1165  cqi2 = sbCqi.at (1);
1166  }
1167 
1168  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1169  {
1170  if (LcActivePerFlow ((*itMax).first) > 0)
1171  {
1172  // this UE has data to transmit
1173  double achievableRate = 0.0;
1174  for (uint8_t j = 0; j < nLayer; j++)
1175  {
1176  uint8_t mcs = 0;
1177  if (sbCqi.size () > j)
1178  {
1179  mcs = m_amc->GetMcsFromCqi (sbCqi.at (j));
1180  }
1181  else
1182  {
1183  // no info on this subband -> worst MCS
1184  mcs = 0;
1185  }
1186  achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, rbgSize) / 8) / 0.001); // = TB size / TTI
1187  }
1188 
1189  if ( achievableRate > achievableRateMax )
1190  {
1191  achievableRateMax = achievableRate;
1192  rbgIndex = k;
1193  }
1194  } // end of LcActivePerFlow
1195  } // end of cqi
1196  } // end of for rbgNum
1197 
1198  if ( rbgIndex == rbgNum) // impossible
1199  {
1200  // all RBGs are already assigned
1201  totalRbg = rbgNum;
1202  break;
1203  }
1204  else
1205  {
1206  // mark this UE as "allocated"
1207  allocatedRbg.insert (rbgIndex);
1208  }
1209 
1210  // assign this RBG to UE
1211  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1212  itMap = allocationMap.find ((*itMax).first);
1213  uint16_t RbgPerRnti;
1214  if (itMap == allocationMap.end ())
1215  {
1216  // insert new element
1217  std::vector <uint16_t> tempMap;
1218  tempMap.push_back (rbgIndex);
1219  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
1220  itMap = allocationMap.find ((*itMax).first); // point itMap to the first RBGs assigned to this UE
1221  }
1222  else
1223  {
1224  (*itMap).second.push_back (rbgIndex);
1225  }
1226  rbgMap.at (rbgIndex) = true; // Mark this RBG as allocated
1227 
1228  RbgPerRnti = (*itMap).second.size();
1229 
1230  // calculate tb size
1231  std::vector <uint8_t> worstCqi (2, 15);
1232  if (itCqi != m_a30CqiRxed.end ())
1233  {
1234  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1235  {
1236  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
1237  {
1238  for (uint8_t j = 0; j < nLayer; j++)
1239  {
1240  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
1241  {
1242  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
1243  {
1244  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
1245  }
1246  }
1247  else
1248  {
1249  // no CQI for this layer of this suband -> worst one
1250  worstCqi.at (j) = 1;
1251  }
1252  }
1253  }
1254  else
1255  {
1256  for (uint8_t j = 0; j < nLayer; j++)
1257  {
1258  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1259  }
1260  }
1261  }
1262  }
1263  else
1264  {
1265  for (uint8_t j = 0; j < nLayer; j++)
1266  {
1267  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1268  }
1269  }
1270 
1271  bytesTxedTmp = bytesTxed;
1272  bytesTxed = 0;
1273  for (uint8_t j = 0; j < nLayer; j++)
1274  {
1275  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)
1276  bytesTxed += tbSize;
1277  }
1278 
1279  } // end of while()
1280 
1281  // remove and unmark last RBG assigned to UE
1282  if ( bytesTxed > budget )
1283  {
1284  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1285  itMap = allocationMap.find ((*itMax).first);
1286  (*itMap).second.pop_back ();
1287  allocatedRbg.erase (rbgIndex);
1288  bytesTxed = bytesTxedTmp; // recovery bytesTxed
1289  totalRbg--;
1290  rbgMap.at (rbgIndex) = false; // unmark this RBG
1291  }
1292 
1293  // update UE stats
1294  if ( bytesTxed <= (*itMax).second.tokenPoolSize )
1295  {
1296  (*itMax).second.tokenPoolSize -= bytesTxed;
1297  }
1298  else
1299  {
1300  (*itMax).second.counter = (*itMax).second.counter - ( bytesTxed - (*itMax).second.tokenPoolSize );
1301  (*itMax).second.tokenPoolSize = 0;
1302  if (bankSize <= ( bytesTxed - (*itMax).second.tokenPoolSize ))
1303  bankSize = 0;
1304  else
1305  bankSize = bankSize - ( bytesTxed - (*itMax).second.tokenPoolSize );
1306  }
1307  } // end of RBGs
1308 
1309  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
1310  // creating the correspondent DCIs
1311  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
1312  while (itMap != allocationMap.end ())
1313  {
1314  // create new BuildDataListElement_s for this LC
1315  BuildDataListElement_s newEl;
1316  newEl.m_rnti = (*itMap).first;
1317  // create the DlDciListElement_s
1318  DlDciListElement_s newDci;
1319  newDci.m_rnti = (*itMap).first;
1320  newDci.m_harqProcess = UpdateHarqProcessId ((*itMap).first);
1321 
1322  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
1323  NS_LOG_INFO (this << "Allocate user " << newEl.m_rnti << " rbg " << lcActives);
1324  if (lcActives == 0)
1325  {
1326  // Set to max value, to avoid divide by 0 below
1327  lcActives = (uint16_t)65535; // UINT16_MAX;
1328  }
1329  uint16_t RgbPerRnti = (*itMap).second.size ();
1330  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1331  itCqi = m_a30CqiRxed.find ((*itMap).first);
1332  std::map <uint16_t,uint8_t>::iterator itTxMode;
1333  itTxMode = m_uesTxMode.find ((*itMap).first);
1334  if (itTxMode == m_uesTxMode.end ())
1335  {
1336  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
1337  }
1338  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1339  std::vector <uint8_t> worstCqi (2, 15);
1340  if (itCqi != m_a30CqiRxed.end ())
1341  {
1342  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1343  {
1344  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
1345  {
1346  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)) );
1347  for (uint8_t j = 0; j < nLayer; j++)
1348  {
1349  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
1350  {
1351  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
1352  {
1353  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
1354  }
1355  }
1356  else
1357  {
1358  // no CQI for this layer of this suband -> worst one
1359  worstCqi.at (j) = 1;
1360  }
1361  }
1362  }
1363  else
1364  {
1365  for (uint8_t j = 0; j < nLayer; j++)
1366  {
1367  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1368  }
1369  }
1370  }
1371  }
1372  else
1373  {
1374  for (uint8_t j = 0; j < nLayer; j++)
1375  {
1376  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1377  }
1378  }
1379  for (uint8_t j = 0; j < nLayer; j++)
1380  {
1381  NS_LOG_INFO (this << " Layer " << (uint16_t)j << " CQI selected " << (uint16_t)worstCqi.at (j));
1382  }
1383  uint32_t bytesTxed = 0;
1384  for (uint8_t j = 0; j < nLayer; j++)
1385  {
1386  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
1387  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)
1388  newDci.m_tbsSize.push_back (tbSize);
1389  NS_LOG_INFO (this << " Layer " << (uint16_t)j << " MCS selected" << m_amc->GetMcsFromCqi (worstCqi.at (j)));
1390  bytesTxed += tbSize;
1391  }
1392 
1393  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
1394  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
1395  uint32_t rbgMask = 0;
1396  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1397  {
1398  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
1399  NS_LOG_INFO (this << " Allocated RBG " << (*itMap).second.at (k));
1400  }
1401  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1402 
1403  // create the rlc PDUs -> equally divide resources among actives LCs
1404  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
1405  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
1406  {
1407  if (((*itBufReq).first.m_rnti == (*itMap).first)
1408  && (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
1409  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
1410  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
1411  {
1412  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1413  for (uint8_t j = 0; j < nLayer; j++)
1414  {
1415  RlcPduListElement_s newRlcEl;
1416  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
1417  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
1418  NS_LOG_INFO (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j);
1419  newRlcPduLe.push_back (newRlcEl);
1420  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
1421  if (m_harqOn == true)
1422  {
1423  // store RLC PDU list for HARQ
1424  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*itMap).first);
1425  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1426  {
1427  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*itMap).first);
1428  }
1429  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1430  }
1431  }
1432  newEl.m_rlcPduList.push_back (newRlcPduLe);
1433  }
1434  if ((*itBufReq).first.m_rnti > (*itMap).first)
1435  {
1436  break;
1437  }
1438  }
1439  for (uint8_t j = 0; j < nLayer; j++)
1440  {
1441  newDci.m_ndi.push_back (1);
1442  newDci.m_rv.push_back (0);
1443  }
1444 
1445  newEl.m_dci = newDci;
1446 
1447  if (m_harqOn == true)
1448  {
1449  // store DCI for HARQ
1450  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1451  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1452  {
1453  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1454  }
1455  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1456  // refresh timer
1457  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1458  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1459  {
1460  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1461  }
1462  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1463  }
1464 
1465  // ...more parameters -> ingored in this version
1466 
1467  ret.m_buildDataList.push_back (newEl);
1468 
1469  itMap++;
1470  } // end while allocation
1471  ret.m_nrOfPdcchOfdmSymbols = 1;
1472 
1474 
1475 
1476  return;
1477 }
1478 
1479 void
1481 {
1482  NS_LOG_FUNCTION (this);
1483 
1484  m_rachList = params.m_rachList;
1485 
1486  return;
1487 }
1488 
1489 void
1491 {
1492  NS_LOG_FUNCTION (this);
1493 
1494  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1495  {
1496  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1497  {
1498  // wideband CQI reporting
1499  std::map <uint16_t,uint8_t>::iterator it;
1500  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1501  it = m_p10CqiRxed.find (rnti);
1502  if (it == m_p10CqiRxed.end ())
1503  {
1504  // create the new entry
1505  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)
1506  // generate correspondent timer
1507  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1508  }
1509  else
1510  {
1511  // update the CQI value and refresh correspondent timer
1512  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1513  // update correspondent timer
1514  std::map <uint16_t,uint32_t>::iterator itTimers;
1515  itTimers = m_p10CqiTimers.find (rnti);
1516  (*itTimers).second = m_cqiTimersThreshold;
1517  }
1518  }
1519  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1520  {
1521  // subband CQI reporting high layer configured
1522  std::map <uint16_t,SbMeasResult_s>::iterator it;
1523  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1524  it = m_a30CqiRxed.find (rnti);
1525  if (it == m_a30CqiRxed.end ())
1526  {
1527  // create the new entry
1528  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
1529  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1530  }
1531  else
1532  {
1533  // update the CQI value and refresh correspondent timer
1534  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
1535  std::map <uint16_t,uint32_t>::iterator itTimers;
1536  itTimers = m_a30CqiTimers.find (rnti);
1537  (*itTimers).second = m_cqiTimersThreshold;
1538  }
1539  }
1540  else
1541  {
1542  NS_LOG_ERROR (this << " CQI type unknown");
1543  }
1544  }
1545 
1546  return;
1547 }
1548 
1549 
1550 double
1551 FdTbfqFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
1552 {
1553  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
1554  if (itCqi == m_ueCqi.end ())
1555  {
1556  // no cqi info about this UE
1557  return (NO_SINR);
1558 
1559  }
1560  else
1561  {
1562  // take the average SINR value among the available
1563  double sinrSum = 0;
1564  int sinrNum = 0;
1565  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1566  {
1567  double sinr = (*itCqi).second.at (i);
1568  if (sinr != NO_SINR)
1569  {
1570  sinrSum += sinr;
1571  sinrNum++;
1572  }
1573  }
1574  double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
1575  // store the value
1576  (*itCqi).second.at (rb) = estimatedSinr;
1577  return (estimatedSinr);
1578  }
1579 }
1580 
1581 void
1583 {
1584  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1585 
1586  RefreshUlCqiMaps ();
1587 
1588  // Generate RBs map
1590  std::vector <bool> rbMap;
1591  uint16_t rbAllocatedNum = 0;
1592  std::set <uint16_t> rntiAllocated;
1593  std::vector <uint16_t> rbgAllocationMap;
1594  // update with RACH allocation map
1595  rbgAllocationMap = m_rachAllocationMap;
1596  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1597  m_rachAllocationMap.clear ();
1599 
1600  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1601  // remove RACH allocation
1602  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1603  {
1604  if (rbgAllocationMap.at (i) != 0)
1605  {
1606  rbMap.at (i) = true;
1607  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1608  }
1609  }
1610 
1611 
1612  if (m_harqOn == true)
1613  {
1614  // Process UL HARQ feedback
1615  // update UL HARQ proc id
1616  std::map <uint16_t, uint8_t>::iterator itProcId;
1617  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
1618  {
1619  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
1620  }
1621 
1622  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1623  {
1624  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1625  {
1626  // retx correspondent block: retrieve the UL-DCI
1627  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1628  itProcId = m_ulHarqCurrentProcessId.find (rnti);
1629  if (itProcId == m_ulHarqCurrentProcessId.end ())
1630  {
1631  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1632  }
1633  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1634  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId << " i " << i << " size " << params.m_ulInfoList.size ());
1635  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1636  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1637  {
1638  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1639  continue;
1640  }
1641  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1642  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1643  if (itStat == m_ulHarqProcessesStatus.end ())
1644  {
1645  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1646  }
1647  if ((*itStat).second.at (harqId) >= 3)
1648  {
1649  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1650  continue;
1651  }
1652  bool free = true;
1653  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1654  {
1655  if (rbMap.at (j) == true)
1656  {
1657  free = false;
1658  NS_LOG_INFO (this << " BUSY " << j);
1659  }
1660  }
1661  if (free)
1662  {
1663  // retx on the same RBs
1664  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1665  {
1666  rbMap.at (j) = true;
1667  rbgAllocationMap.at (j) = dci.m_rnti;
1668  NS_LOG_INFO ("\tRB " << j);
1669  rbAllocatedNum++;
1670  }
1671  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);
1672  }
1673  else
1674  {
1675  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1676  continue;
1677  }
1678  dci.m_ndi = 0;
1679  // Update HARQ buffers with new HarqId
1680  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1681  (*itStat).second.at (harqId) = 0;
1682  (*itHarq).second.at ((*itProcId).second) = dci;
1683  ret.m_dciList.push_back (dci);
1684  rntiAllocated.insert (dci.m_rnti);
1685  }
1686  else
1687  {
1688  NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
1689  }
1690  }
1691  }
1692 
1693  std::map <uint16_t,uint32_t>::iterator it;
1694  int nflows = 0;
1695 
1696  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1697  {
1698  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1699  // select UEs with queues not empty and not yet allocated for HARQ
1700  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1701  {
1702  nflows++;
1703  }
1704  }
1705 
1706  if (nflows == 0)
1707  {
1708  if (ret.m_dciList.size () > 0)
1709  {
1711  }
1712 
1713  return; // no flows to be scheduled
1714  }
1715 
1716 
1717  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1718  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
1719  if (rbPerFlow < 3)
1720  {
1721  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1722  }
1723  int rbAllocated = 0;
1724 
1725  std::map <uint16_t, fdtbfqsFlowPerf_t>::iterator itStats;
1726  if (m_nextRntiUl != 0)
1727  {
1728  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1729  {
1730  if ((*it).first == m_nextRntiUl)
1731  {
1732  break;
1733  }
1734  }
1735  if (it == m_ceBsrRxed.end ())
1736  {
1737  NS_LOG_ERROR (this << " no user found");
1738  }
1739  }
1740  else
1741  {
1742  it = m_ceBsrRxed.begin ();
1743  m_nextRntiUl = (*it).first;
1744  }
1745  do
1746  {
1747  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1748  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1749  {
1750  // UE already allocated for UL-HARQ -> skip it
1751  NS_LOG_DEBUG (this << " UE already allocated in HARQ -> discared, RNTI " << (*it).first);
1752  it++;
1753  if (it == m_ceBsrRxed.end ())
1754  {
1755  // restart from the first
1756  it = m_ceBsrRxed.begin ();
1757  }
1758  continue;
1759  }
1760  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1761  {
1762  // limit to physical resources last resource assignment
1763  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1764  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1765  if (rbPerFlow < 3)
1766  {
1767  // terminate allocation
1768  rbPerFlow = 0;
1769  }
1770  }
1771 
1772  UlDciListElement_s uldci;
1773  uldci.m_rnti = (*it).first;
1774  uldci.m_rbLen = rbPerFlow;
1775  bool allocated = false;
1776  NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1777  while ((!allocated)&&((rbAllocated + rbPerFlow - 1) < m_cschedCellConfig.m_ulBandwidth) && (rbPerFlow != 0))
1778  {
1779  // check availability
1780  bool free = true;
1781  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1782  {
1783  if (rbMap.at (j) == true)
1784  {
1785  free = false;
1786  break;
1787  }
1788  }
1789  if (free)
1790  {
1791  uldci.m_rbStart = rbAllocated;
1792 
1793  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1794  {
1795  rbMap.at (j) = true;
1796  // store info on allocation for managing ul-cqi interpretation
1797  rbgAllocationMap.at (j) = (*it).first;
1798  }
1799  rbAllocated += rbPerFlow;
1800  allocated = true;
1801  break;
1802  }
1803  rbAllocated++;
1804  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1805  {
1806  // limit to physical resources last resource assignment
1807  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1808  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1809  if (rbPerFlow < 3)
1810  {
1811  // terminate allocation
1812  rbPerFlow = 0;
1813  }
1814  }
1815  }
1816  if (!allocated)
1817  {
1818  // unable to allocate new resource: finish scheduling
1819  m_nextRntiUl = (*it).first;
1820  if (ret.m_dciList.size () > 0)
1821  {
1823  }
1824  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1825  return;
1826  }
1827 
1828 
1829 
1830  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1831  int cqi = 0;
1832  if (itCqi == m_ueCqi.end ())
1833  {
1834  // no cqi info about this UE
1835  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1836  }
1837  else
1838  {
1839  // take the lowest CQI value (worst RB)
1840  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1841  if (minSinr == NO_SINR)
1842  {
1843  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
1844  }
1845  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1846  {
1847  double sinr = (*itCqi).second.at (i);
1848  if (sinr == NO_SINR)
1849  {
1850  sinr = EstimateUlSinr ((*it).first, i);
1851  }
1852  if ((*itCqi).second.at (i) < minSinr)
1853  {
1854  minSinr = (*itCqi).second.at (i);
1855  }
1856  }
1857 
1858  // translate SINR -> cqi: WILD ACK: same as DL
1859  double s = log2 ( 1 + (
1860  std::pow (10, minSinr / 10 ) /
1861  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1862  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1863  if (cqi == 0)
1864  {
1865  it++;
1866  if (it == m_ceBsrRxed.end ())
1867  {
1868  // restart from the first
1869  it = m_ceBsrRxed.begin ();
1870  }
1871  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
1872  // remove UE from allocation map
1873  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1874  {
1875  rbgAllocationMap.at (i) = 0;
1876  }
1877  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1878  }
1879  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1880  }
1881 
1882  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
1883  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1884  uldci.m_ndi = 1;
1885  uldci.m_cceIndex = 0;
1886  uldci.m_aggrLevel = 1;
1887  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1888  uldci.m_hopping = false;
1889  uldci.m_n2Dmrs = 0;
1890  uldci.m_tpc = 0; // no power control
1891  uldci.m_cqiRequest = false; // only period CQI at this stage
1892  uldci.m_ulIndex = 0; // TDD parameter
1893  uldci.m_dai = 1; // TDD parameter
1894  uldci.m_freqHopping = 0;
1895  uldci.m_pdcchPowerOffset = 0; // not used
1896  ret.m_dciList.push_back (uldci);
1897  // store DCI for HARQ_PERIOD
1898  uint8_t harqId = 0;
1899  if (m_harqOn == true)
1900  {
1901  std::map <uint16_t, uint8_t>::iterator itProcId;
1902  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1903  if (itProcId == m_ulHarqCurrentProcessId.end ())
1904  {
1905  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1906  }
1907  harqId = (*itProcId).second;
1908  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1909  if (itDci == m_ulHarqProcessesDciBuffer.end ())
1910  {
1911  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1912  }
1913  (*itDci).second.at (harqId) = uldci;
1914  }
1915 
1916  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);
1917 
1918  it++;
1919  if (it == m_ceBsrRxed.end ())
1920  {
1921  // restart from the first
1922  it = m_ceBsrRxed.begin ();
1923  }
1924  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1925  {
1926  // Stop allocation: no more PRBs
1927  m_nextRntiUl = (*it).first;
1928  break;
1929  }
1930  }
1931  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1932 
1933 
1934  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1936 
1937  return;
1938 }
1939 
1940 void
1942 {
1943  NS_LOG_FUNCTION (this);
1944  return;
1945 }
1946 
1947 void
1949 {
1950  NS_LOG_FUNCTION (this);
1951  return;
1952 }
1953 
1954 void
1956 {
1957  NS_LOG_FUNCTION (this);
1958 
1959  std::map <uint16_t,uint32_t>::iterator it;
1960 
1961  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1962  {
1963  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1964  {
1965  // buffer status report
1966  // note that this scheduler does not differentiate the
1967  // allocation according to which LCGs have more/less bytes
1968  // to send.
1969  // Hence the BSR of different LCGs are just summed up to get
1970  // a total queue size that is used for allocation purposes.
1971 
1972  uint32_t buffer = 0;
1973  for (uint8_t lcg = 0; lcg < 4; ++lcg)
1974  {
1975  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1976  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1977  }
1978 
1979  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1980  NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
1981  it = m_ceBsrRxed.find (rnti);
1982  if (it == m_ceBsrRxed.end ())
1983  {
1984  // create the new entry
1985  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1986  }
1987  else
1988  {
1989  // update the buffer size value
1990  (*it).second = buffer;
1991  }
1992  }
1993  }
1994 
1995  return;
1996 }
1997 
1998 void
2000 {
2001  NS_LOG_FUNCTION (this);
2002 // retrieve the allocation for this subframe
2003  switch (m_ulCqiFilter)
2004  {
2006  {
2007  // filter all the CQIs that are not SRS based
2008  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
2009  {
2010  return;
2011  }
2012  }
2013  break;
2015  {
2016  // filter all the CQIs that are not SRS based
2017  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
2018  {
2019  return;
2020  }
2021  }
2023  break;
2024 
2025  default:
2026  NS_FATAL_ERROR ("Unknown UL CQI type");
2027  }
2028 
2029  switch (params.m_ulCqi.m_type)
2030  {
2031  case UlCqi_s::PUSCH:
2032  {
2033  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
2034  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2035  NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
2036  itMap = m_allocationMaps.find (params.m_sfnSf);
2037  if (itMap == m_allocationMaps.end ())
2038  {
2039  return;
2040  }
2041  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
2042  {
2043  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
2044  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
2045  itCqi = m_ueCqi.find ((*itMap).second.at (i));
2046  if (itCqi == m_ueCqi.end ())
2047  {
2048  // create a new entry
2049  std::vector <double> newCqi;
2050  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2051  {
2052  if (i == j)
2053  {
2054  newCqi.push_back (sinr);
2055  }
2056  else
2057  {
2058  // initialize with NO_SINR value.
2059  newCqi.push_back (NO_SINR);
2060  }
2061 
2062  }
2063  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
2064  // generate correspondent timer
2065  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
2066  }
2067  else
2068  {
2069  // update the value
2070  (*itCqi).second.at (i) = sinr;
2071  NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr);
2072  // update correspondent timer
2073  std::map <uint16_t, uint32_t>::iterator itTimers;
2074  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
2075  (*itTimers).second = m_cqiTimersThreshold;
2076 
2077  }
2078 
2079  }
2080  // remove obsolete info on allocation
2081  m_allocationMaps.erase (itMap);
2082  }
2083  break;
2084  case UlCqi_s::SRS:
2085  {
2086  // get the RNTI from vendor specific parameters
2087  uint16_t rnti = 0;
2088  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
2089  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
2090  {
2091  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
2092  {
2093  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
2094  rnti = vsp->GetRnti ();
2095  }
2096  }
2097  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2098  itCqi = m_ueCqi.find (rnti);
2099  if (itCqi == m_ueCqi.end ())
2100  {
2101  // create a new entry
2102  std::vector <double> newCqi;
2103  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2104  {
2105  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2106  newCqi.push_back (sinr);
2107  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
2108 
2109  }
2110  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
2111  // generate correspondent timer
2112  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
2113  }
2114  else
2115  {
2116  // update the values
2117  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2118  {
2119  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2120  (*itCqi).second.at (j) = sinr;
2121  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
2122  }
2123  // update correspondent timer
2124  std::map <uint16_t, uint32_t>::iterator itTimers;
2125  itTimers = m_ueCqiTimers.find (rnti);
2126  (*itTimers).second = m_cqiTimersThreshold;
2127 
2128  }
2129 
2130 
2131  }
2132  break;
2133  case UlCqi_s::PUCCH_1:
2134  case UlCqi_s::PUCCH_2:
2135  case UlCqi_s::PRACH:
2136  {
2137  NS_FATAL_ERROR ("FdTbfqFfMacScheduler supports only PUSCH and SRS UL-CQIs");
2138  }
2139  break;
2140  default:
2141  NS_FATAL_ERROR ("Unknown type of UL-CQI");
2142  }
2143  return;
2144 }
2145 
2146 void
2148 {
2149  // refresh DL CQI P01 Map
2150  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
2151  while (itP10 != m_p10CqiTimers.end ())
2152  {
2153  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2154  if ((*itP10).second == 0)
2155  {
2156  // delete correspondent entries
2157  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
2158  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
2159  NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first);
2160  m_p10CqiRxed.erase (itMap);
2161  std::map <uint16_t,uint32_t>::iterator temp = itP10;
2162  itP10++;
2163  m_p10CqiTimers.erase (temp);
2164  }
2165  else
2166  {
2167  (*itP10).second--;
2168  itP10++;
2169  }
2170  }
2171 
2172  // refresh DL CQI A30 Map
2173  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
2174  while (itA30 != m_a30CqiTimers.end ())
2175  {
2176  NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2177  if ((*itA30).second == 0)
2178  {
2179  // delete correspondent entries
2180  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
2181  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
2182  NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first);
2183  m_a30CqiRxed.erase (itMap);
2184  std::map <uint16_t,uint32_t>::iterator temp = itA30;
2185  itA30++;
2186  m_a30CqiTimers.erase (temp);
2187  }
2188  else
2189  {
2190  (*itA30).second--;
2191  itA30++;
2192  }
2193  }
2194 
2195  return;
2196 }
2197 
2198 
2199 void
2201 {
2202  // refresh UL CQI Map
2203  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
2204  while (itUl != m_ueCqiTimers.end ())
2205  {
2206  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2207  if ((*itUl).second == 0)
2208  {
2209  // delete correspondent entries
2210  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
2211  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
2212  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
2213  (*itMap).second.clear ();
2214  m_ueCqi.erase (itMap);
2215  std::map <uint16_t,uint32_t>::iterator temp = itUl;
2216  itUl++;
2217  m_ueCqiTimers.erase (temp);
2218  }
2219  else
2220  {
2221  (*itUl).second--;
2222  itUl++;
2223  }
2224  }
2225 
2226  return;
2227 }
2228 
2229 void
2230 FdTbfqFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
2231 {
2232  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
2233  LteFlowId_t flow (rnti, lcid);
2234  it = m_rlcBufferReq.find (flow);
2235  if (it != m_rlcBufferReq.end ())
2236  {
2237  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);
2238  // Update queues: RLC tx order Status, ReTx, Tx
2239  // Update status queue
2240  if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
2241  {
2242  (*it).second.m_rlcStatusPduSize = 0;
2243  }
2244  else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
2245  {
2246  (*it).second.m_rlcRetransmissionQueueSize = 0;
2247  }
2248  else if ((*it).second.m_rlcTransmissionQueueSize > 0)
2249  {
2250  uint32_t rlcOverhead;
2251  if (lcid == 1)
2252  {
2253  // for SRB1 (using RLC AM) it's better to
2254  // overestimate RLC overhead rather than
2255  // underestimate it and risk unneeded
2256  // segmentation which increases delay
2257  rlcOverhead = 4;
2258  }
2259  else
2260  {
2261  // minimum RLC overhead due to header
2262  rlcOverhead = 2;
2263  }
2264  // update transmission queue
2265  if ((*it).second.m_rlcTransmissionQueueSize <= size - rlcOverhead)
2266  {
2267  (*it).second.m_rlcTransmissionQueueSize = 0;
2268  }
2269  else
2270  {
2271  (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
2272  }
2273  }
2274  }
2275  else
2276  {
2277  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
2278  }
2279 }
2280 
2281 void
2282 FdTbfqFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
2283 {
2284 
2285  size = size - 2; // remove the minimum RLC overhead
2286  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
2287  if (it != m_ceBsrRxed.end ())
2288  {
2289  NS_LOG_INFO (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
2290  if ((*it).second >= size)
2291  {
2292  (*it).second -= size;
2293  }
2294  else
2295  {
2296  (*it).second = 0;
2297  }
2298  }
2299  else
2300  {
2301  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
2302  }
2303 
2304 }
2305 
2306 void
2308 {
2309  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
2311  params.m_rnti = rnti;
2312  params.m_transmissionMode = txMode;
2314 }
2315 
2316 
2317 }
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)
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:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
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
std::map< uint16_t, SbMeasResult_s > m_a30CqiRxed
int FdTbfqType0AllocationRbg[4]
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 NO_SINR
#define NS_ASSERT(condition)
Definition: assert.h:64
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
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.
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)
Definition: log.h:264
See section 4.3.10 buildRARListElement.
virtual void SchedUlSrInfoReq(const struct SchedUlSrInfoReqParameters &params)
virtual void SchedUlNoiseInterferenceReq(const struct SchedUlNoiseInterferenceReqParameters &params)
std::map< uint16_t, fdtbfqsFlowPerf_t > m_flowStatsUl
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
NS_LOG_COMPONENT_DEFINE("FdTbfqFfMacScheduler")
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
virtual void CschedUeReleaseReq(const struct CschedUeReleaseReqParameters &params)
virtual void SchedUlTriggerReq(const struct SchedUlTriggerReqParameters &params)
std::vector< RlcPduList_t > DlHarqRlcPduListBuffer_t
virtual void CschedUeConfigUpdateInd(const struct CschedUeConfigUpdateIndParameters &params)=0
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
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
Hold an unsigned integer type.
Definition: uinteger.h:46
static uint8_t TxMode2LayerNum(uint8_t txMode)
Definition: lte-common.cc:170
Ptr< SampleEmitter > s
NS_OBJECT_ENSURE_REGISTERED(AntennaModel)
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)
Definition: log.h:334
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
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)
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
virtual void SchedDlMacBufferReq(const struct SchedDlMacBufferReqParameters &params)
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
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
#define HARQ_PROC_NUM
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
static uint32_t BsrId2BufferSize(uint8_t val)
Definition: lte-common.cc:142
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
FfMacSchedSapProvider * m_schedSapProvider
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
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
#define NS_LOG_ERROR(msg)
Definition: log.h:237
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
uint32_t maxTokenPoolSize
current size of token pool (byte)
struct DlDciListElement_s m_dci
#define HARQ_DL_TIMEOUT
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
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
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.