A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("LteFfrEnhancedAlgorithm");
36
37NS_OBJECT_ENSURE_REGISTERED(LteFfrEnhancedAlgorithm);
38
40static 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;
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;
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
133void
135{
136 NS_LOG_FUNCTION(this);
137 delete m_ffrSapProvider;
138 delete m_ffrRrcSapProvider;
139}
140
141TypeId
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
229void
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
243void
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
257void
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
284void
286{
287 NS_LOG_FUNCTION(this);
288 if (m_frCellTypeId != 0)
289 {
292 }
295 m_needReconfiguration = false;
296}
297
298void
299LteFfrEnhancedAlgorithm::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
316void
317LteFfrEnhancedAlgorithm::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
334int
336{
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
348void
350{
351 m_dlRbgMap.clear();
352 m_dlReuse3RbgMap.clear();
353 m_dlReuse1RbgMap.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
404void
406{
407 m_ulRbgMap.clear();
408 m_ulReuse3RbgMap.clear();
409 m_ulReuse1RbgMap.clear();
412
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 {
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
464std::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))
490 {
491 rbgMap.at(i) = false;
492 }
493 }
494 }
495
496 return rbgMap;
497}
498
499bool
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))
550 {
551 return true;
552 }
553 }
554 return false;
555 }
556
557 return false;
558}
559
560std::vector<bool>
562{
563 NS_LOG_FUNCTION(this);
564
565 if (m_ulRbgMap.empty())
566 {
568 }
569
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))
586 {
587 rbgMap.at(i) = false;
588 }
589 }
590 }
591
592 return rbgMap;
593}
594
595bool
597{
598 NS_LOG_FUNCTION(this);
599
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))
650 {
651 return true;
652 }
653 }
654 return false;
655 }
656
657 return false;
658}
659
660void
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
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 ? 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
767void
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
787void
788LteFfrEnhancedAlgorithm::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
794double
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
826uint8_t
828{
829 NS_LOG_FUNCTION(this);
830
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
865uint16_t
867{
868 NS_LOG_FUNCTION(this);
869
870 uint8_t minContinuousUlBandwidth = m_ulBandwidth;
871
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
892void
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);
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
940void
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.
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.
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.
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:360
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
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
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
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.
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
static const FfrEnhancedDownlinkDefaultConfiguration g_ffrEnhancedDownlinkDefaultConfiguration[]
The enhanced downlink default configuration.
static const FfrEnhancedUplinkDefaultConfiguration g_ffrEnhancedUplinkDefaultConfiguration[]
The enhanced uplink default configuration.
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::@62 eventId
Event enumeration.
@ RSRQ
Reference Signal Received Quality.
Definition: lte-rrc-sap.h:426
@ EVENT_A1
Event A1: Serving becomes better than absolute threshold.
Definition: lte-rrc-sap.h:384
enum ns3::LteRrcSap::ReportConfigEutra::@65 reportInterval
Report interval enumeration.
enum ns3::LteRrcSap::ReportConfigEutra::@63 triggerQuantity
Trigger type enumeration.
ThresholdEutra threshold1
Threshold for event A1, A2, A4, and A5.
Definition: lte-rrc-sap.h:393
@ THRESHOLD_RSRQ
RSRQ is used for the threshold.
Definition: lte-rrc-sap.h:365
enum ns3::LteRrcSap::ThresholdEutra::@60 choice
Threshold enumeration.
uint8_t range
Value range used in RSRP/RSRQ threshold.
Definition: lte-rrc-sap.h:368