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 
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 
52 
54 {
55 public:
57 
58  // inherited from FfMacCschedSapProvider
59  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
60  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
61  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
62  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
63  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
64 
65 private:
68 };
69 
71 {
72 }
73 
75 {
76 }
77 
78 
79 void
81 {
83 }
84 
85 void
87 {
89 }
90 
91 
92 void
94 {
96 }
97 
98 void
100 {
102 }
103 
104 void
106 {
108 }
109 
110 
111 
112 
114 {
115 public:
117 
118  // inherited from FfMacSchedSapProvider
119  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
120  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
121  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
122  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
123  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
124  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
125  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
126  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
127  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
128  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
129  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
130 
131 
132 private:
135 };
136 
137 
138 
140 {
141 }
142 
143 
145  : m_scheduler (scheduler)
146 {
147 }
148 
149 void
151 {
153 }
154 
155 void
157 {
159 }
160 
161 void
163 {
165 }
166 
167 void
169 {
171 }
172 
173 void
175 {
177 }
178 
179 void
181 {
183 }
184 
185 void
187 {
189 }
190 
191 void
193 {
195 }
196 
197 void
199 {
201 }
202 
203 void
205 {
207 }
208 
209 void
211 {
213 }
214 
215 
216 
217 
218 
220  : m_cschedSapUser (0),
221  m_schedSapUser (0),
222  m_nextRntiDl (0),
223  m_nextRntiUl (0)
224 {
225  m_amc = CreateObject <LteAmc> ();
228 }
229 
231 {
232  NS_LOG_FUNCTION (this);
233 }
234 
235 void
237 {
238  NS_LOG_FUNCTION (this);
240  m_dlHarqProcessesTimer.clear ();
242  m_dlInfoListBuffered.clear ();
243  m_ulHarqCurrentProcessId.clear ();
244  m_ulHarqProcessesStatus.clear ();
246  delete m_cschedSapProvider;
247  delete m_schedSapProvider;
248 }
249 
250 TypeId
252 {
253  static TypeId tid = TypeId ("ns3::RrFfMacScheduler")
255  .AddConstructor<RrFfMacScheduler> ()
256  .AddAttribute ("CqiTimerThreshold",
257  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
258  UintegerValue (1000),
259  MakeUintegerAccessor (&RrFfMacScheduler::m_cqiTimersThreshold),
260  MakeUintegerChecker<uint32_t> ())
261  .AddAttribute ("HarqEnabled",
262  "Activate/Deactivate the HARQ [by default is active].",
263  BooleanValue (true),
264  MakeBooleanAccessor (&RrFfMacScheduler::m_harqOn),
265  MakeBooleanChecker ())
266  .AddAttribute ("UlGrantMcs",
267  "The MCS of the UL grant, must be [0..15] (default 0)",
268  UintegerValue (0),
269  MakeUintegerAccessor (&RrFfMacScheduler::m_ulGrantMcs),
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  NS_LOG_FUNCTION (this);
305  // Read the subset of parameters used
306  m_cschedCellConfig = params;
309  cnf.m_result = SUCCESS;
311  return;
312 }
313 
314 void
316 {
317  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
318  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
319  if (it == m_uesTxMode.end ())
320  {
321  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
322  // generate HARQ buffers
323  m_dlHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
324  DlHarqProcessesStatus_t dlHarqPrcStatus;
325  dlHarqPrcStatus.resize (8,0);
326  m_dlHarqProcessesStatus.insert (std::pair <uint16_t, DlHarqProcessesStatus_t> (params.m_rnti, dlHarqPrcStatus));
327  DlHarqProcessesTimer_t dlHarqProcessesTimer;
328  dlHarqProcessesTimer.resize (8,0);
329  m_dlHarqProcessesTimer.insert (std::pair <uint16_t, DlHarqProcessesTimer_t> (params.m_rnti, dlHarqProcessesTimer));
330  DlHarqProcessesDciBuffer_t dlHarqdci;
331  dlHarqdci.resize (8);
332  m_dlHarqProcessesDciBuffer.insert (std::pair <uint16_t, DlHarqProcessesDciBuffer_t> (params.m_rnti, dlHarqdci));
333  DlHarqRlcPduListBuffer_t dlHarqRlcPdu;
334  dlHarqRlcPdu.resize (2);
335  dlHarqRlcPdu.at (0).resize (8);
336  dlHarqRlcPdu.at (1).resize (8);
337  m_dlHarqProcessesRlcPduListBuffer.insert (std::pair <uint16_t, DlHarqRlcPduListBuffer_t> (params.m_rnti, dlHarqRlcPdu));
338  m_ulHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
339  UlHarqProcessesStatus_t ulHarqPrcStatus;
340  ulHarqPrcStatus.resize (8,0);
341  m_ulHarqProcessesStatus.insert (std::pair <uint16_t, UlHarqProcessesStatus_t> (params.m_rnti, ulHarqPrcStatus));
342  UlHarqProcessesDciBuffer_t ulHarqdci;
343  ulHarqdci.resize (8);
344  m_ulHarqProcessesDciBuffer.insert (std::pair <uint16_t, UlHarqProcessesDciBuffer_t> (params.m_rnti, ulHarqdci));
345  }
346  else
347  {
348  (*it).second = params.m_transmissionMode;
349  }
350  return;
351 }
352 
353 void
355 {
356  NS_LOG_FUNCTION (this);
357  // Not used at this stage (LCs updated by DoSchedDlRlcBufferReq)
358  return;
359 }
360 
361 void
363 {
364  NS_LOG_FUNCTION (this);
365  for (uint16_t i = 0; i < params.m_logicalChannelIdentity.size (); i++)
366  {
367  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
368  while (it!=m_rlcBufferReq.end ())
369  {
370  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity.at (i)))
371  {
372  it = m_rlcBufferReq.erase (it);
373  }
374  else
375  {
376  it++;
377  }
378  }
379  }
380  return;
381 }
382 
383 void
385 {
386  NS_LOG_FUNCTION (this << " Release RNTI " << params.m_rnti);
387 
388  m_uesTxMode.erase (params.m_rnti);
389  m_dlHarqCurrentProcessId.erase (params.m_rnti);
390  m_dlHarqProcessesStatus.erase (params.m_rnti);
391  m_dlHarqProcessesTimer.erase (params.m_rnti);
392  m_dlHarqProcessesDciBuffer.erase (params.m_rnti);
394  m_ulHarqCurrentProcessId.erase (params.m_rnti);
395  m_ulHarqProcessesStatus.erase (params.m_rnti);
396  m_ulHarqProcessesDciBuffer.erase (params.m_rnti);
397  m_ceBsrRxed.erase (params.m_rnti);
398  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
399  while (it != m_rlcBufferReq.end ())
400  {
401  if ((*it).m_rnti == params.m_rnti)
402  {
403  NS_LOG_INFO (this << " Erase RNTI " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
404  it = m_rlcBufferReq.erase (it);
405  }
406  else
407  {
408  it++;
409  }
410  }
411  if (m_nextRntiUl == params.m_rnti)
412  {
413  m_nextRntiUl = 0;
414  }
415 
416  if (m_nextRntiDl == params.m_rnti)
417  {
418  m_nextRntiDl = 0;
419  }
420 
421  return;
422 }
423 
424 
425 void
427 {
428  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
429  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
430  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
431  bool newLc = true;
432  while (it != m_rlcBufferReq.end ())
433  {
434  // remove old entries of this UE-LC
435  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity))
436  {
437  it = m_rlcBufferReq.erase (it);
438  newLc = false;
439  }
440  else
441  {
442  ++it;
443  }
444  }
445  // add the new parameters
446  m_rlcBufferReq.insert (it, params);
447  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);
448  // initialize statistics of the flow in case of new flows
449  if (newLc == true)
450  {
451  m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (params.m_rnti, 1)); // only codeword 0 at this stage (SISO)
452  // initialized to 1 (i.e., the lowest value for transmitting a signal)
453  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (params.m_rnti, m_cqiTimersThreshold));
454  }
455 
456  return;
457 }
458 
459 void
461 {
462  NS_LOG_FUNCTION (this);
463  NS_FATAL_ERROR ("method not implemented");
464  return;
465 }
466 
467 void
469 {
470  NS_LOG_FUNCTION (this);
471  NS_FATAL_ERROR ("method not implemented");
472  return;
473 }
474 
475 int
477 {
478  for (int i = 0; i < 4; i++)
479  {
480  if (dlbandwidth < Type0AllocationRbg[i])
481  {
482  return (i + 1);
483  }
484  }
485 
486  return (-1);
487 }
488 
489 bool
491 {
492  return (i.m_rnti < j.m_rnti);
493 }
494 
495 
496 uint8_t
498 {
499  NS_LOG_FUNCTION (this << rnti);
500 
501  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
502  if (it == m_dlHarqCurrentProcessId.end ())
503  {
504  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
505  }
506  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
507  if (itStat == m_dlHarqProcessesStatus.end ())
508  {
509  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
510  }
511  uint8_t i = (*it).second;
512  do
513  {
514  i = (i + 1) % HARQ_PROC_NUM;
515  }
516  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
517  if ((*itStat).second.at (i) == 0)
518  {
519  return (true);
520  }
521  else
522  {
523  return (false); // return a not valid harq proc id
524  }
525 }
526 
527 
528 
529 uint8_t
531 {
532  NS_LOG_FUNCTION (this << rnti);
533 
534 
535  if (m_harqOn == false)
536  {
537  return (0);
538  }
539 
540  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
541  if (it == m_dlHarqCurrentProcessId.end ())
542  {
543  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
544  }
545  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
546  if (itStat == m_dlHarqProcessesStatus.end ())
547  {
548  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
549  }
550  uint8_t i = (*it).second;
551  do
552  {
553  i = (i + 1) % HARQ_PROC_NUM;
554  }
555  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
556  if ((*itStat).second.at (i) == 0)
557  {
558  (*it).second = i;
559  (*itStat).second.at (i) = 1;
560  }
561  else
562  {
563  return (9); // return a not valid harq proc id
564  }
565 
566  return ((*it).second);
567 }
568 
569 
570 void
572 {
573  NS_LOG_FUNCTION (this);
574 
575  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
576  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers ++)
577  {
578  for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
579  {
580  if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
581  {
582  // reset HARQ process
583 
584  NS_LOG_INFO (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
585  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
586  if (itStat == m_dlHarqProcessesStatus.end ())
587  {
588  NS_FATAL_ERROR ("No Process Id Status found for this RNTI " << (*itTimers).first);
589  }
590  (*itStat).second.at (i) = 0;
591  (*itTimers).second.at (i) = 0;
592  }
593  else
594  {
595  (*itTimers).second.at (i)++;
596  }
597  }
598  }
599 
600 }
601 
602 
603 
604 void
606 {
607  NS_LOG_FUNCTION (this << " DL Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
608  // API generated by RLC for triggering the scheduling of a DL subframe
609 
610  RefreshDlCqiMaps ();
612  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
614 
615  // Generate RBGs map
616  std::vector <bool> rbgMap;
617  uint16_t rbgAllocatedNum = 0;
618  std::set <uint16_t> rntiAllocated;
619  rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
620 
621  // update UL HARQ proc id
622  std::map <uint16_t, uint8_t>::iterator itProcId;
623  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
624  {
625  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
626  }
627 
628  // RACH Allocation
630  uint16_t rbStart = 0;
631  std::vector <struct RachListElement_s>::iterator itRach;
632  for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
633  {
634  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");
635  BuildRarListElement_s newRar;
636  newRar.m_rnti = (*itRach).m_rnti;
637  // DL-RACH Allocation
638  // Ideal: no needs of configuring m_dci
639  // UL-RACH Allocation
640  newRar.m_grant.m_rnti = newRar.m_rnti;
641  newRar.m_grant.m_mcs = m_ulGrantMcs;
642  uint16_t rbLen = 1;
643  uint16_t tbSizeBits = 0;
644  // find lowest TB size that fits UL grant estimated size
645  while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
646  {
647  rbLen++;
648  tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
649  }
650  if (tbSizeBits < (*itRach).m_estimatedSize)
651  {
652  // no more allocation space: finish allocation
653  break;
654  }
655  newRar.m_grant.m_rbStart = rbStart;
656  newRar.m_grant.m_rbLen = rbLen;
657  newRar.m_grant.m_tbSize = tbSizeBits / 8;
658  newRar.m_grant.m_hopping = false;
659  newRar.m_grant.m_tpc = 0;
660  newRar.m_grant.m_cqiRequest = false;
661  newRar.m_grant.m_ulDelay = false;
662  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);
663  for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
664  {
665  m_rachAllocationMap.at (i) = (*itRach).m_rnti;
666  }
667  rbStart = rbStart + rbLen;
668 
669  if (m_harqOn == true)
670  {
671  // generate UL-DCI for HARQ retransmissions
672  UlDciListElement_s uldci;
673  uldci.m_rnti = newRar.m_rnti;
674  uldci.m_rbLen = rbLen;
675  uldci.m_rbStart = rbStart;
676  uldci.m_mcs = m_ulGrantMcs;
677  uldci.m_tbSize = tbSizeBits / 8;
678  uldci.m_ndi = 1;
679  uldci.m_cceIndex = 0;
680  uldci.m_aggrLevel = 1;
681  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
682  uldci.m_hopping = false;
683  uldci.m_n2Dmrs = 0;
684  uldci.m_tpc = 0; // no power control
685  uldci.m_cqiRequest = false; // only period CQI at this stage
686  uldci.m_ulIndex = 0; // TDD parameter
687  uldci.m_dai = 1; // TDD parameter
688  uldci.m_freqHopping = 0;
689  uldci.m_pdcchPowerOffset = 0; // not used
690 
691  uint8_t harqId = 0;
692  std::map <uint16_t, uint8_t>::iterator itProcId;
693  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
694  if (itProcId == m_ulHarqCurrentProcessId.end ())
695  {
696  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
697  }
698  harqId = (*itProcId).second;
699  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
700  if (itDci == m_ulHarqProcessesDciBuffer.end ())
701  {
702  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
703  }
704  (*itDci).second.at (harqId) = uldci;
705  }
706 
707  ret.m_buildRarList.push_back (newRar);
708  }
709  m_rachList.clear ();
710 
711  // Process DL HARQ feedback
713  // retrieve past HARQ retx buffered
714  if (m_dlInfoListBuffered.size () > 0)
715  {
716  if (params.m_dlInfoList.size () > 0)
717  {
718  NS_LOG_INFO (this << " Received DL-HARQ feedback");
719  m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
720  }
721  }
722  else
723  {
724  if (params.m_dlInfoList.size () > 0)
725  {
727  }
728  }
729  if (m_harqOn == false)
730  {
731  // Ignore HARQ feedback
732  m_dlInfoListBuffered.clear ();
733  }
734  std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
735  for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
736  {
737  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
738  if (itRnti != rntiAllocated.end ())
739  {
740  // RNTI already allocated for retx
741  continue;
742  }
743  uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
744  std::vector <bool> retx;
745  NS_LOG_INFO (this << " Processing DLHARQ feedback");
746  if (nLayers == 1)
747  {
748  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
749  retx.push_back (false);
750  }
751  else
752  {
753  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
754  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
755  }
756  if (retx.at (0) || retx.at (1))
757  {
758  // retrieve HARQ process information
759  uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
760  uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
761  NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
762  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
763  if (itHarq == m_dlHarqProcessesDciBuffer.end ())
764  {
765  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
766  }
767 
768  DlDciListElement_s dci = (*itHarq).second.at (harqId);
769  int rv = 0;
770  if (dci.m_rv.size () == 1)
771  {
772  rv = dci.m_rv.at (0);
773  }
774  else
775  {
776  rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
777  }
778 
779  if (rv == 3)
780  {
781  // maximum number of retx reached -> drop process
782  NS_LOG_INFO ("Max number of retransmissions reached -> drop process");
783  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
784  if (it == m_dlHarqProcessesStatus.end ())
785  {
786  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
787  }
788  (*it).second.at (harqId) = 0;
789  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
790  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
791  {
792  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
793  }
794  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
795  {
796  (*itRlcPdu).second.at (k).at (harqId).clear ();
797  }
798  continue;
799  }
800  // check the feasibility of retransmitting on the same RBGs
801  // translate the DCI to Spectrum framework
802  std::vector <int> dciRbg;
803  uint32_t mask = 0x1;
804  NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
805  for (int j = 0; j < 32; j++)
806  {
807  if (((dci.m_rbBitmap & mask) >> j) == 1)
808  {
809  dciRbg.push_back (j);
810  NS_LOG_INFO ("\t" << j);
811  }
812  mask = (mask << 1);
813  }
814  bool free = true;
815  for (uint8_t j = 0; j < dciRbg.size (); j++)
816  {
817  if (rbgMap.at (dciRbg.at (j)) == true)
818  {
819  free = false;
820  break;
821  }
822  }
823  if (free)
824  {
825  // use the same RBGs for the retx
826  // reserve RBGs
827  for (uint8_t j = 0; j < dciRbg.size (); j++)
828  {
829  rbgMap.at (dciRbg.at (j)) = true;
830  NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
831  rbgAllocatedNum++;
832  }
833 
834  NS_LOG_INFO (this << " Send retx in the same RBGs");
835  }
836  else
837  {
838  // find RBGs for sending HARQ retx
839  uint8_t j = 0;
840  uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % rbgNum;
841  uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
842  std::vector <bool> rbgMapCopy = rbgMap;
843  while ((j < dciRbg.size ())&&(startRbg != rbgId))
844  {
845  if (rbgMapCopy.at (rbgId) == false)
846  {
847  rbgMapCopy.at (rbgId) = true;
848  dciRbg.at (j) = rbgId;
849  j++;
850  }
851  rbgId++;
852  }
853  if (j == dciRbg.size ())
854  {
855  // find new RBGs -> update DCI map
856  uint32_t rbgMask = 0;
857  for (uint16_t k = 0; k < dciRbg.size (); k++)
858  {
859  rbgMask = rbgMask + (0x1 << dciRbg.at (k));
860  NS_LOG_INFO (this << " New allocated RBG " << dciRbg.at (k));
861  rbgAllocatedNum++;
862  }
863  dci.m_rbBitmap = rbgMask;
864  rbgMap = rbgMapCopy;
865  }
866  else
867  {
868  // HARQ retx cannot be performed on this TTI -> store it
869  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
870  NS_LOG_INFO (this << " No resource for this retx -> buffer it");
871  }
872  }
873  // retrieve RLC PDU list for retx TBsize and update DCI
875  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
876  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
877  {
878  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
879  }
880  for (uint8_t j = 0; j < nLayers; j++)
881  {
882  if (retx.at (j))
883  {
884  if (j >= dci.m_ndi.size ())
885  {
886  // for avoiding errors in MIMO transient phases
887  dci.m_ndi.push_back (0);
888  dci.m_rv.push_back (0);
889  dci.m_mcs.push_back (0);
890  dci.m_tbsSize.push_back (0);
891  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
892 
893  }
894  else
895  {
896  dci.m_ndi.at (j) = 0;
897  dci.m_rv.at (j)++;
898  (*itHarq).second.at (harqId).m_rv.at (j)++;
899  NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
900  }
901  }
902  else
903  {
904  // empty TB of layer j
905  dci.m_ndi.at (j) = 0;
906  dci.m_rv.at (j) = 0;
907  dci.m_mcs.at (j) = 0;
908  dci.m_tbsSize.at (j) = 0;
909  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
910  }
911  }
912 
913  for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
914  {
915  std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
916  for (uint8_t j = 0; j < nLayers; j++)
917  {
918  if (retx.at (j))
919  {
920  if (j < dci.m_ndi.size ())
921  {
922  rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
923  }
924  }
925  }
926 
927  if (rlcPduListPerLc.size () > 0)
928  {
929  newEl.m_rlcPduList.push_back (rlcPduListPerLc);
930  }
931  }
932  newEl.m_rnti = rnti;
933  newEl.m_dci = dci;
934  (*itHarq).second.at (harqId).m_rv = dci.m_rv;
935  // refresh timer
936  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
937  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
938  {
939  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
940  }
941  (*itHarqTimer).second.at (harqId) = 0;
942  ret.m_buildDataList.push_back (newEl);
943  rntiAllocated.insert (rnti);
944  }
945  else
946  {
947  // update HARQ process status
948  NS_LOG_INFO (this << " HARQ ACK UE " << m_dlInfoListBuffered.at (i).m_rnti);
949  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
950  if (it == m_dlHarqProcessesStatus.end ())
951  {
952  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
953  }
954  (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
955  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
956  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
957  {
958  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
959  }
960  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
961  {
962  (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
963  }
964  }
965  }
966  m_dlInfoListBuffered.clear ();
967  m_dlInfoListBuffered = dlInfoListUntxed;
968 
969  if (rbgAllocatedNum == rbgNum)
970  {
971  // all the RBGs are already allocated -> exit
972  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
973  {
975  }
976  return;
977  }
978 
979  // Get the actual active flows (queue!=0)
980  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
982  int nflows = 0;
983  int nTbs = 0;
984  std::map <uint16_t,uint8_t> lcActivesPerRnti; // tracks how many active LCs per RNTI there are
985  std::map <uint16_t,uint8_t>::iterator itLcRnti;
986  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
987  {
988  // remove old entries of this UE-LC
989  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
990  if ( (((*it).m_rlcTransmissionQueueSize > 0)
991  || ((*it).m_rlcRetransmissionQueueSize > 0)
992  || ((*it).m_rlcStatusPduSize > 0))
993  && (itRnti == rntiAllocated.end ()) // UE must not be allocated for HARQ retx
994  && (HarqProcessAvailability ((*it).m_rnti)) ) // UE needs HARQ proc free
995 
996  {
997  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);
998  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find ((*it).m_rnti);
999  uint8_t cqi = 0;
1000  if (itCqi != m_p10CqiRxed.end ())
1001  {
1002  cqi = (*itCqi).second;
1003  }
1004  else
1005  {
1006  cqi = 1; // lowest value fro trying a transmission
1007  }
1008  if (cqi != 0)
1009  {
1010  // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1011  nflows++;
1012  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
1013  if (itLcRnti != lcActivesPerRnti.end ())
1014  {
1015  (*itLcRnti).second++;
1016  }
1017  else
1018  {
1019  lcActivesPerRnti.insert (std::pair<uint16_t, uint8_t > ((*it).m_rnti, 1));
1020  nTbs++;
1021  }
1022 
1023  }
1024  }
1025  }
1026 
1027  if (nflows == 0)
1028  {
1029  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
1030  {
1032  }
1033  return;
1034  }
1035  // Divide the resource equally among the active users according to
1036  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
1037 
1038  int rbgPerTb = (nTbs > 0) ? ((rbgNum - rbgAllocatedNum) / nTbs) : INT_MAX;
1039  NS_LOG_INFO (this << " Flows to be transmitted " << nflows << " rbgPerTb " << rbgPerTb);
1040  if (rbgPerTb == 0)
1041  {
1042  rbgPerTb = 1; // at least 1 rbg per TB (till available resource)
1043  }
1044  int rbgAllocated = 0;
1045 
1046  // round robin assignment to all UEs registered starting from the subsequent of the one
1047  // served last scheduling trigger event
1048  if (m_nextRntiDl != 0)
1049  {
1050  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1051  {
1052  if ((*it).m_rnti == m_nextRntiDl)
1053  {
1054  break;
1055  }
1056  }
1057 
1058  if (it == m_rlcBufferReq.end ())
1059  {
1060  NS_LOG_ERROR (this << " no user found");
1061  }
1062  }
1063  else
1064  {
1065  it = m_rlcBufferReq.begin ();
1066  m_nextRntiDl = (*it).m_rnti;
1067  }
1068  std::map <uint16_t,uint8_t>::iterator itTxMode;
1069  do
1070  {
1071  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
1072  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
1073  if ((itLcRnti == lcActivesPerRnti.end ())||(itRnti != rntiAllocated.end ()))
1074  {
1075  // skip this RNTI (no active queue or yet allocated for HARQ)
1076  uint16_t rntiDiscared = (*it).m_rnti;
1077  while (it != m_rlcBufferReq.end ())
1078  {
1079  if ((*it).m_rnti != rntiDiscared)
1080  {
1081  break;
1082  }
1083  it++;
1084  }
1085  if (it == m_rlcBufferReq.end ())
1086  {
1087  // restart from the first
1088  it = m_rlcBufferReq.begin ();
1089  }
1090  continue;
1091  }
1092  itTxMode = m_uesTxMode.find ((*it).m_rnti);
1093  if (itTxMode == m_uesTxMode.end ())
1094  {
1095  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).m_rnti);
1096  }
1097  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1098  int lcNum = (*itLcRnti).second;
1099  // create new BuildDataListElement_s for this RNTI
1100  BuildDataListElement_s newEl;
1101  newEl.m_rnti = (*it).m_rnti;
1102  // create the DlDciListElement_s
1103  DlDciListElement_s newDci;
1104  newDci.m_rnti = (*it).m_rnti;
1105  newDci.m_harqProcess = UpdateHarqProcessId ((*it).m_rnti);
1106  newDci.m_resAlloc = 0;
1107  newDci.m_rbBitmap = 0;
1108  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find (newEl.m_rnti);
1109  for (uint8_t i = 0; i < nLayer; i++)
1110  {
1111  if (itCqi == m_p10CqiRxed.end ())
1112  {
1113  newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS
1114  }
1115  else
1116  {
1117  newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) );
1118  }
1119  }
1120  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
1121  uint16_t rlcPduSize = tbSize / lcNum;
1122  while ((*it).m_rnti == newEl.m_rnti)
1123  {
1124  if ( ((*it).m_rlcTransmissionQueueSize > 0)
1125  || ((*it).m_rlcRetransmissionQueueSize > 0)
1126  || ((*it).m_rlcStatusPduSize > 0) )
1127  {
1128  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1129  for (uint8_t j = 0; j < nLayer; j++)
1130  {
1131  RlcPduListElement_s newRlcEl;
1132  newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
1133  NS_LOG_INFO (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
1134  newRlcEl.m_size = rlcPduSize;
1135  UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
1136  newRlcPduLe.push_back (newRlcEl);
1137 
1138  if (m_harqOn == true)
1139  {
1140  // store RLC PDU list for HARQ
1141  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*it).m_rnti);
1142  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1143  {
1144  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*it).m_rnti);
1145  }
1146  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1147  }
1148 
1149  }
1150  newEl.m_rlcPduList.push_back (newRlcPduLe);
1151  lcNum--;
1152  }
1153  it++;
1154  if (it == m_rlcBufferReq.end ())
1155  {
1156  // restart from the first
1157  it = m_rlcBufferReq.begin ();
1158  break;
1159  }
1160  }
1161  uint32_t rbgMask = 0;
1162  uint16_t i = 0;
1163  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);
1164  NS_LOG_INFO ("RBG:");
1165  while (i < rbgPerTb)
1166  {
1167  if (rbgMap.at (rbgAllocated) == false)
1168  {
1169  rbgMask = rbgMask + (0x1 << rbgAllocated);
1170  NS_LOG_INFO ("\t " << rbgAllocated);
1171  i++;
1172  rbgMap.at (rbgAllocated) = true;
1173  rbgAllocatedNum++;
1174  }
1175  rbgAllocated++;
1176  }
1177  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1178 
1179  for (int i = 0; i < nLayer; i++)
1180  {
1181  newDci.m_tbsSize.push_back (tbSize);
1182  newDci.m_ndi.push_back (1);
1183  newDci.m_rv.push_back (0);
1184  }
1185  newEl.m_dci = newDci;
1186  if (m_harqOn == true)
1187  {
1188  // store DCI for HARQ
1189  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1190  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1191  {
1192  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1193  }
1194  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1195  // refresh timer
1196  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1197  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1198  {
1199  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1200  }
1201  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1202  }
1203  // ...more parameters -> ignored in this version
1204 
1205  ret.m_buildDataList.push_back (newEl);
1206  if (rbgAllocatedNum == rbgNum)
1207  {
1208  m_nextRntiDl = newEl.m_rnti; // store last RNTI served
1209  break; // no more RGB to be allocated
1210  }
1211  }
1212  while ((*it).m_rnti != m_nextRntiDl);
1213 
1214  ret.m_nrOfPdcchOfdmSymbols = 1;
1215 
1217  return;
1218 }
1219 
1220 void
1222 {
1223  NS_LOG_FUNCTION (this);
1224 
1225  m_rachList = params.m_rachList;
1226 
1227  return;
1228 }
1229 
1230 void
1232 {
1233  NS_LOG_FUNCTION (this);
1234 
1235  std::map <uint16_t,uint8_t>::iterator it;
1236  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1237  {
1238  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1239  {
1240  // wideband CQI reporting
1241  std::map <uint16_t,uint8_t>::iterator it;
1242  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1243  it = m_p10CqiRxed.find (rnti);
1244  if (it == m_p10CqiRxed.end ())
1245  {
1246  // create the new entry
1247  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)
1248  // generate correspondent timer
1249  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1250  }
1251  else
1252  {
1253  // update the CQI value
1254  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1255  // update correspondent timer
1256  std::map <uint16_t,uint32_t>::iterator itTimers;
1257  itTimers = m_p10CqiTimers.find (rnti);
1258  (*itTimers).second = m_cqiTimersThreshold;
1259  }
1260  }
1261  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1262  {
1263  // subband CQI reporting high layer configured
1264  // Not used by RR Scheduler
1265  }
1266  else
1267  {
1268  NS_LOG_ERROR (this << " CQI type unknown");
1269  }
1270  }
1271 
1272  return;
1273 }
1274 
1275 void
1277 {
1278  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1279 
1280  RefreshUlCqiMaps ();
1281 
1282  // Generate RBs map
1284  std::vector <bool> rbMap;
1285  uint16_t rbAllocatedNum = 0;
1286  std::set <uint16_t> rntiAllocated;
1287  std::vector <uint16_t> rbgAllocationMap;
1288  // update with RACH allocation map
1289  rbgAllocationMap = m_rachAllocationMap;
1290  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1291  m_rachAllocationMap.clear ();
1293 
1294  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1295  // remove RACH allocation
1296  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1297  {
1298  if (rbgAllocationMap.at (i) != 0)
1299  {
1300  rbMap.at (i) = true;
1301  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1302  }
1303  }
1304 
1305  if (m_harqOn == true)
1306  {
1307  // Process UL HARQ feedback
1308  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1309  {
1310  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1311  {
1312  // retx correspondent block: retrieve the UL-DCI
1313  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1314  std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1315  if (itProcId == m_ulHarqCurrentProcessId.end ())
1316  {
1317  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1318  }
1319  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1320  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
1321  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1322  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1323  {
1324  NS_LOG_ERROR ("No info find in UL-HARQ buffer for UE (might change eNB) " << rnti);
1325  }
1326  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1327  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1328  if (itStat == m_ulHarqProcessesStatus.end ())
1329  {
1330  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1331  }
1332  if ((*itStat).second.at (harqId) > 3)
1333  {
1334  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1335  continue;
1336  }
1337  bool free = true;
1338  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1339  {
1340  if (rbMap.at (j) == true)
1341  {
1342  free = false;
1343  NS_LOG_INFO (this << " BUSY " << j);
1344  }
1345  }
1346  if (free)
1347  {
1348  // retx on the same RBs
1349  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1350  {
1351  rbMap.at (j) = true;
1352  rbgAllocationMap.at (j) = dci.m_rnti;
1353  NS_LOG_INFO ("\tRB " << j);
1354  rbAllocatedNum++;
1355  }
1356  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);
1357  }
1358  else
1359  {
1360  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1361  continue;
1362  }
1363  dci.m_ndi = 0;
1364  // Update HARQ buffers with new HarqId
1365  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1366  (*itStat).second.at (harqId) = 0;
1367  (*itHarq).second.at ((*itProcId).second) = dci;
1368  ret.m_dciList.push_back (dci);
1369  rntiAllocated.insert (dci.m_rnti);
1370  }
1371  }
1372  }
1373 
1374  std::map <uint16_t,uint32_t>::iterator it;
1375  int nflows = 0;
1376 
1377  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1378  {
1379  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1380  // select UEs with queues not empty and not yet allocated for HARQ
1381  NS_LOG_INFO (this << " UE " << (*it).first << " queue " << (*it).second);
1382  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1383  {
1384  nflows++;
1385  }
1386  }
1387 
1388  if (nflows == 0)
1389  {
1390  if (ret.m_dciList.size () > 0)
1391  {
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 - 1) < m_cschedCellConfig.m_ulBandwidth) && (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:59
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:345
#define HARQ_PERIOD
Definition: lte-common.h:30
Hold a bool native type.
Definition: boolean.h:38
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
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)
Definition: assert.h:64
NS_OBJECT_ENSURE_REGISTERED(NullMessageSimulatorImpl)
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)
Definition: log.h:298
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
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
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.
NS_LOG_COMPONENT_DEFINE("RrFfMacScheduler")
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)
Definition: log.h:368
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)
Definition: assert.h:86
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
#define HARQ_PROC_NUM
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
int Type0AllocationRbg[4]
Parameters of the SCHED_UL_MAC_CTRL_INFO_REQ primitive.
#define NS_LOG_DEBUG(msg)
Definition: log.h:289
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)
Definition: log.h:271
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...
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
std::map< uint16_t, uint32_t > m_ceBsrRxed
struct DlDciListElement_s m_dci
#define HARQ_DL_TIMEOUT
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:611
virtual void CschedLcConfigReq(const struct CschedLcConfigReqParameters &params)
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.