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