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