A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
cqa-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) 2012 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  * Authors: Biljana Bojovic <bbojovic@cttc.es>, Nicola Baldo<nbaldo@cttc.es>.
19  *
20  * Note:
21  * Implementation is using many common scheduler functionalities in its
22  * original version implemented by Marco Miozzo<mmiozzo@cttc.es> in
23  * Proportional Fair and Round Robin schedulers implementations.
24  */
25 
26 #include <ns3/log.h>
27 #include <ns3/pointer.h>
28 #include <ns3/math.h>
29 
30 #include <ns3/simulator.h>
31 #include <ns3/lte-amc.h>
32 #include <ns3/cqa-ff-mac-scheduler.h>
33 #include <ns3/ff-mac-common.h>
34 #include <ns3/lte-vendor-specific-parameters.h>
35 #include <ns3/boolean.h>
36 #include <cfloat>
37 #include <set>
38 #include <stdexcept>
39 #include <ns3/integer.h>
40 #include <ns3/string.h>
41 
42 NS_LOG_COMPONENT_DEFINE ("CqaFfMacScheduler");
43 
44 namespace ns3 {
45 
46 static const int CqaType0AllocationRbg[4] = {
47  10, // RGB size 1
48  26, // RGB size 2
49  63, // RGB size 3
50  110 // RGB size 4
51 }; // see table 7.1.6.1-1 of 36.213
52 
53 
54 NS_OBJECT_ENSURE_REGISTERED (CqaFfMacScheduler);
55 
56 
58 {
59  uint16_t resource_block_index; //Resource block indexHOL_GROUP_index
60  uint8_t cqi_value_for_lc; // CQI indicator value
61 };
62 
63 
64 bool CQIValueDescComparator (uint8_t key1, uint8_t key2)
65 {
66  return key1>key2;
67 }
68 
69 bool CqaGroupDescComparator (int key1, int key2)
70 {
71  return key1>key2;
72 }
73 
74 typedef uint8_t CQI_value;
75 typedef int RBG_index;
76 typedef int HOL_group;
77 
78 typedef std::map<CQI_value,LteFlowId_t,bool(*)(uint8_t,uint8_t)> t_map_CQIToUE; //sorted
79 typedef std::map<RBG_index,t_map_CQIToUE> t_map_RBGToCQIsSorted;
80 typedef std::map<HOL_group,t_map_RBGToCQIsSorted> t_map_HOLGroupToRBGs;
81 
82 typedef std::map<CQI_value,LteFlowId_t,bool(*)(uint8_t,uint8_t)>::iterator t_it_CQIToUE; //sorted
83 typedef std::map<RBG_index,t_map_CQIToUE>::iterator t_it_RBGToCQIsSorted;
84 typedef std::map<HOL_group,t_map_RBGToCQIsSorted>::iterator t_it_HOLGroupToRBGs;
85 
86 typedef std::multimap<HOL_group,std::set<LteFlowId_t>,bool(*)(int,int)> t_map_HOLgroupToUEs;
87 typedef std::map<HOL_group,std::set<LteFlowId_t> >::iterator t_it_HOLgroupToUEs;
88 
89 //typedef std::map<RBG_index,CQI_value> map_RBG_to_CQI;
90 //typedef std::map<LteFlowId_t,map_RBG_to_CQI> map_flowId_to_CQI_map;
91 
92 
93 bool CqaKeyDescComparator (uint16_t key1, uint16_t key2)
94 {
95  return key1>key2;
96 }
97 
98 
100 {
101 public:
103 
104  // inherited from FfMacCschedSapProvider
105  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
106  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
107  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
108  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
109  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
110 
111 private:
114 };
115 
117 {
118 }
119 
121 {
122 }
123 
124 
125 void
127 {
129 }
130 
131 void
133 {
135 }
136 
137 
138 void
140 {
142 }
143 
144 void
146 {
148 }
149 
150 void
152 {
154 }
155 
156 
157 
159 {
160 public:
162 
163  // inherited from FfMacSchedSapProvider
164  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
165  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
166  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
167  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
168  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
169  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
170  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
171  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
172  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
173  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
174  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
175 
176 
177 private:
180 };
181 
182 
183 
185 {
186 }
187 
188 
190  : m_scheduler (scheduler)
191 {
192 }
193 
194 void
196 {
198 }
199 
200 void
202 {
204 }
205 
206 void
208 {
210 }
211 
212 void
214 {
216 }
217 
218 void
220 {
222 }
223 
224 void
226 {
228 }
229 
230 void
232 {
234 }
235 
236 void
238 {
240 }
241 
242 void
244 {
246 }
247 
248 void
250 {
252 }
253 
254 void
256 {
258 }
259 
260 
261 
262 
263 
265  : m_cschedSapUser (0),
266  m_schedSapUser (0),
267  m_timeWindow (99.0),
268  m_nextRntiUl (0)
269 {
270  m_amc = CreateObject <LteAmc> ();
273  m_ffrSapProvider = 0;
275 }
276 
278 {
279  NS_LOG_FUNCTION (this);
280 }
281 
282 void
284 {
285  NS_LOG_FUNCTION (this);
287  m_dlHarqProcessesTimer.clear ();
289  m_dlInfoListBuffered.clear ();
290  m_ulHarqCurrentProcessId.clear ();
291  m_ulHarqProcessesStatus.clear ();
293  delete m_cschedSapProvider;
294  delete m_schedSapProvider;
295  delete m_ffrSapUser;
296 }
297 
298 TypeId
300 {
301  static TypeId tid = TypeId ("ns3::CqaFfMacScheduler")
303  .AddConstructor<CqaFfMacScheduler>()
304  .AddAttribute ("CqiTimerThreshold",
305  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
306  UintegerValue (1000),
307  MakeUintegerAccessor (&CqaFfMacScheduler::m_cqiTimersThreshold),
308  MakeUintegerChecker<uint32_t> ())
309  .AddAttribute ("CqaMetric",
310  "CqaFfMacScheduler metric type that can be: CqaFf, CqaPf",
311  StringValue ("CqaFf"),
312  MakeStringAccessor (&CqaFfMacScheduler::m_CqaMetric),
313  MakeStringChecker ())
314  .AddAttribute ("HarqEnabled",
315  "Activate/Deactivate the HARQ [by default is active].",
316  BooleanValue (true),
317  MakeBooleanAccessor (&CqaFfMacScheduler::m_harqOn),
318  MakeBooleanChecker ())
319  .AddAttribute ("UlGrantMcs",
320  "The MCS of the UL grant, must be [0..15] (default 0)",
321  UintegerValue (0),
322  MakeUintegerAccessor (&CqaFfMacScheduler::m_ulGrantMcs),
323  MakeUintegerChecker<uint8_t> ())
324  ;
325  return tid;
326 }
327 
328 
329 
330 void
332 {
333  m_cschedSapUser = s;
334 }
335 
336 void
338 {
339  m_schedSapUser = s;
340 }
341 
344 {
345  return m_cschedSapProvider;
346 }
347 
350 {
351  return m_schedSapProvider;
352 }
353 
354 void
356 {
358 }
359 
362 {
363  return m_ffrSapUser;
364 }
365 
366 void
368 {
369  NS_LOG_FUNCTION (this);
370  // Read the subset of parameters used
371  m_cschedCellConfig = params;
374  cnf.m_result = SUCCESS;
376  return;
377 }
378 
379 void
381 {
382  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
383  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
384  if (it == m_uesTxMode.end ())
385  {
386  m_uesTxMode.insert (std::pair <uint16_t, uint8_t> (params.m_rnti, params.m_transmissionMode));
387  // generate HARQ buffers
388  m_dlHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
389  DlHarqProcessesStatus_t dlHarqPrcStatus;
390  dlHarqPrcStatus.resize (8,0);
391  m_dlHarqProcessesStatus.insert (std::pair <uint16_t, DlHarqProcessesStatus_t> (params.m_rnti, dlHarqPrcStatus));
392  DlHarqProcessesTimer_t dlHarqProcessesTimer;
393  dlHarqProcessesTimer.resize (8,0);
394  m_dlHarqProcessesTimer.insert (std::pair <uint16_t, DlHarqProcessesTimer_t> (params.m_rnti, dlHarqProcessesTimer));
395  DlHarqProcessesDciBuffer_t dlHarqdci;
396  dlHarqdci.resize (8);
397  m_dlHarqProcessesDciBuffer.insert (std::pair <uint16_t, DlHarqProcessesDciBuffer_t> (params.m_rnti, dlHarqdci));
398  DlHarqRlcPduListBuffer_t dlHarqRlcPdu;
399  dlHarqRlcPdu.resize (2);
400  dlHarqRlcPdu.at (0).resize (8);
401  dlHarqRlcPdu.at (1).resize (8);
402  m_dlHarqProcessesRlcPduListBuffer.insert (std::pair <uint16_t, DlHarqRlcPduListBuffer_t> (params.m_rnti, dlHarqRlcPdu));
403  m_ulHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
404  UlHarqProcessesStatus_t ulHarqPrcStatus;
405  ulHarqPrcStatus.resize (8,0);
406  m_ulHarqProcessesStatus.insert (std::pair <uint16_t, UlHarqProcessesStatus_t> (params.m_rnti, ulHarqPrcStatus));
407  UlHarqProcessesDciBuffer_t ulHarqdci;
408  ulHarqdci.resize (8);
409  m_ulHarqProcessesDciBuffer.insert (std::pair <uint16_t, UlHarqProcessesDciBuffer_t> (params.m_rnti, ulHarqdci));
410  }
411  else
412  {
413  (*it).second = params.m_transmissionMode;
414  }
415  return;
416 }
417 
418 void
420 {
421  NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti);
422 
423  NS_LOG_FUNCTION ("LC configuration. Number of LCs:"<<params.m_logicalChannelConfigList.size ());
424 
425  // m_reconfigureFlat indicates if this is a reconfiguration or new UE is added, table 4.1.5 in LTE MAC scheduler specification
426  if (params.m_reconfigureFlag)
427  {
428  std::vector <struct LogicalChannelConfigListElement_s>::const_iterator lcit;
429 
430  for(lcit = params.m_logicalChannelConfigList.begin (); lcit!= params.m_logicalChannelConfigList.end (); lcit++)
431  {
432  LteFlowId_t flowid = LteFlowId_t (params.m_rnti,lcit->m_logicalChannelIdentity);
433 
435  {
436  NS_LOG_ERROR ("UE logical channels can not be reconfigured because it was not configured before.");
437  }
438  else
439  {
440  m_ueLogicalChannelsConfigList.find (flowid)->second = *lcit;
441  }
442  }
443 
444  } // else new UE is added
445  else
446  {
447  std::vector <struct LogicalChannelConfigListElement_s>::const_iterator lcit;
448 
449  for (lcit = params.m_logicalChannelConfigList.begin (); lcit != params.m_logicalChannelConfigList.end (); lcit++)
450  {
451  LteFlowId_t flowId = LteFlowId_t (params.m_rnti,lcit->m_logicalChannelIdentity);
452  m_ueLogicalChannelsConfigList.insert (std::pair<LteFlowId_t, LogicalChannelConfigListElement_s>(flowId,*lcit));
453  }
454  }
455 
456 
457  std::map <uint16_t, CqasFlowPerf_t>::iterator it;
458 
459  for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++)
460  {
461  it = m_flowStatsDl.find (params.m_rnti);
462 
463  if (it == m_flowStatsDl.end ())
464  {
465  double tbrDlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabGuaranteedBitrateDl / 8; // byte/s
466  double tbrUlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabGuaranteedBitrateUl / 8; // byte/s
467 
468  CqasFlowPerf_t flowStatsDl;
469  flowStatsDl.flowStart = Simulator::Now ();
470  flowStatsDl.totalBytesTransmitted = 0;
471  flowStatsDl.lastTtiBytesTransmitted = 0;
472  flowStatsDl.lastAveragedThroughput = 1;
473  flowStatsDl.secondLastAveragedThroughput = 1;
474  flowStatsDl.targetThroughput = tbrDlInBytes;
475  m_flowStatsDl.insert (std::pair<uint16_t, CqasFlowPerf_t> (params.m_rnti, flowStatsDl));
476  CqasFlowPerf_t flowStatsUl;
477  flowStatsUl.flowStart = Simulator::Now ();
478  flowStatsUl.totalBytesTransmitted = 0;
479  flowStatsUl.lastTtiBytesTransmitted = 0;
480  flowStatsUl.lastAveragedThroughput = 1;
481  flowStatsUl.secondLastAveragedThroughput = 1;
482  flowStatsUl.targetThroughput = tbrUlInBytes;
483  m_flowStatsUl.insert (std::pair<uint16_t, CqasFlowPerf_t> (params.m_rnti, flowStatsUl));
484  }
485  else
486  {
487  // update GBR from UeManager::SetupDataRadioBearer ()
488  double tbrDlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabGuaranteedBitrateDl / 8; // byte/s
489  double tbrUlInBytes = params.m_logicalChannelConfigList.at (i).m_eRabGuaranteedBitrateUl / 8; // byte/s
490  m_flowStatsDl[(*it).first].targetThroughput = tbrDlInBytes;
491  m_flowStatsUl[(*it).first].targetThroughput = tbrUlInBytes;
492 
493  }
494  }
495 
496  return;
497 }
498 
499 void
501 {
502  NS_LOG_FUNCTION (this);
503  std::vector <uint8_t>::const_iterator it;
504 
505  for (it = params.m_logicalChannelIdentity.begin (); it != params.m_logicalChannelIdentity.end (); it++)
506  {
507  LteFlowId_t flowId = LteFlowId_t (params.m_rnti, *it);
508 
509  // find the logical channel with the same Logical Channel Identity in the current list, release it
511  {
512  m_ueLogicalChannelsConfigList.erase (flowId);
513  }
514  else
515  {
516  NS_FATAL_ERROR ("Logical channels cannot be released because it can not be found in the list of active LCs");
517  }
518  }
519 
520  for (uint16_t i = 0; i < params.m_logicalChannelIdentity.size (); i++)
521  {
522  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
523  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator temp;
524  while (it!=m_rlcBufferReq.end ())
525  {
526  if (((*it).first.m_rnti == params.m_rnti) && ((*it).first.m_lcId == params.m_logicalChannelIdentity.at (i)))
527  {
528  temp = it;
529  it++;
530  m_rlcBufferReq.erase (temp);
531  }
532  else
533  {
534  it++;
535  }
536  }
537  }
538  return;
539 }
540 
541 void
543 {
544  NS_LOG_FUNCTION (this);
545 
546  for (int i=0; i < MAX_LC_LIST; i++)
547  {
548  LteFlowId_t flowId = LteFlowId_t (params.m_rnti,i);
549  // find the logical channel with the same Logical Channel Identity in the current list, release it
551  {
552  m_ueLogicalChannelsConfigList.erase (flowId);
553  }
554  }
555 
556  m_uesTxMode.erase (params.m_rnti);
557  m_dlHarqCurrentProcessId.erase (params.m_rnti);
558  m_dlHarqProcessesStatus.erase (params.m_rnti);
559  m_dlHarqProcessesTimer.erase (params.m_rnti);
560  m_dlHarqProcessesDciBuffer.erase (params.m_rnti);
562  m_ulHarqCurrentProcessId.erase (params.m_rnti);
563  m_ulHarqProcessesStatus.erase (params.m_rnti);
564  m_ulHarqProcessesDciBuffer.erase (params.m_rnti);
565  m_flowStatsDl.erase (params.m_rnti);
566  m_flowStatsUl.erase (params.m_rnti);
567  m_ceBsrRxed.erase (params.m_rnti);
568  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
569  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator temp;
570  while (it!=m_rlcBufferReq.end ())
571  {
572  if ((*it).first.m_rnti == params.m_rnti)
573  {
574  temp = it;
575  it++;
576  m_rlcBufferReq.erase (temp);
577  }
578  else
579  {
580  it++;
581  }
582  }
583  if (m_nextRntiUl == params.m_rnti)
584  {
585  m_nextRntiUl = 0;
586  }
587 
588  return;
589 }
590 
591 
592 void
594 {
595  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
596  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
597 
598  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
599 
600  LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity);
601 
602  it = m_rlcBufferReq.find (flow);
603 
604  if (it == m_rlcBufferReq.end ())
605  {
606  m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters> (flow, params));
607  }
608  else
609  {
610  (*it).second = params;
611  }
612 
613  return;
614 }
615 
616 void
618 {
619  NS_LOG_FUNCTION (this);
620  NS_FATAL_ERROR ("method not implemented");
621  return;
622 }
623 
624 void
626 {
627  NS_LOG_FUNCTION (this);
628  NS_FATAL_ERROR ("method not implemented");
629  return;
630 }
631 
632 int
634 {
635  for (int i = 0; i < 4; i++)
636  {
637  if (dlbandwidth < CqaType0AllocationRbg[i])
638  {
639  return (i + 1);
640  }
641  }
642 
643  return (-1);
644 }
645 
646 
647 int
649 {
650  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
651  int lcActive = 0;
652  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
653  {
654  if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueSize > 0)
655  || ((*it).second.m_rlcRetransmissionQueueSize > 0)
656  || ((*it).second.m_rlcStatusPduSize > 0) ))
657  {
658  lcActive++;
659  }
660  if ((*it).first.m_rnti > rnti)
661  {
662  break;
663  }
664  }
665  return (lcActive);
666 
667 }
668 
669 
670 uint8_t
672 {
673  NS_LOG_FUNCTION (this << rnti);
674 
675  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
676  if (it == m_dlHarqCurrentProcessId.end ())
677  {
678  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
679  }
680  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
681  if (itStat == m_dlHarqProcessesStatus.end ())
682  {
683  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
684  }
685  uint8_t i = (*it).second;
686  do
687  {
688  i = (i + 1) % HARQ_PROC_NUM;
689  }
690  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
691  if ((*itStat).second.at (i) == 0)
692  {
693  return (true);
694  }
695  else
696  {
697  return (false); // return a not valid harq proc id
698  }
699 }
700 
701 
702 
703 uint8_t
705 {
706  NS_LOG_FUNCTION (this << rnti);
707 
708  if (m_harqOn == false)
709  {
710  return (0);
711  }
712 
713 
714  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
715  if (it == m_dlHarqCurrentProcessId.end ())
716  {
717  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
718  }
719  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
720  if (itStat == m_dlHarqProcessesStatus.end ())
721  {
722  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
723  }
724  uint8_t i = (*it).second;
725  do
726  {
727  i = (i + 1) % HARQ_PROC_NUM;
728  }
729  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
730  if ((*itStat).second.at (i) == 0)
731  {
732  (*it).second = i;
733  (*itStat).second.at (i) = 1;
734  }
735  else
736  {
737  NS_FATAL_ERROR ("No HARQ process available for RNTI " << rnti << " check before update with HarqProcessAvailability");
738  }
739 
740  return ((*it).second);
741 }
742 
743 
744 void
746 {
747  NS_LOG_FUNCTION (this);
748 
749  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
750  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers++)
751  {
752  for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
753  {
754  if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
755  {
756  // reset HARQ process
757 
758  NS_LOG_DEBUG (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
759  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
760  if (itStat == m_dlHarqProcessesStatus.end ())
761  {
762  NS_FATAL_ERROR ("No Process Id Status found for this RNTI " << (*itTimers).first);
763  }
764  (*itStat).second.at (i) = 0;
765  (*itTimers).second.at (i) = 0;
766  }
767  else
768  {
769  (*itTimers).second.at (i)++;
770  }
771  }
772  }
773 
774 }
775 
776 
777 void
779 {
780  NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
781  // API generated by RLC for triggering the scheduling of a DL subframe
782  // evaluate the relative channel quality indicator for each UE per each RBG
783  // (since we are using allocation type 0 the small unit of allocation is RBG)
784  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
785 
786  RefreshDlCqiMaps ();
787 
789  int numberOfRBGs = m_cschedCellConfig.m_dlBandwidth / rbgSize;
790  std::map <uint16_t, std::multimap <uint8_t, qos_rb_and_CQI_assigned_to_lc> > allocationMapPerRntiPerLCId;
791  std::map <uint16_t, std::multimap <uint8_t, qos_rb_and_CQI_assigned_to_lc> >::iterator itMap;
792  allocationMapPerRntiPerLCId.clear ();
793  bool(*key_function_pointer_groups)(int,int) = CqaGroupDescComparator;
794  t_map_HOLgroupToUEs map_GBRHOLgroupToUE (key_function_pointer_groups);
795  t_map_HOLgroupToUEs map_nonGBRHOLgroupToUE (key_function_pointer_groups);
796  int grouping_parameter = 1000;
797  double tolerance = 1.1;
798  std::map<LteFlowId_t,int> UEtoHOL;
799  std::vector <bool> rbgMap; // global RBGs map
800  uint16_t rbgAllocatedNum = 0;
801  std::set <uint16_t> rntiAllocated;
802  rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
803 
804  rbgMap = m_ffrSapProvider->GetAvailableDlRbg ();
805  for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
806  {
807  if ((*it) == true )
808  {
809  rbgAllocatedNum++;
810  }
811  }
812 
814 
815  // update UL HARQ proc id
816  std::map <uint16_t, uint8_t>::iterator itProcId;
817  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
818  {
819  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
820  }
821 
822 
823  // RACH Allocation
824  uint16_t rbAllocatedNum = 0;
825  std::vector <bool> ulRbMap;
826  ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
827  ulRbMap = m_ffrSapProvider->GetAvailableUlRbg ();
828  uint8_t maxContinuousUlBandwidth = 0;
829  uint8_t tmpMinBandwidth = 0;
830  uint16_t ffrRbStartOffset = 0;
831  uint16_t tmpFfrRbStartOffset = 0;
832  uint16_t index = 0;
833 
834  for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
835  {
836  if ((*it) == true )
837  {
838  rbAllocatedNum++;
839  if (tmpMinBandwidth > maxContinuousUlBandwidth)
840  {
841  maxContinuousUlBandwidth = tmpMinBandwidth;
842  ffrRbStartOffset = tmpFfrRbStartOffset;
843  }
844  tmpMinBandwidth = 0;
845  }
846  else
847  {
848  if (tmpMinBandwidth == 0)
849  {
850  tmpFfrRbStartOffset = index;
851  }
852  tmpMinBandwidth++;
853  }
854  index++;
855  }
856 
857  if (tmpMinBandwidth > maxContinuousUlBandwidth)
858  {
859  maxContinuousUlBandwidth = tmpMinBandwidth;
860  ffrRbStartOffset = tmpFfrRbStartOffset;
861  }
862 
864  uint16_t rbStart = 0;
865  rbStart = ffrRbStartOffset;
866  std::vector <struct RachListElement_s>::iterator itRach;
867  for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
868  {
869  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");
870  BuildRarListElement_s newRar;
871  newRar.m_rnti = (*itRach).m_rnti;
872  // DL-RACH Allocation
873  // Ideal: no needs of configuring m_dci
874  // UL-RACH Allocation
875  newRar.m_grant.m_rnti = newRar.m_rnti;
876  newRar.m_grant.m_mcs = m_ulGrantMcs;
877  uint16_t rbLen = 1;
878  uint16_t tbSizeBits = 0;
879  // find lowest TB size that fits UL grant estimated size
880  while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
881  {
882  rbLen++;
883  tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
884  }
885  if (tbSizeBits < (*itRach).m_estimatedSize)
886  {
887  // no more allocation space: finish allocation
888  break;
889  }
890  newRar.m_grant.m_rbStart = rbStart;
891  newRar.m_grant.m_rbLen = rbLen;
892  newRar.m_grant.m_tbSize = tbSizeBits / 8;
893  newRar.m_grant.m_hopping = false;
894  newRar.m_grant.m_tpc = 0;
895  newRar.m_grant.m_cqiRequest = false;
896  newRar.m_grant.m_ulDelay = false;
897  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);
898  for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
899  {
900  m_rachAllocationMap.at (i) = (*itRach).m_rnti;
901  }
902 
903  if (m_harqOn == true)
904  {
905  // generate UL-DCI for HARQ retransmissions
906  UlDciListElement_s uldci;
907  uldci.m_rnti = newRar.m_rnti;
908  uldci.m_rbLen = rbLen;
909  uldci.m_rbStart = rbStart;
910  uldci.m_mcs = m_ulGrantMcs;
911  uldci.m_tbSize = tbSizeBits / 8;
912  uldci.m_ndi = 1;
913  uldci.m_cceIndex = 0;
914  uldci.m_aggrLevel = 1;
915  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
916  uldci.m_hopping = false;
917  uldci.m_n2Dmrs = 0;
918  uldci.m_tpc = 0; // no power control
919  uldci.m_cqiRequest = false; // only period CQI at this stage
920  uldci.m_ulIndex = 0; // TDD parameter
921  uldci.m_dai = 1; // TDD parameter
922  uldci.m_freqHopping = 0;
923  uldci.m_pdcchPowerOffset = 0; // not used
924 
925  uint8_t harqId = 0;
926  std::map <uint16_t, uint8_t>::iterator itProcId;
927  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
928  if (itProcId == m_ulHarqCurrentProcessId.end ())
929  {
930  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
931  }
932  harqId = (*itProcId).second;
933  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
934  if (itDci == m_ulHarqProcessesDciBuffer.end ())
935  {
936  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
937  }
938  (*itDci).second.at (harqId) = uldci;
939  }
940 
941  rbStart = rbStart + rbLen;
942  ret.m_buildRarList.push_back (newRar);
943  }
944  m_rachList.clear ();
945 
946 
947  // Process DL HARQ feedback
949  // retrieve past HARQ retx buffered
950  if (m_dlInfoListBuffered.size () > 0)
951  {
952  if (params.m_dlInfoList.size () > 0)
953  {
954  NS_LOG_INFO (this << " Received DL-HARQ feedback");
955  m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
956  }
957  }
958  else
959  {
960  if (params.m_dlInfoList.size () > 0)
961  {
963  }
964  }
965  if (m_harqOn == false)
966  {
967  // Ignore HARQ feedback
968  m_dlInfoListBuffered.clear ();
969  }
970  std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
971  for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
972  {
973  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
974  if (itRnti != rntiAllocated.end ())
975  {
976  // RNTI already allocated for retx
977  continue;
978  }
979  uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
980  std::vector <bool> retx;
981  NS_LOG_INFO (this << " Processing DLHARQ feedback");
982  if (nLayers == 1)
983  {
984  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
985  retx.push_back (false);
986  }
987  else
988  {
989  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
990  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
991  }
992  if (retx.at (0) || retx.at (1))
993  {
994  // retrieve HARQ process information
995  uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
996  uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
997  NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
998  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
999  if (itHarq == m_dlHarqProcessesDciBuffer.end ())
1000  {
1001  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
1002  }
1003 
1004  DlDciListElement_s dci = (*itHarq).second.at (harqId);
1005  int rv = 0;
1006  if (dci.m_rv.size () == 1)
1007  {
1008  rv = dci.m_rv.at (0);
1009  }
1010  else
1011  {
1012  rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
1013  }
1014 
1015  if (rv == 3)
1016  {
1017  // maximum number of retx reached -> drop process
1018  NS_LOG_INFO ("Maximum number of retransmissions reached -> drop process");
1019  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
1020  if (it == m_dlHarqProcessesStatus.end ())
1021  {
1022  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
1023  }
1024  (*it).second.at (harqId) = 0;
1025  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
1026  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1027  {
1028  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
1029  }
1030  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
1031  {
1032  (*itRlcPdu).second.at (k).at (harqId).clear ();
1033  }
1034  continue;
1035  }
1036  // check the feasibility of retransmitting on the same RBGs
1037  // translate the DCI to Spectrum framework
1038  std::vector <int> dciRbg;
1039  uint32_t mask = 0x1;
1040  NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
1041  for (int j = 0; j < 32; j++)
1042  {
1043  if (((dci.m_rbBitmap & mask) >> j) == 1)
1044  {
1045  dciRbg.push_back (j);
1046  NS_LOG_INFO ("\t" << j);
1047  }
1048  mask = (mask << 1);
1049  }
1050  bool free = true;
1051  for (uint8_t j = 0; j < dciRbg.size (); j++)
1052  {
1053  if (rbgMap.at (dciRbg.at (j)) == true)
1054  {
1055  free = false;
1056  break;
1057  }
1058  }
1059  if (free)
1060  {
1061  // use the same RBGs for the retx
1062  // reserve RBGs
1063  for (uint8_t j = 0; j < dciRbg.size (); j++)
1064  {
1065  rbgMap.at (dciRbg.at (j)) = true;
1066  NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
1067  rbgAllocatedNum++;
1068  }
1069 
1070  NS_LOG_INFO (this << " Send retx in the same RBGs");
1071  }
1072  else
1073  {
1074  // find RBGs for sending HARQ retx
1075  uint8_t j = 0;
1076  uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % numberOfRBGs;
1077  uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
1078  std::vector <bool> rbgMapCopy = rbgMap;
1079  while ((j < dciRbg.size ())&&(startRbg != rbgId))
1080  {
1081  if (rbgMapCopy.at (rbgId) == false)
1082  {
1083  rbgMapCopy.at (rbgId) = true;
1084  dciRbg.at (j) = rbgId;
1085  j++;
1086  }
1087  rbgId = (rbgId + 1) % numberOfRBGs;
1088  }
1089  if (j == dciRbg.size ())
1090  {
1091  // find new RBGs -> update DCI map
1092  uint32_t rbgMask = 0;
1093  for (uint16_t k = 0; k < dciRbg.size (); k++)
1094  {
1095  rbgMask = rbgMask + (0x1 << dciRbg.at (k));
1096  rbgAllocatedNum++;
1097  }
1098  dci.m_rbBitmap = rbgMask;
1099  rbgMap = rbgMapCopy;
1100  NS_LOG_INFO (this << " Move retx in RBGs " << dciRbg.size ());
1101  }
1102  else
1103  {
1104  // HARQ retx cannot be performed on this TTI -> store it
1105  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
1106  NS_LOG_INFO (this << " No resource for this retx -> buffer it");
1107  }
1108  }
1109  // retrieve RLC PDU list for retx TBsize and update DCI
1110  BuildDataListElement_s newEl;
1111  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
1112  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1113  {
1114  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
1115  }
1116  for (uint8_t j = 0; j < nLayers; j++)
1117  {
1118  if (retx.at (j))
1119  {
1120  if (j >= dci.m_ndi.size ())
1121  {
1122  // for avoiding errors in MIMO transient phases
1123  dci.m_ndi.push_back (0);
1124  dci.m_rv.push_back (0);
1125  dci.m_mcs.push_back (0);
1126  dci.m_tbsSize.push_back (0);
1127  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
1128  }
1129  else
1130  {
1131  dci.m_ndi.at (j) = 0;
1132  dci.m_rv.at (j)++;
1133  (*itHarq).second.at (harqId).m_rv.at (j)++;
1134  NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
1135  }
1136  }
1137  else
1138  {
1139  // empty TB of layer j
1140  dci.m_ndi.at (j) = 0;
1141  dci.m_rv.at (j) = 0;
1142  dci.m_mcs.at (j) = 0;
1143  dci.m_tbsSize.at (j) = 0;
1144  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
1145  }
1146  }
1147  for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
1148  {
1149  std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
1150  for (uint8_t j = 0; j < nLayers; j++)
1151  {
1152  if (retx.at (j))
1153  {
1154  if (j < dci.m_ndi.size ())
1155  {
1156  rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
1157  }
1158  }
1159  }
1160 
1161  if (rlcPduListPerLc.size () > 0)
1162  {
1163  newEl.m_rlcPduList.push_back (rlcPduListPerLc);
1164  }
1165  }
1166  newEl.m_rnti = rnti;
1167  newEl.m_dci = dci;
1168  (*itHarq).second.at (harqId).m_rv = dci.m_rv;
1169  // refresh timer
1170  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
1171  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1172  {
1173  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
1174  }
1175  (*itHarqTimer).second.at (harqId) = 0;
1176  ret.m_buildDataList.push_back (newEl);
1177  rntiAllocated.insert (rnti);
1178  }
1179  else
1180  {
1181  // update HARQ process status
1182  NS_LOG_INFO (this << " HARQ received ACK for UE " << m_dlInfoListBuffered.at (i).m_rnti);
1183  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
1184  if (it == m_dlHarqProcessesStatus.end ())
1185  {
1186  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
1187  }
1188  (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
1189  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
1190  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1191  {
1192  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
1193  }
1194  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
1195  {
1196  (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
1197  }
1198  }
1199  }
1200  m_dlInfoListBuffered.clear ();
1201  m_dlInfoListBuffered = dlInfoListUntxed;
1202 
1203 
1204  std::map <LteFlowId_t,struct LogicalChannelConfigListElement_s>::iterator itLogicalChannels;
1205 
1206  for (itLogicalChannels = m_ueLogicalChannelsConfigList.begin (); itLogicalChannels != m_ueLogicalChannelsConfigList.end (); itLogicalChannels++)
1207  {
1208  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (itLogicalChannels->first.m_rnti);
1209  if ((itRnti != rntiAllocated.end ())||(!HarqProcessAvailability (itLogicalChannels->first.m_rnti)))
1210  {
1211  // UE already allocated for HARQ or without HARQ process available -> drop it
1212  if (itRnti != rntiAllocated.end ())
1213  {
1214  NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(itLogicalChannels->first.m_rnti));
1215  }
1216  if (!HarqProcessAvailability (itLogicalChannels->first.m_rnti))
1217  {
1218  NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(itLogicalChannels->first.m_rnti));
1219  }
1220  continue;
1221  }
1222 
1223 
1224  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itRlcBufferReq = m_rlcBufferReq.find (itLogicalChannels->first);
1225  if (itRlcBufferReq==m_rlcBufferReq.end ())
1226  continue;
1227 
1228  int group = -1;
1229  int delay = 0;
1230 
1231  if (itRlcBufferReq->second.m_rlcRetransmissionQueueSize > 0)
1232  {
1233  delay = itRlcBufferReq->second.m_rlcRetransmissionHolDelay;
1234  group = delay/grouping_parameter;
1235  }
1236  else if (itRlcBufferReq->second.m_rlcTransmissionQueueSize > 0)
1237  {
1238  delay = itRlcBufferReq->second.m_rlcTransmissionQueueHolDelay;
1239  group = delay/grouping_parameter;
1240  }
1241  else
1242  {
1243  continue;
1244  }
1245 
1246  UEtoHOL.insert (std::pair<LteFlowId_t,int>(itLogicalChannels->first,delay));
1247 
1248  if (itLogicalChannels->second.m_qosBearerType == itLogicalChannels->second.QBT_NON_GBR )
1249  {
1250  if (map_nonGBRHOLgroupToUE.count (group)==0)
1251  {
1252  std::set<LteFlowId_t> v;
1253  v.insert (itRlcBufferReq->first);
1254  map_nonGBRHOLgroupToUE.insert (std::pair<int,std::set<LteFlowId_t> >(group,v));
1255  }
1256  else
1257  {
1258  map_nonGBRHOLgroupToUE.find (group)->second.insert (itRlcBufferReq->first);
1259  }
1260  }
1261  else if (itLogicalChannels->second.m_qosBearerType == itLogicalChannels->second.QBT_GBR) {
1262  if (map_GBRHOLgroupToUE.count (group)==0)
1263  {
1264  std::set<LteFlowId_t> v;
1265  v.insert (itRlcBufferReq->first);
1266  map_GBRHOLgroupToUE.insert (std::pair<int,std::set<LteFlowId_t> >(group,v));
1267  }
1268  else
1269  {
1270  map_GBRHOLgroupToUE.find (group)->second.insert (itRlcBufferReq->first);
1271  }
1272  }
1273  };
1274 
1275 
1276  // Prepare data for the scheduling mechanism
1277  // map: UE, to the amount of traffic they have to transfer
1278  std::map<LteFlowId_t, int> UeToAmountOfDataToTransfer;
1279  //Initialize the map per UE, how much resources is already assigned to the user
1280  std::map<LteFlowId_t, int> UeToAmountOfAssignedResources;
1281  // prepare values to calculate FF metric, this metric will be the same for all flows(logical channels) that belong to the same RNTI
1282  std::map < uint16_t, uint8_t > sbCqiSum;
1283 
1284  for( std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itrbr = m_rlcBufferReq.begin ();
1285  itrbr!=m_rlcBufferReq.end (); itrbr++)
1286  {
1287 
1288  LteFlowId_t flowId = itrbr->first; // Prepare data for the scheduling mechanism
1289  // map: UE, to the amount of traffic they have to transfer
1290  int amountOfDataToTransfer = 8*((int)m_rlcBufferReq.find (flowId)->second.m_rlcRetransmissionQueueSize +
1291  (int)m_rlcBufferReq.find (flowId)->second.m_rlcTransmissionQueueSize);
1292 
1293  UeToAmountOfDataToTransfer.insert (std::pair<LteFlowId_t,int>(flowId,amountOfDataToTransfer));
1294  UeToAmountOfAssignedResources.insert (std::pair<LteFlowId_t,int>(flowId,0));
1295 
1296  uint8_t sum = 0;
1297  for (int i = 0; i < numberOfRBGs; i++)
1298  {
1299  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1300  itCqi = m_a30CqiRxed.find ((*itrbr).first.m_rnti);
1301  std::map <uint16_t,uint8_t>::iterator itTxMode;
1302  itTxMode = m_uesTxMode.find ((*itrbr).first.m_rnti);
1303  if (itTxMode == m_uesTxMode.end ())
1304  {
1305  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itrbr).first.m_rnti);
1306  }
1307  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1308  std::vector <uint8_t> sbCqis;
1309  if (itCqi == m_a30CqiRxed.end ())
1310  {
1311  for (uint8_t k = 0; k < nLayer; k++)
1312  {
1313  sbCqis.push_back (1); // start with lowest value
1314  }
1315  }
1316  else
1317  {
1318  sbCqis = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi;
1319  }
1320 
1321  uint8_t cqi1 = sbCqis.at (0);
1322  uint8_t cqi2 = 1;
1323  if (sbCqis.size () > 1)
1324  {
1325  cqi2 = sbCqis.at (1);
1326  }
1327 
1328  uint8_t sbCqi;
1329  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1330  {
1331  for (uint8_t k = 0; k < nLayer; k++)
1332  {
1333  if (sbCqis.size () > k)
1334  {
1335  sbCqi = sbCqis.at (k);
1336  }
1337  else
1338  {
1339  // no info on this subband
1340  sbCqi = 0;
1341  }
1342  sum += sbCqi;
1343  }
1344  } // end if cqi
1345  } // end of rbgNum
1346 
1347  sbCqiSum.insert (std::pair<uint16_t, uint8_t> ((*itrbr).first.m_rnti, sum));
1348  }
1349 
1350  // availableRBGs - set that contains indexes of available resource block groups
1351  std::set<int> availableRBGs;
1352  for (int i = 0; i < numberOfRBGs; i++)
1353  {
1354  if (rbgMap.at (i) == false)
1355  {
1356  availableRBGs.insert (i);
1357  }
1358  }
1359 
1360  t_it_HOLgroupToUEs itGBRgroups = map_GBRHOLgroupToUE.begin ();
1361  t_it_HOLgroupToUEs itnonGBRgroups = map_nonGBRHOLgroupToUE.begin ();
1362 
1363 
1364 
1365  // while there are more resources available, loop through the users that are grouped by HOL value
1366  while (availableRBGs.size ()>0)
1367  {
1368  std::set<LteFlowId_t> vUEs;
1369  t_it_HOLgroupToUEs itCurrentGroup;
1370 
1371  if (itGBRgroups!=map_GBRHOLgroupToUE.end ())
1372  {
1373  itCurrentGroup=itGBRgroups;
1374  itGBRgroups++;
1375  }
1376  else if (itnonGBRgroups!=map_nonGBRHOLgroupToUE.end ()) // if there are no more flows with retransmission queue start to scheduler flows with transmission queue
1377  {
1378  itCurrentGroup=itnonGBRgroups;
1379  itnonGBRgroups++;
1380  }
1381  else
1382  {
1383  NS_LOG_INFO ("Available RBGs:"<< availableRBGs.size ()<<"but no users");
1384  break;
1385  }
1386 
1387  while (availableRBGs.size ()>0 and itCurrentGroup->second.size ()>0)
1388  {
1389  bool currentRBchecked = false;
1390  int currentRB = *(availableRBGs.begin ());
1391  std::map<LteFlowId_t, CQI_value> UeToCQIValue;
1392  std::map<LteFlowId_t, double > UeToCoitaMetric;
1393  std::map<LteFlowId_t, bool> UeHasReachedGBR;
1394  double maximumValueMetric = 0;
1395  LteFlowId_t userWithMaximumMetric;
1396  UeToCQIValue.clear ();
1397  UeToCoitaMetric.clear ();
1398 
1399  // Iterate through the users and calculate which user will use the best of the current resource bloc.end()k and assign to that user.
1400  for (std::set<LteFlowId_t>::iterator it=itCurrentGroup->second.begin (); it!=itCurrentGroup->second.end (); it++)
1401  {
1402  LteFlowId_t flowId = *it;
1403  uint8_t cqi_value = 1; //higher better, maximum is 15
1404  double coita_metric = 1;
1405  double coita_sum = 0;
1406  double metric = 0;
1407  uint8_t worstCQIAmongRBGsAllocatedForThisUser = 15;
1408  int numberOfRBGAllocatedForThisUser = 0;
1410  std::map <uint16_t,SbMeasResult_s>::iterator itRntiCQIsMap = m_a30CqiRxed.find (flowId.m_rnti);
1411 
1412  std::map <uint16_t, CqasFlowPerf_t>::iterator itStats;
1413 
1414  if ((m_ffrSapProvider->IsDlRbgAvailableForUe (currentRB, flowId.m_rnti)) == false)
1415  {
1416  continue;
1417  }
1418 
1419  if (m_flowStatsDl.find (flowId.m_rnti) == m_flowStatsDl.end ())
1420  {
1421  continue; // TO DO: check if this should be logged and how.
1422  }
1423  currentRBchecked = true;
1424 
1425  itStats = m_flowStatsDl.find (flowId.m_rnti);
1426  double tbr_weight = (*itStats).second.targetThroughput / (*itStats).second.lastAveragedThroughput;
1427  if (tbr_weight < 1.0)
1428  tbr_weight = 1.0;
1429 
1430  if (itRntiCQIsMap != m_a30CqiRxed.end ())
1431  {
1432  for(std::set<int>::iterator it=availableRBGs.begin (); it!=availableRBGs.end (); it++)
1433  {
1434  try
1435  {
1436  int val = (itRntiCQIsMap->second.m_higherLayerSelected.at (*it).m_sbCqi.at (0));
1437  if (val==0)
1438  val=1; //if no info, use minimum
1439  if (*it == currentRB)
1440  cqi_value = val;
1441  coita_sum+=val;
1442 
1443  }
1444  catch(std::out_of_range&)
1445  {
1446  coita_sum+=1; //if no info on channel use the worst cqi
1447  NS_LOG_INFO ("No CQI for lcId:"<<flowId.m_lcId<<" rnti:"<<flowId.m_rnti<<" at subband:"<<currentRB);
1448  //std::cout<<"\n No CQI for lcId:.....................................";
1449  }
1450  }
1451  coita_metric =cqi_value/coita_sum;
1452  UeToCQIValue.insert (std::pair<LteFlowId_t,CQI_value>(flowId,cqi_value));
1453  UeToCoitaMetric.insert (std::pair<LteFlowId_t, double>(flowId,coita_metric));
1454  }
1455 
1456  if (allocationMapPerRntiPerLCId.find (flowId.m_rnti)==allocationMapPerRntiPerLCId.end ())
1457  {
1458  worstCQIAmongRBGsAllocatedForThisUser=cqi_value;
1459  }
1460  else {
1461 
1462  numberOfRBGAllocatedForThisUser = (allocationMapPerRntiPerLCId.find (flowId.m_rnti)->second.size ());
1463 
1464  for (std::multimap <uint8_t, qos_rb_and_CQI_assigned_to_lc>::iterator itRBG = allocationMapPerRntiPerLCId.find (flowId.m_rnti)->second.begin ();
1465  itRBG!=allocationMapPerRntiPerLCId.find (flowId.m_rnti)->second.end (); itRBG++)
1466  {
1467  qos_rb_and_CQI_assigned_to_lc e = itRBG->second;
1468  if (e.cqi_value_for_lc < worstCQIAmongRBGsAllocatedForThisUser)
1469  worstCQIAmongRBGsAllocatedForThisUser=e.cqi_value_for_lc;
1470  }
1471 
1472  if (cqi_value < worstCQIAmongRBGsAllocatedForThisUser)
1473  {
1474  worstCQIAmongRBGsAllocatedForThisUser=cqi_value;
1475  }
1476  }
1477 
1478  int mcsForThisUser = m_amc->GetMcsFromCqi (worstCQIAmongRBGsAllocatedForThisUser);
1479  int tbSize = m_amc->GetTbSizeFromMcs (mcsForThisUser, (numberOfRBGAllocatedForThisUser+1) * rbgSize)/8; // similar to calculation of TB size (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
1480 
1481 
1482  double achievableRate = (( m_amc->GetTbSizeFromMcs (mcsForThisUser, rbgSize)/ 8) / 0.001);
1483  double pf_weight = achievableRate / (*itStats).second.secondLastAveragedThroughput;
1484 
1485  UeToAmountOfAssignedResources.find (flowId)->second = tbSize;
1486  FfMacSchedSapProvider::SchedDlRlcBufferReqParameters lcBufferInfo = m_rlcBufferReq.find (flowId)->second;
1487 
1488  if (UeToAmountOfDataToTransfer.find (flowId)->second - UeToAmountOfAssignedResources.find (flowId)->second < 0)
1489  {
1490  UeHasReachedGBR.insert (std::pair<LteFlowId_t,bool>(flowId,false));
1491  }
1492 
1493  double bitRateWithNewRBG = 0;
1494 
1495  if (m_flowStatsDl.find (flowId.m_rnti)!= m_flowStatsDl.end ()) // there are some statistics{
1496  {
1497  bitRateWithNewRBG = (1.0 - (1.0 / m_timeWindow)) * (m_flowStatsDl.find (flowId.m_rnti)->second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)(tbSize*1000));
1498  }
1499  else
1500  {
1501  bitRateWithNewRBG = (1.0 / m_timeWindow) * (double)(tbSize*1000);
1502  }
1503 
1504  if(bitRateWithNewRBG > lc.m_eRabGuaranteedBitrateDl)
1505  {
1506  UeHasReachedGBR.insert (std::pair<LteFlowId_t,bool>(flowId,true));
1507  }
1508  else
1509  {
1510  UeHasReachedGBR.insert (std::pair<LteFlowId_t,bool>(flowId,false));
1511  }
1512 
1513  int hol = UEtoHOL.find (flowId)->second;
1514 
1515  if (hol==0)
1516  hol=1;
1517 
1518  if ( m_CqaMetric.compare ("CqaFf") == 0)
1519  {
1520  metric = coita_metric*tbr_weight*hol;
1521  }
1522  else if (m_CqaMetric.compare ("CqaPf") == 0)
1523  {
1524  metric = tbr_weight*pf_weight*hol;
1525  }
1526  else
1527  {
1528  metric = 1;
1529  }
1530 
1531  if (metric >= maximumValueMetric)
1532  {
1533  maximumValueMetric = metric;
1534  userWithMaximumMetric = flowId;
1535  }
1536  }
1537 
1538  if (!currentRBchecked)
1539  {
1540  // erase current RBG from the list of available RBG
1541  availableRBGs.erase (currentRB);
1542  continue;
1543  }
1544 
1546  s.cqi_value_for_lc = UeToCQIValue.find (userWithMaximumMetric)->second;
1547  s.resource_block_index = currentRB;
1548 
1549  itMap = allocationMapPerRntiPerLCId.find (userWithMaximumMetric.m_rnti);
1550 
1551  if (itMap == allocationMapPerRntiPerLCId.end ())
1552  {
1553  std::multimap <uint8_t, qos_rb_and_CQI_assigned_to_lc> tempMap;
1554  tempMap.insert (std::pair<uint8_t, qos_rb_and_CQI_assigned_to_lc> (userWithMaximumMetric.m_lcId,s));
1555  allocationMapPerRntiPerLCId.insert (std::pair <uint16_t, std::multimap <uint8_t,qos_rb_and_CQI_assigned_to_lc> > (userWithMaximumMetric.m_rnti, tempMap));
1556  }
1557  else
1558  {
1559  itMap->second.insert (std::pair<uint8_t,qos_rb_and_CQI_assigned_to_lc> (userWithMaximumMetric.m_lcId,s));
1560  }
1561 
1562  // erase current RBG from the list of available RBG
1563  availableRBGs.erase (currentRB);
1564 
1565  if (UeToAmountOfDataToTransfer.find (userWithMaximumMetric)->second <= UeToAmountOfAssignedResources.find (userWithMaximumMetric)->second*tolerance)
1566  //||(UeHasReachedGBR.find(userWithMaximumMetric)->second == true))
1567  {
1568  itCurrentGroup->second.erase (userWithMaximumMetric);
1569  }
1570 
1571  } // while there are more users in current group
1572  } // while there are more groups of users
1573 
1574 
1575  // reset TTI stats of users
1576  std::map <uint16_t, CqasFlowPerf_t>::iterator itStats;
1577  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
1578  {
1579  (*itStats).second.lastTtiBytesTransmitted = 0;
1580  }
1581 
1582  // 3) Creating the correspondent DCIs (Generate the transmission opportunities by grouping the RBGs of the same RNTI)
1583  //FfMacSchedSapUser::SchedDlConfigIndParameters ret;
1584  itMap = allocationMapPerRntiPerLCId.begin ();
1585  int counter = 0;
1586  std::map<uint16_t, double> m_rnti_per_ratio;
1587 
1588  while (itMap != allocationMapPerRntiPerLCId.end ())
1589  {
1590  // create new BuildDataListElement_s for this LC
1591  BuildDataListElement_s newEl;
1592  newEl.m_rnti = (*itMap).first;
1593  NS_LOG_INFO ("Scheduled RNTI:"<<newEl.m_rnti);
1594  // create the DlDciListElement_s
1595  DlDciListElement_s newDci;
1596  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1597  newDci.m_rnti = (*itMap).first;
1598  newDci.m_harqProcess = UpdateHarqProcessId ((*itMap).first);
1599  uint16_t lcActives = LcActivePerFlow (itMap->first);
1600  if (lcActives==0) // if there is still no buffer report information on any flow
1601  lcActives = 1;
1602  // NS_LOG_DEBUG (this << "Allocate user " << newEl.m_rnti << " rbg " << lcActives);
1603  uint16_t RgbPerRnti = (*itMap).second.size ();
1604  double doubleRBgPerRnti = RgbPerRnti;
1605  double doubleRbgNum = numberOfRBGs;
1606  double rrRatio = doubleRBgPerRnti/doubleRbgNum;
1607  m_rnti_per_ratio.insert (std::pair<uint16_t,double>((*itMap).first,rrRatio));
1608  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1609  itCqi = m_a30CqiRxed.find ((*itMap).first);
1610  uint8_t worstCqi = 15;
1611 
1612  // assign the worst value of CQI that user experienced on any of its subbands
1613  for ( std::multimap <uint8_t, qos_rb_and_CQI_assigned_to_lc> ::iterator it = (*itMap).second.begin (); it != (*itMap).second.end (); it++)
1614  {
1615  if (it->second.cqi_value_for_lc<worstCqi)
1616  {
1617  worstCqi = it->second.cqi_value_for_lc;
1618  }
1619  counter++;
1620  }
1621 
1622  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi));
1623  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), RgbPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
1624  newDci.m_tbsSize.push_back (tbSize);
1625  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
1626  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
1627  uint32_t rbgMask = 0;
1628  std::multimap <uint8_t, qos_rb_and_CQI_assigned_to_lc> ::iterator itRBGsPerRNTI;
1629  for ( itRBGsPerRNTI = (*itMap).second.begin (); itRBGsPerRNTI != (*itMap).second.end (); itRBGsPerRNTI++)
1630  {
1631  rbgMask = rbgMask + (0x1 << itRBGsPerRNTI->second.resource_block_index);
1632  }
1633  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1634  // NOTE: In this first version of CqaFfMacScheduler, it is assumed one flow per user.
1635  // create the rlc PDUs -> equally divide resources among active LCs
1636  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
1637  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
1638  {
1639  if (((*itBufReq).first.m_rnti == (*itMap).first)
1640  && (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
1641  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
1642  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
1643  {
1644  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1645  //for (uint8_t j = 0; j < nLayer; j++)
1646  //{
1647  RlcPduListElement_s newRlcEl;
1648  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
1649  // newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
1650  newRlcEl.m_size = tbSize / lcActives;
1651  // NS_LOG_INFO (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j);
1652  newRlcPduLe.push_back (newRlcEl);
1653  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
1654  if (m_harqOn == true)
1655  {
1656  // store RLC PDU list for HARQ
1657  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*itMap).first);
1658  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1659  {
1660  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*itMap).first);
1661  }
1662  int j=0;
1663  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1664  }
1665  // }
1666  newEl.m_rlcPduList.push_back (newRlcPduLe);
1667  }
1668  if ((*itBufReq).first.m_rnti > (*itMap).first)
1669  {
1670  break;
1671  }
1672  }
1673  // for (uint8_t j = 0; j < nLayer; j++)
1674  // {
1675  newDci.m_ndi.push_back (1);
1676  newDci.m_rv.push_back (0);
1677  //}
1678 
1679  newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
1680 
1681  newEl.m_dci = newDci;
1682 
1683  if (m_harqOn == true)
1684  {
1685  // store DCI for HARQ
1686  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1687  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1688  {
1689  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1690  }
1691  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1692  // refresh timer
1693  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1694  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1695  {
1696  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1697  }
1698  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1699  }
1700 
1701  // ...more parameters -> ingored in this version
1702 
1703  ret.m_buildDataList.push_back (newEl);
1704  // update UE stats
1705  std::map <uint16_t, CqasFlowPerf_t>::iterator it;
1706  it = m_flowStatsDl.find ((*itMap).first);
1707  if (it != m_flowStatsDl.end ())
1708  {
1709  (*it).second.lastTtiBytesTransmitted = tbSize;
1710  }
1711  else
1712  {
1713  NS_FATAL_ERROR (this << " No Stats for this allocated UE");
1714  }
1715 
1716  itMap++;
1717  } // end while allocation
1718  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
1719 
1720  // update UEs stats
1721  NS_LOG_INFO (this << " Update UEs statistics");
1722  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
1723  {
1724  if (allocationMapPerRntiPerLCId.find (itStats->first)!= allocationMapPerRntiPerLCId.end ())
1725  {
1726  (*itStats).second.secondLastAveragedThroughput = ((1.0 - (1 / m_timeWindow)) * (*itStats).second.secondLastAveragedThroughput) + ((1 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTransmitted / 0.001));
1727  }
1728 
1729  (*itStats).second.totalBytesTransmitted += (*itStats).second.lastTtiBytesTransmitted;
1730  // update average throughput (see eq. 12.3 of Sec 12.3.1.2 of LTE – The UMTS Long Term Evolution, Ed Wiley)
1731  (*itStats).second.lastAveragedThroughput = ((1.0 - (1.0 / m_timeWindow)) * (*itStats).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTransmitted / 0.001));
1732  NS_LOG_INFO (this << " UE total bytes " << (*itStats).second.totalBytesTransmitted);
1733  NS_LOG_INFO (this << " UE average throughput " << (*itStats).second.lastAveragedThroughput);
1734  (*itStats).second.lastTtiBytesTransmitted = 0;
1735  }
1736 
1738 
1739  int count_allocated_resource_blocks = 0;
1740  for (std::map <uint16_t, std::multimap <uint8_t, qos_rb_and_CQI_assigned_to_lc> >::iterator itMap = allocationMapPerRntiPerLCId.begin (); itMap!=allocationMapPerRntiPerLCId.end (); itMap++)
1741  {
1742  count_allocated_resource_blocks+=itMap->second.size ();
1743  }
1744  NS_LOG_INFO (this << " Allocated RBs:" << count_allocated_resource_blocks);
1745 
1746  return;
1747 }
1748 
1749 void
1751 {
1752  NS_LOG_FUNCTION (this);
1753 
1754  m_rachList = params.m_rachList;
1755 
1756  return;
1757 }
1758 
1759 void
1761 {
1762  NS_LOG_FUNCTION (this);
1764 
1765  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1766  {
1767  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1768  {
1769  // wideband CQI reporting
1770  std::map <uint16_t,uint8_t>::iterator it;
1771  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1772  it = m_p10CqiRxed.find (rnti);
1773  if (it == m_p10CqiRxed.end ())
1774  {
1775  // create the new entry
1776  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)
1777  // generate correspondent timer
1778  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1779  }
1780  else
1781  {
1782  // update the CQI value and refresh correspondent timer
1783  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1784  // update correspondent timer
1785  std::map <uint16_t,uint32_t>::iterator itTimers;
1786  itTimers = m_p10CqiTimers.find (rnti);
1787  (*itTimers).second = m_cqiTimersThreshold;
1788  }
1789  }
1790  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1791  {
1792  // subband CQI reporting high layer configured
1793  std::map <uint16_t,SbMeasResult_s>::iterator it;
1794  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1795  it = m_a30CqiRxed.find (rnti);
1796  if (it == m_a30CqiRxed.end ())
1797  {
1798  // create the new entry
1799  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
1800  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1801  }
1802  else
1803  {
1804  // update the CQI value and refresh correspondent timer
1805  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
1806  std::map <uint16_t,uint32_t>::iterator itTimers;
1807  itTimers = m_a30CqiTimers.find (rnti);
1808  (*itTimers).second = m_cqiTimersThreshold;
1809  }
1810  }
1811  else
1812  {
1813  NS_LOG_ERROR (this << " CQI type unknown");
1814  }
1815  }
1816 
1817  return;
1818 }
1819 
1820 
1821 double
1822 CqaFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
1823 {
1824  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
1825  if (itCqi == m_ueCqi.end ())
1826  {
1827  // no cqi info about this UE
1828  return (NO_SINR);
1829 
1830  }
1831  else
1832  {
1833  // take the average SINR value among the available
1834  double sinrSum = 0;
1835  int sinrNum = 0;
1836  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1837  {
1838  double sinr = (*itCqi).second.at (i);
1839  if (sinr != NO_SINR)
1840  {
1841  sinrSum += sinr;
1842  sinrNum++;
1843  }
1844  }
1845  double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
1846  // store the value
1847  (*itCqi).second.at (rb) = estimatedSinr;
1848  return (estimatedSinr);
1849  }
1850 }
1851 
1852 void
1854 {
1855  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1856 
1857  RefreshUlCqiMaps ();
1859 
1860  // Generate RBs map
1862  std::vector <bool> rbMap;
1863  uint16_t rbAllocatedNum = 0;
1864  std::set <uint16_t> rntiAllocated;
1865  std::vector <uint16_t> rbgAllocationMap;
1866  // update with RACH allocation map
1867  rbgAllocationMap = m_rachAllocationMap;
1868  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1869  m_rachAllocationMap.clear ();
1871 
1872  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1873 
1874  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
1875 
1876  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
1877  {
1878  if ((*it) == true )
1879  {
1880  rbAllocatedNum++;
1881  }
1882  }
1883 
1884  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
1885  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
1886 
1887  // remove RACH allocation
1888  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1889  {
1890  if (rbgAllocationMap.at (i) != 0)
1891  {
1892  rbMap.at (i) = true;
1893  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1894  }
1895  }
1896 
1897 
1898  if (m_harqOn == true)
1899  {
1900  // Process UL HARQ feedback
1901  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1902  {
1903  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1904  {
1905  // retx correspondent block: retrieve the UL-DCI
1906  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1907  std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1908  if (itProcId == m_ulHarqCurrentProcessId.end ())
1909  {
1910  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1911  }
1912  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1913  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId << " i " << i << " size " << params.m_ulInfoList.size ());
1914  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1915  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1916  {
1917  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1918  continue;
1919  }
1920  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1921  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1922  if (itStat == m_ulHarqProcessesStatus.end ())
1923  {
1924  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1925  }
1926  if ((*itStat).second.at (harqId) >= 3)
1927  {
1928  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1929  continue;
1930  }
1931  bool free = true;
1932 
1933  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1934  {
1935  if (rbMap.at (j) == true)
1936  {
1937  free = false;
1938  NS_LOG_INFO (this << " BUSY " << j);
1939  }
1940  }
1941  if (free)
1942  {
1943  // retx on the same RBs
1944  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1945  {
1946  rbMap.at (j) = true;
1947  rbgAllocationMap.at (j) = dci.m_rnti;
1948  NS_LOG_INFO ("\tRB " << j);
1949  rbAllocatedNum++;
1950  }
1951  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);
1952  }
1953  else
1954  {
1955  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1956  continue;
1957  }
1958  dci.m_ndi = 0;
1959  // Update HARQ buffers with new HarqId
1960  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1961  (*itStat).second.at (harqId) = 0;
1962  (*itHarq).second.at ((*itProcId).second) = dci;
1963  ret.m_dciList.push_back (dci);
1964  rntiAllocated.insert (dci.m_rnti);
1965  }
1966  else
1967  {
1968  NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
1969  }
1970  }
1971  }
1972 
1973  std::map <uint16_t,uint32_t>::iterator it;
1974  int nflows = 0;
1975 
1976  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1977  {
1978  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1979  // select UEs with queues not empty and not yet allocated for HARQ
1980  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1981  {
1982  nflows++;
1983  }
1984  }
1985 
1986  if (nflows == 0)
1987  {
1988  if (ret.m_dciList.size () > 0)
1989  {
1990  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1992  }
1993 
1994  return; // no flows to be scheduled
1995  }
1996 
1997 
1998  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1999  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
2000  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
2001 
2002  if (rbPerFlow < 3)
2003  {
2004  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
2005  }
2006  int rbAllocated = 0;
2007 
2008  std::map <uint16_t, CqasFlowPerf_t>::iterator itStats;
2009  if (m_nextRntiUl != 0)
2010  {
2011  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
2012  {
2013  if ((*it).first == m_nextRntiUl)
2014  {
2015  break;
2016  }
2017  }
2018  if (it == m_ceBsrRxed.end ())
2019  {
2020  NS_LOG_ERROR (this << " no user found");
2021  }
2022  }
2023  else
2024  {
2025  it = m_ceBsrRxed.begin ();
2026  m_nextRntiUl = (*it).first;
2027  }
2028  do
2029  {
2030  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
2031  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
2032  {
2033  // UE already allocated for UL-HARQ -> skip it
2034  NS_LOG_DEBUG (this << " UE already allocated in HARQ -> discared, RNTI " << (*it).first);
2035  it++;
2036  if (it == m_ceBsrRxed.end ())
2037  {
2038  // restart from the first
2039  it = m_ceBsrRxed.begin ();
2040  }
2041  continue;
2042  }
2043  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
2044  {
2045  // limit to physical resources last resource assignment
2046  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
2047  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
2048  if (rbPerFlow < 3)
2049  {
2050  // terminate allocation
2051  rbPerFlow = 0;
2052  }
2053  }
2054 
2055  rbAllocated = 0;
2056  UlDciListElement_s uldci;
2057  uldci.m_rnti = (*it).first;
2058  uldci.m_rbLen = rbPerFlow;
2059  bool allocated = false;
2060  NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
2061  while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
2062  {
2063  // check availability
2064  bool free = true;
2065  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
2066  {
2067  if (rbMap.at (j) == true)
2068  {
2069  free = false;
2070  break;
2071  }
2072  if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
2073  {
2074  free = false;
2075  break;
2076  }
2077  }
2078  if (free)
2079  {
2080  NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
2081  uldci.m_rbStart = rbAllocated;
2082 
2083  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
2084  {
2085  rbMap.at (j) = true;
2086  // store info on allocation for managing ul-cqi interpretation
2087  rbgAllocationMap.at (j) = (*it).first;
2088  }
2089  rbAllocated += rbPerFlow;
2090  allocated = true;
2091  break;
2092  }
2093  rbAllocated++;
2094  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
2095  {
2096  // limit to physical resources last resource assignment
2097  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
2098  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
2099  if (rbPerFlow < 3)
2100  {
2101  // terminate allocation
2102  rbPerFlow = 0;
2103  }
2104  }
2105  }
2106  if (!allocated)
2107  {
2108  // unable to allocate new resource: finish scheduling
2109 // m_nextRntiUl = (*it).first;
2110 // if (ret.m_dciList.size () > 0)
2111 // {
2112 // m_schedSapUser->SchedUlConfigInd (ret);
2113 // }
2114 // m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
2115 // return;
2116  break;
2117  }
2118 
2119 
2120 
2121  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
2122  int cqi = 0;
2123  if (itCqi == m_ueCqi.end ())
2124  {
2125  // no cqi info about this UE
2126  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
2127  }
2128  else
2129  {
2130  // take the lowest CQI value (worst RB)
2131  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
2132  if (minSinr == NO_SINR)
2133  {
2134  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
2135  }
2136  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
2137  {
2138  double sinr = (*itCqi).second.at (i);
2139  if (sinr == NO_SINR)
2140  {
2141  sinr = EstimateUlSinr ((*it).first, i);
2142  }
2143  if ((*itCqi).second.at (i) < minSinr)
2144  {
2145  minSinr = (*itCqi).second.at (i);
2146  }
2147  }
2148 
2149  // translate SINR -> cqi: WILD ACK: same as DL
2150  double s = log2 ( 1 + (
2151  std::pow (10, minSinr / 10 ) /
2152  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
2153  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
2154  if (cqi == 0)
2155  {
2156  it++;
2157  if (it == m_ceBsrRxed.end ())
2158  {
2159  // restart from the first
2160  it = m_ceBsrRxed.begin ();
2161  }
2162  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
2163  // remove UE from allocation map
2164  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
2165  {
2166  rbgAllocationMap.at (i) = 0;
2167  }
2168  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
2169  }
2170  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
2171  }
2172 
2173  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
2174  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
2175  uldci.m_ndi = 1;
2176  uldci.m_cceIndex = 0;
2177  uldci.m_aggrLevel = 1;
2178  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
2179  uldci.m_hopping = false;
2180  uldci.m_n2Dmrs = 0;
2181  uldci.m_tpc = 0; // no power control
2182  uldci.m_cqiRequest = false; // only period CQI at this stage
2183  uldci.m_ulIndex = 0; // TDD parameter
2184  uldci.m_dai = 1; // TDD parameter
2185  uldci.m_freqHopping = 0;
2186  uldci.m_pdcchPowerOffset = 0; // not used
2187  ret.m_dciList.push_back (uldci);
2188  // store DCI for HARQ_PERIOD
2189  uint8_t harqId = 0;
2190  if (m_harqOn == true)
2191  {
2192  std::map <uint16_t, uint8_t>::iterator itProcId;
2193  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
2194  if (itProcId == m_ulHarqCurrentProcessId.end ())
2195  {
2196  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
2197  }
2198  harqId = (*itProcId).second;
2199  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
2200  if (itDci == m_ulHarqProcessesDciBuffer.end ())
2201  {
2202  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
2203  }
2204  (*itDci).second.at (harqId) = uldci;
2205  // Update HARQ process status (RV 0)
2206  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (uldci.m_rnti);
2207  if (itStat == m_ulHarqProcessesStatus.end ())
2208  {
2209  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << uldci.m_rnti);
2210  }
2211  (*itStat).second.at (harqId) = 0;
2212  }
2213 
2214  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);
2215 
2216  // update TTI UE stats
2217  itStats = m_flowStatsUl.find ((*it).first);
2218  if (itStats != m_flowStatsUl.end ())
2219  {
2220  (*itStats).second.lastTtiBytesTransmitted = uldci.m_tbSize;
2221  }
2222  else
2223  {
2224  NS_LOG_DEBUG (this << " No Stats for this allocated UE");
2225  }
2226 
2227 
2228  it++;
2229  if (it == m_ceBsrRxed.end ())
2230  {
2231  // restart from the first
2232  it = m_ceBsrRxed.begin ();
2233  }
2234  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
2235  {
2236  // Stop allocation: no more PRBs
2237  m_nextRntiUl = (*it).first;
2238  break;
2239  }
2240  }
2241  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
2242 
2243 
2244  // Update global UE stats
2245  // update UEs stats
2246  for (itStats = m_flowStatsUl.begin (); itStats != m_flowStatsUl.end (); itStats++)
2247  {
2248  (*itStats).second.totalBytesTransmitted += (*itStats).second.lastTtiBytesTransmitted;
2249  // update average throughput (see eq. 12.3 of Sec 12.3.1.2 of LTE – The UMTS Long Term Evolution, Ed Wiley)
2250  (*itStats).second.lastAveragedThroughput = ((1.0 - (1.0 / m_timeWindow)) * (*itStats).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTransmitted / 0.001));
2251  NS_LOG_INFO (this << " UE total bytes " << (*itStats).second.totalBytesTransmitted);
2252  NS_LOG_INFO (this << " UE average throughput " << (*itStats).second.lastAveragedThroughput);
2253  (*itStats).second.lastTtiBytesTransmitted = 0;
2254  }
2255  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
2257 
2258  return;
2259 }
2260 
2261 void
2263 {
2264  NS_LOG_FUNCTION (this);
2265  return;
2266 }
2267 
2268 void
2270 {
2271  NS_LOG_FUNCTION (this);
2272  return;
2273 }
2274 
2275 void
2277 {
2278  NS_LOG_FUNCTION (this);
2279 
2280  std::map <uint16_t,uint32_t>::iterator it;
2281 
2282  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
2283  {
2284  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
2285  {
2286  // buffer status report
2287  // note that this scheduler does not differentiate the
2288  // allocation according to which LCGs have more/less bytes
2289  // to send.
2290  // Hence the BSR of different LCGs are just summed up to get
2291  // a total queue size that is used for allocation purposes.
2292 
2293  uint32_t buffer = 0;
2294  for (uint8_t lcg = 0; lcg < 4; ++lcg)
2295  {
2296  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
2297  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
2298  }
2299 
2300  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
2301  NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
2302  it = m_ceBsrRxed.find (rnti);
2303  if (it == m_ceBsrRxed.end ())
2304  {
2305  // create the new entry
2306  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
2307  }
2308  else
2309  {
2310  // update the buffer size value
2311  (*it).second = buffer;
2312  }
2313  }
2314  }
2315 
2316  return;
2317 }
2318 
2319 void
2321 {
2322  NS_LOG_FUNCTION (this);
2323 // retrieve the allocation for this subframe
2324  switch (m_ulCqiFilter)
2325  {
2327  {
2328  // filter all the CQIs that are not SRS based
2329  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
2330  {
2331  return;
2332  }
2333  }
2334  break;
2336  {
2337  // filter all the CQIs that are not SRS based
2338  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
2339  {
2340  return;
2341  }
2342  }
2344  break;
2345 
2346  default:
2347  NS_FATAL_ERROR ("Unknown UL CQI type");
2348  }
2349 
2350  switch (params.m_ulCqi.m_type)
2351  {
2352  case UlCqi_s::PUSCH:
2353  {
2354  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
2355  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2356  NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
2357  itMap = m_allocationMaps.find (params.m_sfnSf);
2358  if (itMap == m_allocationMaps.end ())
2359  {
2360  return;
2361  }
2362  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
2363  {
2364  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
2365  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
2366  itCqi = m_ueCqi.find ((*itMap).second.at (i));
2367  if (itCqi == m_ueCqi.end ())
2368  {
2369  // create a new entry
2370  std::vector <double> newCqi;
2371  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2372  {
2373  if (i == j)
2374  {
2375  newCqi.push_back (sinr);
2376  }
2377  else
2378  {
2379  // initialize with NO_SINR value.
2380  newCqi.push_back (NO_SINR);
2381  }
2382 
2383  }
2384  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
2385  // generate correspondent timer
2386  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
2387  }
2388  else
2389  {
2390  // update the value
2391  (*itCqi).second.at (i) = sinr;
2392  NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr);
2393  // update correspondent timer
2394  std::map <uint16_t, uint32_t>::iterator itTimers;
2395  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
2396  (*itTimers).second = m_cqiTimersThreshold;
2397 
2398  }
2399 
2400  }
2401  // remove obsolete info on allocation
2402  m_allocationMaps.erase (itMap);
2403  }
2404  break;
2405  case UlCqi_s::SRS:
2406  {
2407  NS_LOG_DEBUG (this << " Collect SRS CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
2408  // get the RNTI from vendor specific parameters
2409  uint16_t rnti = 0;
2410  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
2411  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
2412  {
2413  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
2414  {
2415  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
2416  rnti = vsp->GetRnti ();
2417  }
2418  }
2419  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2420  itCqi = m_ueCqi.find (rnti);
2421  if (itCqi == m_ueCqi.end ())
2422  {
2423  // create a new entry
2424  std::vector <double> newCqi;
2425  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2426  {
2427  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2428  newCqi.push_back (sinr);
2429  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
2430 
2431  }
2432  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
2433  // generate correspondent timer
2434  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
2435  }
2436  else
2437  {
2438  // update the values
2439  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2440  {
2441  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2442  (*itCqi).second.at (j) = sinr;
2443  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
2444  }
2445  // update correspondent timer
2446  std::map <uint16_t, uint32_t>::iterator itTimers;
2447  itTimers = m_ueCqiTimers.find (rnti);
2448  (*itTimers).second = m_cqiTimersThreshold;
2449 
2450  }
2451 
2452 
2453  }
2454  break;
2455  case UlCqi_s::PUCCH_1:
2456  case UlCqi_s::PUCCH_2:
2457  case UlCqi_s::PRACH:
2458  {
2459  NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
2460  }
2461  break;
2462  default:
2463  NS_FATAL_ERROR ("Unknown type of UL-CQI");
2464  }
2465  return;
2466 }
2467 
2468 void
2470 {
2471  // refresh DL CQI P01 Map
2472  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
2473  while (itP10 != m_p10CqiTimers.end ())
2474  {
2475  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2476  if ((*itP10).second == 0)
2477  {
2478  // delete correspondent entries
2479  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
2480  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
2481  NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first);
2482  m_p10CqiRxed.erase (itMap);
2483  std::map <uint16_t,uint32_t>::iterator temp = itP10;
2484  itP10++;
2485  m_p10CqiTimers.erase (temp);
2486  }
2487  else
2488  {
2489  (*itP10).second--;
2490  itP10++;
2491  }
2492  }
2493 
2494  // refresh DL CQI A30 Map
2495  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
2496  while (itA30 != m_a30CqiTimers.end ())
2497  {
2498  NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2499  if ((*itA30).second == 0)
2500  {
2501  // delete correspondent entries
2502  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
2503  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
2504  NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first);
2505  m_a30CqiRxed.erase (itMap);
2506  std::map <uint16_t,uint32_t>::iterator temp = itA30;
2507  itA30++;
2508  m_a30CqiTimers.erase (temp);
2509  }
2510  else
2511  {
2512  (*itA30).second--;
2513  itA30++;
2514  }
2515  }
2516 
2517  return;
2518 }
2519 
2520 
2521 void
2523 {
2524  // refresh UL CQI Map
2525  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
2526  while (itUl != m_ueCqiTimers.end ())
2527  {
2528  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2529  if ((*itUl).second == 0)
2530  {
2531  // delete correspondent entries
2532  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
2533  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
2534  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
2535  (*itMap).second.clear ();
2536  m_ueCqi.erase (itMap);
2537  std::map <uint16_t,uint32_t>::iterator temp = itUl;
2538  itUl++;
2539  m_ueCqiTimers.erase (temp);
2540  }
2541  else
2542  {
2543  (*itUl).second--;
2544  itUl++;
2545  }
2546  }
2547 
2548  return;
2549 }
2550 
2551 void
2552 CqaFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
2553 {
2554  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
2555  LteFlowId_t flow (rnti, lcid);
2556  it = m_rlcBufferReq.find (flow);
2557  if (it != m_rlcBufferReq.end ())
2558  {
2559  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);
2560  // Update queues: RLC tx order Status, ReTx, Tx
2561  // Update status queue
2562  if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
2563  {
2564  (*it).second.m_rlcStatusPduSize = 0;
2565  }
2566  else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
2567  {
2568  (*it).second.m_rlcRetransmissionQueueSize = 0;
2569  }
2570  else if ((*it).second.m_rlcTransmissionQueueSize > 0)
2571  {
2572  uint32_t rlcOverhead;
2573  if (lcid == 1)
2574  {
2575  // for SRB1 (using RLC AM) it's better to
2576  // overestimate RLC overhead rather than
2577  // underestimate it and risk unneeded
2578  // segmentation which increases delay
2579  rlcOverhead = 4;
2580  }
2581  else
2582  {
2583  // minimum RLC overhead due to header
2584  rlcOverhead = 2;
2585  }
2586  // update transmission queue
2587  if ((*it).second.m_rlcTransmissionQueueSize <= size - rlcOverhead)
2588  {
2589  (*it).second.m_rlcTransmissionQueueSize = 0;
2590  }
2591  else
2592  {
2593  (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
2594  }
2595  }
2596  }
2597  else
2598  {
2599  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
2600  }
2601 }
2602 
2603 void
2604 CqaFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
2605 {
2606 
2607  size = size - 2; // remove the minimum RLC overhead
2608  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
2609  if (it != m_ceBsrRxed.end ())
2610  {
2611  NS_LOG_INFO (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
2612  if ((*it).second >= size)
2613  {
2614  (*it).second -= size;
2615  }
2616  else
2617  {
2618  (*it).second = 0;
2619  }
2620  }
2621  else
2622  {
2623  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
2624  }
2625 
2626 }
2627 
2628 void
2630 {
2631  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
2633  params.m_rnti = rnti;
2634  params.m_transmissionMode = txMode;
2636 }
2637 
2638 
2639 }
double EstimateUlSinr(uint16_t rnti, uint16_t rb)
virtual void SchedDlTriggerReq(const struct SchedDlTriggerReqParameters &params)
std::vector< struct UlInfoListElement_s > m_ulInfoList
See section 4.3.1 dlDciListElement.
Definition: ff-mac-common.h:88
void DoSchedUlMacCtrlInfoReq(const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters &params)
unsigned int lastTtiBytesTransmitted
Total bytes send by eNb for this UE.
int GetRbgSize(int dlbandwidth)
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
virtual ~CqaFfMacScheduler()
Destructor.
friend class CqaSchedulerMemberSchedSapProvider
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:60
Service Access Point (SAP) offered by the eNodeB RRC instance to the Frequency Reuse algorithm instan...
Definition: lte-ffr-sap.h:132
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
virtual void SchedUlSrInfoReq(const struct SchedUlSrInfoReqParameters &params)
#define HARQ_PERIOD
Definition: lte-common.h:30
Hold a bool native type.
Definition: boolean.h:38
std::map< uint16_t, CqasFlowPerf_t > m_flowStatsDl
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
virtual void ReportUlCqiInfo(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)=0
ReportUlCqiInfo.
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
Parameters of the CSCHED_UE_CONFIG_CNF primitive.
hold variables of type string
Definition: string.h:18
Parameters of the CSCHED_UE_RELEASE_REQ primitive.
virtual bool IsDlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in DL.
virtual bool IsUlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in UL.
enum ns3::UlCqi_s::Type_e m_type
std::vector< UlDciListElement_s > UlHarqProcessesDciBuffer_t
std::vector< struct LogicalChannelConfigListElement_s > m_logicalChannelConfigList
std::vector< uint16_t > m_sinr
std::map< CQI_value, LteFlowId_t, bool(*)(uint8_t, uint8_t)> t_map_CQIToUE
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
std::vector< uint8_t > DlHarqProcessesTimer_t
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
virtual void SchedDlRlcBufferReq(const struct SchedDlRlcBufferReqParameters &params)
std::vector< uint8_t > m_mcs
Definition: ff-mac-common.h:95
std::map< uint16_t, uint32_t > m_a30CqiTimers
See section 4.3.2 ulDciListElement.
Provides the CSCHED SAP.
void DoSchedDlMacBufferReq(const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters &params)
std::vector< struct UlDciListElement_s > m_dciList
std::map< HOL_group, t_map_RBGToCQIsSorted > t_map_HOLGroupToRBGs
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:223
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
See section 4.3.10 buildRARListElement.
virtual void SetLteFfrSapProvider(LteFfrSapProvider *s)
Set the Provider part of the LteFfrSap that this Scheduler will interact with.
Parameters of the CSCHED_UE_CONFIG_UPDATE_IND primitive.
Parameters of the CSCHED_LC_RELEASE_REQ primitive.
virtual uint8_t GetTpc(uint16_t rnti)=0
GetTpc.
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
virtual void SchedDlMacBufferReq(const struct SchedDlMacBufferReqParameters &params)
std::map< uint16_t, UlHarqProcessesDciBuffer_t > m_ulHarqProcessesDciBuffer
Parameters of the SCHED_DL_TRIGGER_REQ primitive.
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
double lastAveragedThroughput
Total bytes send by eNB in last tti for this UE.
void DoSchedUlNoiseInterferenceReq(const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters &params)
void DoSchedUlTriggerReq(const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters &params)
#define MAX_LC_LIST
Definition: ff-mac-common.h:33
See section 4.3.4 logicalChannelConfigListElement.
std::vector< RlcPduList_t > DlHarqRlcPduListBuffer_t
Parameters of the SCHED_DL_MAC_BUFFER_REQ primitive.
Parameters of the SCHED_DL_PAGING_BUFFER_REQ primitive.
void DoSchedUlCqiInfoReq(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
virtual void CschedUeConfigUpdateInd(const struct CschedUeConfigUpdateIndParameters &params)=0
std::vector< struct VendorSpecificListElement_s > m_vendorSpecificList
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
std::map< uint16_t, uint8_t > m_p10CqiRxed
void DoSchedUlSrInfoReq(const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters &params)
unsigned long totalBytesTransmitted
Service Access Point (SAP) offered by the Frequency Reuse algorithm instance to the MAC Scheduler ins...
Definition: lte-ffr-sap.h:39
Parameters of the SCHED_UL_TRIGGER_REQ primitive.
Hold an unsigned integer type.
Definition: uinteger.h:46
FfMacSchedSapUser * m_schedSapUser
static uint8_t TxMode2LayerNum(uint8_t txMode)
Definition: lte-common.cc:170
Ptr< SampleEmitter > s
FfMacCschedSapUser * m_cschedSapUser
friend class CqaSchedulerMemberCschedSapProvider
std::map< uint16_t, DlHarqProcessesTimer_t > m_dlHarqProcessesTimer
std::vector< uint8_t > m_ndi
Definition: ff-mac-common.h:96
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
Provides the SCHED SAP.
LteFfrSapProvider * m_ffrSapProvider
virtual void SchedUlCqiInfoReq(const struct SchedUlCqiInfoReqParameters &params)
virtual void CschedUeConfigCnf(const struct CschedUeConfigCnfParameters &params)=0
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
Parameters of the SCHED_UL_NOISE_INTERFERENCE_REQ primitive.
std::vector< struct CqiListElement_s > m_cqiList
std::vector< struct DlInfoListElement_s > m_dlInfoList
virtual void ReportDlCqiInfo(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)=0
ReportDlCqiInfo.
std::map< uint16_t, DlHarqRlcPduListBuffer_t > m_dlHarqProcessesRlcPduListBuffer
virtual void SchedDlCqiInfoReq(const struct SchedDlCqiInfoReqParameters &params)
virtual void SchedDlConfigInd(const struct SchedDlConfigIndParameters &params)=0
bool CQIValueDescComparator(uint8_t key1, uint8_t key2)
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
set the user part of the FfMacCschedSap that this Scheduler will interact with.
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
std::map< CQI_value, LteFlowId_t, bool(*)(uint8_t, uint8_t)>::iterator t_it_CQIToUE
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
std::vector< uint16_t > m_tbsSize
Definition: ff-mac-common.h:94
virtual void CschedCellConfigReq(const struct CschedCellConfigReqParameters &params)
CSCHED_CELL_CONFIG_REQ.
See section 4.3.9 rlcPDU_ListElement.
std::vector< uint16_t > m_rachAllocationMap
std::map< uint16_t, uint32_t > m_ceBsrRxed
std::vector< DlDciListElement_s > DlHarqProcessesDciBuffer_t
FfMacSchedSapProvider * m_schedSapProvider
Parameters of the CSCHED_LC_CONFIG_REQ primitive.
uint8_t CQI_value
std::map< uint16_t, std::vector< double > > m_ueCqi
std::map< uint16_t, UlHarqProcessesStatus_t > m_ulHarqProcessesStatus
std::vector< uint8_t > m_rv
Definition: ff-mac-common.h:97
std::map< uint16_t, CqasFlowPerf_t > m_flowStatsUl
virtual std::vector< bool > GetAvailableUlRbg()=0
Get vector of available RB in UL for this Cell.
virtual uint8_t GetMinContinuousUlBandwidth()=0
GetMinContinuousUlBandwidth.
virtual void SchedUlConfigInd(const struct SchedUlConfigIndParameters &params)=0
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
virtual void SchedUlNoiseInterferenceReq(const struct SchedUlNoiseInterferenceReqParameters &params)
UlCqiFilter_t m_ulCqiFilter
#define SRS_CQI_RNTI_VSP
This abstract base class identifies the interface by means of which the helper object can plug on the...
virtual void CschedUeConfigReq(const struct CschedUeConfigReqParameters &params)
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:84
bool m_harqOn
m_harqOn when false inhibit te HARQ mechanisms (by default active)
virtual void CschedUeReleaseReq(const struct CschedUeReleaseReqParameters &params)
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct MacCeListElement_s > m_macCeList
std::vector< struct RachListElement_s > m_rachList
std::map< RBG_index, t_map_CQIToUE > t_map_RBGToCQIsSorted
static double fpS11dot3toDouble(uint16_t val)
Definition: lte-common.cc:114
virtual void CschedLcReleaseReq(const struct CschedLcReleaseReqParameters &params)
static TypeId GetTypeId(void)
bool CqaKeyDescComparator(uint16_t key1, uint16_t key2)
std::map< LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters > m_rlcBufferReq
std::vector< uint8_t > UlHarqProcessesStatus_t
virtual void SchedUlTriggerReq(const struct SchedUlTriggerReqParameters &params)
std::map< uint16_t, std::vector< uint16_t > > m_allocationMaps
void DoSchedDlCqiInfoReq(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
std::vector< uint8_t > DlHarqProcessesStatus_t
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
static uint32_t BsrId2BufferSize(uint8_t val)
Definition: lte-common.cc:142
void DoCschedCellConfigReq(const struct FfMacCschedSapProvider::CschedCellConfigReqParameters &params)
std::map< uint16_t, SbMeasResult_s > m_a30CqiRxed
void DoCschedUeConfigReq(const struct FfMacCschedSapProvider::CschedUeConfigReqParameters &params)
Template for the implementation of the LteFfrSapUser as a member of an owner class of type C to which...
Definition: lte-ffr-sap.h:244
double secondLastAveragedThroughput
Past average throughput.
Parameters of the SCHED_UL_MAC_CTRL_INFO_REQ primitive.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:213
virtual std::vector< bool > GetAvailableDlRbg()=0
Get vector of available RBG in DL for this Cell.
FfMacCschedSapProvider * m_cschedSapProvider
uint8_t m_lcId
Definition: lte-common.h:38
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
set the user part of the FfMacSchedSap that this Scheduler will interact with.
int LcActivePerFlow(uint16_t rnti)
std::map< LteFlowId_t, struct LogicalChannelConfigListElement_s > m_ueLogicalChannelsConfigList
virtual void SchedUlMacCtrlInfoReq(const struct SchedUlMacCtrlInfoReqParameters &params)
Parameters of the SCHED_UL_SR_INFO_REQ primitive.
void DoSchedDlRlcBufferReq(const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
void DoCschedLcConfigReq(const struct FfMacCschedSapProvider::CschedLcConfigReqParameters &params)
virtual LteFfrSapUser * GetLteFfrSapUser()
void DoCschedLcReleaseReq(const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters &params)
std::map< uint16_t, DlHarqProcessesDciBuffer_t > m_dlHarqProcessesDciBuffer
void UpdateDlRlcBufferInfo(uint16_t rnti, uint8_t lcid, uint16_t size)
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:193
std::map< uint16_t, uint8_t > m_dlHarqCurrentProcessId
Parameters of the SCHED_DL_RACH_INFO_REQ primitive.
void TransmissionModeConfigurationUpdate(uint16_t rnti, uint8_t txMode)
std::multimap< HOL_group, std::set< LteFlowId_t >, bool(*)(int, int)> t_map_HOLgroupToUEs
Parameters of the SCHED_UL_CONFIG_IND primitive.
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
std::vector< struct RachListElement_s > m_rachList
std::map< HOL_group, t_map_RBGToCQIsSorted >::iterator t_it_HOLGroupToRBGs
Parameters of the CSCHED_UE_CONFIG_REQ primitive.
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
virtual void SchedDlRachInfoReq(const struct SchedDlRachInfoReqParameters &params)
virtual void CschedLcConfigReq(const struct CschedLcConfigReqParameters &params)
#define HARQ_DL_TIMEOUT
std::map< uint16_t, uint32_t > m_ueCqiTimers
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
std::map< uint16_t, uint32_t > m_p10CqiTimers
#define NO_SINR
static const int CqaType0AllocationRbg[4]
struct DlDciListElement_s m_dci
std::vector< struct BuildRarListElement_s > m_buildRarList
bool CqaGroupDescComparator(int key1, int key2)
a unique identifier for an interface.
Definition: type-id.h:49
std::map< HOL_group, std::set< LteFlowId_t > >::iterator t_it_HOLgroupToUEs
Implements the SCHED SAP and CSCHED SAP for the Channel and QoS Aware Scheduler.
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
#define HARQ_PROC_NUM
std::map< uint16_t, uint8_t > m_uesTxMode
uint16_t m_rnti
Definition: lte-common.h:37
virtual void SchedDlPagingBufferReq(const struct SchedDlPagingBufferReqParameters &params)
std::map< RBG_index, t_map_CQIToUE >::iterator t_it_RBGToCQIsSorted
std::vector< struct BuildDataListElement_s > m_buildDataList
See section 4.3.8 builDataListElement.