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  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1063  {
1064  if ((*it).m_rnti == m_nextRntiDl)
1065  {
1066  break;
1067  }
1068  }
1069 
1070  if (it == m_rlcBufferReq.end ())
1071  {
1072  NS_LOG_ERROR (this << " no user found");
1073  }
1074  }
1075  else
1076  {
1077  it = m_rlcBufferReq.begin ();
1078  m_nextRntiDl = (*it).m_rnti;
1079  }
1080  std::map <uint16_t,uint8_t>::iterator itTxMode;
1081  do
1082  {
1083  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
1084  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
1085  if ((itLcRnti == lcActivesPerRnti.end ())||(itRnti != rntiAllocated.end ()))
1086  {
1087  // skip this RNTI (no active queue or yet allocated for HARQ)
1088  uint16_t rntiDiscared = (*it).m_rnti;
1089  while (it != m_rlcBufferReq.end ())
1090  {
1091  if ((*it).m_rnti != rntiDiscared)
1092  {
1093  break;
1094  }
1095  it++;
1096  }
1097  if (it == m_rlcBufferReq.end ())
1098  {
1099  // restart from the first
1100  it = m_rlcBufferReq.begin ();
1101  }
1102  continue;
1103  }
1104  itTxMode = m_uesTxMode.find ((*it).m_rnti);
1105  if (itTxMode == m_uesTxMode.end ())
1106  {
1107  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).m_rnti);
1108  }
1109  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1110  int lcNum = (*itLcRnti).second;
1111  // create new BuildDataListElement_s for this RNTI
1112  BuildDataListElement_s newEl;
1113  newEl.m_rnti = (*it).m_rnti;
1114  // create the DlDciListElement_s
1115  DlDciListElement_s newDci;
1116  newDci.m_rnti = (*it).m_rnti;
1117  newDci.m_harqProcess = UpdateHarqProcessId ((*it).m_rnti);
1118  newDci.m_resAlloc = 0;
1119  newDci.m_rbBitmap = 0;
1120  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find (newEl.m_rnti);
1121  for (uint8_t i = 0; i < nLayer; i++)
1122  {
1123  if (itCqi == m_p10CqiRxed.end ())
1124  {
1125  newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS
1126  }
1127  else
1128  {
1129  newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) );
1130  }
1131  }
1132  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
1133  uint16_t rlcPduSize = tbSize / lcNum;
1134  while ((*it).m_rnti == newEl.m_rnti)
1135  {
1136  if ( ((*it).m_rlcTransmissionQueueSize > 0)
1137  || ((*it).m_rlcRetransmissionQueueSize > 0)
1138  || ((*it).m_rlcStatusPduSize > 0) )
1139  {
1140  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1141  for (uint8_t j = 0; j < nLayer; j++)
1142  {
1143  RlcPduListElement_s newRlcEl;
1144  newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
1145  NS_LOG_INFO (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
1146  newRlcEl.m_size = rlcPduSize;
1147  UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
1148  newRlcPduLe.push_back (newRlcEl);
1149 
1150  if (m_harqOn == true)
1151  {
1152  // store RLC PDU list for HARQ
1153  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*it).m_rnti);
1154  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1155  {
1156  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*it).m_rnti);
1157  }
1158  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1159  }
1160 
1161  }
1162  newEl.m_rlcPduList.push_back (newRlcPduLe);
1163  lcNum--;
1164  }
1165  it++;
1166  if (it == m_rlcBufferReq.end ())
1167  {
1168  // restart from the first
1169  it = m_rlcBufferReq.begin ();
1170  break;
1171  }
1172  }
1173  uint32_t rbgMask = 0;
1174  uint16_t i = 0;
1175  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);
1176  NS_LOG_INFO ("RBG:");
1177  while (i < rbgPerTb)
1178  {
1179  if (rbgMap.at (rbgAllocated) == false)
1180  {
1181  rbgMask = rbgMask + (0x1 << rbgAllocated);
1182  NS_LOG_INFO ("\t " << rbgAllocated);
1183  i++;
1184  rbgMap.at (rbgAllocated) = true;
1185  rbgAllocatedNum++;
1186  }
1187  rbgAllocated++;
1188  }
1189  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1190 
1191  for (int i = 0; i < nLayer; i++)
1192  {
1193  newDci.m_tbsSize.push_back (tbSize);
1194  newDci.m_ndi.push_back (1);
1195  newDci.m_rv.push_back (0);
1196  }
1197 
1198  newDci.m_tpc = 1; //1 is mapped to 0 in Accumulated Mode and to -1 in Absolute Mode
1199 
1200  newEl.m_dci = newDci;
1201  if (m_harqOn == true)
1202  {
1203  // store DCI for HARQ
1204  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1205  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1206  {
1207  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1208  }
1209  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1210  // refresh timer
1211  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1212  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1213  {
1214  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1215  }
1216  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1217  }
1218  // ...more parameters -> ignored in this version
1219 
1220  ret.m_buildDataList.push_back (newEl);
1221  if (rbgAllocatedNum == rbgNum)
1222  {
1223  m_nextRntiDl = newEl.m_rnti; // store last RNTI served
1224  break; // no more RGB to be allocated
1225  }
1226  }
1227  while ((*it).m_rnti != m_nextRntiDl);
1228 
1229  ret.m_nrOfPdcchOfdmSymbols = 1;
1230 
1232  return;
1233 }
1234 
1235 void
1237 {
1238  NS_LOG_FUNCTION (this);
1239 
1240  m_rachList = params.m_rachList;
1241 
1242  return;
1243 }
1244 
1245 void
1247 {
1248  NS_LOG_FUNCTION (this);
1249 
1250  std::map <uint16_t,uint8_t>::iterator it;
1251  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1252  {
1253  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1254  {
1255  NS_LOG_LOGIC ("wideband CQI " << (uint32_t) params.m_cqiList.at (i).m_wbCqi.at (0) << " reported");
1256  std::map <uint16_t,uint8_t>::iterator it;
1257  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1258  it = m_p10CqiRxed.find (rnti);
1259  if (it == m_p10CqiRxed.end ())
1260  {
1261  // create the new entry
1262  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)
1263  // generate correspondent timer
1264  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1265  }
1266  else
1267  {
1268  // update the CQI value
1269  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1270  // update correspondent timer
1271  std::map <uint16_t,uint32_t>::iterator itTimers;
1272  itTimers = m_p10CqiTimers.find (rnti);
1273  (*itTimers).second = m_cqiTimersThreshold;
1274  }
1275  }
1276  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1277  {
1278  // subband CQI reporting high layer configured
1279  // Not used by RR Scheduler
1280  }
1281  else
1282  {
1283  NS_LOG_ERROR (this << " CQI type unknown");
1284  }
1285  }
1286 
1287  return;
1288 }
1289 
1290 void
1292 {
1293  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1294 
1295  RefreshUlCqiMaps ();
1296 
1297  // Generate RBs map
1299  std::vector <bool> rbMap;
1300  uint16_t rbAllocatedNum = 0;
1301  std::set <uint16_t> rntiAllocated;
1302  std::vector <uint16_t> rbgAllocationMap;
1303  // update with RACH allocation map
1304  rbgAllocationMap = m_rachAllocationMap;
1305  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1306  m_rachAllocationMap.clear ();
1308 
1309  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1310  // remove RACH allocation
1311  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1312  {
1313  if (rbgAllocationMap.at (i) != 0)
1314  {
1315  rbMap.at (i) = true;
1316  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1317  }
1318  }
1319 
1320  if (m_harqOn == true)
1321  {
1322  // Process UL HARQ feedback
1323  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1324  {
1325  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1326  {
1327  // retx correspondent block: retrieve the UL-DCI
1328  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1329  std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1330  if (itProcId == m_ulHarqCurrentProcessId.end ())
1331  {
1332  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1333  }
1334  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1335  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
1336  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1337  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1338  {
1339  NS_LOG_ERROR ("No info find in UL-HARQ buffer for UE (might change eNB) " << rnti);
1340  }
1341  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1342  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1343  if (itStat == m_ulHarqProcessesStatus.end ())
1344  {
1345  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1346  }
1347  if ((*itStat).second.at (harqId) > 3)
1348  {
1349  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1350  continue;
1351  }
1352  bool free = true;
1353  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1354  {
1355  if (rbMap.at (j) == true)
1356  {
1357  free = false;
1358  NS_LOG_INFO (this << " BUSY " << j);
1359  }
1360  }
1361  if (free)
1362  {
1363  // retx on the same RBs
1364  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1365  {
1366  rbMap.at (j) = true;
1367  rbgAllocationMap.at (j) = dci.m_rnti;
1368  NS_LOG_INFO ("\tRB " << j);
1369  rbAllocatedNum++;
1370  }
1371  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);
1372  }
1373  else
1374  {
1375  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1376  continue;
1377  }
1378  dci.m_ndi = 0;
1379  // Update HARQ buffers with new HarqId
1380  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1381  (*itStat).second.at (harqId) = 0;
1382  (*itHarq).second.at ((*itProcId).second) = dci;
1383  ret.m_dciList.push_back (dci);
1384  rntiAllocated.insert (dci.m_rnti);
1385  }
1386  }
1387  }
1388 
1389  std::map <uint16_t,uint32_t>::iterator it;
1390  int nflows = 0;
1391 
1392  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1393  {
1394  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1395  // select UEs with queues not empty and not yet allocated for HARQ
1396  NS_LOG_INFO (this << " UE " << (*it).first << " queue " << (*it).second);
1397  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1398  {
1399  nflows++;
1400  }
1401  }
1402 
1403  if (nflows == 0)
1404  {
1405  if (ret.m_dciList.size () > 0)
1406  {
1407  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1409  }
1410  return; // no flows to be scheduled
1411  }
1412 
1413 
1414  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1415  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
1416  if (rbPerFlow < 3)
1417  {
1418  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1419  }
1420  uint16_t rbAllocated = 0;
1421 
1422  if (m_nextRntiUl != 0)
1423  {
1424  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1425  {
1426  if ((*it).first == m_nextRntiUl)
1427  {
1428  break;
1429  }
1430  }
1431  if (it == m_ceBsrRxed.end ())
1432  {
1433  NS_LOG_ERROR (this << " no user found");
1434  }
1435  }
1436  else
1437  {
1438  it = m_ceBsrRxed.begin ();
1439  m_nextRntiUl = (*it).first;
1440  }
1441  NS_LOG_INFO (this << " NFlows " << nflows << " RB per Flow " << rbPerFlow);
1442  do
1443  {
1444  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1445  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1446  {
1447  // UE already allocated for UL-HARQ -> skip it
1448  it++;
1449  if (it == m_ceBsrRxed.end ())
1450  {
1451  // restart from the first
1452  it = m_ceBsrRxed.begin ();
1453  }
1454  continue;
1455  }
1456  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1457  {
1458  // limit to physical resources last resource assignment
1459  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1460  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1461  if (rbPerFlow < 3)
1462  {
1463  // terminate allocation
1464  rbPerFlow = 0;
1465  }
1466  }
1467  NS_LOG_INFO (this << " try to allocate " << (*it).first);
1468  UlDciListElement_s uldci;
1469  uldci.m_rnti = (*it).first;
1470  uldci.m_rbLen = rbPerFlow;
1471  bool allocated = false;
1472  NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1473  while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
1474  {
1475  // check availability
1476  bool free = true;
1477  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1478  {
1479  if (rbMap.at (j) == true)
1480  {
1481  free = false;
1482  break;
1483  }
1484  }
1485  if (free)
1486  {
1487  uldci.m_rbStart = rbAllocated;
1488 
1489  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1490  {
1491  rbMap.at (j) = true;
1492  // store info on allocation for managing ul-cqi interpretation
1493  rbgAllocationMap.at (j) = (*it).first;
1494  NS_LOG_INFO ("\t " << j);
1495  }
1496  rbAllocated += rbPerFlow;
1497  allocated = true;
1498  break;
1499  }
1500  rbAllocated++;
1501  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1502  {
1503  // limit to physical resources last resource assignment
1504  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1505  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1506  if (rbPerFlow < 3)
1507  {
1508  // terminate allocation
1509  rbPerFlow = 0;
1510  }
1511  }
1512  }
1513  if (!allocated)
1514  {
1515  // unable to allocate new resource: finish scheduling
1516  m_nextRntiUl = (*it).first;
1517  if (ret.m_dciList.size () > 0)
1518  {
1520  }
1521  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1522  return;
1523  }
1524  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1525  int cqi = 0;
1526  if (itCqi == m_ueCqi.end ())
1527  {
1528  // no cqi info about this UE
1529  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1530  NS_LOG_INFO (this << " UE does not have ULCQI " << (*it).first );
1531  }
1532  else
1533  {
1534  // take the lowest CQI value (worst RB)
1535  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1536  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1537  {
1538  if ((*itCqi).second.at (i) < minSinr)
1539  {
1540  minSinr = (*itCqi).second.at (i);
1541  }
1542  }
1543  // translate SINR -> cqi: WILD ACK: same as DL
1544  double s = log2 ( 1 + (
1545  std::pow (10, minSinr / 10 ) /
1546  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1547 
1548 
1549  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1550  if (cqi == 0)
1551  {
1552  it++;
1553  if (it == m_ceBsrRxed.end ())
1554  {
1555  // restart from the first
1556  it = m_ceBsrRxed.begin ();
1557  }
1558  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
1559  // remove UE from allocation map
1560  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1561  {
1562  rbgAllocationMap.at (i) = 0;
1563  }
1564  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1565  }
1566  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1567  }
1568  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD
1569 
1570  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1571  uldci.m_ndi = 1;
1572  uldci.m_cceIndex = 0;
1573  uldci.m_aggrLevel = 1;
1574  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1575  uldci.m_hopping = false;
1576  uldci.m_n2Dmrs = 0;
1577  uldci.m_tpc = 0; // no power control
1578  uldci.m_cqiRequest = false; // only period CQI at this stage
1579  uldci.m_ulIndex = 0; // TDD parameter
1580  uldci.m_dai = 1; // TDD parameter
1581  uldci.m_freqHopping = 0;
1582  uldci.m_pdcchPowerOffset = 0; // not used
1583  ret.m_dciList.push_back (uldci);
1584  // store DCI for HARQ_PERIOD
1585  uint8_t harqId = 0;
1586  if (m_harqOn == true)
1587  {
1588  std::map <uint16_t, uint8_t>::iterator itProcId;
1589  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1590  if (itProcId == m_ulHarqCurrentProcessId.end ())
1591  {
1592  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1593  }
1594  harqId = (*itProcId).second;
1595  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1596  if (itDci == m_ulHarqProcessesDciBuffer.end ())
1597  {
1598  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1599  }
1600  (*itDci).second.at (harqId) = uldci;
1601  // Update HARQ process status (RV 0)
1602  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (uldci.m_rnti);
1603  if (itStat == m_ulHarqProcessesStatus.end ())
1604  {
1605  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << uldci.m_rnti);
1606  }
1607  (*itStat).second.at (harqId) = 0;
1608  }
1609 
1610  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);
1611 
1612  it++;
1613  if (it == m_ceBsrRxed.end ())
1614  {
1615  // restart from the first
1616  it = m_ceBsrRxed.begin ();
1617  }
1618  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1619  {
1620  // Stop allocation: no more PRBs
1621  m_nextRntiUl = (*it).first;
1622  break;
1623  }
1624  }
1625  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1626 
1627  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1628 
1630  return;
1631 }
1632 
1633 void
1635 {
1636  NS_LOG_FUNCTION (this);
1637  return;
1638 }
1639 
1640 void
1642 {
1643  NS_LOG_FUNCTION (this);
1644  return;
1645 }
1646 
1647 void
1649 {
1650  NS_LOG_FUNCTION (this);
1651 
1652  std::map <uint16_t,uint32_t>::iterator it;
1653 
1654  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1655  {
1656  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1657  {
1658  // buffer status report
1659  // note that this scheduler does not differentiate the
1660  // allocation according to which LCGs have more/less bytes
1661  // to send.
1662  // Hence the BSR of different LCGs are just summed up to get
1663  // a total queue size that is used for allocation purposes.
1664 
1665  uint32_t buffer = 0;
1666  for (uint8_t lcg = 0; lcg < 4; ++lcg)
1667  {
1668  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1669  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1670  }
1671 
1672  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1673  it = m_ceBsrRxed.find (rnti);
1674  if (it == m_ceBsrRxed.end ())
1675  {
1676  // create the new entry
1677  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1678  NS_LOG_INFO (this << " Insert RNTI " << rnti << " queue " << buffer);
1679  }
1680  else
1681  {
1682  // update the buffer size value
1683  (*it).second = buffer;
1684  NS_LOG_INFO (this << " Update RNTI " << rnti << " queue " << buffer);
1685  }
1686  }
1687  }
1688 
1689  return;
1690 }
1691 
1692 void
1694 {
1695  NS_LOG_FUNCTION (this);
1696 
1697  switch (m_ulCqiFilter)
1698  {
1700  {
1701  // filter all the CQIs that are not SRS based
1702  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
1703  {
1704  return;
1705  }
1706  }
1707  break;
1709  {
1710  // filter all the CQIs that are not SRS based
1711  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
1712  {
1713  return;
1714  }
1715  }
1717  break;
1718 
1719  default:
1720  NS_FATAL_ERROR ("Unknown UL CQI type");
1721  }
1722  switch (params.m_ulCqi.m_type)
1723  {
1724  case UlCqi_s::PUSCH:
1725  {
1726  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1727  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1728  itMap = m_allocationMaps.find (params.m_sfnSf);
1729  if (itMap == m_allocationMaps.end ())
1730  {
1731  NS_LOG_INFO (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1732  return;
1733  }
1734  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1735  {
1736  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1737  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1738  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1739  if (itCqi == m_ueCqi.end ())
1740  {
1741  // create a new entry
1742  std::vector <double> newCqi;
1743  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1744  {
1745  if (i == j)
1746  {
1747  newCqi.push_back (sinr);
1748  }
1749  else
1750  {
1751  // initialize with NO_SINR value.
1752  newCqi.push_back (30.0);
1753  }
1754 
1755  }
1756  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1757  // generate correspondent timer
1758  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1759  }
1760  else
1761  {
1762  // update the value
1763  (*itCqi).second.at (i) = sinr;
1764  // update correspondent timer
1765  std::map <uint16_t, uint32_t>::iterator itTimers;
1766  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1767  (*itTimers).second = m_cqiTimersThreshold;
1768 
1769  }
1770 
1771  }
1772  // remove obsolete info on allocation
1773  m_allocationMaps.erase (itMap);
1774  }
1775  break;
1776  case UlCqi_s::SRS:
1777  {
1778  // get the RNTI from vendor specific parameters
1779  uint16_t rnti = 0;
1780  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1781  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1782  {
1783  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1784  {
1785  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1786  rnti = vsp->GetRnti ();
1787  }
1788  }
1789  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1790  itCqi = m_ueCqi.find (rnti);
1791  if (itCqi == m_ueCqi.end ())
1792  {
1793  // create a new entry
1794  std::vector <double> newCqi;
1795  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1796  {
1797  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1798  newCqi.push_back (sinr);
1799  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1800 
1801  }
1802  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1803  // generate correspondent timer
1804  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1805  }
1806  else
1807  {
1808  // update the values
1809  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1810  {
1811  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1812  (*itCqi).second.at (j) = sinr;
1813  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1814  }
1815  // update correspondent timer
1816  std::map <uint16_t, uint32_t>::iterator itTimers;
1817  itTimers = m_ueCqiTimers.find (rnti);
1818  (*itTimers).second = m_cqiTimersThreshold;
1819 
1820  }
1821 
1822 
1823  }
1824  break;
1825  case UlCqi_s::PUCCH_1:
1826  case UlCqi_s::PUCCH_2:
1827  case UlCqi_s::PRACH:
1828  {
1829  NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1830  }
1831  break;
1832  default:
1833  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1834  }
1835  return;
1836 }
1837 
1838 
1839 void
1841 {
1842  NS_LOG_FUNCTION (this << m_p10CqiTimers.size ());
1843  // refresh DL CQI P01 Map
1844  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1845  while (itP10 != m_p10CqiTimers.end ())
1846  {
1847  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1848  if ((*itP10).second == 0)
1849  {
1850  // delete correspondent entries
1851  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1852  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1853  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1854  m_p10CqiRxed.erase (itMap);
1855  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1856  itP10++;
1857  m_p10CqiTimers.erase (temp);
1858  }
1859  else
1860  {
1861  (*itP10).second--;
1862  itP10++;
1863  }
1864  }
1865 
1866  return;
1867 }
1868 
1869 
1870 void
1872 {
1873  // refresh UL CQI Map
1874  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1875  while (itUl != m_ueCqiTimers.end ())
1876  {
1877  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1878  if ((*itUl).second == 0)
1879  {
1880  // delete correspondent entries
1881  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1882  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1883  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1884  (*itMap).second.clear ();
1885  m_ueCqi.erase (itMap);
1886  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1887  itUl++;
1888  m_ueCqiTimers.erase (temp);
1889  }
1890  else
1891  {
1892  (*itUl).second--;
1893  itUl++;
1894  }
1895  }
1896 
1897  return;
1898 }
1899 
1900 void
1901 RrFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1902 {
1903  NS_LOG_FUNCTION (this);
1904  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1905  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1906  {
1907  if (((*it).m_rnti == rnti) && ((*it).m_logicalChannelIdentity == lcid))
1908  {
1909  NS_LOG_INFO (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).m_rlcTransmissionQueueSize << " retxqueue " << (*it).m_rlcRetransmissionQueueSize << " status " << (*it).m_rlcStatusPduSize << " decrease " << size);
1910  // Update queues: RLC tx order Status, ReTx, Tx
1911  // Update status queue
1912  if (((*it).m_rlcStatusPduSize > 0) && (size >= (*it).m_rlcStatusPduSize))
1913  {
1914  (*it).m_rlcStatusPduSize = 0;
1915  }
1916  else if (((*it).m_rlcRetransmissionQueueSize > 0) && (size >= (*it).m_rlcRetransmissionQueueSize))
1917  {
1918  (*it).m_rlcRetransmissionQueueSize = 0;
1919  }
1920  else if ((*it).m_rlcTransmissionQueueSize > 0)
1921  {
1922  uint32_t rlcOverhead;
1923  if (lcid == 1)
1924  {
1925  // for SRB1 (using RLC AM) it's better to
1926  // overestimate RLC overhead rather than
1927  // underestimate it and risk unneeded
1928  // segmentation which increases delay
1929  rlcOverhead = 4;
1930  }
1931  else
1932  {
1933  // minimum RLC overhead due to header
1934  rlcOverhead = 2;
1935  }
1936  // update transmission queue
1937  if ((*it).m_rlcTransmissionQueueSize <= size - rlcOverhead)
1938  {
1939  (*it).m_rlcTransmissionQueueSize = 0;
1940  }
1941  else
1942  {
1943  (*it).m_rlcTransmissionQueueSize -= size - rlcOverhead;
1944  }
1945  }
1946  return;
1947  }
1948  }
1949 }
1950 
1951 void
1952 RrFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1953 {
1954 
1955  size = size - 2; // remove the minimum RLC overhead
1956  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1957  if (it != m_ceBsrRxed.end ())
1958  {
1959  NS_LOG_INFO (this << " Update RLC BSR UE " << rnti << " size " << size << " BSR " << (*it).second);
1960  if ((*it).second >= size)
1961  {
1962  (*it).second -= size;
1963  }
1964  else
1965  {
1966  (*it).second = 0;
1967  }
1968  }
1969  else
1970  {
1971  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1972  }
1973 
1974 }
1975 
1976 
1977 void
1979 {
1980  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1982  params.m_rnti = rnti;
1983  params.m_transmissionMode = txMode;
1985 }
1986 
1987 
1988 
1989 }
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:145
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:826
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.