A Discrete-Event Network Simulator
API
lte-ffr-enhanced-algorithm.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Piotr Gawlowicz
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: Piotr Gawlowicz <gawlowicz.p@gmail.com>
19  *
20  */
21 
23 #include "ns3/ff-mac-common.h"
24 #include "ns3/lte-common.h"
25 #include "ns3/lte-vendor-specific-parameters.h"
26 #include <ns3/log.h>
27 #include "ns3/boolean.h"
28 #include <ns3/double.h>
29 #include <cfloat>
30 
31 namespace ns3 {
32 
33 NS_LOG_COMPONENT_DEFINE ("LteFfrEnhancedAlgorithm");
34 
35 NS_OBJECT_ENSURE_REGISTERED (LteFfrEnhancedAlgorithm);
36 
38 static const double SpectralEfficiencyForCqi[16] = {
39  0.0, // out of range
40  0.15, 0.23, 0.38, 0.6, 0.88, 1.18,
41  1.48, 1.91, 2.41,
42  2.73, 3.32, 3.9, 4.52, 5.12, 5.55
43 };
44 
47 {
48  uint8_t cellId;
49  uint8_t dlBandwidth;
50  uint8_t dlSubBandOffset;
54  { 1, 25, 0, 4, 4},
55  { 2, 25, 8, 4, 4},
56  { 3, 25, 16, 4, 4},
57  { 1, 50, 0, 9, 6},
58  { 2, 50, 15, 9, 6},
59  { 3, 50, 30, 9, 6},
60  { 1, 75, 0, 8, 16},
61  { 2, 75, 24, 8, 16},
62  { 3, 75, 48, 8, 16},
63  { 1, 100, 0, 16, 16},
64  { 2, 100, 32, 16, 16},
65  { 3, 100, 64, 16, 16}
66 };
67 
70 {
71  uint8_t cellId;
72  uint8_t ulBandwidth;
73  uint8_t ulSubBandOffset;
77  { 1, 25, 0, 4, 4},
78  { 2, 25, 8, 4, 4},
79  { 3, 25, 16, 4, 4},
80  { 1, 50, 0, 9, 6},
81  { 2, 50, 15, 9, 6},
82  { 3, 50, 30, 9, 6},
83  { 1, 75, 0, 8, 16},
84  { 2, 75, 24, 8, 16},
85  { 3, 75, 48, 8, 16},
86  { 1, 100, 0, 16, 16},
87  { 2, 100, 32, 16, 16},
88  { 3, 100, 64, 16, 16}
89 };
90 
95 
96 
98  : m_ffrSapUser (0),
99  m_ffrRrcSapUser (0),
100  m_measId (0)
101 {
102  NS_LOG_FUNCTION (this);
105 }
106 
107 
109 {
110  NS_LOG_FUNCTION (this);
111 }
112 
113 
114 void
116 {
117  NS_LOG_FUNCTION (this);
118  delete m_ffrSapProvider;
119  delete m_ffrRrcSapProvider;
120 }
121 
122 
123 TypeId
125 {
126  static TypeId tid = TypeId ("ns3::LteFfrEnhancedAlgorithm")
128  .SetGroupName("Lte")
129  .AddConstructor<LteFfrEnhancedAlgorithm> ()
130  .AddAttribute ("UlSubBandOffset",
131  "Uplink SubBand Offset for this cell in number of Resource Block Groups",
132  UintegerValue (0),
134  MakeUintegerChecker<uint8_t> ())
135  .AddAttribute ("UlReuse3SubBandwidth",
136  "Uplink Reuse 3 SubBandwidth Configuration in number of Resource Block Groups",
137  UintegerValue (4),
139  MakeUintegerChecker<uint8_t> ())
140  .AddAttribute ("UlReuse1SubBandwidth",
141  "Uplink Reuse 1 SubBandwidth Configuration in number of Resource Block Groups",
142  UintegerValue (4),
144  MakeUintegerChecker<uint8_t> ())
145  .AddAttribute ("DlSubBandOffset",
146  "Downlink SubBand Offset for this cell in number of Resource Block Groups",
147  UintegerValue (0),
149  MakeUintegerChecker<uint8_t> ())
150  .AddAttribute ("DlReuse3SubBandwidth",
151  "Downlink Reuse 3 SubBandwidth Configuration in number of Resource Block Groups",
152  UintegerValue (4),
154  MakeUintegerChecker<uint8_t> ())
155  .AddAttribute ("DlReuse1SubBandwidth",
156  "Downlink Reuse 1 SubBandwidth Configuration in number of Resource Block Groups",
157  UintegerValue (4),
159  MakeUintegerChecker<uint8_t> ())
160  .AddAttribute ("RsrqThreshold",
161  "If the RSRQ of is worse than this threshold, UE should be served in Edge sub-band",
162  UintegerValue (26),
164  MakeUintegerChecker<uint8_t> ())
165  .AddAttribute ("CenterAreaPowerOffset",
166  "PdschConfigDedicated::Pa value for Center Sub-band, default value dB0",
167  UintegerValue (5),
169  MakeUintegerChecker<uint8_t> ())
170  .AddAttribute ("EdgeAreaPowerOffset",
171  "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
172  UintegerValue (5),
174  MakeUintegerChecker<uint8_t> ())
175  .AddAttribute ("DlCqiThreshold",
176  "If the DL-CQI for RBG of is higher than this threshold, transmission on RBG is possible",
177  UintegerValue (15),
179  MakeUintegerChecker<uint8_t> ())
180  .AddAttribute ("UlCqiThreshold",
181  "If the UL-CQI for RBG of is higher than this threshold, transmission on RBG is possible",
182  UintegerValue (15),
184  MakeUintegerChecker <uint8_t> ())
185  .AddAttribute ("CenterAreaTpc",
186  "TPC value which will be set in DL-DCI for UEs in center area"
187  "Absolute mode is used, default value 1 is mapped to -1 according to"
188  "TS36.213 Table 5.1.1.1-2",
189  UintegerValue (1),
191  MakeUintegerChecker<uint8_t> ())
192  .AddAttribute ("EdgeAreaTpc",
193  "TPC value which will be set in DL-DCI for UEs in edge area"
194  "Absolute mode is used, default value 1 is mapped to -1 according to"
195  "TS36.213 Table 5.1.1.1-2",
196  UintegerValue (1),
198  MakeUintegerChecker<uint8_t> ())
199  ;
200  return tid;
201 }
202 
203 
204 void
206 {
207  NS_LOG_FUNCTION (this << s);
208  m_ffrSapUser = s;
209 }
210 
211 
214 {
215  NS_LOG_FUNCTION (this);
216  return m_ffrSapProvider;
217 }
218 
219 void
221 {
222  NS_LOG_FUNCTION (this << s);
223  m_ffrRrcSapUser = s;
224 }
225 
226 
229 {
230  NS_LOG_FUNCTION (this);
231  return m_ffrRrcSapProvider;
232 }
233 
234 
235 void
237 {
238  NS_LOG_FUNCTION (this);
240 
241  NS_ASSERT_MSG (m_dlBandwidth > 24,"DlBandwidth must be at least 25 to use EFFR algorithm");
242  NS_ASSERT_MSG (m_ulBandwidth > 24,"UlBandwidth must be at least 25 to use EFFR algorithm");
243 
244  if (m_frCellTypeId != 0)
245  {
248  }
249 
250  NS_LOG_LOGIC (this << " requesting Event A1 measurements"
251  << " (threshold = 0" << ")");
252  LteRrcSap::ReportConfigEutra reportConfig;
255  reportConfig.threshold1.range = 0;
259 }
260 
261 void
263 {
264  NS_LOG_FUNCTION (this);
265  if (m_frCellTypeId != 0)
266  {
269  }
272  m_needReconfiguration = false;
273 }
274 
275 void
276 LteFfrEnhancedAlgorithm::SetDownlinkConfiguration (uint16_t cellId, uint8_t bandwidth)
277 {
278  NS_LOG_FUNCTION (this);
279  for (uint16_t i = 0; i < NUM_DOWNLINK_CONFS; ++i)
280  {
281  if ((g_ffrEnhancedDownlinkDefaultConfiguration[i].cellId == cellId)
283  {
287  }
288  }
289 }
290 
291 void
292 LteFfrEnhancedAlgorithm::SetUplinkConfiguration (uint16_t cellId, uint8_t bandwidth)
293 {
294  NS_LOG_FUNCTION (this);
295  for (uint16_t i = 0; i < NUM_UPLINK_CONFS; ++i)
296  {
297  if ((g_ffrEnhancedUplinkDefaultConfiguration[i].cellId == cellId)
299  {
303  }
304  }
305 }
306 
307 int
309 {
310  NS_LOG_FUNCTION (s);
311  NS_ASSERT_MSG (s >= 0.0, "negative spectral efficiency = " << s);
312  int cqi = 0;
313  while ((cqi < 15) && (SpectralEfficiencyForCqi[cqi + 1] < s))
314  {
315  ++cqi;
316  }
317  NS_LOG_LOGIC ("cqi = " << cqi);
318  return cqi;
319 }
320 
321 void
323 {
324  m_dlRbgMap.clear ();
325  m_dlReuse3RbgMap.clear ();
326  m_dlReuse1RbgMap.clear ();
327  m_dlPrimarySegmentRbgMap.clear ();
329 
330  int rbgSize = GetRbgSize (m_dlBandwidth);
331  m_dlRbgMap.resize (m_dlBandwidth / rbgSize, true);
332 
333  m_dlReuse3RbgMap.resize (m_dlBandwidth / rbgSize, false);
334  m_dlReuse1RbgMap.resize (m_dlBandwidth / rbgSize, false);
335  m_dlPrimarySegmentRbgMap.resize (m_dlBandwidth / rbgSize, false);
336  m_dlSecondarySegmentRbgMap.resize (m_dlBandwidth / rbgSize, true);
337 
338  NS_ASSERT_MSG (m_dlSubBandOffset <= m_dlBandwidth,"DlSubBandOffset higher than DlBandwidth");
340  "DlSubBandOffset + DlReuse3SubBandwidth + DlReuse1SubBandwidth higher than DlBandwidth");
341 
342  for (uint8_t i = 0; i < m_dlReuse3SubBandwidth / rbgSize; i++)
343  {
344  int offset = m_dlSubBandOffset / rbgSize;
345  uint8_t index = offset + i;
346  m_dlReuse3RbgMap[index] = true;
347  m_dlPrimarySegmentRbgMap[index] = true;
348  m_dlRbgMap[index] = false;
349  }
350 
351  for (uint8_t i = 0; i < m_dlReuse1SubBandwidth / rbgSize; i++)
352  {
353  int offset = (m_dlSubBandOffset + m_dlReuse3SubBandwidth) / rbgSize;
354  uint8_t index = offset + i;
355  m_dlReuse1RbgMap[index] = true;
356  m_dlPrimarySegmentRbgMap[index] = true;
357  m_dlSecondarySegmentRbgMap[index] = false;
358  m_dlRbgMap[index] = false;
359  }
360 
361  for (uint8_t i = 0; i < m_dlReuse3SubBandwidth / rbgSize; i++)
362  {
363  uint8_t offset = (m_dlReuse3SubBandwidth + m_dlReuse1SubBandwidth) / rbgSize;
364 
365  uint8_t index = 0 * offset + i;
366  m_dlSecondarySegmentRbgMap[index] = false;
367 
368  index = 1 * offset + i;
369  m_dlSecondarySegmentRbgMap[index] = false;
370 
371  index = 2 * offset + i;
372  m_dlSecondarySegmentRbgMap[index] = false;
373  }
374 }
375 
376 
377 void
379 {
380  m_ulRbgMap.clear ();
381  m_ulReuse3RbgMap.clear ();
382  m_ulReuse1RbgMap.clear ();
383  m_ulPrimarySegmentRbgMap.clear ();
385 
386  if (!m_enabledInUplink)
387  {
388  m_ulRbgMap.resize (m_ulBandwidth, false);
389  return;
390  }
391 
392  m_ulRbgMap.resize (m_ulBandwidth, true);
393  m_ulReuse3RbgMap.resize (m_ulBandwidth, false);
394  m_ulReuse1RbgMap.resize (m_ulBandwidth, false);
395  m_ulPrimarySegmentRbgMap.resize (m_ulBandwidth, false);
397 
398 
399  NS_ASSERT_MSG (m_ulSubBandOffset <= m_ulBandwidth, "UlSubBandOffset higher than UlBandwidth");
401  "UlSubBandOffset + UlReuse3SubBandwidth + UlReuse1SubBandwidth higher than UlBandwidth");
402 
403 
404  for (uint8_t i = 0; i < m_ulReuse3SubBandwidth; i++)
405  {
406  int offset = m_ulSubBandOffset;
407  uint8_t index = offset + i;
408  m_ulReuse3RbgMap[index] = true;
409  m_ulPrimarySegmentRbgMap[index] = true;
410  m_ulRbgMap[index] = false;
411  }
412 
413  for (uint8_t i = 0; i < m_ulReuse1SubBandwidth; i++)
414  {
415  int offset = (m_ulSubBandOffset + m_ulReuse3SubBandwidth);
416  uint8_t index = offset + i;
417  m_ulReuse1RbgMap[index] = true;
418  m_ulPrimarySegmentRbgMap[index] = true;
419  m_ulSecondarySegmentRbgMap[index] = false;
420  m_ulRbgMap[index] = false;
421  }
422 
423  for (uint8_t i = 0; i < m_ulReuse3SubBandwidth; i++)
424  {
426 
427  uint8_t index = 0 * offset + i;
428  m_ulSecondarySegmentRbgMap[index] = false;
429 
430  index = 1 * offset + i;
431  m_ulSecondarySegmentRbgMap[index] = false;
432 
433  index = 2 * offset + i;
434  m_ulSecondarySegmentRbgMap[index] = false;
435 
436  }
437 }
438 
439 std::vector <bool>
441 {
442  NS_LOG_FUNCTION (this);
443 
445  {
446  Reconfigure ();
447  }
448 
449  if (m_dlRbgMap.empty ())
450  {
452  }
453 
454  std::vector <bool> rbgMap = m_dlRbgMap;
455 
456  std::map <uint16_t, std::vector<bool> >::iterator it;
457  for (it = m_dlRbgAvailableforUe.begin (); it != m_dlRbgAvailableforUe.end (); it++)
458  {
459  NS_LOG_INFO ("RNTI : " << it->first);
460  std::vector<bool> rbgAvailableMap = it->second;
461  for (uint32_t i = 0; i < rbgMap.size (); i++)
462  {
463  NS_LOG_INFO ("\t rbgId: " << i << " available " << (int)rbgAvailableMap.at (i));
464  if ( rbgAvailableMap.at (i) == true)
465  {
466  rbgMap.at (i) = false;
467  }
468  }
469  }
470 
471  return rbgMap;
472 }
473 
474 bool
476 {
477  NS_LOG_FUNCTION (this);
478 
479  bool isReuse3Rbg = m_dlReuse3RbgMap[rbgId];
480  bool isReuse1Rbg = m_dlReuse1RbgMap[rbgId];
481  bool isPrimarySegmentRbg = m_dlPrimarySegmentRbgMap[rbgId];
482  bool isSecondarySegmentRbg = m_dlSecondarySegmentRbgMap[rbgId];
483 
484  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
485  if (it == m_ues.end ())
486  {
487  m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
488  }
489 
490  it = m_ues.find (rnti);
491 
492  //if UE area is unknown, serve UE in edge area RBGs
493  if (it->second == AreaUnset)
494  {
495  return isReuse3Rbg;
496  }
497 
498 
499  bool isCenterUe = false;
500  bool isEdgeUe = false;
501 
502  if (it->second == CenterArea )
503  {
504  isCenterUe = true;
505  }
506  else if (it->second == EdgeArea)
507  {
508  isEdgeUe = true;
509  }
510 
511  if (isPrimarySegmentRbg)
512  {
513  NS_LOG_INFO ("PRIMARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId );
514  return (isReuse1Rbg && isCenterUe) || (isReuse3Rbg && isEdgeUe);
515  }
516  else if (isSecondarySegmentRbg && isCenterUe)
517  {
518  //check if RB can be used by UE based on CQI information
519  NS_LOG_INFO ("SECONDARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId );
520  std::map <uint16_t, std::vector<bool> >::iterator it = m_dlRbgAvailableforUe.find (rnti);
521  if (it != m_dlRbgAvailableforUe.end ())
522  {
523  NS_LOG_INFO ("RNTI: " << rnti << " rbgId: " << rbgId << " available: " << it->second.at (rbgId));
524  if (it->second.at (rbgId) == true)
525  {
526  return true;
527  }
528  }
529  return false;
530  }
531 
532  return false;
533 }
534 
535 std::vector <bool>
537 {
538  NS_LOG_FUNCTION (this);
539 
540  if (m_ulRbgMap.empty ())
541  {
543  }
544 
545  if (!m_enabledInUplink)
546  {
547  return m_ulRbgMap;
548  }
549 
550  std::vector <bool> rbgMap = m_ulRbgMap;
551 
552  std::map <uint16_t, std::vector<bool> >::iterator it;
553  for (it = m_ulRbAvailableforUe.begin (); it != m_ulRbAvailableforUe.end (); it++)
554  {
555  NS_LOG_INFO ("RNTI : " << it->first);
556  std::vector<bool> rbAvailableMap = it->second;
557  for (uint32_t i = 0; i < rbgMap.size (); i++)
558  {
559  NS_LOG_INFO ("\t rbgId: " << i << " available " << (int)rbAvailableMap.at (i));
560  if ( rbAvailableMap.at (i) == true)
561  {
562  rbgMap.at (i) = false;
563  }
564  }
565  }
566 
567  return rbgMap;
568 }
569 
570 bool
572 {
573  NS_LOG_FUNCTION (this);
574 
575  if (!m_enabledInUplink)
576  {
577  return true;
578  }
579 
580  bool isReuse3Rbg = m_ulReuse3RbgMap[rbgId];
581  bool isReuse1Rbg = m_ulReuse1RbgMap[rbgId];
582  bool isPrimarySegmentRbg = m_ulPrimarySegmentRbgMap[rbgId];
583  bool isSecondarySegmentRbg = m_ulSecondarySegmentRbgMap[rbgId];
584 
585  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
586  if (it == m_ues.end ())
587  {
588  m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
589  }
590 
591  it = m_ues.find (rnti);
592 
593  //if UE area is unknown, serve UE in edge area RBGs
594  if (it->second == AreaUnset)
595  {
596  return isReuse3Rbg;
597  }
598 
599  bool isCenterUe = false;
600  bool isEdgeUe = false;
601 
602  if (it->second == CenterArea )
603  {
604  isCenterUe = true;
605  }
606  else if (it->second == EdgeArea)
607  {
608  isEdgeUe = true;
609  }
610 
611  if (isPrimarySegmentRbg)
612  {
613  return (isReuse1Rbg && isCenterUe) || (isReuse3Rbg && isEdgeUe);
614  }
615  else if (isSecondarySegmentRbg && isCenterUe)
616  {
617  //check if RB can be used by UE based on CQI information
618  NS_LOG_INFO ("UL SECONDARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId );
619  std::map <uint16_t, std::vector<bool> >::iterator it = m_ulRbAvailableforUe.find (rnti);
620  if (it != m_ulRbAvailableforUe.end ())
621  {
622  NS_LOG_INFO ("RNTI: " << rnti << " rbgId: " << rbgId << " available: " << it->second.at (rbgId));
623  if (it->second.at (rbgId) == true)
624  {
625  return true;
626  }
627  }
628  return false;
629  }
630 
631  return false;
632 }
633 
634 void
636 {
637  NS_LOG_FUNCTION (this);
638 
639  m_dlCqi.clear ();
640  for (unsigned int i = 0; i < params.m_cqiList.size (); i++)
641  {
642  if ( params.m_cqiList.at (i).m_cqiType == CqiListElement_s::A30 )
643  {
644  NS_LOG_INFO ("subband CQI reporting high layer configured");
645  // subband CQI reporting high layer configured
646  std::map <uint16_t,SbMeasResult_s>::iterator it;
647  uint16_t rnti = params.m_cqiList.at (i).m_rnti;
648 
649  std::map< uint16_t, uint8_t >::iterator ueIt = m_ues.find (rnti);
650  if (ueIt != m_ues.end ())
651  {
652  if (ueIt->second != CenterArea )
653  {
654  continue;
655  }
656  }
657  else
658  {
659  continue;
660  }
661 
662  it = m_dlCqi.find (rnti);
663  if (it == m_dlCqi.end ())
664  {
665  // create the new entry
666  m_dlCqi.insert ( std::pair<uint16_t, SbMeasResult_s > (rnti, params.m_cqiList.at (i).m_sbMeasResult) );
667  }
668  else
669  {
670  // update the CQI value and refresh correspondent timer
671  (*it).second = params.m_cqiList.at (i).m_sbMeasResult;
672  }
673  }
674  else
675  {
676  NS_LOG_ERROR (this << " CQI type unknown");
677  }
678  }
679 
680  uint32_t rbgSize = GetRbgSize (m_dlBandwidth);
681  m_dlRbgAvailableforUe.clear ();
682  std::map <uint16_t,SbMeasResult_s>::iterator it;
683  for (it = m_dlCqi.begin (); it != m_dlCqi.end (); it++)
684  {
685  uint16_t rnti = it->first;
686  std::vector<bool> rbgAvailableMap;
687 
688  for (uint32_t i = 0; i < (*it).second.m_higherLayerSelected.size (); i++)
689  {
690  uint8_t rbgCqi = (*it).second.m_higherLayerSelected.at (i).m_sbCqi.at (0);
691 
692  if (i > m_dlBandwidth / rbgSize)
693  {
694  continue;
695  }
696  NS_LOG_INFO (this << " RNTI " << rnti << " RBG " << i << " DL-CQI: " << (int)rbgCqi);
697 
698  bool rbgAvailable = (rbgCqi > m_dlCqiThreshold);
699 
700  bool isSecondarySegmentRbg = false;
701  if (i < m_dlSecondarySegmentRbgMap.size ())
702  {
703  isSecondarySegmentRbg = m_dlSecondarySegmentRbgMap[i];
704  }
705 
706  rbgAvailable = (isSecondarySegmentRbg == true) ? rbgAvailable : false;
707 
708  rbgAvailableMap.push_back (rbgAvailable);
709  }
710 
711  m_dlRbgAvailableforUe.insert ( std::pair<uint16_t, std::vector<bool> > (rnti, rbgAvailableMap ) );
712  }
713 
714  m_ulRbAvailableforUe.clear ();
715  for (std::map<uint16_t, std::vector<bool> >::iterator it = m_dlRbgAvailableforUe.begin ();
716  it != m_dlRbgAvailableforUe.end (); it++)
717  {
718  uint16_t rnti = it->first;
719  std::vector<bool> dlRbgAvailableMap = it->second;
720  std::vector<bool> ulRbAvailableMap;
721  ulRbAvailableMap.resize (m_ulBandwidth, false);
722 
723  for (uint32_t j = 0; j < dlRbgAvailableMap.size (); j++)
724  {
725  uint32_t index = rbgSize * j;
726  for (uint32_t i = 0; i < rbgSize; i++)
727  {
728  index = index + i;
729  ulRbAvailableMap[index] = dlRbgAvailableMap[j];
730  }
731  }
732 
733  m_ulRbAvailableforUe.insert ( std::pair<uint16_t, std::vector<bool> > (rnti, ulRbAvailableMap ) );
734  }
735 
736  return;
737 }
738 
739 void
741 {
742  NS_LOG_FUNCTION (this);
743  if (params.m_ulCqi.m_type == UlCqi_s::SRS)
744  {
745  // get the RNTI from vendor specific parameters
746  uint16_t rnti = 0;
747  for (uint32_t j = 0; j < m_ulBandwidth; j++)
748  {
749  double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (j));
750  double s = log2 ( 1 + (
751  std::pow (10, sinr / 10 ) /
752  ( (-std::log (5.0 * 0.00005 )) / 1.5) ));
753  int cqi = GetCqiFromSpectralEfficiency (s);
754  NS_LOG_INFO (this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value " << sinr << " UL-CQI: " << cqi);
755  }
756  }
757 }
758 
759 void
760 LteFfrEnhancedAlgorithm::DoReportUlCqiInfo ( std::map <uint16_t, std::vector <double> > ulCqiMap )
761 {
762  NS_LOG_FUNCTION (this);
763  NS_LOG_WARN ("Method should not be called, because it is empty");
764 }
765 
766 double
767 LteFfrEnhancedAlgorithm::EstimateUlSinr (uint16_t rnti, uint16_t rb, std::map <uint16_t, std::vector <double> > ulCqiMap)
768 {
769  std::map <uint16_t, std::vector <double> >::iterator itCqi = ulCqiMap.find (rnti);
770  if (itCqi == ulCqiMap.end ())
771  {
772  // no cqi info about this UE
773  return (NO_SINR);
774  }
775  else
776  {
777  // take the average SINR value among the available
778  double sinrSum = 0;
779  unsigned int sinrNum = 0;
780  for (uint32_t i = 0; i < m_ulBandwidth; i++)
781  {
782  double sinr = (*itCqi).second.at (i);
783  if (sinr != NO_SINR)
784  {
785  sinrSum += sinr;
786  sinrNum++;
787  }
788  }
789  double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
790  // store the value
791  (*itCqi).second.at (rb) = estimatedSinr;
792  return (estimatedSinr);
793  }
794 }
795 
796 uint8_t
798 {
799  NS_LOG_FUNCTION (this);
800 
801  if (!m_enabledInUplink)
802  {
803  return 1; // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213 Table 5.1.1.1-2
804  }
805 
806  //TS36.213 Table 5.1.1.1-2
807  // TPC | Accumulated Mode | Absolute Mode
808  //------------------------------------------------
809  // 0 | -1 | -4
810  // 1 | 0 | -1
811  // 2 | 1 | 1
812  // 3 | 3 | 4
813  //------------------------------------------------
814  // here Absolute mode is used
815 
816  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
817  if (it == m_ues.end ())
818  {
819  return 1;
820  }
821 
822  if (it->second == EdgeArea )
823  {
824  return m_edgeAreaTpc;
825  }
826  else
827  {
828  return m_centerAreaTpc;
829  }
830 
831  return 1;
832 }
833 
834 uint16_t
836 {
837  NS_LOG_FUNCTION (this);
838 
839  uint8_t minContinuousUlBandwidth = m_ulBandwidth;
840 
841  if (!m_enabledInUplink)
842  {
843  return minContinuousUlBandwidth;
844  }
845 
846  minContinuousUlBandwidth =
847  ((m_ulReuse3SubBandwidth > 0 ) && (m_ulReuse3SubBandwidth < minContinuousUlBandwidth)) ? m_ulReuse3SubBandwidth : minContinuousUlBandwidth;
848 
849  minContinuousUlBandwidth =
850  ((m_ulReuse1SubBandwidth > 0 ) && (m_ulReuse1SubBandwidth < minContinuousUlBandwidth)) ? m_ulReuse1SubBandwidth : minContinuousUlBandwidth;
851 
852  NS_LOG_INFO ("minContinuousUlBandwidth: " << (int)minContinuousUlBandwidth);
853 
854  return minContinuousUlBandwidth;
855 }
856 
857 
858 void
860  LteRrcSap::MeasResults measResults)
861 {
862  NS_LOG_FUNCTION (this << rnti << (uint16_t) measResults.measId);
863  NS_LOG_INFO ("RNTI :" << rnti << " MeasId: " << (uint16_t) measResults.measId
864  << " RSRP: " << (uint16_t)measResults.measResultPCell.rsrpResult
865  << " RSRQ: " << (uint16_t)measResults.measResultPCell.rsrqResult);
866 
867  if (measResults.measId != m_measId)
868  {
869  NS_LOG_WARN ("Ignoring measId " << (uint16_t) measResults.measId);
870  }
871  else
872  {
873  std::map< uint16_t, uint8_t >::iterator it = m_ues.find (rnti);
874  if (it == m_ues.end ())
875  {
876  m_ues.insert (std::pair< uint16_t, uint8_t > (rnti, AreaUnset));
877  }
878 
879  it = m_ues.find (rnti);
880  if (measResults.measResultPCell.rsrqResult < m_rsrqThreshold)
881  {
882  if (it->second != EdgeArea)
883  {
884  NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Edge sub-band");
885  it->second = EdgeArea;
886 
887  LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
888  pdschConfigDedicated.pa = m_edgeAreaPowerOffset;
889  m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
890  }
891  }
892  else
893  {
894  if (it->second != CenterArea)
895  {
896  NS_LOG_INFO ("UE RNTI: " << rnti << " will be served in Center sub-band");
897  it->second = CenterArea;
898 
899  LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
900  pdschConfigDedicated.pa = m_centerAreaPowerOffset;
901  m_ffrRrcSapUser->SetPdschConfigDedicated (rnti, pdschConfigDedicated);
902  }
903  }
904  }
905 }
906 void
908 {
909  NS_LOG_FUNCTION (this);
910  NS_LOG_WARN ("Method should not be called, because it is empty");
911 }
912 
913 } // end of namespace ns3
static double fpS11dot3toDouble(uint16_t val)
Convert from fixed point S11.3 notation to double.
Definition: lte-common.cc:155
The abstract base class of a Frequency Reuse algorithm.
bool m_needReconfiguration
If true FR algorithm will be reconfigured.
uint8_t m_frCellTypeId
FFR cell type ID for automatic configuration.
int GetRbgSize(int dlbandwidth)
Get RBG size for DL Bandwidth according to table 7.1.6.1-1 of 36.213.
bool m_enabledInUplink
If true FR algorithm will also work in Uplink.
uint8_t m_dlBandwidth
downlink bandwidth in RBs
uint8_t m_ulBandwidth
uplink bandwidth in RBs
Enhanced Fractional Frequency Reuse algorithm implementation.
std::map< uint16_t, SbMeasResult_s > m_dlCqi
Map of UE's DL CQI A30 received.
uint8_t m_ulSubBandOffset
UL subband offset.
virtual void DoDispose()
Destructor implementation.
virtual void SetLteFfrRrcSapUser(LteFfrRrcSapUser *s)
Set the "user" part of the LteFfrRrcSap interface that this frequency reuse algorithm instance will i...
uint8_t m_measId
The expected measurement identity.
LteFfrSapProvider * m_ffrSapProvider
FFR SAP provider.
void SetDownlinkConfiguration(uint16_t cellId, uint8_t bandwidth)
Set downlink configuration.
void InitializeDownlinkRbgMaps()
Initialize downlink RBG maps.
friend class MemberLteFfrSapProvider< LteFfrEnhancedAlgorithm >
let the forwarder class access the protected and private members
std::vector< bool > m_dlRbgMap
DL RBG map.
double EstimateUlSinr(uint16_t rnti, uint16_t rb, std::map< uint16_t, std::vector< double > > ulCqiMap)
Initialize uplink RBG maps.
static TypeId GetTypeId()
Get the type ID.
uint8_t m_dlSubBandOffset
DL subband offset.
uint8_t m_ulCqiThreshold
UL CQI threshold.
virtual uint8_t DoGetTpc(uint16_t rnti)
DoGetTpc for UE.
std::map< uint16_t, std::vector< bool > > m_dlRbgAvailableforUe
DL RBG available for UE.
std::vector< bool > m_dlSecondarySegmentRbgMap
DL secondary segment RBG map.
uint8_t m_centerAreaPowerOffset
Center area power offset.
virtual std::vector< bool > DoGetAvailableUlRbg()
Implementation of LteFfrSapProvider::GetAvailableUlRbg.
uint8_t m_dlCqiThreshold
DL CQI threshold.
std::vector< bool > m_ulReuse1RbgMap
UL reuse 1 RBG map.
virtual LteFfrSapProvider * GetLteFfrSapProvider()
Export the "provider" part of the LteFfrSap interface.
virtual LteFfrRrcSapProvider * GetLteFfrRrcSapProvider()
Export the "provider" part of the LteFfrRrcSap interface.
std::vector< bool > m_dlPrimarySegmentRbgMap
DL primary segment RBG map.
virtual uint16_t DoGetMinContinuousUlBandwidth()
DoGetMinContinuousUlBandwidth in number of RB.
virtual void SetLteFfrSapUser(LteFfrSapUser *s)
Set the "user" part of the LteFfrSap interface that this frequency reuse algorithm instance will inte...
virtual void DoRecvLoadInformation(EpcX2Sap::LoadInformationParams params)
DoRecvLoadInformation.
std::vector< bool > m_ulPrimarySegmentRbgMap
UL primary segment RBG map.
uint8_t m_dlReuse1SubBandwidth
DL reuse 1 subband bandwidth.
LteFfrRrcSapUser * m_ffrRrcSapUser
FFR RRC SAP user.
std::vector< bool > m_dlReuse3RbgMap
DL reuse 3 RBG map.
friend class MemberLteFfrRrcSapProvider< LteFfrEnhancedAlgorithm >
let the forwarder class access the protected and private members
virtual void Reconfigure()
Automatic FR reconfiguration.
virtual void DoReportUeMeas(uint16_t rnti, LteRrcSap::MeasResults measResults)
Implementation of LteFfrRrcSapProvider::ReportUeMeas.
int GetCqiFromSpectralEfficiency(double s)
Get CQI from spectral efficiency.
std::vector< bool > m_ulReuse3RbgMap
UL reuse 3 RBG map.
virtual void DoReportUlCqiInfo(const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params)
DoReportUlCqiInfo.
void SetUplinkConfiguration(uint16_t cellId, uint8_t bandwidth)
Set uplink configuration.
uint8_t m_ulReuse1SubBandwidth
UL reuse 1 subbandwidth.
LteFfrSapUser * m_ffrSapUser
FFR SAP user.
LteFfrEnhancedAlgorithm()
Creates a trivial ffr algorithm instance.
std::map< uint16_t, std::vector< bool > > m_ulRbAvailableforUe
UL RB available for UE.
virtual bool DoIsUlRbgAvailableForUe(int i, uint16_t rnti)
Implementation of LteFfrSapProvider::IsUlRbgAvailableForUe.
std::vector< bool > m_ulRbgMap
UL RBG Map.
virtual std::vector< bool > DoGetAvailableDlRbg()
Implementation of LteFfrSapProvider::GetAvailableDlRbg.
virtual void DoReportDlCqiInfo(const struct FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params)
DoReportDlCqiInfo.
LteFfrRrcSapProvider * m_ffrRrcSapProvider
FFR RRC SAP provider.
std::map< uint16_t, uint8_t > m_ues
UEs.
std::vector< bool > m_dlReuse1RbgMap
DL reuse 1 RBG map.
void InitializeUplinkRbgMaps()
Initialize uplink RBG maps.
virtual void DoInitialize()
Initialize() implementation.
uint8_t m_ulReuse3SubBandwidth
UL reuse 3 subbandwidth.
std::vector< bool > m_ulSecondarySegmentRbgMap
UL secondary segment RBG map.
uint8_t m_edgeAreaPowerOffset
Edge area power offset.
uint8_t m_dlReuse3SubBandwidth
DL reuse 3 subband bandwidth.
virtual bool DoIsDlRbgAvailableForUe(int i, uint16_t rnti)
Implementation of LteFfrSapProvider::IsDlRbgAvailableForUe.
Service Access Point (SAP) offered by the Frequency Reuse algorithm instance to the eNodeB RRC instan...
Service Access Point (SAP) offered by the eNodeB RRC instance to the Frequency Reuse algorithm instan...
virtual void SetPdschConfigDedicated(uint16_t rnti, LteRrcSap::PdschConfigDedicated pdschConfigDedicated)=0
Instruct the eNodeB RRC entity to perform RrcConnectionReconfiguration to inform UE about new PdschCo...
virtual uint8_t AddUeMeasReportConfigForFfr(LteRrcSap::ReportConfigEutra reportConfig)=0
Request a certain reporting configuration to be fulfilled by the UEs attached to the eNodeB entity.
Service Access Point (SAP) offered by the Frequency Reuse algorithm instance to the MAC Scheduler ins...
Definition: lte-ffr-sap.h:40
Service Access Point (SAP) offered by the eNodeB RRC instance to the Frequency Reuse algorithm instan...
Definition: lte-ffr-sap.h:139
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:353
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NO_SINR
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const struct ns3::FfrEnhancedDownlinkDefaultConfiguration g_ffrEnhancedDownlinkDefaultConfiguration[]
the enhanced downlink default configation
const uint16_t NUM_DOWNLINK_CONFS(sizeof(g_ffrEnhancedDownlinkDefaultConfiguration)/sizeof(FfrEnhancedDownlinkDefaultConfiguration))
const uint16_t NUM_UPLINK_CONFS(sizeof(g_ffrEnhancedUplinkDefaultConfiguration)/sizeof(FfrEnhancedUplinkDefaultConfiguration))
static const struct ns3::FfrEnhancedUplinkDefaultConfiguration g_ffrEnhancedUplinkDefaultConfiguration[]
the enhanced uplink default configuration
static const double SpectralEfficiencyForCqi[16]
Table of CQI index and its spectral efficiency.
Definition: lte-amc.cc:48
Parameters of the LOAD INFORMATION message.
Definition: epc-x2-sap.h:304
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct CqiListElement_s > m_cqiList
CQI list.
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
uint8_t rsrqResult
the RSRQ result
Definition: lte-rrc-sap.h:639
uint8_t rsrpResult
the RSRP result
Definition: lte-rrc-sap.h:638
MeasResults structure.
Definition: lte-rrc-sap.h:680
uint8_t measId
measure ID
Definition: lte-rrc-sap.h:681
MeasResultPCell measResultPCell
measurement result primary cell
Definition: lte-rrc-sap.h:682
PdschConfigDedicated structure.
Definition: lte-rrc-sap.h:155
Specifies criteria for triggering of an E-UTRA measurement reporting event.
Definition: lte-rrc-sap.h:362
@ EVENT_A1
Event A1: Serving becomes better than absolute threshold.
Definition: lte-rrc-sap.h:373
@ RSRQ
Reference Signal Received Quality.
Definition: lte-rrc-sap.h:407
ThresholdEutra threshold1
Threshold for event A1, A2, A4, and A5.
Definition: lte-rrc-sap.h:381
enum ns3::LteRrcSap::ReportConfigEutra::@67 triggerQuantity
Trigger type enumeration.
enum ns3::LteRrcSap::ReportConfigEutra::@66 eventId
Event enumeration.
enum ns3::LteRrcSap::ReportConfigEutra::@69 reportInterval
Report interval enumeration.
@ THRESHOLD_RSRQ
RSRQ is used for the threshold.
Definition: lte-rrc-sap.h:355
uint8_t range
Value range used in RSRP/RSRQ threshold.
Definition: lte-rrc-sap.h:357
enum ns3::LteRrcSap::ThresholdEutra::@64 choice
Threshold enumeration.
std::vector< uint16_t > m_sinr
SINR.