5#include "nr-fh-control.h"
7#include "ns3/core-module.h"
12NS_LOG_COMPONENT_DEFINE(
"NrFhControl");
13NS_OBJECT_ENSURE_REGISTERED(NrFhControl);
15static constexpr uint32_t
16Cantor(uint16_t x1, uint16_t x2)
18 return (((x1 + x2) * (x1 + x2 + 1)) / 2) + x2;
25 TypeId(
"ns3::NrFhControl")
27 .AddConstructor<NrFhControl>()
31 "The FH Control method defines the model that the fhControl will use"
32 "to limit the capacity. There are four FH Control methods: "
33 "a) Dropping. When CTRL channels are sent, PHY asks the FhControl whether"
34 "the allocation fits. If not, it drops the DCI + data."
35 "b) Postponing. When tdma/ofdma have allocated the RBs/symbols to all the"
36 "UEs, it iterates through all the UEs and asks the FhControl whether the"
37 "allocation fits. If not, it sets the assigned RBGs to 0 and therefore the"
38 "sending of the data is postponed (DCI is not created – data stays in RLC queue)"
39 "c) Optimize MCS. When tdma/ofdma have allocated the RBs/symbols to all the UEs,"
40 "it iterates through all the UEs (with data in their queues and resources"
41 "allocated during the scheduling process) and asks fhControl for the max MCS."
42 "It assigns the min among the allocated one and the max MCS."
43 "d) Optimize RBs. When tdma/ofdma are allocating the RBs/symbols to a UE,"
44 "it calls the fhControl to provide the max RBs that can be assigned.",
47 &NrFhControl::GetFhControlMethod),
56 .AddAttribute(
"FhCapacity",
57 "The available fronthaul capacity (in Mbps)."
58 "The capacity is shared among the active BWPs"
62 MakeUintegerChecker<uint32_t>(0, 150000))
63 .AddAttribute(
"OverheadDyn",
64 "The overhead for dynamic adaptation (in bits)",
67 MakeUintegerChecker<uint8_t>(0, 100))
69 "RequiredFhDlThroughput",
70 "Report required fronthaul throughput in DL per BWP (Sfnfn, bwpId, reqFhThr)",
71 MakeTraceSourceAccessor(&NrFhControl::m_reqFhDlThrTrace),
72 "ns3::ReqFhDlThr::TracedCallback")
75 "Report the employed RBs of the air interface in DL per BWP (Sfnfn, bwpId, rbsAir)",
76 MakeTraceSourceAccessor(&NrFhControl::m_rbsAirTrace),
77 "ns3::rbsAir::TracedCallback");
82 : m_physicalCellId(0),
86 NS_LOG_FUNCTION(
this);
93 delete m_fhPhySapProvider;
94 delete m_fhSchedSapProvider;
100 NS_LOG_FUNCTION(
this << s);
101 std::map<uint16_t, NrFhPhySapUser*>::iterator it = m_fhPhySapUser.find(bwpId);
103 if (it != m_fhPhySapUser.end())
105 NS_FATAL_ERROR(
"Tried to allocated an existing bwpId");
107 if (it == m_fhPhySapUser.end())
109 m_fhPhySapUser.insert(std::pair<uint8_t, NrFhPhySapUser*>(bwpId, s));
116 NS_LOG_FUNCTION(
this);
118 return m_fhPhySapProvider;
124 NS_LOG_FUNCTION(
this << s);
126 std::map<uint16_t, NrFhSchedSapUser*>::iterator it = m_fhSchedSapUser.find(bwpId);
128 if (it != m_fhSchedSapUser.end())
130 NS_FATAL_ERROR(
"Tried to allocated an existing bwpId");
132 if (it == m_fhSchedSapUser.end())
134 m_fhSchedSapUser.insert(std::pair<uint8_t, NrFhSchedSapUser*>(bwpId, s));
141 NS_LOG_FUNCTION(
this);
142 return m_fhSchedSapProvider;
148 NS_LOG_FUNCTION(
this);
149 NS_LOG_DEBUG(
"Set the Fh Control Method to: " << model);
150 m_fhControlMethod = model;
154NrFhControl::GetFhControlMethod()
const
156 NS_LOG_FUNCTION(
this);
157 return m_fhControlMethod;
161NrFhControl::DoGetFhControlMethod()
const
163 return m_fhControlMethod;
169 NS_LOG_FUNCTION(
this);
170 m_fhCapacity = capacity;
176 NS_LOG_FUNCTION(
this);
177 m_overheadDyn = overhead;
183 m_errorModelType = errorModelType;
185 if (m_errorModelType ==
"ns3::NrEesmIrT1" || m_errorModelType ==
"ns3::NrEesmCcT1")
189 else if (m_errorModelType ==
"ns3::NrEesmIrT2" || m_errorModelType ==
"ns3::NrEesmCcT2")
196 "Wrong error model type. To use NrFhControl, one of the Nr error models should be set."
197 "Please select among: ns3::NrEesmIrT1, ns3::NrEesmCcT1 for MCS Table 1 and"
198 "ns3::NrEesmIrT2 and ns3::NrEesmCcT2 for MCS Table 2");
205 NS_LOG_FUNCTION(
this);
206 m_physicalCellId = physicalCellId;
207 NS_LOG_DEBUG(
"NrFhControl initialized for cell Id: " << m_physicalCellId);
211NrFhControl::DoGetPhysicalCellId()
const
213 return m_physicalCellId;
219 if (m_numerologyPerBwp.find(bwpId) == m_numerologyPerBwp.end())
221 m_numerologyPerBwp.insert(std::make_pair(bwpId, num));
222 SfnSf waitingSlot = {0, 0, 0,
static_cast<uint8_t
>(num)};
223 m_waitingSlotPerBwp.insert(std::make_pair(bwpId, waitingSlot));
224 NS_LOG_DEBUG(
"Cell: " << m_physicalCellId <<
" BWP: " << bwpId <<
" num: " << num);
228 NS_ABORT_MSG(
"Configure NrFhControl should be called only once");
233NrFhControl::DoSetActiveUe(uint16_t bwpId, uint16_t rnti, uint32_t bytes)
235 if (m_activeUesPerBwp.find(bwpId) == m_activeUesPerBwp.end())
237 NS_LOG_DEBUG(
"Creating m_activeUesPerBwp entry for bwpId: " << bwpId);
238 m_activeUesPerBwp[bwpId] = {};
240 NS_LOG_DEBUG(
"Creating m_activeUesPerBwp entry for bwpId: " << bwpId <<
" and rnti: " << rnti);
241 m_activeUesPerBwp.at(bwpId).emplace(rnti);
243 uint32_t c1 = Cantor(bwpId, rnti);
244 if (m_rntiQueueSize.find(c1) == m_rntiQueueSize.end())
246 NS_LOG_DEBUG(
"Cell: " << m_physicalCellId <<
" Creating pair " << c1 <<
" for bwpId: "
247 << bwpId <<
" and rnti: " << rnti <<
" with bytes: " << bytes);
249 m_rntiQueueSize.insert(std::make_pair(c1, bytes));
253 NS_LOG_DEBUG(
"Cell: " << m_physicalCellId <<
" Updating pair " << c1 <<
" for bwpId: "
254 << bwpId <<
" and rnti: " << rnti <<
" with bytes: " << bytes);
255 m_rntiQueueSize.at(c1) = bytes;
260NrFhControl::DoSetActiveHarqUes(uint16_t bwpId, uint16_t rnti)
262 if (m_activeHarqUesPerBwp.find(bwpId) == m_activeHarqUesPerBwp.end())
264 NS_LOG_DEBUG(
"Creating m_activeHarqUesPerBwp entry for bwpId: " << bwpId);
265 m_activeHarqUesPerBwp[bwpId] = {};
267 NS_LOG_DEBUG(
"Creating m_activeHarqUesPerBwp entry for bwpId: " << bwpId
268 <<
" and rnti: " << rnti);
269 m_activeHarqUesPerBwp.at(bwpId).emplace(rnti);
273NrFhControl::DoUpdateActiveUesMap(
275 const std::deque<VarTtiAllocInfo>& allocation,
276 const std::unordered_map<uint16_t, std::shared_ptr<NrMacSchedulerUeInfo>>& ueMap)
278 for (
const auto& alloc : allocation)
286 uint16_t rnti = alloc.m_dci->m_rnti;
287 uint32_t c1 = Cantor(bwpId, rnti);
289 static_cast<uint32_t
>(
290 std::count(alloc.m_dci->m_rbgBitmask.begin(), alloc.m_dci->m_rbgBitmask.end(), 1)) *
291 static_cast<uint32_t
>(m_fhSchedSapUser.at(bwpId)->GetNumRbPerRbgFromSched());
293 NS_LOG_INFO(
"Cell: " << m_physicalCellId <<
" We got called for Update for bwpId: " << bwpId
294 <<
" RNTI: " << rnti);
297 uint64_t fhDlThr = GetFhThr(bwpId,
298 static_cast<uint32_t
>(alloc.m_dci->m_mcs),
299 static_cast<uint32_t
>(alloc.m_dci->m_numSym) * numRbs,
300 alloc.m_dci->m_rank);
301 if (m_reqFhDlThrTracedValuePerBwp.find(bwpId) == m_reqFhDlThrTracedValuePerBwp.end())
303 NS_LOG_DEBUG(
"Create pair for m_reqFhDlThrTracedValuePerBwp.at(" << bwpId
304 <<
"): " << fhDlThr);
306 m_reqFhDlThrTracedValuePerBwp[bwpId] += fhDlThr;
307 NS_LOG_DEBUG(
"Update m_reqFhDlThrTracedValuePerBwp.at("
308 << bwpId <<
"): " << m_reqFhDlThrTracedValuePerBwp.at(bwpId));
311 if (m_rbsAirTracedValue.find(bwpId) == m_rbsAirTracedValue.end())
313 NS_LOG_DEBUG(
"Create pair for m_rbsAirTracedValue.at(" << bwpId <<
"): " << numRbs
316 m_rbsAirTracedValue[bwpId] += numRbs;
317 NS_LOG_DEBUG(
"Update m_rbsAirTracedValue.at(" << bwpId <<
")" << m_rbsAirTracedValue[bwpId]
320 if (alloc.m_dci->m_ndi == 0)
322 NS_LOG_DEBUG(
"Retransmission, update only m_activeHarqUesPerBwp");
323 if (m_activeHarqUesPerBwp.find(rnti) != m_activeHarqUesPerBwp.end())
325 m_activeHarqUesPerBwp.at(bwpId).erase(rnti);
326 NS_LOG_DEBUG(
"Update m_activeHarqBwps map for bwpId: "
327 << bwpId <<
" with: " << m_activeHarqUesPerBwp.at(bwpId).size()
329 if (m_activeHarqUesPerBwp.at(bwpId).empty())
332 "Remove BWP from m_activeHarqBwps because we served all its HARQ UEs");
333 m_activeHarqUesPerBwp.erase(bwpId);
340 if (m_rntiQueueSize.empty())
342 NS_LOG_DEBUG(
"empty MAP");
343 NS_ABORT_MSG_IF(!m_activeUesPerBwp.at(bwpId).empty(),
344 "No UE in map, but something in activeUes map");
348 if (ueMap.find(rnti) != ueMap.end())
350 uint32_t totBuffer = ueMap.at(rnti)->GetTotalDlBuffer();
353 m_rntiQueueSize.at(c1) = totBuffer;
354 NS_LOG_DEBUG(
"Updating queue size for bwpId: " << bwpId <<
" RNTI: " << rnti
355 <<
" to " << m_rntiQueueSize.at(c1)
361 "Removing UE because we served it. RLC queue size: " << m_rntiQueueSize.at(c1));
362 m_rntiQueueSize.erase(c1);
363 m_activeUesPerBwp.at(bwpId).erase(rnti);
364 NS_LOG_DEBUG(
"Update ActiveBwps map for bwpId: "
365 << bwpId <<
" with: " << m_activeUesPerBwp.at(bwpId).size() <<
" UEs");
367 if (m_activeUesPerBwp.at(bwpId).empty())
369 NS_LOG_DEBUG(
"Remove BWP from Active BWPs because we served all its UEs");
370 m_activeUesPerBwp.erase(bwpId);
376 NS_ABORT_MSG(
"UE not in the map, but has an allocation");
382NrFhControl::GetNumberActiveUes(uint16_t bwpId)
const
384 return m_activeUesPerBwp.at(bwpId).size();
388NrFhControl::GetNumberActiveBwps()
const
391 uint16_t numActiveBwps = m_activeUesPerBwp.size();
392 for (
auto& it : m_activeHarqUesPerBwp)
396 if (m_activeUesPerBwp.find(it.first) == m_activeUesPerBwp.end())
401 NS_LOG_DEBUG(
"Number of active BWPs calculated: " << numActiveBwps);
402 return numActiveBwps;
406NrFhControl::DoGetDoesAllocationFit(uint16_t bwpId, uint32_t mcs, uint32_t nRegs, uint8_t dlRank)
408 NS_LOG_INFO(
"NrFhControl::DoGetDoesAllocationFit for cell: " << m_physicalCellId <<
" bwpId: "
409 << bwpId <<
" mcs: " << mcs
410 <<
" nRegs: " << nRegs);
411 uint16_t numOfActiveBwps =
412 GetNumberActiveBwps();
414 NS_LOG_DEBUG(
"Number of active BWPs in DoesAllocFit: " << numOfActiveBwps);
416 if (numOfActiveBwps == 0)
421 uint64_t thr = GetFhThr(
424 nRegs *
static_cast<uint32_t
>(m_fhSchedSapUser.at(bwpId)->GetNumRbPerRbgFromSched()),
427 if (m_allocThrPerBwp.find(bwpId) == m_allocThrPerBwp.end())
429 if (thr < (m_fhCapacity /
static_cast<uint32_t
>(numOfActiveBwps) * 1e6))
431 m_allocThrPerBwp.insert(std::make_pair(bwpId, thr));
432 NS_LOG_DEBUG(
"BWP not in the map, Allocation can be included. BWP Thr: "
433 << m_allocThrPerBwp.at(bwpId));
436 NS_LOG_DEBUG(
"BWP not in the map, Allocation cannot be included");
439 if ((m_allocThrPerBwp[bwpId] + thr) <
440 (m_fhCapacity /
static_cast<uint32_t
>(numOfActiveBwps) * 1e6))
442 m_allocThrPerBwp[bwpId] += thr;
444 "BWP in the map, Allocation can be included. BWP Thr: " << m_allocThrPerBwp.at(bwpId));
447 NS_LOG_INFO(
"BWP in the map, Allocation cannot be included");
452NrFhControl::DoGetMaxMcsAssignable(uint16_t bwpId, uint32_t reg, uint32_t rnti, uint8_t dlRank)
454 uint16_t numOfActiveBwps =
455 GetNumberActiveBwps();
456 NS_ASSERT_MSG(numOfActiveBwps > 0,
"No Active BWPs, sth is wrong");
457 uint32_t availableCapacity = m_fhCapacity /
static_cast<uint32_t
>(numOfActiveBwps);
459 uint16_t numActiveUes = GetNumberActiveUes(bwpId);
460 NS_LOG_INFO(
"BwpId: " << bwpId <<
" Number of Active UEs: " << numActiveUes);
461 uint16_t Kp = numActiveUes;
463 Time slotLength = MicroSeconds(
464 static_cast<uint16_t
>(1000 / std::pow(2, m_numerologyPerBwp.at(bwpId))));
465 uint32_t overheadMac =
static_cast<uint32_t
>(
467 std::pow(2, m_numerologyPerBwp.at(bwpId)));
469 if (availableCapacity * 1e6 * slotLength.GetSeconds() <=
470 numActiveUes * m_overheadDyn + numActiveUes * overheadMac + numActiveUes * 12 * 2 * 10)
472 while (availableCapacity * 1e6 * slotLength.GetSeconds() <=
473 Kp * m_overheadDyn + Kp * overheadMac + Kp * 12 * 2 * 10)
478 NS_ABORT_MSG_IF(availableCapacity * 1e6 * slotLength.GetSeconds() <=
479 Kp * m_overheadDyn + Kp * overheadMac + Kp * 12 * 2 * 10,
480 "Not enough fronthaul capacity to send intra-PHY split overhead");
482 uint32_t num =
static_cast<uint32_t
>(availableCapacity * 1e6 * slotLength.GetSeconds() -
483 Kp * m_overheadDyn - Kp * overheadMac - Kp * 12 * 2 * 10);
488 uint16_t modOrderMax =
489 num / (12 * Kp * reg * dlRank) /
490 static_cast<uint32_t
>(
491 m_fhSchedSapUser.at(bwpId)
492 ->GetNumRbPerRbgFromSched());
493 uint8_t mcsMax = GetMaxMcs(m_mcsTable, modOrderMax);
495 NS_ABORT_MSG_IF(mcsMax == 0,
"could not compute correctly the maxMCS");
501NrFhControl::DoGetMaxRegAssignable(uint16_t bwpId, uint32_t mcs, uint32_t rnti, uint8_t dlRank)
503 uint32_t modulationOrder =
504 m_mcsTable == 1 ? GetModulationOrderTable1(mcs) : GetModulationOrderTable2(mcs);
506 uint16_t numOfActiveBwps =
507 GetNumberActiveBwps();
508 NS_ASSERT_MSG(numOfActiveBwps > 0,
"No Active BWPs, sth is wrong");
509 uint32_t availableCapacity = m_fhCapacity /
static_cast<uint32_t
>(numOfActiveBwps);
511 uint16_t numActiveUes = GetNumberActiveUes(bwpId);
512 NS_LOG_INFO(
"BwpId: " << bwpId <<
" Number of Active UEs: " << numActiveUes);
513 uint16_t Kp = numActiveUes;
515 Time slotLength = MicroSeconds(
516 static_cast<uint16_t
>(1000 / std::pow(2, m_numerologyPerBwp.at(bwpId))));
517 uint32_t overheadMac =
static_cast<uint32_t
>(
519 std::pow(2, m_numerologyPerBwp.at(bwpId)));
521 if (availableCapacity * 1e6 * slotLength.GetSeconds() <=
522 numActiveUes * m_overheadDyn + numActiveUes * overheadMac + numActiveUes * 12 * 2 * 10)
524 while (availableCapacity * 1e6 * slotLength.GetSeconds() <=
525 Kp * m_overheadDyn + Kp * overheadMac + Kp * 12 * 2 * 10)
530 NS_ABORT_MSG_IF(availableCapacity * 1e6 * slotLength.GetSeconds() <=
531 Kp * m_overheadDyn + Kp * overheadMac + Kp * 12 * 2 * 10,
532 "Not enough fronthaul capacity to send intra-PHY split overhead");
534 uint32_t num =
static_cast<uint32_t
>(availableCapacity * 1e6 * slotLength.GetSeconds() -
535 Kp * m_overheadDyn - Kp * overheadMac - Kp * 12 * 2 * 10);
541 num / (12 * Kp * modulationOrder * dlRank) /
542 static_cast<uint32_t
>(
543 m_fhSchedSapUser.at(bwpId)
544 ->GetNumRbPerRbgFromSched());
546 NS_LOG_DEBUG(
"Scheduler GetMaxRegAssignable " << nMax <<
" for UE " << rnti <<
" with mcs "
553NrFhControl::DoUpdateTracesBasedOnDroppedData(uint16_t bwpId,
561 nRbgs *
static_cast<uint32_t
>(m_fhSchedSapUser.at(bwpId)->GetNumRbPerRbgFromSched());
564 NS_LOG_DEBUG(
"Update Traces based on Dropped Data");
566 if (m_reqFhDlThrTracedValuePerBwp.find(bwpId) == m_reqFhDlThrTracedValuePerBwp.end())
568 NS_LOG_DEBUG(
"Create pair for"
569 <<
" m_reqFhDlThrTracedValuePerBwp.at(" << bwpId
570 <<
"): " << GetFhThr(bwpId, mcs, (numRbs * nSymb), dlRank));
572 m_reqFhDlThrTracedValuePerBwp[bwpId] += GetFhThr(bwpId, mcs, (numRbs * nSymb), dlRank);
573 NS_LOG_DEBUG(
"Update m_reqFhDlThrTracedValuePerBwp.at("
574 << bwpId <<
"): " << m_reqFhDlThrTracedValuePerBwp.at(bwpId));
576 if (m_rbsAirTracedValue.find(bwpId) == m_rbsAirTracedValue.end())
578 NS_LOG_DEBUG(
"Create pair for m_rbsAirTracedValue.at(" << bwpId <<
"): " << numRbs
581 m_rbsAirTracedValue[bwpId] += numRbs;
582 NS_LOG_DEBUG(
"Update m_rbsAirTracedValue.at(" << bwpId <<
"): " << m_rbsAirTracedValue.at(bwpId)
587NrFhControl::DoNotifyEndSlot(uint16_t bwpId, SfnSf currentSlot)
590 if (currentSlot == m_waitingSlotPerBwp.at(bwpId))
592 NS_LOG_INFO(currentSlot);
595 if (m_reqFhDlThrTracedValuePerBwp.find(bwpId) == m_reqFhDlThrTracedValuePerBwp.end())
597 m_reqFhDlThrTrace(currentSlot, m_physicalCellId, bwpId, 0);
598 NS_LOG_DEBUG(
"Size 0, bwpId: " << bwpId <<
" FH DL Throughput 0");
602 NS_LOG_INFO(
"Req FH DL thr at end slot for m_reqFhDlThrTracedValuePerBwp.at("
603 << bwpId <<
"): " << m_reqFhDlThrTracedValuePerBwp.at(bwpId));
604 m_reqFhDlThrTrace(currentSlot,
607 m_reqFhDlThrTracedValuePerBwp.at(
612 if (m_rbsAirTracedValue.empty())
614 m_rbsAirTrace(currentSlot,
618 NS_LOG_DEBUG(
"Size 0, bwpId: " << bwpId
619 <<
" Average RBs used at the end of slot: " << rbSum);
623 for (std::pair<uint16_t, uint32_t> element : m_rbsAirTracedValue)
625 rbSum += element.second;
627 rbSum = rbSum / m_rbsAirTracedValue.size();
628 m_rbsAirTrace(currentSlot,
632 NS_LOG_DEBUG(
"Average RBs used at the end of slot: " << rbSum);
635 NS_LOG_DEBUG(
"Reset traces for next slot");
636 m_reqFhDlThrTracedValuePerBwp.erase(bwpId);
637 m_rbsAirTracedValue.erase(bwpId);
638 m_allocThrPerCell = 0;
639 m_allocThrPerBwp.erase(bwpId);
640 m_waitingSlotPerBwp.at(bwpId).Add(1);
645NrFhControl::GetFhThr(uint16_t bwpId, uint32_t mcs, uint32_t nRegs, uint8_t dlRank)
const
648 uint32_t modulationOrder =
649 m_mcsTable == 1 ? GetModulationOrderTable1(mcs) : GetModulationOrderTable2(mcs);
651 uint16_t numerology = m_fhPhySapUser.at(bwpId)->GetNumerology();
652 NS_ASSERT_MSG(numerology == m_numerologyPerBwp.at(bwpId),
653 " Numerology has not been configured properly for bwpId: " << bwpId);
655 MicroSeconds(
static_cast<uint16_t
>(1000 / std::pow(2, numerology)));
656 uint32_t overheadMac =
static_cast<uint32_t
>(
657 10e6 * 1e-3 / std::pow(2, numerology));
659 thr = (12 * modulationOrder * nRegs * dlRank + m_overheadDyn + overheadMac + 12 * 2 * 10) /
660 slotLength.GetSeconds();
666NrFhControl::GetMaxMcs(uint8_t mcsTable, uint16_t modOrder)
const
673 mcsMax = GetMcsTable1(0);
675 else if (modOrder >= 4 && modOrder < 6)
677 mcsMax = GetMcsTable1(1);
679 else if (modOrder >= 6)
681 mcsMax = GetMcsTable1(2);
684 else if (m_mcsTable == 2)
688 mcsMax = GetMcsTable2(0);
690 else if (modOrder >= 4 && modOrder < 6)
692 mcsMax = GetMcsTable2(1);
694 else if (modOrder >= 6 && modOrder < 8)
696 mcsMax = GetMcsTable2(2);
698 else if (modOrder >= 8)
700 mcsMax = GetMcsTable2(3);
707NrFhControl::GetModulationOrderTable1(
const uint32_t mcs)
const
709 std::vector<uint8_t> McsMTable1 = {
741 return McsMTable1.at(mcs);
745NrFhControl::GetModulationOrderTable2(
const uint32_t mcs)
const
747 NS_ASSERT_MSG(mcs <= 27,
"MCS must be up to 27");
748 std::vector<uint8_t> McsMTable2 = {
780 return McsMTable2.at(mcs);
784NrFhControl::GetMcsTable1(
const uint8_t modOrd)
const
786 std::vector<uint8_t> McsTable1 = {
792 return McsTable1.at(modOrd);
796NrFhControl::GetMcsTable2(
const uint8_t modOrd)
const
798 std::vector<uint8_t> McsTable2 = {
806 return McsTable2.at(modOrd);
friend class MemberNrFhSchedSapProvider< NrFhControl >
let the forwarder class access the protected and private members
void SetNrFhPhySapUser(uint16_t bwpId, NrFhPhySapUser *s)
Set the Fh control - PHY SAP User PHY is per bwp as such we store in a map the bwpId and the correspo...
NrFhPhySapProvider * GetNrFhPhySapProvider()
Get the Fh control - PHY SAP User ptr.
void SetCellFhCapacity(uint32_t capacity)
Set the available fronthaul capacity of the cell. Notice that throughout the code,...
void SetErrorModelType(std::string errorModelType)
Set the ErrorModelType based on which the MCS Table (1 or 2) will be set." "ns3::NrEesmIrT1 an...
~NrFhControl() override
~NrFhControl deconstructor
NrFhControl()
NrFhControl constructor.
friend class MemberNrFhPhySapProvider< NrFhControl >
let the forwarder class access the protected and private members
NrFhSchedSapProvider * GetNrFhSchedSapProvider()
Get the Fh control - Sched SAP User ptr.
void SetOverheadDyn(uint8_t overhead)
Set the overhead for dynamic modulation compression.
FhControlMethod
The optimization models (FH Control method) of the NrFhControl.
@ Postponing
Postpone sending data (MAC Layer)
@ OptimizeRBs
Optimize RBs allocated.
@ Dropping
Drop DCI + DATA at the PHY Layer.
@ OptimizeMcs
Optimize MCS.
static TypeId GetTypeId()
GetTypeId.
void SetPhysicalCellId(uint16_t physCellId)
Set the physical cell Id of the cell to which this NrFhControl instance belongs to.
void SetFhNumerology(uint16_t bwpId, uint16_t num)
Set the numerology.
void SetFhControlMethod(FhControlMethod model)
Set the FH Control method type.
void SetNrFhSchedSapUser(uint16_t bwpId, NrFhSchedSapUser *s)
Set the Fh control - Sched SAP User Sched is per bwp as such we store in a map the bwpId and the corr...
Service Access Point (SAP) offered by the FhControl instance to the gnb PHY instance.
Service Access Point (SAP) offered by the gnb PHY instance to the FhControl instance.
Service Access Point (SAP) offered by the FhControl instance to the MAC Scheduler instance.
Service Access Point (SAP) offered by the MAC Scheduler instance to the FhControl instance.
@ DATA
Used for DL/UL DATA.