A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
pf-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 
25 #include <ns3/simulator.h>
26 #include <ns3/lte-amc.h>
27 #include <ns3/pf-ff-mac-scheduler.h>
28 #include <ns3/lte-vendor-specific-parameters.h>
29 #include <ns3/boolean.h>
30 #include <cfloat>
31 #include <set>
32 
33 
34 NS_LOG_COMPONENT_DEFINE ("PfFfMacScheduler");
35 
36 namespace ns3 {
37 
38 static const int PfType0AllocationRbg[4] = {
39  10, // RGB size 1
40  26, // RGB size 2
41  63, // RGB size 3
42  110 // RGB size 4
43 }; // see table 7.1.6.1-1 of 36.213
44 
45 
46 NS_OBJECT_ENSURE_REGISTERED (PfFfMacScheduler);
47 
48 
49 
51 {
52 public:
54 
55  // inherited from FfMacCschedSapProvider
56  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
57  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
58  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
59  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
60  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
61 
62 private:
65 };
66 
68 {
69 }
70 
72 {
73 }
74 
75 
76 void
78 {
80 }
81 
82 void
84 {
86 }
87 
88 
89 void
91 {
93 }
94 
95 void
97 {
99 }
100 
101 void
103 {
105 }
106 
107 
108 
109 
111 {
112 public:
114 
115  // inherited from FfMacSchedSapProvider
116  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
117  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
118  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
119  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
120  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
121  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
122  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
123  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
124  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
125  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
126  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
127 
128 
129 private:
132 };
133 
134 
135 
137 {
138 }
139 
140 
142  : m_scheduler (scheduler)
143 {
144 }
145 
146 void
148 {
150 }
151 
152 void
154 {
156 }
157 
158 void
160 {
162 }
163 
164 void
166 {
168 }
169 
170 void
172 {
174 }
175 
176 void
178 {
180 }
181 
182 void
184 {
186 }
187 
188 void
190 {
192 }
193 
194 void
196 {
198 }
199 
200 void
202 {
204 }
205 
206 void
208 {
210 }
211 
212 
213 
214 
215 
217  : m_cschedSapUser (0),
218  m_schedSapUser (0),
219  m_timeWindow (99.0),
220  m_nextRntiUl (0)
221 {
222  m_amc = CreateObject <LteAmc> ();
225  m_ffrSapProvider = 0;
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  delete m_ffrSapUser;
248 }
249 
250 TypeId
252 {
253  static TypeId tid = TypeId ("ns3::PfFfMacScheduler")
255  .AddConstructor<PfFfMacScheduler> ()
256  .AddAttribute ("CqiTimerThreshold",
257  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
258  UintegerValue (1000),
259  MakeUintegerAccessor (&PfFfMacScheduler::m_cqiTimersThreshold),
260  MakeUintegerChecker<uint32_t> ())
261  .AddAttribute ("HarqEnabled",
262  "Activate/Deactivate the HARQ [by default is active].",
263  BooleanValue (true),
264  MakeBooleanAccessor (&PfFfMacScheduler::m_harqOn),
265  MakeBooleanChecker ())
266  .AddAttribute ("UlGrantMcs",
267  "The MCS of the UL grant, must be [0..15] (default 0)",
268  UintegerValue (0),
269  MakeUintegerAccessor (&PfFfMacScheduler::m_ulGrantMcs),
270  MakeUintegerChecker<uint8_t> ())
271  ;
272  return tid;
273 }
274 
275 
276 
277 void
279 {
280  m_cschedSapUser = s;
281 }
282 
283 void
285 {
286  m_schedSapUser = s;
287 }
288 
291 {
292  return m_cschedSapProvider;
293 }
294 
297 {
298  return m_schedSapProvider;
299 }
300 
301 void
303 {
305 }
306 
309 {
310  return m_ffrSapUser;
311 }
312 
313 void
315 {
316  NS_LOG_FUNCTION (this);
317  // Read the subset of parameters used
318  m_cschedCellConfig = params;
321  cnf.m_result = SUCCESS;
323  return;
324 }
325 
326 void
328 {
329  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
330  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
331  if (it == m_uesTxMode.end ())
332  {
333  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
334  // generate HARQ buffers
335  m_dlHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
336  DlHarqProcessesStatus_t dlHarqPrcStatus;
337  dlHarqPrcStatus.resize (8,0);
338  m_dlHarqProcessesStatus.insert (std::pair <uint16_t, DlHarqProcessesStatus_t> (params.m_rnti, dlHarqPrcStatus));
339  DlHarqProcessesTimer_t dlHarqProcessesTimer;
340  dlHarqProcessesTimer.resize (8,0);
341  m_dlHarqProcessesTimer.insert (std::pair <uint16_t, DlHarqProcessesTimer_t> (params.m_rnti, dlHarqProcessesTimer));
342  DlHarqProcessesDciBuffer_t dlHarqdci;
343  dlHarqdci.resize (8);
344  m_dlHarqProcessesDciBuffer.insert (std::pair <uint16_t, DlHarqProcessesDciBuffer_t> (params.m_rnti, dlHarqdci));
345  DlHarqRlcPduListBuffer_t dlHarqRlcPdu;
346  dlHarqRlcPdu.resize (2);
347  dlHarqRlcPdu.at (0).resize (8);
348  dlHarqRlcPdu.at (1).resize (8);
349  m_dlHarqProcessesRlcPduListBuffer.insert (std::pair <uint16_t, DlHarqRlcPduListBuffer_t> (params.m_rnti, dlHarqRlcPdu));
350  m_ulHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
351  UlHarqProcessesStatus_t ulHarqPrcStatus;
352  ulHarqPrcStatus.resize (8,0);
353  m_ulHarqProcessesStatus.insert (std::pair <uint16_t, UlHarqProcessesStatus_t> (params.m_rnti, ulHarqPrcStatus));
354  UlHarqProcessesDciBuffer_t ulHarqdci;
355  ulHarqdci.resize (8);
356  m_ulHarqProcessesDciBuffer.insert (std::pair <uint16_t, UlHarqProcessesDciBuffer_t> (params.m_rnti, ulHarqdci));
357  }
358  else
359  {
360  (*it).second = params.m_transmissionMode;
361  }
362  return;
363 }
364 
365 void
367 {
368  NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti);
369 
370  std::map <uint16_t, pfsFlowPerf_t>::iterator it;
371  for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++)
372  {
373  it = m_flowStatsDl.find (params.m_rnti);
374 
375  if (it == m_flowStatsDl.end ())
376  {
377  pfsFlowPerf_t flowStatsDl;
378  flowStatsDl.flowStart = Simulator::Now ();
379  flowStatsDl.totalBytesTransmitted = 0;
380  flowStatsDl.lastTtiBytesTrasmitted = 0;
381  flowStatsDl.lastAveragedThroughput = 1;
382  m_flowStatsDl.insert (std::pair<uint16_t, pfsFlowPerf_t> (params.m_rnti, flowStatsDl));
383  pfsFlowPerf_t flowStatsUl;
384  flowStatsUl.flowStart = Simulator::Now ();
385  flowStatsUl.totalBytesTransmitted = 0;
386  flowStatsUl.lastTtiBytesTrasmitted = 0;
387  flowStatsUl.lastAveragedThroughput = 1;
388  m_flowStatsUl.insert (std::pair<uint16_t, pfsFlowPerf_t> (params.m_rnti, flowStatsUl));
389  }
390  }
391 
392  return;
393 }
394 
395 void
397 {
398  NS_LOG_FUNCTION (this);
399  for (uint16_t i = 0; i < params.m_logicalChannelIdentity.size (); i++)
400  {
401  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
402  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator temp;
403  while (it!=m_rlcBufferReq.end ())
404  {
405  if (((*it).first.m_rnti == params.m_rnti) && ((*it).first.m_lcId == params.m_logicalChannelIdentity.at (i)))
406  {
407  temp = it;
408  it++;
409  m_rlcBufferReq.erase (temp);
410  }
411  else
412  {
413  it++;
414  }
415  }
416  }
417  return;
418 }
419 
420 void
422 {
423  NS_LOG_FUNCTION (this);
424 
425  m_uesTxMode.erase (params.m_rnti);
426  m_dlHarqCurrentProcessId.erase (params.m_rnti);
427  m_dlHarqProcessesStatus.erase (params.m_rnti);
428  m_dlHarqProcessesTimer.erase (params.m_rnti);
429  m_dlHarqProcessesDciBuffer.erase (params.m_rnti);
431  m_ulHarqCurrentProcessId.erase (params.m_rnti);
432  m_ulHarqProcessesStatus.erase (params.m_rnti);
433  m_ulHarqProcessesDciBuffer.erase (params.m_rnti);
434  m_flowStatsDl.erase (params.m_rnti);
435  m_flowStatsUl.erase (params.m_rnti);
436  m_ceBsrRxed.erase (params.m_rnti);
437  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
438  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator temp;
439  while (it!=m_rlcBufferReq.end ())
440  {
441  if ((*it).first.m_rnti == params.m_rnti)
442  {
443  temp = it;
444  it++;
445  m_rlcBufferReq.erase (temp);
446  }
447  else
448  {
449  it++;
450  }
451  }
452  if (m_nextRntiUl == params.m_rnti)
453  {
454  m_nextRntiUl = 0;
455  }
456 
457  return;
458 }
459 
460 
461 void
463 {
464  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
465  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
466 
467  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
468 
469  LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity);
470 
471  it = m_rlcBufferReq.find (flow);
472 
473  if (it == m_rlcBufferReq.end ())
474  {
475  m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters> (flow, params));
476  }
477  else
478  {
479  (*it).second = params;
480  }
481 
482  return;
483 }
484 
485 void
487 {
488  NS_LOG_FUNCTION (this);
489  NS_FATAL_ERROR ("method not implemented");
490  return;
491 }
492 
493 void
495 {
496  NS_LOG_FUNCTION (this);
497  NS_FATAL_ERROR ("method not implemented");
498  return;
499 }
500 
501 int
503 {
504  for (int i = 0; i < 4; i++)
505  {
506  if (dlbandwidth < PfType0AllocationRbg[i])
507  {
508  return (i + 1);
509  }
510  }
511 
512  return (-1);
513 }
514 
515 
516 int
518 {
519  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
520  int lcActive = 0;
521  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
522  {
523  if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueSize > 0)
524  || ((*it).second.m_rlcRetransmissionQueueSize > 0)
525  || ((*it).second.m_rlcStatusPduSize > 0) ))
526  {
527  lcActive++;
528  }
529  if ((*it).first.m_rnti > rnti)
530  {
531  break;
532  }
533  }
534  return (lcActive);
535 
536 }
537 
538 
539 uint8_t
541 {
542  NS_LOG_FUNCTION (this << rnti);
543 
544  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
545  if (it == m_dlHarqCurrentProcessId.end ())
546  {
547  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
548  }
549  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
550  if (itStat == m_dlHarqProcessesStatus.end ())
551  {
552  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
553  }
554  uint8_t i = (*it).second;
555  do
556  {
557  i = (i + 1) % HARQ_PROC_NUM;
558  }
559  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
560  if ((*itStat).second.at (i) == 0)
561  {
562  return (true);
563  }
564  else
565  {
566  return (false); // return a not valid harq proc id
567  }
568 }
569 
570 
571 
572 uint8_t
574 {
575  NS_LOG_FUNCTION (this << rnti);
576 
577  if (m_harqOn == false)
578  {
579  return (0);
580  }
581 
582 
583  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
584  if (it == m_dlHarqCurrentProcessId.end ())
585  {
586  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
587  }
588  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
589  if (itStat == m_dlHarqProcessesStatus.end ())
590  {
591  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
592  }
593  uint8_t i = (*it).second;
594  do
595  {
596  i = (i + 1) % HARQ_PROC_NUM;
597  }
598  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
599  if ((*itStat).second.at (i) == 0)
600  {
601  (*it).second = i;
602  (*itStat).second.at (i) = 1;
603  }
604  else
605  {
606  NS_FATAL_ERROR ("No HARQ process available for RNTI " << rnti << " check before update with HarqProcessAvailability");
607  }
608 
609  return ((*it).second);
610 }
611 
612 
613 void
615 {
616  NS_LOG_FUNCTION (this);
617 
618  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
619  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers++)
620  {
621  for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
622  {
623  if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
624  {
625  // reset HARQ process
626 
627  NS_LOG_DEBUG (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
628  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
629  if (itStat == m_dlHarqProcessesStatus.end ())
630  {
631  NS_FATAL_ERROR ("No Process Id Status found for this RNTI " << (*itTimers).first);
632  }
633  (*itStat).second.at (i) = 0;
634  (*itTimers).second.at (i) = 0;
635  }
636  else
637  {
638  (*itTimers).second.at (i)++;
639  }
640  }
641  }
642 
643 }
644 
645 
646 void
648 {
649  NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
650  // API generated by RLC for triggering the scheduling of a DL subframe
651 
652 
653  // evaluate the relative channel quality indicator for each UE per each RBG
654  // (since we are using allocation type 0 the small unit of allocation is RBG)
655  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
656 
657  RefreshDlCqiMaps ();
658 
660  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
661  std::map <uint16_t, std::vector <uint16_t> > allocationMap; // RBs map per RNTI
662  std::vector <bool> rbgMap; // global RBGs map
663  uint16_t rbgAllocatedNum = 0;
664  std::set <uint16_t> rntiAllocated;
665  rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
666 
667  rbgMap = m_ffrSapProvider->GetAvailableDlRbg ();
668  for (std::vector<bool>::iterator it = rbgMap.begin (); it != rbgMap.end (); it++)
669  {
670  if ((*it) == true )
671  {
672  rbgAllocatedNum++;
673  }
674  }
675 
677 
678  // update UL HARQ proc id
679  std::map <uint16_t, uint8_t>::iterator itProcId;
680  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
681  {
682  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
683  }
684 
685 
686  // RACH Allocation
687  uint16_t rbAllocatedNum = 0;
688  std::vector <bool> ulRbMap;
689  ulRbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
690  ulRbMap = m_ffrSapProvider->GetAvailableUlRbg ();
691  uint8_t maxContinuousUlBandwidth = 0;
692  uint8_t tmpMinBandwidth = 0;
693  uint16_t ffrRbStartOffset = 0;
694  uint16_t tmpFfrRbStartOffset = 0;
695  uint16_t index = 0;
696 
697  for (std::vector<bool>::iterator it = ulRbMap.begin (); it != ulRbMap.end (); it++)
698  {
699  if ((*it) == true )
700  {
701  rbAllocatedNum++;
702  if (tmpMinBandwidth > maxContinuousUlBandwidth)
703  {
704  maxContinuousUlBandwidth = tmpMinBandwidth;
705  ffrRbStartOffset = tmpFfrRbStartOffset;
706  }
707  tmpMinBandwidth = 0;
708  }
709  else
710  {
711  if (tmpMinBandwidth == 0)
712  {
713  tmpFfrRbStartOffset = index;
714  }
715  tmpMinBandwidth++;
716  }
717  index++;
718  }
719 
720  if (tmpMinBandwidth > maxContinuousUlBandwidth)
721  {
722  maxContinuousUlBandwidth = tmpMinBandwidth;
723  ffrRbStartOffset = tmpFfrRbStartOffset;
724  }
725 
727  uint16_t rbStart = 0;
728  rbStart = ffrRbStartOffset;
729  std::vector <struct RachListElement_s>::iterator itRach;
730  for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
731  {
732  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");
733  BuildRarListElement_s newRar;
734  newRar.m_rnti = (*itRach).m_rnti;
735  // DL-RACH Allocation
736  // Ideal: no needs of configuring m_dci
737  // UL-RACH Allocation
738  newRar.m_grant.m_rnti = newRar.m_rnti;
739  newRar.m_grant.m_mcs = m_ulGrantMcs;
740  uint16_t rbLen = 1;
741  uint16_t tbSizeBits = 0;
742  // find lowest TB size that fits UL grant estimated size
743  while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < (ffrRbStartOffset + maxContinuousUlBandwidth)))
744  {
745  rbLen++;
746  tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
747  }
748  if (tbSizeBits < (*itRach).m_estimatedSize)
749  {
750  // no more allocation space: finish allocation
751  break;
752  }
753  newRar.m_grant.m_rbStart = rbStart;
754  newRar.m_grant.m_rbLen = rbLen;
755  newRar.m_grant.m_tbSize = tbSizeBits / 8;
756  newRar.m_grant.m_hopping = false;
757  newRar.m_grant.m_tpc = 0;
758  newRar.m_grant.m_cqiRequest = false;
759  newRar.m_grant.m_ulDelay = false;
760  NS_LOG_INFO (this << " UL grant allocated to RNTI " << (*itRach).m_rnti << " rbStart " << rbStart << " rbLen " << rbLen << " MCS " << m_ulGrantMcs << " tbSize " << newRar.m_grant.m_tbSize);
761  for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
762  {
763  m_rachAllocationMap.at (i) = (*itRach).m_rnti;
764  }
765 
766  if (m_harqOn == true)
767  {
768  // generate UL-DCI for HARQ retransmissions
769  UlDciListElement_s uldci;
770  uldci.m_rnti = newRar.m_rnti;
771  uldci.m_rbLen = rbLen;
772  uldci.m_rbStart = rbStart;
773  uldci.m_mcs = m_ulGrantMcs;
774  uldci.m_tbSize = tbSizeBits / 8;
775  uldci.m_ndi = 1;
776  uldci.m_cceIndex = 0;
777  uldci.m_aggrLevel = 1;
778  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
779  uldci.m_hopping = false;
780  uldci.m_n2Dmrs = 0;
781  uldci.m_tpc = 0; // no power control
782  uldci.m_cqiRequest = false; // only period CQI at this stage
783  uldci.m_ulIndex = 0; // TDD parameter
784  uldci.m_dai = 1; // TDD parameter
785  uldci.m_freqHopping = 0;
786  uldci.m_pdcchPowerOffset = 0; // not used
787 
788  uint8_t harqId = 0;
789  std::map <uint16_t, uint8_t>::iterator itProcId;
790  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
791  if (itProcId == m_ulHarqCurrentProcessId.end ())
792  {
793  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
794  }
795  harqId = (*itProcId).second;
796  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
797  if (itDci == m_ulHarqProcessesDciBuffer.end ())
798  {
799  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
800  }
801  (*itDci).second.at (harqId) = uldci;
802  }
803 
804  rbStart = rbStart + rbLen;
805  ret.m_buildRarList.push_back (newRar);
806  }
807  m_rachList.clear ();
808 
809 
810  // Process DL HARQ feedback
812  // retrieve past HARQ retx buffered
813  if (m_dlInfoListBuffered.size () > 0)
814  {
815  if (params.m_dlInfoList.size () > 0)
816  {
817  NS_LOG_INFO (this << " Received DL-HARQ feedback");
818  m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
819  }
820  }
821  else
822  {
823  if (params.m_dlInfoList.size () > 0)
824  {
826  }
827  }
828  if (m_harqOn == false)
829  {
830  // Ignore HARQ feedback
831  m_dlInfoListBuffered.clear ();
832  }
833  std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
834  for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
835  {
836  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
837  if (itRnti != rntiAllocated.end ())
838  {
839  // RNTI already allocated for retx
840  continue;
841  }
842  uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
843  std::vector <bool> retx;
844  NS_LOG_INFO (this << " Processing DLHARQ feedback");
845  if (nLayers == 1)
846  {
847  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
848  retx.push_back (false);
849  }
850  else
851  {
852  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
853  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
854  }
855  if (retx.at (0) || retx.at (1))
856  {
857  // retrieve HARQ process information
858  uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
859  uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
860  NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
861  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
862  if (itHarq == m_dlHarqProcessesDciBuffer.end ())
863  {
864  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
865  }
866 
867  DlDciListElement_s dci = (*itHarq).second.at (harqId);
868  int rv = 0;
869  if (dci.m_rv.size () == 1)
870  {
871  rv = dci.m_rv.at (0);
872  }
873  else
874  {
875  rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
876  }
877 
878  if (rv == 3)
879  {
880  // maximum number of retx reached -> drop process
881  NS_LOG_INFO ("Maximum number of retransmissions reached -> drop process");
882  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
883  if (it == m_dlHarqProcessesStatus.end ())
884  {
885  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
886  }
887  (*it).second.at (harqId) = 0;
888  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
889  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
890  {
891  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
892  }
893  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
894  {
895  (*itRlcPdu).second.at (k).at (harqId).clear ();
896  }
897  continue;
898  }
899  // check the feasibility of retransmitting on the same RBGs
900  // translate the DCI to Spectrum framework
901  std::vector <int> dciRbg;
902  uint32_t mask = 0x1;
903  NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
904  for (int j = 0; j < 32; j++)
905  {
906  if (((dci.m_rbBitmap & mask) >> j) == 1)
907  {
908  dciRbg.push_back (j);
909  NS_LOG_INFO ("\t" << j);
910  }
911  mask = (mask << 1);
912  }
913  bool free = true;
914  for (uint8_t j = 0; j < dciRbg.size (); j++)
915  {
916  if (rbgMap.at (dciRbg.at (j)) == true)
917  {
918  free = false;
919  break;
920  }
921  }
922  if (free)
923  {
924  // use the same RBGs for the retx
925  // reserve RBGs
926  for (uint8_t j = 0; j < dciRbg.size (); j++)
927  {
928  rbgMap.at (dciRbg.at (j)) = true;
929  NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
930  rbgAllocatedNum++;
931  }
932 
933  NS_LOG_INFO (this << " Send retx in the same RBGs");
934  }
935  else
936  {
937  // find RBGs for sending HARQ retx
938  uint8_t j = 0;
939  uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % rbgNum;
940  uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
941  std::vector <bool> rbgMapCopy = rbgMap;
942  while ((j < dciRbg.size ())&&(startRbg != rbgId))
943  {
944  if (rbgMapCopy.at (rbgId) == false)
945  {
946  rbgMapCopy.at (rbgId) = true;
947  dciRbg.at (j) = rbgId;
948  j++;
949  }
950  rbgId = (rbgId + 1) % rbgNum;
951  }
952  if (j == dciRbg.size ())
953  {
954  // find new RBGs -> update DCI map
955  uint32_t rbgMask = 0;
956  for (uint16_t k = 0; k < dciRbg.size (); k++)
957  {
958  rbgMask = rbgMask + (0x1 << dciRbg.at (k));
959  rbgAllocatedNum++;
960  }
961  dci.m_rbBitmap = rbgMask;
962  rbgMap = rbgMapCopy;
963  NS_LOG_INFO (this << " Move retx in RBGs " << dciRbg.size ());
964  }
965  else
966  {
967  // HARQ retx cannot be performed on this TTI -> store it
968  dlInfoListUntxed.push_back (m_dlInfoListBuffered.at (i));
969  NS_LOG_INFO (this << " No resource for this retx -> buffer it");
970  }
971  }
972  // retrieve RLC PDU list for retx TBsize and update DCI
974  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
975  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
976  {
977  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
978  }
979  for (uint8_t j = 0; j < nLayers; j++)
980  {
981  if (retx.at (j))
982  {
983  if (j >= dci.m_ndi.size ())
984  {
985  // for avoiding errors in MIMO transient phases
986  dci.m_ndi.push_back (0);
987  dci.m_rv.push_back (0);
988  dci.m_mcs.push_back (0);
989  dci.m_tbsSize.push_back (0);
990  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
991  }
992  else
993  {
994  dci.m_ndi.at (j) = 0;
995  dci.m_rv.at (j)++;
996  (*itHarq).second.at (harqId).m_rv.at (j)++;
997  NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
998  }
999  }
1000  else
1001  {
1002  // empty TB of layer j
1003  dci.m_ndi.at (j) = 0;
1004  dci.m_rv.at (j) = 0;
1005  dci.m_mcs.at (j) = 0;
1006  dci.m_tbsSize.at (j) = 0;
1007  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
1008  }
1009  }
1010  for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
1011  {
1012  std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
1013  for (uint8_t j = 0; j < nLayers; j++)
1014  {
1015  if (retx.at (j))
1016  {
1017  if (j < dci.m_ndi.size ())
1018  {
1019  rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
1020  }
1021  }
1022  }
1023 
1024  if (rlcPduListPerLc.size () > 0)
1025  {
1026  newEl.m_rlcPduList.push_back (rlcPduListPerLc);
1027  }
1028  }
1029  newEl.m_rnti = rnti;
1030  newEl.m_dci = dci;
1031  (*itHarq).second.at (harqId).m_rv = dci.m_rv;
1032  // refresh timer
1033  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
1034  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1035  {
1036  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
1037  }
1038  (*itHarqTimer).second.at (harqId) = 0;
1039  ret.m_buildDataList.push_back (newEl);
1040  rntiAllocated.insert (rnti);
1041  }
1042  else
1043  {
1044  // update HARQ process status
1045  NS_LOG_INFO (this << " HARQ received ACK for UE " << m_dlInfoListBuffered.at (i).m_rnti);
1046  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
1047  if (it == m_dlHarqProcessesStatus.end ())
1048  {
1049  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
1050  }
1051  (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
1052  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
1053  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1054  {
1055  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
1056  }
1057  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
1058  {
1059  (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
1060  }
1061  }
1062  }
1063  m_dlInfoListBuffered.clear ();
1064  m_dlInfoListBuffered = dlInfoListUntxed;
1065 
1066  if (rbgAllocatedNum == rbgNum)
1067  {
1068  // all the RBGs are already allocated -> exit
1069  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
1070  {
1072  }
1073  return;
1074  }
1075 
1076 
1077 
1078  for (int i = 0; i < rbgNum; i++)
1079  {
1080  NS_LOG_INFO (this << " ALLOCATION for RBG " << i << " of " << rbgNum);
1081  if (rbgMap.at (i) == false)
1082  {
1083  std::map <uint16_t, pfsFlowPerf_t>::iterator it;
1084  std::map <uint16_t, pfsFlowPerf_t>::iterator itMax = m_flowStatsDl.end ();
1085  double rcqiMax = 0.0;
1086  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
1087  {
1088  if ((m_ffrSapProvider->IsDlRbgAvailableForUe (i, (*it).first)) == false)
1089  continue;
1090 
1091  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1092  if ((itRnti != rntiAllocated.end ())||(!HarqProcessAvailability ((*it).first)))
1093  {
1094  // UE already allocated for HARQ or without HARQ process available -> drop it
1095  if (itRnti != rntiAllocated.end ())
1096  {
1097  NS_LOG_DEBUG (this << " RNTI discared for HARQ tx" << (uint16_t)(*it).first);
1098  }
1099  if (!HarqProcessAvailability ((*it).first))
1100  {
1101  NS_LOG_DEBUG (this << " RNTI discared for HARQ id" << (uint16_t)(*it).first);
1102  }
1103  continue;
1104  }
1105  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1106  itCqi = m_a30CqiRxed.find ((*it).first);
1107  std::map <uint16_t,uint8_t>::iterator itTxMode;
1108  itTxMode = m_uesTxMode.find ((*it).first);
1109  if (itTxMode == m_uesTxMode.end ())
1110  {
1111  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).first);
1112  }
1113  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1114  std::vector <uint8_t> sbCqi;
1115  if (itCqi == m_a30CqiRxed.end ())
1116  {
1117  for (uint8_t k = 0; k < nLayer; k++)
1118  {
1119  sbCqi.push_back (1); // start with lowest value
1120  }
1121  }
1122  else
1123  {
1124  sbCqi = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi;
1125  }
1126  uint8_t cqi1 = sbCqi.at (0);
1127  uint8_t cqi2 = 1;
1128  if (sbCqi.size () > 1)
1129  {
1130  cqi2 = sbCqi.at (1);
1131  }
1132 
1133  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1134  {
1135  if (LcActivePerFlow ((*it).first) > 0)
1136  {
1137  // this UE has data to transmit
1138  double achievableRate = 0.0;
1139  uint8_t mcs = 0;
1140  for (uint8_t k = 0; k < nLayer; k++)
1141  {
1142  if (sbCqi.size () > k)
1143  {
1144  mcs = m_amc->GetMcsFromCqi (sbCqi.at (k));
1145  }
1146  else
1147  {
1148  // no info on this subband -> worst MCS
1149  mcs = 0;
1150  }
1151  achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, rbgSize) / 8) / 0.001); // = TB size / TTI
1152  }
1153 
1154  double rcqi = achievableRate / (*it).second.lastAveragedThroughput;
1155  NS_LOG_INFO (this << " RNTI " << (*it).first << " MCS " << (uint32_t)mcs << " achievableRate " << achievableRate << " avgThr " << (*it).second.lastAveragedThroughput << " RCQI " << rcqi);
1156 
1157  if (rcqi > rcqiMax)
1158  {
1159  rcqiMax = rcqi;
1160  itMax = it;
1161  }
1162  }
1163  } // end if cqi
1164  } // end for m_rlcBufferReq
1165 
1166  if (itMax == m_flowStatsDl.end ())
1167  {
1168  // no UE available for this RB
1169  NS_LOG_INFO (this << " any UE found");
1170  }
1171  else
1172  {
1173  rbgMap.at (i) = true;
1174  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1175  itMap = allocationMap.find ((*itMax).first);
1176  if (itMap == allocationMap.end ())
1177  {
1178  // insert new element
1179  std::vector <uint16_t> tempMap;
1180  tempMap.push_back (i);
1181  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax).first, tempMap));
1182  }
1183  else
1184  {
1185  (*itMap).second.push_back (i);
1186  }
1187  NS_LOG_INFO (this << " UE assigned " << (*itMax).first);
1188  }
1189  } // end for RBG free
1190  } // end for RBGs
1191 
1192  // reset TTI stats of users
1193  std::map <uint16_t, pfsFlowPerf_t>::iterator itStats;
1194  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
1195  {
1196  (*itStats).second.lastTtiBytesTrasmitted = 0;
1197  }
1198 
1199  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
1200  // creating the correspondent DCIs
1201  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
1202  while (itMap != allocationMap.end ())
1203  {
1204  // create new BuildDataListElement_s for this LC
1205  BuildDataListElement_s newEl;
1206  newEl.m_rnti = (*itMap).first;
1207  // create the DlDciListElement_s
1208  DlDciListElement_s newDci;
1209  newDci.m_rnti = (*itMap).first;
1210  newDci.m_harqProcess = UpdateHarqProcessId ((*itMap).first);
1211 
1212  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
1213  NS_LOG_INFO (this << "Allocate user " << newEl.m_rnti << " rbg " << lcActives);
1214  if (lcActives == 0)
1215  {
1216  // Set to max value, to avoid divide by 0 below
1217  lcActives = (uint16_t)65535; // UINT16_MAX;
1218  }
1219  uint16_t RgbPerRnti = (*itMap).second.size ();
1220  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
1221  itCqi = m_a30CqiRxed.find ((*itMap).first);
1222  std::map <uint16_t,uint8_t>::iterator itTxMode;
1223  itTxMode = m_uesTxMode.find ((*itMap).first);
1224  if (itTxMode == m_uesTxMode.end ())
1225  {
1226  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
1227  }
1228  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1229  std::vector <uint8_t> worstCqi (2, 15);
1230  if (itCqi != m_a30CqiRxed.end ())
1231  {
1232  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1233  {
1234  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
1235  {
1236  NS_LOG_INFO (this << " RBG " << (*itMap).second.at (k) << " CQI " << (uint16_t)((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (0)) );
1237  for (uint8_t j = 0; j < nLayer; j++)
1238  {
1239  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
1240  {
1241  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
1242  {
1243  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
1244  }
1245  }
1246  else
1247  {
1248  // no CQI for this layer of this suband -> worst one
1249  worstCqi.at (j) = 1;
1250  }
1251  }
1252  }
1253  else
1254  {
1255  for (uint8_t j = 0; j < nLayer; j++)
1256  {
1257  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1258  }
1259  }
1260  }
1261  }
1262  else
1263  {
1264  for (uint8_t j = 0; j < nLayer; j++)
1265  {
1266  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
1267  }
1268  }
1269  for (uint8_t j = 0; j < nLayer; j++)
1270  {
1271  NS_LOG_INFO (this << " Layer " << (uint16_t)j << " CQI selected " << (uint16_t)worstCqi.at (j));
1272  }
1273  uint32_t bytesTxed = 0;
1274  for (uint8_t j = 0; j < nLayer; j++)
1275  {
1276  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
1277  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (j), RgbPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
1278  newDci.m_tbsSize.push_back (tbSize);
1279  NS_LOG_INFO (this << " Layer " << (uint16_t)j << " MCS selected" << m_amc->GetMcsFromCqi (worstCqi.at (j)));
1280  bytesTxed += tbSize;
1281  }
1282 
1283  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
1284  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
1285  uint32_t rbgMask = 0;
1286  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
1287  {
1288  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
1289  NS_LOG_INFO (this << " Allocated RBG " << (*itMap).second.at (k));
1290  }
1291  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1292 
1293  // create the rlc PDUs -> equally divide resources among actives LCs
1294  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
1295  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
1296  {
1297  if (((*itBufReq).first.m_rnti == (*itMap).first)
1298  && (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
1299  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
1300  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
1301  {
1302  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1303  for (uint8_t j = 0; j < nLayer; j++)
1304  {
1305  RlcPduListElement_s newRlcEl;
1306  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
1307  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
1308  NS_LOG_INFO (this << " LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << newRlcEl.m_size << " layer " << (uint16_t)j);
1309  newRlcPduLe.push_back (newRlcEl);
1310  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
1311  if (m_harqOn == true)
1312  {
1313  // store RLC PDU list for HARQ
1314  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*itMap).first);
1315  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1316  {
1317  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*itMap).first);
1318  }
1319  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1320  }
1321  }
1322  newEl.m_rlcPduList.push_back (newRlcPduLe);
1323  }
1324  if ((*itBufReq).first.m_rnti > (*itMap).first)
1325  {
1326  break;
1327  }
1328  }
1329  for (uint8_t j = 0; j < nLayer; j++)
1330  {
1331  newDci.m_ndi.push_back (1);
1332  newDci.m_rv.push_back (0);
1333  }
1334 
1335  newDci.m_tpc = m_ffrSapProvider->GetTpc ((*itMap).first);
1336 
1337  newEl.m_dci = newDci;
1338 
1339  if (m_harqOn == true)
1340  {
1341  // store DCI for HARQ
1342  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1343  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1344  {
1345  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << newEl.m_rnti);
1346  }
1347  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1348  // refresh timer
1349  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1350  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1351  {
1352  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1353  }
1354  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1355  }
1356 
1357  // ...more parameters -> ingored in this version
1358 
1359  ret.m_buildDataList.push_back (newEl);
1360  // update UE stats
1361  std::map <uint16_t, pfsFlowPerf_t>::iterator it;
1362  it = m_flowStatsDl.find ((*itMap).first);
1363  if (it != m_flowStatsDl.end ())
1364  {
1365  (*it).second.lastTtiBytesTrasmitted = bytesTxed;
1366  NS_LOG_INFO (this << " UE total bytes txed " << (*it).second.lastTtiBytesTrasmitted);
1367 
1368 
1369  }
1370  else
1371  {
1372  NS_FATAL_ERROR (this << " No Stats for this allocated UE");
1373  }
1374 
1375  itMap++;
1376  } // end while allocation
1377  ret.m_nrOfPdcchOfdmSymbols = 1;
1378 
1379 
1380  // update UEs stats
1381  NS_LOG_INFO (this << " Update UEs statistics");
1382  for (itStats = m_flowStatsDl.begin (); itStats != m_flowStatsDl.end (); itStats++)
1383  {
1384  (*itStats).second.totalBytesTransmitted += (*itStats).second.lastTtiBytesTrasmitted;
1385  // update average throughput (see eq. 12.3 of Sec 12.3.1.2 of LTE – The UMTS Long Term Evolution, Ed Wiley)
1386  (*itStats).second.lastAveragedThroughput = ((1.0 - (1.0 / m_timeWindow)) * (*itStats).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTrasmitted / 0.001));
1387  NS_LOG_INFO (this << " UE total bytes " << (*itStats).second.totalBytesTransmitted);
1388  NS_LOG_INFO (this << " UE average throughput " << (*itStats).second.lastAveragedThroughput);
1389  (*itStats).second.lastTtiBytesTrasmitted = 0;
1390  }
1391 
1393 
1394 
1395  return;
1396 }
1397 
1398 void
1400 {
1401  NS_LOG_FUNCTION (this);
1402 
1403  m_rachList = params.m_rachList;
1404 
1405  return;
1406 }
1407 
1408 void
1410 {
1411  NS_LOG_FUNCTION (this);
1413 
1414  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1415  {
1416  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1417  {
1418  // wideband CQI reporting
1419  std::map <uint16_t,uint8_t>::iterator it;
1420  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1421  it = m_p10CqiRxed.find (rnti);
1422  if (it == m_p10CqiRxed.end ())
1423  {
1424  // create the new entry
1425  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)
1426  // generate correspondent timer
1427  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1428  }
1429  else
1430  {
1431  // update the CQI value and refresh correspondent timer
1432  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1433  // update correspondent timer
1434  std::map <uint16_t,uint32_t>::iterator itTimers;
1435  itTimers = m_p10CqiTimers.find (rnti);
1436  (*itTimers).second = m_cqiTimersThreshold;
1437  }
1438  }
1439  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1440  {
1441  // subband CQI reporting high layer configured
1442  std::map <uint16_t,SbMeasResult_s>::iterator it;
1443  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1444  it = m_a30CqiRxed.find (rnti);
1445  if (it == m_a30CqiRxed.end ())
1446  {
1447  // create the new entry
1448  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
1449  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1450  }
1451  else
1452  {
1453  // update the CQI value and refresh correspondent timer
1454  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
1455  std::map <uint16_t,uint32_t>::iterator itTimers;
1456  itTimers = m_a30CqiTimers.find (rnti);
1457  (*itTimers).second = m_cqiTimersThreshold;
1458  }
1459  }
1460  else
1461  {
1462  NS_LOG_ERROR (this << " CQI type unknown");
1463  }
1464  }
1465 
1466  return;
1467 }
1468 
1469 
1470 double
1471 PfFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
1472 {
1473  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
1474  if (itCqi == m_ueCqi.end ())
1475  {
1476  // no cqi info about this UE
1477  return (NO_SINR);
1478 
1479  }
1480  else
1481  {
1482  // take the average SINR value among the available
1483  double sinrSum = 0;
1484  int sinrNum = 0;
1485  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1486  {
1487  double sinr = (*itCqi).second.at (i);
1488  if (sinr != NO_SINR)
1489  {
1490  sinrSum += sinr;
1491  sinrNum++;
1492  }
1493  }
1494  double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
1495  // store the value
1496  (*itCqi).second.at (rb) = estimatedSinr;
1497  return (estimatedSinr);
1498  }
1499 }
1500 
1501 void
1503 {
1504  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf) << " size " << params.m_ulInfoList.size ());
1505 
1506  RefreshUlCqiMaps ();
1508 
1509  // Generate RBs map
1511  std::vector <bool> rbMap;
1512  uint16_t rbAllocatedNum = 0;
1513  std::set <uint16_t> rntiAllocated;
1514  std::vector <uint16_t> rbgAllocationMap;
1515  // update with RACH allocation map
1516  rbgAllocationMap = m_rachAllocationMap;
1517  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1518  m_rachAllocationMap.clear ();
1520 
1521  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1522  rbMap = m_ffrSapProvider->GetAvailableUlRbg ();
1523 
1524  for (std::vector<bool>::iterator it = rbMap.begin (); it != rbMap.end (); it++)
1525  {
1526  if ((*it) == true )
1527  {
1528  rbAllocatedNum++;
1529  }
1530  }
1531 
1532  uint8_t minContinuousUlBandwidth = m_ffrSapProvider->GetMinContinuousUlBandwidth ();
1533  uint8_t ffrUlBandwidth = m_cschedCellConfig.m_ulBandwidth - rbAllocatedNum;
1534 
1535  // remove RACH allocation
1536  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1537  {
1538  if (rbgAllocationMap.at (i) != 0)
1539  {
1540  rbMap.at (i) = true;
1541  NS_LOG_DEBUG (this << " Allocated for RACH " << i);
1542  }
1543  }
1544 
1545 
1546  if (m_harqOn == true)
1547  {
1548  // Process UL HARQ feedback
1549 
1550  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1551  {
1552  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1553  {
1554  // retx correspondent block: retrieve the UL-DCI
1555  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1556  std::map <uint16_t, uint8_t>::iterator itProcId = m_ulHarqCurrentProcessId.find (rnti);
1557  if (itProcId == m_ulHarqCurrentProcessId.end ())
1558  {
1559  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1560  }
1561  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1562  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId << " i " << i << " size " << params.m_ulInfoList.size ());
1563  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1564  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1565  {
1566  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1567  continue;
1568  }
1569  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1570  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1571  if (itStat == m_ulHarqProcessesStatus.end ())
1572  {
1573  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1574  }
1575  if ((*itStat).second.at (harqId) >= 3)
1576  {
1577  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1578  continue;
1579  }
1580  bool free = true;
1581  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1582  {
1583  if (rbMap.at (j) == true)
1584  {
1585  free = false;
1586  NS_LOG_INFO (this << " BUSY " << j);
1587  }
1588  }
1589  if (free)
1590  {
1591  // retx on the same RBs
1592  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1593  {
1594  rbMap.at (j) = true;
1595  rbgAllocationMap.at (j) = dci.m_rnti;
1596  NS_LOG_INFO ("\tRB " << j);
1597  rbAllocatedNum++;
1598  }
1599  NS_LOG_INFO (this << " Send retx in the same RBs " << (uint16_t)dci.m_rbStart << " to " << dci.m_rbStart + dci.m_rbLen << " RV " << (*itStat).second.at (harqId) + 1);
1600  }
1601  else
1602  {
1603  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1604  continue;
1605  }
1606  dci.m_ndi = 0;
1607  // Update HARQ buffers with new HarqId
1608  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1609  (*itStat).second.at (harqId) = 0;
1610  (*itHarq).second.at ((*itProcId).second) = dci;
1611  ret.m_dciList.push_back (dci);
1612  rntiAllocated.insert (dci.m_rnti);
1613  }
1614  else
1615  {
1616  NS_LOG_INFO (this << " HARQ-ACK feedback from RNTI " << params.m_ulInfoList.at (i).m_rnti);
1617  }
1618  }
1619  }
1620 
1621  std::map <uint16_t,uint32_t>::iterator it;
1622  int nflows = 0;
1623 
1624  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1625  {
1626  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1627  // select UEs with queues not empty and not yet allocated for HARQ
1628  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1629  {
1630  nflows++;
1631  }
1632  }
1633 
1634  if (nflows == 0)
1635  {
1636  if (ret.m_dciList.size () > 0)
1637  {
1638  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1640  }
1641 
1642  return; // no flows to be scheduled
1643  }
1644 
1645 
1646  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1647  uint16_t tempRbPerFlow = (ffrUlBandwidth) / (nflows + rntiAllocated.size ());
1648  uint16_t rbPerFlow = (minContinuousUlBandwidth < tempRbPerFlow) ? minContinuousUlBandwidth : tempRbPerFlow;
1649 
1650  if (rbPerFlow < 3)
1651  {
1652  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1653  }
1654 
1655  int rbAllocated = 0;
1656 
1657  std::map <uint16_t, pfsFlowPerf_t>::iterator itStats;
1658  if (m_nextRntiUl != 0)
1659  {
1660  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1661  {
1662  if ((*it).first == m_nextRntiUl)
1663  {
1664  break;
1665  }
1666  }
1667  if (it == m_ceBsrRxed.end ())
1668  {
1669  NS_LOG_ERROR (this << " no user found");
1670  }
1671  }
1672  else
1673  {
1674  it = m_ceBsrRxed.begin ();
1675  m_nextRntiUl = (*it).first;
1676  }
1677  do
1678  {
1679  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1680  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1681  {
1682  // UE already allocated for UL-HARQ -> skip it
1683  NS_LOG_DEBUG (this << " UE already allocated in HARQ -> discared, RNTI " << (*it).first);
1684  it++;
1685  if (it == m_ceBsrRxed.end ())
1686  {
1687  // restart from the first
1688  it = m_ceBsrRxed.begin ();
1689  }
1690  continue;
1691  }
1692  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1693  {
1694  // limit to physical resources last resource assignment
1695  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1696  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1697  if (rbPerFlow < 3)
1698  {
1699  // terminate allocation
1700  rbPerFlow = 0;
1701  }
1702  }
1703 
1704  rbAllocated = 0;
1705  UlDciListElement_s uldci;
1706  uldci.m_rnti = (*it).first;
1707  uldci.m_rbLen = rbPerFlow;
1708  bool allocated = false;
1709 
1710  while ((!allocated)&&((rbAllocated + rbPerFlow - m_cschedCellConfig.m_ulBandwidth) < 1) && (rbPerFlow != 0))
1711  {
1712  // check availability
1713  bool free = true;
1714  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1715  {
1716  if (rbMap.at (j) == true)
1717  {
1718  free = false;
1719  break;
1720  }
1721  if ((m_ffrSapProvider->IsUlRbgAvailableForUe (j, (*it).first)) == false)
1722  {
1723  free = false;
1724  break;
1725  }
1726  }
1727  if (free)
1728  {
1729  NS_LOG_INFO (this << "RNTI: "<< (*it).first<< " RB Allocated " << rbAllocated << " rbPerFlow " << rbPerFlow << " flows " << nflows);
1730  uldci.m_rbStart = rbAllocated;
1731 
1732  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1733  {
1734  rbMap.at (j) = true;
1735  // store info on allocation for managing ul-cqi interpretation
1736  rbgAllocationMap.at (j) = (*it).first;
1737  }
1738  rbAllocated += rbPerFlow;
1739  allocated = true;
1740  break;
1741  }
1742  rbAllocated++;
1743  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1744  {
1745  // limit to physical resources last resource assignment
1746  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1747  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1748  if (rbPerFlow < 3)
1749  {
1750  // terminate allocation
1751  rbPerFlow = 0;
1752  }
1753  }
1754  }
1755  if (!allocated)
1756  {
1757  // unable to allocate new resource: finish scheduling
1758  m_nextRntiUl = (*it).first;
1759 // if (ret.m_dciList.size () > 0)
1760 // {
1761 // m_schedSapUser->SchedUlConfigInd (ret);
1762 // }
1763 // m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1764 // return;
1765  break;
1766  }
1767 
1768 
1769 
1770  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1771  int cqi = 0;
1772  if (itCqi == m_ueCqi.end ())
1773  {
1774  // no cqi info about this UE
1775  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1776  }
1777  else
1778  {
1779  // take the lowest CQI value (worst RB)
1780  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1781  if (minSinr == NO_SINR)
1782  {
1783  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
1784  }
1785  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1786  {
1787  double sinr = (*itCqi).second.at (i);
1788  if (sinr == NO_SINR)
1789  {
1790  sinr = EstimateUlSinr ((*it).first, i);
1791  }
1792  if ((*itCqi).second.at (i) < minSinr)
1793  {
1794  minSinr = (*itCqi).second.at (i);
1795  }
1796  }
1797 
1798  // translate SINR -> cqi: WILD ACK: same as DL
1799  double s = log2 ( 1 + (
1800  std::pow (10, minSinr / 10 ) /
1801  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1802  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1803  if (cqi == 0)
1804  {
1805  it++;
1806  if (it == m_ceBsrRxed.end ())
1807  {
1808  // restart from the first
1809  it = m_ceBsrRxed.begin ();
1810  }
1811  NS_LOG_DEBUG (this << " UE discared for CQI=0, RNTI " << uldci.m_rnti);
1812  // remove UE from allocation map
1813  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1814  {
1815  rbgAllocationMap.at (i) = 0;
1816  }
1817  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1818  }
1819  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1820  }
1821 
1822  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
1823  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1824  uldci.m_ndi = 1;
1825  uldci.m_cceIndex = 0;
1826  uldci.m_aggrLevel = 1;
1827  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1828  uldci.m_hopping = false;
1829  uldci.m_n2Dmrs = 0;
1830  uldci.m_tpc = 0; // no power control
1831  uldci.m_cqiRequest = false; // only period CQI at this stage
1832  uldci.m_ulIndex = 0; // TDD parameter
1833  uldci.m_dai = 1; // TDD parameter
1834  uldci.m_freqHopping = 0;
1835  uldci.m_pdcchPowerOffset = 0; // not used
1836  ret.m_dciList.push_back (uldci);
1837  // store DCI for HARQ_PERIOD
1838  uint8_t harqId = 0;
1839  if (m_harqOn == true)
1840  {
1841  std::map <uint16_t, uint8_t>::iterator itProcId;
1842  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1843  if (itProcId == m_ulHarqCurrentProcessId.end ())
1844  {
1845  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1846  }
1847  harqId = (*itProcId).second;
1848  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1849  if (itDci == m_ulHarqProcessesDciBuffer.end ())
1850  {
1851  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1852  }
1853  (*itDci).second.at (harqId) = uldci;
1854  // Update HARQ process status (RV 0)
1855  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (uldci.m_rnti);
1856  if (itStat == m_ulHarqProcessesStatus.end ())
1857  {
1858  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << uldci.m_rnti);
1859  }
1860  (*itStat).second.at (harqId) = 0;
1861  }
1862 
1863  NS_LOG_INFO (this << " UE Allocation RNTI " << (*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 << " RbAlloc " << rbAllocated << " harqId " << (uint16_t)harqId);
1864 
1865  // update TTI UE stats
1866  itStats = m_flowStatsUl.find ((*it).first);
1867  if (itStats != m_flowStatsUl.end ())
1868  {
1869  (*itStats).second.lastTtiBytesTrasmitted = uldci.m_tbSize;
1870  }
1871  else
1872  {
1873  NS_LOG_DEBUG (this << " No Stats for this allocated UE");
1874  }
1875 
1876 
1877  it++;
1878  if (it == m_ceBsrRxed.end ())
1879  {
1880  // restart from the first
1881  it = m_ceBsrRxed.begin ();
1882  }
1883  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1884  {
1885  // Stop allocation: no more PRBs
1886  m_nextRntiUl = (*it).first;
1887  break;
1888  }
1889  }
1890  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1891 
1892 
1893  // Update global UE stats
1894  // update UEs stats
1895  for (itStats = m_flowStatsUl.begin (); itStats != m_flowStatsUl.end (); itStats++)
1896  {
1897  (*itStats).second.totalBytesTransmitted += (*itStats).second.lastTtiBytesTrasmitted;
1898  // update average throughput (see eq. 12.3 of Sec 12.3.1.2 of LTE – The UMTS Long Term Evolution, Ed Wiley)
1899  (*itStats).second.lastAveragedThroughput = ((1.0 - (1.0 / m_timeWindow)) * (*itStats).second.lastAveragedThroughput) + ((1.0 / m_timeWindow) * (double)((*itStats).second.lastTtiBytesTrasmitted / 0.001));
1900  NS_LOG_INFO (this << " UE total bytes " << (*itStats).second.totalBytesTransmitted);
1901  NS_LOG_INFO (this << " UE average throughput " << (*itStats).second.lastAveragedThroughput);
1902  (*itStats).second.lastTtiBytesTrasmitted = 0;
1903  }
1904  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1906 
1907  return;
1908 }
1909 
1910 void
1912 {
1913  NS_LOG_FUNCTION (this);
1914  return;
1915 }
1916 
1917 void
1919 {
1920  NS_LOG_FUNCTION (this);
1921  return;
1922 }
1923 
1924 void
1926 {
1927  NS_LOG_FUNCTION (this);
1928 
1929  std::map <uint16_t,uint32_t>::iterator it;
1930 
1931  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1932  {
1933  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1934  {
1935  // buffer status report
1936  // note that this scheduler does not differentiate the
1937  // allocation according to which LCGs have more/less bytes
1938  // to send.
1939  // Hence the BSR of different LCGs are just summed up to get
1940  // a total queue size that is used for allocation purposes.
1941 
1942  uint32_t buffer = 0;
1943  for (uint8_t lcg = 0; lcg < 4; ++lcg)
1944  {
1945  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1946  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1947  }
1948 
1949  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1950  NS_LOG_LOGIC (this << "RNTI=" << rnti << " buffer=" << buffer);
1951  it = m_ceBsrRxed.find (rnti);
1952  if (it == m_ceBsrRxed.end ())
1953  {
1954  // create the new entry
1955  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1956  }
1957  else
1958  {
1959  // update the buffer size value
1960  (*it).second = buffer;
1961  }
1962  }
1963  }
1964 
1965  return;
1966 }
1967 
1968 void
1970 {
1971  NS_LOG_FUNCTION (this);
1973 
1974 // retrieve the allocation for this subframe
1975  switch (m_ulCqiFilter)
1976  {
1978  {
1979  // filter all the CQIs that are not SRS based
1980  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
1981  {
1982  return;
1983  }
1984  }
1985  break;
1987  {
1988  // filter all the CQIs that are not SRS based
1989  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
1990  {
1991  return;
1992  }
1993  }
1995  break;
1996 
1997  default:
1998  NS_FATAL_ERROR ("Unknown UL CQI type");
1999  }
2000 
2001  switch (params.m_ulCqi.m_type)
2002  {
2003  case UlCqi_s::PUSCH:
2004  {
2005  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
2006  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2007  NS_LOG_DEBUG (this << " Collect PUSCH CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
2008  itMap = m_allocationMaps.find (params.m_sfnSf);
2009  if (itMap == m_allocationMaps.end ())
2010  {
2011  return;
2012  }
2013  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
2014  {
2015  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
2016  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
2017  itCqi = m_ueCqi.find ((*itMap).second.at (i));
2018  if (itCqi == m_ueCqi.end ())
2019  {
2020  // create a new entry
2021  std::vector <double> newCqi;
2022  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2023  {
2024  if (i == j)
2025  {
2026  newCqi.push_back (sinr);
2027  }
2028  else
2029  {
2030  // initialize with NO_SINR value.
2031  newCqi.push_back (NO_SINR);
2032  }
2033 
2034  }
2035  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
2036  // generate correspondent timer
2037  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
2038  }
2039  else
2040  {
2041  // update the value
2042  (*itCqi).second.at (i) = sinr;
2043  NS_LOG_DEBUG (this << " RNTI " << (*itMap).second.at (i) << " RB " << i << " SINR " << sinr);
2044  // update correspondent timer
2045  std::map <uint16_t, uint32_t>::iterator itTimers;
2046  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
2047  (*itTimers).second = m_cqiTimersThreshold;
2048 
2049  }
2050 
2051  }
2052  // remove obsolete info on allocation
2053  m_allocationMaps.erase (itMap);
2054  }
2055  break;
2056  case UlCqi_s::SRS:
2057  {
2058  NS_LOG_DEBUG (this << " Collect SRS CQIs of Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
2059  // get the RNTI from vendor specific parameters
2060  uint16_t rnti = 0;
2061  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
2062  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
2063  {
2064  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
2065  {
2066  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
2067  rnti = vsp->GetRnti ();
2068  }
2069  }
2070  std::map <uint16_t, std::vector <double> >::iterator itCqi;
2071  itCqi = m_ueCqi.find (rnti);
2072  if (itCqi == m_ueCqi.end ())
2073  {
2074  // create a new entry
2075  std::vector <double> newCqi;
2076  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2077  {
2078  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2079  newCqi.push_back (sinr);
2080  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
2081 
2082  }
2083  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
2084  // generate correspondent timer
2085  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
2086  }
2087  else
2088  {
2089  // update the values
2090  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
2091  {
2092  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
2093  (*itCqi).second.at (j) = sinr;
2094  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
2095  }
2096  // update correspondent timer
2097  std::map <uint16_t, uint32_t>::iterator itTimers;
2098  itTimers = m_ueCqiTimers.find (rnti);
2099  (*itTimers).second = m_cqiTimersThreshold;
2100 
2101  }
2102 
2103 
2104  }
2105  break;
2106  case UlCqi_s::PUCCH_1:
2107  case UlCqi_s::PUCCH_2:
2108  case UlCqi_s::PRACH:
2109  {
2110  NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
2111  }
2112  break;
2113  default:
2114  NS_FATAL_ERROR ("Unknown type of UL-CQI");
2115  }
2116  return;
2117 }
2118 
2119 void
2121 {
2122  // refresh DL CQI P01 Map
2123  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
2124  while (itP10 != m_p10CqiTimers.end ())
2125  {
2126  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2127  if ((*itP10).second == 0)
2128  {
2129  // delete correspondent entries
2130  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
2131  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
2132  NS_LOG_INFO (this << " P10-CQI expired for user " << (*itP10).first);
2133  m_p10CqiRxed.erase (itMap);
2134  std::map <uint16_t,uint32_t>::iterator temp = itP10;
2135  itP10++;
2136  m_p10CqiTimers.erase (temp);
2137  }
2138  else
2139  {
2140  (*itP10).second--;
2141  itP10++;
2142  }
2143  }
2144 
2145  // refresh DL CQI A30 Map
2146  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
2147  while (itA30 != m_a30CqiTimers.end ())
2148  {
2149  NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2150  if ((*itA30).second == 0)
2151  {
2152  // delete correspondent entries
2153  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
2154  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
2155  NS_LOG_INFO (this << " A30-CQI expired for user " << (*itA30).first);
2156  m_a30CqiRxed.erase (itMap);
2157  std::map <uint16_t,uint32_t>::iterator temp = itA30;
2158  itA30++;
2159  m_a30CqiTimers.erase (temp);
2160  }
2161  else
2162  {
2163  (*itA30).second--;
2164  itA30++;
2165  }
2166  }
2167 
2168  return;
2169 }
2170 
2171 
2172 void
2174 {
2175  // refresh UL CQI Map
2176  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
2177  while (itUl != m_ueCqiTimers.end ())
2178  {
2179  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
2180  if ((*itUl).second == 0)
2181  {
2182  // delete correspondent entries
2183  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
2184  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
2185  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
2186  (*itMap).second.clear ();
2187  m_ueCqi.erase (itMap);
2188  std::map <uint16_t,uint32_t>::iterator temp = itUl;
2189  itUl++;
2190  m_ueCqiTimers.erase (temp);
2191  }
2192  else
2193  {
2194  (*itUl).second--;
2195  itUl++;
2196  }
2197  }
2198 
2199  return;
2200 }
2201 
2202 void
2203 PfFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
2204 {
2205  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
2206  LteFlowId_t flow (rnti, lcid);
2207  it = m_rlcBufferReq.find (flow);
2208  if (it != m_rlcBufferReq.end ())
2209  {
2210  NS_LOG_INFO (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).second.m_rlcTransmissionQueueSize << " retxqueue " << (*it).second.m_rlcRetransmissionQueueSize << " status " << (*it).second.m_rlcStatusPduSize << " decrease " << size);
2211  // Update queues: RLC tx order Status, ReTx, Tx
2212  // Update status queue
2213  if (((*it).second.m_rlcStatusPduSize > 0) && (size >= (*it).second.m_rlcStatusPduSize))
2214  {
2215  (*it).second.m_rlcStatusPduSize = 0;
2216  }
2217  else if (((*it).second.m_rlcRetransmissionQueueSize > 0) && (size >= (*it).second.m_rlcRetransmissionQueueSize))
2218  {
2219  (*it).second.m_rlcRetransmissionQueueSize = 0;
2220  }
2221  else if ((*it).second.m_rlcTransmissionQueueSize > 0)
2222  {
2223  uint32_t rlcOverhead;
2224  if (lcid == 1)
2225  {
2226  // for SRB1 (using RLC AM) it's better to
2227  // overestimate RLC overhead rather than
2228  // underestimate it and risk unneeded
2229  // segmentation which increases delay
2230  rlcOverhead = 4;
2231  }
2232  else
2233  {
2234  // minimum RLC overhead due to header
2235  rlcOverhead = 2;
2236  }
2237  // update transmission queue
2238  if ((*it).second.m_rlcTransmissionQueueSize <= size - rlcOverhead)
2239  {
2240  (*it).second.m_rlcTransmissionQueueSize = 0;
2241  }
2242  else
2243  {
2244  (*it).second.m_rlcTransmissionQueueSize -= size - rlcOverhead;
2245  }
2246  }
2247  }
2248  else
2249  {
2250  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
2251  }
2252 }
2253 
2254 void
2255 PfFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
2256 {
2257 
2258  size = size - 2; // remove the minimum RLC overhead
2259  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
2260  if (it != m_ceBsrRxed.end ())
2261  {
2262  NS_LOG_INFO (this << " UE " << rnti << " size " << size << " BSR " << (*it).second);
2263  if ((*it).second >= size)
2264  {
2265  (*it).second -= size;
2266  }
2267  else
2268  {
2269  (*it).second = 0;
2270  }
2271  }
2272  else
2273  {
2274  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
2275  }
2276 
2277 }
2278 
2279 void
2281 {
2282  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
2284  params.m_rnti = rnti;
2285  params.m_transmissionMode = txMode;
2287 }
2288 
2289 
2290 }
friend class PfSchedulerMemberCschedSapProvider
std::vector< struct UlInfoListElement_s > m_ulInfoList
See section 4.3.1 dlDciListElement.
Definition: ff-mac-common.h:88
void DoSchedUlCqiInfoReq(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
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 "...
void DoSchedUlTriggerReq(const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters &params)
#define HARQ_PERIOD
Definition: lte-common.h:30
virtual void SetLteFfrSapProvider(LteFfrSapProvider *s)
Set the Provider part of the LteFfrSap that this Scheduler will interact with.
Hold a bool native type.
Definition: boolean.h:38
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
virtual void ReportUlCqiInfo(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)=0
ReportUlCqiInfo.
std::map< LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters > m_rlcBufferReq
void DoSchedUlMacCtrlInfoReq(const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters &params)
void DoSchedDlCqiInfoReq(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
Parameters of the CSCHED_UE_CONFIG_CNF primitive.
Parameters of the CSCHED_UE_RELEASE_REQ primitive.
virtual bool IsDlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in DL.
virtual bool IsUlRbgAvailableForUe(int i, uint16_t rnti)=0
Check if UE can be served on i-th RB in UL.
enum ns3::UlCqi_s::Type_e m_type
std::map< uint16_t, pfsFlowPerf_t > m_flowStatsUl
Implements the SCHED SAP and CSCHED SAP for a Proportional Fair scheduler.
std::vector< UlDciListElement_s > UlHarqProcessesDciBuffer_t
std::map< uint16_t, std::vector< double > > m_ueCqi
virtual void SchedDlRachInfoReq(const struct SchedDlRachInfoReqParameters &params)
std::vector< struct LogicalChannelConfigListElement_s > m_logicalChannelConfigList
std::vector< uint16_t > m_sinr
std::vector< uint8_t > DlHarqProcessesTimer_t
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
#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
int LcActivePerFlow(uint16_t rnti)
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
virtual void SchedDlCqiInfoReq(const struct SchedDlCqiInfoReqParameters &params)
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
virtual void CschedCellConfigReq(const struct CschedCellConfigReqParameters &params)
CSCHED_CELL_CONFIG_REQ.
std::vector< uint8_t > m_mcs
Definition: ff-mac-common.h:95
See section 4.3.2 ulDciListElement.
std::map< uint16_t, UlHarqProcessesStatus_t > m_ulHarqProcessesStatus
Provides the CSCHED SAP.
std::map< uint16_t, pfsFlowPerf_t > m_flowStatsDl
std::vector< struct UlDciListElement_s > m_dciList
virtual ~PfFfMacScheduler()
Destructor.
#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.
Parameters of the CSCHED_UE_CONFIG_UPDATE_IND primitive.
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
set the user part of the FfMacSchedSap that this Scheduler will interact with.
virtual void SchedUlTriggerReq(const struct SchedUlTriggerReqParameters &params)
Parameters of the CSCHED_LC_RELEASE_REQ primitive.
virtual uint8_t GetTpc(uint16_t rnti)=0
GetTpc.
std::vector< std::vector< struct RlcPduListElement_s > > m_rlcPduList
Parameters of the SCHED_DL_TRIGGER_REQ primitive.
double EstimateUlSinr(uint16_t rnti, uint16_t rb)
void UpdateDlRlcBufferInfo(uint16_t rnti, uint8_t lcid, uint16_t size)
void TransmissionModeConfigurationUpdate(uint16_t rnti, uint8_t txMode)
unsigned int lastTtiBytesTrasmitted
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
LteFfrSapUser * m_ffrSapUser
std::vector< RlcPduList_t > DlHarqRlcPduListBuffer_t
Parameters of the SCHED_DL_MAC_BUFFER_REQ primitive.
std::map< uint16_t, uint32_t > m_a30CqiTimers
Parameters of the SCHED_DL_PAGING_BUFFER_REQ primitive.
static const int PfType0AllocationRbg[4]
virtual void CschedUeConfigUpdateInd(const struct CschedUeConfigUpdateIndParameters &params)=0
std::vector< struct VendorSpecificListElement_s > m_vendorSpecificList
void DoSchedUlNoiseInterferenceReq(const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters &params)
void DoSchedDlMacBufferReq(const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters &params)
std::vector< struct RachListElement_s > m_rachList
Service Access Point (SAP) offered by the Frequency Reuse algorithm instance to the MAC Scheduler ins...
Definition: lte-ffr-sap.h:39
FfMacSchedSapProvider * m_schedSapProvider
Parameters of the SCHED_UL_TRIGGER_REQ primitive.
Hold an unsigned integer type.
Definition: uinteger.h:46
virtual void SchedUlMacCtrlInfoReq(const struct SchedUlMacCtrlInfoReqParameters &params)
std::map< uint16_t, DlHarqProcessesTimer_t > m_dlHarqProcessesTimer
static uint8_t TxMode2LayerNum(uint8_t txMode)
Definition: lte-common.cc:170
Ptr< SampleEmitter > s
std::vector< uint8_t > m_ndi
Definition: ff-mac-common.h:96
int GetRbgSize(int dlbandwidth)
Provides the SCHED SAP.
std::map< uint16_t, uint32_t > m_ueCqiTimers
std::vector< DlInfoListElement_s > m_dlInfoListBuffered
virtual void CschedUeConfigCnf(const struct CschedUeConfigCnfParameters &params)=0
FfMacSchedSapUser * m_schedSapUser
#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
virtual void DoDispose(void)
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
std::map< uint16_t, SbMeasResult_s > m_a30CqiRxed
bool m_harqOn
m_harqOn when false inhibit te HARQ mechanisms (by default active)
std::map< uint16_t, DlHarqRlcPduListBuffer_t > m_dlHarqProcessesRlcPduListBuffer
std::vector< struct DlInfoListElement_s > m_dlInfoList
virtual void SchedDlPagingBufferReq(const struct SchedDlPagingBufferReqParameters &params)
virtual void ReportDlCqiInfo(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)=0
ReportDlCqiInfo.
std::map< uint16_t, DlHarqProcessesDciBuffer_t > m_dlHarqProcessesDciBuffer
std::map< uint16_t, uint8_t > m_p10CqiRxed
void DoCschedLcConfigReq(const struct FfMacCschedSapProvider::CschedLcConfigReqParameters &params)
virtual void SchedDlConfigInd(const struct SchedDlConfigIndParameters &params)=0
virtual void CschedLcReleaseReq(const struct CschedLcReleaseReqParameters &params)
void DoCschedUeReleaseReq(const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters &params)
std::vector< uint16_t > m_tbsSize
Definition: ff-mac-common.h:94
See section 4.3.9 rlcPDU_ListElement.
FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig
FfMacCschedSapUser * m_cschedSapUser
std::map< uint16_t, uint8_t > m_dlHarqCurrentProcessId
virtual LteFfrSapUser * GetLteFfrSapUser()
friend class PfSchedulerMemberSchedSapProvider
std::vector< DlDciListElement_s > DlHarqProcessesDciBuffer_t
virtual void SchedUlNoiseInterferenceReq(const struct SchedUlNoiseInterferenceReqParameters &params)
Parameters of the CSCHED_LC_CONFIG_REQ primitive.
void DoCschedCellConfigReq(const struct FfMacCschedSapProvider::CschedCellConfigReqParameters &params)
std::vector< uint8_t > m_rv
Definition: ff-mac-common.h:97
static TypeId GetTypeId(void)
void DoSchedUlSrInfoReq(const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters &params)
std::map< uint16_t, std::vector< uint16_t > > m_allocationMaps
void UpdateUlRlcBufferInfo(uint16_t rnti, uint16_t size)
std::map< uint16_t, uint32_t > m_p10CqiTimers
std::map< uint16_t, uint32_t > m_ceBsrRxed
virtual std::vector< bool > GetAvailableUlRbg()=0
Get vector of available RB in UL for this Cell.
virtual uint8_t GetMinContinuousUlBandwidth()=0
GetMinContinuousUlBandwidth.
virtual void SchedUlConfigInd(const struct SchedUlConfigIndParameters &params)=0
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
void DoSchedDlRachInfoReq(const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters &params)
UlCqiFilter_t m_ulCqiFilter
std::map< uint16_t, uint8_t > m_ulHarqCurrentProcessId
#define SRS_CQI_RNTI_VSP
This abstract base class identifies the interface by means of which the helper object can plug on the...
void DoSchedDlTriggerReq(const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters &params)
FfMacCschedSapProvider * m_cschedSapProvider
#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
virtual void SchedDlMacBufferReq(const struct SchedDlMacBufferReqParameters &params)
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct MacCeListElement_s > m_macCeList
std::vector< uint16_t > m_rachAllocationMap
std::vector< struct RachListElement_s > m_rachList
static double fpS11dot3toDouble(uint16_t val)
Definition: lte-common.cc:114
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
std::map< uint16_t, DlHarqProcessesStatus_t > m_dlHarqProcessesStatus
std::vector< uint8_t > UlHarqProcessesStatus_t
unsigned long totalBytesTransmitted
std::vector< uint8_t > DlHarqProcessesStatus_t
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
static uint32_t BsrId2BufferSize(uint8_t val)
Definition: lte-common.cc:142
Template for the implementation of the LteFfrSapUser as a member of an owner class of type C to which...
Definition: lte-ffr-sap.h:244
LteFfrSapProvider * m_ffrSapProvider
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
virtual std::vector< bool > GetAvailableDlRbg()=0
Get vector of available RBG in DL for this Cell.
virtual void SchedUlCqiInfoReq(const struct SchedUlCqiInfoReqParameters &params)
std::map< uint16_t, UlHarqProcessesDciBuffer_t > m_ulHarqProcessesDciBuffer
virtual void SchedDlRlcBufferReq(const struct SchedDlRlcBufferReqParameters &params)
virtual void CschedUeConfigReq(const struct CschedUeConfigReqParameters &params)
Parameters of the SCHED_UL_SR_INFO_REQ primitive.
virtual void SchedUlSrInfoReq(const struct SchedUlSrInfoReqParameters &params)
void DoCschedLcReleaseReq(const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters &params)
virtual void CschedUeReleaseReq(const struct CschedUeReleaseReqParameters &params)
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:193
Parameters of the SCHED_DL_RACH_INFO_REQ primitive.
virtual void CschedLcConfigReq(const struct CschedLcConfigReqParameters &params)
Parameters of the SCHED_UL_CONFIG_IND primitive.
virtual void SchedDlTriggerReq(const struct SchedDlTriggerReqParameters &params)
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
set the user part of the FfMacCschedSap that this Scheduler will interact with.
Parameters of the CSCHED_UE_CONFIG_REQ primitive.
#define HARQ_DL_TIMEOUT
#define NO_SINR
struct DlDciListElement_s m_dci
std::vector< struct BuildRarListElement_s > m_buildRarList
void DoSchedDlPagingBufferReq(const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters &params)
a unique identifier for an interface.
Definition: type-id.h:49
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
std::map< uint16_t, uint8_t > m_uesTxMode
#define HARQ_PROC_NUM
void DoCschedUeConfigReq(const struct FfMacCschedSapProvider::CschedUeConfigReqParameters &params)
void DoSchedDlRlcBufferReq(const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
std::vector< struct BuildDataListElement_s > m_buildDataList
See section 4.3.8 builDataListElement.