5G-LENA nr-v3.3-159-ga6832aa7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-mac-scheduler-lcg.cc
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include "nr-mac-scheduler-lcg.h"
6
7#include "nr-eps-bearer.h"
8
9#include "ns3/log.h"
10
11namespace ns3
12{
13
14NS_LOG_COMPONENT_DEFINE("NrMacSchedulerLCG");
15
17 : m_id(conf.m_logicalChannelIdentity)
18{
19 NrEpsBearer bearer(static_cast<NrEpsBearer::Qci>(conf.m_qci));
20
21 m_delayBudget = MilliSeconds(bearer.GetPacketDelayBudgetMs());
24 m_qci = conf.m_qci;
25 m_priority = bearer.GetPriority();
27}
28
29void
40
41uint32_t
46
48// NrMacSchedulerLCG
49
51 : m_id(id)
52{
53 NS_LOG_FUNCTION(this);
54 (void)m_id;
55}
56
57bool
58NrMacSchedulerLCG::Contains(uint8_t lcId) const
59{
60 NS_LOG_FUNCTION(this);
61 return m_lcMap.find(lcId) != m_lcMap.end();
62}
63
64uint32_t
66{
67 NS_LOG_FUNCTION(this);
68 return static_cast<uint32_t>(m_lcMap.size());
69}
70
71bool
73{
74 NS_LOG_FUNCTION(this);
75 NS_ASSERT(!Contains(lc->m_id));
76 return m_lcMap.emplace(lc->m_id, std::move(lc)).second;
77}
78
79void
81{
82 NS_LOG_FUNCTION(this);
83 NS_ASSERT(Contains(params.m_logicalChannelIdentity));
84 m_lcMap.at(params.m_logicalChannelIdentity)->Update(params);
85}
86
87void
88NrMacSchedulerLCG::UpdateInfo(uint32_t lcgQueueSize)
89{
90 NS_LOG_FUNCTION(this);
91 NS_ABORT_IF(m_lcMap.size() > 1);
92 uint32_t lcIdPart = lcgQueueSize / m_lcMap.size();
93
94 for (auto& lc : m_lcMap)
95 {
96 lc.second->m_rlcTransmissionQueueSize = lcIdPart;
97 }
98}
99
100uint32_t
102{
103 NS_LOG_FUNCTION(this);
104 uint32_t totalSize = 0;
105 for (const auto& lc : m_lcMap)
106 {
107 totalSize += lc.second->GetTotalSize();
108 }
109 NS_LOG_INFO("Total size: " << totalSize);
110 return totalSize;
111}
112
113uint32_t
115{
116 NS_LOG_FUNCTION(this);
117 NS_ABORT_IF(m_lcMap.empty());
118 return m_lcMap.at(lcId)->GetTotalSize();
119}
120
121std::vector<uint8_t>
123{
124 std::vector<uint8_t> ret;
125 ret.reserve(m_lcMap.size());
126 for (const auto& lc : m_lcMap)
127 {
128 ret.emplace_back(lc.first);
129 }
130 return ret;
131}
132
133std::vector<uint8_t>
135{
136 NS_LOG_FUNCTION(this);
137 std::vector<uint8_t> ret;
138 for (const auto& lc : m_lcMap)
139 {
140 if (GetTotalSizeOfLC(lc.first) > 0)
141 {
142 ret.emplace_back(lc.first);
143 }
144 }
145 return ret;
146}
147
148uint8_t
149NrMacSchedulerLCG::GetQci(uint8_t lcId) const
150{
151 NS_LOG_FUNCTION(this);
152 return m_lcMap.at(lcId)->m_qci;
153}
154
155std::unique_ptr<NrMacSchedulerLC>&
157{
158 NS_LOG_FUNCTION(this);
159
160 NS_ASSERT(!m_lcMap.empty());
161 NS_ASSERT(GetTotalSizeOfLC(lcId) > 0);
162
163 return m_lcMap.at(lcId);
164}
165
166void
167NrMacSchedulerLCG::AssignedData(uint8_t lcId, uint32_t size, std::string type)
168{
169 NS_LOG_FUNCTION(this);
170 NS_ASSERT(!m_lcMap.empty());
171
172 NS_LOG_INFO("Assigning " << size << " bytes to lcId: " << +lcId);
173 // Update queues: RLC tx order Status, ReTx, Tx. To understand this, you have
174 // to see RlcAm::NotifyTxOpportunity
175 NS_LOG_INFO("Status of LCID " << static_cast<uint32_t>(lcId)
176 << " before: RLC PDU =" << m_lcMap.at(lcId)->m_rlcStatusPduSize
177 << ", RLC RX=" << m_lcMap.at(lcId)->m_rlcRetransmissionQueueSize
178 << ", RLC TX=" << m_lcMap.at(lcId)->m_rlcTransmissionQueueSize);
179
180 if ((m_lcMap.at(lcId)->m_rlcStatusPduSize > 0) &&
181 (size >= m_lcMap.at(lcId)->m_rlcStatusPduSize))
182 {
183 m_lcMap.at(lcId)->m_rlcStatusPduSize = 0;
184 }
185 else if ((m_lcMap.at(lcId)->m_rlcRetransmissionQueueSize > 0) &&
186 (size >= m_lcMap.at(lcId)->m_rlcRetransmissionQueueSize))
187 {
188 m_lcMap.at(lcId)->m_rlcRetransmissionQueueSize = 0;
189 }
190 else if (m_lcMap.at(lcId)->m_rlcTransmissionQueueSize >
191 0) // if not enough size for retransmission use if for transmission if there is any
192 // data to be transmitted
193 {
194 uint32_t rlcOverhead = 0;
195 // The following logic of selecting the overhead is
196 // inherited from the LTE module scheduler API
197 if (lcId == 1 && type == "DL")
198 {
199 // for SRB1 (using RLC AM) it's better to
200 // overestimate RLC overhead rather than
201 // underestimate it and risk unneeded
202 // segmentation which increases delay
203 rlcOverhead = 4;
204 }
205 else
206 {
207 // minimum RLC overhead due to header
208 rlcOverhead = 2;
209 }
210
211 if (size - rlcOverhead >= m_lcMap.at(lcId)->m_rlcTransmissionQueueSize)
212 {
213 // we can transmit everything from the queue, reset it
214 m_lcMap.at(lcId)->m_rlcTransmissionQueueSize = 0;
215 }
216 else
217 {
218 // not enough to empty all queue, but send what you can, this is normal situation to
219 // happen
220 m_lcMap.at(lcId)->m_rlcTransmissionQueueSize -= size - rlcOverhead;
221 }
222
223 // If there are 5 bytes the RLC TX queue info at MAC, MAC will assign 5 bytes Tx
224 // opportunity, but NrRlcAm will complain that the minimum TX opportunity should be at
225 // least 7 bytes. To be sure that the MAC scheduler will assign at least 7 bytes (so that 5
226 // bytes can be transmitted), we tell here to MAC that there are 7 bytes in the queue
227 // instead of e.g. 5 bytes. Yeah, this is a workaround, because MAC and RLC have to be "on
228 // the same page". We however should take into account the next UL SHORT_BSR (we add 5
229 // bytes, because in the current TX opportunity 5 bytes is being spent on SHORT_BSR).
230
231 if (type == "UL" && m_lcMap.at(lcId)->m_rlcTransmissionQueueSize > 0 &&
232 m_lcMap.at(lcId)->m_rlcTransmissionQueueSize < 12)
233 {
234 m_lcMap.at(lcId)->m_rlcTransmissionQueueSize = 12;
235 }
236
237 // in order to take into account the MAC header of 3 bytes
238 // 10 -3 = 7 which is the minimum allowed TX opportunity by RLC AM
239 if (type == "DL" && m_lcMap.at(lcId)->m_rlcTransmissionQueueSize > 0 &&
240 m_lcMap.at(lcId)->m_rlcTransmissionQueueSize < 10)
241 {
242 m_lcMap.at(lcId)->m_rlcTransmissionQueueSize = 10;
243 }
244 }
245 else
246 {
247 NS_LOG_WARN(" This opportunity cannot be used, not enough bytes to perform retransmission "
248 "or not active flows.");
249 }
250
251 NS_LOG_INFO("Status of LCID " << static_cast<uint32_t>(lcId)
252 << " after: RLC PDU=" << m_lcMap.at(lcId)->m_rlcStatusPduSize
253 << ", RLC RX=" << m_lcMap.at(lcId)->m_rlcRetransmissionQueueSize
254 << ", RLC TX=" << m_lcMap.at(lcId)->m_rlcTransmissionQueueSize);
255}
256
257void
258NrMacSchedulerLCG::ReleaseLC(uint8_t lcId)
259{
260 m_lcMap.erase(lcId);
261}
262
263} // namespace ns3
This class contains the specification of EPS Bearers.
uint16_t GetPacketDelayBudgetMs() const
uint8_t GetPriority() const
uint8_t GetResourceType() const
double GetPacketErrorLossRate() const
uint32_t NumOfLC() const
Get the number of LC currently in the LCG.
NrMacSchedulerLCG(uint8_t id)
NrMacSchedulerLCG constructor.
bool Insert(LCPtr &&lc)
Insert LC in the group.
std::vector< uint8_t > GetActiveLCIds() const
Get a vector of the active LC IDs.
std::unique_ptr< NrMacSchedulerLC > & GetLC(uint8_t lcId)
Get the LC Ptr for a specific LC ID.
bool Contains(uint8_t lcId) const
Check if the LCG contains the LC id specified.
uint32_t GetTotalSize() const
Get the total size of the LCG.
uint8_t GetQci(uint8_t lcId) const
Get the QoS Class Identifier of the flow.
std::vector< uint8_t > GetLCId() const
Get a vector of LC ID.
void UpdateInfo(const NrMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
Update the LCG with a message coming from RLC in the gNB.
uint32_t GetTotalSizeOfLC(uint8_t lcId) const
Get TotalSize Of LC.
void AssignedData(uint8_t lcId, uint32_t size, std::string type)
Inform the LCG of the assigned data to a LC id.
void Update(const NrMacSchedSapProvider::SchedDlRlcBufferReqParameters &params)
Overwrite all the parameters with the one contained in the message.
uint8_t m_resourceType
the resource type associated with the QCI of the flow
uint64_t m_eRabGuaranteedBitrateDl
ERAB guaranteed bit rate DL.
uint32_t GetTotalSize() const
Get the total size of the LC.
double m_PER
PER of the flow.
uint8_t m_qci
QoS Class Identifier of the flow.
uint32_t m_rlcTransmissionQueueSize
The current size of the new transmission queue in byte.
NrMacSchedulerLC()=delete
NrMacSchedulerLC default constructor (deletec)
uint16_t m_rlcTransmissionQueueHolDelay
Head of line delay of new transmissions in ms.
uint16_t m_rlcRetransmissionHolDelay
Head of line delay of retransmissions in ms.
uint32_t m_rlcRetransmissionQueueSize
The current size of the retransmission queue in byte.
uint16_t m_rlcStatusPduSize
The current size of the pending STATUS message in byte.
Time m_delayBudget
Delay budget of the flow.
uint32_t m_id
ID of the LC.
uint8_t m_priority
the priority associated with the QCI of the flow 3GPP 23.203
std::unique_ptr< NrMacSchedulerLC > LCPtr
Unique pointer to an instance of NrMacSchedulerLC.
uint16_t m_rlcTransmissionQueueHolDelay
Head of line delay of new transmissions in ms.
uint8_t m_logicalChannelIdentity
The logical channel ID, range: 0..10.
uint16_t m_rlcRetransmissionHolDelay
Head of line delay of retransmissions in ms.
uint32_t m_rlcRetransmissionQueueSize
The current size of the retransmission queue in byte.
uint16_t m_rlcStatusPduSize
The current size of the pending STATUS message in byte.
uint32_t m_rlcTransmissionQueueSize
The current size of the new transmission queue in byte.
See section 4.3.4 logicalChannelConfigListElement.
uint64_t m_eRabGuaranteedBitrateDl
ERAB guaranteed bit rate DL.