A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 NS_LOG_COMPONENT_DEFINE ("RrFfMacScheduler");
36 
37 namespace ns3 {
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  .AddConstructor<RrFfMacScheduler> ()
255  .AddAttribute ("CqiTimerThreshold",
256  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
257  UintegerValue (1000),
258  MakeUintegerAccessor (&RrFfMacScheduler::m_cqiTimersThreshold),
259  MakeUintegerChecker<uint32_t> ())
260  .AddAttribute ("HarqEnabled",
261  "Activate/Deactivate the HARQ [by default is active].",
262  BooleanValue (true),
263  MakeBooleanAccessor (&RrFfMacScheduler::m_harqOn),
264  MakeBooleanChecker ())
265  .AddAttribute ("UlGrantMcs",
266  "The MCS of the UL grant, must be [0..15] (default 0)",
267  UintegerValue (0),
268  MakeUintegerAccessor (&RrFfMacScheduler::m_ulGrantMcs),
269  MakeUintegerChecker<uint8_t> ())
270  ;
271  return tid;
272 }
273 
274 
275 
276 void
278 {
279  m_cschedSapUser = s;
280 }
281 
282 void
284 {
285  m_schedSapUser = s;
286 }
287 
290 {
291  return m_cschedSapProvider;
292 }
293 
296 {
297  return m_schedSapProvider;
298 }
299 
300 void
302 {
303  NS_LOG_FUNCTION (this);
304  // Read the subset of parameters used
305  m_cschedCellConfig = params;
308  cnf.m_result = SUCCESS;
310  return;
311 }
312 
313 void
315 {
316  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
317  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
318  if (it == m_uesTxMode.end ())
319  {
320  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
321  // generate HARQ buffers
322  m_dlHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
323  DlHarqProcessesStatus_t dlHarqPrcStatus;
324  dlHarqPrcStatus.resize (8,0);
325  m_dlHarqProcessesStatus.insert (std::pair <uint16_t, DlHarqProcessesStatus_t> (params.m_rnti, dlHarqPrcStatus));
326  DlHarqProcessesTimer_t dlHarqProcessesTimer;
327  dlHarqProcessesTimer.resize (8,0);
328  m_dlHarqProcessesTimer.insert (std::pair <uint16_t, DlHarqProcessesTimer_t> (params.m_rnti, dlHarqProcessesTimer));
329  DlHarqProcessesDciBuffer_t dlHarqdci;
330  dlHarqdci.resize (8);
331  m_dlHarqProcessesDciBuffer.insert (std::pair <uint16_t, DlHarqProcessesDciBuffer_t> (params.m_rnti, dlHarqdci));
332  DlHarqRlcPduListBuffer_t dlHarqRlcPdu;
333  dlHarqRlcPdu.resize (2);
334  dlHarqRlcPdu.at (0).resize (8);
335  dlHarqRlcPdu.at (1).resize (8);
336  m_dlHarqProcessesRlcPduListBuffer.insert (std::pair <uint16_t, DlHarqRlcPduListBuffer_t> (params.m_rnti, dlHarqRlcPdu));
337  m_ulHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
338  UlHarqProcessesStatus_t ulHarqPrcStatus;
339  ulHarqPrcStatus.resize (8,0);
340  m_ulHarqProcessesStatus.insert (std::pair <uint16_t, UlHarqProcessesStatus_t> (params.m_rnti, ulHarqPrcStatus));
341  UlHarqProcessesDciBuffer_t ulHarqdci;
342  ulHarqdci.resize (8);
343  m_ulHarqProcessesDciBuffer.insert (std::pair <uint16_t, UlHarqProcessesDciBuffer_t> (params.m_rnti, ulHarqdci));
344  }
345  else
346  {
347  (*it).second = params.m_transmissionMode;
348  }
349  return;
350 }
351 
352 void
354 {
355  NS_LOG_FUNCTION (this);
356  // Not used at this stage (LCs updated by DoSchedDlRlcBufferReq)
357  return;
358 }
359 
360 void
362 {
363  NS_LOG_FUNCTION (this);
364  for (uint16_t i = 0; i < params.m_logicalChannelIdentity.size (); i++)
365  {
366  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
367  while (it!=m_rlcBufferReq.end ())
368  {
369  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity.at (i)))
370  {
371  it = m_rlcBufferReq.erase (it);
372  }
373  else
374  {
375  it++;
376  }
377  }
378  }
379  return;
380 }
381 
382 void
384 {
385  NS_LOG_FUNCTION (this << " Release RNTI " << params.m_rnti);
386 
387  m_uesTxMode.erase (params.m_rnti);
388  m_dlHarqCurrentProcessId.erase (params.m_rnti);
389  m_dlHarqProcessesStatus.erase (params.m_rnti);
390  m_dlHarqProcessesTimer.erase (params.m_rnti);
391  m_dlHarqProcessesDciBuffer.erase (params.m_rnti);
393  m_ulHarqCurrentProcessId.erase (params.m_rnti);
394  m_ulHarqProcessesStatus.erase (params.m_rnti);
395  m_ulHarqProcessesDciBuffer.erase (params.m_rnti);
396  m_ceBsrRxed.erase (params.m_rnti);
397  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
398  while (it != m_rlcBufferReq.end ())
399  {
400  if ((*it).m_rnti == params.m_rnti)
401  {
402  NS_LOG_INFO (this << " Erase RNTI " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
403  it = m_rlcBufferReq.erase (it);
404  }
405  else
406  {
407  it++;
408  }
409  }
410  if (m_nextRntiUl == params.m_rnti)
411  {
412  m_nextRntiUl = 0;
413  }
414 
415  if (m_nextRntiDl == params.m_rnti)
416  {
417  m_nextRntiDl = 0;
418  }
419 
420  return;
421 }
422 
423 
424 void
426 {
427  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
428  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
429  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
430  bool newLc = true;
431  while (it != m_rlcBufferReq.end ())
432  {
433  // remove old entries of this UE-LC
434  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity))
435  {
436  it = m_rlcBufferReq.erase (it);
437  newLc = false;
438  }
439  else
440  {
441  ++it;
442  }
443  }
444  // add the new parameters
445  m_rlcBufferReq.insert (it, params);
446  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);
447  // initialize statistics of the flow in case of new flows
448  if (newLc == true)
449  {
450  m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (params.m_rnti, 1)); // only codeword 0 at this stage (SISO)
451  // initialized to 1 (i.e., the lowest value for transmitting a signal)
452  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (params.m_rnti, m_cqiTimersThreshold));
453  }
454 
455  return;
456 }
457 
458 void
460 {
461  NS_LOG_FUNCTION (this);
462  NS_FATAL_ERROR ("method not implemented");
463  return;
464 }
465 
466 void
468 {
469  NS_LOG_FUNCTION (this);
470  NS_FATAL_ERROR ("method not implemented");
471  return;
472 }
473 
474 int
476 {
477  for (int i = 0; i < 4; i++)
478  {
479  if (dlbandwidth < Type0AllocationRbg[i])
480  {
481  return (i + 1);
482  }
483  }
484 
485  return (-1);
486 }
487 
488 bool
490 {
491  return (i.m_rnti < j.m_rnti);
492 }
493 
494 
495 uint8_t
497 {
498  NS_LOG_FUNCTION (this << rnti);
499 
500  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
501  if (it == m_dlHarqCurrentProcessId.end ())
502  {
503  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
504  }
505  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
506  if (itStat == m_dlHarqProcessesStatus.end ())
507  {
508  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
509  }
510  uint8_t i = (*it).second;
511  do
512  {
513  i = (i + 1) % HARQ_PROC_NUM;
514  }
515  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
516  if ((*itStat).second.at (i) == 0)
517  {
518  return (true);
519  }
520  else
521  {
522  return (false); // return a not valid harq proc id
523  }
524 }
525 
526 
527 
528 uint8_t
530 {
531  NS_LOG_FUNCTION (this << rnti);
532 
533 
534  if (m_harqOn == false)
535  {
536  return (0);
537  }
538 
539  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
540  if (it == m_dlHarqCurrentProcessId.end ())
541  {
542  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
543  }
544  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
545  if (itStat == m_dlHarqProcessesStatus.end ())
546  {
547  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
548  }
549  uint8_t i = (*it).second;
550  do
551  {
552  i = (i + 1) % HARQ_PROC_NUM;
553  }
554  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
555  if ((*itStat).second.at (i) == 0)
556  {
557  (*it).second = i;
558  (*itStat).second.at (i) = 1;
559  }
560  else
561  {
562  return (9); // return a not valid harq proc id
563  }
564 
565  return ((*it).second);
566 }
567 
568 
569 void
571 {
572  NS_LOG_FUNCTION (this);
573 
574  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
575  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers ++)
576  {
577  for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
578  {
579  if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
580  {
581  // reset HARQ process
582 
583  NS_LOG_INFO (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
584  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
585  if (itStat == m_dlHarqProcessesStatus.end ())
586  {
587  NS_FATAL_ERROR ("No Process Id Status found for this RNTI " << (*itTimers).first);
588  }
589  (*itStat).second.at (i) = 0;
590  (*itTimers).second.at (i) = 0;
591  }
592  else
593  {
594  (*itTimers).second.at (i)++;
595  }
596  }
597  }
598 
599 }
600 
601 
602 
603 void
605 {
606  NS_LOG_FUNCTION (this << " DL Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
607  // API generated by RLC for triggering the scheduling of a DL subframe
608 
609  RefreshDlCqiMaps ();
611  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
613 
614  // Generate RBGs map
615  std::vector <bool> rbgMap;
616  uint16_t rbgAllocatedNum = 0;
617  std::set <uint16_t> rntiAllocated;
618  rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
619 
620  // update UL HARQ proc id
621  std::map <uint16_t, uint8_t>::iterator itProcId;
622  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
623  {
624  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
625  }
626 
627  // RACH Allocation
629  uint16_t rbStart = 0;
630  std::vector <struct RachListElement_s>::iterator itRach;
631  for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
632  {
633  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");
634  BuildRarListElement_s newRar;
635  newRar.m_rnti = (*itRach).m_rnti;
636  // DL-RACH Allocation
637  // Ideal: no needs of configuring m_dci
638  // UL-RACH Allocation
639  newRar.m_grant.m_rnti = newRar.m_rnti;
640  newRar.m_grant.m_mcs = m_ulGrantMcs;
641  uint16_t rbLen = 1;
642  uint16_t tbSizeBits = 0;
643  // find lowest TB size that fits UL grant estimated size
644  while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
645  {
646  rbLen++;
647  tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
648  }
649  if (tbSizeBits < (*itRach).m_estimatedSize)
650  {
651  // no more allocation space: finish allocation
652  break;
653  }
654  newRar.m_grant.m_rbStart = rbStart;
655  newRar.m_grant.m_rbLen = rbLen;
656  newRar.m_grant.m_tbSize = tbSizeBits / 8;
657  newRar.m_grant.m_hopping = false;
658  newRar.m_grant.m_tpc = 0;
659  newRar.m_grant.m_cqiRequest = false;
660  newRar.m_grant.m_ulDelay = false;
661  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);
662  for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
663  {
664  m_rachAllocationMap.at (i) = (*itRach).m_rnti;
665  }
666  rbStart = rbStart + rbLen;
667 
668  if (m_harqOn == true)
669  {
670  // generate UL-DCI for HARQ retransmissions
671  UlDciListElement_s uldci;
672  uldci.m_rnti = newRar.m_rnti;
673  uldci.m_rbLen = rbLen;
674  uldci.m_rbStart = rbStart;
675  uldci.m_mcs = m_ulGrantMcs;
676  uldci.m_tbSize = tbSizeBits / 8;
677  uldci.m_ndi = 1;
678  uldci.m_cceIndex = 0;
679  uldci.m_aggrLevel = 1;
680  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
681  uldci.m_hopping = false;
682  uldci.m_n2Dmrs = 0;
683  uldci.m_tpc = 0; // no power control
684  uldci.m_cqiRequest = false; // only period CQI at this stage
685  uldci.m_ulIndex = 0; // TDD parameter
686  uldci.m_dai = 1; // TDD parameter
687  uldci.m_freqHopping = 0;
688  uldci.m_pdcchPowerOffset = 0; // not used
689 
690  uint8_t harqId = 0;
691  std::map <uint16_t, uint8_t>::iterator itProcId;
692  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
693  if (itProcId == m_ulHarqCurrentProcessId.end ())
694  {
695  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
696  }
697  harqId = (*itProcId).second;
698  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
699  if (itDci == m_ulHarqProcessesDciBuffer.end ())
700  {
701  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
702  }
703  (*itDci).second.at (harqId) = uldci;
704  }
705 
706  ret.m_buildRarList.push_back (newRar);
707  }
708  m_rachList.clear ();
709 
710  // Process DL HARQ feedback
712  // retrieve past HARQ retx buffered
713  if (m_dlInfoListBuffered.size () > 0)
714  {
715  if (params.m_dlInfoList.size () > 0)
716  {
717  NS_LOG_INFO (this << " Received DL-HARQ feedback");
718  m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
719  }
720  }
721  else
722  {
723  if (params.m_dlInfoList.size () > 0)
724  {
726  }
727  }
728  if (m_harqOn == false)
729  {
730  // Ignore HARQ feedback
731  m_dlInfoListBuffered.clear ();
732  }
733  std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
734  for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
735  {
736  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
737  if (itRnti != rntiAllocated.end ())
738  {
739  // RNTI already allocated for retx
740  continue;
741  }
742  uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
743  std::vector <bool> retx;
744  NS_LOG_INFO (this << " Processing DLHARQ feedback");
745  if (nLayers == 1)
746  {
747  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
748  retx.push_back (false);
749  }
750  else
751  {
752  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
753  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
754  }
755  if (retx.at (0) || retx.at (1))
756  {
757  // retrieve HARQ process information
758  uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
759  uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
760  NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
761  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
762  if (itHarq == m_dlHarqProcessesDciBuffer.end ())
763  {
764  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
765  }
766 
767  DlDciListElement_s dci = (*itHarq).second.at (harqId);
768  int rv = 0;
769  if (dci.m_rv.size () == 1)
770  {
771  rv = dci.m_rv.at (0);
772  }
773  else
774  {
775  rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
776  }
777 
778  if (rv == 3)
779  {
780  // maximum number of retx reached -> drop process
781  NS_LOG_INFO ("Max number of retransmissions reached -> drop process");
782  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
783  if (it == m_dlHarqProcessesStatus.end ())
784  {
785  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
786  }
787  (*it).second.at (harqId) = 0;
788  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
789  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
790  {
791  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
792  }
793  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
794  {
795  (*itRlcPdu).second.at (k).at (harqId).clear ();
796  }
797  continue;
798  }
799  // check the feasibility of retransmitting on the same RBGs
800  // translate the DCI to Spectrum framework
801  std::vector <int> dciRbg;
802  uint32_t mask = 0x1;
803  NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
804  for (int j = 0; j < 32; j++)
805  {
806  if (((dci.m_rbBitmap & mask) >> j) == 1)
807  {
808  dciRbg.push_back (j);
809  NS_LOG_INFO ("\t" << j);
810  }
811  mask = (mask << 1);
812  }
813  bool free = true;
814  for (uint8_t j = 0; j < dciRbg.size (); j++)
815  {
816  if (rbgMap.at (dciRbg.at (j)) == true)
817  {
818  free = false;
819  break;
820  }
821  }
822  if (free)
823  {
824  // use the same RBGs for the retx
825  // reserve RBGs
826  for (uint8_t j = 0; j < dciRbg.size (); j++)
827  {
828  rbgMap.at (dciRbg.at (j)) = true;
829  NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
830  rbgAllocatedNum++;
831  }
832 
833  NS_LOG_INFO (this << " Send retx in the same RBGs");
834  }
835  else
836  {
837  // find RBGs for sending HARQ retx
838  uint8_t j = 0;
839  uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % rbgNum;
840  uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
841  std::vector <bool> rbgMapCopy = rbgMap;
842  while ((j < dciRbg.size ())&&(startRbg != rbgId))
843  {
844  if (rbgMapCopy.at (rbgId) == false)
845  {
846  rbgMapCopy.at (rbgId) = true;
847  dciRbg.at (j) = rbgId;
848  j++;
849  }
850  rbgId++;
851  }
852  if (j == dciRbg.size ())
853  {
854  // find new RBGs -> update DCI map
855  uint32_t rbgMask = 0;
856  for (uint16_t k = 0; k < dciRbg.size (); k++)
857  {
858  rbgMask = rbgMask + (0x1 << dciRbg.at (k));
859  NS_LOG_INFO (this << " New allocated RBG " << dciRbg.at (k));
860  rbgAllocatedNum++;
861  }
862  dci.m_rbBitmap = rbgMask;
863  rbgMap = rbgMapCopy;
864  }
865  else
866  {
867  // HARQ retx cannot be performed on this TTI -> store it
868  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
869  NS_LOG_INFO (this << " No resource for this retx -> buffer it");
870  }
871  }
872  // retrieve RLC PDU list for retx TBsize and update DCI
874  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
875  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
876  {
877  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
878  }
879  for (uint8_t j = 0; j < nLayers; j++)
880  {
881  if (retx.at (j))
882  {
883  if (j >= dci.m_ndi.size ())
884  {
885  // for avoiding errors in MIMO transient phases
886  dci.m_ndi.push_back (0);
887  dci.m_rv.push_back (0);
888  dci.m_mcs.push_back (0);
889  dci.m_tbsSize.push_back (0);
890  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
891 
892  }
893  else
894  {
895  dci.m_ndi.at (j) = 0;
896  dci.m_rv.at (j)++;
897  (*itHarq).second.at (harqId).m_rv.at (j)++;
898  NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
899  }
900  }
901  else
902  {
903  // empty TB of layer j
904  dci.m_ndi.at (j) = 0;
905  dci.m_rv.at (j) = 0;
906  dci.m_mcs.at (j) = 0;
907  dci.m_tbsSize.at (j) = 0;
908  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
909  }
910  }
911 
912  for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
913  {
914  std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
915  for (uint8_t j = 0; j < nLayers; j++)
916  {
917  if (retx.at (j))
918  {
919  if (j < dci.m_ndi.size ())
920  {
921  rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
922  }
923  }
924  }
925 
926  if (rlcPduListPerLc.size () > 0)
927  {
928  newEl.m_rlcPduList.push_back (rlcPduListPerLc);
929  }
930  }
931  newEl.m_rnti = rnti;
932  newEl.m_dci = dci;
933  (*itHarq).second.at (harqId).m_rv = dci.m_rv;
934  // refresh timer
935  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
936  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
937  {
938  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
939  }
940  (*itHarqTimer).second.at (harqId) = 0;
941  ret.m_buildDataList.push_back (newEl);
942  rntiAllocated.insert (rnti);
943  }
944  else
945  {
946  // update HARQ process status
947  NS_LOG_INFO (this << " HARQ ACK UE " << m_dlInfoListBuffered.at (i).m_rnti);
948  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
949  if (it == m_dlHarqProcessesStatus.end ())
950  {
951  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
952  }
953  (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
954  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
955  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
956  {
957  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
958  }
959  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
960  {
961  (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
962  }
963  }
964  }
965  m_dlInfoListBuffered.clear ();
966  m_dlInfoListBuffered = dlInfoListUntxed;
967 
968  if (rbgAllocatedNum == rbgNum)
969  {
970  // all the RBGs are already allocated -> exit
971  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
972  {
974  }
975  return;
976  }
977 
978  // Get the actual active flows (queue!=0)
979  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
981  int nflows = 0;
982  int nTbs = 0;
983  std::map <uint16_t,uint8_t> lcActivesPerRnti; // tracks how many active LCs per RNTI there are
984  std::map <uint16_t,uint8_t>::iterator itLcRnti;
985  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
986  {
987  // remove old entries of this UE-LC
988  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
989  if ( (((*it).m_rlcTransmissionQueueSize > 0)
990  || ((*it).m_rlcRetransmissionQueueSize > 0)
991  || ((*it).m_rlcStatusPduSize > 0))
992  && (itRnti == rntiAllocated.end ()) // UE must not be allocated for HARQ retx
993  && (HarqProcessAvailability ((*it).m_rnti)) ) // UE needs HARQ proc free
994 
995  {
996  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);
997  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find ((*it).m_rnti);
998  uint8_t cqi = 0;
999  if (itCqi != m_p10CqiRxed.end ())
1000  {
1001  cqi = (*itCqi).second;
1002  }
1003  else
1004  {
1005  cqi = 1; // lowest value fro trying a transmission
1006  }
1007  if (cqi != 0)
1008  {
1009  // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1010  nflows++;
1011  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
1012  if (itLcRnti != lcActivesPerRnti.end ())
1013  {
1014  (*itLcRnti).second++;
1015  }
1016  else
1017  {
1018  lcActivesPerRnti.insert (std::pair<uint16_t, uint8_t > ((*it).m_rnti, 1));
1019  nTbs++;
1020  }
1021 
1022  }
1023  }
1024  }
1025 
1026  if (nflows == 0)
1027  {
1028  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
1029  {
1031  }
1032  return;
1033  }
1034  // Divide the resource equally among the active users according to
1035  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
1036 
1037  int rbgPerTb = (nTbs > 0) ? ((rbgNum - rbgAllocatedNum) / nTbs) : INT_MAX;
1038  NS_LOG_INFO (this << " Flows to be transmitted " << nflows << " rbgPerTb " << rbgPerTb);
1039  if (rbgPerTb == 0)
1040  {
1041  rbgPerTb = 1; // at least 1 rbg per TB (till available resource)
1042  }
1043  int rbgAllocated = 0;
1044 
1045  // round robin assignment to all UEs registered starting from the subsequent of the one
1046  // served last scheduling trigger event
1047  if (m_nextRntiDl != 0)
1048  {
1049  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1050  {
1051  if ((*it).m_rnti == m_nextRntiDl)
1052  {
1053  break;
1054  }
1055  }
1056 
1057  if (it == m_rlcBufferReq.end ())
1058  {
1059  NS_LOG_ERROR (this << " no user found");
1060  }
1061  }
1062  else
1063  {
1064  it = m_rlcBufferReq.begin ();
1065  m_nextRntiDl = (*it).m_rnti;
1066  }
1067  std::map <uint16_t,uint8_t>::iterator itTxMode;
1068  do
1069  {
1070  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
1071  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
1072  if ((itLcRnti == lcActivesPerRnti.end ())||(itRnti != rntiAllocated.end ()))
1073  {
1074  // skip this RNTI (no active queue or yet allocated for HARQ)
1075  uint16_t rntiDiscared = (*it).m_rnti;
1076  while (it != m_rlcBufferReq.end ())
1077  {
1078  if ((*it).m_rnti != rntiDiscared)
1079  {
1080  break;
1081  }
1082  it++;
1083  }
1084  if (it == m_rlcBufferReq.end ())
1085  {
1086  // restart from the first
1087  it = m_rlcBufferReq.begin ();
1088  }
1089  continue;
1090  }
1091  itTxMode = m_uesTxMode.find ((*it).m_rnti);
1092  if (itTxMode == m_uesTxMode.end ())
1093  {
1094  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).m_rnti);
1095  }
1096  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1097  int lcNum = (*itLcRnti).second;
1098  // create new BuildDataListElement_s for this RNTI
1099  BuildDataListElement_s newEl;
1100  newEl.m_rnti = (*it).m_rnti;
1101  // create the DlDciListElement_s
1102  DlDciListElement_s newDci;
1103  newDci.m_rnti = (*it).m_rnti;
1104  newDci.m_harqProcess = UpdateHarqProcessId ((*it).m_rnti);
1105  newDci.m_resAlloc = 0;
1106  newDci.m_rbBitmap = 0;
1107  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find (newEl.m_rnti);
1108  for (uint8_t i = 0; i < nLayer; i++)
1109  {
1110  if (itCqi == m_p10CqiRxed.end ())
1111  {
1112  newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS
1113  }
1114  else
1115  {
1116  newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) );
1117  }
1118  }
1119  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
1120  uint16_t rlcPduSize = tbSize / lcNum;
1121  while ((*it).m_rnti == newEl.m_rnti)
1122  {
1123  if ( ((*it).m_rlcTransmissionQueueSize > 0)
1124  || ((*it).m_rlcRetransmissionQueueSize > 0)
1125  || ((*it).m_rlcStatusPduSize > 0) )
1126  {
1127  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1128  for (uint8_t j = 0; j < nLayer; j++)
1129  {
1130  RlcPduListElement_s newRlcEl;
1131  newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
1132  NS_LOG_INFO (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
1133  newRlcEl.m_size = rlcPduSize;
1134  UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
1135  newRlcPduLe.push_back (newRlcEl);
1136 
1137  if (m_harqOn == true)
1138  {
1139  // store RLC PDU list for HARQ
1140  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*it).m_rnti);
1141  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1142  {
1143  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*it).m_rnti);
1144  }
1145  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1146  }
1147 
1148  }
1149  newEl.m_rlcPduList.push_back (newRlcPduLe);
1150  lcNum--;
1151  }
1152  it++;
1153  if (it == m_rlcBufferReq.end ())
1154  {
1155  // restart from the first
1156  it = m_rlcBufferReq.begin ();
1157  break;
1158  }
1159  }
1160  uint32_t rbgMask = 0;
1161  uint16_t i = 0;
1162  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);
1163  NS_LOG_INFO ("RBG:");
1164  while (i < rbgPerTb)
1165  {
1166  if (rbgMap.at (rbgAllocated) == false)
1167  {
1168  rbgMask = rbgMask + (0x1 << rbgAllocated);
1169  NS_LOG_INFO ("\t " << rbgAllocated);
1170  i++;
1171  rbgMap.at (rbgAllocated) = true;
1172  rbgAllocatedNum++;
1173  }
1174  rbgAllocated++;
1175  }
1176  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1177 
1178  for (int i = 0; i < nLayer; i++)
1179  {
1180  newDci.m_tbsSize.push_back (tbSize);
1181  newDci.m_ndi.push_back (1);
1182  newDci.m_rv.push_back (0);
1183  }
1184  newEl.m_dci = newDci;
1185  if (m_harqOn == true)
1186  {
1187  // store DCI for HARQ
1188  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1189  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1190  {
1191  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1192  }
1193  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1194  // refresh timer
1195  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1196  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1197  {
1198  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1199  }
1200  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1201  }
1202  // ...more parameters -> ignored in this version
1203 
1204  ret.m_buildDataList.push_back (newEl);
1205  if (rbgAllocatedNum == rbgNum)
1206  {
1207  m_nextRntiDl = newEl.m_rnti; // store last RNTI served
1208  break; // no more RGB to be allocated
1209  }
1210  }
1211  while ((*it).m_rnti != m_nextRntiDl);
1212 
1213  ret.m_nrOfPdcchOfdmSymbols = 1;
1214 
1216  return;
1217 }
1218 
1219 void
1221 {
1222  NS_LOG_FUNCTION (this);
1223 
1224  m_rachList = params.m_rachList;
1225 
1226  return;
1227 }
1228 
1229 void
1231 {
1232  NS_LOG_FUNCTION (this);
1233 
1234  std::map <uint16_t,uint8_t>::iterator it;
1235  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1236  {
1237  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1238  {
1239  // wideband CQI reporting
1240  std::map <uint16_t,uint8_t>::iterator it;
1241  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1242  it = m_p10CqiRxed.find (rnti);
1243  if (it == m_p10CqiRxed.end ())
1244  {
1245  // create the new entry
1246  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)
1247  // generate correspondent timer
1248  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1249  }
1250  else
1251  {
1252  // update the CQI value
1253  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1254  // update correspondent timer
1255  std::map <uint16_t,uint32_t>::iterator itTimers;
1256  itTimers = m_p10CqiTimers.find (rnti);
1257  (*itTimers).second = m_cqiTimersThreshold;
1258  }
1259  }
1260  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1261  {
1262  // subband CQI reporting high layer configured
1263  // Not used by RR Scheduler
1264  }
1265  else
1266  {
1267  NS_LOG_ERROR (this << " CQI type unknown");
1268  }
1269  }
1270 
1271  return;
1272 }
1273 
1274 void
1276 {
1277  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1278 
1279  RefreshUlCqiMaps ();
1280 
1281  // Generate RBs map
1283  std::vector <bool> rbMap;
1284  uint16_t rbAllocatedNum = 0;
1285  std::set <uint16_t> rntiAllocated;
1286  std::vector <uint16_t> rbgAllocationMap;
1287  // update with RACH allocation map
1288  rbgAllocationMap = m_rachAllocationMap;
1289  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1290  m_rachAllocationMap.clear ();
1292 
1293  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1294  // remove RACH allocation
1295  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1296  {
1297  if (rbgAllocationMap.at (i) != 0)
1298  {
1299  rbMap.at (i) = true;
1300  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1301  }
1302  }
1303 
1304  if (m_harqOn == true)
1305  {
1306  // Process UL HARQ feedback
1307  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1308  {
1309  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1310  {
1311  // retx correspondent block: retrieve the UL-DCI
1312  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1313  std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1314  if (itProcId == m_ulHarqCurrentProcessId.end ())
1315  {
1316  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1317  }
1318  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1319  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
1320  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1321  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1322  {
1323  NS_LOG_ERROR ("No info find in UL-HARQ buffer for UE (might change eNB) " << rnti);
1324  }
1325  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1326  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1327  if (itStat == m_ulHarqProcessesStatus.end ())
1328  {
1329  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1330  }
1331  if ((*itStat).second.at (harqId) > 3)
1332  {
1333  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1334  continue;
1335  }
1336  bool free = true;
1337  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1338  {
1339  if (rbMap.at (j) == true)
1340  {
1341  free = false;
1342  NS_LOG_INFO (this << " BUSY " << j);
1343  }
1344  }
1345  if (free)
1346  {
1347  // retx on the same RBs
1348  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1349  {
1350  rbMap.at (j) = true;
1351  rbgAllocationMap.at (j) = dci.m_rnti;
1352  NS_LOG_INFO ("\tRB " << j);
1353  rbAllocatedNum++;
1354  }
1355  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);
1356  }
1357  else
1358  {
1359  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1360  continue;
1361  }
1362  dci.m_ndi = 0;
1363  // Update HARQ buffers with new HarqId
1364  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1365  (*itStat).second.at (harqId) = 0;
1366  (*itHarq).second.at ((*itProcId).second) = dci;
1367  ret.m_dciList.push_back (dci);
1368  rntiAllocated.insert (dci.m_rnti);
1369  }
1370  }
1371  }
1372 
1373  std::map <uint16_t,uint32_t>::iterator it;
1374  int nflows = 0;
1375 
1376  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1377  {
1378  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1379  // select UEs with queues not empty and not yet allocated for HARQ
1380  NS_LOG_INFO (this << " UE " << (*it).first << " queue " << (*it).second);
1381  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1382  {
1383  nflows++;
1384  }
1385  }
1386 
1387  if (nflows == 0)
1388  {
1389  if (ret.m_dciList.size () > 0)
1390  {
1391  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1393  }
1394  return; // no flows to be scheduled
1395  }
1396 
1397 
1398  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1399  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
1400  if (rbPerFlow < 3)
1401  {
1402  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1403  }
1404  uint16_t rbAllocated = 0;
1405 
1406  if (m_nextRntiUl != 0)
1407  {
1408  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1409  {
1410  if ((*it).first == m_nextRntiUl)
1411  {
1412  break;
1413  }
1414  }
1415  if (it == m_ceBsrRxed.end ())
1416  {
1417  NS_LOG_ERROR (this << " no user found");
1418  }
1419  }
1420  else
1421  {
1422  it = m_ceBsrRxed.begin ();
1423  m_nextRntiUl = (*it).first;
1424  }
1425  NS_LOG_INFO (this << " NFlows " << nflows << " RB per Flow " << rbPerFlow);
1426  do
1427  {
1428  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1429  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1430  {
1431  // UE already allocated for UL-HARQ -> skip it
1432  it++;
1433  if (it == m_ceBsrRxed.end ())
1434  {
1435  // restart from the first
1436  it = m_ceBsrRxed.begin ();
1437  }
1438  continue;
1439  }
1440  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1441  {
1442  // limit to physical resources last resource assignment
1443  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1444  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1445  if (rbPerFlow < 3)
1446  {
1447  // terminate allocation
1448  rbPerFlow = 0;
1449  }
1450  }
1451  NS_LOG_INFO (this << " try to allocate " << (*it).first);
1452  UlDciListElement_s uldci;
1453  uldci.m_rnti = (*it).first;
1454  uldci.m_rbLen = rbPerFlow;
1455  bool allocated = false;
1456  NS_LOG_INFO (this << " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1457  while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
1458  {
1459  // check availability
1460  bool free = true;
1461  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1462  {
1463  if (rbMap.at (j) == true)
1464  {
1465  free = false;
1466  break;
1467  }
1468  }
1469  if (free)
1470  {
1471  uldci.m_rbStart = rbAllocated;
1472 
1473  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1474  {
1475  rbMap.at (j) = true;
1476  // store info on allocation for managing ul-cqi interpretation
1477  rbgAllocationMap.at (j) = (*it).first;
1478  NS_LOG_INFO ("\t " << j);
1479  }
1480  rbAllocated += rbPerFlow;
1481  allocated = true;
1482  break;
1483  }
1484  rbAllocated++;
1485  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1486  {
1487  // limit to physical resources last resource assignment
1488  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1489  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1490  if (rbPerFlow < 3)
1491  {
1492  // terminate allocation
1493  rbPerFlow = 0;
1494  }
1495  }
1496  }
1497  if (!allocated)
1498  {
1499  // unable to allocate new resource: finish scheduling
1500  m_nextRntiUl = (*it).first;
1501  if (ret.m_dciList.size () > 0)
1502  {
1504  }
1505  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1506  return;
1507  }
1508  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1509  int cqi = 0;
1510  if (itCqi == m_ueCqi.end ())
1511  {
1512  // no cqi info about this UE
1513  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1514  NS_LOG_INFO (this << " UE does not have ULCQI " << (*it).first );
1515  }
1516  else
1517  {
1518  // take the lowest CQI value (worst RB)
1519  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1520  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1521  {
1522  if ((*itCqi).second.at (i) < minSinr)
1523  {
1524  minSinr = (*itCqi).second.at (i);
1525  }
1526  }
1527  // translate SINR -> cqi: WILD ACK: same as DL
1528  double s = log2 ( 1 + (
1529  std::pow (10, minSinr / 10 ) /
1530  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1531 
1532 
1533  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1534  if (cqi == 0)
1535  {
1536  it++;
1537  if (it == m_ceBsrRxed.end ())
1538  {
1539  // restart from the first
1540  it = m_ceBsrRxed.begin ();
1541  }
1542  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
1543  // remove UE from allocation map
1544  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1545  {
1546  rbgAllocationMap.at (i) = 0;
1547  }
1548  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1549  }
1550  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1551  }
1552  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD
1553 
1554  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1555  uldci.m_ndi = 1;
1556  uldci.m_cceIndex = 0;
1557  uldci.m_aggrLevel = 1;
1558  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1559  uldci.m_hopping = false;
1560  uldci.m_n2Dmrs = 0;
1561  uldci.m_tpc = 0; // no power control
1562  uldci.m_cqiRequest = false; // only period CQI at this stage
1563  uldci.m_ulIndex = 0; // TDD parameter
1564  uldci.m_dai = 1; // TDD parameter
1565  uldci.m_freqHopping = 0;
1566  uldci.m_pdcchPowerOffset = 0; // not used
1567  ret.m_dciList.push_back (uldci);
1568  // store DCI for HARQ_PERIOD
1569  uint8_t harqId = 0;
1570  if (m_harqOn == true)
1571  {
1572  std::map <uint16_t, uint8_t>::iterator itProcId;
1573  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1574  if (itProcId == m_ulHarqCurrentProcessId.end ())
1575  {
1576  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1577  }
1578  harqId = (*itProcId).second;
1579  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1580  if (itDci == m_ulHarqProcessesDciBuffer.end ())
1581  {
1582  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1583  }
1584  (*itDci).second.at (harqId) = uldci;
1585  }
1586  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);
1587 
1588  it++;
1589  if (it == m_ceBsrRxed.end ())
1590  {
1591  // restart from the first
1592  it = m_ceBsrRxed.begin ();
1593  }
1594  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1595  {
1596  // Stop allocation: no more PRBs
1597  m_nextRntiUl = (*it).first;
1598  break;
1599  }
1600  }
1601  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1602 
1603  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1604 
1606  return;
1607 }
1608 
1609 void
1611 {
1612  NS_LOG_FUNCTION (this);
1613  return;
1614 }
1615 
1616 void
1618 {
1619  NS_LOG_FUNCTION (this);
1620  return;
1621 }
1622 
1623 void
1625 {
1626  NS_LOG_FUNCTION (this);
1627 
1628  std::map <uint16_t,uint32_t>::iterator it;
1629 
1630  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1631  {
1632  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1633  {
1634  // buffer status report
1635  // note that this scheduler does not differentiate the
1636  // allocation according to which LCGs have more/less bytes
1637  // to send.
1638  // Hence the BSR of different LCGs are just summed up to get
1639  // a total queue size that is used for allocation purposes.
1640 
1641  uint32_t buffer = 0;
1642  for (uint8_t lcg = 0; lcg < 4; ++lcg)
1643  {
1644  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1645  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1646  }
1647 
1648  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1649  it = m_ceBsrRxed.find (rnti);
1650  if (it == m_ceBsrRxed.end ())
1651  {
1652  // create the new entry
1653  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1654  NS_LOG_INFO (this << " Insert RNTI " << rnti << " queue " << buffer);
1655  }
1656  else
1657  {
1658  // update the buffer size value
1659  (*it).second = buffer;
1660  NS_LOG_INFO (this << " Update RNTI " << rnti << " queue " << buffer);
1661  }
1662  }
1663  }
1664 
1665  return;
1666 }
1667 
1668 void
1670 {
1671  NS_LOG_FUNCTION (this);
1672 
1673  switch (m_ulCqiFilter)
1674  {
1676  {
1677  // filter all the CQIs that are not SRS based
1678  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
1679  {
1680  return;
1681  }
1682  }
1683  break;
1685  {
1686  // filter all the CQIs that are not SRS based
1687  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
1688  {
1689  return;
1690  }
1691  }
1693  break;
1694 
1695  default:
1696  NS_FATAL_ERROR ("Unknown UL CQI type");
1697  }
1698  switch (params.m_ulCqi.m_type)
1699  {
1700  case UlCqi_s::PUSCH:
1701  {
1702  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1703  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1704  itMap = m_allocationMaps.find (params.m_sfnSf);
1705  if (itMap == m_allocationMaps.end ())
1706  {
1707  NS_LOG_INFO (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1708  return;
1709  }
1710  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1711  {
1712  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1713  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1714  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1715  if (itCqi == m_ueCqi.end ())
1716  {
1717  // create a new entry
1718  std::vector <double> newCqi;
1719  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1720  {
1721  if (i == j)
1722  {
1723  newCqi.push_back (sinr);
1724  }
1725  else
1726  {
1727  // initialize with NO_SINR value.
1728  newCqi.push_back (30.0);
1729  }
1730 
1731  }
1732  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1733  // generate correspondent timer
1734  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1735  }
1736  else
1737  {
1738  // update the value
1739  (*itCqi).second.at (i) = sinr;
1740  // update correspondent timer
1741  std::map <uint16_t, uint32_t>::iterator itTimers;
1742  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1743  (*itTimers).second = m_cqiTimersThreshold;
1744 
1745  }
1746 
1747  }
1748  // remove obsolete info on allocation
1749  m_allocationMaps.erase (itMap);
1750  }
1751  break;
1752  case UlCqi_s::SRS:
1753  {
1754  // get the RNTI from vendor specific parameters
1755  uint16_t rnti = 0;
1756  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1757  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1758  {
1759  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1760  {
1761  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1762  rnti = vsp->GetRnti ();
1763  }
1764  }
1765  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1766  itCqi = m_ueCqi.find (rnti);
1767  if (itCqi == m_ueCqi.end ())
1768  {
1769  // create a new entry
1770  std::vector <double> newCqi;
1771  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1772  {
1773  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1774  newCqi.push_back (sinr);
1775  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1776 
1777  }
1778  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1779  // generate correspondent timer
1780  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1781  }
1782  else
1783  {
1784  // update the values
1785  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1786  {
1787  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1788  (*itCqi).second.at (j) = sinr;
1789  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1790  }
1791  // update correspondent timer
1792  std::map <uint16_t, uint32_t>::iterator itTimers;
1793  itTimers = m_ueCqiTimers.find (rnti);
1794  (*itTimers).second = m_cqiTimersThreshold;
1795 
1796  }
1797 
1798 
1799  }
1800  break;
1801  case UlCqi_s::PUCCH_1:
1802  case UlCqi_s::PUCCH_2:
1803  case UlCqi_s::PRACH:
1804  {
1805  NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1806  }
1807  break;
1808  default:
1809  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1810  }
1811  return;
1812 }
1813 
1814 
1815 void
1817 {
1818  NS_LOG_FUNCTION (this << m_p10CqiTimers.size ());
1819  // refresh DL CQI P01 Map
1820  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1821  while (itP10 != m_p10CqiTimers.end ())
1822  {
1823  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1824  if ((*itP10).second == 0)
1825  {
1826  // delete correspondent entries
1827  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1828  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1829  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1830  m_p10CqiRxed.erase (itMap);
1831  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1832  itP10++;
1833  m_p10CqiTimers.erase (temp);
1834  }
1835  else
1836  {
1837  (*itP10).second--;
1838  itP10++;
1839  }
1840  }
1841 
1842  return;
1843 }
1844 
1845 
1846 void
1848 {
1849  // refresh UL CQI Map
1850  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1851  while (itUl != m_ueCqiTimers.end ())
1852  {
1853  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1854  if ((*itUl).second == 0)
1855  {
1856  // delete correspondent entries
1857  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1858  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1859  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1860  (*itMap).second.clear ();
1861  m_ueCqi.erase (itMap);
1862  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1863  itUl++;
1864  m_ueCqiTimers.erase (temp);
1865  }
1866  else
1867  {
1868  (*itUl).second--;
1869  itUl++;
1870  }
1871  }
1872 
1873  return;
1874 }
1875 
1876 void
1877 RrFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1878 {
1879  NS_LOG_FUNCTION (this);
1880  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1881  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1882  {
1883  if (((*it).m_rnti == rnti) && ((*it).m_logicalChannelIdentity == lcid))
1884  {
1885  NS_LOG_INFO (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).m_rlcTransmissionQueueSize << " retxqueue " << (*it).m_rlcRetransmissionQueueSize << " status " << (*it).m_rlcStatusPduSize << " decrease " << size);
1886  // Update queues: RLC tx order Status, ReTx, Tx
1887  // Update status queue
1888  if (((*it).m_rlcStatusPduSize > 0) && (size >= (*it).m_rlcStatusPduSize))
1889  {
1890  (*it).m_rlcStatusPduSize = 0;
1891  }
1892  else if (((*it).m_rlcRetransmissionQueueSize > 0) && (size >= (*it).m_rlcRetransmissionQueueSize))
1893  {
1894  (*it).m_rlcRetransmissionQueueSize = 0;
1895  }
1896  else if ((*it).m_rlcTransmissionQueueSize > 0)
1897  {
1898  uint32_t rlcOverhead;
1899  if (lcid == 1)
1900  {
1901  // for SRB1 (using RLC AM) it's better to
1902  // overestimate RLC overhead rather than
1903  // underestimate it and risk unneeded
1904  // segmentation which increases delay
1905  rlcOverhead = 4;
1906  }
1907  else
1908  {
1909  // minimum RLC overhead due to header
1910  rlcOverhead = 2;
1911  }
1912  // update transmission queue
1913  if ((*it).m_rlcTransmissionQueueSize <= size - rlcOverhead)
1914  {
1915  (*it).m_rlcTransmissionQueueSize = 0;
1916  }
1917  else
1918  {
1919  (*it).m_rlcTransmissionQueueSize -= size - rlcOverhead;
1920  }
1921  }
1922  return;
1923  }
1924  }
1925 }
1926 
1927 void
1928 RrFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1929 {
1930 
1931  size = size - 2; // remove the minimum RLC overhead
1932  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1933  if (it != m_ceBsrRxed.end ())
1934  {
1935  NS_LOG_INFO (this << " Update RLC BSR UE " << rnti << " size " << size << " BSR " << (*it).second);
1936  if ((*it).second >= size)
1937  {
1938  (*it).second -= size;
1939  }
1940  else
1941  {
1942  (*it).second = 0;
1943  }
1944  }
1945  else
1946  {
1947  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1948  }
1949 
1950 }
1951 
1952 
1953 void
1955 {
1956  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1958  params.m_rnti = rnti;
1959  params.m_transmissionMode = txMode;
1961 }
1962 
1963 
1964 
1965 }
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:60
#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
Hold a bool native type.
Definition: boolean.h:38
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
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
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:61
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
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:223
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
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
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
Parameters of the SCHED_UL_TRIGGER_REQ primitive.
Hold an unsigned integer type.
Definition: uinteger.h:46
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
static uint8_t TxMode2LayerNum(uint8_t txMode)
Definition: lte-common.cc:170
Ptr< SampleEmitter > s
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:233
Parameters of the SCHED_UL_NOISE_INTERFERENCE_REQ primitive.
std::vector< struct CqiListElement_s > m_cqiList
std::vector< struct DlInfoListElement_s > m_dlInfoList
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.
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)
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
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:84
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:114
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:142
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:213
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:193
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)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
#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)
a unique identifier for an interface.
Definition: type-id.h:49
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
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.