A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
rr-ff-mac-scheduler.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Marco Miozzo <marco.miozzo@cttc.es>
19  */
20 
21 #include <ns3/log.h>
22 #include <ns3/pointer.h>
23 #include <ns3/math.h>
24 
25 #include <ns3/lte-amc.h>
26 #include <ns3/rr-ff-mac-scheduler.h>
27 #include <ns3/simulator.h>
28 #include <ns3/lte-common.h>
29 #include <ns3/lte-vendor-specific-parameters.h>
30 
31 NS_LOG_COMPONENT_DEFINE ("RrFfMacScheduler");
32 
33 namespace ns3 {
34 
36  10, // RGB size 1
37  26, // RGB size 2
38  63, // RGB size 3
39  110 // RGB size 4
40 }; // see table 7.1.6.1-1 of 36.213
41 
42 
43 
44 
45 NS_OBJECT_ENSURE_REGISTERED (RrFfMacScheduler);
46 
47 
49 {
50 public:
52 
53  // inherited from FfMacCschedSapProvider
54  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
55  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
56  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
57  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
58  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
59 
60 private:
63 };
64 
66 {
67 }
68 
70 {
71 }
72 
73 
74 void
76 {
78 }
79 
80 void
82 {
84 }
85 
86 
87 void
89 {
91 }
92 
93 void
95 {
97 }
98 
99 void
101 {
103 }
104 
105 
106 
107 
109 {
110 public:
112 
113  // inherited from FfMacSchedSapProvider
114  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
115  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
116  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
117  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
118  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
119  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
120  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
121  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
122  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
123  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
124  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
125 
126 
127 private:
130 };
131 
132 
133 
135 {
136 }
137 
138 
140  : m_scheduler (scheduler)
141 {
142 }
143 
144 void
146 {
148 }
149 
150 void
152 {
154 }
155 
156 void
158 {
160 }
161 
162 void
164 {
166 }
167 
168 void
170 {
172 }
173 
174 void
176 {
178 }
179 
180 void
182 {
184 }
185 
186 void
188 {
190 }
191 
192 void
194 {
196 }
197 
198 void
200 {
202 }
203 
204 void
206 {
208 }
209 
210 
211 
212 
213 
215  : m_cschedSapUser (0),
216  m_schedSapUser (0),
217  m_nextRntiDl (0),
218  m_nextRntiUl (0)
219 {
220  m_amc = CreateObject <LteAmc> ();
223 }
224 
226 {
227  NS_LOG_FUNCTION (this);
228 }
229 
230 void
232 {
233  NS_LOG_FUNCTION (this);
234  delete m_cschedSapProvider;
235  delete m_schedSapProvider;
236 }
237 
238 TypeId
240 {
241  static TypeId tid = TypeId ("ns3::RrFfMacScheduler")
243  .AddConstructor<RrFfMacScheduler> ()
244  .AddAttribute ("CqiTimerThreshold",
245  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
246  UintegerValue (1000),
247  MakeUintegerAccessor (&RrFfMacScheduler::m_cqiTimersThreshold),
248  MakeUintegerChecker<uint32_t> ())
249  ;
250  return tid;
251 }
252 
253 
254 
255 void
257 {
258  m_cschedSapUser = s;
259 }
260 
261 void
263 {
264  m_schedSapUser = s;
265 }
266 
269 {
270  return m_cschedSapProvider;
271 }
272 
275 {
276  return m_schedSapProvider;
277 }
278 
279 void
281 {
282  NS_LOG_FUNCTION (this);
283  // Read the subset of parameters used
284  m_cschedCellConfig = params;
286  cnf.m_result = SUCCESS;
288  return;
289 }
290 
291 void
293 {
294  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
295  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
296  if (it==m_uesTxMode.end ())
297  {
298  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
299  }
300  else
301  {
302  (*it).second = params.m_transmissionMode;
303  }
304  return;
305 }
306 
307 void
309 {
310  NS_LOG_FUNCTION (this);
311  // Not used at this stage
312  return;
313 }
314 
315 void
317 {
318  NS_LOG_FUNCTION (this);
319  NS_FATAL_ERROR ("method not implemented");
320  return;
321 }
322 
323 void
325 {
326  NS_LOG_FUNCTION (this);
327  NS_FATAL_ERROR ("method not implemented");
328  return;
329 }
330 
331 
332 void
334 {
335  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
336  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
337  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it = m_rlcBufferReq.begin ();
338  bool newLc = true;
339  while (it != m_rlcBufferReq.end ())
340  {
341  // remove old entries of this UE-LC
342  if (((*it).m_rnti == params.m_rnti)&&((*it).m_logicalChannelIdentity == params.m_logicalChannelIdentity))
343  {
344  it = m_rlcBufferReq.erase (it);
345  newLc = false;
346  }
347  else
348  {
349  ++it;
350  }
351  }
352  // add the new parameters
353  m_rlcBufferReq.insert (it, params);
354  // initialize statistics of the flow in case of new flows
355  if (newLc == true)
356  {
357  m_p10CqiRxed.insert ( std::pair<uint16_t, uint8_t > (params.m_rnti, 1)); // only codeword 0 at this stage (SISO)
358  // initialized to 1 (i.e., the lowest value for transmitting a signal)
359  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (params.m_rnti, m_cqiTimersThreshold));
360  }
361 
362  return;
363 }
364 
365 void
367 {
368  NS_LOG_FUNCTION (this);
369  NS_FATAL_ERROR ("method not implemented");
370  return;
371 }
372 
373 void
375 {
376  NS_LOG_FUNCTION (this);
377  NS_FATAL_ERROR ("method not implemented");
378  return;
379 }
380 
381 int
383 {
384  for (int i = 0; i < 4; i++)
385  {
386  if (dlbandwidth < Type0AllocationRbg[i])
387  {
388  return (i + 1);
389  }
390  }
391 
392  return (-1);
393 }
394 
395 bool
397 {
398  return (i.m_rnti<j.m_rnti);
399 }
400 
401 
402 void
404 {
405  NS_LOG_FUNCTION (this << " DL Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
406  // API generated by RLC for triggering the scheduling of a DL subframe
407 
408  RefreshDlCqiMaps ();
409 
410  // Get the actual active flows (queue!=0)
411  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
413  int nflows = 0;
414  int nTbs = 0;
415  std::map <uint16_t,uint8_t> lcActivesPerRnti;
416  std::map <uint16_t,uint8_t>::iterator itLcRnti;
417  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
418  {
419 // NS_LOG_INFO (this << " User " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
420  // remove old entries of this UE-LC
421  if ( ((*it).m_rlcTransmissionQueueSize > 0)
422  || ((*it).m_rlcRetransmissionQueueSize > 0)
423  || ((*it).m_rlcStatusPduSize > 0) )
424  {
425  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find ((*it).m_rnti);
426  uint8_t cqi = 0;
427  if (itCqi != m_p10CqiRxed.end ())
428  {
429  cqi = (*itCqi).second;
430  }
431  else
432  {
433  cqi = 1; // lowest value fro trying a transmission
434  }
435  if (cqi != 0)
436  {
437  // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
438  nflows++;
439  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
440  if (itLcRnti != lcActivesPerRnti.end ())
441  {
442  (*itLcRnti).second++;
443  }
444  else
445  {
446  lcActivesPerRnti.insert (std::pair<uint16_t, uint8_t > ((*it).m_rnti, 1));
447  nTbs++;
448  }
449 
450  }
451  }
452  }
453 
454  if (nflows == 0)
455  {
456  return;
457  }
458  // Divide the resource equally among the active users according to
459  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
461  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
462  int rbgPerTb = rbgNum / nTbs;
463  if (rbgPerTb == 0)
464  {
465  rbgPerTb = 1; // at least 1 rbg per TB (till available resource)
466  }
467  int rbgAllocated = 0;
468 
470  // round robin assignment to all UE-LC registered starting from the subsequent of the one
471  // served last scheduling trigger
472  //NS_LOG_DEBUG (this << " next to be served " << m_nextRntiDl << " nflows " << nflows);
473  if (m_nextRntiDl != 0)
474  {
475  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
476  {
477  if ((*it).m_rnti == m_nextRntiDl)
478  {
479  break;
480  }
481  }
482 
483  if (it == m_rlcBufferReq.end ())
484  {
485  NS_LOG_ERROR (this << " no user found");
486  }
487  }
488  else
489  {
490  it = m_rlcBufferReq.begin ();
491  m_nextRntiDl = (*it).m_rnti;
492  }
493  std::map <uint16_t,uint8_t>::iterator itTxMode;
494  do
495  {
496  itLcRnti = lcActivesPerRnti.find ((*it).m_rnti);
497  if (itLcRnti == lcActivesPerRnti.end ())
498  {
499  // skip this entry
500  it++;
501  if (it == m_rlcBufferReq.end ())
502  {
503  // restart from the first
504  it = m_rlcBufferReq.begin ();
505  }
506  continue;
507  }
508  itTxMode = m_uesTxMode.find ((*it).m_rnti);
509  if (itTxMode == m_uesTxMode.end())
510  {
511  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it).m_rnti);
512  }
513  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
514  int lcNum = (*itLcRnti).second;
515  // create new BuildDataListElement_s for this RNTI
517  newEl.m_rnti = (*it).m_rnti;
518  // create the DlDciListElement_s
519  DlDciListElement_s newDci;
520  newDci.m_rnti = (*it).m_rnti;
521  newDci.m_resAlloc = 0;
522  newDci.m_rbBitmap = 0;
523  std::map <uint16_t,uint8_t>::iterator itCqi = m_p10CqiRxed.find (newEl.m_rnti);
524  for (uint8_t i = 0; i < nLayer; i++)
525  {
526  if (itCqi == m_p10CqiRxed.end ())
527  {
528  newDci.m_mcs.push_back (0); // no info on this user -> lowest MCS
529  }
530  else
531  {
532  newDci.m_mcs.push_back ( m_amc->GetMcsFromCqi ((*itCqi).second) );
533  }
534  }
535  // group the LCs of this RNTI
536  std::vector <struct RlcPduListElement_s> newRlcPduLe;
537 // int totRbg = lcNum * rbgPerFlow;
538 // totRbg = rbgNum / nTbs;
539  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
540  NS_LOG_DEBUG (this << " DL - Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " PRBs " << rbgAllocated * rbgSize << "..." << (rbgAllocated* rbgSize) + (rbgPerTb * rbgSize) - 1 << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " layers " << nLayer);
541  uint16_t rlcPduSize = tbSize / lcNum;
542  for (int i = 0; i < lcNum ; i++)
543  {
544  for (uint8_t j = 0; j < nLayer; j++)
545  {
546  RlcPduListElement_s newRlcEl;
547  newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
548 // NS_LOG_DEBUG (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
549  newRlcEl.m_size = rlcPduSize;
550  UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
551  newRlcPduLe.push_back (newRlcEl);
552  }
553  it++;
554  if (it == m_rlcBufferReq.end ())
555  {
556  // restart from the first
557  it = m_rlcBufferReq.begin ();
558  }
559  }
560  uint32_t rbgMask = 0;
561  for (int i = 0; i < rbgPerTb; i++)
562  {
563  rbgMask = rbgMask + (0x1 << rbgAllocated);
564  rbgAllocated++;
565  }
566  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
567 
568  for (int i = 0; i < nLayer; i++)
569  {
570  newDci.m_tbsSize.push_back (tbSize);
571  newDci.m_ndi.push_back (1); // TBD (new data indicator)
572  newDci.m_rv.push_back (0); // TBD (redundancy version)
573  }
574  newEl.m_dci = newDci;
575  // ...more parameters -> ignored in this version
576 
577 
578 
579 
580  newEl.m_rlcPduList.push_back (newRlcPduLe);
581  ret.m_buildDataList.push_back (newEl);
582  if (rbgAllocated == rbgNum)
583  {
584  //NS_LOG_DEBUG (this << " FULL " << (*it).m_rnti);
585  m_nextRntiDl = (*it).m_rnti; // store last RNTI served
586  break; // no more RGB to be allocated
587  }
588  }
589  while ((*it).m_rnti != m_nextRntiDl);
590 
591  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
592 
594  return;
595 }
596 
597 void
599 {
600  NS_LOG_FUNCTION (this);
601  NS_FATAL_ERROR ("method not implemented");
602  return;
603 }
604 
605 void
607 {
608  NS_LOG_FUNCTION (this);
609 
610  std::map <uint16_t,uint8_t>::iterator it;
611  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
612  {
613  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
614  {
615  // wideband CQI reporting
616  std::map <uint16_t,uint8_t>::iterator it;
617  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
618  it = m_p10CqiRxed.find (rnti);
619  if (it == m_p10CqiRxed.end ())
620  {
621  // create the new entry
622  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)
623  // generate correspondent timer
624  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
625  }
626  else
627  {
628  // update the CQI value
629  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
630  // update correspondent timer
631  std::map <uint16_t,uint32_t>::iterator itTimers;
632  itTimers = m_p10CqiTimers.find (rnti);
633  (*itTimers).second = m_cqiTimersThreshold;
634  }
635  }
636  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
637  {
638  // subband CQI reporting high layer configured
639  // Not used by RR Scheduler
640  }
641  else
642  {
643  NS_LOG_ERROR (this << " CQI type unknown");
644  }
645  }
646 
647  return;
648 }
649 
650 void
652 {
653  NS_LOG_FUNCTION (this << " Ul - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
654 
655 
656  RefreshUlCqiMaps ();
657 
658  std::map <uint16_t,uint32_t>::iterator it;
659  int nflows = 0;
660 
661  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
662  {
663  // remove old entries of this UE-LC
664  if ((*it).second > 0)
665  {
666  nflows++;
667  }
668  }
669 
670  if (nflows == 0)
671  {
672  return ; // no flows to be scheduled
673  }
674 
675 
676  // Divide the resource equally among the active users starting from the subsequent one served last scheduling trigger
677  int rbPerFlow = m_cschedCellConfig.m_ulBandwidth / nflows;
678  if (rbPerFlow == 0)
679  {
680  rbPerFlow = 1; // at least 1 rbg per flow (till available resource)
681  }
682  int rbAllocated = 0;
683 
685  std::vector <uint16_t> rbgAllocationMap;
686  if (m_nextRntiUl != 0)
687  {
688  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
689  {
690  if ((*it).first == m_nextRntiUl)
691  {
692  break;
693  }
694  }
695  if (it == m_ceBsrRxed.end ())
696  {
697  NS_LOG_ERROR (this << " no user found");
698  }
699  }
700  else
701  {
702  it = m_ceBsrRxed.begin ();
703  m_nextRntiUl = (*it).first;
704  }
705  do
706  {
707  if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth)
708  {
709  // limit to physical resources last resource assignment
710  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
711  }
712 
713  UlDciListElement_s uldci;
714  uldci.m_rnti = (*it).first;
715  uldci.m_rbStart = rbAllocated;
716  uldci.m_rbLen = rbPerFlow;
717  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
718  int cqi = 0;
719  if (itCqi == m_ueCqi.end ())
720  {
721  // no cqi info about this UE
722  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
723  NS_LOG_DEBUG (this << " UE does not have ULCQI " << (*it).first );
724  }
725  else
726  {
727  // take the lowest CQI value (worst RB)
728  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
729  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
730  {
731  if ((*itCqi).second.at (i) < minSinr)
732  {
733  minSinr = (*itCqi).second.at (i);
734  }
735  }
736  // translate SINR -> cqi: WILD ACK: same as DL
737  double s = log2 ( 1 + (
738  std::pow (10, minSinr / 10 ) /
739  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
740 
741 
743  if (cqi == 0)
744  {
745  it++;
746  if (it == m_ceBsrRxed.end ())
747  {
748  // restart from the first
749  it = m_ceBsrRxed.begin ();
750  }
751  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
752  }
753  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
754 // NS_LOG_DEBUG (this << " UE " << (*it).first << " minsinr " << minSinr << " -> mcs " << (uint16_t)uldci.m_mcs);
755 
756  }
757 
758  rbAllocated += rbPerFlow;
759  // store info on allocation for managing ul-cqi interpretation
760  for (int i = 0; i < rbPerFlow; i++)
761  {
762  rbgAllocationMap.push_back ((*it).first);
763  }
764 
765  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD
766  NS_LOG_DEBUG (this << " UL - 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);
767  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
768  uldci.m_ndi = 1;
769  uldci.m_cceIndex = 0;
770  uldci.m_aggrLevel = 1;
771  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
772  uldci.m_hopping = false;
773  uldci.m_n2Dmrs = 0;
774  uldci.m_tpc = 0; // no power control
775  uldci.m_cqiRequest = false; // only period CQI at this stage
776  uldci.m_ulIndex = 0; // TDD parameter
777  uldci.m_dai = 1; // TDD parameter
778  uldci.m_freqHopping = 0;
779  uldci.m_pdcchPowerOffset = 0; // not used
780  ret.m_dciList.push_back (uldci);
781  it++;
782  if (it == m_ceBsrRxed.end ())
783  {
784  // restart from the first
785  it = m_ceBsrRxed.begin ();
786  }
787  if (rbAllocated == m_cschedCellConfig.m_ulBandwidth)
788  {
789  // Stop allocation: no more PRBs
790  m_nextRntiUl = (*it).first;
791  break;
792  }
793  }
794  while ((*it).first != m_nextRntiUl);
795  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
797  return;
798 }
799 
800 void
802 {
803  NS_LOG_FUNCTION (this);
804  // TODO: Implementation of the API
805  return;
806 }
807 
808 void
810 {
811  NS_LOG_FUNCTION (this);
812  // TODO: Implementation of the API
813  return;
814 }
815 
816 void
818 {
819  NS_LOG_FUNCTION (this);
820 
821  std::map <uint16_t,uint32_t>::iterator it;
822 
823  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
824  {
825  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
826  {
827  // buffer status report
828  // note that we only consider LCG 0, the other three LCGs are neglected
829  // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
830  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
831  it = m_ceBsrRxed.find (rnti);
832  if (it == m_ceBsrRxed.end ())
833  {
834  // create the new entry
835  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
836  int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
837  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
838  }
839  else
840  {
841  // update the buffer size value
842  (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
843  }
844  }
845  }
846 
847  return;
848 }
849 
850 void
852 {
853  NS_LOG_FUNCTION (this);
854  NS_LOG_DEBUG (this << " RX SFNID " << params.m_sfnSf);
855 // NS_LOG_DEBUG (this << " Actual sfn " << frameNo << " sbfn " << subframeNo << " sfnSf " << sfnSf);
856  switch (m_ulCqiFilter)
857  {
859  {
860  // filter all the CQIs that are not SRS based
861  if (params.m_ulCqi.m_type!=UlCqi_s::SRS)
862  {
863  return;
864  }
865  }
866  break;
868  {
869  // filter all the CQIs that are not SRS based
870  if (params.m_ulCqi.m_type!=UlCqi_s::PUSCH)
871  {
872  return;
873  }
874  }
876  break;
877 
878  default:
879  NS_FATAL_ERROR ("Unknown UL CQI type");
880  }
881  switch (params.m_ulCqi.m_type)
882  {
883  case UlCqi_s::PUSCH:
884  {
885  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
886  std::map <uint16_t, std::vector <double> >::iterator itCqi;
887  itMap = m_allocationMaps.find (params.m_sfnSf);
888  if (itMap == m_allocationMaps.end ())
889  {
890  NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
891  return;
892  }
893  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
894  {
895  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
896  // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
897  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
898  //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr);
899  itCqi = m_ueCqi.find ((*itMap).second.at (i));
900  if (itCqi == m_ueCqi.end ())
901  {
902  // create a new entry
903  std::vector <double> newCqi;
904  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
905  {
906  if (i == j)
907  {
908  newCqi.push_back (sinr);
909  }
910  else
911  {
912  // initialize with NO_SINR value.
913  newCqi.push_back (30.0);
914  }
915 
916  }
917  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
918  // generate correspondent timer
919  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
920  }
921  else
922  {
923  // update the value
924  (*itCqi).second.at (i) = sinr;
925  // update correspondent timer
926  std::map <uint16_t, uint32_t>::iterator itTimers;
927  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
928  (*itTimers).second = m_cqiTimersThreshold;
929 
930  }
931 
932  }
933  // remove obsolete info on allocation
934  m_allocationMaps.erase (itMap);
935  }
936  break;
937  case UlCqi_s::SRS:
938  {
939  // get the RNTI from vendor specific parameters
940  uint16_t rnti = 0;
941  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
942  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
943  {
944  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
945  {
946  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
947  rnti = vsp->GetRnti ();
948  }
949  }
950  std::map <uint16_t, std::vector <double> >::iterator itCqi;
951  itCqi = m_ueCqi.find (rnti);
952  if (itCqi == m_ueCqi.end ())
953  {
954  // create a new entry
955  std::vector <double> newCqi;
956  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
957  {
958  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
959  newCqi.push_back (sinr);
960  NS_LOG_DEBUG (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
961 
962  }
963  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
964  // generate correspondent timer
965  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
966  }
967  else
968  {
969  // update the values
970  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
971  {
972  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
973  (*itCqi).second.at (j) = sinr;
974  NS_LOG_DEBUG (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
975  }
976  // update correspondent timer
977  std::map <uint16_t, uint32_t>::iterator itTimers;
978  itTimers = m_ueCqiTimers.find (rnti);
979  (*itTimers).second = m_cqiTimersThreshold;
980 
981  }
982 
983 
984  }
985  break;
986  case UlCqi_s::PUCCH_1:
987  case UlCqi_s::PUCCH_2:
988  case UlCqi_s::PRACH:
989  {
990  NS_FATAL_ERROR ("PfFfMacScheduler supports only PUSCH and SRS UL-CQIs");
991  }
992  break;
993  default:
994  NS_FATAL_ERROR ("Unknown type of UL-CQI");
995  }
996  return;
997 }
998 
999 
1000 void
1002 {
1003  NS_LOG_FUNCTION (this << m_p10CqiTimers.size ());
1004  // refresh DL CQI P01 Map
1005  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1006  while (itP10!=m_p10CqiTimers.end ())
1007  {
1008  NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1009  if ((*itP10).second == 0)
1010  {
1011  // delete correspondent entries
1012  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1013  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1014  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1015  m_p10CqiRxed.erase (itMap);
1016  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1017  itP10++;
1018  m_p10CqiTimers.erase (temp);
1019  }
1020  else
1021  {
1022  (*itP10).second--;
1023  itP10++;
1024  }
1025  }
1026 
1027  return;
1028 }
1029 
1030 
1031 void
1033 {
1034  // refresh UL CQI Map
1035  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1036  while (itUl!=m_ueCqiTimers.end ())
1037  {
1038  NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1039  if ((*itUl).second == 0)
1040  {
1041  // delete correspondent entries
1042  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1043  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1044  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1045  (*itMap).second.clear ();
1046  m_ueCqi.erase (itMap);
1047  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1048  itUl++;
1049  m_ueCqiTimers.erase (temp);
1050  }
1051  else
1052  {
1053  (*itUl).second--;
1054  itUl++;
1055  }
1056  }
1057 
1058  return;
1059 }
1060 
1061 void
1062 RrFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1063 {
1064  size = size - 2; // remove the minimum RLC overhead
1065  std::list<FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1066  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
1067  {
1068  if (((*it).m_rnti == rnti) && ((*it).m_logicalChannelIdentity))
1069  {
1070 // NS_LOG_DEBUG (this << " UE " << rnti << " LC " << (uint16_t)lcid << " txqueue " << (*it).m_rlcTransmissionQueueSize << " retxqueue " << (*it).m_rlcRetransmissionQueueSize << " status " << (*it).m_rlcStatusPduSize << " decrease " << size);
1071  // Update queues: RLC tx order Status, ReTx, Tx
1072  // Update status queue
1073  if ((*it).m_rlcStatusPduSize <= size)
1074  {
1075  size -= (*it).m_rlcStatusPduSize;
1076  (*it).m_rlcStatusPduSize = 0;
1077  }
1078  else
1079  {
1080  (*it).m_rlcStatusPduSize -= size;
1081  return;
1082  }
1083  // update retransmission queue
1084  if ((*it).m_rlcRetransmissionQueueSize <= size)
1085  {
1086  size -= (*it).m_rlcRetransmissionQueueSize;
1087  (*it).m_rlcRetransmissionQueueSize = 0;
1088  }
1089  else
1090  {
1091  (*it).m_rlcRetransmissionQueueSize -= size;
1092  return;
1093  }
1094  // update transmission queue
1095  if ((*it).m_rlcTransmissionQueueSize <= size)
1096  {
1097  size -= (*it).m_rlcTransmissionQueueSize;
1098  (*it).m_rlcTransmissionQueueSize = 0;
1099  }
1100  else
1101  {
1102  (*it).m_rlcTransmissionQueueSize -= size;
1103  return;
1104  }
1105  return;
1106  }
1107  }
1108 }
1109 
1110 void
1111 RrFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1112 {
1113 
1114  size = size - 2; // remove the minimum RLC overhead
1115  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1116  if (it!=m_ceBsrRxed.end ())
1117  {
1118 // NS_LOG_DEBUG (this << " Update RLC BSR UE " << rnti << " size " << size << " BSR " << (*it).second);
1119  if ((*it).second >= size)
1120  {
1121  (*it).second -= size;
1122  }
1123  else
1124  {
1125  (*it).second = 0;
1126  }
1127  }
1128  else
1129  {
1130  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1131  }
1132 
1133 }
1134 
1135 
1136 void
1138 {
1139  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1141  params.m_rnti = rnti;
1142  params.m_transmissionMode = txMode;
1144 }
1145 
1146 
1147 
1148 }