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