A Discrete-Event Network Simulator
API
rr-ff-mac-scheduler.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Marco Miozzo <marco.miozzo@cttc.es>
19  */
20 
21 #include <ns3/log.h>
22 #include <ns3/pointer.h>
23 #include <ns3/math.h>
24 #include <cfloat>
25 #include <set>
26 #include <climits>
27 
28 #include <ns3/lte-amc.h>
29 #include <ns3/rr-ff-mac-scheduler.h>
30 #include <ns3/simulator.h>
31 #include <ns3/lte-common.h>
32 #include <ns3/lte-vendor-specific-parameters.h>
33 #include <ns3/boolean.h>
34 
35 namespace ns3 {
36 
37 NS_LOG_COMPONENT_DEFINE ("RrFfMacScheduler");
38 
39 static const int Type0AllocationRbg[4] = {
40  10, // RGB size 1
41  26, // RGB size 2
42  63, // RGB size 3
43  110 // RGB size 4
44 }; // see table 7.1.6.1-1 of 36.213
45 
46 
47 
48 
49 NS_OBJECT_ENSURE_REGISTERED (RrFfMacScheduler);
50 
51 
53 {
54 public:
56 
57  // inherited from FfMacCschedSapProvider
58  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
59  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
60  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
61  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
62  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
63 
64 private:
67 };
68 
70 {
71 }
72 
74 {
75 }
76 
77 
78 void
80 {
82 }
83 
84 void
86 {
88 }
89 
90 
91 void
93 {
95 }
96 
97 void
99 {
101 }
102 
103 void
105 {
107 }
108 
109 
110 
111 
113 {
114 public:
116 
117  // inherited from FfMacSchedSapProvider
118  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
119  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
120  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
121  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
122  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
123  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
124  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
125  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
126  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
127  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
128  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
129 
130 
131 private:
134 };
135 
136 
137 
139 {
140 }
141 
142 
144  : m_scheduler (scheduler)
145 {
146 }
147 
148 void
150 {
152 }
153 
154 void
156 {
158 }
159 
160 void
162 {
164 }
165 
166 void
168 {
170 }
171 
172 void
174 {
176 }
177 
178 void
180 {
182 }
183 
184 void
186 {
188 }
189 
190 void
192 {
194 }
195 
196 void
198 {
200 }
201 
202 void
204 {
206 }
207 
208 void
210 {
212 }
213 
214 
215 
216 
217 
219  : m_cschedSapUser (0),
220  m_schedSapUser (0),
221  m_nextRntiDl (0),
222  m_nextRntiUl (0)
223 {
224  m_amc = CreateObject <LteAmc> ();
227 }
228 
230 {
231  NS_LOG_FUNCTION (this);
232 }
233 
234 void
236 {
237  NS_LOG_FUNCTION (this);
239  m_dlHarqProcessesTimer.clear ();
241  m_dlInfoListBuffered.clear ();
242  m_ulHarqCurrentProcessId.clear ();
243  m_ulHarqProcessesStatus.clear ();
245  delete m_cschedSapProvider;
246  delete m_schedSapProvider;
247 }
248 
249 TypeId
251 {
252  static TypeId tid = TypeId ("ns3::RrFfMacScheduler")
254  .SetGroupName("Lte")
255  .AddConstructor<RrFfMacScheduler> ()
256  .AddAttribute ("CqiTimerThreshold",
257  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
258  UintegerValue (1000),
260  MakeUintegerChecker<uint32_t> ())
261  .AddAttribute ("HarqEnabled",
262  "Activate/Deactivate the HARQ [by default is active].",
263  BooleanValue (true),
266  .AddAttribute ("UlGrantMcs",
267  "The MCS of the UL grant, must be [0..15] (default 0)",
268  UintegerValue (0),
270  MakeUintegerChecker<uint8_t> ())
271  ;
272  return tid;
273 }
274 
275 
276 
277 void
279 {
280  m_cschedSapUser = s;
281 }
282 
283 void
285 {
286  m_schedSapUser = s;
287 }
288 
291 {
292  return m_cschedSapProvider;
293 }
294 
297 {
298  return m_schedSapProvider;
299 }
300 
301 void
303 {
304  m_ffrSapProvider = s;
305 }
306 
309 {
310  return m_ffrSapUser;
311 }
312 
313 void
315 {
316  NS_LOG_FUNCTION (this);
317  // Read the subset of parameters used
318  m_cschedCellConfig = params;
321  cnf.m_result = SUCCESS;
323  return;
324 }
325 
326 void
328 {
329  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
330  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
331  if (it == m_uesTxMode.end ())
332  {
333  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
334  // generate HARQ buffers
335  m_dlHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
336  DlHarqProcessesStatus_t dlHarqPrcStatus;
337  dlHarqPrcStatus.resize (8,0);
338  m_dlHarqProcessesStatus.insert (std::pair <uint16_t, DlHarqProcessesStatus_t> (params.m_rnti, dlHarqPrcStatus));
339  DlHarqProcessesTimer_t dlHarqProcessesTimer;
340  dlHarqProcessesTimer.resize (8,0);
341  m_dlHarqProcessesTimer.insert (std::pair <uint16_t, DlHarqProcessesTimer_t> (params.m_rnti, dlHarqProcessesTimer));
342  DlHarqProcessesDciBuffer_t dlHarqdci;
343  dlHarqdci.resize (8);
344  m_dlHarqProcessesDciBuffer.insert (std::pair <uint16_t, DlHarqProcessesDciBuffer_t> (params.m_rnti, dlHarqdci));
345  DlHarqRlcPduListBuffer_t dlHarqRlcPdu;
346  dlHarqRlcPdu.resize (2);
347  dlHarqRlcPdu.at (0).resize (8);
348  dlHarqRlcPdu.at (1).resize (8);
349  m_dlHarqProcessesRlcPduListBuffer.insert (std::pair <uint16_t, DlHarqRlcPduListBuffer_t> (params.m_rnti, dlHarqRlcPdu));
350  m_ulHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
351  UlHarqProcessesStatus_t ulHarqPrcStatus;
352  ulHarqPrcStatus.resize (8,0);
353  m_ulHarqProcessesStatus.insert (std::pair <uint16_t, UlHarqProcessesStatus_t> (params.m_rnti, ulHarqPrcStatus));
354  UlHarqProcessesDciBuffer_t ulHarqdci;
355  ulHarqdci.resize (8);
356  m_ulHarqProcessesDciBuffer.insert (std::pair <uint16_t, UlHarqProcessesDciBuffer_t> (params.m_rnti, ulHarqdci));
357  }
358  else
359  {
360  (*it).second = params.m_transmissionMode;
361  }
362  return;
363 }
364 
365 void
367 {
368  NS_LOG_FUNCTION (this);
369  // Not used at this stage (LCs updated by DoSchedDlRlcBufferReq)
370  return;
371 }
372 
373 void
375 {
376  NS_LOG_FUNCTION (this);
377  for (uint16_t i = 0; i < params.m_logicalChannelIdentity.size (); i++)
378  {
379  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
380  while (it!=m_rlcBufferReq.end ())
381  {
382  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity.at (i)))
383  {
384  it = m_rlcBufferReq.erase (it);
385  }
386  else
387  {
388  it++;
389  }
390  }
391  }
392  return;
393 }
394 
395 void
397 {
398  NS_LOG_FUNCTION (this << " Release RNTI " << params.m_rnti);
399 
400  m_uesTxMode.erase (params.m_rnti);
401  m_dlHarqCurrentProcessId.erase (params.m_rnti);
402  m_dlHarqProcessesStatus.erase (params.m_rnti);
403  m_dlHarqProcessesTimer.erase (params.m_rnti);
404  m_dlHarqProcessesDciBuffer.erase (params.m_rnti);
406  m_ulHarqCurrentProcessId.erase (params.m_rnti);
407  m_ulHarqProcessesStatus.erase (params.m_rnti);
408  m_ulHarqProcessesDciBuffer.erase (params.m_rnti);
409  m_ceBsrRxed.erase (params.m_rnti);
410  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
411  while (it != m_rlcBufferReq.end ())
412  {
413  if ((*it).m_rnti == params.m_rnti)
414  {
415  NS_LOG_INFO (this << " Erase RNTI " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
416  it = m_rlcBufferReq.erase (it);
417  }
418  else
419  {
420  it++;
421  }
422  }
423  if (m_nextRntiUl == params.m_rnti)
424  {
425  m_nextRntiUl = 0;
426  }
427 
428  if (m_nextRntiDl == params.m_rnti)
429  {
430  m_nextRntiDl = 0;
431  }
432 
433  return;
434 }
435 
436 
437 void
439 {
440  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
441  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
442  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
443  bool newLc = true;
444  while (it != m_rlcBufferReq.end ())
445  {
446  // remove old entries of this UE-LC
447  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity))
448  {
449  it = m_rlcBufferReq.erase (it);
450  newLc = false;
451  }
452  else
453  {
454  ++it;
455  }
456  }
457  // add the new parameters
458  m_rlcBufferReq.insert (it, params);
459  NS_LOG_INFO (this << " RNTI " << params.m_rnti << " LC " << (uint16_t)params.m_logicalChannelIdentity << " RLC tx size " << params.m_rlcTransmissionQueueHolDelay << " RLC retx size " << params.m_rlcRetransmissionQueueSize << " RLC stat size " << params.m_rlcStatusPduSize);
460  // initialize statistics of the flow in case of new flows
461  if (newLc == true)
462  {
463  m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (params.m_rnti, 1)); // only codeword 0 at this stage (SISO)
464  // initialized to 1 (i.e., the lowest value for transmitting a signal)
465  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (params.m_rnti, m_cqiTimersThreshold));
466  }
467 
468  return;
469 }
470 
471 void
473 {
474  NS_LOG_FUNCTION (this);
475  NS_FATAL_ERROR ("method not implemented");
476  return;
477 }
478 
479 void
481 {
482  NS_LOG_FUNCTION (this);
483  NS_FATAL_ERROR ("method not implemented");
484  return;
485 }
486 
487 int
489 {
490  for (int i = 0; i < 4; i++)
491  {
492  if (dlbandwidth < Type0AllocationRbg[i])
493  {
494  return (i + 1);
495  }
496  }
497 
498  return (-1);
499 }
500 
501 bool
503 {
504  return (i.m_rnti < j.m_rnti);
505 }
506 
507 
508 uint8_t
510 {
511  NS_LOG_FUNCTION (this << rnti);
512 
513  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
514  if (it == m_dlHarqCurrentProcessId.end ())
515  {
516  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
517  }
518  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
519  if (itStat == m_dlHarqProcessesStatus.end ())
520  {
521  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
522  }
523  uint8_t i = (*it).second;
524  do
525  {
526  i = (i + 1) % HARQ_PROC_NUM;
527  }
528  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
529  if ((*itStat).second.at (i) == 0)
530  {
531  return (true);
532  }
533  else
534  {
535  return (false); // return a not valid harq proc id
536  }
537 }
538 
539 
540 
541 uint8_t
543 {
544  NS_LOG_FUNCTION (this << rnti);
545 
546 
547  if (m_harqOn == false)
548  {
549  return (0);
550  }
551 
552  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
553  if (it == m_dlHarqCurrentProcessId.end ())
554  {
555  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
556  }
557  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
558  if (itStat == m_dlHarqProcessesStatus.end ())
559  {
560  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
561  }
562  uint8_t i = (*it).second;
563  do
564  {
565  i = (i + 1) % HARQ_PROC_NUM;
566  }
567  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
568  if ((*itStat).second.at (i) == 0)
569  {
570  (*it).second = i;
571  (*itStat).second.at (i) = 1;
572  }
573  else
574  {
575  return (9); // return a not valid harq proc id
576  }
577 
578  return ((*it).second);
579 }
580 
581 
582 void
584 {
585  NS_LOG_FUNCTION (this);
586 
587  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
588  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers ++)
589  {
590  for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
591  {
592  if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
593  {
594  // reset HARQ process
595 
596  NS_LOG_INFO (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
597  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
598  if (itStat == m_dlHarqProcessesStatus.end ())
599  {
600  NS_FATAL_ERROR ("No Process Id Status found for this RNTI " << (*itTimers).first);
601  }
602  (*itStat).second.at (i) = 0;
603  (*itTimers).second.at (i) = 0;
604  }
605  else
606  {
607  (*itTimers).second.at (i)++;
608  }
609  }
610  }
611 
612 }
613 
614 
615 
616 void
618 {
619  NS_LOG_FUNCTION (this << " DL Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
620  // API generated by RLC for triggering the scheduling of a DL subframe
621 
622  RefreshDlCqiMaps ();
624  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
626 
627  // Generate RBGs map
628  std::vector <bool> rbgMap;
629  uint16_t rbgAllocatedNum = 0;
630  std::set <uint16_t> rntiAllocated;
631  rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
632 
633  // update UL HARQ proc id
634  std::map <uint16_t, uint8_t>::iterator itProcId;
635  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
636  {
637  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
638  }
639 
640  // RACH Allocation
642  uint16_t rbStart = 0;
643  std::vector <struct RachListElement_s>::iterator itRach;
644  for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
645  {
646  NS_ASSERT_MSG (m_amc->GetTbSizeFromMcs (m_ulGrantMcs, m_cschedCellConfig.m_ulBandwidth) > (*itRach).m_estimatedSize, " Default UL Grant MCS does not allow to send RACH messages");
647  BuildRarListElement_s newRar;
648  newRar.m_rnti = (*itRach).m_rnti;
649  // DL-RACH Allocation
650  // Ideal: no needs of configuring m_dci
651  // UL-RACH Allocation
652  newRar.m_grant.m_rnti = newRar.m_rnti;
653  newRar.m_grant.m_mcs = m_ulGrantMcs;
654  uint16_t rbLen = 1;
655  uint16_t tbSizeBits = 0;
656  // find lowest TB size that fits UL grant estimated size
657  while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
658  {
659  rbLen++;
660  tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
661  }
662  if (tbSizeBits < (*itRach).m_estimatedSize)
663  {
664  // no more allocation space: finish allocation
665  break;
666  }
667  newRar.m_grant.m_rbStart = rbStart;
668  newRar.m_grant.m_rbLen = rbLen;
669  newRar.m_grant.m_tbSize = tbSizeBits / 8;
670  newRar.m_grant.m_hopping = false;
671  newRar.m_grant.m_tpc = 0;
672  newRar.m_grant.m_cqiRequest = false;
673  newRar.m_grant.m_ulDelay = false;
674  NS_LOG_INFO (this << " UL grant allocated to RNTI " << (*itRach).m_rnti << " rbStart " << rbStart << " rbLen " << rbLen << " MCS " << (uint16_t) m_ulGrantMcs << " tbSize " << newRar.m_grant.m_tbSize);
675  for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
676  {
677  m_rachAllocationMap.at (i) = (*itRach).m_rnti;
678  }
679 
680  if (m_harqOn == true)
681  {
682  // generate UL-DCI for HARQ retransmissions
683  UlDciListElement_s uldci;
684  uldci.m_rnti = newRar.m_rnti;
685  uldci.m_rbLen = rbLen;
686  uldci.m_rbStart = rbStart;
687  uldci.m_mcs = m_ulGrantMcs;
688  uldci.m_tbSize = tbSizeBits / 8;
689  uldci.m_ndi = 1;
690  uldci.m_cceIndex = 0;
691  uldci.m_aggrLevel = 1;
692  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
693  uldci.m_hopping = false;
694  uldci.m_n2Dmrs = 0;
695  uldci.m_tpc = 0; // no power control
696  uldci.m_cqiRequest = false; // only period CQI at this stage
697  uldci.m_ulIndex = 0; // TDD parameter
698  uldci.m_dai = 1; // TDD parameter
699  uldci.m_freqHopping = 0;
700  uldci.m_pdcchPowerOffset = 0; // not used
701 
702  uint8_t harqId = 0;
703  std::map <uint16_t, uint8_t>::iterator itProcId;
704  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
705  if (itProcId == m_ulHarqCurrentProcessId.end ())
706  {
707  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
708  }
709  harqId = (*itProcId).second;
710  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
711  if (itDci == m_ulHarqProcessesDciBuffer.end ())
712  {
713  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
714  }
715  (*itDci).second.at (harqId) = uldci;
716  }
717 
718  rbStart = rbStart + rbLen;
719  ret.m_buildRarList.push_back (newRar);
720  }
721  m_rachList.clear ();
722 
723  // Process DL HARQ feedback
725  // retrieve past HARQ retx buffered
726  if (m_dlInfoListBuffered.size () > 0)
727  {
728  if (params.m_dlInfoList.size () > 0)
729  {
730  NS_LOG_INFO (this << " Received DL-HARQ feedback");
731  m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
732  }
733  }
734  else
735  {
736  if (params.m_dlInfoList.size () > 0)
737  {
739  }
740  }
741  if (m_harqOn == false)
742  {
743  // Ignore HARQ feedback
744  m_dlInfoListBuffered.clear ();
745  }
746  std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
747  for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
748  {
749  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
750  if (itRnti != rntiAllocated.end ())
751  {
752  // RNTI already allocated for retx
753  continue;
754  }
755  uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
756  std::vector <bool> retx;
757  NS_LOG_INFO (this << " Processing DLHARQ feedback");
758  if (nLayers == 1)
759  {
760  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
761  retx.push_back (false);
762  }
763  else
764  {
765  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
766  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
767  }
768  if (retx.at (0) || retx.at (1))
769  {
770  // retrieve HARQ process information
771  uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
772  uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
773  NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
774  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
775  if (itHarq == m_dlHarqProcessesDciBuffer.end ())
776  {
777  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
778  }
779 
780  DlDciListElement_s dci = (*itHarq).second.at (harqId);
781  int rv = 0;
782  if (dci.m_rv.size () == 1)
783  {
784  rv = dci.m_rv.at (0);
785  }
786  else
787  {
788  rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
789  }
790 
791  if (rv == 3)
792  {
793  // maximum number of retx reached -> drop process
794  NS_LOG_INFO ("Max number of retransmissions reached -> drop process");
795  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
796  if (it == m_dlHarqProcessesStatus.end ())
797  {
798  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
799  }
800  (*it).second.at (harqId) = 0;
801  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
802  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
803  {
804  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
805  }
806  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
807  {
808  (*itRlcPdu).second.at (k).at (harqId).clear ();
809  }
810  continue;
811  }
812  // check the feasibility of retransmitting on the same RBGs
813  // translate the DCI to Spectrum framework
814  std::vector <int> dciRbg;
815  uint32_t mask = 0x1;
816  NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
817  for (int j = 0; j < 32; j++)
818  {
819  if (((dci.m_rbBitmap & mask) >> j) == 1)
820  {
821  dciRbg.push_back (j);
822  NS_LOG_INFO ("\t" << j);
823  }
824  mask = (mask << 1);
825  }
826  bool free = true;
827  for (uint8_t j = 0; j < dciRbg.size (); j++)
828  {
829  if (rbgMap.at (dciRbg.at (j)) == true)
830  {
831  free = false;
832  break;
833  }
834  }
835  if (free)
836  {
837  // use the same RBGs for the retx
838  // reserve RBGs
839  for (uint8_t j = 0; j < dciRbg.size (); j++)
840  {
841  rbgMap.at (dciRbg.at (j)) = true;
842  NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
843  rbgAllocatedNum++;
844  }
845 
846  NS_LOG_INFO (this << " Send retx in the same RBGs");
847  }
848  else
849  {
850  // find RBGs for sending HARQ retx
851  uint8_t j = 0;
852  uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % rbgNum;
853  uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
854  std::vector <bool> rbgMapCopy = rbgMap;
855  while ((j < dciRbg.size ())&&(startRbg != rbgId))
856  {
857  if (rbgMapCopy.at (rbgId) == false)
858  {
859  rbgMapCopy.at (rbgId) = true;
860  dciRbg.at (j) = rbgId;
861  j++;
862  }
863  rbgId = (rbgId + 1) % rbgNum;
864  }
865  if (j == dciRbg.size ())
866  {
867  // find new RBGs -> update DCI map
868  uint32_t rbgMask = 0;
869  for (uint16_t k = 0; k < dciRbg.size (); k++)
870  {
871  rbgMask = rbgMask + (0x1 << dciRbg.at (k));
872  NS_LOG_INFO (this << " New allocated RBG " << dciRbg.at (k));
873  rbgAllocatedNum++;
874  }
875  dci.m_rbBitmap = rbgMask;
876  rbgMap = rbgMapCopy;
877  }
878  else
879  {
880  // HARQ retx cannot be performed on this TTI -> store it
881  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
882  NS_LOG_INFO (this << " No resource for this retx -> buffer it");
883  }
884  }
885  // retrieve RLC PDU list for retx TBsize and update DCI
887  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
888  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
889  {
890  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
891  }
892  for (uint8_t j = 0; j < nLayers; j++)
893  {
894  if (retx.at (j))
895  {
896  if (j >= dci.m_ndi.size ())
897  {
898  // for avoiding errors in MIMO transient phases
899  dci.m_ndi.push_back (0);
900  dci.m_rv.push_back (0);
901  dci.m_mcs.push_back (0);
902  dci.m_tbsSize.push_back (0);
903  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
904 
905  }
906  else
907  {
908  dci.m_ndi.at (j) = 0;
909  dci.m_rv.at (j)++;
910  (*itHarq).second.at (harqId).m_rv.at (j)++;
911  NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
912  }
913  }
914  else
915  {
916  // empty TB of layer j
917  dci.m_ndi.at (j) = 0;
918  dci.m_rv.at (j) = 0;
919  dci.m_mcs.at (j) = 0;
920  dci.m_tbsSize.at (j) = 0;
921  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
922  }
923  }
924 
925  for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
926  {
927  std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
928  for (uint8_t j = 0; j < nLayers; j++)
929  {
930  if (retx.at (j))
931  {
932  if (j < dci.m_ndi.size ())
933  {
934  rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
935  }
936  }
937  }
938 
939  if (rlcPduListPerLc.size () > 0)
940  {
941  newEl.m_rlcPduList.push_back (rlcPduListPerLc);
942  }
943  }
944  newEl.m_rnti = rnti;
945  newEl.m_dci = dci;
946  (*itHarq).second.at (harqId).m_rv = dci.m_rv;
947  // refresh timer
948  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
949  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
950  {
951  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
952  }
953  (*itHarqTimer).second.at (harqId) = 0;
954  ret.m_buildDataList.push_back (newEl);
955  rntiAllocated.insert (rnti);
956  }
957  else
958  {
959  // update HARQ process status
960  NS_LOG_INFO (this << " HARQ ACK UE " << m_dlInfoListBuffered.at (i).m_rnti);
961  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
962  if (it == m_dlHarqProcessesStatus.end ())
963  {
964  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
965  }
966  (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
967  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
968  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
969  {
970  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
971  }
972  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
973  {
974  (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
975  }
976  }
977  }
978  m_dlInfoListBuffered.clear ();
979  m_dlInfoListBuffered = dlInfoListUntxed;
980 
981  if (rbgAllocatedNum == rbgNum)
982  {
983  // all the RBGs are already allocated -> exit
984  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
985  {
987  }
988  return;
989  }
990 
991  // Get the actual active flows (queue!=0)
992  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
994  int nflows = 0;
995  int nTbs = 0;
996  std::map <uint16_t,uint8_t> lcActivesPerRnti; // tracks how many active LCs per RNTI there are
997  std::map <uint16_t,uint8_t>::iterator itLcRnti;
998  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
999  {
1000  // remove old entries of this UE-LC
1001  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
1002  if ( (((*it).m_rlcTransmissionQueueSize > 0)
1003  || ((*it).m_rlcRetransmissionQueueSize > 0)
1004  || ((*it).m_rlcStatusPduSize > 0))
1005  && (itRnti == rntiAllocated.end ()) // UE must not be allocated for HARQ retx
1006  && (HarqProcessAvailability ((*it).m_rnti)) ) // UE needs HARQ proc free
1007 
1008  {
1009  NS_LOG_LOGIC (this << " User " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity << " is active, status " << (*it).m_rlcStatusPduSize << " retx " << (*it).m_rlcRetransmissionQueueSize << " tx " << (*it).m_rlcTransmissionQueueSize);
1010  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find ((*it).m_rnti);
1011  uint8_t cqi = 0;
1012  if (itCqi != m_p10CqiRxed.end ())
1013  {
1014  cqi = (*itCqi).second;
1015  }
1016  else
1017  {
1018  cqi = 1; // lowest value fro trying a transmission
1019  }
1020  if (cqi != 0)
1021  {
1022  // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1023  nflows++;
1024  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
1025  if (itLcRnti != lcActivesPerRnti.end ())
1026  {
1027  (*itLcRnti).second++;
1028  }
1029  else
1030  {
1031  lcActivesPerRnti.insert (std::pair<uint16_t, uint8_t > ((*it).m_rnti, 1));
1032  nTbs++;
1033  }
1034 
1035  }
1036  }
1037  }
1038 
1039  if (nflows == 0)
1040  {
1041  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
1042  {
1044  }
1045  return;
1046  }
1047  // Divide the resource equally among the active users according to
1048  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
1049 
1050  int rbgPerTb = (nTbs > 0) ? ((rbgNum - rbgAllocatedNum) / nTbs) : INT_MAX;
1051  NS_LOG_INFO (this << " Flows to be transmitted " << nflows << " rbgPerTb " << rbgPerTb);
1052  if (rbgPerTb == 0)
1053  {
1054  rbgPerTb = 1; // at least 1 rbg per TB (till available resource)
1055  }
1056  int rbgAllocated = 0;
1057 
1058  // round robin assignment to all UEs registered starting from the subsequent of the one
1059  // served last scheduling trigger event
1060  if (m_nextRntiDl != 0)
1061  {
1062  NS_LOG_DEBUG ("Start from the successive of " << (uint16_t) m_nextRntiDl);
1063  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1064  {
1065  if ((*it).m_rnti == m_nextRntiDl)
1066  {
1067  // select the next RNTI to starting
1068  it++;
1069  if (it == m_rlcBufferReq.end ())
1070  {
1071  it = m_rlcBufferReq.begin ();
1072  }
1073  m_nextRntiDl = (*it).m_rnti;
1074  break;
1075  }
1076  }
1077 
1078  if (it == m_rlcBufferReq.end ())
1079  {
1080  NS_LOG_ERROR (this << " no user found");
1081  }
1082  }
1083  else
1084  {
1085  it = m_rlcBufferReq.begin ();
1086  m_nextRntiDl = (*it).m_rnti;
1087  }
1088  std::map <uint16_t,uint8_t>::iterator itTxMode;
1089  do
1090  {
1091  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
1092  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
1093  if ((itLcRnti == lcActivesPerRnti.end ())||(itRnti != rntiAllocated.end ()))
1094  {
1095  // skip this RNTI (no active queue or yet allocated for HARQ)
1096  uint16_t rntiDiscared = (*it).m_rnti;
1097  while (it != m_rlcBufferReq.end ())
1098  {
1099  if ((*it).m_rnti != rntiDiscared)
1100  {
1101  break;
1102  }
1103  it++;
1104  }
1105  if (it == m_rlcBufferReq.end ())
1106  {
1107  // restart from the first
1108  it = m_rlcBufferReq.begin ();
1109  }
1110  continue;
1111  }
1112  itTxMode = m_uesTxMode.find ((*it).m_rnti);
1113  if (itTxMode == m_uesTxMode.end ())
1114  {
1115  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).m_rnti);
1116  }
1117  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1118  int lcNum = (*itLcRnti).second;
1119  // create new BuildDataListElement_s for this RNTI
1120  BuildDataListElement_s newEl;
1121  newEl.m_rnti = (*it).m_rnti;
1122  // create the DlDciListElement_s
1123  DlDciListElement_s newDci;
1124  newDci.m_rnti = (*it).m_rnti;
1125  newDci.m_harqProcess = UpdateHarqProcessId ((*it).m_rnti);
1126  newDci.m_resAlloc = 0;
1127  newDci.m_rbBitmap = 0;
1128  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find (newEl.m_rnti);
1129  for (uint8_t i = 0; i < nLayer; i++)
1130  {
1131  if (itCqi == m_p10CqiRxed.end ())
1132  {
1133  newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS
1134  }
1135  else
1136  {
1137  newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) );
1138  }
1139  }
1140  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
1141  uint16_t rlcPduSize = tbSize / lcNum;
1142  while ((*it).m_rnti == newEl.m_rnti)
1143  {
1144  if ( ((*it).m_rlcTransmissionQueueSize > 0)
1145  || ((*it).m_rlcRetransmissionQueueSize > 0)
1146  || ((*it).m_rlcStatusPduSize > 0) )
1147  {
1148  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1149  for (uint8_t j = 0; j < nLayer; j++)
1150  {
1151  RlcPduListElement_s newRlcEl;
1152  newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
1153  NS_LOG_INFO (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
1154  newRlcEl.m_size = rlcPduSize;
1155  UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
1156  newRlcPduLe.push_back (newRlcEl);
1157 
1158  if (m_harqOn == true)
1159  {
1160  // store RLC PDU list for HARQ
1161  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*it).m_rnti);
1162  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1163  {
1164  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*it).m_rnti);
1165  }
1166  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1167  }
1168 
1169  }
1170  newEl.m_rlcPduList.push_back (newRlcPduLe);
1171  lcNum--;
1172  }
1173  it++;
1174  if (it == m_rlcBufferReq.end ())
1175  {
1176  // restart from the first
1177  it = m_rlcBufferReq.begin ();
1178  break;
1179  }
1180  }
1181  uint32_t rbgMask = 0;
1182  uint16_t i = 0;
1183  NS_LOG_INFO (this << " DL - Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " harqId " << (uint16_t)newDci.m_harqProcess << " layers " << nLayer);
1184  NS_LOG_INFO ("RBG:");
1185  while (i < rbgPerTb)
1186  {
1187  if (rbgMap.at (rbgAllocated) == false)
1188  {
1189  rbgMask = rbgMask + (0x1 << rbgAllocated);
1190  NS_LOG_INFO ("\t " << rbgAllocated);
1191  i++;
1192  rbgMap.at (rbgAllocated) = true;
1193  rbgAllocatedNum++;
1194  }
1195  rbgAllocated++;
1196  }
1197  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1198 
1199  for (int i = 0; i < nLayer; i++)
1200  {
1201  newDci.m_tbsSize.push_back (tbSize);
1202  newDci.m_ndi.push_back (1);
1203  newDci.m_rv.push_back (0);
1204  }
1205 
1206  newDci.m_tpc = 1; //1 is mapped to 0 in Accumulated Mode and to -1 in Absolute Mode
1207 
1208  newEl.m_dci = newDci;
1209  if (m_harqOn == true)
1210  {
1211  // store DCI for HARQ
1212  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1213  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1214  {
1215  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1216  }
1217  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1218  // refresh timer
1219  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1220  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1221  {
1222  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1223  }
1224  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1225  }
1226  // ...more parameters -> ignored in this version
1227 
1228  ret.m_buildDataList.push_back (newEl);
1229  if (rbgAllocatedNum == rbgNum)
1230  {
1231  m_nextRntiDl = newEl.m_rnti; // store last RNTI served
1232  break; // no more RGB to be allocated
1233  }
1234  }
1235  while ((*it).m_rnti != m_nextRntiDl);
1236 
1237  ret.m_nrOfPdcchOfdmSymbols = 1;
1238 
1240  return;
1241 }
1242 
1243 void
1245 {
1246  NS_LOG_FUNCTION (this);
1247 
1248  m_rachList = params.m_rachList;
1249 
1250  return;
1251 }
1252 
1253 void
1255 {
1256  NS_LOG_FUNCTION (this);
1257 
1258  std::map <uint16_t,uint8_t>::iterator it;
1259  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1260  {
1261  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1262  {
1263  NS_LOG_LOGIC ("wideband CQI " << (uint32_t) params.m_cqiList.at (i).m_wbCqi.at (0) << " reported");
1264  std::map <uint16_t,uint8_t>::iterator it;
1265  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1266  it = m_p10CqiRxed.find (rnti);
1267  if (it == m_p10CqiRxed.end ())
1268  {
1269  // create the new entry
1270  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)
1271  // generate correspondent timer
1272  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1273  }
1274  else
1275  {
1276  // update the CQI value
1277  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1278  // update correspondent timer
1279  std::map <uint16_t,uint32_t>::iterator itTimers;
1280  itTimers = m_p10CqiTimers.find (rnti);
1281  (*itTimers).second = m_cqiTimersThreshold;
1282  }
1283  }
1284  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1285  {
1286  // subband CQI reporting high layer configured
1287  // Not used by RR Scheduler
1288  }
1289  else
1290  {
1291  NS_LOG_ERROR (this << " CQI type unknown");
1292  }
1293  }
1294 
1295  return;
1296 }
1297 
1298 void
1300 {
1301  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1302 
1303  RefreshUlCqiMaps ();
1304 
1305  // Generate RBs map
1307  std::vector <bool> rbMap;
1308  uint16_t rbAllocatedNum = 0;
1309  std::set <uint16_t> rntiAllocated;
1310  std::vector <uint16_t> rbgAllocationMap;
1311  // update with RACH allocation map
1312  rbgAllocationMap = m_rachAllocationMap;
1313  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1314  m_rachAllocationMap.clear ();
1316 
1317  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1318  // remove RACH allocation
1319  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1320  {
1321  if (rbgAllocationMap.at (i) != 0)
1322  {
1323  rbMap.at (i) = true;
1324  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1325  }
1326  }
1327 
1328  if (m_harqOn == true)
1329  {
1330  // Process UL HARQ feedback
1331  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1332  {
1333  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1334  {
1335  // retx correspondent block: retrieve the UL-DCI
1336  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1337  std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1338  if (itProcId == m_ulHarqCurrentProcessId.end ())
1339  {
1340  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1341  }
1342  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1343  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
1344  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1345  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1346  {
1347  NS_LOG_ERROR ("No info find in UL-HARQ buffer for UE (might change eNB) " << rnti);
1348  }
1349  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1350  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1351  if (itStat == m_ulHarqProcessesStatus.end ())
1352  {
1353  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1354  }
1355  if ((*itStat).second.at (harqId) > 3)
1356  {
1357  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1358  continue;
1359  }
1360  bool free = true;
1361  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1362  {
1363  if (rbMap.at (j) == true)
1364  {
1365  free = false;
1366  NS_LOG_INFO (this << " BUSY " << j);
1367  }
1368  }
1369  if (free)
1370  {
1371  // retx on the same RBs
1372  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1373  {
1374  rbMap.at (j) = true;
1375  rbgAllocationMap.at (j) = dci.m_rnti;
1376  NS_LOG_INFO ("\tRB " << j);
1377  rbAllocatedNum++;
1378  }
1379  NS_LOG_INFO (this << " Send retx in the same RBGs " << (uint16_t)dci.m_rbStart << " to " << dci.m_rbStart + dci.m_rbLen << " RV " << (*itStat).second.at (harqId) + 1);
1380  }
1381  else
1382  {
1383  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1384  continue;
1385  }
1386  dci.m_ndi = 0;
1387  // Update HARQ buffers with new HarqId
1388  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1389  (*itStat).second.at (harqId) = 0;
1390  (*itHarq).second.at ((*itProcId).second) = dci;
1391  ret.m_dciList.push_back (dci);
1392  rntiAllocated.insert (dci.m_rnti);
1393  }
1394  }
1395  }
1396 
1397  std::map <uint16_t,uint32_t>::iterator it;
1398  int nflows = 0;
1399 
1400  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1401  {
1402  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1403  // select UEs with queues not empty and not yet allocated for HARQ
1404  NS_LOG_INFO (this << " UE " << (*it).first << " queue " << (*it).second);
1405  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1406  {
1407  nflows++;
1408  }
1409  }
1410 
1411  if (nflows == 0)
1412  {
1413  if (ret.m_dciList.size () > 0)
1414  {
1415  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1417  }
1418  return; // no flows to be scheduled
1419  }
1420 
1421 
1422  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1423  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
1424  if (rbPerFlow < 3)
1425  {
1426  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1427  }
1428  uint16_t rbAllocated = 0;
1429 
1430  if (m_nextRntiUl != 0)
1431  {
1432  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1433  {
1434  if ((*it).first == m_nextRntiUl)
1435  {
1436  break;
1437  }
1438  }
1439  if (it == m_ceBsrRxed.end ())
1440  {
1441  NS_LOG_ERROR (this << " no user found");
1442  }
1443  }
1444  else
1445  {
1446  it = m_ceBsrRxed.begin ();
1447  m_nextRntiUl = (*it).first;
1448  }
1449  NS_LOG_INFO (this << " NFlows " << nflows << " RB per Flow " << rbPerFlow);
1450  do
1451  {
1452  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1453  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1454  {
1455  // UE already allocated for UL-HARQ -> skip it
1456  it++;
1457  if (it == m_ceBsrRxed.end ())
1458  {
1459  // restart from the first
1460  it = m_ceBsrRxed.begin ();
1461  }
1462  continue;
1463  }
1464  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1465  {
1466  // limit to physical resources last resource assignment
1467  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1468  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1469  if (rbPerFlow < 3)
1470  {
1471  // terminate allocation
1472  rbPerFlow = 0;
1473  }
1474  }
1475  NS_LOG_INFO (this << " try to allocate " << (*it).first);
1476  UlDciListElement_s uldci;
1477  uldci.m_rnti = (*it).first;
1478  uldci.m_rbLen = rbPerFlow;
1479  bool allocated = false;
1480  NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1481  while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
1482  {
1483  // check availability
1484  bool free = true;
1485  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1486  {
1487  if (rbMap.at (j) == true)
1488  {
1489  free = false;
1490  break;
1491  }
1492  }
1493  if (free)
1494  {
1495  uldci.m_rbStart = rbAllocated;
1496 
1497  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1498  {
1499  rbMap.at (j) = true;
1500  // store info on allocation for managing ul-cqi interpretation
1501  rbgAllocationMap.at (j) = (*it).first;
1502  NS_LOG_INFO ("\t " << j);
1503  }
1504  rbAllocated += rbPerFlow;
1505  allocated = true;
1506  break;
1507  }
1508  rbAllocated++;
1509  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1510  {
1511  // limit to physical resources last resource assignment
1512  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1513  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1514  if (rbPerFlow < 3)
1515  {
1516  // terminate allocation
1517  rbPerFlow = 0;
1518  }
1519  }
1520  }
1521  if (!allocated)
1522  {
1523  // unable to allocate new resource: finish scheduling
1524  m_nextRntiUl = (*it).first;
1525  if (ret.m_dciList.size () > 0)
1526  {
1528  }
1529  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1530  return;
1531  }
1532  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1533  int cqi = 0;
1534  if (itCqi == m_ueCqi.end ())
1535  {
1536  // no cqi info about this UE
1537  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1538  NS_LOG_INFO (this << " UE does not have ULCQI " << (*it).first );
1539  }
1540  else
1541  {
1542  // take the lowest CQI value (worst RB)
1543  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1544  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1545  {
1546  if ((*itCqi).second.at (i) < minSinr)
1547  {
1548  minSinr = (*itCqi).second.at (i);
1549  }
1550  }
1551  // translate SINR -> cqi: WILD ACK: same as DL
1552  double s = log2 ( 1 + (
1553  std::pow (10, minSinr / 10 ) /
1554  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1555 
1556 
1557  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1558  if (cqi == 0)
1559  {
1560  it++;
1561  if (it == m_ceBsrRxed.end ())
1562  {
1563  // restart from the first
1564  it = m_ceBsrRxed.begin ();
1565  }
1566  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
1567  // remove UE from allocation map
1568  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1569  {
1570  rbgAllocationMap.at (i) = 0;
1571  }
1572  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1573  }
1574  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1575  }
1576  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD
1577 
1578  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1579  uldci.m_ndi = 1;
1580  uldci.m_cceIndex = 0;
1581  uldci.m_aggrLevel = 1;
1582  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1583  uldci.m_hopping = false;
1584  uldci.m_n2Dmrs = 0;
1585  uldci.m_tpc = 0; // no power control
1586  uldci.m_cqiRequest = false; // only period CQI at this stage
1587  uldci.m_ulIndex = 0; // TDD parameter
1588  uldci.m_dai = 1; // TDD parameter
1589  uldci.m_freqHopping = 0;
1590  uldci.m_pdcchPowerOffset = 0; // not used
1591  ret.m_dciList.push_back (uldci);
1592  // store DCI for HARQ_PERIOD
1593  uint8_t harqId = 0;
1594  if (m_harqOn == true)
1595  {
1596  std::map <uint16_t, uint8_t>::iterator itProcId;
1597  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1598  if (itProcId == m_ulHarqCurrentProcessId.end ())
1599  {
1600  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1601  }
1602  harqId = (*itProcId).second;
1603  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1604  if (itDci == m_ulHarqProcessesDciBuffer.end ())
1605  {
1606  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1607  }
1608  (*itDci).second.at (harqId) = uldci;
1609  // Update HARQ process status (RV 0)
1610  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (uldci.m_rnti);
1611  if (itStat == m_ulHarqProcessesStatus.end ())
1612  {
1613  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << uldci.m_rnti);
1614  }
1615  (*itStat).second.at (harqId) = 0;
1616  }
1617 
1618  NS_LOG_INFO (this << " UL Allocation - UE " << (*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 << " harqId " << (uint16_t)harqId);
1619 
1620  it++;
1621  if (it == m_ceBsrRxed.end ())
1622  {
1623  // restart from the first
1624  it = m_ceBsrRxed.begin ();
1625  }
1626  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1627  {
1628  // Stop allocation: no more PRBs
1629  m_nextRntiUl = (*it).first;
1630  break;
1631  }
1632  }
1633  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1634 
1635  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1636 
1638  return;
1639 }
1640 
1641 void
1643 {
1644  NS_LOG_FUNCTION (this);
1645  return;
1646 }
1647 
1648 void
1650 {
1651  NS_LOG_FUNCTION (this);
1652  return;
1653 }
1654 
1655 void
1657 {
1658  NS_LOG_FUNCTION (this);
1659 
1660  std::map <uint16_t,uint32_t>::iterator it;
1661 
1662  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1663  {
1664  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1665  {
1666  // buffer status report
1667  // note that this scheduler does not differentiate the
1668  // allocation according to which LCGs have more/less bytes
1669  // to send.
1670  // Hence the BSR of different LCGs are just summed up to get
1671  // a total queue size that is used for allocation purposes.
1672 
1673  uint32_t buffer = 0;
1674  for (uint8_t lcg = 0; lcg < 4; ++lcg)
1675  {
1676  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1677  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1678  }
1679 
1680  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1681  it = m_ceBsrRxed.find (rnti);
1682  if (it == m_ceBsrRxed.end ())
1683  {
1684  // create the new entry
1685  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1686  NS_LOG_INFO (this << " Insert RNTI " << rnti << " queue " << buffer);
1687  }
1688  else
1689  {
1690  // update the buffer size value
1691  (*it).second = buffer;
1692  NS_LOG_INFO (this << " Update RNTI " << rnti << " queue " << buffer);
1693  }
1694  }
1695  }
1696 
1697  return;
1698 }
1699 
1700 void
1702 {
1703  NS_LOG_FUNCTION (this);
1704 
1705  switch (m_ulCqiFilter)
1706  {
1708  {
1709  // filter all the CQIs that are not SRS based
1710  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
1711  {
1712  return;
1713  }
1714  }
1715  break;
1717  {
1718  // filter all the CQIs that are not SRS based
1719  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
1720  {
1721  return;
1722  }
1723  }
1725  break;
1726 
1727  default:
1728  NS_FATAL_ERROR ("Unknown UL CQI type");
1729  }
1730  switch (params.m_ulCqi.m_type)
1731  {
1732  case UlCqi_s::PUSCH:
1733  {
1734  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1735  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1736  itMap = m_allocationMaps.find (params.m_sfnSf);
1737  if (itMap == m_allocationMaps.end ())
1738  {
1739  NS_LOG_INFO (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1740  return;
1741  }
1742  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1743  {
1744  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1745  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1746  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1747  if (itCqi == m_ueCqi.end ())
1748  {
1749  // create a new entry
1750  std::vector <double> newCqi;
1751  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1752  {
1753  if (i == j)
1754  {
1755  newCqi.push_back (sinr);
1756  }
1757  else
1758  {
1759  // initialize with NO_SINR value.
1760  newCqi.push_back (30.0);
1761  }
1762 
1763  }
1764  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1765  // generate correspondent timer
1766  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1767  }
1768  else
1769  {
1770  // update the value
1771  (*itCqi).second.at (i) = sinr;
1772  // update correspondent timer
1773  std::map <uint16_t, uint32_t>::iterator itTimers;
1774  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1775  (*itTimers).second = m_cqiTimersThreshold;
1776 
1777  }
1778 
1779  }
1780  // remove obsolete info on allocation
1781  m_allocationMaps.erase (itMap);
1782  }
1783  break;
1784  case UlCqi_s::SRS:
1785  {
1786  // get the RNTI from vendor specific parameters
1787  uint16_t rnti = 0;
1788  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1789  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1790  {
1791  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1792  {
1793  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1794  rnti = vsp->GetRnti ();
1795  }
1796  }
1797  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1798  itCqi = m_ueCqi.find (rnti);
1799  if (itCqi == m_ueCqi.end ())
1800  {
1801  // create a new entry
1802  std::vector <double> newCqi;
1803  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1804  {
1805  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1806  newCqi.push_back (sinr);
1807  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1808 
1809  }
1810  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1811  // generate correspondent timer
1812  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1813  }
1814  else
1815  {
1816  // update the values
1817  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1818  {
1819  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1820  (*itCqi).second.at (j) = sinr;
1821  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1822  }
1823  // update correspondent timer
1824  std::map <uint16_t, uint32_t>::iterator itTimers;
1825  itTimers = m_ueCqiTimers.find (rnti);
1826  (*itTimers).second = m_cqiTimersThreshold;
1827 
1828  }
1829 
1830 
1831  }
1832  break;
1833  case UlCqi_s::PUCCH_1:
1834  case UlCqi_s::PUCCH_2:
1835  case UlCqi_s::PRACH:
1836  {
1837  NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1838  }
1839  break;
1840  default:
1841  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1842  }
1843  return;
1844 }
1845 
1846 
1847 void
1849 {
1850  NS_LOG_FUNCTION (this << m_p10CqiTimers.size ());
1851  // refresh DL CQI P01 Map
1852  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1853  while (itP10 != m_p10CqiTimers.end ())
1854  {
1855  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1856  if ((*itP10).second == 0)
1857  {
1858  // delete correspondent entries
1859  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1860  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1861  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1862  m_p10CqiRxed.erase (itMap);
1863  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1864  itP10++;
1865  m_p10CqiTimers.erase (temp);
1866  }
1867  else
1868  {
1869  (*itP10).second--;
1870  itP10++;
1871  }
1872  }
1873 
1874  return;
1875 }
1876 
1877 
1878 void
1880 {
1881  // refresh UL CQI Map
1882  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1883  while (itUl != m_ueCqiTimers.end ())
1884  {
1885  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1886  if ((*itUl).second == 0)
1887  {
1888  // delete correspondent entries
1889  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1890  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1891  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1892  (*itMap).second.clear ();
1893  m_ueCqi.erase (itMap);
1894  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1895  itUl++;
1896  m_ueCqiTimers.erase (temp);
1897  }
1898  else
1899  {
1900  (*itUl).second--;
1901  itUl++;
1902  }
1903  }
1904 
1905  return;
1906 }
1907 
1908 void
1909 RrFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1910 {
1911  NS_LOG_FUNCTION (this);
1912  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1913  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1914  {
1915  if (((*it).m_rnti == rnti) && ((*it).m_logicalChannelIdentity == lcid))
1916  {
1917  NS_LOG_INFO (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).m_rlcTransmissionQueueSize << " retxqueue " << (*it).m_rlcRetransmissionQueueSize << " status " << (*it).m_rlcStatusPduSize << " decrease " << size);
1918  // Update queues: RLC tx order Status, ReTx, Tx
1919  // Update status queue
1920  if (((*it).m_rlcStatusPduSize > 0) && (size >= (*it).m_rlcStatusPduSize))
1921  {
1922  (*it).m_rlcStatusPduSize = 0;
1923  }
1924  else if (((*it).m_rlcRetransmissionQueueSize > 0) && (size >= (*it).m_rlcRetransmissionQueueSize))
1925  {
1926  (*it).m_rlcRetransmissionQueueSize = 0;
1927  }
1928  else if ((*it).m_rlcTransmissionQueueSize > 0)
1929  {
1930  uint32_t rlcOverhead;
1931  if (lcid == 1)
1932  {
1933  // for SRB1 (using RLC AM) it's better to
1934  // overestimate RLC overhead rather than
1935  // underestimate it and risk unneeded
1936  // segmentation which increases delay
1937  rlcOverhead = 4;
1938  }
1939  else
1940  {
1941  // minimum RLC overhead due to header
1942  rlcOverhead = 2;
1943  }
1944  // update transmission queue
1945  if ((*it).m_rlcTransmissionQueueSize <= size - rlcOverhead)
1946  {
1947  (*it).m_rlcTransmissionQueueSize = 0;
1948  }
1949  else
1950  {
1951  (*it).m_rlcTransmissionQueueSize -= size - rlcOverhead;
1952  }
1953  }
1954  return;
1955  }
1956  }
1957 }
1958 
1959 void
1960 RrFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1961 {
1962 
1963  size = size - 2; // remove the minimum RLC overhead
1964  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1965  if (it != m_ceBsrRxed.end ())
1966  {
1967  NS_LOG_INFO (this << " Update RLC BSR UE " << rnti << " size " << size << " BSR " << (*it).second);
1968  if ((*it).second >= size)
1969  {
1970  (*it).second -= size;
1971  }
1972  else
1973  {
1974  (*it).second = 0;
1975  }
1976  }
1977  else
1978  {
1979  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1980  }
1981 
1982 }
1983 
1984 
1985 void
1987 {
1988  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1990  params.m_rnti = rnti;
1991  params.m_transmissionMode = txMode;
1993 }
1994 
1995 
1996 
1997 }
std::vector< struct UlInfoListElement_s > m_ulInfoList
See section 4.3.1 dlDciListElement.
Definition: ff-mac-common.h:88
virtual void SchedUlMacCtrlInfoReq(const struct SchedUlMacCtrlInfoReqParameters &params)
friend class RrSchedulerMemberCschedSapProvider
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
Service Access Point (SAP) offered by the eNodeB RRC instance to the Frequency Reuse algorithm instan...
Definition: lte-ffr-sap.h:132
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
#define HARQ_PERIOD
Definition: lte-common.h:30
AttributeValue implementation for Boolean.
Definition: boolean.h:34
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
std::map< uint16_t, uint32_t > m_ueCqiTimers
Parameters of the CSCHED_UE_CONFIG_CNF primitive.
Parameters of the CSCHED_UE_RELEASE_REQ primitive.
virtual void SchedDlPagingBufferReq(const struct SchedDlPagingBufferReqParameters &params)
static TypeId GetTypeId(void)
enum ns3::UlCqi_s::Type_e m_type
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: boolean.h:81
std::vector< UlDciListElement_s > UlHarqProcessesDciBuffer_t
std::vector< uint16_t > m_sinr
std::vector< uint8_t > DlHarqProcessesTimer_t
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
void DoCschedCellConfigReq(const struct FfMacCschedSapProvider::CschedCellConfigReqParameters &params)
std::vector< uint8_t > m_mcs
Definition: ff-mac-common.h:95
virtual void SchedDlCqiInfoReq(const struct SchedDlCqiInfoReqParameters &params)
See section 4.3.2 ulDciListElement.
Provides the CSCHED SAP.
static bool SortRlcBufferReq(FfMacSchedSapProvider::SchedDlRlcBufferReqParameters i, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters j)
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
set the user part of the FfMacSchedSap that this Scheduler will interact with.
std::vector< struct UlDciListElement_s > m_dciList
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
See section 4.3.10 buildRARListElement.
virtual void SchedUlCqiInfoReq(const struct SchedUlCqiInfoReqParameters &params)
Parameters of the CSCHED_UE_CONFIG_UPDATE_IND primitive.
FfMacCschedSapProvider * m_cschedSapProvider
Parameters of the CSCHED_LC_RELEASE_REQ primitive.
void DoCschedLcConfigReq(const struct FfMacCschedSapProvider::CschedLcConfigReqParameters &params)
void DoCschedUeConfigReq(const struct FfMacCschedSapProvider::CschedUeConfigReqParameters &params)
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
FfMacSchedSapUser * m_schedSapUser
Parameters of the SCHED_DL_TRIGGER_REQ primitive.
virtual ~RrFfMacScheduler()
Destructor.
friend class RrSchedulerMemberSchedSapProvider
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
static const int Type0AllocationRbg[4]
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
std::map< uint16_t, DlHarqRlcPduListBuffer_t > m_dlHarqProcessesRlcPduListBuffer
std::vector< RlcPduList_t > DlHarqRlcPduListBuffer_t
Parameters of the SCHED_DL_MAC_BUFFER_REQ primitive.
virtual void CschedUeReleaseReq(const struct CschedUeReleaseReqParameters &params)
Parameters of the SCHED_DL_PAGING_BUFFER_REQ primitive.
std::map< uint16_t, uint8_t > m_p10CqiRxed
virtual void CschedUeConfigUpdateInd(const struct CschedUeConfigUpdateIndParameters &params)=0
std::vector< struct VendorSpecificListElement_s > m_vendorSpecificList
virtual LteFfrSapUser * GetLteFfrSapUser()
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
Service Access Point (SAP) offered by the Frequency Reuse algorithm instance to the MAC Scheduler ins...
Definition: lte-ffr-sap.h:39
Parameters of the SCHED_UL_TRIGGER_REQ primitive.
Hold an unsigned integer type.
Definition: uinteger.h:44
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
static uint8_t TxMode2LayerNum(uint8_t txMode)
Definition: lte-common.cc:169
LteFfrSapUser * m_ffrSapUser
std::vector< uint8_t > m_ndi
Definition: ff-mac-common.h:96
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
set the user part of the FfMacCschedSap that this Scheduler will interact with.
std::map< uint16_t, std::vector< uint16_t > > m_allocationMaps
FfMacCschedSapUser * m_cschedSapUser
void DoSchedDlRlcBufferReq(const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
std::map< uint16_t, UlHarqProcessesDciBuffer_t > m_ulHarqProcessesDciBuffer
Provides the SCHED SAP.
std::map< uint16_t, uint32_t > m_p10CqiTimers
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
void DoSchedUlCqiInfoReq(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
virtual void CschedUeConfigCnf(const struct CschedUeConfigCnfParameters &params)=0
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
Parameters of the SCHED_UL_NOISE_INTERFERENCE_REQ primitive.
std::vector< struct CqiListElement_s > m_cqiList
std::vector< struct DlInfoListElement_s > m_dlInfoList
virtual void SetLteFfrSapProvider(LteFfrSapProvider *s)
Set the Provider part of the LteFfrSap that this Scheduler will interact with.
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
void DoSchedUlSrInfoReq(const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters &params)
virtual void SchedDlConfigInd(const struct SchedDlConfigIndParameters &params)=0
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
void DoSchedUlMacCtrlInfoReq(const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters &params)
std::vector< uint16_t > m_tbsSize
Definition: ff-mac-common.h:94
See section 4.3.9 rlcPDU_ListElement.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool m_harqOn
m_harqOn when false inhibit te HARQ mechanisms (by default active)
int GetRbgSize(int dlbandwidth)
std::list< FfMacSchedSapProvider::SchedDlRlcBufferReqParameters > m_rlcBufferReq
virtual void SchedUlNoiseInterferenceReq(const struct SchedUlNoiseInterferenceReqParameters &params)
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
virtual void CschedUeConfigReq(const struct CschedUeConfigReqParameters &params)
std::map< uint16_t, std::vector< double > > m_ueCqi
std::vector< DlDciListElement_s > DlHarqProcessesDciBuffer_t
Parameters of the CSCHED_LC_CONFIG_REQ primitive.
virtual void SchedDlRlcBufferReq(const struct SchedDlRlcBufferReqParameters &params)
void DoSchedUlNoiseInterferenceReq(const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters &params)
std::vector< uint8_t > m_rv
Definition: ff-mac-common.h:97
virtual void SchedUlConfigInd(const struct SchedUlConfigIndParameters &params)=0
std::map< uint16_t, UlHarqProcessesStatus_t > m_ulHarqProcessesStatus
virtual void SchedDlTriggerReq(const struct SchedDlTriggerReqParameters &params)
UlCqiFilter_t m_ulCqiFilter
LteFfrSapProvider * m_ffrSapProvider
void DoCschedLcReleaseReq(const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters &params)
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
#define SRS_CQI_RNTI_VSP
This abstract base class identifies the interface by means of which the helper object can plug on the...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct MacCeListElement_s > m_macCeList
std::vector< struct RachListElement_s > m_rachList
static double fpS11dot3toDouble(uint16_t val)
Definition: lte-common.cc:113
virtual void SchedUlSrInfoReq(const struct SchedUlSrInfoReqParameters &params)
FfMacSchedSapProvider * m_schedSapProvider
Implements the SCHED SAP and CSCHED SAP for a Round Robin scheduler.
std::vector< uint8_t > UlHarqProcessesStatus_t
std::vector< uint8_t > DlHarqProcessesStatus_t
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
virtual void SchedDlMacBufferReq(const struct SchedDlMacBufferReqParameters &params)
static uint32_t BsrId2BufferSize(uint8_t val)
Definition: lte-common.cc:141
virtual void CschedLcReleaseReq(const struct CschedLcReleaseReqParameters &params)
std::map< uint16_t, DlHarqProcessesDciBuffer_t > m_dlHarqProcessesDciBuffer
std::vector< struct RachListElement_s > m_rachList
void UpdateDlRlcBufferInfo(uint16_t rnti, uint8_t lcid, uint16_t size)
std::map< uint16_t, DlHarqProcessesTimer_t > m_dlHarqProcessesTimer
std::map< uint16_t, uint8_t > m_dlHarqCurrentProcessId
Parameters of the SCHED_UL_MAC_CTRL_INFO_REQ primitive.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
virtual void SchedUlTriggerReq(const struct SchedUlTriggerReqParameters &params)
Parameters of the SCHED_UL_SR_INFO_REQ primitive.
void DoSchedDlCqiInfoReq(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:220
void TransmissionModeConfigurationUpdate(uint16_t rnti, uint8_t txMode)
Parameters of the SCHED_DL_RACH_INFO_REQ primitive.
Parameters of the SCHED_UL_CONFIG_IND primitive.
void DoSchedDlMacBufferReq(const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters &params)
Parameters of the CSCHED_UE_CONFIG_REQ primitive.
virtual void DoDispose(void)
Destructor implementation.
#define HARQ_DL_TIMEOUT
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
std::map< uint16_t, uint32_t > m_ceBsrRxed
struct DlDciListElement_s m_dci
std::vector< struct BuildRarListElement_s > m_buildRarList
std::vector< uint16_t > m_rachAllocationMap
virtual void SchedDlRachInfoReq(const struct SchedDlRachInfoReqParameters &params)
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
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
virtual void CschedLcConfigReq(const struct CschedLcConfigReqParameters &params)
#define HARQ_PROC_NUM
std::map< uint16_t, uint8_t > m_uesTxMode
virtual void CschedCellConfigReq(const struct CschedCellConfigReqParameters &params)
CSCHED_CELL_CONFIG_REQ.
std::vector< struct BuildDataListElement_s > m_buildDataList
void DoSchedUlTriggerReq(const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters &params)
See section 4.3.8 builDataListElement.