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