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