A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 "ff-mac-common.h"
24 #include "lte-common.h"
25 
26 #include "ns3/boolean.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  for (auto it = m_dlRbgAvailableforUe.begin(); it != m_dlRbgAvailableforUe.end(); it++)
482  {
483  NS_LOG_INFO("RNTI : " << it->first);
484  std::vector<bool> rbgAvailableMap = it->second;
485  for (uint32_t i = 0; i < rbgMap.size(); i++)
486  {
487  NS_LOG_INFO("\t rbgId: " << i << " available " << (int)rbgAvailableMap.at(i));
488  if (rbgAvailableMap.at(i))
489  {
490  rbgMap.at(i) = false;
491  }
492  }
493  }
494 
495  return rbgMap;
496 }
497 
498 bool
500 {
501  NS_LOG_FUNCTION(this);
502 
503  bool isReuse3Rbg = m_dlReuse3RbgMap[rbgId];
504  bool isReuse1Rbg = m_dlReuse1RbgMap[rbgId];
505  bool isPrimarySegmentRbg = m_dlPrimarySegmentRbgMap[rbgId];
506  bool isSecondarySegmentRbg = m_dlSecondarySegmentRbgMap[rbgId];
507 
508  auto it = m_ues.find(rnti);
509  if (it == m_ues.end())
510  {
511  m_ues.insert(std::pair<uint16_t, uint8_t>(rnti, AreaUnset));
512  }
513 
514  it = m_ues.find(rnti);
515 
516  // if UE area is unknown, serve UE in edge area RBGs
517  if (it->second == AreaUnset)
518  {
519  return isReuse3Rbg;
520  }
521 
522  bool isCenterUe = false;
523  bool isEdgeUe = false;
524 
525  if (it->second == CenterArea)
526  {
527  isCenterUe = true;
528  }
529  else if (it->second == EdgeArea)
530  {
531  isEdgeUe = true;
532  }
533 
534  if (isPrimarySegmentRbg)
535  {
536  NS_LOG_INFO("PRIMARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId);
537  return (isReuse1Rbg && isCenterUe) || (isReuse3Rbg && isEdgeUe);
538  }
539  else if (isSecondarySegmentRbg && isCenterUe)
540  {
541  // check if RB can be used by UE based on CQI information
542  NS_LOG_INFO("SECONDARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId);
543  auto it = m_dlRbgAvailableforUe.find(rnti);
544  if (it != m_dlRbgAvailableforUe.end())
545  {
546  NS_LOG_INFO("RNTI: " << rnti << " rbgId: " << rbgId
547  << " available: " << it->second.at(rbgId));
548  if (it->second.at(rbgId))
549  {
550  return true;
551  }
552  }
553  return false;
554  }
555 
556  return false;
557 }
558 
559 std::vector<bool>
561 {
562  NS_LOG_FUNCTION(this);
563 
564  if (m_ulRbgMap.empty())
565  {
567  }
568 
569  if (!m_enabledInUplink)
570  {
571  return m_ulRbgMap;
572  }
573 
574  std::vector<bool> rbgMap = m_ulRbgMap;
575 
576  for (auto it = m_ulRbAvailableforUe.begin(); it != m_ulRbAvailableforUe.end(); it++)
577  {
578  NS_LOG_INFO("RNTI : " << it->first);
579  std::vector<bool> rbAvailableMap = it->second;
580  for (uint32_t i = 0; i < rbgMap.size(); i++)
581  {
582  NS_LOG_INFO("\t rbgId: " << i << " available " << (int)rbAvailableMap.at(i));
583  if (rbAvailableMap.at(i))
584  {
585  rbgMap.at(i) = false;
586  }
587  }
588  }
589 
590  return rbgMap;
591 }
592 
593 bool
595 {
596  NS_LOG_FUNCTION(this);
597 
598  if (!m_enabledInUplink)
599  {
600  return true;
601  }
602 
603  bool isReuse3Rbg = m_ulReuse3RbgMap[rbgId];
604  bool isReuse1Rbg = m_ulReuse1RbgMap[rbgId];
605  bool isPrimarySegmentRbg = m_ulPrimarySegmentRbgMap[rbgId];
606  bool isSecondarySegmentRbg = m_ulSecondarySegmentRbgMap[rbgId];
607 
608  auto it = m_ues.find(rnti);
609  if (it == m_ues.end())
610  {
611  m_ues.insert(std::pair<uint16_t, uint8_t>(rnti, AreaUnset));
612  }
613 
614  it = m_ues.find(rnti);
615 
616  // if UE area is unknown, serve UE in edge area RBGs
617  if (it->second == AreaUnset)
618  {
619  return isReuse3Rbg;
620  }
621 
622  bool isCenterUe = false;
623  bool isEdgeUe = false;
624 
625  if (it->second == CenterArea)
626  {
627  isCenterUe = true;
628  }
629  else if (it->second == EdgeArea)
630  {
631  isEdgeUe = true;
632  }
633 
634  if (isPrimarySegmentRbg)
635  {
636  return (isReuse1Rbg && isCenterUe) || (isReuse3Rbg && isEdgeUe);
637  }
638  else if (isSecondarySegmentRbg && isCenterUe)
639  {
640  // check if RB can be used by UE based on CQI information
641  NS_LOG_INFO("UL SECONDARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId);
642  auto it = m_ulRbAvailableforUe.find(rnti);
643  if (it != m_ulRbAvailableforUe.end())
644  {
645  NS_LOG_INFO("RNTI: " << rnti << " rbgId: " << rbgId
646  << " available: " << it->second.at(rbgId));
647  if (it->second.at(rbgId))
648  {
649  return true;
650  }
651  }
652  return false;
653  }
654 
655  return false;
656 }
657 
658 void
661 {
662  NS_LOG_FUNCTION(this);
663 
664  m_dlCqi.clear();
665  for (unsigned int i = 0; i < params.m_cqiList.size(); i++)
666  {
667  if (params.m_cqiList.at(i).m_cqiType == CqiListElement_s::A30)
668  {
669  NS_LOG_INFO("subband CQI reporting high layer configured");
670  // subband CQI reporting high layer configured
671  uint16_t rnti = params.m_cqiList.at(i).m_rnti;
672 
673  auto ueIt = m_ues.find(rnti);
674  if (ueIt != m_ues.end())
675  {
676  if (ueIt->second != CenterArea)
677  {
678  continue;
679  }
680  }
681  else
682  {
683  continue;
684  }
685 
686  auto it = m_dlCqi.find(rnti);
687  if (it == m_dlCqi.end())
688  {
689  // create the new entry
690  m_dlCqi.insert(
691  std::pair<uint16_t, SbMeasResult_s>(rnti,
692  params.m_cqiList.at(i).m_sbMeasResult));
693  }
694  else
695  {
696  // update the CQI value and refresh correspondent timer
697  (*it).second = params.m_cqiList.at(i).m_sbMeasResult;
698  }
699  }
700  else
701  {
702  NS_LOG_ERROR(this << " CQI type unknown");
703  }
704  }
705 
706  uint32_t rbgSize = GetRbgSize(m_dlBandwidth);
707  m_dlRbgAvailableforUe.clear();
708  for (auto it = m_dlCqi.begin(); it != m_dlCqi.end(); it++)
709  {
710  uint16_t rnti = it->first;
711  std::vector<bool> rbgAvailableMap;
712 
713  for (uint32_t i = 0; i < (*it).second.m_higherLayerSelected.size(); i++)
714  {
715  uint8_t rbgCqi = (*it).second.m_higherLayerSelected.at(i).m_sbCqi.at(0);
716 
717  if (i > m_dlBandwidth / rbgSize)
718  {
719  continue;
720  }
721  NS_LOG_INFO(this << " RNTI " << rnti << " RBG " << i << " DL-CQI: " << (int)rbgCqi);
722 
723  bool rbgAvailable = (rbgCqi > m_dlCqiThreshold);
724 
725  bool isSecondarySegmentRbg = false;
726  if (i < m_dlSecondarySegmentRbgMap.size())
727  {
728  isSecondarySegmentRbg = m_dlSecondarySegmentRbgMap[i];
729  }
730 
731  rbgAvailable = (isSecondarySegmentRbg ? rbgAvailable : false);
732 
733  rbgAvailableMap.push_back(rbgAvailable);
734  }
735 
736  m_dlRbgAvailableforUe.insert(std::pair<uint16_t, std::vector<bool>>(rnti, rbgAvailableMap));
737  }
738 
739  m_ulRbAvailableforUe.clear();
740  for (auto it = m_dlRbgAvailableforUe.begin(); it != m_dlRbgAvailableforUe.end(); it++)
741  {
742  uint16_t rnti = it->first;
743  std::vector<bool> dlRbgAvailableMap = it->second;
744  std::vector<bool> ulRbAvailableMap;
745  ulRbAvailableMap.resize(m_ulBandwidth, false);
746 
747  for (uint32_t j = 0; j < dlRbgAvailableMap.size(); j++)
748  {
749  uint32_t index = rbgSize * j;
750  for (uint32_t i = 0; i < rbgSize; i++)
751  {
752  index = index + i;
753  ulRbAvailableMap[index] = dlRbgAvailableMap[j];
754  }
755  }
756 
757  m_ulRbAvailableforUe.insert(std::pair<uint16_t, std::vector<bool>>(rnti, ulRbAvailableMap));
758  }
759 }
760 
761 void
764 {
765  NS_LOG_FUNCTION(this);
766  if (params.m_ulCqi.m_type == UlCqi_s::SRS)
767  {
768  // get the RNTI from vendor specific parameters
769  uint16_t rnti = 0;
770  for (uint32_t j = 0; j < m_ulBandwidth; j++)
771  {
772  double sinr = LteFfConverter::fpS11dot3toDouble(params.m_ulCqi.m_sinr.at(j));
773  double s = log2(1 + (std::pow(10, sinr / 10) / ((-std::log(5.0 * 0.00005)) / 1.5)));
774  int cqi = GetCqiFromSpectralEfficiency(s);
775  NS_LOG_INFO(this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value "
776  << sinr << " UL-CQI: " << cqi);
777  }
778  }
779 }
780 
781 void
782 LteFfrEnhancedAlgorithm::DoReportUlCqiInfo(std::map<uint16_t, std::vector<double>> ulCqiMap)
783 {
784  NS_LOG_FUNCTION(this);
785  NS_LOG_WARN("Method should not be called, because it is empty");
786 }
787 
788 double
790  uint16_t rb,
791  std::map<uint16_t, std::vector<double>> ulCqiMap)
792 {
793  auto itCqi = ulCqiMap.find(rnti);
794  if (itCqi == ulCqiMap.end())
795  {
796  // no cqi info about this UE
797  return NO_SINR;
798  }
799  else
800  {
801  // take the average SINR value among the available
802  double sinrSum = 0;
803  unsigned int sinrNum = 0;
804  for (uint32_t i = 0; i < m_ulBandwidth; i++)
805  {
806  double sinr = (*itCqi).second.at(i);
807  if (sinr != NO_SINR)
808  {
809  sinrSum += sinr;
810  sinrNum++;
811  }
812  }
813  double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
814  // store the value
815  (*itCqi).second.at(rb) = estimatedSinr;
816  return estimatedSinr;
817  }
818 }
819 
820 uint8_t
822 {
823  NS_LOG_FUNCTION(this);
824 
825  if (!m_enabledInUplink)
826  {
827  return 1; // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213
828  // Table 5.1.1.1-2
829  }
830 
831  // TS36.213 Table 5.1.1.1-2
832  // TPC | Accumulated Mode | Absolute Mode
833  //------------------------------------------------
834  // 0 | -1 | -4
835  // 1 | 0 | -1
836  // 2 | 1 | 1
837  // 3 | 3 | 4
838  //------------------------------------------------
839  // here Absolute mode is used
840 
841  auto it = m_ues.find(rnti);
842  if (it == m_ues.end())
843  {
844  return 1;
845  }
846 
847  if (it->second == EdgeArea)
848  {
849  return m_edgeAreaTpc;
850  }
851  else
852  {
853  return m_centerAreaTpc;
854  }
855 
856  return 1;
857 }
858 
859 uint16_t
861 {
862  NS_LOG_FUNCTION(this);
863 
864  uint8_t minContinuousUlBandwidth = m_ulBandwidth;
865 
866  if (!m_enabledInUplink)
867  {
868  return minContinuousUlBandwidth;
869  }
870 
871  minContinuousUlBandwidth =
872  ((m_ulReuse3SubBandwidth > 0) && (m_ulReuse3SubBandwidth < minContinuousUlBandwidth))
874  : minContinuousUlBandwidth;
875 
876  minContinuousUlBandwidth =
877  ((m_ulReuse1SubBandwidth > 0) && (m_ulReuse1SubBandwidth < minContinuousUlBandwidth))
879  : minContinuousUlBandwidth;
880 
881  NS_LOG_INFO("minContinuousUlBandwidth: " << (int)minContinuousUlBandwidth);
882 
883  return minContinuousUlBandwidth;
884 }
885 
886 void
888 {
889  NS_LOG_FUNCTION(this << rnti << (uint16_t)measResults.measId);
890  NS_LOG_INFO("RNTI :" << rnti << " MeasId: " << (uint16_t)measResults.measId
891  << " RSRP: " << (uint16_t)measResults.measResultPCell.rsrpResult
892  << " RSRQ: " << (uint16_t)measResults.measResultPCell.rsrqResult);
893 
894  if (measResults.measId != m_measId)
895  {
896  NS_LOG_WARN("Ignoring measId " << (uint16_t)measResults.measId);
897  }
898  else
899  {
900  auto it = m_ues.find(rnti);
901  if (it == m_ues.end())
902  {
903  m_ues.insert(std::pair<uint16_t, uint8_t>(rnti, AreaUnset));
904  }
905 
906  it = m_ues.find(rnti);
907  if (measResults.measResultPCell.rsrqResult < m_rsrqThreshold)
908  {
909  if (it->second != EdgeArea)
910  {
911  NS_LOG_INFO("UE RNTI: " << rnti << " will be served in Edge sub-band");
912  it->second = EdgeArea;
913 
914  LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
915  pdschConfigDedicated.pa = m_edgeAreaPowerOffset;
916  m_ffrRrcSapUser->SetPdschConfigDedicated(rnti, pdschConfigDedicated);
917  }
918  }
919  else
920  {
921  if (it->second != CenterArea)
922  {
923  NS_LOG_INFO("UE RNTI: " << rnti << " will be served in Center sub-band");
924  it->second = CenterArea;
925 
926  LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
927  pdschConfigDedicated.pa = m_centerAreaPowerOffset;
928  m_ffrRrcSapUser->SetPdschConfigDedicated(rnti, pdschConfigDedicated);
929  }
930  }
931  }
932 }
933 
934 void
936 {
937  NS_LOG_FUNCTION(this);
938  NS_LOG_WARN("Method should not be called, because it is empty");
939 }
940 
941 } // 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.
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.
void DoReportUlCqiInfo(const FfMacSchedSapProvider::SchedUlCqiInfoReqParameters &params) override
DoReportUlCqiInfo.
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...
void DoReportDlCqiInfo(const FfMacSchedSapProvider::SchedDlCqiInfoReqParameters &params) override
DoReportDlCqiInfo.
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.
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:40
Service Access Point (SAP) offered by the eNodeB RRC instance to the Frequency Reuse algorithm instan...
Definition: lte-ffr-sap.h:140
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:359
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
#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
#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.
constexpr double NO_SINR
Value for SINR outside the range defined by FF-API, used to indicate that there is no CQI for this el...
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:49
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
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:306
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
enum ns3::LteRrcSap::ReportConfigEutra::@64 eventId
Event enumeration.
@ EVENT_A1
Event A1: Serving becomes better than absolute threshold.
Definition: lte-rrc-sap.h:384
ThresholdEutra threshold1
Threshold for event A1, A2, A4, and A5.
Definition: lte-rrc-sap.h:393
enum ns3::LteRrcSap::ReportConfigEutra::@67 reportInterval
Report interval enumeration.
enum ns3::LteRrcSap::ReportConfigEutra::@65 triggerQuantity
Trigger type enumeration.
@ RSRQ
Reference Signal Received Quality.
Definition: lte-rrc-sap.h:426
enum ns3::LteRrcSap::ThresholdEutra::@62 choice
Threshold enumeration.
@ 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