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