A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
tta-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> // original version
19  * Modification: Dizhi Zhou <dizhi.zhou@gmail.com> // modify codes related to downlink scheduler
20  */
21 
22 #include <ns3/log.h>
23 #include <ns3/pointer.h>
24 #include <ns3/math.h>
25 
26 #include <ns3/simulator.h>
27 #include <ns3/lte-amc.h>
28 #include <ns3/tta-ff-mac-scheduler.h>
29 #include <ns3/lte-vendor-specific-parameters.h>
30 
31 NS_LOG_COMPONENT_DEFINE ("TtaFfMacScheduler");
32 
33 // value for SINR outside the range defined by LTE, used to indicate that there
34 // is no CQI for this element
35 #define NO_SINR -5000
36 
37 namespace ns3 {
38 
40  10, // RGB size 1
41  26, // RGB size 2
42  63, // RGB size 3
43  110 // RGB size 4
44 }; // see table 7.1.6.1-1 of 36.213
45 
46 
47 NS_OBJECT_ENSURE_REGISTERED (TtaFfMacScheduler);
48 
49 
50 
52 {
53 public:
55 
56  // inherited from FfMacCschedSapProvider
57  virtual void CschedCellConfigReq (const struct CschedCellConfigReqParameters& params);
58  virtual void CschedUeConfigReq (const struct CschedUeConfigReqParameters& params);
59  virtual void CschedLcConfigReq (const struct CschedLcConfigReqParameters& params);
60  virtual void CschedLcReleaseReq (const struct CschedLcReleaseReqParameters& params);
61  virtual void CschedUeReleaseReq (const struct CschedUeReleaseReqParameters& params);
62 
63 private:
66 };
67 
69 {
70 }
71 
73 {
74 }
75 
76 
77 void
79 {
81 }
82 
83 void
85 {
87 }
88 
89 
90 void
92 {
94 }
95 
96 void
98 {
100 }
101 
102 void
104 {
106 }
107 
108 
109 
110 
112 {
113 public:
115 
116  // inherited from FfMacSchedSapProvider
117  virtual void SchedDlRlcBufferReq (const struct SchedDlRlcBufferReqParameters& params);
118  virtual void SchedDlPagingBufferReq (const struct SchedDlPagingBufferReqParameters& params);
119  virtual void SchedDlMacBufferReq (const struct SchedDlMacBufferReqParameters& params);
120  virtual void SchedDlTriggerReq (const struct SchedDlTriggerReqParameters& params);
121  virtual void SchedDlRachInfoReq (const struct SchedDlRachInfoReqParameters& params);
122  virtual void SchedDlCqiInfoReq (const struct SchedDlCqiInfoReqParameters& params);
123  virtual void SchedUlTriggerReq (const struct SchedUlTriggerReqParameters& params);
124  virtual void SchedUlNoiseInterferenceReq (const struct SchedUlNoiseInterferenceReqParameters& params);
125  virtual void SchedUlSrInfoReq (const struct SchedUlSrInfoReqParameters& params);
126  virtual void SchedUlMacCtrlInfoReq (const struct SchedUlMacCtrlInfoReqParameters& params);
127  virtual void SchedUlCqiInfoReq (const struct SchedUlCqiInfoReqParameters& params);
128 
129 
130 private:
133 };
134 
135 
136 
138 {
139 }
140 
141 
143  : m_scheduler (scheduler)
144 {
145 }
146 
147 void
149 {
151 }
152 
153 void
155 {
157 }
158 
159 void
161 {
163 }
164 
165 void
167 {
169 }
170 
171 void
173 {
175 }
176 
177 void
179 {
181 }
182 
183 void
185 {
187 }
188 
189 void
191 {
193 }
194 
195 void
197 {
199 }
200 
201 void
203 {
205 }
206 
207 void
209 {
211 }
212 
213 
214 
215 
216 
218  : m_cschedSapUser (0),
219  m_schedSapUser (0),
220  m_nextRntiUl (0)
221 {
222  m_amc = CreateObject <LteAmc> ();
225 }
226 
228 {
229  NS_LOG_FUNCTION (this);
230 }
231 
232 void
234 {
235  NS_LOG_FUNCTION (this);
236  delete m_cschedSapProvider;
237  delete m_schedSapProvider;
238 }
239 
240 TypeId
242 {
243  static TypeId tid = TypeId ("ns3::TtaFfMacScheduler")
245  .AddConstructor<TtaFfMacScheduler> ()
246  .AddAttribute ("CqiTimerThreshold",
247  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
248  UintegerValue (1000),
249  MakeUintegerAccessor (&TtaFfMacScheduler::m_cqiTimersThreshold),
250  MakeUintegerChecker<uint32_t> ())
251  ;
252  return tid;
253 }
254 
255 
256 
257 void
259 {
260  m_cschedSapUser = s;
261 }
262 
263 void
265 {
266  m_schedSapUser = s;
267 }
268 
271 {
272  return m_cschedSapProvider;
273 }
274 
277 {
278  return m_schedSapProvider;
279 }
280 
281 void
283 {
284  NS_LOG_FUNCTION (this);
285  // Read the subset of parameters used
286  m_cschedCellConfig = params;
288  cnf.m_result = SUCCESS;
290  return;
291 }
292 
293 void
295 {
296  NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
297  std::map <uint16_t,uint8_t>::iterator it = m_uesTxMode.find (params.m_rnti);
298  if (it == m_uesTxMode.end ())
299  {
300  m_uesTxMode.insert (std::pair <uint16_t, double> (params.m_rnti, params.m_transmissionMode));
301  }
302  else
303  {
304  (*it).second = params.m_transmissionMode;
305  }
306  return;
307 }
308 
309 void
311 {
312  NS_LOG_FUNCTION (this << " New LC, rnti: " << params.m_rnti);
313 
314  std::set<uint16_t>::iterator it;
315 
316  for (uint16_t i = 0; i < params.m_logicalChannelConfigList.size (); i++)
317  {
318  it = m_flowStatsDl.find (params.m_rnti);
319 
320  if (it == m_flowStatsDl.end ())
321  {
322  m_flowStatsDl.insert (params.m_rnti);
323  m_flowStatsUl.insert (params.m_rnti);
324  }
325  else
326  {
327  NS_LOG_ERROR ("RNTI already exists");
328  }
329 
330  }
331 
332  return;
333 }
334 
335 
336 void
338 {
339  NS_FATAL_ERROR ("unimplemented");
340  return;
341 }
342 
343 void
345 {
346  NS_FATAL_ERROR ("unimplemented");
347  return;
348 }
349 
350 
351 void
353 {
354  NS_LOG_FUNCTION (this << params.m_rnti << (uint32_t) params.m_logicalChannelIdentity);
355  // API generated by RLC for updating RLC parameters on a LC (tx and retx queues)
356 
357  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
358 
359  LteFlowId_t flow (params.m_rnti, params.m_logicalChannelIdentity);
360 
361  it = m_rlcBufferReq.find (flow);
362 
363  if (it == m_rlcBufferReq.end ())
364  {
365  m_rlcBufferReq.insert (std::pair <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters> (flow, params));
366  }
367  else
368  {
369  (*it).second = params;
370  }
371 
372  return;
373 }
374 
375 void
377 {
378  NS_FATAL_ERROR ("unimplemented");
379  return;
380 }
381 
382 void
384 {
385  NS_FATAL_ERROR ("unimplemented");
386  return;
387 }
388 
389 int
391 {
392  for (int i = 0; i < 4; i++)
393  {
394  if (dlbandwidth < TtaType0AllocationRbg[i])
395  {
396  return (i + 1);
397  }
398  }
399 
400  return (-1);
401 }
402 
403 
404 int
406 {
407  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
408  int lcActive = 0;
409  for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
410  {
411  if (((*it).first.m_rnti == rnti) && (((*it).second.m_rlcTransmissionQueueSize > 0)
412  || ((*it).second.m_rlcRetransmissionQueueSize > 0)
413  || ((*it).second.m_rlcStatusPduSize > 0) ))
414  {
415  lcActive++;
416  }
417  if ((*it).first.m_rnti > rnti)
418  {
419  break;
420  }
421  }
422  return (lcActive);
423 
424 }
425 
426 
427 void
429 {
430  NS_LOG_FUNCTION (this << " Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
431  // API generated by RLC for triggering the scheduling of a DL subframe
432 
433 
434  // evaluate the relative channel quality indicator for each UE per each RBG
435  // (since we are using allocation type 0 the small unit of allocation is RBG)
436  // Resource allocation type 0 (see sec 7.1.6.1 of 36.213)
437 
438  RefreshDlCqiMaps ();
439 
441  int rbgNum = m_cschedCellConfig.m_dlBandwidth / rbgSize;
442  std::map <uint16_t, std::vector <uint16_t> > allocationMap;
443  for (int i = 0; i < rbgNum; i++)
444  {
445  std::set <uint16_t>::iterator it;
446  std::set <uint16_t>::iterator itMax = m_flowStatsDl.end ();
447  double metricMax = 0.0;
448  for (it = m_flowStatsDl.begin (); it != m_flowStatsDl.end (); it++)
449  {
450  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
451  itCqi = m_a30CqiRxed.find ((*it));
452  std::map <uint16_t,uint8_t>::iterator itWbCqi;
453  itWbCqi = m_p10CqiRxed.find ((*it));
454  std::map <uint16_t,uint8_t>::iterator itTxMode;
455  itTxMode = m_uesTxMode.find ((*it));
456  if (itTxMode == m_uesTxMode.end ())
457  {
458  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it));
459  }
460  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
461  std::vector <uint8_t> sbCqi;
462  if (itCqi == m_a30CqiRxed.end ())
463  {
464  for (uint8_t k = 0; k < nLayer; k++)
465  {
466  sbCqi.push_back (1); // start with lowest value
467  }
468  }
469  else
470  {
471  sbCqi = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi;
472  }
473 
474  uint8_t wbCqi = 0;
475  if (itWbCqi == m_p10CqiRxed.end())
476  {
477  wbCqi = 1; // start with lowest value
478  }
479  else
480  {
481  wbCqi = (*itWbCqi).second;
482  }
483 
484  uint8_t cqi1 = sbCqi.at(0);
485  uint8_t cqi2 = 1;
486  if (sbCqi.size () > 1)
487  {
488  cqi2 = sbCqi.at(1);
489  }
490 
491  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
492  {
493  if (LcActivePerFlow (*it) > 0)
494  {
495  // this UE has data to transmit
496  uint8_t sbMcs = 0;
497  uint8_t wbMcs = 0;
498  double achievableSbRate = 1.0;
499  double achievableWbRate = 1.0;
500  for (uint8_t k = 0; k < nLayer; k++)
501  {
502  if (sbCqi.size () > k)
503  {
504  sbMcs = m_amc->GetMcsFromCqi (sbCqi.at (k));
505  }
506  else
507  {
508  // no info on this subband -> worst MCS
509  sbMcs = 0;
510  }
511  achievableSbRate += ((m_amc->GetTbSizeFromMcs (sbMcs, rbgSize) / 8) / 0.001); // = TB size / TTI
512  wbMcs = m_amc->GetMcsFromCqi (wbCqi);
513  achievableWbRate += ((m_amc->GetTbSizeFromMcs (wbMcs, rbgSize) / 8) / 0.001); // = TB size / TTI
514  }
515 
516  double metric = achievableSbRate / achievableWbRate;
517 
518  if (metric > metricMax)
519  {
520  metricMax = metric;
521  itMax = it;
522  }
523  }
524  } // end if cqi
525  } // end for m_flowStatsDl
526 
527  if (itMax == m_flowStatsDl.end ())
528  {
529  // no UE available for this RB
530  NS_LOG_DEBUG (this << " no UE found");
531  }
532  else
533  {
534  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
535  itMap = allocationMap.find ((*itMax));
536  if (itMap == allocationMap.end ())
537  {
538  // insert new element
539  std::vector <uint16_t> tempMap;
540  tempMap.push_back (i);
541  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax), tempMap));
542  }
543  else
544  {
545  (*itMap).second.push_back (i);
546  }
547  }
548  } // end for RBGs
549 
550 
551  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
552  // creating the correspondent DCIs
554  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
555  while (itMap != allocationMap.end ())
556  {
557  // create new BuildDataListElement_s for this LC
559  newEl.m_rnti = (*itMap).first;
560  // create the DlDciListElement_s
561  DlDciListElement_s newDci;
562  std::vector <struct RlcPduListElement_s> newRlcPduLe;
563  newDci.m_rnti = (*itMap).first;
564 
565  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
566  uint16_t rbgPerRnti = (*itMap).second.size ();
567  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
568  itCqi = m_a30CqiRxed.find ((*itMap).first);
569  std::map <uint16_t,uint8_t>::iterator itTxMode;
570  itTxMode = m_uesTxMode.find ((*itMap).first);
571  if (itTxMode == m_uesTxMode.end ())
572  {
573  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
574  }
575  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
576  std::vector <uint8_t> worstCqi (2, 15);
577  if (itCqi != m_a30CqiRxed.end ())
578  {
579  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
580  {
581  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
582  {
583  for (uint8_t j = 0; j < nLayer; j++)
584  {
585  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
586  {
587  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
588  {
589  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
590  }
591  }
592  else
593  {
594  // no CQI for this layer of this suband -> worst one
595  worstCqi.at (j) = 1;
596  }
597  }
598  }
599  else
600  {
601  for (uint8_t j = 0; j < nLayer; j++)
602  {
603  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
604  }
605  }
606  }
607  }
608  else
609  {
610  for (uint8_t j = 0; j < nLayer; j++)
611  {
612  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
613  }
614  }
615  for (uint8_t j = 0; j < nLayer; j++)
616  {
617  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
618  int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (j), rbgPerRnti * rbgSize) / 8); // (size of TB in bytes according to table 7.1.7.2.1-1 of 36.213)
619  newDci.m_tbsSize.push_back (tbSize);
620  }
621 
622  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
623  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
624  uint32_t rbgMask = 0;
625  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
626  {
627  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
628  }
629  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
630 
631  // create the rlc PDUs -> equally divide resources among actives LCs
632  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
633  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
634  {
635  if (((*itBufReq).first.m_rnti == (*itMap).first) &&
636  (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
637  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
638  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
639  {
640  for (uint8_t j = 0; j < nLayer; j++)
641  {
642  RlcPduListElement_s newRlcEl;
643  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
644  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
645  newRlcPduLe.push_back (newRlcEl);
646  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
647  }
648  }
649  if ((*itBufReq).first.m_rnti > (*itMap).first)
650  {
651  break;
652  }
653  }
654  newDci.m_ndi.push_back (1); // TBD (new data indicator)
655  newDci.m_rv.push_back (0); // TBD (redundancy version)
656 
657  newEl.m_dci = newDci;
658  // ...more parameters -> ingored in this version
659 
660  newEl.m_rlcPduList.push_back (newRlcPduLe);
661  ret.m_buildDataList.push_back (newEl);
662 
663 
664  itMap++;
665  } // end while allocation
666  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
667 
669 
670  return;
671 }
672 
673 void
675 {
676  NS_FATAL_ERROR ("unimplemented");
677  return;
678 }
679 
680 void
682 {
683  NS_LOG_FUNCTION (this);
684 
685  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
686  {
687  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
688  {
689  // wideband CQI reporting
690  std::map <uint16_t,uint8_t>::iterator it;
691  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
692  it = m_p10CqiRxed.find (rnti);
693  if (it == m_p10CqiRxed.end ())
694  {
695  // create the new entry
696  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)
697  // generate correspondent timer
698  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
699  }
700  else
701  {
702  // update the CQI value and refresh correspondent timer
703  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
704  // update correspondent timer
705  std::map <uint16_t,uint32_t>::iterator itTimers;
706  itTimers = m_p10CqiTimers.find (rnti);
707  (*itTimers).second = m_cqiTimersThreshold;
708  }
709  }
710  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
711  {
712  // subband CQI reporting high layer configured
713  std::map <uint16_t,SbMeasResult_s>::iterator it;
714  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
715  it = m_a30CqiRxed.find (rnti);
716  if (it == m_a30CqiRxed.end ())
717  {
718  // create the new entry
719  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
720  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
721  }
722  else
723  {
724  // update the CQI value and refresh correspondent timer
725  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
726  std::map <uint16_t,uint32_t>::iterator itTimers;
727  itTimers = m_a30CqiTimers.find (rnti);
728  (*itTimers).second = m_cqiTimersThreshold;
729  }
730  }
731  else
732  {
733  NS_LOG_ERROR (this << " CQI type unknown");
734  }
735  }
736 
737  return;
738 }
739 
740 
741 double
742 TtaFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
743 {
744  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
745  if (itCqi == m_ueCqi.end ())
746  {
747  // no cqi info about this UE
748  return (NO_SINR);
749 
750  }
751  else
752  {
753  // take the average SINR value among the available
754  double sinrSum = 0;
755  int sinrNum = 0;
756  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
757  {
758  double sinr = (*itCqi).second.at (i);
759  if (sinr != NO_SINR)
760  {
761  sinrSum += sinr;
762  sinrNum++;
763  }
764  }
765  double estimatedSinr = sinrSum / (double)sinrNum;
766  // store the value
767  (*itCqi).second.at (rb) = estimatedSinr;
768  return (estimatedSinr);
769  }
770 }
771 
772 void
774 {
775  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
776 
777  RefreshUlCqiMaps ();
778 
779  std::map <uint16_t,uint32_t>::iterator it;
780  int nflows = 0;
781 
782  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
783  {
784  // remove old entries of this UE-LC
785  if ((*it).second > 0)
786  {
787  nflows++;
788  }
789  }
790 
791  if (nflows == 0)
792  {
793  return ; // no flows to be scheduled
794  }
795 
796 
797  // Divide the resource equally among the active users
798  int rbPerFlow = m_cschedCellConfig.m_ulBandwidth / nflows;
799  if (rbPerFlow == 0)
800  {
801  rbPerFlow = 1; // at least 1 rbg per flow (till available resource)
802  }
803  int rbAllocated = 0;
804 
806  std::vector <uint16_t> rbgAllocationMap;
807  if (m_nextRntiUl != 0)
808  {
809  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
810  {
811  if ((*it).first == m_nextRntiUl)
812  {
813  break;
814  }
815  }
816  if (it == m_ceBsrRxed.end ())
817  {
818  NS_LOG_ERROR (this << " no user found");
819  }
820  }
821  else
822  {
823  it = m_ceBsrRxed.begin ();
824  m_nextRntiUl = (*it).first;
825  }
826  do
827  {
828  if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth)
829  {
830  // limit to physical resources last resource assignment
831  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
832  }
833 
834  UlDciListElement_s uldci;
835  uldci.m_rnti = (*it).first;
836  uldci.m_rbStart = rbAllocated;
837  uldci.m_rbLen = rbPerFlow;
838  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
839  int cqi = 0;
840  if (itCqi == m_ueCqi.end ())
841  {
842  // no cqi info about this UE
843  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
844  }
845  else
846  {
847  // take the lowest CQI value (worst RB)
848  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
849  if (minSinr == NO_SINR)
850  {
851  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
852  }
853  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
854  {
855  double sinr = (*itCqi).second.at (i);
856  if (sinr == NO_SINR)
857  {
858  sinr = EstimateUlSinr ((*it).first, i);
859  }
860  if ((*itCqi).second.at (i) < minSinr)
861  {
862  minSinr = (*itCqi).second.at (i);
863  }
864  }
865 
866  // translate SINR -> cqi: WILD ACK: same as DL
867  double s = log2 ( 1 + (
868  std::pow (10, minSinr / 10 ) /
869  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
871  if (cqi == 0)
872  {
873  it++;
874  if (it == m_ceBsrRxed.end ())
875  {
876  // restart from the first
877  it = m_ceBsrRxed.begin ();
878  }
879  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
880  }
881  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
882 
883  }
884 
885  rbAllocated += rbPerFlow;
886  // store info on allocation for managing ul-cqi interpretation
887  for (int i = 0; i < rbPerFlow; i++)
888  {
889  rbgAllocationMap.push_back ((*it).first);
890  }
891  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
892  NS_LOG_DEBUG (this << " 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 << " RbAlloc " << rbAllocated);
893  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
894  uldci.m_ndi = 1;
895  uldci.m_cceIndex = 0;
896  uldci.m_aggrLevel = 1;
897  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
898  uldci.m_hopping = false;
899  uldci.m_n2Dmrs = 0;
900  uldci.m_tpc = 0; // no power control
901  uldci.m_cqiRequest = false; // only period CQI at this stage
902  uldci.m_ulIndex = 0; // TDD parameter
903  uldci.m_dai = 1; // TDD parameter
904  uldci.m_freqHopping = 0;
905  uldci.m_pdcchPowerOffset = 0; // not used
906  ret.m_dciList.push_back (uldci);
907 
908 
909  it++;
910  if (it == m_ceBsrRxed.end ())
911  {
912  // restart from the first
913  it = m_ceBsrRxed.begin ();
914  }
915  if (rbAllocated == m_cschedCellConfig.m_ulBandwidth)
916  {
917  // Stop allocation: no more PRBs
918  m_nextRntiUl = (*it).first;
919  break;
920  }
921  }
922  while ((*it).first != m_nextRntiUl);
923 
924 
925  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
927  return;
928 }
929 
930 void
932 {
933  NS_FATAL_ERROR ("unimplemented");
934  return;
935 }
936 
937 void
939 {
940  NS_FATAL_ERROR ("unimplemented");
941  return;
942 }
943 
944 void
946 {
947  NS_LOG_FUNCTION (this);
948 
949  std::map <uint16_t,uint32_t>::iterator it;
950 
951  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
952  {
953  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
954  {
955  // buffer status report
956  // note that we only consider LCG 0, the other three LCGs are neglected
957  // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
958  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
959  it = m_ceBsrRxed.find (rnti);
960  if (it == m_ceBsrRxed.end ())
961  {
962  // create the new entry
963  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
964  int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
965  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
966  }
967  else
968  {
969  // update the buffer size value
970  (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
971  }
972  }
973  }
974 
975  return;
976 }
977 
978 void
980 {
981  NS_LOG_FUNCTION (this);
982  // retrieve the allocation for this subframe
983  switch (m_ulCqiFilter)
984  {
986  {
987  // filter all the CQIs that are not SRS based
988  if (params.m_ulCqi.m_type!=UlCqi_s::SRS)
989  {
990  return;
991  }
992  }
993  break;
995  {
996  // filter all the CQIs that are not SRS based
997  if (params.m_ulCqi.m_type!=UlCqi_s::PUSCH)
998  {
999  return;
1000  }
1001  }
1003  break;
1004 
1005  default:
1006  NS_FATAL_ERROR ("Unknown UL CQI type");
1007  }
1008 
1009  switch (params.m_ulCqi.m_type)
1010  {
1011  case UlCqi_s::PUSCH:
1012  {
1013  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
1014  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1015  itMap = m_allocationMaps.find (params.m_sfnSf);
1016  if (itMap == m_allocationMaps.end ())
1017  {
1018  NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1019  return;
1020  }
1021  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1022  {
1023  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1024  // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
1025  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1026  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1027  if (itCqi == m_ueCqi.end ())
1028  {
1029  // create a new entry
1030  std::vector <double> newCqi;
1031  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1032  {
1033  if (i == j)
1034  {
1035  newCqi.push_back (sinr);
1036  }
1037  else
1038  {
1039  // initialize with NO_SINR value.
1040  newCqi.push_back (NO_SINR);
1041  }
1042 
1043  }
1044  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1045  // generate correspondent timer
1046  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1047  }
1048  else
1049  {
1050  // update the value
1051  (*itCqi).second.at (i) = sinr;
1052  // update correspondent timer
1053  std::map <uint16_t, uint32_t>::iterator itTimers;
1054  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1055  (*itTimers).second = m_cqiTimersThreshold;
1056 
1057  }
1058 
1059  }
1060  // remove obsolete info on allocation
1061  m_allocationMaps.erase (itMap);
1062  }
1063  break;
1064  case UlCqi_s::SRS:
1065  {
1066  // get the RNTI from vendor specific parameters
1067  uint16_t rnti = 0;
1068  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1069  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1070  {
1071  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1072  {
1073  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1074  rnti = vsp->GetRnti ();
1075  }
1076  }
1077  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1078  itCqi = m_ueCqi.find (rnti);
1079  if (itCqi == m_ueCqi.end ())
1080  {
1081  // create a new entry
1082  std::vector <double> newCqi;
1083  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1084  {
1085  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1086  newCqi.push_back (sinr);
1087  NS_LOG_DEBUG (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1088 
1089  }
1090  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1091  // generate correspondent timer
1092  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1093  }
1094  else
1095  {
1096  // update the values
1097  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1098  {
1099  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1100  (*itCqi).second.at (j) = sinr;
1101  NS_LOG_DEBUG (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1102  }
1103  // update correspondent timer
1104  std::map <uint16_t, uint32_t>::iterator itTimers;
1105  itTimers = m_ueCqiTimers.find (rnti);
1106  (*itTimers).second = m_cqiTimersThreshold;
1107 
1108  }
1109 
1110 
1111  }
1112  break;
1113  case UlCqi_s::PUCCH_1:
1114  case UlCqi_s::PUCCH_2:
1115  case UlCqi_s::PRACH:
1116  {
1117  NS_FATAL_ERROR ("TtaFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1118  }
1119  break;
1120  default:
1121  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1122  }
1123  return;
1124 }
1125 
1126 void
1128 {
1129  // refresh DL CQI P01 Map
1130  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1131  while (itP10!=m_p10CqiTimers.end ())
1132  {
1133 // NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1134  if ((*itP10).second == 0)
1135  {
1136  // delete correspondent entries
1137  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1138  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1139  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1140  m_p10CqiRxed.erase (itMap);
1141  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1142  itP10++;
1143  m_p10CqiTimers.erase (temp);
1144  }
1145  else
1146  {
1147  (*itP10).second--;
1148  itP10++;
1149  }
1150  }
1151 
1152  // refresh DL CQI A30 Map
1153  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
1154  while (itA30!=m_a30CqiTimers.end ())
1155  {
1156 // NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1157  if ((*itA30).second == 0)
1158  {
1159  // delete correspondent entries
1160  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
1161  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
1162  NS_LOG_INFO (this << " A30-CQI exired for user " << (*itA30).first);
1163  m_a30CqiRxed.erase (itMap);
1164  std::map <uint16_t,uint32_t>::iterator temp = itA30;
1165  itA30++;
1166  m_a30CqiTimers.erase (temp);
1167  }
1168  else
1169  {
1170  (*itA30).second--;
1171  itA30++;
1172  }
1173  }
1174 
1175  return;
1176 }
1177 
1178 
1179 void
1181 {
1182  // refresh UL CQI Map
1183  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1184  while (itUl!=m_ueCqiTimers.end ())
1185  {
1186 // NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1187  if ((*itUl).second == 0)
1188  {
1189  // delete correspondent entries
1190  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1191  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1192  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1193  (*itMap).second.clear ();
1194  m_ueCqi.erase (itMap);
1195  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1196  itUl++;
1197  m_ueCqiTimers.erase (temp);
1198  }
1199  else
1200  {
1201  (*itUl).second--;
1202  itUl++;
1203  }
1204  }
1205 
1206  return;
1207 }
1208 
1209 void
1210 TtaFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1211 {
1212  size = size - 2; // remove the minimum RLC overhead
1213  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1214  LteFlowId_t flow (rnti, lcid);
1215  it = m_rlcBufferReq.find (flow);
1216  if (it!=m_rlcBufferReq.end ())
1217  {
1218  // Update queues: RLC tx order Status, ReTx, Tx
1219  // Update status queue
1220  if ((*it).second.m_rlcStatusPduSize <= size)
1221  {
1222  size -= (*it).second.m_rlcStatusPduSize;
1223  (*it).second.m_rlcStatusPduSize = 0;
1224  }
1225  else
1226  {
1227  (*it).second.m_rlcStatusPduSize -= size;
1228  return;
1229  }
1230  // update retransmission queue
1231  if ((*it).second.m_rlcRetransmissionQueueSize <= size)
1232  {
1233  size -= (*it).second.m_rlcRetransmissionQueueSize;
1234  (*it).second.m_rlcRetransmissionQueueSize = 0;
1235  }
1236  else
1237  {
1238  (*it).second.m_rlcRetransmissionQueueSize -= size;
1239  return;
1240  }
1241  // update transmission queue
1242  if ((*it).second.m_rlcTransmissionQueueSize <= size)
1243  {
1244  size -= (*it).second.m_rlcTransmissionQueueSize;
1245  (*it).second.m_rlcTransmissionQueueSize = 0;
1246  }
1247  else
1248  {
1249  (*it).second.m_rlcTransmissionQueueSize -= size;
1250  return;
1251  }
1252  }
1253  else
1254  {
1255  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
1256  }
1257 }
1258 
1259 void
1260 TtaFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1261 {
1262 
1263  size = size - 2; // remove the minimum RLC overhead
1264  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1265  if (it!=m_ceBsrRxed.end ())
1266  {
1267  if ((*it).second >= size)
1268  {
1269  (*it).second -= size;
1270  }
1271  else
1272  {
1273  (*it).second = 0;
1274  }
1275  }
1276  else
1277  {
1278  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1279  }
1280 
1281 }
1282 
1283 void
1285 {
1286  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1288  params.m_rnti = rnti;
1289  params.m_transmissionMode = txMode;
1291 }
1292 
1293 
1294 }