A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
rr-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  */
20 
21 #include <ns3/log.h>
22 #include <ns3/pointer.h>
23 #include <ns3/math.h>
24 #include <set>
25 
26 #include <ns3/lte-amc.h>
27 #include <ns3/rr-ff-mac-scheduler.h>
28 #include <ns3/simulator.h>
29 #include <ns3/lte-common.h>
30 #include <ns3/lte-vendor-specific-parameters.h>
31 #include <ns3/boolean.h>
32 
33 NS_LOG_COMPONENT_DEFINE ("RrFfMacScheduler");
34 
35 namespace ns3 {
36 
37 int Type0AllocationRbg[4] = {
38  10, // RGB size 1
39  26, // RGB size 2
40  63, // RGB size 3
41  110 // RGB size 4
42 }; // see table 7.1.6.1-1 of 36.213
43 
44 
45 
46 
47 NS_OBJECT_ENSURE_REGISTERED (RrFfMacScheduler);
48 
49 
51 {
52 public:
54 
55  // inherited from FfMacCschedSapProvider
56  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
57  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
58  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
59  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
60  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
61 
62 private:
64  RrFfMacScheduler* m_scheduler;
65 };
66 
67 RrSchedulerMemberCschedSapProvider::RrSchedulerMemberCschedSapProvider ()
68 {
69 }
70 
71 RrSchedulerMemberCschedSapProvider::RrSchedulerMemberCschedSapProvider (RrFfMacScheduler* scheduler) : m_scheduler (scheduler)
72 {
73 }
74 
75 
76 void
78 {
79  m_scheduler->DoCschedCellConfigReq (params);
80 }
81 
82 void
83 RrSchedulerMemberCschedSapProvider::CschedUeConfigReq (const struct CschedUeConfigReqParameters& params)
84 {
85  m_scheduler->DoCschedUeConfigReq (params);
86 }
87 
88 
89 void
90 RrSchedulerMemberCschedSapProvider::CschedLcConfigReq (const struct CschedLcConfigReqParameters& params)
91 {
92  m_scheduler->DoCschedLcConfigReq (params);
93 }
94 
95 void
96 RrSchedulerMemberCschedSapProvider::CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params)
97 {
98  m_scheduler->DoCschedLcReleaseReq (params);
99 }
100 
101 void
102 RrSchedulerMemberCschedSapProvider::CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params)
103 {
104  m_scheduler->DoCschedUeReleaseReq (params);
105 }
106 
107 
108 
109 
111 {
112 public:
114 
115  // inherited from FfMacSchedSapProvider
116  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
117  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
118  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
119  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
120  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
121  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
122  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
123  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
124  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
125  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
126  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
127 
128 
129 private:
131  RrFfMacScheduler* m_scheduler;
132 };
133 
134 
135 
136 RrSchedulerMemberSchedSapProvider::RrSchedulerMemberSchedSapProvider ()
137 {
138 }
139 
140 
141 RrSchedulerMemberSchedSapProvider::RrSchedulerMemberSchedSapProvider (RrFfMacScheduler* scheduler)
142  : m_scheduler (scheduler)
143 {
144 }
145 
146 void
147 RrSchedulerMemberSchedSapProvider::SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params)
148 {
149  m_scheduler->DoSchedDlRlcBufferReq (params);
150 }
151 
152 void
153 RrSchedulerMemberSchedSapProvider::SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params)
154 {
155  m_scheduler->DoSchedDlPagingBufferReq (params);
156 }
157 
158 void
159 RrSchedulerMemberSchedSapProvider::SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params)
160 {
161  m_scheduler->DoSchedDlMacBufferReq (params);
162 }
163 
164 void
165 RrSchedulerMemberSchedSapProvider::SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params)
166 {
167  m_scheduler->DoSchedDlTriggerReq (params);
168 }
169 
170 void
171 RrSchedulerMemberSchedSapProvider::SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params)
172 {
173  m_scheduler->DoSchedDlRachInfoReq (params);
174 }
175 
176 void
177 RrSchedulerMemberSchedSapProvider::SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params)
178 {
179  m_scheduler->DoSchedDlCqiInfoReq (params);
180 }
181 
182 void
183 RrSchedulerMemberSchedSapProvider::SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params)
184 {
185  m_scheduler->DoSchedUlTriggerReq (params);
186 }
187 
188 void
189 RrSchedulerMemberSchedSapProvider::SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params)
190 {
191  m_scheduler->DoSchedUlNoiseInterferenceReq (params);
192 }
193 
194 void
195 RrSchedulerMemberSchedSapProvider::SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params)
196 {
197  m_scheduler->DoSchedUlSrInfoReq (params);
198 }
199 
200 void
201 RrSchedulerMemberSchedSapProvider::SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params)
202 {
203  m_scheduler->DoSchedUlMacCtrlInfoReq (params);
204 }
205 
206 void
207 RrSchedulerMemberSchedSapProvider::SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params)
208 {
209  m_scheduler->DoSchedUlCqiInfoReq (params);
210 }
211 
212 
213 
214 
215 
217  : m_cschedSapUser (0),
218  m_schedSapUser (0),
219  m_nextRntiDl (0),
220  m_nextRntiUl (0)
221 {
222  m_amc = CreateObject <LteAmc> ();
223  m_cschedSapProvider = new RrSchedulerMemberCschedSapProvider (this);
224  m_schedSapProvider = new RrSchedulerMemberSchedSapProvider (this);
225 }
226 
228 {
229  NS_LOG_FUNCTION (this);
230 }
231 
232 void
234 {
235  NS_LOG_FUNCTION (this);
236  m_dlHarqProcessesDciBuffer.clear ();
237  m_dlHarqProcessesTimer.clear ();
238  m_dlHarqProcessesRlcPduListBuffer.clear ();
239  m_dlInfoListBuffered.clear ();
240  m_ulHarqCurrentProcessId.clear ();
241  m_ulHarqProcessesStatus.clear ();
242  m_ulHarqProcessesDciBuffer.clear ();
243  delete m_cschedSapProvider;
244  delete m_schedSapProvider;
245 }
246 
247 TypeId
248 RrFfMacScheduler::GetTypeId (void)
249 {
250  static TypeId tid = TypeId ("ns3::RrFfMacScheduler")
252  .AddConstructor<RrFfMacScheduler> ()
253  .AddAttribute ("CqiTimerThreshold",
254  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
255  UintegerValue (1000),
256  MakeUintegerAccessor (&RrFfMacScheduler::m_cqiTimersThreshold),
257  MakeUintegerChecker<uint32_t> ())
258  .AddAttribute ("HarqEnabled",
259  "Activate/Deactivate the HARQ [by default is active].",
260  BooleanValue (true),
261  MakeBooleanAccessor (&RrFfMacScheduler::m_harqOn),
262  MakeBooleanChecker ())
263  .AddAttribute ("UlGrantMcs",
264  "The MCS of the UL grant, must be [0..15] (default 0)",
265  UintegerValue (0),
266  MakeUintegerAccessor (&RrFfMacScheduler::m_ulGrantMcs),
267  MakeUintegerChecker<uint8_t> ())
268  ;
269  return tid;
270 }
271 
272 
273 
274 void
276 {
277  m_cschedSapUser = s;
278 }
279 
280 void
282 {
283  m_schedSapUser = s;
284 }
285 
288 {
289  return m_cschedSapProvider;
290 }
291 
294 {
295  return m_schedSapProvider;
296 }
297 
298 void
299 RrFfMacScheduler::DoCschedCellConfigReq (const struct FfMacCschedSapProvider::CschedCellConfigReqParameters& params)
300 {
301  NS_LOG_FUNCTION (this);
302  // Read the subset of parameters used
303  m_cschedCellConfig = params;
304  m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
306  cnf.m_result = SUCCESS;
307  m_cschedSapUser->CschedUeConfigCnf (cnf);
308  return;
309 }
310 
311 void
312 RrFfMacScheduler::DoCschedUeConfigReq (const struct FfMacCschedSapProvider::CschedUeConfigReqParameters& params)
313 {
314  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
315  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
316  if (it == m_uesTxMode.end ())
317  {
318  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
319  // generate HARQ buffers
320  m_dlHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
321  DlHarqProcessesStatus_t dlHarqPrcStatus;
322  dlHarqPrcStatus.resize (8,0);
323  m_dlHarqProcessesStatus.insert (std::pair <uint16_t, DlHarqProcessesStatus_t> (params.m_rnti, dlHarqPrcStatus));
324  DlHarqProcessesTimer_t dlHarqProcessesTimer;
325  dlHarqProcessesTimer.resize (8,0);
326  m_dlHarqProcessesTimer.insert (std::pair <uint16_t, DlHarqProcessesTimer_t> (params.m_rnti, dlHarqProcessesTimer));
327  DlHarqProcessesDciBuffer_t dlHarqdci;
328  dlHarqdci.resize (8);
329  m_dlHarqProcessesDciBuffer.insert (std::pair <uint16_t, DlHarqProcessesDciBuffer_t> (params.m_rnti, dlHarqdci));
330  DlHarqRlcPduListBuffer_t dlHarqRlcPdu;
331  dlHarqRlcPdu.resize (2);
332  dlHarqRlcPdu.at (0).resize (8);
333  dlHarqRlcPdu.at (1).resize (8);
334  m_dlHarqProcessesRlcPduListBuffer.insert (std::pair <uint16_t, DlHarqRlcPduListBuffer_t> (params.m_rnti, dlHarqRlcPdu));
335  m_ulHarqCurrentProcessId.insert (std::pair <uint16_t,uint8_t > (params.m_rnti, 0));
336  UlHarqProcessesStatus_t ulHarqPrcStatus;
337  ulHarqPrcStatus.resize (8,0);
338  m_ulHarqProcessesStatus.insert (std::pair <uint16_t, UlHarqProcessesStatus_t> (params.m_rnti, ulHarqPrcStatus));
339  UlHarqProcessesDciBuffer_t ulHarqdci;
340  ulHarqdci.resize (8);
341  m_ulHarqProcessesDciBuffer.insert (std::pair <uint16_t, UlHarqProcessesDciBuffer_t> (params.m_rnti, ulHarqdci));
342  }
343  else
344  {
345  (*it).second = params.m_transmissionMode;
346  }
347  return;
348 }
349 
350 void
351 RrFfMacScheduler::DoCschedLcConfigReq (const struct FfMacCschedSapProvider::CschedLcConfigReqParameters& params)
352 {
353  NS_LOG_FUNCTION (this);
354  // Not used at this stage (LCs updated by DoSchedDlRlcBufferReq)
355  return;
356 }
357 
358 void
359 RrFfMacScheduler::DoCschedLcReleaseReq (const struct FfMacCschedSapProvider::CschedLcReleaseReqParameters& params)
360 {
361  NS_LOG_FUNCTION (this);
362  for (uint16_t i = 0; i < params.m_logicalChannelIdentity.size (); i++)
363  {
364  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
365  while (it!=m_rlcBufferReq.end ())
366  {
367  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity.at (i)))
368  {
369  it = m_rlcBufferReq.erase (it);
370  }
371  else
372  {
373  it++;
374  }
375  }
376  }
377  return;
378 }
379 
380 void
381 RrFfMacScheduler::DoCschedUeReleaseReq (const struct FfMacCschedSapProvider::CschedUeReleaseReqParameters& params)
382 {
383  NS_LOG_FUNCTION (this << " Release RNTI " << params.m_rnti);
384 
385  m_uesTxMode.erase (params.m_rnti);
386  m_dlHarqCurrentProcessId.erase (params.m_rnti);
387  m_dlHarqProcessesStatus.erase (params.m_rnti);
388  m_dlHarqProcessesTimer.erase (params.m_rnti);
389  m_dlHarqProcessesDciBuffer.erase (params.m_rnti);
390  m_dlHarqProcessesRlcPduListBuffer.erase (params.m_rnti);
391  m_ulHarqCurrentProcessId.erase (params.m_rnti);
392  m_ulHarqProcessesStatus.erase (params.m_rnti);
393  m_ulHarqProcessesDciBuffer.erase (params.m_rnti);
394  m_ceBsrRxed.erase (params.m_rnti);
395  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
396  while (it != m_rlcBufferReq.end ())
397  {
398  if ((*it).m_rnti == params.m_rnti)
399  {
400  NS_LOG_INFO (this << " Erase RNTI " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
401  it = m_rlcBufferReq.erase (it);
402  }
403  else
404  {
405  it++;
406  }
407  }
408  if (m_nextRntiUl == params.m_rnti)
409  {
410  m_nextRntiUl = 0;
411  }
412 
413  if (m_nextRntiDl == params.m_rnti)
414  {
415  m_nextRntiDl = 0;
416  }
417 
418  return;
419 }
420 
421 
422 void
423 RrFfMacScheduler::DoSchedDlRlcBufferReq (const struct FfMacSchedSapProvider::SchedDlRlcBufferReqParameters& params)
424 {
425  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
426  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
427  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
428  bool newLc = true;
429  while (it != m_rlcBufferReq.end ())
430  {
431  // remove old entries of this UE-LC
432  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity))
433  {
434  it = m_rlcBufferReq.erase (it);
435  newLc = false;
436  }
437  else
438  {
439  ++it;
440  }
441  }
442  // add the new parameters
443  m_rlcBufferReq.insert (it, params);
444  NS_LOG_INFO (this << " RNTI " << params.m_rnti << " LC " << (uint16_t)params.m_logicalChannelIdentity << " RLC tx size " << params.m_rlcTransmissionQueueHolDelay << " RLC retx size " << params.m_rlcRetransmissionQueueSize << " RLC stat size " << params.m_rlcStatusPduSize);
445  // initialize statistics of the flow in case of new flows
446  if (newLc == true)
447  {
448  m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (params.m_rnti, 1)); // only codeword 0 at this stage (SISO)
449  // initialized to 1 (i.e., the lowest value for transmitting a signal)
450  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (params.m_rnti, m_cqiTimersThreshold));
451  }
452 
453  return;
454 }
455 
456 void
457 RrFfMacScheduler::DoSchedDlPagingBufferReq (const struct FfMacSchedSapProvider::SchedDlPagingBufferReqParameters& params)
458 {
459  NS_LOG_FUNCTION (this);
460  NS_FATAL_ERROR ("method not implemented");
461  return;
462 }
463 
464 void
465 RrFfMacScheduler::DoSchedDlMacBufferReq (const struct FfMacSchedSapProvider::SchedDlMacBufferReqParameters& params)
466 {
467  NS_LOG_FUNCTION (this);
468  NS_FATAL_ERROR ("method not implemented");
469  return;
470 }
471 
472 int
473 RrFfMacScheduler::GetRbgSize (int dlbandwidth)
474 {
475  for (int i = 0; i < 4; i++)
476  {
477  if (dlbandwidth < Type0AllocationRbg[i])
478  {
479  return (i + 1);
480  }
481  }
482 
483  return (-1);
484 }
485 
486 bool
487 RrFfMacScheduler::SortRlcBufferReq (FfMacSchedSapProvider::SchedDlRlcBufferReqParameters i,FfMacSchedSapProvider::SchedDlRlcBufferReqParameters j)
488 {
489  return (i.m_rnti < j.m_rnti);
490 }
491 
492 
493 uint8_t
495 {
496  NS_LOG_FUNCTION (this << rnti);
497 
498  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
499  if (it == m_dlHarqCurrentProcessId.end ())
500  {
501  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
502  }
503  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
504  if (itStat == m_dlHarqProcessesStatus.end ())
505  {
506  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
507  }
508  uint8_t i = (*it).second;
509  do
510  {
511  i = (i + 1) % HARQ_PROC_NUM;
512  }
513  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
514  if ((*itStat).second.at (i) == 0)
515  {
516  return (true);
517  }
518  else
519  {
520  return (false); // return a not valid harq proc id
521  }
522 }
523 
524 
525 
526 uint8_t
528 {
529  NS_LOG_FUNCTION (this << rnti);
530 
531 
532  if (m_harqOn == false)
533  {
534  return (0);
535  }
536 
537  std::map <uint16_t, uint8_t>::iterator it = m_dlHarqCurrentProcessId.find (rnti);
538  if (it == m_dlHarqCurrentProcessId.end ())
539  {
540  NS_FATAL_ERROR ("No Process Id found for this RNTI " << rnti);
541  }
542  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find (rnti);
543  if (itStat == m_dlHarqProcessesStatus.end ())
544  {
545  NS_FATAL_ERROR ("No Process Id Statusfound for this RNTI " << rnti);
546  }
547  uint8_t i = (*it).second;
548  do
549  {
550  i = (i + 1) % HARQ_PROC_NUM;
551  }
552  while ( ((*itStat).second.at (i) != 0)&&(i != (*it).second));
553  if ((*itStat).second.at (i) == 0)
554  {
555  (*it).second = i;
556  (*itStat).second.at (i) = 1;
557  }
558  else
559  {
560  return (9); // return a not valid harq proc id
561  }
562 
563  return ((*it).second);
564 }
565 
566 
567 void
569 {
570  NS_LOG_FUNCTION (this);
571 
572  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itTimers;
573  for (itTimers = m_dlHarqProcessesTimer.begin (); itTimers != m_dlHarqProcessesTimer.end (); itTimers ++)
574  {
575  for (uint16_t i = 0; i < HARQ_PROC_NUM; i++)
576  {
577  if ((*itTimers).second.at (i) == HARQ_DL_TIMEOUT)
578  {
579  // reset HARQ process
580 
581  NS_LOG_INFO (this << " Reset HARQ proc " << i << " for RNTI " << (*itTimers).first);
582  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator itStat = m_dlHarqProcessesStatus.find ((*itTimers).first);
583  if (itStat == m_dlHarqProcessesStatus.end ())
584  {
585  NS_FATAL_ERROR ("No Process Id Status found for this RNTI " << (*itTimers).first);
586  }
587  (*itStat).second.at (i) = 0;
588  (*itTimers).second.at (i) = 0;
589  }
590  else
591  {
592  (*itTimers).second.at (i)++;
593  }
594  }
595  }
596 
597 }
598 
599 
600 
601 void
602 RrFfMacScheduler::DoSchedDlTriggerReq (const struct FfMacSchedSapProvider::SchedDlTriggerReqParameters& params)
603 {
604  NS_LOG_FUNCTION (this << " DL Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
605  // API generated by RLC for triggering the scheduling of a DL subframe
606 
607  RefreshDlCqiMaps ();
608  int rbgSize = GetRbgSize (m_cschedCellConfig.m_dlBandwidth);
609  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
611 
612  // Generate RBGs map
613  std::vector <bool> rbgMap;
614  uint16_t rbgAllocatedNum = 0;
615  std::set <uint16_t> rntiAllocated;
616  rbgMap.resize (m_cschedCellConfig.m_dlBandwidth / rbgSize, false);
617 
618  // RACH Allocation
619  m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
620  uint16_t rbStart = 0;
621  std::vector <struct RachListElement_s>::iterator itRach;
622  for (itRach = m_rachList.begin (); itRach != m_rachList.end (); itRach++)
623  {
624  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");
625  BuildRarListElement_s newRar;
626  newRar.m_rnti = (*itRach).m_rnti;
627  // DL-RACH Allocation
628  // Ideal: no needs of configuring m_dci
629  // UL-RACH Allocation
630  newRar.m_grant.m_rnti = newRar.m_rnti;
631  newRar.m_grant.m_mcs = m_ulGrantMcs;
632  uint16_t rbLen = 1;
633  uint16_t tbSizeBits = 0;
634  // find lowest TB size that fits UL grant estimated size
635  while ((tbSizeBits < (*itRach).m_estimatedSize) && (rbStart + rbLen < m_cschedCellConfig.m_ulBandwidth))
636  {
637  rbLen++;
638  tbSizeBits = m_amc->GetTbSizeFromMcs (m_ulGrantMcs, rbLen);
639  }
640  if (tbSizeBits < (*itRach).m_estimatedSize)
641  {
642  // no more allocation space: finish allocation
643  break;
644  }
645  newRar.m_grant.m_rbStart = rbStart;
646  newRar.m_grant.m_rbLen = rbLen;
647  newRar.m_grant.m_tbSize = tbSizeBits / 8;
648  newRar.m_grant.m_hopping = false;
649  newRar.m_grant.m_tpc = 0;
650  newRar.m_grant.m_cqiRequest = false;
651  newRar.m_grant.m_ulDelay = false;
652  NS_LOG_INFO (this << " UL grant allocated to RNTI " << (*itRach).m_rnti << " rbStart " << rbStart << " rbLen " << rbLen << " MCS " << (uint16_t) m_ulGrantMcs << " tbSize " << newRar.m_grant.m_tbSize);
653  for (uint16_t i = rbStart; i < rbStart + rbLen; i++)
654  {
655  m_rachAllocationMap.at (i) = (*itRach).m_rnti;
656  }
657  rbStart = rbStart + rbLen;
658 
659  ret.m_buildRarList.push_back (newRar);
660  }
661  m_rachList.clear ();
662 
663  // Process DL HARQ feedback
665  // retrieve past HARQ retx buffered
666  if (m_dlInfoListBuffered.size () > 0)
667  {
668  if (params.m_dlInfoList.size () > 0)
669  {
670  NS_LOG_INFO (this << " Received DL-HARQ feedback");
671  m_dlInfoListBuffered.insert (m_dlInfoListBuffered.end (), params.m_dlInfoList.begin (), params.m_dlInfoList.end ());
672  }
673  }
674  else
675  {
676  if (params.m_dlInfoList.size () > 0)
677  {
678  m_dlInfoListBuffered = params.m_dlInfoList;
679  }
680  }
681  if (m_harqOn == false)
682  {
683  // Ignore HARQ feedback
684  m_dlInfoListBuffered.clear ();
685  }
686  std::vector <struct DlInfoListElement_s> dlInfoListUntxed;
687  for (uint16_t i = 0; i < m_dlInfoListBuffered.size (); i++)
688  {
689  std::set <uint16_t>::iterator itRnti = rntiAllocated.find (m_dlInfoListBuffered.at (i).m_rnti);
690  if (itRnti != rntiAllocated.end ())
691  {
692  // RNTI already allocated for retx
693  continue;
694  }
695  uint8_t nLayers = m_dlInfoListBuffered.at (i).m_harqStatus.size ();
696  std::vector <bool> retx;
697  NS_LOG_INFO (this << " Processing DLHARQ feedback");
698  if (nLayers == 1)
699  {
700  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
701  retx.push_back (false);
702  }
703  else
704  {
705  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (0) == DlInfoListElement_s::NACK);
706  retx.push_back (m_dlInfoListBuffered.at (i).m_harqStatus.at (1) == DlInfoListElement_s::NACK);
707  }
708  if (retx.at (0) || retx.at (1))
709  {
710  // retrieve HARQ process information
711  uint16_t rnti = m_dlInfoListBuffered.at (i).m_rnti;
712  uint8_t harqId = m_dlInfoListBuffered.at (i).m_harqProcessId;
713  NS_LOG_INFO (this << " HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
714  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itHarq = m_dlHarqProcessesDciBuffer.find (rnti);
715  if (itHarq == m_dlHarqProcessesDciBuffer.end ())
716  {
717  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << rnti);
718  }
719 
720  DlDciListElement_s dci = (*itHarq).second.at (harqId);
721  int rv = 0;
722  if (dci.m_rv.size () == 1)
723  {
724  rv = dci.m_rv.at (0);
725  }
726  else
727  {
728  rv = (dci.m_rv.at (0) > dci.m_rv.at (1) ? dci.m_rv.at (0) : dci.m_rv.at (1));
729  }
730 
731  if (rv == 3)
732  {
733  // maximum number of retx reached -> drop process
734  NS_LOG_INFO ("Max number of retransmissions reached -> drop process");
735  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (rnti);
736  if (it == m_dlHarqProcessesStatus.end ())
737  {
738  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << m_dlInfoListBuffered.at (i).m_rnti);
739  }
740  (*it).second.at (harqId) = 0;
741  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
742  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
743  {
744  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
745  }
746  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
747  {
748  (*itRlcPdu).second.at (k).at (harqId).clear ();
749  }
750  continue;
751  }
752  // check the feasibility of retransmitting on the same RBGs
753  // translate the DCI to Spectrum framework
754  std::vector <int> dciRbg;
755  uint32_t mask = 0x1;
756  NS_LOG_INFO ("Original RBGs " << dci.m_rbBitmap << " rnti " << dci.m_rnti);
757  for (int j = 0; j < 32; j++)
758  {
759  if (((dci.m_rbBitmap & mask) >> j) == 1)
760  {
761  dciRbg.push_back (j);
762  NS_LOG_INFO ("\t" << j);
763  }
764  mask = (mask << 1);
765  }
766  bool free = true;
767  for (uint8_t j = 0; j < dciRbg.size (); j++)
768  {
769  if (rbgMap.at (dciRbg.at (j)) == true)
770  {
771  free = false;
772  break;
773  }
774  }
775  if (free)
776  {
777  // use the same RBGs for the retx
778  // reserve RBGs
779  for (uint8_t j = 0; j < dciRbg.size (); j++)
780  {
781  rbgMap.at (dciRbg.at (j)) = true;
782  NS_LOG_INFO ("RBG " << dciRbg.at (j) << " assigned");
783  rbgAllocatedNum++;
784  }
785 
786  NS_LOG_INFO (this << " Send retx in the same RBGs");
787  }
788  else
789  {
790  // find RBGs for sending HARQ retx
791  uint8_t j = 0;
792  uint8_t rbgId = (dciRbg.at (dciRbg.size () - 1) + 1) % rbgNum;
793  uint8_t startRbg = dciRbg.at (dciRbg.size () - 1);
794  std::vector <bool> rbgMapCopy = rbgMap;
795  while ((j < dciRbg.size ())&&(startRbg != rbgId))
796  {
797  if (rbgMapCopy.at (rbgId) == false)
798  {
799  rbgMapCopy.at (rbgId) = true;
800  dciRbg.at (j) = rbgId;
801  j++;
802  }
803  rbgId++;
804  }
805  if (j == dciRbg.size ())
806  {
807  // find new RBGs -> update DCI map
808  uint32_t rbgMask = 0;
809  for (uint16_t k = 0; k < dciRbg.size (); k++)
810  {
811  rbgMask = rbgMask + (0x1 << dciRbg.at (k));
812  NS_LOG_INFO (this << " New allocated RBG " << dciRbg.at (k));
813  rbgAllocatedNum++;
814  }
815  dci.m_rbBitmap = rbgMask;
816  rbgMap = rbgMapCopy;
817  }
818  else
819  {
820  // HARQ retx cannot be performed on this TTI -> store it
821  dlInfoListUntxed.push_back (params.m_dlInfoList.at (i));
822  NS_LOG_INFO (this << " No resource for this retx -> buffer it");
823  }
824  }
825  // retrieve RLC PDU list for retx TBsize and update DCI
826  BuildDataListElement_s newEl;
827  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (rnti);
828  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
829  {
830  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << rnti);
831  }
832  for (uint8_t j = 0; j < nLayers; j++)
833  {
834  if (retx.at (j))
835  {
836  if (j >= dci.m_ndi.size ())
837  {
838  // for avoiding errors in MIMO transient phases
839  dci.m_ndi.push_back (0);
840  dci.m_rv.push_back (0);
841  dci.m_mcs.push_back (0);
842  dci.m_tbsSize.push_back (0);
843  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no txed (MIMO transition)");
844 
845  }
846  else
847  {
848  dci.m_ndi.at (j) = 0;
849  dci.m_rv.at (j)++;
850  (*itHarq).second.at (harqId).m_rv.at (j)++;
851  NS_LOG_INFO (this << " layer " << (uint16_t)j << " RV " << (uint16_t)dci.m_rv.at (j));
852  }
853  }
854  else
855  {
856  // empty TB of layer j
857  dci.m_ndi.at (j) = 0;
858  dci.m_rv.at (j) = 0;
859  dci.m_mcs.at (j) = 0;
860  dci.m_tbsSize.at (j) = 0;
861  NS_LOG_INFO (this << " layer " << (uint16_t)j << " no retx");
862  }
863  }
864 
865  for (uint16_t k = 0; k < (*itRlcPdu).second.at (0).at (dci.m_harqProcess).size (); k++)
866  {
867  std::vector <struct RlcPduListElement_s> rlcPduListPerLc;
868  for (uint8_t j = 0; j < nLayers; j++)
869  {
870  if (retx.at (j))
871  {
872  if (j < dci.m_ndi.size ())
873  {
874  rlcPduListPerLc.push_back ((*itRlcPdu).second.at (j).at (dci.m_harqProcess).at (k));
875  }
876  }
877  }
878 
879  if (rlcPduListPerLc.size () > 0)
880  {
881  newEl.m_rlcPduList.push_back (rlcPduListPerLc);
882  }
883  }
884  newEl.m_rnti = rnti;
885  newEl.m_dci = dci;
886  (*itHarq).second.at (harqId).m_rv = dci.m_rv;
887  // refresh timer
888  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (rnti);
889  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
890  {
891  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)rnti);
892  }
893  (*itHarqTimer).second.at (harqId) = 0;
894  ret.m_buildDataList.push_back (newEl);
895  rntiAllocated.insert (rnti);
896  }
897  else
898  {
899  // update HARQ process status
900  NS_LOG_INFO (this << " HARQ ACK UE " << m_dlInfoListBuffered.at (i).m_rnti);
901  std::map <uint16_t, DlHarqProcessesStatus_t>::iterator it = m_dlHarqProcessesStatus.find (m_dlInfoListBuffered.at (i).m_rnti);
902  if (it == m_dlHarqProcessesStatus.end ())
903  {
904  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << m_dlInfoListBuffered.at (i).m_rnti);
905  }
906  (*it).second.at (m_dlInfoListBuffered.at (i).m_harqProcessId) = 0;
907  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find (m_dlInfoListBuffered.at (i).m_rnti);
908  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
909  {
910  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << m_dlInfoListBuffered.at (i).m_rnti);
911  }
912  for (uint16_t k = 0; k < (*itRlcPdu).second.size (); k++)
913  {
914  (*itRlcPdu).second.at (k).at (m_dlInfoListBuffered.at (i).m_harqProcessId).clear ();
915  }
916  }
917  }
918  m_dlInfoListBuffered.clear ();
919  m_dlInfoListBuffered = dlInfoListUntxed;
920 
921  // Get the actual active flows (queue!=0)
922  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
923  m_rlcBufferReq.sort (SortRlcBufferReq);
924  int nflows = 0;
925  int nTbs = 0;
926  std::map <uint16_t,uint8_t> lcActivesPerRnti; // tracks how many active LCs per RNTI there are
927  std::map <uint16_t,uint8_t>::iterator itLcRnti;
928  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
929  {
930  // remove old entries of this UE-LC
931  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
932  if ( (((*it).m_rlcTransmissionQueueSize > 0)
933  || ((*it).m_rlcRetransmissionQueueSize > 0)
934  || ((*it).m_rlcStatusPduSize > 0))
935  && (itRnti == rntiAllocated.end ()) // UE must not be allocated for HARQ retx
936  && (HarqProcessAvailability ((*it).m_rnti)) ) // UE needs HARQ proc free
937 
938  {
939  NS_LOG_LOGIC (this << " User " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity << " is active, status " << (*it).m_rlcStatusPduSize << " retx " << (*it).m_rlcRetransmissionQueueSize << " tx " << (*it).m_rlcTransmissionQueueSize);
940  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find ((*it).m_rnti);
941  uint8_t cqi = 0;
942  if (itCqi != m_p10CqiRxed.end ())
943  {
944  cqi = (*itCqi).second;
945  }
946  else
947  {
948  cqi = 1; // lowest value fro trying a transmission
949  }
950  if (cqi != 0)
951  {
952  // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
953  nflows++;
954  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
955  if (itLcRnti != lcActivesPerRnti.end ())
956  {
957  (*itLcRnti).second++;
958  }
959  else
960  {
961  lcActivesPerRnti.insert (std::pair<uint16_t, uint8_t > ((*it).m_rnti, 1));
962  nTbs++;
963  }
964 
965  }
966  }
967  }
968 
969  if (nflows == 0)
970  {
971  if ((ret.m_buildDataList.size () > 0) || (ret.m_buildRarList.size () > 0))
972  {
973  m_schedSapUser->SchedDlConfigInd (ret);
974  }
975  return;
976  }
977  // Divide the resource equally among the active users according to
978  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
979 
980  int rbgPerTb = (rbgNum - rbgAllocatedNum) / nTbs;
981  NS_LOG_INFO (this << " Flows to be transmitted " << nflows << " rbgPerTb " << rbgPerTb);
982  if (rbgPerTb == 0)
983  {
984  rbgPerTb = 1; // at least 1 rbg per TB (till available resource)
985  }
986  int rbgAllocated = 0;
987 
988  // round robin assignment to all UEs registered starting from the subsequent of the one
989  // served last scheduling trigger event
990  if (m_nextRntiDl != 0)
991  {
992  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
993  {
994  if ((*it).m_rnti == m_nextRntiDl)
995  {
996  break;
997  }
998  }
999 
1000  if (it == m_rlcBufferReq.end ())
1001  {
1002  NS_LOG_ERROR (this << " no user found");
1003  }
1004  }
1005  else
1006  {
1007  it = m_rlcBufferReq.begin ();
1008  m_nextRntiDl = (*it).m_rnti;
1009  }
1010  std::map <uint16_t,uint8_t>::iterator itTxMode;
1011  do
1012  {
1013  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
1014  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).m_rnti);
1015  if ((itLcRnti == lcActivesPerRnti.end ())||(itRnti != rntiAllocated.end ()))
1016  {
1017  // skip this RNTI (no active queue or yet allocated for HARQ)
1018  uint16_t rntiDiscared = (*it).m_rnti;
1019  while (it != m_rlcBufferReq.end ())
1020  {
1021  if ((*it).m_rnti != rntiDiscared)
1022  {
1023  break;
1024  }
1025  it++;
1026  }
1027  if (it == m_rlcBufferReq.end ())
1028  {
1029  // restart from the first
1030  it = m_rlcBufferReq.begin ();
1031  }
1032  continue;
1033  }
1034  itTxMode = m_uesTxMode.find ((*it).m_rnti);
1035  if (itTxMode == m_uesTxMode.end ())
1036  {
1037  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).m_rnti);
1038  }
1039  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
1040  int lcNum = (*itLcRnti).second;
1041  // create new BuildDataListElement_s for this RNTI
1042  BuildDataListElement_s newEl;
1043  newEl.m_rnti = (*it).m_rnti;
1044  // create the DlDciListElement_s
1045  DlDciListElement_s newDci;
1046  newDci.m_rnti = (*it).m_rnti;
1047  newDci.m_harqProcess = UpdateHarqProcessId ((*it).m_rnti);
1048  newDci.m_resAlloc = 0;
1049  newDci.m_rbBitmap = 0;
1050  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find (newEl.m_rnti);
1051  for (uint8_t i = 0; i < nLayer; i++)
1052  {
1053  if (itCqi == m_p10CqiRxed.end ())
1054  {
1055  newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS
1056  }
1057  else
1058  {
1059  newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) );
1060  }
1061  }
1062  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
1063  uint16_t rlcPduSize = tbSize / lcNum;
1064  while (lcNum > 0)
1065  {
1066  if ( ((*it).m_rlcTransmissionQueueSize > 0)
1067  || ((*it).m_rlcRetransmissionQueueSize > 0)
1068  || ((*it).m_rlcStatusPduSize > 0) )
1069  {
1070  std::vector <struct RlcPduListElement_s> newRlcPduLe;
1071  for (uint8_t j = 0; j < nLayer; j++)
1072  {
1073  RlcPduListElement_s newRlcEl;
1074  newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
1075  NS_LOG_INFO (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
1076  newRlcEl.m_size = rlcPduSize;
1077  UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
1078  newRlcPduLe.push_back (newRlcEl);
1079 
1080  if (m_harqOn == true)
1081  {
1082  // store RLC PDU list for HARQ
1083  std::map <uint16_t, DlHarqRlcPduListBuffer_t>::iterator itRlcPdu = m_dlHarqProcessesRlcPduListBuffer.find ((*it).m_rnti);
1084  if (itRlcPdu == m_dlHarqProcessesRlcPduListBuffer.end ())
1085  {
1086  NS_FATAL_ERROR ("Unable to find RlcPdcList in HARQ buffer for RNTI " << (*it).m_rnti);
1087  }
1088  (*itRlcPdu).second.at (j).at (newDci.m_harqProcess).push_back (newRlcEl);
1089  }
1090 
1091  }
1092  newEl.m_rlcPduList.push_back (newRlcPduLe);
1093  lcNum--;
1094  }
1095  it++;
1096  if (it == m_rlcBufferReq.end ())
1097  {
1098  // restart from the first
1099  it = m_rlcBufferReq.begin ();
1100  }
1101  }
1102  uint32_t rbgMask = 0;
1103  uint16_t i = 0;
1104  NS_LOG_INFO (this << " DL - Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " harqId " << (uint16_t)newDci.m_harqProcess << " layers " << nLayer);
1105  NS_LOG_INFO ("RBG:");
1106  while (i < rbgPerTb)
1107  {
1108  if (rbgMap.at (rbgAllocated) == false)
1109  {
1110  rbgMask = rbgMask + (0x1 << rbgAllocated);
1111  NS_LOG_INFO ("\t " << rbgAllocated);
1112  i++;
1113  rbgMap.at (rbgAllocated) = true;
1114  }
1115  rbgAllocated++;
1116  }
1117  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
1118 
1119  for (int i = 0; i < nLayer; i++)
1120  {
1121  newDci.m_tbsSize.push_back (tbSize);
1122  newDci.m_ndi.push_back (1);
1123  newDci.m_rv.push_back (0);
1124  }
1125  newEl.m_dci = newDci;
1126  if (m_harqOn == true)
1127  {
1128  // store DCI for HARQ
1129  std::map <uint16_t, DlHarqProcessesDciBuffer_t>::iterator itDci = m_dlHarqProcessesDciBuffer.find (newEl.m_rnti);
1130  if (itDci == m_dlHarqProcessesDciBuffer.end ())
1131  {
1132  NS_FATAL_ERROR ("Unable to find RNTI entry in DCI HARQ buffer for RNTI " << (*it).m_rnti);
1133  }
1134  (*itDci).second.at (newDci.m_harqProcess) = newDci;
1135  // refresh timer
1136  std::map <uint16_t, DlHarqProcessesTimer_t>::iterator itHarqTimer = m_dlHarqProcessesTimer.find (newEl.m_rnti);
1137  if (itHarqTimer== m_dlHarqProcessesTimer.end ())
1138  {
1139  NS_FATAL_ERROR ("Unable to find HARQ timer for RNTI " << (uint16_t)newEl.m_rnti);
1140  }
1141  (*itHarqTimer).second.at (newDci.m_harqProcess) = 0;
1142  }
1143  // ...more parameters -> ignored in this version
1144 
1145  ret.m_buildDataList.push_back (newEl);
1146  if (rbgAllocated == rbgNum)
1147  {
1148  m_nextRntiDl = (*it).m_rnti; // store last RNTI served
1149  break; // no more RGB to be allocated
1150  }
1151  }
1152  while ((*it).m_rnti != m_nextRntiDl);
1153 
1154  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
1155 
1156  m_schedSapUser->SchedDlConfigInd (ret);
1157  return;
1158 }
1159 
1160 void
1161 RrFfMacScheduler::DoSchedDlRachInfoReq (const struct FfMacSchedSapProvider::SchedDlRachInfoReqParameters& params)
1162 {
1163  NS_LOG_FUNCTION (this);
1164 
1165  m_rachList = params.m_rachList;
1166 
1167  return;
1168 }
1169 
1170 void
1171 RrFfMacScheduler::DoSchedDlCqiInfoReq (const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters& params)
1172 {
1173  NS_LOG_FUNCTION (this);
1174 
1175  std::map <uint16_t,uint8_t>::iterator it;
1176  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
1177  {
1178  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
1179  {
1180  // wideband CQI reporting
1181  std::map <uint16_t,uint8_t>::iterator it;
1182  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
1183  it = m_p10CqiRxed.find (rnti);
1184  if (it == m_p10CqiRxed.end ())
1185  {
1186  // create the new entry
1187  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)
1188  // generate correspondent timer
1189  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1190  }
1191  else
1192  {
1193  // update the CQI value
1194  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
1195  // update correspondent timer
1196  std::map <uint16_t,uint32_t>::iterator itTimers;
1197  itTimers = m_p10CqiTimers.find (rnti);
1198  (*itTimers).second = m_cqiTimersThreshold;
1199  }
1200  }
1201  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
1202  {
1203  // subband CQI reporting high layer configured
1204  // Not used by RR Scheduler
1205  }
1206  else
1207  {
1208  NS_LOG_ERROR (this << " CQI type unknown");
1209  }
1210  }
1211 
1212  return;
1213 }
1214 
1215 void
1216 RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::SchedUlTriggerReqParameters& params)
1217 {
1218  NS_LOG_FUNCTION (this << " Ul - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
1219 
1220 
1221  RefreshUlCqiMaps ();
1222 
1223  // Generate RBs map
1224  FfMacSchedSapUser::SchedUlConfigIndParameters ret;
1225  std::vector <bool> rbMap;
1226  uint16_t rbAllocatedNum = 0;
1227  std::set <uint16_t> rntiAllocated;
1228  std::vector <uint16_t> rbgAllocationMap;
1229  // update with RACH allocation map
1230  rbgAllocationMap = m_rachAllocationMap;
1231  //rbgAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1232  m_rachAllocationMap.clear ();
1233  m_rachAllocationMap.resize (m_cschedCellConfig.m_ulBandwidth, 0);
1234 
1235  rbMap.resize (m_cschedCellConfig.m_ulBandwidth, false);
1236  // remove RACH allocation
1237  for (uint16_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
1238  {
1239  if (rbgAllocationMap.at (i) != 0)
1240  {
1241  rbMap.at (i) = true;
1242  }
1243  }
1244 
1245  if (m_harqOn == true)
1246  {
1247  // Process UL HARQ feedback
1248  // update UL HARQ proc id
1249  std::map <uint16_t, uint8_t>::iterator itProcId;
1250  for (itProcId = m_ulHarqCurrentProcessId.begin (); itProcId != m_ulHarqCurrentProcessId.end (); itProcId++)
1251  {
1252  (*itProcId).second = ((*itProcId).second + 1) % HARQ_PROC_NUM;
1253  }
1254  for (uint16_t i = 0; i < params.m_ulInfoList.size (); i++)
1255  {
1256  if (params.m_ulInfoList.at (i).m_receptionStatus == UlInfoListElement_s::NotOk)
1257  {
1258  // retx correspondent block: retrieve the UL-DCI
1259  uint16_t rnti = params.m_ulInfoList.at (i).m_rnti;
1260  itProcId = m_ulHarqCurrentProcessId.find (rnti);
1261  if (itProcId == m_ulHarqCurrentProcessId.end ())
1262  {
1263  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1264  }
1265  uint8_t harqId = (uint8_t)((*itProcId).second - HARQ_PERIOD) % HARQ_PROC_NUM;
1266  NS_LOG_INFO (this << " UL-HARQ retx RNTI " << rnti << " harqId " << (uint16_t)harqId);
1267  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itHarq = m_ulHarqProcessesDciBuffer.find (rnti);
1268  if (itHarq == m_ulHarqProcessesDciBuffer.end ())
1269  {
1270  NS_LOG_ERROR ("No info find in UL-HARQ buffer for UE (might change eNB) " << rnti);
1271  }
1272  UlDciListElement_s dci = (*itHarq).second.at (harqId);
1273  std::map <uint16_t, UlHarqProcessesStatus_t>::iterator itStat = m_ulHarqProcessesStatus.find (rnti);
1274  if (itStat == m_ulHarqProcessesStatus.end ())
1275  {
1276  NS_LOG_ERROR ("No info find in HARQ buffer for UE (might change eNB) " << rnti);
1277  }
1278  if ((*itStat).second.at (harqId) > 3)
1279  {
1280  NS_LOG_INFO ("Max number of retransmissions reached (UL)-> drop process");
1281  continue;
1282  }
1283  bool free = true;
1284  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1285  {
1286  if (rbMap.at (j) == true)
1287  {
1288  free = false;
1289  NS_LOG_INFO (this << " BUSY " << j);
1290  }
1291  }
1292  if (free)
1293  {
1294  // retx on the same RBs
1295  for (int j = dci.m_rbStart; j < dci.m_rbStart + dci.m_rbLen; j++)
1296  {
1297  rbMap.at (j) = true;
1298  rbgAllocationMap.at (j) = dci.m_rnti;
1299  NS_LOG_INFO ("\tRB " << j);
1300  rbAllocatedNum++;
1301  }
1302  NS_LOG_INFO (this << " Send retx in the same RBGs " << (uint16_t)dci.m_rbStart << " to " << dci.m_rbStart + dci.m_rbLen << " RV " << (*itStat).second.at (harqId) + 1);
1303  }
1304  else
1305  {
1306  NS_LOG_INFO ("Cannot allocate retx due to RACH allocations for UE " << rnti);
1307  continue;
1308  }
1309  dci.m_ndi = 0;
1310  // Update HARQ buffers with new HarqId
1311  (*itStat).second.at ((*itProcId).second) = (*itStat).second.at (harqId) + 1;
1312  (*itStat).second.at (harqId) = 0;
1313  (*itHarq).second.at ((*itProcId).second) = dci;
1314  ret.m_dciList.push_back (dci);
1315  rntiAllocated.insert (dci.m_rnti);
1316  }
1317  }
1318  }
1319 
1320  std::map <uint16_t,uint32_t>::iterator it;
1321  int nflows = 0;
1322 
1323  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1324  {
1325  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1326  // select UEs with queues not empty and not yet allocated for HARQ
1327  NS_LOG_INFO (this << " UE " << (*it).first << " queue " << (*it).second);
1328  if (((*it).second > 0)&&(itRnti == rntiAllocated.end ()))
1329  {
1330  nflows++;
1331  }
1332  }
1333 
1334  if (nflows == 0)
1335  {
1336  if (ret.m_dciList.size () > 0)
1337  {
1338  m_schedSapUser->SchedUlConfigInd (ret);
1339  }
1340  return; // no flows to be scheduled
1341  }
1342 
1343 
1344  // Divide the remaining resources equally among the active users starting from the subsequent one served last scheduling trigger
1345  uint16_t rbPerFlow = (m_cschedCellConfig.m_ulBandwidth) / (nflows + rntiAllocated.size ());
1346  if (rbPerFlow < 3)
1347  {
1348  rbPerFlow = 3; // at least 3 rbg per flow (till available resource) to ensure TxOpportunity >= 7 bytes
1349  }
1350  uint16_t rbAllocated = 0;
1351 
1352  if (m_nextRntiUl != 0)
1353  {
1354  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
1355  {
1356  if ((*it).first == m_nextRntiUl)
1357  {
1358  break;
1359  }
1360  }
1361  if (it == m_ceBsrRxed.end ())
1362  {
1363  NS_LOG_ERROR (this << " no user found");
1364  }
1365  }
1366  else
1367  {
1368  it = m_ceBsrRxed.begin ();
1369  m_nextRntiUl = (*it).first;
1370  }
1371  NS_LOG_INFO (this << " NFlows " << nflows << " RB per Flow " << rbPerFlow);
1372  do
1373  {
1374  std::set <uint16_t>::iterator itRnti = rntiAllocated.find ((*it).first);
1375  if ((itRnti != rntiAllocated.end ())||((*it).second == 0))
1376  {
1377  // UE already allocated for UL-HARQ -> skip it
1378  it++;
1379  if (it == m_ceBsrRxed.end ())
1380  {
1381  // restart from the first
1382  it = m_ceBsrRxed.begin ();
1383  }
1384  continue;
1385  }
1386  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1387  {
1388  // limit to physical resources last resource assignment
1389  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1390  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1391  if (rbPerFlow < 3)
1392  {
1393  // terminate allocation
1394  rbPerFlow = 0;
1395  }
1396  }
1397  NS_LOG_INFO (this << " try to allocate " << (*it).first);
1398  UlDciListElement_s uldci;
1399  uldci.m_rnti = (*it).first;
1400  uldci.m_rbLen = rbPerFlow;
1401  bool allocated = false;
1402  while ((!allocated)&&((rbAllocated + rbPerFlow - 1) < m_cschedCellConfig.m_ulBandwidth) && (rbPerFlow != 0))
1403  {
1404  // check availability
1405  bool free = true;
1406  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1407  {
1408  if (rbMap.at (j) == true)
1409  {
1410  free = false;
1411  break;
1412  }
1413  }
1414  if (free)
1415  {
1416  uldci.m_rbStart = rbAllocated;
1417 
1418  for (uint16_t j = rbAllocated; j < rbAllocated + rbPerFlow; j++)
1419  {
1420  rbMap.at (j) = true;
1421  // store info on allocation for managing ul-cqi interpretation
1422  rbgAllocationMap.at (j) = (*it).first;
1423  NS_LOG_INFO ("\t " << j);
1424  }
1425  rbAllocated += rbPerFlow;
1426  allocated = true;
1427  break;
1428  }
1429  rbAllocated++;
1430  if (rbAllocated + rbPerFlow - 1 > m_cschedCellConfig.m_ulBandwidth)
1431  {
1432  // limit to physical resources last resource assignment
1433  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
1434  // at least 3 rbg per flow to ensure TxOpportunity >= 7 bytes
1435  if (rbPerFlow < 3)
1436  {
1437  // terminate allocation
1438  rbPerFlow = 0;
1439  }
1440  }
1441  }
1442  if (!allocated)
1443  {
1444  // unable to allocate new resource: finish scheduling
1445  m_nextRntiUl = (*it).first;
1446  if (ret.m_dciList.size () > 0)
1447  {
1448  m_schedSapUser->SchedUlConfigInd (ret);
1449  }
1450  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1451  return;
1452  }
1453  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
1454  int cqi = 0;
1455  if (itCqi == m_ueCqi.end ())
1456  {
1457  // no cqi info about this UE
1458  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
1459  NS_LOG_INFO (this << " UE does not have ULCQI " << (*it).first );
1460  }
1461  else
1462  {
1463  // take the lowest CQI value (worst RB)
1464  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
1465  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
1466  {
1467  if ((*itCqi).second.at (i) < minSinr)
1468  {
1469  minSinr = (*itCqi).second.at (i);
1470  }
1471  }
1472  // translate SINR -> cqi: WILD ACK: same as DL
1473  double s = log2 ( 1 + (
1474  std::pow (10, minSinr / 10 ) /
1475  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
1476 
1477 
1478  cqi = m_amc->GetCqiFromSpectralEfficiency (s);
1479  if (cqi == 0)
1480  {
1481  it++;
1482  if (it == m_ceBsrRxed.end ())
1483  {
1484  // restart from the first
1485  it = m_ceBsrRxed.begin ();
1486  }
1487  NS_LOG_INFO (this << " UE discarded for CQI = 0");
1488  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
1489  }
1490  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
1491  }
1492  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD
1493 
1494  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
1495  uldci.m_ndi = 1;
1496  uldci.m_cceIndex = 0;
1497  uldci.m_aggrLevel = 1;
1498  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
1499  uldci.m_hopping = false;
1500  uldci.m_n2Dmrs = 0;
1501  uldci.m_tpc = 0; // no power control
1502  uldci.m_cqiRequest = false; // only period CQI at this stage
1503  uldci.m_ulIndex = 0; // TDD parameter
1504  uldci.m_dai = 1; // TDD parameter
1505  uldci.m_freqHopping = 0;
1506  uldci.m_pdcchPowerOffset = 0; // not used
1507  ret.m_dciList.push_back (uldci);
1508  // store DCI for HARQ_PERIOD
1509  uint8_t harqId = 0;
1510  if (m_harqOn == true)
1511  {
1512  std::map <uint16_t, uint8_t>::iterator itProcId;
1513  itProcId = m_ulHarqCurrentProcessId.find (uldci.m_rnti);
1514  if (itProcId == m_ulHarqCurrentProcessId.end ())
1515  {
1516  NS_FATAL_ERROR ("No info find in HARQ buffer for UE " << uldci.m_rnti);
1517  }
1518  harqId = (*itProcId).second;
1519  std::map <uint16_t, UlHarqProcessesDciBuffer_t>::iterator itDci = m_ulHarqProcessesDciBuffer.find (uldci.m_rnti);
1520  if (itDci == m_ulHarqProcessesDciBuffer.end ())
1521  {
1522  NS_FATAL_ERROR ("Unable to find RNTI entry in UL DCI HARQ buffer for RNTI " << uldci.m_rnti);
1523  }
1524  (*itDci).second.at (harqId) = uldci;
1525  }
1526  NS_LOG_INFO (this << " UL Allocation - UE " << (*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 << " harqId " << (uint16_t)harqId);
1527 
1528  it++;
1529  if (it == m_ceBsrRxed.end ())
1530  {
1531  // restart from the first
1532  it = m_ceBsrRxed.begin ();
1533  }
1534  if ((rbAllocated == m_cschedCellConfig.m_ulBandwidth) || (rbPerFlow == 0))
1535  {
1536  // Stop allocation: no more PRBs
1537  m_nextRntiUl = (*it).first;
1538  break;
1539  }
1540  }
1541  while (((*it).first != m_nextRntiUl)&&(rbPerFlow!=0));
1542 
1543  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
1544 
1545  m_schedSapUser->SchedUlConfigInd (ret);
1546  return;
1547 }
1548 
1549 void
1550 RrFfMacScheduler::DoSchedUlNoiseInterferenceReq (const struct FfMacSchedSapProvider::SchedUlNoiseInterferenceReqParameters& params)
1551 {
1552  NS_LOG_FUNCTION (this);
1553  return;
1554 }
1555 
1556 void
1557 RrFfMacScheduler::DoSchedUlSrInfoReq (const struct FfMacSchedSapProvider::SchedUlSrInfoReqParameters& params)
1558 {
1559  NS_LOG_FUNCTION (this);
1560  return;
1561 }
1562 
1563 void
1564 RrFfMacScheduler::DoSchedUlMacCtrlInfoReq (const struct FfMacSchedSapProvider::SchedUlMacCtrlInfoReqParameters& params)
1565 {
1566  NS_LOG_FUNCTION (this);
1567 
1568  std::map <uint16_t,uint32_t>::iterator it;
1569 
1570  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
1571  {
1572  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
1573  {
1574  // buffer status report
1575  // note that this scheduler does not differentiate the
1576  // allocation according to which LCGs have more/less bytes
1577  // to send.
1578  // Hence the BSR of different LCGs are just summed up to get
1579  // a total queue size that is used for allocation purposes.
1580 
1581  uint32_t buffer = 0;
1582  for (uint8_t lcg = 0; lcg < 4; ++lcg)
1583  {
1584  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
1585  buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
1586  }
1587 
1588  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
1589  it = m_ceBsrRxed.find (rnti);
1590  if (it == m_ceBsrRxed.end ())
1591  {
1592  // create the new entry
1593  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
1594  NS_LOG_INFO (this << " Insert RNTI " << rnti << " queue " << buffer);
1595  }
1596  else
1597  {
1598  // update the buffer size value
1599  (*it).second = buffer;
1600  NS_LOG_INFO (this << " Update RNTI " << rnti << " queue " << buffer);
1601  }
1602  }
1603  }
1604 
1605  return;
1606 }
1607 
1608 void
1609 RrFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params)
1610 {
1611  NS_LOG_FUNCTION (this);
1612 
1613  switch (m_ulCqiFilter)
1614  {
1615  case FfMacScheduler::SRS_UL_CQI:
1616  {
1617  // filter all the CQIs that are not SRS based
1618  if (params.m_ulCqi.m_type != UlCqi_s::SRS)
1619  {
1620  return;
1621  }
1622  }
1623  break;
1624  case FfMacScheduler::PUSCH_UL_CQI:
1625  {
1626  // filter all the CQIs that are not SRS based
1627  if (params.m_ulCqi.m_type != UlCqi_s::PUSCH)
1628  {
1629  return;
1630  }
1631  }
1632  case FfMacScheduler::ALL_UL_CQI:
1633  break;
1634 
1635  default:
1636  NS_FATAL_ERROR ("Unknown UL CQI type");
1637  }
1638  switch (params.m_ulCqi.m_type)
1639  {
1640  case UlCqi_s::PUSCH:
1641  {
1642  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1643  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1644  itMap = m_allocationMaps.find (params.m_sfnSf);
1645  if (itMap == m_allocationMaps.end ())
1646  {
1647  NS_LOG_INFO (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1648  return;
1649  }
1650  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1651  {
1652  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1653  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1654  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1655  if (itCqi == m_ueCqi.end ())
1656  {
1657  // create a new entry
1658  std::vector <double> newCqi;
1659  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1660  {
1661  if (i == j)
1662  {
1663  newCqi.push_back (sinr);
1664  }
1665  else
1666  {
1667  // initialize with NO_SINR value.
1668  newCqi.push_back (30.0);
1669  }
1670 
1671  }
1672  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1673  // generate correspondent timer
1674  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1675  }
1676  else
1677  {
1678  // update the value
1679  (*itCqi).second.at (i) = sinr;
1680  // update correspondent timer
1681  std::map <uint16_t, uint32_t>::iterator itTimers;
1682  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1683  (*itTimers).second = m_cqiTimersThreshold;
1684 
1685  }
1686 
1687  }
1688  // remove obsolete info on allocation
1689  m_allocationMaps.erase (itMap);
1690  }
1691  break;
1692  case UlCqi_s::SRS:
1693  {
1694  // get the RNTI from vendor specific parameters
1695  uint16_t rnti = 0;
1696  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1697  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1698  {
1699  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1700  {
1701  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1702  rnti = vsp->GetRnti ();
1703  }
1704  }
1705  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1706  itCqi = m_ueCqi.find (rnti);
1707  if (itCqi == m_ueCqi.end ())
1708  {
1709  // create a new entry
1710  std::vector <double> newCqi;
1711  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1712  {
1713  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1714  newCqi.push_back (sinr);
1715  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1716 
1717  }
1718  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1719  // generate correspondent timer
1720  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1721  }
1722  else
1723  {
1724  // update the values
1725  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1726  {
1727  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1728  (*itCqi).second.at (j) = sinr;
1729  NS_LOG_INFO (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1730  }
1731  // update correspondent timer
1732  std::map <uint16_t, uint32_t>::iterator itTimers;
1733  itTimers = m_ueCqiTimers.find (rnti);
1734  (*itTimers).second = m_cqiTimersThreshold;
1735 
1736  }
1737 
1738 
1739  }
1740  break;
1741  case UlCqi_s::PUCCH_1:
1742  case UlCqi_s::PUCCH_2:
1743  case UlCqi_s::PRACH:
1744  {
1745  NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1746  }
1747  break;
1748  default:
1749  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1750  }
1751  return;
1752 }
1753 
1754 
1755 void
1756 RrFfMacScheduler::RefreshDlCqiMaps (void)
1757 {
1758  NS_LOG_FUNCTION (this << m_p10CqiTimers.size ());
1759  // refresh DL CQI P01 Map
1760  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1761  while (itP10 != m_p10CqiTimers.end ())
1762  {
1763  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1764  if ((*itP10).second == 0)
1765  {
1766  // delete correspondent entries
1767  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1768  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1769  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1770  m_p10CqiRxed.erase (itMap);
1771  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1772  itP10++;
1773  m_p10CqiTimers.erase (temp);
1774  }
1775  else
1776  {
1777  (*itP10).second--;
1778  itP10++;
1779  }
1780  }
1781 
1782  return;
1783 }
1784 
1785 
1786 void
1787 RrFfMacScheduler::RefreshUlCqiMaps (void)
1788 {
1789  // refresh UL CQI Map
1790  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1791  while (itUl != m_ueCqiTimers.end ())
1792  {
1793  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1794  if ((*itUl).second == 0)
1795  {
1796  // delete correspondent entries
1797  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1798  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1799  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1800  (*itMap).second.clear ();
1801  m_ueCqi.erase (itMap);
1802  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1803  itUl++;
1804  m_ueCqiTimers.erase (temp);
1805  }
1806  else
1807  {
1808  (*itUl).second--;
1809  itUl++;
1810  }
1811  }
1812 
1813  return;
1814 }
1815 
1816 void
1817 RrFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1818 {
1819  NS_LOG_FUNCTION (this);
1820  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1821  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1822  {
1823  if (((*it).m_rnti == rnti) && ((*it).m_logicalChannelIdentity == lcid))
1824  {
1825  NS_LOG_INFO (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).m_rlcTransmissionQueueSize << " retxqueue " << (*it).m_rlcRetransmissionQueueSize << " status " << (*it).m_rlcStatusPduSize << " decrease " << size);
1826  // Update queues: RLC tx order Status, ReTx, Tx
1827  // Update status queue
1828  if (((*it).m_rlcStatusPduSize > 0) && (size >= (*it).m_rlcStatusPduSize))
1829  {
1830  (*it).m_rlcStatusPduSize = 0;
1831  }
1832  else if (((*it).m_rlcRetransmissionQueueSize > 0) && (size >= (*it).m_rlcRetransmissionQueueSize))
1833  {
1834  (*it).m_rlcRetransmissionQueueSize = 0;
1835  }
1836  else if ((*it).m_rlcTransmissionQueueSize > 0)
1837  {
1838  // update transmission queue
1839  if ((*it).m_rlcTransmissionQueueSize <= size)
1840  {
1841  (*it).m_rlcTransmissionQueueSize = 0;
1842  }
1843  else
1844  {
1845  size -= 2; // remove minimun RLC overhead due to header
1846  (*it).m_rlcTransmissionQueueSize -= size;
1847  }
1848  }
1849  return;
1850  }
1851  }
1852 }
1853 
1854 void
1855 RrFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1856 {
1857 
1858  size = size - 2; // remove the minimum RLC overhead
1859  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1860  if (it != m_ceBsrRxed.end ())
1861  {
1862  NS_LOG_INFO (this << " Update RLC BSR UE " << rnti << " size " << size << " BSR " << (*it).second);
1863  if ((*it).second >= size)
1864  {
1865  (*it).second -= size;
1866  }
1867  else
1868  {
1869  (*it).second = 0;
1870  }
1871  }
1872  else
1873  {
1874  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1875  }
1876 
1877 }
1878 
1879 
1880 void
1881 RrFfMacScheduler::TransmissionModeConfigurationUpdate (uint16_t rnti, uint8_t txMode)
1882 {
1883  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1884  FfMacCschedSapUser::CschedUeConfigUpdateIndParameters params;
1885  params.m_rnti = rnti;
1886  params.m_transmissionMode = txMode;
1887  m_cschedSapUser->CschedUeConfigUpdateInd (params);
1888 }
1889 
1890 
1891 
1892 }
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
Hold a bool native type.
Definition: boolean.h:38
virtual FfMacSchedSapProvider * GetFfMacSchedSapProvider()
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
Provides the CSCHED SAP.
virtual void SetFfMacSchedSapUser(FfMacSchedSapUser *s)
#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
uint8_t UpdateHarqProcessId(uint16_t rnti)
Update and return a new process Id for the RNTI specified.
Hold an unsigned integer type.
Definition: uinteger.h:46
virtual void SetFfMacCschedSapUser(FfMacCschedSapUser *s)
Provides the SCHED SAP.
uint8_t HarqProcessAvailability(uint16_t rnti)
Return the availability of free process for the RNTI specified.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
void RefreshHarqProcesses()
Refresh HARQ processes according to the timers.
virtual FfMacCschedSapProvider * GetFfMacCschedSapProvider()
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
Implements the SCHED SAP and CSCHED SAP for a Round Robin scheduler.
#define NS_LOG_ERROR(msg)
Definition: log.h:237
virtual void DoDispose(void)
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.