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