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