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->GetUlTbSizeFromMcs (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->GetUlTbSizeFromMcs (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->GetDlTbSizeFromMcs (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->GetDlTbSizeFromMcs (mcsForThisUser, rbgSize)/ 8) / 0.001);
1406  double pf_weight = achievableRate / (*itStats).second.secondLastAveragedThroughput;
1407 
1408  UeToAmountOfAssignedResources.find (flowId)->second = 8*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->GetDlTbSizeFromMcs (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 -> ignored 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  NS_ABORT_MSG_IF ((*itCqi).second.size() == 0, "CQI of RNTI = " << (*it).first << " has expired");
2055  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
2056  if (minSinr == NO_SINR)
2057  {
2058  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
2059  }
2060  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
2061  {
2062  double sinr = (*itCqi).second.at (i);
2063  if (sinr == NO_SINR)
2064  {
2065  sinr = EstimateUlSinr ((*it).first, i);
2066  }
2067  if (sinr < minSinr)
2068  {
2069  minSinr = sinr;
2070  }
2071  }
2072 
2073  // translate SINR -> cqi: WILD ACK: same as DL
2074  double s = log2 ( 1 + (
2075  std::pow (10, minSinr / 10 ) /
2076  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
2077  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
2078  if (cqi == 0)
2079  {
2080  it++;
2081  if (it == m_ceBsrRxed.end ())
2082  {
2083  // restart from the first
2084  it = m_ceBsrRxed.begin ();
2085  }
2086  NS_LOG_DEBUG (this << " UE discarded for CQI = 0, RNTI " << uldci.m_rnti);
2087  // remove UE from allocation map
2088  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
2089  {
2090  rbgAllocationMap.at (i) = 0;
2091  }
2092  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
2093  }
2094  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
2095  }
2096 
2097  uldci.m_tbSize = (m_amc->GetUlTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
2098  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
2099  uldci.m_ndi = 1;
2100  uldci.m_cceIndex = 0;
2101  uldci.m_aggrLevel = 1;
2102  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
2103  uldci.m_hopping = false;
2104  uldci.m_n2Dmrs = 0;
2105  uldci.m_tpc = 0; // no power control
2106  uldci.m_cqiRequest = false; // only period CQI at this stage
2107  uldci.m_ulIndex = 0; // TDD parameter
2108  uldci.m_dai = 1; // TDD parameter
2109  uldci.m_freqHopping = 0;
2110  uldci.m_pdcchPowerOffset = 0; // not used
2111  ret.m_dciList.push_back (uldci);
2112  // store DCI for HARQ_PERIOD
2113  uint8_t harqId = 0;
2114  if (m_harqOn == true)
2115  {
2116  std::map <uint16_t, uint8_t>::iterator itProcId;
2117  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
2118  if (itProcId == m_ulHarqCurrentProcessId.end ())
2119  {
2120  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
2121  }
2122  harqId = (*itProcId).second;
2123  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
2124  if (itDci == m_ulHarqProcessesDciBuffer.end ())
2125  {
2126  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
2127  }
2128  (*itDci).second.at (harqId) = uldci;
2129  // Update HARQ process status (RV 0)
2130  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (uldci.m_rnti);
2131  if (itStat == m_ulHarqProcessesStatus.end ())
2132  {
2133  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << uldci.m_rnti);
2134  }
2135  (*itStat).second.at (harqId) = 0;
2136  }
2137 
2138  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);
2139 
2140  // update TTI UE stats
2141  itStats = m_flowStatsUl.find ((*it).first);
2142  if (itStats != m_flowStatsUl.end ())
2143  {
2144  (*itStats).second.lastTtiBytesTransmitted = uldci.m_tbSize;
2145  }
2146  else
2147  {
2148  NS_LOG_DEBUG (this << " No Stats for this allocated UE");
2149  }
2150 
2151 
2152  it++;
2153  if (it == m_ceBsrRxed.end ())
2154  {
2155  // restart from the first
2156  it = m_ceBsrRxed.begin ();
2157  }
2158  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
2159  {
2160  // Stop allocation: no more PRBs
2161  m_nextRntiUl = (*it).first;
2162  break;
2163  }
2164  }
2165  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
2166 
2167 
2168  // Update global UE stats
2169  // update UEs stats
2170  for (itStats = m_flowStatsUl.begin (); itStats != m_flowStatsUl.end (); itStats++)
2171  {
2172  (*itStats).second.totalBytesTransmitted += (*itStats).second.lastTtiBytesTransmitted;
2173  // update average throughput (see eq. 12.3 of Sec 12.3.1.2 of LTE – The UMTS Long Term Evolution, Ed Wiley)
2174  (*itStats).second.lastAveragedThroughput = ((1.0 - (1.0 / m_timeWindow)) * (*itStats).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTransmitted / 0.001));
2175  NS_LOG_INFO (this << " UE total bytes " << (*itStats).second.totalBytesTransmitted);
2176  NS_LOG_INFO (this << " UE average throughput " << (*itStats).second.lastAveragedThroughput);
2177  (*itStats).second.lastTtiBytesTransmitted = 0;
2178  }
2179  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
2181 
2182  return;
2183 }
2184 
2185 void
2187 {
2188  NS_LOG_FUNCTION (this);
2189  return;
2190 }
2191 
2192 void
2194 {
2195  NS_LOG_FUNCTION (this);
2196  return;
2197 }
2198 
2199 void
2201 {
2202  NS_LOG_FUNCTION (this);
2203 
2204  std::map <uint16_t,uint32_t>::iterator it;
2205 
2206  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
2207  {
2208  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
2209  {
2210  // buffer status report
2211  // note that this scheduler does not differentiate the
2212  // allocation according to which LCGs have more/less bytes
2213  // to send.
2214  // Hence the BSR of different LCGs are just summed up to get
2215  // a total queue size that is used for allocation purposes.
2216 
2217  uint32_t buffer = 0;
2218  for (uint8_t lcg = 0; lcg < 4; ++lcg)
2219  {
2220  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
2221  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
2222  }
2223 
2224  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
2225  NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
2226  it = m_ceBsrRxed.find (rnti);
2227  if (it == m_ceBsrRxed.end ())
2228  {
2229  // create the new entry
2230  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
2231  }
2232  else
2233  {
2234  // update the buffer size value
2235  (*it).second = buffer;
2236  }
2237  }
2238  }
2239 
2240  return;
2241 }
2242 
2243 void
2245 {
2246  NS_LOG_FUNCTION (this);
2247 // retrieve the allocation for this subframe
2248  switch (m_ulCqiFilter)
2249  {
2251  {
2252  // filter all the CQIs that are not SRS based
2253  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
2254  {
2255  return;
2256  }
2257  }
2258  break;
2260  {
2261  // filter all the CQIs that are not SRS based
2262  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
2263  {
2264  return;
2265  }
2266  }
2267  break;
2268  default:
2269  NS_FATAL_ERROR ("Unknown UL CQI type");
2270  }
2271 
2272  switch (params.m_ulCqi.m_type)
2273  {
2274  case UlCqi_s::PUSCH:
2275  {
2276  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
2277  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2278  NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
2279  itMap = m_allocationMaps.find (params.m_sfnSf);
2280  if (itMap == m_allocationMaps.end ())
2281  {
2282  return;
2283  }
2284  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
2285  {
2286  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
2287  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
2288  itCqi = m_ueCqi.find ((*itMap).second.at (i));
2289  if (itCqi == m_ueCqi.end ())
2290  {
2291  // create a new entry
2292  std::vector <double> newCqi;
2293  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2294  {
2295  if (i == j)
2296  {
2297  newCqi.push_back (sinr);
2298  }
2299  else
2300  {
2301  // initialize with NO_SINR value.
2302  newCqi.push_back (NO_SINR);
2303  }
2304 
2305  }
2306  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
2307  // generate correspondent timer
2308  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
2309  }
2310  else
2311  {
2312  // update the value
2313  (*itCqi).second.at (i) = sinr;
2314  NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr);
2315  // update correspondent timer
2316  std::map <uint16_t, uint32_t>::iterator itTimers;
2317  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
2318  (*itTimers).second = m_cqiTimersThreshold;
2319 
2320  }
2321 
2322  }
2323  // remove obsolete info on allocation
2324  m_allocationMaps.erase (itMap);
2325  }
2326  break;
2327  case UlCqi_s::SRS:
2328  {
2329  NS_LOG_DEBUG (this << " Collect SRS CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
2330  // get the RNTI from vendor specific parameters
2331  uint16_t rnti = 0;
2332  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
2333  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
2334  {
2335  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
2336  {
2337  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
2338  rnti = vsp->GetRnti ();
2339  }
2340  }
2341  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2342  itCqi = m_ueCqi.find (rnti);
2343  if (itCqi == m_ueCqi.end ())
2344  {
2345  // create a new entry
2346  std::vector <double> newCqi;
2347  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2348  {
2349  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2350  newCqi.push_back (sinr);
2351  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
2352 
2353  }
2354  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
2355  // generate correspondent timer
2356  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
2357  }
2358  else
2359  {
2360  // update the values
2361  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2362  {
2363  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2364  (*itCqi).second.at (j) = sinr;
2365  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
2366  }
2367  // update correspondent timer
2368  std::map <uint16_t, uint32_t>::iterator itTimers;
2369  itTimers = m_ueCqiTimers.find (rnti);
2370  (*itTimers).second = m_cqiTimersThreshold;
2371 
2372  }
2373 
2374 
2375  }
2376  break;
2377  case UlCqi_s::PUCCH_1:
2378  case UlCqi_s::PUCCH_2:
2379  case UlCqi_s::PRACH:
2380  {
2381  NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
2382  }
2383  break;
2384  default:
2385  NS_FATAL_ERROR ("Unknown type of UL-CQI");
2386  }
2387  return;
2388 }
2389 
2390 void
2392 {
2393  // refresh DL CQI P01 Map
2394  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
2395  while (itP10 != m_p10CqiTimers.end ())
2396  {
2397  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2398  if ((*itP10).second == 0)
2399  {
2400  // delete correspondent entries
2401  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
2402  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
2403  NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first);
2404  m_p10CqiRxed.erase (itMap);
2405  std::map <uint16_t,uint32_t>::iterator temp = itP10;
2406  itP10++;
2407  m_p10CqiTimers.erase (temp);
2408  }
2409  else
2410  {
2411  (*itP10).second--;
2412  itP10++;
2413  }
2414  }
2415 
2416  // refresh DL CQI A30 Map
2417  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
2418  while (itA30 != m_a30CqiTimers.end ())
2419  {
2420  NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2421  if ((*itA30).second == 0)
2422  {
2423  // delete correspondent entries
2424  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
2425  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
2426  NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first);
2427  m_a30CqiRxed.erase (itMap);
2428  std::map <uint16_t,uint32_t>::iterator temp = itA30;
2429  itA30++;
2430  m_a30CqiTimers.erase (temp);
2431  }
2432  else
2433  {
2434  (*itA30).second--;
2435  itA30++;
2436  }
2437  }
2438 
2439  return;
2440 }
2441 
2442 
2443 void
2445 {
2446  // refresh UL CQI Map
2447  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
2448  while (itUl != m_ueCqiTimers.end ())
2449  {
2450  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2451  if ((*itUl).second == 0)
2452  {
2453  // delete correspondent entries
2454  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
2455  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
2456  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
2457  (*itMap).second.clear ();
2458  m_ueCqi.erase (itMap);
2459  std::map <uint16_t,uint32_t>::iterator temp = itUl;
2460  itUl++;
2461  m_ueCqiTimers.erase (temp);
2462  }
2463  else
2464  {
2465  (*itUl).second--;
2466  itUl++;
2467  }
2468  }
2469 
2470  return;
2471 }
2472 
2473 void
2474 CqaFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
2475 {
2476  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
2477  LteFlowId_t flow (rnti, lcid);
2478  it = m_rlcBufferReq.find (flow);
2479  if (it != m_rlcBufferReq.end ())
2480  {
2481  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);
2482  // Update queues: RLC tx order Status, ReTx, Tx
2483  // Update status queue
2484  if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
2485  {
2486  (*it).second.m_rlcStatusPduSize = 0;
2487  }
2488  else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
2489  {
2490  (*it).second.m_rlcRetransmissionQueueSize = 0;
2491  }
2492  else if ((*it).second.m_rlcTransmissionQueueSize > 0)
2493  {
2494  uint32_t rlcOverhead;
2495  if (lcid == 1)
2496  {
2497  // for SRB1 (using RLC AM) it's better to
2498  // overestimate RLC overhead rather than
2499  // underestimate it and risk unneeded
2500  // segmentation which increases delay
2501  rlcOverhead = 4;
2502  }
2503  else
2504  {
2505  // minimum RLC overhead due to header
2506  rlcOverhead = 2;
2507  }
2508  // update transmission queue
2509  if ((*it).second.m_rlcTransmissionQueueSize <= size - rlcOverhead)
2510  {
2511  (*it).second.m_rlcTransmissionQueueSize = 0;
2512  }
2513  else
2514  {
2515  (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
2516  }
2517  }
2518  }
2519  else
2520  {
2521  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
2522  }
2523 }
2524 
2525 void
2526 CqaFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
2527 {
2528 
2529  size = size - 2; // remove the minimum RLC overhead
2530  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
2531  if (it != m_ceBsrRxed.end ())
2532  {
2533  NS_LOG_INFO (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
2534  if ((*it).second >= size)
2535  {
2536  (*it).second -= size;
2537  }
2538  else
2539  {
2540  (*it).second = 0;
2541  }
2542  }
2543  else
2544  {
2545  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
2546  }
2547 
2548 }
2549 
2550 void
2552 {
2553  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
2555  params.m_rnti = rnti;
2556  params.m_transmissionMode = txMode;
2558 }
2559 
2560 
2561 }
AttributeValue implementation for Boolean.
Definition: boolean.h:37
static uint32_t BsrId2BufferSize(uint8_t val)
Convert BSR ID to buffer size.
Definition: lte-common.cc:184
Implements the SCHED SAP and CSCHED SAP for the Channel and QoS Aware Scheduler.
std::map< uint16_t, DlHarqRlcPduListBuffer_t > m_dlHarqProcessesRlcPduListBuffer
DL HARQ process RLC PDU list buffer.
FfMacCschedSapProvider * m_cschedSapProvider
Csched SAP provider.
std::map< uint16_t, uint8_t > m_p10CqiRxed
Map of UE's DL CQI P01 received.
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
void DoSchedUlSrInfoReq(const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters &params)
Sched UL Sr Info Request.
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
int GetRbgSize(int dlbandwidth)
Get RGB Size.
std::map< uint16_t, CqasFlowPerf_t > m_flowStatsDl
Map of UE statistics (per RNTI basis) in downlink.
std::map< uint16_t, uint8_t > m_dlHarqCurrentProcessId
DL HARQ process ID.
std::map< uint16_t, std::vector< double > > m_ueCqi
Map of UEs' UL-CQI per RBG.
static TypeId GetTypeId(void)
Get the type ID.
void DoCschedCellConfigReq(const struct FfMacCschedSapProvider::CschedCellConfigReqParameters &params)
Csched Cell Config Request.
std::map< uint16_t, DlHarqProcessesTimer_t > m_dlHarqProcessesTimer
DL HARQ process timers.
double m_timeWindow
time window
std::map< LteFlowId_t, struct LogicalChannelConfigListElement_s > m_ueLogicalChannelsConfigList
Map of UE logical channel config list.
void RefreshDlCqiMaps(void)
Refresh DL CGI maps.
std::map< uint16_t, uint32_t > m_ueCqiTimers
Map of UEs' timers on UL-CQI per RBG.
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
set the user part of the FfMacSchedSap that this Scheduler will interact with.
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
Sched DL RLC Buffer Request.
std::map< uint16_t, std::vector< uint16_t > > m_allocationMaps
Map of previous allocated UE per RBG (used to retrieve info from UL-CQI)
std::map< uint16_t, uint32_t > m_p10CqiTimers
Map of UE's timers on DL CQI P01 received.
unsigned int LcActivePerFlow(uint16_t rnti)
LC Active per flow.
FfMacSchedSapUser * m_schedSapUser
MAC Sched SAP user.
void UpdateDlRlcBufferInfo(uint16_t rnti, uint8_t lcid, uint16_t size)
Update DL RLC buffer info.
LteFfrSapProvider * m_ffrSapProvider
FFR SAP provider.
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
void DoSchedUlNoiseInterferenceReq(const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters &params)
Sched UL Noise InterferenceRequest.
std::map< uint16_t, DlHarqProcessesDciBuffer_t > m_dlHarqProcessesDciBuffer
DL HARQ process DCI buffer.
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
UL HARQ current process ID.
friend class MemberSchedSapProvider< CqaFfMacScheduler >
allow MemberSchedSapProvider<CqaFfMacScheduler> class friend access
virtual ~CqaFfMacScheduler()
Destructor.
void DoSchedDlCqiInfoReq(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
Sched DL CGI Info Request.
FfMacCschedSapUser * m_cschedSapUser
MAC Csched SAP user.
std::map< uint16_t, SbMeasResult_s > m_a30CqiRxed
Map of UE's DL CQI A30 received.
LteFfrSapUser * m_ffrSapUser
FFR SAP user.
void DoCschedLcConfigReq(const struct FfMacCschedSapProvider::CschedLcConfigReqParameters &params)
Csched LC Config Request.
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
Update UL RLC buffer info.
virtual void SetLteFfrSapProvider(LteFfrSapProvider *s)
Set the Provider part of the LteFfrSap that this Scheduler will interact with.
std::map< uint16_t, UlHarqProcessesStatus_t > m_ulHarqProcessesStatus
UL HARQ process status.
uint8_t m_ulGrantMcs
MCS for UL grant (default 0)
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
Sched DL RACH Info Request.
std::vector< uint16_t > m_rachAllocationMap
RACH allocation map.
void DoCschedUeConfigReq(const struct FfMacCschedSapProvider::CschedUeConfigReqParameters &params)
Csched UE Config Request.
std::vector< struct RachListElement_s > m_rachList
RACH list.
void DoSchedUlTriggerReq(const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters &params)
Sched UL Trigger Request.
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
Sched DL Paging Buffer Request.
void DoSchedUlCqiInfoReq(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
Sched UL CGI Info Request.
std::map< uint16_t, UlHarqProcessesDciBuffer_t > m_ulHarqProcessesDciBuffer
UL HARQ process DCI buffer.
Ptr< LteAmc > m_amc
LTE AMC object.
void DoSchedDlMacBufferReq(const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters &params)
Sched DL MAC Buffer Request.
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
DL HARQ retx buffered.
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
Csched UE Release Request.
std::map< uint16_t, CqasFlowPerf_t > m_flowStatsUl
Map of UE statistics (per RNTI basis)
std::map< uint16_t, uint32_t > m_a30CqiTimers
Map of UE's timers on DL CQI A30 received.
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
set the user part of the FfMacCschedSap that this Scheduler will interact with.
FfMacSchedSapProvider * m_schedSapProvider
Sched SAP provider.
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
std::map< uint16_t, uint8_t > m_uesTxMode
txMode of the UEs
void DoSchedUlMacCtrlInfoReq(const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters &params)
Sched UL MAC Control Info Request.
friend class MemberCschedSapProvider< CqaFfMacScheduler >
allow MemberCschedSapProvider<CqaFfMacScheduler> class friend access
double EstimateUlSinr(uint16_t rnti, uint16_t rb)
Estimate UL Sinr.
void RefreshUlCqiMaps(void)
Refresh UL CGI maps.
virtual LteFfrSapUser * GetLteFfrSapUser()
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
Internal parameters.
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
DL HARQ process statuses.
uint16_t m_nextRntiUl
RNTI of the next user to be served next scheduling in UL.
std::map< uint16_t, uint32_t > m_ceBsrRxed
Map of UE's buffer status reports received.
void DoSchedDlRlcBufferReq(const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
Sched DL RLC Buffer Request.
std::map< LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters > m_rlcBufferReq
Vectors of UE's LC info.
std::string m_CqaMetric
CQA metric name.
virtual void DoDispose(void)
Destructor implementation.
void DoCschedLcReleaseReq(const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters &params)
Csched LC Release Request.
bool m_harqOn
m_harqOn when false inhibit the HARQ mechanisms (by default active)
void TransmissionModeConfigurationUpdate(uint16_t rnti, uint8_t txMode)
Trans mode config update.
Provides the CSCHED SAP.
FfMacCschedSapUser class.
virtual void CschedUeConfigUpdateInd(const struct CschedUeConfigUpdateIndParameters &params)=0
CSCHED_UE_UPDATE_IND.
virtual void CschedUeConfigCnf(const struct CschedUeConfigCnfParameters &params)=0
CSCHED_UE_CONFIG_CNF.
Provides the SCHED SAP.
FfMacSchedSapUser class.
virtual void SchedUlConfigInd(const struct SchedUlConfigIndParameters &params)=0
SCHED_UL_CONFIG_IND.
virtual void SchedDlConfigInd(const struct SchedDlConfigIndParameters &params)=0
SCHED_DL_CONFIG_IND.
This abstract base class identifies the interface by means of which the helper object can plug on the...
UlCqiFilter_t m_ulCqiFilter
UL CQI filter.
static double fpS11dot3toDouble(uint16_t val)
Convert from fixed point S11.3 notation to double.
Definition: lte-common.cc:155
Service Access Point (SAP) offered by the Frequency Reuse algorithm instance to the MAC Scheduler ins...
Definition: lte-ffr-sap.h:40
virtual uint8_t GetTpc(uint16_t rnti)=0
GetTpc.
virtual void ReportUlCqiInfo(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)=0
ReportUlCqiInfo.
virtual bool IsUlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in UL.
virtual uint16_t GetMinContinuousUlBandwidth()=0
Get the minimum continuous Ul bandwidth.
virtual bool IsDlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in DL.
virtual void ReportDlCqiInfo(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)=0
ReportDlCqiInfo.
virtual std::vector< bool > GetAvailableUlRbg()=0
Get vector of available RB in UL for this Cell.
virtual std::vector< bool > GetAvailableDlRbg()=0
Get vector of available RBG in DL for this Cell.
Service Access Point (SAP) offered by the eNodeB RRC instance to the Frequency Reuse algorithm instan...
Definition: lte-ffr-sap.h:139
Template for the implementation of the LteFfrSapUser as a member of an owner class of type C to which...
Definition: lte-ffr-sap.h:256
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Hold variables of type string.
Definition: string.h:41
static uint8_t TxMode2LayerNum(uint8_t txMode)
Transmit mode 2 layer number.
Definition: lte-common.cc:212
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NO_SINR
#define HARQ_PROC_NUM
#define HARQ_DL_TIMEOUT
#define MAX_LC_LIST
Definition: ff-mac-common.h:33
#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_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:88
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
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:85
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
Ptr< const AttributeChecker > MakeStringChecker(void)
Definition: string.cc:30
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
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
#define HARQ_PERIOD
Definition: lte-common.h:30
#define SRS_CQI_RNTI_VSP
Every class exported by the ns3 library is enclosed in the ns3 namespace.
int RBG_index
RBG index typedef.
std::vector< UlDciListElement_s > UlHarqProcessesDciBuffer_t
UL HARQ process DCI buffer vector.
bool CqaKeyDescComparator(uint16_t key1, uint16_t key2)
CQA key comparator.
std::map< CQI_value, LteFlowId_t, bool(*)(uint8_t, uint8_t)>::iterator t_it_CQIToUE
CQI value map iterator typedef.
std::map< HOL_group, t_map_RBGToCQIsSorted > t_map_HOLGroupToRBGs
HOL group map typedef.
std::vector< uint8_t > DlHarqProcessesTimer_t
DL HARQ process timer vector typedef.
int HOL_group
HOL group typedef.
std::vector< uint8_t > DlHarqProcessesStatus_t
DL HARQ process status vector typedef.
std::vector< RlcPduList_t > DlHarqRlcPduListBuffer_t
vector of the 8 HARQ processes per UE
bool CQIValueDescComparator(uint8_t key1, uint8_t key2)
CQI value comparator function.
@ SUCCESS
Definition: ff-mac-common.h:62
std::map< HOL_group, t_map_RBGToCQIsSorted >::iterator t_it_HOLGroupToRBGs
HOL group map iterator typedef.
std::map< RBG_index, t_map_CQIToUE >::iterator t_it_RBGToCQIsSorted
RBG index map iterator typedef.
std::map< CQI_value, LteFlowId_t, bool(*)(uint8_t, uint8_t)> t_map_CQIToUE
CQI value map typedef.
std::multimap< HOL_group, std::set< LteFlowId_t >, bool(*)(int, int)> t_map_HOLgroupToUEs
HOL group map typedef.
static const int CqaType0AllocationRbg[4]
CGA Type 0 Allocation.
uint8_t CQI_value
CQI value typedef.
std::map< RBG_index, t_map_CQIToUE > t_map_RBGToCQIsSorted
RBG index map typedef.
std::vector< DlDciListElement_s > DlHarqProcessesDciBuffer_t
DL HARQ process DCI buffer vector typedef.
std::vector< uint8_t > UlHarqProcessesStatus_t
UL HARQ process status vector.
bool CqaGroupDescComparator(int key1, int key2)
CGA group comparator function.
std::map< HOL_group, std::set< LteFlowId_t > >::iterator t_it_HOLgroupToUEs
HOL group multi map iterator typedef.
See section 4.3.8 builDataListElement.
struct DlDciListElement_s m_dci
DCI.
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
RLC PDU list.
See section 4.3.10 buildRARListElement.
CGA Flow Performance structure.
double lastAveragedThroughput
Past average throughput.
double secondLastAveragedThroughput
Second last average throughput.
double targetThroughput
Target throughput.
Time flowStart
flow start time
unsigned int lastTtiBytesTransmitted
Total bytes send by eNB in last tti for this UE.
unsigned long totalBytesTransmitted
Total bytes send by eNb for this UE.
See section 4.3.1 dlDciListElement.
Definition: ff-mac-common.h:94
std::vector< uint8_t > m_ndi
New data indicator.
uint8_t m_harqProcess
HARQ process.
uint32_t m_rbBitmap
RB bitmap.
Definition: ff-mac-common.h:96
std::vector< uint8_t > m_mcs
MCS.
uint8_t m_resAlloc
The type of resource allocation.
Definition: ff-mac-common.h:98
std::vector< uint16_t > m_tbsSize
The TBs size.
Definition: ff-mac-common.h:99
std::vector< uint8_t > m_rv
Redundancy version.
uint8_t m_tpc
Tx power control command.
Parameters of the CSCHED_LC_CONFIG_REQ primitive.
std::vector< struct LogicalChannelConfigListElement_s > m_logicalChannelConfigList
logicalChannelConfigList
Parameters of the CSCHED_LC_RELEASE_REQ primitive.
std::vector< uint8_t > m_logicalChannelIdentity
logical channel identity
Parameters of the CSCHED_UE_CONFIG_REQ primitive.
Parameters of the CSCHED_UE_RELEASE_REQ primitive.
Parameters of the CSCHED_UE_CONFIG_CNF primitive.
Parameters of the CSCHED_UE_CONFIG_UPDATE_IND primitive.
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct CqiListElement_s > m_cqiList
CQI list.
Parameters of the SCHED_DL_MAC_BUFFER_REQ primitive.
Parameters of the SCHED_DL_PAGING_BUFFER_REQ primitive.
Parameters of the SCHED_DL_RACH_INFO_REQ primitive.
std::vector< struct RachListElement_s > m_rachList
RACH list.
Parameters of the SCHED_DL_TRIGGER_REQ primitive.
std::vector< struct DlInfoListElement_s > m_dlInfoList
DL info list.
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
std::vector< struct VendorSpecificListElement_s > m_vendorSpecificList
vendor specific list
Parameters of the SCHED_UL_MAC_CTRL_INFO_REQ primitive.
std::vector< struct MacCeListElement_s > m_macCeList
MAC CE list.
Parameters of the SCHED_UL_NOISE_INTERFERENCE_REQ primitive.
Parameters of the SCHED_UL_SR_INFO_REQ primitive.
Parameters of the SCHED_UL_TRIGGER_REQ primitive.
std::vector< struct UlInfoListElement_s > m_ulInfoList
UL info list.
uint8_t m_nrOfPdcchOfdmSymbols
number of PDCCH OFDM symbols
std::vector< struct BuildDataListElement_s > m_buildDataList
build data list
std::vector< struct BuildRarListElement_s > m_buildRarList
build rar list
Parameters of the SCHED_UL_CONFIG_IND primitive.
std::vector< struct UlDciListElement_s > m_dciList
DCI list.
See section 4.3.4 logicalChannelConfigListElement.
uint64_t m_eRabGuaranteedBitrateDl
ERAB guaranteed bit rate DL.
LteFlowId structure.
Definition: lte-common.h:37
uint8_t m_lcId
LCID.
Definition: lte-common.h:39
uint16_t m_rnti
RNTI.
Definition: lte-common.h:38
See section 4.3.9 rlcPDU_ListElement.
uint8_t m_logicalChannelIdentity
logical channel identity
std::vector< uint16_t > m_sinr
SINR.
See section 4.3.2 ulDciListElement.
int8_t m_pdcchPowerOffset
CCH power offset.
int8_t m_tpc
Tx power control command.
uint8_t m_dai
DL assignment index.
uint8_t m_cceIndex
Control Channel Element index.
uint8_t m_ulIndex
UL index.
uint8_t m_ueTxAntennaSelection
UE antenna selection.
bool m_cqiRequest
CQI request.
uint8_t m_n2Dmrs
n2 DMRS
uint8_t m_freqHopping
freq hopping
uint8_t m_aggrLevel
The aggregation level.
bool m_ulDelay
UL delay?
int8_t m_tpc
Tx power control command.
bool m_cqiRequest
CQI request?
bool m_hopping
hopping?
uint16_t m_tbSize
size
uint8_t m_rbLen
length
uint8_t m_mcs
MCS.
uint8_t m_rbStart
start
uint16_t m_rnti
RNTI.
qos_rb_and_CQI_assigned_to_lc
uint8_t cqi_value_for_lc
CQI indicator value.
uint16_t resource_block_index
Resource block indexHOL_GROUP_index.