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