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