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