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