A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
fdmt-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/fdmt-ff-mac-scheduler.h>
29 #include <ns3/lte-vendor-specific-parameters.h>
30 
31 NS_LOG_COMPONENT_DEFINE ("FdMtFfMacScheduler");
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 (FdMtFfMacScheduler);
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::FdMtFfMacScheduler")
245  .AddConstructor<FdMtFfMacScheduler> ()
246  .AddAttribute ("CqiTimerThreshold",
247  "The number of TTIs a CQI is valid (default 1000 - 1 sec.)",
248  UintegerValue (1000),
249  MakeUintegerAccessor (&FdMtFfMacScheduler::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 < FdMtType0AllocationRbg[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 rcqiMax = 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 itTxMode;
453  itTxMode = m_uesTxMode.find ((*it));
454  if (itTxMode == m_uesTxMode.end ())
455  {
456  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*it));
457  }
458  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
459  std::vector <uint8_t> sbCqi;
460  if (itCqi == m_a30CqiRxed.end ())
461  {
462  for (uint8_t k = 0; k < nLayer; k++)
463  {
464  sbCqi.push_back (1); // start with lowest value
465  }
466  }
467  else
468  {
469  sbCqi = (*itCqi).second.m_higherLayerSelected.at (i).m_sbCqi;
470  }
471  uint8_t cqi1 = sbCqi.at (0);
472  uint8_t cqi2 = 1;
473  if (sbCqi.size () > 1)
474  {
475  cqi2 = sbCqi.at (1);
476  }
477 
478  if ((cqi1 > 0)||(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
479  {
480  if (LcActivePerFlow ((*it)) > 0)
481  {
482  // this UE has data to transmit
483  double achievableRate = 0.0;
484  for (uint8_t k = 0; k < nLayer; k++)
485  {
486  uint8_t mcs = 0;
487  if (sbCqi.size () > k)
488  {
489  mcs = m_amc->GetMcsFromCqi (sbCqi.at (k));
490  }
491  else
492  {
493  // no info on this subband -> worst MCS
494  mcs = 0;
495  }
496  achievableRate += ((m_amc->GetTbSizeFromMcs (mcs, rbgSize) / 8) / 0.001); // = TB size / TTI
497  }
498 
499  double rcqi = achievableRate;
500 
501  if (rcqi > rcqiMax)
502  {
503  rcqiMax = rcqi;
504  itMax = it;
505  }
506  }
507  } // end if cqi
508  } // end for m_flowStatsDl
509 
510  if (itMax == m_flowStatsDl.end ())
511  {
512  // no UE available for this RB
513  NS_LOG_DEBUG (this << " no UE found");
514  }
515  else
516  {
517  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
518  itMap = allocationMap.find ((*itMax));
519  if (itMap == allocationMap.end ())
520  {
521  // insert new element
522  std::vector <uint16_t> tempMap;
523  tempMap.push_back (i);
524  allocationMap.insert (std::pair <uint16_t, std::vector <uint16_t> > ((*itMax), tempMap));
525  }
526  else
527  {
528  (*itMap).second.push_back (i);
529  }
530  }
531  } // end for RBGs
532 
533  // generate the transmission opportunities by grouping the RBGs of the same RNTI and
534  // creating the correspondent DCIs
536  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap = allocationMap.begin ();
537  while (itMap != allocationMap.end ())
538  {
539  // create new BuildDataListElement_s for this LC
541  newEl.m_rnti = (*itMap).first;
542  // create the DlDciListElement_s
543  DlDciListElement_s newDci;
544  std::vector <struct RlcPduListElement_s> newRlcPduLe;
545  newDci.m_rnti = (*itMap).first;
546 
547  uint16_t lcActives = LcActivePerFlow ((*itMap).first);
548  uint16_t rbgPerRnti = (*itMap).second.size ();
549  std::map <uint16_t,SbMeasResult_s>::iterator itCqi;
550  itCqi = m_a30CqiRxed.find ((*itMap).first);
551  std::map <uint16_t,uint8_t>::iterator itTxMode;
552  itTxMode = m_uesTxMode.find ((*itMap).first);
553  if (itTxMode == m_uesTxMode.end ())
554  {
555  NS_FATAL_ERROR ("No Transmission Mode info on user " << (*itMap).first);
556  }
557  int nLayer = TransmissionModesLayers::TxMode2LayerNum ((*itTxMode).second);
558  std::vector <uint8_t> worstCqi (2, 15);
559  if (itCqi != m_a30CqiRxed.end ())
560  {
561  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
562  {
563  if ((*itCqi).second.m_higherLayerSelected.size () > (*itMap).second.at (k))
564  {
565  for (uint8_t j = 0; j < nLayer; j++)
566  {
567  if ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.size () > j)
568  {
569  if (((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j)) < worstCqi.at (j))
570  {
571  worstCqi.at (j) = ((*itCqi).second.m_higherLayerSelected.at ((*itMap).second.at (k)).m_sbCqi.at (j));
572  }
573  }
574  else
575  {
576  // no CQI for this layer of this suband -> worst one
577  worstCqi.at (j) = 1;
578  }
579  }
580  }
581  else
582  {
583  for (uint8_t j = 0; j < nLayer; j++)
584  {
585  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
586  }
587  }
588  }
589  }
590  else
591  {
592  for (uint8_t j = 0; j < nLayer; j++)
593  {
594  worstCqi.at (j) = 1; // try with lowest MCS in RBG with no info on channel
595  }
596  }
597  uint32_t bytesTxed = 0;
598  for (uint8_t j = 0; j < nLayer; j++)
599  {
600  newDci.m_mcs.push_back (m_amc->GetMcsFromCqi (worstCqi.at (j)));
601  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)
602  newDci.m_tbsSize.push_back (tbSize);
603  bytesTxed += tbSize;
604  }
605 
606  newDci.m_resAlloc = 0; // only allocation type 0 at this stage
607  newDci.m_rbBitmap = 0; // TBD (32 bit bitmap see 7.1.6 of 36.213)
608  uint32_t rbgMask = 0;
609  for (uint16_t k = 0; k < (*itMap).second.size (); k++)
610  {
611  rbgMask = rbgMask + (0x1 << (*itMap).second.at (k));
612  }
613  newDci.m_rbBitmap = rbgMask; // (32 bit bitmap see 7.1.6 of 36.213)
614 
615  // create the rlc PDUs -> equally divide resources among actives LCs
616  std::map <LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator itBufReq;
617  for (itBufReq = m_rlcBufferReq.begin (); itBufReq != m_rlcBufferReq.end (); itBufReq++)
618  {
619  if (((*itBufReq).first.m_rnti == (*itMap).first) &&
620  (((*itBufReq).second.m_rlcTransmissionQueueSize > 0)
621  || ((*itBufReq).second.m_rlcRetransmissionQueueSize > 0)
622  || ((*itBufReq).second.m_rlcStatusPduSize > 0) ))
623  {
624  for (uint8_t j = 0; j < nLayer; j++)
625  {
626  RlcPduListElement_s newRlcEl;
627  newRlcEl.m_logicalChannelIdentity = (*itBufReq).first.m_lcId;
628  newRlcEl.m_size = newDci.m_tbsSize.at (j) / lcActives;
629  newRlcPduLe.push_back (newRlcEl);
630  UpdateDlRlcBufferInfo (newDci.m_rnti, newRlcEl.m_logicalChannelIdentity, newRlcEl.m_size);
631  }
632  }
633  if ((*itBufReq).first.m_rnti > (*itMap).first)
634  {
635  break;
636  }
637  }
638  newDci.m_ndi.push_back (1); // TBD (new data indicator)
639  newDci.m_rv.push_back (0); // TBD (redundancy version)
640 
641  newEl.m_dci = newDci;
642  // ...more parameters -> ingored in this version
643 
644  newEl.m_rlcPduList.push_back (newRlcPduLe);
645  ret.m_buildDataList.push_back (newEl);
646 
647 
648  itMap++;
649  } // end while allocation
650  ret.m_nrOfPdcchOfdmSymbols = 1; // TODO: check correct value according the DCIs txed
651 
653 
654  return;
655 }
656 
657 void
659 {
660  NS_FATAL_ERROR ("unimplemented");
661  return;
662 }
663 
664 void
666 {
667  NS_LOG_FUNCTION (this);
668 
669  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
670  {
671  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::P10 )
672  {
673  // wideband CQI reporting
674  std::map <uint16_t,uint8_t>::iterator it;
675  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
676  it = m_p10CqiRxed.find (rnti);
677  if (it == m_p10CqiRxed.end ())
678  {
679  // create the new entry
680  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)
681  // generate correspondent timer
682  m_p10CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
683  }
684  else
685  {
686  // update the CQI value and refresh correspondent timer
687  (*it).second = params.m_cqiList.at (i).m_wbCqi.at (0);
688  // update correspondent timer
689  std::map <uint16_t,uint32_t>::iterator itTimers;
690  itTimers = m_p10CqiTimers.find (rnti);
691  (*itTimers).second = m_cqiTimersThreshold;
692  }
693  }
694  else if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
695  {
696  // subband CQI reporting high layer configured
697  std::map <uint16_t,SbMeasResult_s>::iterator it;
698  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
699  it = m_a30CqiRxed.find (rnti);
700  if (it == m_a30CqiRxed.end ())
701  {
702  // create the new entry
703  m_a30CqiRxed.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
704  m_a30CqiTimers.insert ( std::pair<uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
705  }
706  else
707  {
708  // update the CQI value and refresh correspondent timer
709  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
710  std::map <uint16_t,uint32_t>::iterator itTimers;
711  itTimers = m_a30CqiTimers.find (rnti);
712  (*itTimers).second = m_cqiTimersThreshold;
713  }
714  }
715  else
716  {
717  NS_LOG_ERROR (this << " CQI type unknown");
718  }
719  }
720 
721  return;
722 }
723 
724 
725 double
726 FdMtFfMacScheduler::EstimateUlSinr (uint16_t rnti, uint16_t rb)
727 {
728  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find (rnti);
729  if (itCqi == m_ueCqi.end ())
730  {
731  // no cqi info about this UE
732  return (NO_SINR);
733 
734  }
735  else
736  {
737  // take the average SINR value among the available
738  double sinrSum = 0;
739  int sinrNum = 0;
740  for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
741  {
742  double sinr = (*itCqi).second.at (i);
743  if (sinr != NO_SINR)
744  {
745  sinrSum += sinr;
746  sinrNum++;
747  }
748  }
749  double estimatedSinr = sinrSum / (double)sinrNum;
750  // store the value
751  (*itCqi).second.at (rb) = estimatedSinr;
752  return (estimatedSinr);
753  }
754 }
755 
756 void
758 {
759  NS_LOG_FUNCTION (this << " UL - Frame no. " << (params.m_sfnSf >> 4) << " subframe no. " << (0xF & params.m_sfnSf));
760 
761  RefreshUlCqiMaps ();
762 
763  std::map <uint16_t,uint32_t>::iterator it;
764  int nflows = 0;
765 
766  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
767  {
768  // remove old entries of this UE-LC
769  if ((*it).second > 0)
770  {
771  nflows++;
772  }
773  }
774 
775  if (nflows == 0)
776  {
777  return ; // no flows to be scheduled
778  }
779 
780 
781  // Divide the resource equally among the active users
782  int rbPerFlow = m_cschedCellConfig.m_ulBandwidth / nflows;
783  if (rbPerFlow == 0)
784  {
785  rbPerFlow = 1; // at least 1 rbg per flow (till available resource)
786  }
787  int rbAllocated = 0;
788 
790  std::vector <uint16_t> rbgAllocationMap;
791  if (m_nextRntiUl != 0)
792  {
793  for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++)
794  {
795  if ((*it).first == m_nextRntiUl)
796  {
797  break;
798  }
799  }
800  if (it == m_ceBsrRxed.end ())
801  {
802  NS_LOG_ERROR (this << " no user found");
803  }
804  }
805  else
806  {
807  it = m_ceBsrRxed.begin ();
808  m_nextRntiUl = (*it).first;
809  }
810  do
811  {
812  if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth)
813  {
814  // limit to physical resources last resource assignment
815  rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated;
816  }
817 
818  UlDciListElement_s uldci;
819  uldci.m_rnti = (*it).first;
820  uldci.m_rbStart = rbAllocated;
821  uldci.m_rbLen = rbPerFlow;
822  std::map <uint16_t, std::vector <double> >::iterator itCqi = m_ueCqi.find ((*it).first);
823  int cqi = 0;
824  if (itCqi == m_ueCqi.end ())
825  {
826  // no cqi info about this UE
827  uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD
828  }
829  else
830  {
831  // take the lowest CQI value (worst RB)
832  double minSinr = (*itCqi).second.at (uldci.m_rbStart);
833  if (minSinr == NO_SINR)
834  {
835  minSinr = EstimateUlSinr ((*it).first, uldci.m_rbStart);
836  }
837  for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++)
838  {
839  double sinr = (*itCqi).second.at (i);
840  if (sinr == NO_SINR)
841  {
842  sinr = EstimateUlSinr ((*it).first, i);
843  }
844  if ((*itCqi).second.at (i) < minSinr)
845  {
846  minSinr = (*itCqi).second.at (i);
847  }
848  }
849 
850  // translate SINR -> cqi: WILD ACK: same as DL
851  double s = log2 ( 1 + (
852  std::pow (10, minSinr / 10 ) /
853  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
855  if (cqi == 0)
856  {
857  it++;
858  if (it == m_ceBsrRxed.end ())
859  {
860  // restart from the first
861  it = m_ceBsrRxed.begin ();
862  }
863  continue; // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
864  }
865  uldci.m_mcs = m_amc->GetMcsFromCqi (cqi);
866  }
867 
868  rbAllocated += rbPerFlow;
869  // store info on allocation for managing ul-cqi interpretation
870  for (int i = 0; i < rbPerFlow; i++)
871  {
872  rbgAllocationMap.push_back ((*it).first);
873  }
874  uldci.m_tbSize = (m_amc->GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8);
875  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);
876  UpdateUlRlcBufferInfo (uldci.m_rnti, uldci.m_tbSize);
877  uldci.m_ndi = 1;
878  uldci.m_cceIndex = 0;
879  uldci.m_aggrLevel = 1;
880  uldci.m_ueTxAntennaSelection = 3; // antenna selection OFF
881  uldci.m_hopping = false;
882  uldci.m_n2Dmrs = 0;
883  uldci.m_tpc = 0; // no power control
884  uldci.m_cqiRequest = false; // only period CQI at this stage
885  uldci.m_ulIndex = 0; // TDD parameter
886  uldci.m_dai = 1; // TDD parameter
887  uldci.m_freqHopping = 0;
888  uldci.m_pdcchPowerOffset = 0; // not used
889  ret.m_dciList.push_back (uldci);
890 
891 
892  it++;
893  if (it == m_ceBsrRxed.end ())
894  {
895  // restart from the first
896  it = m_ceBsrRxed.begin ();
897  }
898  if (rbAllocated == m_cschedCellConfig.m_ulBandwidth)
899  {
900  // Stop allocation: no more PRBs
901  m_nextRntiUl = (*it).first;
902  break;
903  }
904  }
905  while ((*it).first != m_nextRntiUl);
906 
907 
908  m_allocationMaps.insert (std::pair <uint16_t, std::vector <uint16_t> > (params.m_sfnSf, rbgAllocationMap));
910  return;
911 }
912 
913 void
915 {
916  NS_FATAL_ERROR ("unimplemented");
917  return;
918 }
919 
920 void
922 {
923  NS_FATAL_ERROR ("unimplemented");
924  return;
925 }
926 
927 void
929 {
930  NS_LOG_FUNCTION (this);
931 
932  std::map <uint16_t,uint32_t>::iterator it;
933 
934  for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
935  {
936  if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
937  {
938  // buffer status report
939  // note that we only consider LCG 0, the other three LCGs are neglected
940  // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
941  uint16_t rnti = params.m_macCeList.at (i).m_rnti;
942  it = m_ceBsrRxed.find (rnti);
943  if (it == m_ceBsrRxed.end ())
944  {
945  // create the new entry
946  uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
947  int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
948  m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
949  }
950  else
951  {
952  // update the buffer size value
953  (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
954  }
955  }
956  }
957 
958  return;
959 }
960 
961 void
963 {
964  NS_LOG_FUNCTION (this);
965  // retrieve the allocation for this subframe
966  switch (m_ulCqiFilter)
967  {
969  {
970  // filter all the CQIs that are not SRS based
971  if (params.m_ulCqi.m_type!=UlCqi_s::SRS)
972  {
973  return;
974  }
975  }
976  break;
978  {
979  // filter all the CQIs that are not SRS based
980  if (params.m_ulCqi.m_type!=UlCqi_s::PUSCH)
981  {
982  return;
983  }
984  }
986  break;
987 
988  default:
989  NS_FATAL_ERROR ("Unknown UL CQI type");
990  }
991 
992  switch (params.m_ulCqi.m_type)
993  {
994  case UlCqi_s::PUSCH:
995  {
996  std::map <uint16_t, std::vector <uint16_t> >::iterator itMap;
997  std::map <uint16_t, std::vector <double> >::iterator itCqi;
998  itMap = m_allocationMaps.find (params.m_sfnSf);
999  if (itMap == m_allocationMaps.end ())
1000  {
1001  NS_LOG_DEBUG (this << " Does not find info on allocation, size : " << m_allocationMaps.size ());
1002  return;
1003  }
1004  for (uint32_t i = 0; i < (*itMap).second.size (); i++)
1005  {
1006  // convert from fixed point notation Sxxxxxxxxxxx.xxx to double
1007  // NS_LOG_INFO (this << " i " << i << " size " << params.m_ulCqi.m_sinr.size () << " mapSIze " << (*itMap).second.size ());
1008  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i));
1009  itCqi = m_ueCqi.find ((*itMap).second.at (i));
1010  if (itCqi == m_ueCqi.end ())
1011  {
1012  // create a new entry
1013  std::vector <double> newCqi;
1014  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1015  {
1016  if (i == j)
1017  {
1018  newCqi.push_back (sinr);
1019  }
1020  else
1021  {
1022  // initialize with NO_SINR value.
1023  newCqi.push_back (NO_SINR);
1024  }
1025 
1026  }
1027  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > ((*itMap).second.at (i), newCqi));
1028  // generate correspondent timer
1029  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > ((*itMap).second.at (i), m_cqiTimersThreshold));
1030  }
1031  else
1032  {
1033  // update the value
1034  (*itCqi).second.at (i) = sinr;
1035  // update correspondent timer
1036  std::map <uint16_t, uint32_t>::iterator itTimers;
1037  itTimers = m_ueCqiTimers.find ((*itMap).second.at (i));
1038  (*itTimers).second = m_cqiTimersThreshold;
1039 
1040  }
1041 
1042  }
1043  // remove obsolete info on allocation
1044  m_allocationMaps.erase (itMap);
1045  }
1046  break;
1047  case UlCqi_s::SRS:
1048  {
1049  // get the RNTI from vendor specific parameters
1050  uint16_t rnti = 0;
1051  NS_ASSERT (params.m_vendorSpecificList.size () > 0);
1052  for (uint16_t i = 0; i < params.m_vendorSpecificList.size (); i++)
1053  {
1054  if (params.m_vendorSpecificList.at (i).m_type == SRS_CQI_RNTI_VSP)
1055  {
1056  Ptr<SrsCqiRntiVsp> vsp = DynamicCast<SrsCqiRntiVsp> (params.m_vendorSpecificList.at (i).m_value);
1057  rnti = vsp->GetRnti ();
1058  }
1059  }
1060  std::map <uint16_t, std::vector <double> >::iterator itCqi;
1061  itCqi = m_ueCqi.find (rnti);
1062  if (itCqi == m_ueCqi.end ())
1063  {
1064  // create a new entry
1065  std::vector <double> newCqi;
1066  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1067  {
1068  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1069  newCqi.push_back (sinr);
1070  NS_LOG_DEBUG (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr);
1071 
1072  }
1073  m_ueCqi.insert (std::pair <uint16_t, std::vector <double> > (rnti, newCqi));
1074  // generate correspondent timer
1075  m_ueCqiTimers.insert (std::pair <uint16_t, uint32_t > (rnti, m_cqiTimersThreshold));
1076  }
1077  else
1078  {
1079  // update the values
1080  for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++)
1081  {
1082  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
1083  (*itCqi).second.at (j) = sinr;
1084  NS_LOG_DEBUG (this << " RNTI " << rnti << " update SRS-CQI for RB " << j << " value " << sinr);
1085  }
1086  // update correspondent timer
1087  std::map <uint16_t, uint32_t>::iterator itTimers;
1088  itTimers = m_ueCqiTimers.find (rnti);
1089  (*itTimers).second = m_cqiTimersThreshold;
1090 
1091  }
1092 
1093 
1094  }
1095  break;
1096  case UlCqi_s::PUCCH_1:
1097  case UlCqi_s::PUCCH_2:
1098  case UlCqi_s::PRACH:
1099  {
1100  NS_FATAL_ERROR ("FdMtFfMacScheduler supports only PUSCH and SRS UL-CQIs");
1101  }
1102  break;
1103  default:
1104  NS_FATAL_ERROR ("Unknown type of UL-CQI");
1105  }
1106  return;
1107 }
1108 
1109 void
1111 {
1112  // refresh DL CQI P01 Map
1113  std::map <uint16_t,uint32_t>::iterator itP10 = m_p10CqiTimers.begin ();
1114  while (itP10!=m_p10CqiTimers.end ())
1115  {
1116 // NS_LOG_INFO (this << " P10-CQI for user " << (*itP10).first << " is " << (uint32_t)(*itP10).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1117  if ((*itP10).second == 0)
1118  {
1119  // delete correspondent entries
1120  std::map <uint16_t,uint8_t>::iterator itMap = m_p10CqiRxed.find ((*itP10).first);
1121  NS_ASSERT_MSG (itMap != m_p10CqiRxed.end (), " Does not find CQI report for user " << (*itP10).first);
1122  NS_LOG_INFO (this << " P10-CQI exired for user " << (*itP10).first);
1123  m_p10CqiRxed.erase (itMap);
1124  std::map <uint16_t,uint32_t>::iterator temp = itP10;
1125  itP10++;
1126  m_p10CqiTimers.erase (temp);
1127  }
1128  else
1129  {
1130  (*itP10).second--;
1131  itP10++;
1132  }
1133  }
1134 
1135  // refresh DL CQI A30 Map
1136  std::map <uint16_t,uint32_t>::iterator itA30 = m_a30CqiTimers.begin ();
1137  while (itA30!=m_a30CqiTimers.end ())
1138  {
1139 // NS_LOG_INFO (this << " A30-CQI for user " << (*itA30).first << " is " << (uint32_t)(*itA30).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1140  if ((*itA30).second == 0)
1141  {
1142  // delete correspondent entries
1143  std::map <uint16_t,SbMeasResult_s>::iterator itMap = m_a30CqiRxed.find ((*itA30).first);
1144  NS_ASSERT_MSG (itMap != m_a30CqiRxed.end (), " Does not find CQI report for user " << (*itA30).first);
1145  NS_LOG_INFO (this << " A30-CQI exired for user " << (*itA30).first);
1146  m_a30CqiRxed.erase (itMap);
1147  std::map <uint16_t,uint32_t>::iterator temp = itA30;
1148  itA30++;
1149  m_a30CqiTimers.erase (temp);
1150  }
1151  else
1152  {
1153  (*itA30).second--;
1154  itA30++;
1155  }
1156  }
1157 
1158  return;
1159 }
1160 
1161 
1162 void
1164 {
1165  // refresh UL CQI Map
1166  std::map <uint16_t,uint32_t>::iterator itUl = m_ueCqiTimers.begin ();
1167  while (itUl!=m_ueCqiTimers.end ())
1168  {
1169 // NS_LOG_INFO (this << " UL-CQI for user " << (*itUl).first << " is " << (uint32_t)(*itUl).second << " thr " << (uint32_t)m_cqiTimersThreshold);
1170  if ((*itUl).second == 0)
1171  {
1172  // delete correspondent entries
1173  std::map <uint16_t, std::vector <double> >::iterator itMap = m_ueCqi.find ((*itUl).first);
1174  NS_ASSERT_MSG (itMap != m_ueCqi.end (), " Does not find CQI report for user " << (*itUl).first);
1175  NS_LOG_INFO (this << " UL-CQI exired for user " << (*itUl).first);
1176  (*itMap).second.clear ();
1177  m_ueCqi.erase (itMap);
1178  std::map <uint16_t,uint32_t>::iterator temp = itUl;
1179  itUl++;
1180  m_ueCqiTimers.erase (temp);
1181  }
1182  else
1183  {
1184  (*itUl).second--;
1185  itUl++;
1186  }
1187  }
1188 
1189  return;
1190 }
1191 
1192 void
1193 FdMtFfMacScheduler::UpdateDlRlcBufferInfo (uint16_t rnti, uint8_t lcid, uint16_t size)
1194 {
1195  size = size - 2; // remove the minimum RLC overhead
1196  std::map<LteFlowId_t, FfMacSchedSapProvider::SchedDlRlcBufferReqParameters>::iterator it;
1197  LteFlowId_t flow (rnti, lcid);
1198  it = m_rlcBufferReq.find (flow);
1199  if (it!=m_rlcBufferReq.end ())
1200  {
1201  // Update queues: RLC tx order Status, ReTx, Tx
1202  // Update status queue
1203  if ((*it).second.m_rlcStatusPduSize <= size)
1204  {
1205  size -= (*it).second.m_rlcStatusPduSize;
1206  (*it).second.m_rlcStatusPduSize = 0;
1207  }
1208  else
1209  {
1210  (*it).second.m_rlcStatusPduSize -= size;
1211  return;
1212  }
1213  // update retransmission queue
1214  if ((*it).second.m_rlcRetransmissionQueueSize <= size)
1215  {
1216  size -= (*it).second.m_rlcRetransmissionQueueSize;
1217  (*it).second.m_rlcRetransmissionQueueSize = 0;
1218  }
1219  else
1220  {
1221  (*it).second.m_rlcRetransmissionQueueSize -= size;
1222  return;
1223  }
1224  // update transmission queue
1225  if ((*it).second.m_rlcTransmissionQueueSize <= size)
1226  {
1227  size -= (*it).second.m_rlcTransmissionQueueSize;
1228  (*it).second.m_rlcTransmissionQueueSize = 0;
1229  }
1230  else
1231  {
1232  (*it).second.m_rlcTransmissionQueueSize -= size;
1233  return;
1234  }
1235  }
1236  else
1237  {
1238  NS_LOG_ERROR (this << " Does not find DL RLC Buffer Report of UE " << rnti);
1239  }
1240 }
1241 
1242 void
1243 FdMtFfMacScheduler::UpdateUlRlcBufferInfo (uint16_t rnti, uint16_t size)
1244 {
1245 
1246  size = size - 2; // remove the minimum RLC overhead
1247  std::map <uint16_t,uint32_t>::iterator it = m_ceBsrRxed.find (rnti);
1248  if (it!=m_ceBsrRxed.end ())
1249  {
1250  if ((*it).second >= size)
1251  {
1252  (*it).second -= size;
1253  }
1254  else
1255  {
1256  (*it).second = 0;
1257  }
1258  }
1259  else
1260  {
1261  NS_LOG_ERROR (this << " Does not find BSR report info of UE " << rnti);
1262  }
1263 
1264 }
1265 
1266 void
1268 {
1269  NS_LOG_FUNCTION (this << " RNTI " << rnti << " txMode " << (uint16_t)txMode);
1271  params.m_rnti = rnti;
1272  params.m_transmissionMode = txMode;
1274 }
1275 
1276 
1277 }