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
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("LteFfrEnhancedAlgorithm");
36
37NS_OBJECT_ENSURE_REGISTERED(LteFfrEnhancedAlgorithm);
38
40static const double SpectralEfficiencyForCqi[16] = {0.0, // out of range
41 0.15,
42 0.23,
43 0.38,
44 0.6,
45 0.88,
46 1.18,
47 1.48,
48 1.91,
49 2.41,
50 2.73,
51 3.32,
52 3.9,
53 4.52,
54 5.12,
55 5.55};
56
59{
60 uint8_t cellId;
61 uint8_t dlBandwidth;
66 {1, 25, 0, 4, 4},
67 {2, 25, 8, 4, 4},
68 {3, 25, 16, 4, 4},
69 {1, 50, 0, 9, 6},
70 {2, 50, 15, 9, 6},
71 {3, 50, 30, 9, 6},
72 {1, 75, 0, 8, 16},
73 {2, 75, 24, 8, 16},
74 {3, 75, 48, 8, 16},
75 {1, 100, 0, 16, 16},
76 {2, 100, 32, 16, 16},
77 {3, 100, 64, 16, 16}};
78
81{
82 uint8_t cellId;
83 uint8_t ulBandwidth;
88 {1, 25, 0, 4, 4},
89 {2, 25, 8, 4, 4},
90 {3, 25, 16, 4, 4},
91 {1, 50, 0, 9, 6},
92 {2, 50, 15, 9, 6},
93 {3, 50, 30, 9, 6},
94 {1, 75, 0, 8, 16},
95 {2, 75, 24, 8, 16},
96 {3, 75, 48, 8, 16},
97 {1, 100, 0, 16, 16},
98 {2, 100, 32, 16, 16},
99 {3, 100, 64, 16, 16}};
100
107
109 : m_ffrSapUser(nullptr),
110 m_ffrRrcSapUser(nullptr),
111 m_measId(0)
112{
113 NS_LOG_FUNCTION(this);
116}
117
119{
120 NS_LOG_FUNCTION(this);
121}
122
123void
125{
126 NS_LOG_FUNCTION(this);
127 delete m_ffrSapProvider;
128 delete m_ffrRrcSapProvider;
129}
130
131TypeId
133{
134 static TypeId tid =
135 TypeId("ns3::LteFfrEnhancedAlgorithm")
137 .SetGroupName("Lte")
138 .AddConstructor<LteFfrEnhancedAlgorithm>()
139 .AddAttribute("UlSubBandOffset",
140 "Uplink SubBand Offset for this cell in number of Resource Block Groups",
141 UintegerValue(0),
143 MakeUintegerChecker<uint8_t>())
144 .AddAttribute(
145 "UlReuse3SubBandwidth",
146 "Uplink Reuse 3 SubBandwidth Configuration in number of Resource Block Groups",
147 UintegerValue(4),
149 MakeUintegerChecker<uint8_t>())
150 .AddAttribute(
151 "UlReuse1SubBandwidth",
152 "Uplink Reuse 1 SubBandwidth Configuration in number of Resource Block Groups",
153 UintegerValue(4),
155 MakeUintegerChecker<uint8_t>())
156 .AddAttribute(
157 "DlSubBandOffset",
158 "Downlink SubBand Offset for this cell in number of Resource Block Groups",
159 UintegerValue(0),
161 MakeUintegerChecker<uint8_t>())
162 .AddAttribute(
163 "DlReuse3SubBandwidth",
164 "Downlink Reuse 3 SubBandwidth Configuration in number of Resource Block Groups",
165 UintegerValue(4),
167 MakeUintegerChecker<uint8_t>())
168 .AddAttribute(
169 "DlReuse1SubBandwidth",
170 "Downlink Reuse 1 SubBandwidth Configuration in number of Resource Block Groups",
171 UintegerValue(4),
173 MakeUintegerChecker<uint8_t>())
174 .AddAttribute(
175 "RsrqThreshold",
176 "If the RSRQ of is worse than this threshold, UE should be served in Edge sub-band",
177 UintegerValue(26),
179 MakeUintegerChecker<uint8_t>())
180 .AddAttribute("CenterAreaPowerOffset",
181 "PdschConfigDedicated::Pa value for Center Sub-band, default value dB0",
182 UintegerValue(5),
184 MakeUintegerChecker<uint8_t>())
185 .AddAttribute("EdgeAreaPowerOffset",
186 "PdschConfigDedicated::Pa value for Edge Sub-band, default value dB0",
187 UintegerValue(5),
189 MakeUintegerChecker<uint8_t>())
190 .AddAttribute("DlCqiThreshold",
191 "If the DL-CQI for RBG of is higher than this threshold, transmission on "
192 "RBG is possible",
193 UintegerValue(15),
195 MakeUintegerChecker<uint8_t>())
196 .AddAttribute("UlCqiThreshold",
197 "If the UL-CQI for RBG of is higher than this threshold, transmission on "
198 "RBG is possible",
199 UintegerValue(15),
201 MakeUintegerChecker<uint8_t>())
202 .AddAttribute("CenterAreaTpc",
203 "TPC value which will be set in DL-DCI for UEs in center area"
204 "Absolute mode is used, default value 1 is mapped to -1 according to"
205 "TS36.213 Table 5.1.1.1-2",
206 UintegerValue(1),
208 MakeUintegerChecker<uint8_t>())
209 .AddAttribute("EdgeAreaTpc",
210 "TPC value which will be set in DL-DCI for UEs in edge area"
211 "Absolute mode is used, default value 1 is mapped to -1 according to"
212 "TS36.213 Table 5.1.1.1-2",
213 UintegerValue(1),
215 MakeUintegerChecker<uint8_t>());
216 return tid;
217}
218
219void
221{
222 NS_LOG_FUNCTION(this << s);
223 m_ffrSapUser = s;
224}
225
228{
229 NS_LOG_FUNCTION(this);
230 return m_ffrSapProvider;
231}
232
233void
235{
236 NS_LOG_FUNCTION(this << s);
237 m_ffrRrcSapUser = s;
238}
239
242{
243 NS_LOG_FUNCTION(this);
244 return m_ffrRrcSapProvider;
245}
246
247void
249{
250 NS_LOG_FUNCTION(this);
252
253 NS_ASSERT_MSG(m_dlBandwidth > 24, "DlBandwidth must be at least 25 to use EFFR algorithm");
254 NS_ASSERT_MSG(m_ulBandwidth > 24, "UlBandwidth must be at least 25 to use EFFR algorithm");
255
256 if (m_frCellTypeId != 0)
257 {
260 }
261
262 NS_LOG_LOGIC(this << " requesting Event A1 measurements"
263 << " (threshold = 0"
264 << ")");
265 LteRrcSap::ReportConfigEutra reportConfig;
268 reportConfig.threshold1.range = 0;
272}
273
274void
276{
277 NS_LOG_FUNCTION(this);
278 if (m_frCellTypeId != 0)
279 {
282 }
285 m_needReconfiguration = false;
286}
287
288void
289LteFfrEnhancedAlgorithm::SetDownlinkConfiguration(uint16_t cellId, uint8_t bandwidth)
290{
291 NS_LOG_FUNCTION(this);
292 for (uint16_t i = 0; i < NUM_DOWNLINK_CONFS; ++i)
293 {
294 if ((g_ffrEnhancedDownlinkDefaultConfiguration[i].cellId == cellId) &&
296 {
302 }
303 }
304}
305
306void
307LteFfrEnhancedAlgorithm::SetUplinkConfiguration(uint16_t cellId, uint8_t bandwidth)
308{
309 NS_LOG_FUNCTION(this);
310 for (uint16_t i = 0; i < NUM_UPLINK_CONFS; ++i)
311 {
312 if ((g_ffrEnhancedUplinkDefaultConfiguration[i].cellId == cellId) &&
314 {
320 }
321 }
322}
323
324int
326{
328 NS_ASSERT_MSG(s >= 0.0, "negative spectral efficiency = " << s);
329 int cqi = 0;
330 while ((cqi < 15) && (SpectralEfficiencyForCqi[cqi + 1] < s))
331 {
332 ++cqi;
333 }
334 NS_LOG_LOGIC("cqi = " << cqi);
335 return cqi;
336}
337
338void
340{
341 m_dlRbgMap.clear();
342 m_dlReuse3RbgMap.clear();
343 m_dlReuse1RbgMap.clear();
346
347 int rbgSize = GetRbgSize(m_dlBandwidth);
348 m_dlRbgMap.resize(m_dlBandwidth / rbgSize, true);
349
350 m_dlReuse3RbgMap.resize(m_dlBandwidth / rbgSize, false);
351 m_dlReuse1RbgMap.resize(m_dlBandwidth / rbgSize, false);
352 m_dlPrimarySegmentRbgMap.resize(m_dlBandwidth / rbgSize, false);
353 m_dlSecondarySegmentRbgMap.resize(m_dlBandwidth / rbgSize, true);
354
355 NS_ASSERT_MSG(m_dlSubBandOffset <= m_dlBandwidth, "DlSubBandOffset higher than DlBandwidth");
358 "DlSubBandOffset + DlReuse3SubBandwidth + DlReuse1SubBandwidth higher than DlBandwidth");
359
360 for (int i = 0; i < m_dlReuse3SubBandwidth / rbgSize; i++)
361 {
362 int offset = m_dlSubBandOffset / rbgSize;
363 uint8_t index = offset + i;
364 m_dlReuse3RbgMap[index] = true;
365 m_dlPrimarySegmentRbgMap[index] = true;
366 m_dlRbgMap[index] = false;
367 }
368
369 for (int i = 0; i < m_dlReuse1SubBandwidth / rbgSize; i++)
370 {
371 int offset = (m_dlSubBandOffset + m_dlReuse3SubBandwidth) / rbgSize;
372 uint8_t index = offset + i;
373 m_dlReuse1RbgMap[index] = true;
374 m_dlPrimarySegmentRbgMap[index] = true;
375 m_dlSecondarySegmentRbgMap[index] = false;
376 m_dlRbgMap[index] = false;
377 }
378
379 for (int i = 0; i < m_dlReuse3SubBandwidth / rbgSize; i++)
380 {
381 uint8_t offset = (m_dlReuse3SubBandwidth + m_dlReuse1SubBandwidth) / rbgSize;
382
383 uint8_t index = 0 * offset + i;
384 m_dlSecondarySegmentRbgMap[index] = false;
385
386 index = 1 * offset + i;
387 m_dlSecondarySegmentRbgMap[index] = false;
388
389 index = 2 * offset + i;
390 m_dlSecondarySegmentRbgMap[index] = false;
391 }
392}
393
394void
396{
397 m_ulRbgMap.clear();
398 m_ulReuse3RbgMap.clear();
399 m_ulReuse1RbgMap.clear();
402
404 {
405 m_ulRbgMap.resize(m_ulBandwidth, false);
406 return;
407 }
408
409 m_ulRbgMap.resize(m_ulBandwidth, true);
410 m_ulReuse3RbgMap.resize(m_ulBandwidth, false);
411 m_ulReuse1RbgMap.resize(m_ulBandwidth, false);
414
415 NS_ASSERT_MSG(m_ulSubBandOffset <= m_ulBandwidth, "UlSubBandOffset higher than UlBandwidth");
418 "UlSubBandOffset + UlReuse3SubBandwidth + UlReuse1SubBandwidth higher than UlBandwidth");
419
420 for (uint8_t i = 0; i < m_ulReuse3SubBandwidth; i++)
421 {
422 int offset = m_ulSubBandOffset;
423 uint8_t index = offset + i;
424 m_ulReuse3RbgMap[index] = true;
425 m_ulPrimarySegmentRbgMap[index] = true;
426 m_ulRbgMap[index] = false;
427 }
428
429 for (uint8_t i = 0; i < m_ulReuse1SubBandwidth; i++)
430 {
432 uint8_t index = offset + i;
433 m_ulReuse1RbgMap[index] = true;
434 m_ulPrimarySegmentRbgMap[index] = true;
435 m_ulSecondarySegmentRbgMap[index] = false;
436 m_ulRbgMap[index] = false;
437 }
438
439 for (uint8_t i = 0; i < m_ulReuse3SubBandwidth; i++)
440 {
442
443 uint8_t index = 0 * offset + i;
444 m_ulSecondarySegmentRbgMap[index] = false;
445
446 index = 1 * offset + i;
447 m_ulSecondarySegmentRbgMap[index] = false;
448
449 index = 2 * offset + i;
450 m_ulSecondarySegmentRbgMap[index] = false;
451 }
452}
453
454std::vector<bool>
456{
457 NS_LOG_FUNCTION(this);
458
460 {
461 Reconfigure();
462 }
463
464 if (m_dlRbgMap.empty())
465 {
467 }
468
469 std::vector<bool> rbgMap = m_dlRbgMap;
470
471 std::map<uint16_t, std::vector<bool>>::iterator it;
472 for (it = m_dlRbgAvailableforUe.begin(); it != m_dlRbgAvailableforUe.end(); it++)
473 {
474 NS_LOG_INFO("RNTI : " << it->first);
475 std::vector<bool> rbgAvailableMap = it->second;
476 for (uint32_t i = 0; i < rbgMap.size(); i++)
477 {
478 NS_LOG_INFO("\t rbgId: " << i << " available " << (int)rbgAvailableMap.at(i));
479 if (rbgAvailableMap.at(i) == true)
480 {
481 rbgMap.at(i) = false;
482 }
483 }
484 }
485
486 return rbgMap;
487}
488
489bool
491{
492 NS_LOG_FUNCTION(this);
493
494 bool isReuse3Rbg = m_dlReuse3RbgMap[rbgId];
495 bool isReuse1Rbg = m_dlReuse1RbgMap[rbgId];
496 bool isPrimarySegmentRbg = m_dlPrimarySegmentRbgMap[rbgId];
497 bool isSecondarySegmentRbg = m_dlSecondarySegmentRbgMap[rbgId];
498
499 std::map<uint16_t, uint8_t>::iterator it = m_ues.find(rnti);
500 if (it == m_ues.end())
501 {
502 m_ues.insert(std::pair<uint16_t, uint8_t>(rnti, AreaUnset));
503 }
504
505 it = m_ues.find(rnti);
506
507 // if UE area is unknown, serve UE in edge area RBGs
508 if (it->second == AreaUnset)
509 {
510 return isReuse3Rbg;
511 }
512
513 bool isCenterUe = false;
514 bool isEdgeUe = false;
515
516 if (it->second == CenterArea)
517 {
518 isCenterUe = true;
519 }
520 else if (it->second == EdgeArea)
521 {
522 isEdgeUe = true;
523 }
524
525 if (isPrimarySegmentRbg)
526 {
527 NS_LOG_INFO("PRIMARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId);
528 return (isReuse1Rbg && isCenterUe) || (isReuse3Rbg && isEdgeUe);
529 }
530 else if (isSecondarySegmentRbg && isCenterUe)
531 {
532 // check if RB can be used by UE based on CQI information
533 NS_LOG_INFO("SECONDARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId);
534 std::map<uint16_t, std::vector<bool>>::iterator it = m_dlRbgAvailableforUe.find(rnti);
535 if (it != m_dlRbgAvailableforUe.end())
536 {
537 NS_LOG_INFO("RNTI: " << rnti << " rbgId: " << rbgId
538 << " available: " << it->second.at(rbgId));
539 if (it->second.at(rbgId) == true)
540 {
541 return true;
542 }
543 }
544 return false;
545 }
546
547 return false;
548}
549
550std::vector<bool>
552{
553 NS_LOG_FUNCTION(this);
554
555 if (m_ulRbgMap.empty())
556 {
558 }
559
561 {
562 return m_ulRbgMap;
563 }
564
565 std::vector<bool> rbgMap = m_ulRbgMap;
566
567 std::map<uint16_t, std::vector<bool>>::iterator it;
568 for (it = m_ulRbAvailableforUe.begin(); it != m_ulRbAvailableforUe.end(); it++)
569 {
570 NS_LOG_INFO("RNTI : " << it->first);
571 std::vector<bool> rbAvailableMap = it->second;
572 for (uint32_t i = 0; i < rbgMap.size(); i++)
573 {
574 NS_LOG_INFO("\t rbgId: " << i << " available " << (int)rbAvailableMap.at(i));
575 if (rbAvailableMap.at(i) == true)
576 {
577 rbgMap.at(i) = false;
578 }
579 }
580 }
581
582 return rbgMap;
583}
584
585bool
587{
588 NS_LOG_FUNCTION(this);
589
591 {
592 return true;
593 }
594
595 bool isReuse3Rbg = m_ulReuse3RbgMap[rbgId];
596 bool isReuse1Rbg = m_ulReuse1RbgMap[rbgId];
597 bool isPrimarySegmentRbg = m_ulPrimarySegmentRbgMap[rbgId];
598 bool isSecondarySegmentRbg = m_ulSecondarySegmentRbgMap[rbgId];
599
600 std::map<uint16_t, uint8_t>::iterator it = m_ues.find(rnti);
601 if (it == m_ues.end())
602 {
603 m_ues.insert(std::pair<uint16_t, uint8_t>(rnti, AreaUnset));
604 }
605
606 it = m_ues.find(rnti);
607
608 // if UE area is unknown, serve UE in edge area RBGs
609 if (it->second == AreaUnset)
610 {
611 return isReuse3Rbg;
612 }
613
614 bool isCenterUe = false;
615 bool isEdgeUe = false;
616
617 if (it->second == CenterArea)
618 {
619 isCenterUe = true;
620 }
621 else if (it->second == EdgeArea)
622 {
623 isEdgeUe = true;
624 }
625
626 if (isPrimarySegmentRbg)
627 {
628 return (isReuse1Rbg && isCenterUe) || (isReuse3Rbg && isEdgeUe);
629 }
630 else if (isSecondarySegmentRbg && isCenterUe)
631 {
632 // check if RB can be used by UE based on CQI information
633 NS_LOG_INFO("UL SECONDARY SEGMENT RNTI: " << rnti << " rbgId: " << rbgId);
634 std::map<uint16_t, std::vector<bool>>::iterator it = m_ulRbAvailableforUe.find(rnti);
635 if (it != m_ulRbAvailableforUe.end())
636 {
637 NS_LOG_INFO("RNTI: " << rnti << " rbgId: " << rbgId
638 << " available: " << it->second.at(rbgId));
639 if (it->second.at(rbgId) == true)
640 {
641 return true;
642 }
643 }
644 return false;
645 }
646
647 return false;
648}
649
650void
653{
654 NS_LOG_FUNCTION(this);
655
656 m_dlCqi.clear();
657 for (unsigned int i = 0; i < params.m_cqiList.size(); i++)
658 {
659 if (params.m_cqiList.at(i).m_cqiType == CqiListElement_s::A30)
660 {
661 NS_LOG_INFO("subband CQI reporting high layer configured");
662 // subband CQI reporting high layer configured
663 std::map<uint16_t, SbMeasResult_s>::iterator it;
664 uint16_t rnti = params.m_cqiList.at(i).m_rnti;
665
666 std::map<uint16_t, uint8_t>::iterator ueIt = m_ues.find(rnti);
667 if (ueIt != m_ues.end())
668 {
669 if (ueIt->second != CenterArea)
670 {
671 continue;
672 }
673 }
674 else
675 {
676 continue;
677 }
678
679 it = m_dlCqi.find(rnti);
680 if (it == m_dlCqi.end())
681 {
682 // create the new entry
683 m_dlCqi.insert(
684 std::pair<uint16_t, SbMeasResult_s>(rnti,
685 params.m_cqiList.at(i).m_sbMeasResult));
686 }
687 else
688 {
689 // update the CQI value and refresh correspondent timer
690 (*it).second = params.m_cqiList.at(i).m_sbMeasResult;
691 }
692 }
693 else
694 {
695 NS_LOG_ERROR(this << " CQI type unknown");
696 }
697 }
698
700 m_dlRbgAvailableforUe.clear();
701 std::map<uint16_t, SbMeasResult_s>::iterator it;
702 for (it = m_dlCqi.begin(); it != m_dlCqi.end(); it++)
703 {
704 uint16_t rnti = it->first;
705 std::vector<bool> rbgAvailableMap;
706
707 for (uint32_t i = 0; i < (*it).second.m_higherLayerSelected.size(); i++)
708 {
709 uint8_t rbgCqi = (*it).second.m_higherLayerSelected.at(i).m_sbCqi.at(0);
710
711 if (i > m_dlBandwidth / rbgSize)
712 {
713 continue;
714 }
715 NS_LOG_INFO(this << " RNTI " << rnti << " RBG " << i << " DL-CQI: " << (int)rbgCqi);
716
717 bool rbgAvailable = (rbgCqi > m_dlCqiThreshold);
718
719 bool isSecondarySegmentRbg = false;
720 if (i < m_dlSecondarySegmentRbgMap.size())
721 {
722 isSecondarySegmentRbg = m_dlSecondarySegmentRbgMap[i];
723 }
724
725 rbgAvailable = (isSecondarySegmentRbg == true) ? rbgAvailable : false;
726
727 rbgAvailableMap.push_back(rbgAvailable);
728 }
729
730 m_dlRbgAvailableforUe.insert(std::pair<uint16_t, std::vector<bool>>(rnti, rbgAvailableMap));
731 }
732
733 m_ulRbAvailableforUe.clear();
734 for (std::map<uint16_t, std::vector<bool>>::iterator it = m_dlRbgAvailableforUe.begin();
735 it != m_dlRbgAvailableforUe.end();
736 it++)
737 {
738 uint16_t rnti = it->first;
739 std::vector<bool> dlRbgAvailableMap = it->second;
740 std::vector<bool> ulRbAvailableMap;
741 ulRbAvailableMap.resize(m_ulBandwidth, false);
742
743 for (uint32_t j = 0; j < dlRbgAvailableMap.size(); j++)
744 {
745 uint32_t index = rbgSize * j;
746 for (uint32_t i = 0; i < rbgSize; i++)
747 {
748 index = index + i;
749 ulRbAvailableMap[index] = dlRbgAvailableMap[j];
750 }
751 }
752
753 m_ulRbAvailableforUe.insert(std::pair<uint16_t, std::vector<bool>>(rnti, ulRbAvailableMap));
754 }
755}
756
757void
760{
761 NS_LOG_FUNCTION(this);
762 if (params.m_ulCqi.m_type == UlCqi_s::SRS)
763 {
764 // get the RNTI from vendor specific parameters
765 uint16_t rnti = 0;
766 for (uint32_t j = 0; j < m_ulBandwidth; j++)
767 {
768 double sinr = LteFfConverter::fpS11dot3toDouble(params.m_ulCqi.m_sinr.at(j));
769 double s = log2(1 + (std::pow(10, sinr / 10) / ((-std::log(5.0 * 0.00005)) / 1.5)));
770 int cqi = GetCqiFromSpectralEfficiency(s);
771 NS_LOG_INFO(this << " RNTI " << rnti << " new SRS-CQI for RB " << j << " value "
772 << sinr << " UL-CQI: " << cqi);
773 }
774 }
775}
776
777void
778LteFfrEnhancedAlgorithm::DoReportUlCqiInfo(std::map<uint16_t, std::vector<double>> ulCqiMap)
779{
780 NS_LOG_FUNCTION(this);
781 NS_LOG_WARN("Method should not be called, because it is empty");
782}
783
784double
786 uint16_t rb,
787 std::map<uint16_t, std::vector<double>> ulCqiMap)
788{
789 std::map<uint16_t, std::vector<double>>::iterator itCqi = ulCqiMap.find(rnti);
790 if (itCqi == ulCqiMap.end())
791 {
792 // no cqi info about this UE
793 return (NO_SINR);
794 }
795 else
796 {
797 // take the average SINR value among the available
798 double sinrSum = 0;
799 unsigned int sinrNum = 0;
800 for (uint32_t i = 0; i < m_ulBandwidth; i++)
801 {
802 double sinr = (*itCqi).second.at(i);
803 if (sinr != NO_SINR)
804 {
805 sinrSum += sinr;
806 sinrNum++;
807 }
808 }
809 double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
810 // store the value
811 (*itCqi).second.at(rb) = estimatedSinr;
812 return (estimatedSinr);
813 }
814}
815
816uint8_t
818{
819 NS_LOG_FUNCTION(this);
820
822 {
823 return 1; // 1 is mapped to 0 for Accumulated mode, and to -1 in Absolute mode TS36.213
824 // Table 5.1.1.1-2
825 }
826
827 // TS36.213 Table 5.1.1.1-2
828 // TPC | Accumulated Mode | Absolute Mode
829 //------------------------------------------------
830 // 0 | -1 | -4
831 // 1 | 0 | -1
832 // 2 | 1 | 1
833 // 3 | 3 | 4
834 //------------------------------------------------
835 // here Absolute mode is used
836
837 std::map<uint16_t, uint8_t>::iterator it = m_ues.find(rnti);
838 if (it == m_ues.end())
839 {
840 return 1;
841 }
842
843 if (it->second == EdgeArea)
844 {
845 return m_edgeAreaTpc;
846 }
847 else
848 {
849 return m_centerAreaTpc;
850 }
851
852 return 1;
853}
854
855uint16_t
857{
858 NS_LOG_FUNCTION(this);
859
860 uint8_t minContinuousUlBandwidth = m_ulBandwidth;
861
863 {
864 return minContinuousUlBandwidth;
865 }
866
867 minContinuousUlBandwidth =
868 ((m_ulReuse3SubBandwidth > 0) && (m_ulReuse3SubBandwidth < minContinuousUlBandwidth))
870 : minContinuousUlBandwidth;
871
872 minContinuousUlBandwidth =
873 ((m_ulReuse1SubBandwidth > 0) && (m_ulReuse1SubBandwidth < minContinuousUlBandwidth))
875 : minContinuousUlBandwidth;
876
877 NS_LOG_INFO("minContinuousUlBandwidth: " << (int)minContinuousUlBandwidth);
878
879 return minContinuousUlBandwidth;
880}
881
882void
884{
885 NS_LOG_FUNCTION(this << rnti << (uint16_t)measResults.measId);
886 NS_LOG_INFO("RNTI :" << rnti << " MeasId: " << (uint16_t)measResults.measId
887 << " RSRP: " << (uint16_t)measResults.measResultPCell.rsrpResult
888 << " RSRQ: " << (uint16_t)measResults.measResultPCell.rsrqResult);
889
890 if (measResults.measId != m_measId)
891 {
892 NS_LOG_WARN("Ignoring measId " << (uint16_t)measResults.measId);
893 }
894 else
895 {
896 std::map<uint16_t, uint8_t>::iterator it = m_ues.find(rnti);
897 if (it == m_ues.end())
898 {
899 m_ues.insert(std::pair<uint16_t, uint8_t>(rnti, AreaUnset));
900 }
901
902 it = m_ues.find(rnti);
904 {
905 if (it->second != EdgeArea)
906 {
907 NS_LOG_INFO("UE RNTI: " << rnti << " will be served in Edge sub-band");
908 it->second = EdgeArea;
909
910 LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
911 pdschConfigDedicated.pa = m_edgeAreaPowerOffset;
912 m_ffrRrcSapUser->SetPdschConfigDedicated(rnti, pdschConfigDedicated);
913 }
914 }
915 else
916 {
917 if (it->second != CenterArea)
918 {
919 NS_LOG_INFO("UE RNTI: " << rnti << " will be served in Center sub-band");
920 it->second = CenterArea;
921
922 LteRrcSap::PdschConfigDedicated pdschConfigDedicated;
923 pdschConfigDedicated.pa = m_centerAreaPowerOffset;
924 m_ffrRrcSapUser->SetPdschConfigDedicated(rnti, pdschConfigDedicated);
925 }
926 }
927 }
928}
929
930void
932{
933 NS_LOG_FUNCTION(this);
934 NS_LOG_WARN("Method should not be called, because it is empty");
935}
936
937} // 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.
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.
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)
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:45
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static const struct ns3::FfrEnhancedDownlinkDefaultConfiguration g_ffrEnhancedDownlinkDefaultConfiguration[]
the enhanced downlink default configation
const uint16_t NUM_DOWNLINK_CONFS(sizeof(g_ffrEnhancedDownlinkDefaultConfiguration)/sizeof(FfrEnhancedDownlinkDefaultConfiguration))
const uint16_t NUM_UPLINK_CONFS(sizeof(g_ffrEnhancedUplinkDefaultConfiguration)/sizeof(FfrEnhancedUplinkDefaultConfiguration))
static const struct ns3::FfrEnhancedUplinkDefaultConfiguration g_ffrEnhancedUplinkDefaultConfiguration[]
the enhanced uplink default configuration
static const double SpectralEfficiencyForCqi[16]
Table of CQI index and its spectral efficiency.
Definition: lte-amc.cc:47
Parameters of the LOAD INFORMATION message.
Definition: epc-x2-sap.h:305
Parameters of the SCHED_DL_CQI_INFO_REQ primitive.
std::vector< struct CqiListElement_s > m_cqiList
CQI list.
Parameters of the SCHED_UL_CQI_INFO_REQ primitive.
uint8_t rsrqResult
the RSRQ result
Definition: lte-rrc-sap.h:661
uint8_t rsrpResult
the RSRP result
Definition: lte-rrc-sap.h:660
MeasResults structure.
Definition: lte-rrc-sap.h:703
uint8_t measId
measure ID
Definition: lte-rrc-sap.h:704
MeasResultPCell measResultPCell
measurement result primary cell
Definition: lte-rrc-sap.h:705
PdschConfigDedicated structure.
Definition: lte-rrc-sap.h:157
Specifies criteria for triggering of an E-UTRA measurement reporting event.
Definition: lte-rrc-sap.h:367
@ RSRQ
Reference Signal Received Quality.
Definition: lte-rrc-sap.h:418
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:387
@ EVENT_A1
Event A1: Serving becomes better than absolute threshold.
Definition: lte-rrc-sap.h:378
@ THRESHOLD_RSRQ
RSRQ is used for the threshold.
Definition: lte-rrc-sap.h:359
uint8_t range
Value range used in RSRP/RSRQ threshold.
Definition: lte-rrc-sap.h:362
enum ns3::LteRrcSap::ThresholdEutra::@63 choice
Threshold enumeration.
std::vector< uint16_t > m_sinr
SINR.