A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
tdtbfq-ff-mac-scheduler.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Marco Miozzo <marco.miozzo@cttc.es>
19  * Modification: Dizhi Zhou <dizhi.zhou@gmail.com> // modify codes related to downlink scheduler
20  */
21 
22 #include <ns3/log.h>
23 #include <ns3/pointer.h>
24 #include <ns3/math.h>
25 
26 #include <ns3/simulator.h>
27 #include <ns3/lte-amc.h>
28 #include <ns3/tdtbfq-ff-mac-scheduler.h>
29 #include <ns3/lte-vendor-specific-parameters.h>
30 #include <ns3/boolean.h>
31 #include <ns3/integer.h>
32 #include <set>
33 #include <cfloat>
34 
35 NS_LOG_COMPONENT_DEFINE ("TdTbfqFfMacScheduler");
36 
37 namespace ns3 {
38 
40  10, // RGB size 1
41  26, // RGB size 2
42  63, // RGB size 3
43  110 // RGB size 4
44 }; // see table 7.1.6.1-1 of 36.213
45 
46 
47 NS_OBJECT_ENSURE_REGISTERED (TdTbfqFfMacScheduler);
48 
49 
50 
52 {
53 public:
55 
56  // inherited from FfMacCschedSapProvider
57  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
58  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
59  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
60  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
61  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
62 
63 private:
66 };
67 
69 {
70 }
71 
73 {
74 }
75 
76 
77 void
79 {
81 }
82 
83 void
85 {
87 }
88 
89 
90 void
92 {
94 }
95 
96 void
98 {
100 }
101 
102 void
104 {
106 }
107 
108 
109 
110 
112 {
113 public:
115 
116  // inherited from FfMacSchedSapProvider
117  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
118  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
119  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
120  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
121  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
122  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
123  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
124  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
125  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
126  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
127  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
128 
129 
130 private:
133 };
134 
135 
136 
138 {
139 }
140 
141 
143  : m_scheduler (scheduler)
144 {
145 }
146 
147 void
149 {
151 }
152 
153 void
155 {
157 }
158 
159 void
161 {
163 }
164 
165 void
167 {
169 }
170 
171 void
173 {
175 }
176 
177 void
179 {
181 }
182 
183 void
185 {
187 }
188 
189 void
191 {
193 }
194 
195 void
197 {
199 }
200 
201 void
203 {
205 }
206 
207 void
209 {
211 }
212 
213 
214 
215 
216 
218  : m_cschedSapUser (0),
219  m_schedSapUser (0),
220  m_nextRntiUl (0),
221  bankSize (0)
222 {
223  m_amc = CreateObject <LteAmc> ();
226 }
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::TdTbfqFfMacScheduler")
253  .AddConstructor<TdTbfqFfMacScheduler> ()
254  .AddAttribute ("CqiTimerThreshold",
255  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
256  UintegerValue (1000),
257  MakeUintegerAccessor (&TdTbfqFfMacScheduler::m_cqiTimersThreshold),
258  MakeUintegerChecker<uint32_t> ())
259  .AddAttribute ("DebtLimit",
260  "Flow debt limit (default -625000 bytes)",
261  IntegerValue (-625000),
262  MakeIntegerAccessor (&TdTbfqFfMacScheduler::m_debtLimit),
263  MakeIntegerChecker<int> ())
264  .AddAttribute ("CreditLimit",
265  "Flow credit limit (default 625000 bytes)",
266  UintegerValue (625000),
267  MakeUintegerAccessor (&TdTbfqFfMacScheduler::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 (&TdTbfqFfMacScheduler::m_tokenPoolSize),
273  MakeUintegerChecker<uint32_t> ())
274  .AddAttribute ("CreditableThreshold",
275  "Threshold of flow credit (default 0 bytes)",
276  UintegerValue (0),
277  MakeUintegerAccessor (&TdTbfqFfMacScheduler::m_creditableThreshold),
278  MakeUintegerChecker<uint32_t> ())
279 
280  .AddAttribute ("HarqEnabled",
281  "Activate/Deactivate the HARQ [by default is active].",
282  BooleanValue (true),
283  MakeBooleanAccessor (&TdTbfqFfMacScheduler::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 (&TdTbfqFfMacScheduler::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, tdtbfqsFlowPerf_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  tdtbfqsFlowPerf_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, tdtbfqsFlowPerf_t> (params.m_rnti, flowStatsDl));
398  tdtbfqsFlowPerf_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, tdtbfqsFlowPerf_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 < TdTbfqType0AllocationRbg[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, tdtbfqsFlowPerf_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 
1017  // select UE with largest metric
1018  std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator it;
1019  std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itMax = m_flowStatsDl.end ();
1020  double metricMax = 0.0;
1021  bool firstRnti = true;
1022  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
1023  {
1024  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1025  if ((itRnti != rntiAllocated.end ())||(!HarqProcessAvailability ((*it).first)))
1026  {
1027  // UE already allocated for HARQ or without HARQ process available -> drop it
1028  if (itRnti != rntiAllocated.end ())
1029  {
1030  NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(*it).first);
1031  }
1032  if (!HarqProcessAvailability ((*it).first))
1033  {
1034  NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*it).first);
1035  }
1036  continue;
1037  }
1038 
1039  /*
1040  if (LcActivePerFlow ((*it).first) == 0)
1041  {
1042  continue;
1043  }
1044  */
1045 
1046  double metric = ( ( (double)(*it).second.counter ) / ( (double)(*it).second.tokenGenerationRate ) );
1047 
1048  if (firstRnti == true)
1049  {
1050  metricMax = metric;
1051  itMax = it;
1052  firstRnti = false;
1053  continue;
1054  }
1055  if (metric > metricMax)
1056  {
1057  metricMax = metric;
1058  itMax = it;
1059  }
1060  } // end for m_flowStatsDl
1061 
1062  if (itMax == m_flowStatsDl.end ())
1063  {
1064  // all UEs are allocated RBG or all UEs already allocated for HARQ or without HARQ process available
1065  return;
1066  }
1067  else
1068  {
1069  // assign all RBGs to this UE
1070  std::vector <uint16_t> tempMap;
1071  for (int i = 0; i < rbgNum; i++)
1072  {
1073  if ( rbgMap.at (i) == true) // this RBG is allocated in RACH procedure
1074  continue;
1075 
1076  tempMap.push_back (i);
1077  rbgMap.at (i) = true;
1078  }
1079  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
1080  }
1081 
1082 
1083 
1084  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
1085  // creating the correspondent DCIs
1086  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
1087  while (itMap != allocationMap.end ())
1088  {
1089  // create new BuildDataListElement_s for this LC
1090  BuildDataListElement_s newEl;
1091  newEl.m_rnti = (*itMap).first;
1092  // create the DlDciListElement_s
1093  DlDciListElement_s newDci;
1094  newDci.m_rnti = (*itMap).first;
1095  newDci.m_harqProcess = UpdateHarqProcessId ((*itMap).first);
1096 
1097  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
1098  NS_LOG_INFO (this << "Allocate user " << newEl.m_rnti << " rbg " << lcActives);
1099  if (lcActives == 0)
1100  {
1101  // Set to max value, to avoid divide by 0 below
1102  lcActives = (uint16_t)65535; // UINT16_MAX;
1103  }
1104  uint16_t RgbPerRnti = (*itMap).second.size ();
1105  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1106  itCqi = m_a30CqiRxed.find ((*itMap).first);
1107  std::map <uint16_t,uint8_t>::iterator itTxMode;
1108  itTxMode = m_uesTxMode.find ((*itMap).first);
1109  if (itTxMode == m_uesTxMode.end ())
1110  {
1111  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
1112  }
1113  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1114  std::vector <uint8_t> worstCqi (2, 15);
1115  if (itCqi != m_a30CqiRxed.end ())
1116  {
1117  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1118  {
1119  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
1120  {
1121  for (uint8_t j = 0; j < nLayer; j++)
1122  {
1123  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
1124  {
1125  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
1126  {
1127  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
1128  }
1129  }
1130  else
1131  {
1132  // no CQI for this layer of this suband -> worst one
1133  worstCqi.at (j) = 1;
1134  }
1135  }
1136  }
1137  else
1138  {
1139  for (uint8_t j = 0; j < nLayer; j++)
1140  {
1141  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1142  }
1143  }
1144  }
1145  }
1146  else
1147  {
1148  for (uint8_t j = 0; j < nLayer; j++)
1149  {
1150  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1151  }
1152  }
1153  uint32_t bytesTxed = 0;
1154  for (uint8_t j = 0; j < nLayer; j++)
1155  {
1156  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
1157  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)
1158  newDci.m_tbsSize.push_back (tbSize);
1159  bytesTxed += tbSize;
1160  }
1161 
1162  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
1163  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
1164  uint32_t rbgMask = 0;
1165  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1166  {
1167  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
1168  NS_LOG_INFO (this << " Allocated RBG " << (*itMap).second.at (k));
1169  }
1170  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1171 
1172  // create the rlc PDUs -> equally divide resources among actives LCs
1173  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
1174  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
1175  {
1176  if (((*itBufReq).first.m_rnti == (*itMap).first)
1177  && (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
1178  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
1179  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
1180  {
1181  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1182  for (uint8_t j = 0; j < nLayer; j++)
1183  {
1184  RlcPduListElement_s newRlcEl;
1185  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
1186  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
1187  NS_LOG_INFO (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j);
1188  newRlcPduLe.push_back (newRlcEl);
1189  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
1190  if (m_harqOn == true)
1191  {
1192  // store RLC PDU list for HARQ
1193  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*itMap).first);
1194  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1195  {
1196  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*itMap).first);
1197  }
1198  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1199  }
1200  }
1201  newEl.m_rlcPduList.push_back (newRlcPduLe);
1202  }
1203  if ((*itBufReq).first.m_rnti > (*itMap).first)
1204  {
1205  break;
1206  }
1207  }
1208  for (uint8_t j = 0; j < nLayer; j++)
1209  {
1210  newDci.m_ndi.push_back (1);
1211  newDci.m_rv.push_back (0);
1212  }
1213 
1214  newEl.m_dci = newDci;
1215 
1216  if (m_harqOn == true)
1217  {
1218  // store DCI for HARQ
1219  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1220  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1221  {
1222  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1223  }
1224  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1225  // refresh timer
1226  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1227  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1228  {
1229  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1230  }
1231  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1232  }
1233 
1234 
1235  // update UE stats
1236  if ( bytesTxed <= (*itMax).second.tokenPoolSize )
1237  {
1238  (*itMax).second.tokenPoolSize -= bytesTxed;
1239  }
1240  else
1241  {
1242  (*itMax).second.counter = (*itMax).second.counter - ( bytesTxed - (*itMax).second.tokenPoolSize );
1243  (*itMax).second.tokenPoolSize = 0;
1244  if (bankSize <= ( bytesTxed - (*itMax).second.tokenPoolSize ))
1245  bankSize = 0;
1246  else
1247  bankSize = bankSize - ( bytesTxed - (*itMax).second.tokenPoolSize );
1248  }
1249 
1250 
1251  // ...more parameters -> ingored in this version
1252 
1253  ret.m_buildDataList.push_back (newEl);
1254 
1255  itMap++;
1256  } // end while allocation
1257  ret.m_nrOfPdcchOfdmSymbols = 1;
1258 
1260 
1261 
1262  return;
1263 }
1264 
1265 void
1267 {
1268  NS_LOG_FUNCTION (this);
1269 
1270  m_rachList = params.m_rachList;
1271 
1272  return;
1273 }
1274 
1275 void
1277 {
1278  NS_LOG_FUNCTION (this);
1279 
1280  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1281  {
1282  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1283  {
1284  // wideband CQI reporting
1285  std::map <uint16_t,uint8_t>::iterator it;
1286  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1287  it = m_p10CqiRxed.find (rnti);
1288  if (it == m_p10CqiRxed.end ())
1289  {
1290  // create the new entry
1291  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)
1292  // generate correspondent timer
1293  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1294  }
1295  else
1296  {
1297  // update the CQI value and refresh correspondent timer
1298  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1299  // update correspondent timer
1300  std::map <uint16_t,uint32_t>::iterator itTimers;
1301  itTimers = m_p10CqiTimers.find (rnti);
1302  (*itTimers).second = m_cqiTimersThreshold;
1303  }
1304  }
1305  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1306  {
1307  // subband CQI reporting high layer configured
1308  std::map <uint16_t,SbMeasResult_s>::iterator it;
1309  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1310  it = m_a30CqiRxed.find (rnti);
1311  if (it == m_a30CqiRxed.end ())
1312  {
1313  // create the new entry
1314  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
1315  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1316  }
1317  else
1318  {
1319  // update the CQI value and refresh correspondent timer
1320  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
1321  std::map <uint16_t,uint32_t>::iterator itTimers;
1322  itTimers = m_a30CqiTimers.find (rnti);
1323  (*itTimers).second = m_cqiTimersThreshold;
1324  }
1325  }
1326  else
1327  {
1328  NS_LOG_ERROR (this << " CQI type unknown");
1329  }
1330  }
1331 
1332  return;
1333 }
1334 
1335 
1336 double
1337 TdTbfqFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
1338 {
1339  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
1340  if (itCqi == m_ueCqi.end ())
1341  {
1342  // no cqi info about this UE
1343  return (NO_SINR);
1344 
1345  }
1346  else
1347  {
1348  // take the average SINR value among the available
1349  double sinrSum = 0;
1350  int sinrNum = 0;
1351  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1352  {
1353  double sinr = (*itCqi).second.at (i);
1354  if (sinr != NO_SINR)
1355  {
1356  sinrSum += sinr;
1357  sinrNum++;
1358  }
1359  }
1360  double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
1361  // store the value
1362  (*itCqi).second.at (rb) = estimatedSinr;
1363  return (estimatedSinr);
1364  }
1365 }
1366 
1367 void
1369 {
1370  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1371 
1372  RefreshUlCqiMaps ();
1373 
1374  // Generate RBs map
1376  std::vector <bool> rbMap;
1377  uint16_t rbAllocatedNum = 0;
1378  std::set <uint16_t> rntiAllocated;
1379  std::vector <uint16_t> rbgAllocationMap;
1380  // update with RACH allocation map
1381  rbgAllocationMap = m_rachAllocationMap;
1382  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1383  m_rachAllocationMap.clear ();
1385 
1386  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1387  // remove RACH allocation
1388  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1389  {
1390  if (rbgAllocationMap.at (i) != 0)
1391  {
1392  rbMap.at (i) = true;
1393  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1394  }
1395  }
1396 
1397 
1398  if (m_harqOn == true)
1399  {
1400  // Process UL HARQ feedback
1401  // update UL HARQ proc id
1402  std::map <uint16_t, uint8_t>::iterator itProcId;
1403  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
1404  {
1405  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
1406  }
1407 
1408  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1409  {
1410  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1411  {
1412  // retx correspondent block: retrieve the UL-DCI
1413  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1414  itProcId = m_ulHarqCurrentProcessId.find (rnti);
1415  if (itProcId == m_ulHarqCurrentProcessId.end ())
1416  {
1417  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1418  }
1419  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1420  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId << " i " << i << " size " << params.m_ulInfoList.size ());
1421  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1422  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1423  {
1424  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1425  continue;
1426  }
1427  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1428  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1429  if (itStat == m_ulHarqProcessesStatus.end ())
1430  {
1431  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1432  }
1433  if ((*itStat).second.at (harqId) >= 3)
1434  {
1435  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1436  continue;
1437  }
1438  bool free = true;
1439  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1440  {
1441  if (rbMap.at (j) == true)
1442  {
1443  free = false;
1444  NS_LOG_INFO (this << " BUSY " << j);
1445  }
1446  }
1447  if (free)
1448  {
1449  // retx on the same RBs
1450  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1451  {
1452  rbMap.at (j) = true;
1453  rbgAllocationMap.at (j) = dci.m_rnti;
1454  NS_LOG_INFO ("\tRB " << j);
1455  rbAllocatedNum++;
1456  }
1457  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);
1458  }
1459  else
1460  {
1461  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1462  continue;
1463  }
1464  dci.m_ndi = 0;
1465  // Update HARQ buffers with new HarqId
1466  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1467  (*itStat).second.at (harqId) = 0;
1468  (*itHarq).second.at ((*itProcId).second) = dci;
1469  ret.m_dciList.push_back (dci);
1470  rntiAllocated.insert (dci.m_rnti);
1471  }
1472  else
1473  {
1474  NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
1475  }
1476  }
1477  }
1478 
1479  std::map <uint16_t,uint32_t>::iterator it;
1480  int nflows = 0;
1481 
1482  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1483  {
1484  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1485  // select UEs with queues not empty and not yet allocated for HARQ
1486  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1487  {
1488  nflows++;
1489  }
1490  }
1491 
1492  if (nflows == 0)
1493  {
1494  if (ret.m_dciList.size () > 0)
1495  {
1497  }
1498 
1499  return; // no flows to be scheduled
1500  }
1501 
1502 
1503  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1504  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
1505  if (rbPerFlow < 3)
1506  {
1507  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1508  }
1509  int rbAllocated = 0;
1510 
1511  std::map <uint16_t, tdtbfqsFlowPerf_t>::iterator itStats;
1512  if (m_nextRntiUl != 0)
1513  {
1514  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1515  {
1516  if ((*it).first == m_nextRntiUl)
1517  {
1518  break;
1519  }
1520  }
1521  if (it == m_ceBsrRxed.end ())
1522  {
1523  NS_LOG_ERROR (this << " no user found");
1524  }
1525  }
1526  else
1527  {
1528  it = m_ceBsrRxed.begin ();
1529  m_nextRntiUl = (*it).first;
1530  }
1531  do
1532  {
1533  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1534  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1535  {
1536  // UE already allocated for UL-HARQ -> skip it
1537  NS_LOG_DEBUG (this << " UE already allocated in HARQ -> discared, RNTI " << (*it).first);
1538  it++;
1539  if (it == m_ceBsrRxed.end ())
1540  {
1541  // restart from the first
1542  it = m_ceBsrRxed.begin ();
1543  }
1544  continue;
1545  }
1546  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1547  {
1548  // limit to physical resources last resource assignment
1549  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1550  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1551  if (rbPerFlow < 3)
1552  {
1553  // terminate allocation
1554  rbPerFlow = 0;
1555  }
1556  }
1557 
1558  UlDciListElement_s uldci;
1559  uldci.m_rnti = (*it).first;
1560  uldci.m_rbLen = rbPerFlow;
1561  bool allocated = false;
1562  NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1563  while ((!allocated)&&((rbAllocated + rbPerFlow - 1) < m_cschedCellConfig.m_ulBandwidth) && (rbPerFlow != 0))
1564  {
1565  // check availability
1566  bool free = true;
1567  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1568  {
1569  if (rbMap.at (j) == true)
1570  {
1571  free = false;
1572  break;
1573  }
1574  }
1575  if (free)
1576  {
1577  uldci.m_rbStart = rbAllocated;
1578 
1579  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1580  {
1581  rbMap.at (j) = true;
1582  // store info on allocation for managing ul-cqi interpretation
1583  rbgAllocationMap.at (j) = (*it).first;
1584  }
1585  rbAllocated += rbPerFlow;
1586  allocated = true;
1587  break;
1588  }
1589  rbAllocated++;
1590  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1591  {
1592  // limit to physical resources last resource assignment
1593  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1594  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1595  if (rbPerFlow < 3)
1596  {
1597  // terminate allocation
1598  rbPerFlow = 0;
1599  }
1600  }
1601  }
1602  if (!allocated)
1603  {
1604  // unable to allocate new resource: finish scheduling
1605  m_nextRntiUl = (*it).first;
1606  if (ret.m_dciList.size () > 0)
1607  {
1609  }
1610  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1611  return;
1612  }
1613 
1614 
1615 
1616  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1617  int cqi = 0;
1618  if (itCqi == m_ueCqi.end ())
1619  {
1620  // no cqi info about this UE
1621  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1622  }
1623  else
1624  {
1625  // take the lowest CQI value (worst RB)
1626  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1627  if (minSinr == NO_SINR)
1628  {
1629  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
1630  }
1631  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1632  {
1633  double sinr = (*itCqi).second.at (i);
1634  if (sinr == NO_SINR)
1635  {
1636  sinr = EstimateUlSinr ((*it).first, i);
1637  }
1638  if ((*itCqi).second.at (i) < minSinr)
1639  {
1640  minSinr = (*itCqi).second.at (i);
1641  }
1642  }
1643 
1644  // translate SINR -> cqi: WILD ACK: same as DL
1645  double s = log2 ( 1 + (
1646  std::pow (10, minSinr / 10 ) /
1647  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1648  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1649  if (cqi == 0)
1650  {
1651  it++;
1652  if (it == m_ceBsrRxed.end ())
1653  {
1654  // restart from the first
1655  it = m_ceBsrRxed.begin ();
1656  }
1657  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
1658  // remove UE from allocation map
1659  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1660  {
1661  rbgAllocationMap.at (i) = 0;
1662  }
1663  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1664  }
1665  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1666  }
1667 
1668  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
1669  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1670  uldci.m_ndi = 1;
1671  uldci.m_cceIndex = 0;
1672  uldci.m_aggrLevel = 1;
1673  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1674  uldci.m_hopping = false;
1675  uldci.m_n2Dmrs = 0;
1676  uldci.m_tpc = 0; // no power control
1677  uldci.m_cqiRequest = false; // only period CQI at this stage
1678  uldci.m_ulIndex = 0; // TDD parameter
1679  uldci.m_dai = 1; // TDD parameter
1680  uldci.m_freqHopping = 0;
1681  uldci.m_pdcchPowerOffset = 0; // not used
1682  ret.m_dciList.push_back (uldci);
1683  // store DCI for HARQ_PERIOD
1684  uint8_t harqId = 0;
1685  if (m_harqOn == true)
1686  {
1687  std::map <uint16_t, uint8_t>::iterator itProcId;
1688  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1689  if (itProcId == m_ulHarqCurrentProcessId.end ())
1690  {
1691  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1692  }
1693  harqId = (*itProcId).second;
1694  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1695  if (itDci == m_ulHarqProcessesDciBuffer.end ())
1696  {
1697  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1698  }
1699  (*itDci).second.at (harqId) = uldci;
1700  }
1701 
1702  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);
1703 
1704  it++;
1705  if (it == m_ceBsrRxed.end ())
1706  {
1707  // restart from the first
1708  it = m_ceBsrRxed.begin ();
1709  }
1710  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1711  {
1712  // Stop allocation: no more PRBs
1713  m_nextRntiUl = (*it).first;
1714  break;
1715  }
1716  }
1717  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1718 
1719 
1720  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1722 
1723  return;
1724 }
1725 
1726 void
1728 {
1729  NS_LOG_FUNCTION (this);
1730  return;
1731 }
1732 
1733 void
1735 {
1736  NS_LOG_FUNCTION (this);
1737  return;
1738 }
1739 
1740 void
1742 {
1743  NS_LOG_FUNCTION (this);
1744 
1745  std::map <uint16_t,uint32_t>::iterator it;
1746 
1747  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1748  {
1749  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1750  {
1751  // buffer status report
1752  // note that this scheduler does not differentiate the
1753  // allocation according to which LCGs have more/less bytes
1754  // to send.
1755  // Hence the BSR of different LCGs are just summed up to get
1756  // a total queue size that is used for allocation purposes.
1757 
1758  uint32_t buffer = 0;
1759  for (uint8_t lcg = 0; lcg < 4; ++lcg)
1760  {
1761  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1762  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1763  }
1764 
1765  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1766  NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
1767  it = m_ceBsrRxed.find (rnti);
1768  if (it == m_ceBsrRxed.end ())
1769  {
1770  // create the new entry
1771  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1772  }
1773  else
1774  {
1775  // update the buffer size value
1776  (*it).second = buffer;
1777  }
1778  }
1779  }
1780 
1781  return;
1782 }
1783 
1784 void
1786 {
1787  NS_LOG_FUNCTION (this);
1788 // retrieve the allocation for this subframe
1789  switch (m_ulCqiFilter)
1790  {
1792  {
1793  // filter all the CQIs that are not SRS based
1794  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
1795  {
1796  return;
1797  }
1798  }
1799  break;
1801  {
1802  // filter all the CQIs that are not SRS based
1803  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
1804  {
1805  return;
1806  }
1807  }
1809  break;
1810 
1811  default:
1812  NS_FATAL_ERROR ("Unknown UL CQI type");
1813  }
1814 
1815  switch (params.m_ulCqi.m_type)
1816  {
1817  case UlCqi_s::PUSCH:
1818  {
1819  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1820  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1821  NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
1822  itMap = m_allocationMaps.find (params.m_sfnSf);
1823  if (itMap == m_allocationMaps.end ())
1824  {
1825  return;
1826  }
1827  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1828  {
1829  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1830  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1831  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1832  if (itCqi == m_ueCqi.end ())
1833  {
1834  // create a new entry
1835  std::vector <double> newCqi;
1836  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1837  {
1838  if (i == j)
1839  {
1840  newCqi.push_back (sinr);
1841  }
1842  else
1843  {
1844  // initialize with NO_SINR value.
1845  newCqi.push_back (NO_SINR);
1846  }
1847 
1848  }
1849  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1850  // generate correspondent timer
1851  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1852  }
1853  else
1854  {
1855  // update the value
1856  (*itCqi).second.at (i) = sinr;
1857  NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr);
1858  // update correspondent timer
1859  std::map <uint16_t, uint32_t>::iterator itTimers;
1860  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1861  (*itTimers).second = m_cqiTimersThreshold;
1862 
1863  }
1864 
1865  }
1866  // remove obsolete info on allocation
1867  m_allocationMaps.erase (itMap);
1868  }
1869  break;
1870  case UlCqi_s::SRS:
1871  {
1872  // get the RNTI from vendor specific parameters
1873  uint16_t rnti = 0;
1874  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1875  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1876  {
1877  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1878  {
1879  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1880  rnti = vsp->GetRnti ();
1881  }
1882  }
1883  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1884  itCqi = m_ueCqi.find (rnti);
1885  if (itCqi == m_ueCqi.end ())
1886  {
1887  // create a new entry
1888  std::vector <double> newCqi;
1889  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1890  {
1891  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1892  newCqi.push_back (sinr);
1893  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1894 
1895  }
1896  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1897  // generate correspondent timer
1898  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1899  }
1900  else
1901  {
1902  // update the values
1903  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1904  {
1905  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1906  (*itCqi).second.at (j) = sinr;
1907  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1908  }
1909  // update correspondent timer
1910  std::map <uint16_t, uint32_t>::iterator itTimers;
1911  itTimers = m_ueCqiTimers.find (rnti);
1912  (*itTimers).second = m_cqiTimersThreshold;
1913 
1914  }
1915 
1916 
1917  }
1918  break;
1919  case UlCqi_s::PUCCH_1:
1920  case UlCqi_s::PUCCH_2:
1921  case UlCqi_s::PRACH:
1922  {
1923  NS_FATAL_ERROR ("TdTbfqFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1924  }
1925  break;
1926  default:
1927  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1928  }
1929  return;
1930 }
1931 
1932 void
1934 {
1935  // refresh DL CQI P01 Map
1936  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1937  while (itP10 != m_p10CqiTimers.end ())
1938  {
1939  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1940  if ((*itP10).second == 0)
1941  {
1942  // delete correspondent entries
1943  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1944  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1945  NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first);
1946  m_p10CqiRxed.erase (itMap);
1947  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1948  itP10++;
1949  m_p10CqiTimers.erase (temp);
1950  }
1951  else
1952  {
1953  (*itP10).second--;
1954  itP10++;
1955  }
1956  }
1957 
1958  // refresh DL CQI A30 Map
1959  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
1960  while (itA30 != m_a30CqiTimers.end ())
1961  {
1962  NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1963  if ((*itA30).second == 0)
1964  {
1965  // delete correspondent entries
1966  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
1967  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
1968  NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first);
1969  m_a30CqiRxed.erase (itMap);
1970  std::map <uint16_t,uint32_t>::iterator temp = itA30;
1971  itA30++;
1972  m_a30CqiTimers.erase (temp);
1973  }
1974  else
1975  {
1976  (*itA30).second--;
1977  itA30++;
1978  }
1979  }
1980 
1981  return;
1982 }
1983 
1984 
1985 void
1987 {
1988  // refresh UL CQI Map
1989  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1990  while (itUl != m_ueCqiTimers.end ())
1991  {
1992  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1993  if ((*itUl).second == 0)
1994  {
1995  // delete correspondent entries
1996  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1997  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1998  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1999  (*itMap).second.clear ();
2000  m_ueCqi.erase (itMap);
2001  std::map <uint16_t,uint32_t>::iterator temp = itUl;
2002  itUl++;
2003  m_ueCqiTimers.erase (temp);
2004  }
2005  else
2006  {
2007  (*itUl).second--;
2008  itUl++;
2009  }
2010  }
2011 
2012  return;
2013 }
2014 
2015 void
2016 TdTbfqFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
2017 {
2018  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
2019  LteFlowId_t flow (rnti, lcid);
2020  it = m_rlcBufferReq.find (flow);
2021  if (it != m_rlcBufferReq.end ())
2022  {
2023  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);
2024  // Update queues: RLC tx order Status, ReTx, Tx
2025  // Update status queue
2026  if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
2027  {
2028  (*it).second.m_rlcStatusPduSize = 0;
2029  }
2030  else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
2031  {
2032  (*it).second.m_rlcRetransmissionQueueSize = 0;
2033  }
2034  else if ((*it).second.m_rlcTransmissionQueueSize > 0)
2035  {
2036  uint32_t rlcOverhead;
2037  if (lcid == 1)
2038  {
2039  // for SRB1 (using RLC AM) it's better to
2040  // overestimate RLC overhead rather than
2041  // underestimate it and risk unneeded
2042  // segmentation which increases delay
2043  rlcOverhead = 4;
2044  }
2045  else
2046  {
2047  // minimum RLC overhead due to header
2048  rlcOverhead = 2;
2049  }
2050  // update transmission queue
2051  if ((*it).second.m_rlcTransmissionQueueSize <= size - rlcOverhead)
2052  {
2053  (*it).second.m_rlcTransmissionQueueSize = 0;
2054  }
2055  else
2056  {
2057  (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
2058  }
2059  }
2060  }
2061  else
2062  {
2063  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
2064  }
2065 }
2066 
2067 void
2068 TdTbfqFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
2069 {
2070 
2071  size = size - 2; // remove the minimum RLC overhead
2072  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
2073  if (it != m_ceBsrRxed.end ())
2074  {
2075  NS_LOG_INFO (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
2076  if ((*it).second >= size)
2077  {
2078  (*it).second -= size;
2079  }
2080  else
2081  {
2082  (*it).second = 0;
2083  }
2084  }
2085  else
2086  {
2087  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
2088  }
2089 
2090 }
2091 
2092 void
2094 {
2095  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
2097  params.m_rnti = rnti;
2098  params.m_transmissionMode = txMode;
2100 }
2101 
2102 
2103 }
void DoSchedUlNoiseInterferenceReq(const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters &params)
std::vector< struct UlInfoListElement_s > m_ulInfoList
See section 4.3.1 dlDciListElement.
Definition: ff-mac-common.h:88
void DoCschedLcReleaseReq(const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters &params)
std::map< uint16_t, uint8_t > m_dlHarqCurrentProcessId
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
NS_LOG_COMPONENT_DEFINE("TdTbfqFfMacScheduler")
void DoSchedDlRlcBufferReq(const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
#define HARQ_PERIOD
Definition: lte-common.h:30
Hold a bool native type.
Definition: boolean.h:38
void DoCschedUeConfigReq(const struct FfMacCschedSapProvider::CschedUeConfigReqParameters &params)
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
friend class TdTbfqSchedulerMemberCschedSapProvider
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
uint32_t burstCredit
the number of token borrow or given to token bank
FfMacSchedSapProvider * m_schedSapProvider
enum ns3::UlCqi_s::Type_e m_type
friend class TdTbfqSchedulerMemberSchedSapProvider
std::vector< UlDciListElement_s > UlHarqProcessesDciBuffer_t
uint32_t maxTokenPoolSize
current size of token pool (byte)
std::vector< struct LogicalChannelConfigListElement_s > m_logicalChannelConfigList
std::vector< uint16_t > m_sinr
double EstimateUlSinr(uint16_t rnti, uint16_t rb)
std::vector< uint8_t > DlHarqProcessesTimer_t
#define NO_SINR
#define NS_ASSERT(condition)
Definition: assert.h:64
Hold a signed integer type.
Definition: integer.h:45
virtual void CschedLcReleaseReq(const struct CschedLcReleaseReqParameters &params)
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
std::vector< uint8_t > m_mcs
Definition: ff-mac-common.h:95
See section 4.3.2 ulDciListElement.
Provides the CSCHED SAP.
std::vector< struct UlDciListElement_s > m_dciList
void DoCschedLcConfigReq(const struct FfMacCschedSapProvider::CschedLcConfigReqParameters &params)
#define NS_LOG_INFO(msg)
Definition: log.h:264
See section 4.3.10 buildRARListElement.
int counter
maximum size of token pool (byte)
void TransmissionModeConfigurationUpdate(uint16_t rnti, uint8_t txMode)
virtual void CschedLcConfigReq(const struct CschedLcConfigReqParameters &params)
std::map< LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters > m_rlcBufferReq
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
Implements the SCHED SAP and CSCHED SAP for a Time Domain Token Bank Fair Queue scheduler.
std::vector< struct RachListElement_s > m_rachList
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
FfMacCschedSapUser * m_cschedSapUser
void DoSchedUlTriggerReq(const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters &params)
virtual void SchedUlNoiseInterferenceReq(const struct SchedUlNoiseInterferenceReqParameters &params)
std::map< uint16_t, DlHarqProcessesTimer_t > m_dlHarqProcessesTimer
virtual void SchedUlMacCtrlInfoReq(const struct SchedUlMacCtrlInfoReqParameters &params)
std::vector< RlcPduList_t > DlHarqRlcPduListBuffer_t
virtual void CschedUeConfigUpdateInd(const struct CschedUeConfigUpdateIndParameters &params)=0
void DoSchedUlSrInfoReq(const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters &params)
std::vector< struct VendorSpecificListElement_s > m_vendorSpecificList
std::map< uint16_t, std::vector< uint16_t > > m_allocationMaps
int debtLimit
the maximum number of tokens connection i can borrow from the bank each time
Hold an unsigned integer type.
Definition: uinteger.h:46
static uint8_t TxMode2LayerNum(uint8_t txMode)
Definition: lte-common.cc:170
Ptr< SampleEmitter > s
NS_OBJECT_ENSURE_REGISTERED(AntennaModel)
std::map< uint16_t, uint32_t > m_a30CqiTimers
virtual void SchedDlCqiInfoReq(const struct SchedDlCqiInfoReqParameters &params)
void UpdateDlRlcBufferInfo(uint16_t rnti, uint8_t lcid, uint16_t size)
std::vector< uint8_t > m_ndi
Definition: ff-mac-common.h:96
virtual void SchedDlTriggerReq(const struct SchedDlTriggerReqParameters &params)
Provides the SCHED SAP.
void DoSchedDlCqiInfoReq(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
void DoSchedDlMacBufferReq(const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters &params)
virtual void CschedUeConfigCnf(const struct CschedUeConfigCnfParameters &params)=0
std::map< uint16_t, UlHarqProcessesDciBuffer_t > m_ulHarqProcessesDciBuffer
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
std::vector< struct CqiListElement_s > m_cqiList
std::map< uint16_t, DlHarqRlcPduListBuffer_t > m_dlHarqProcessesRlcPduListBuffer
std::vector< struct DlInfoListElement_s > m_dlInfoList
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
virtual void SchedDlConfigInd(const struct SchedDlConfigIndParameters &params)=0
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
std::vector< uint16_t > m_tbsSize
Definition: ff-mac-common.h:94
See section 4.3.9 rlcPDU_ListElement.
uint64_t tokenGenerationRate
packet arrival rate( byte/s)
virtual void SchedDlPagingBufferReq(const struct SchedDlPagingBufferReqParameters &params)
std::map< uint16_t, std::vector< double > > m_ueCqi
virtual void SchedDlRachInfoReq(const struct SchedDlRachInfoReqParameters &params)
std::vector< DlDciListElement_s > DlHarqProcessesDciBuffer_t
virtual void SchedDlRlcBufferReq(const struct SchedDlRlcBufferReqParameters &params)
std::vector< uint8_t > m_rv
Definition: ff-mac-common.h:97
std::map< uint16_t, SbMeasResult_s > m_a30CqiRxed
std::map< uint16_t, uint8_t > m_p10CqiRxed
virtual void SchedUlConfigInd(const struct SchedUlConfigIndParameters &params)=0
static Time Now(void)
Definition: simulator.cc:180
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
uint32_t creditableThreshold
counter threshold that the flow cannot further borrow tokens from bank
UlCqiFilter_t m_ulCqiFilter
uint32_t tokenPoolSize
token generation rate ( byte/s )
#define SRS_CQI_RNTI_VSP
virtual void CschedCellConfigReq(const struct CschedCellConfigReqParameters &params)
CSCHED_CELL_CONFIG_REQ.
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
virtual void CschedUeConfigReq(const struct CschedUeConfigReqParameters &params)
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
std::vector< struct MacCeListElement_s > m_macCeList
std::map< uint16_t, tdtbfqsFlowPerf_t > m_flowStatsDl
std::vector< struct RachListElement_s > m_rachList
static double fpS11dot3toDouble(uint16_t val)
Definition: lte-common.cc:114
#define HARQ_PROC_NUM
virtual void SchedUlSrInfoReq(const struct SchedUlSrInfoReqParameters &params)
std::map< uint16_t, uint8_t > m_uesTxMode
std::vector< uint8_t > UlHarqProcessesStatus_t
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
std::map< uint16_t, uint32_t > m_ueCqiTimers
std::vector< uint8_t > DlHarqProcessesStatus_t
static uint32_t BsrId2BufferSize(uint8_t val)
Definition: lte-common.cc:142
virtual void SchedDlMacBufferReq(const struct SchedDlMacBufferReqParameters &params)
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
virtual void CschedUeReleaseReq(const struct CschedUeReleaseReqParameters &params)
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
int TdTbfqType0AllocationRbg[4]
void DoSchedUlCqiInfoReq(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
void DoCschedCellConfigReq(const struct FfMacCschedSapProvider::CschedCellConfigReqParameters &params)
virtual void SchedUlTriggerReq(const struct SchedUlTriggerReqParameters &params)
FfMacCschedSapProvider * m_cschedSapProvider
#define NS_LOG_ERROR(msg)
Definition: log.h:237
std::map< uint16_t, DlHarqProcessesDciBuffer_t > m_dlHarqProcessesDciBuffer
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
virtual void SchedUlCqiInfoReq(const struct SchedUlCqiInfoReqParameters &params)
void DoSchedUlMacCtrlInfoReq(const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters &params)
std::vector< uint16_t > m_rachAllocationMap
struct DlDciListElement_s m_dci
#define HARQ_DL_TIMEOUT
std::vector< struct BuildRarListElement_s > m_buildRarList
std::map< uint16_t, UlHarqProcessesStatus_t > m_ulHarqProcessesStatus
std::map< uint16_t, uint32_t > m_ceBsrRxed
a unique identifier for an interface.
Definition: type-id.h:49
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
std::map< uint16_t, uint32_t > m_p10CqiTimers
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
std::vector< struct BuildDataListElement_s > m_buildDataList
std::map< uint16_t, tdtbfqsFlowPerf_t > m_flowStatsUl
See section 4.3.8 builDataListElement.