5G-LENA nr-v4.0
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-rlc-um.cc
1// Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4//
5// Author: Manuel Requena <manuel.requena@cttc.es>
6
7#include "nr-rlc-um.h"
8
9#include "nr-rlc-header.h"
10#include "nr-rlc-sdu-status-tag.h"
11#include "nr-rlc-tag.h"
12
13#include "ns3/log.h"
14#include "ns3/simulator.h"
15
16namespace ns3
17{
18
19NS_LOG_COMPONENT_DEFINE("NrRlcUm");
20
21NS_OBJECT_ENSURE_REGISTERED(NrRlcUm);
22
23NrRlcUm::NrRlcUm()
24 : m_maxTxBufferSize(10 * 1024),
25 m_txBufferSize(0),
26 m_sequenceNumber(0),
27 m_vrUr(0),
28 m_vrUx(0),
29 m_vrUh(0),
30 m_windowSize(512),
31 m_expectedSeqNumber(0)
32{
33 NS_LOG_FUNCTION(this);
34 m_reassemblingState = WAITING_S0_FULL;
35}
36
37NrRlcUm::~NrRlcUm()
38{
39 NS_LOG_FUNCTION(this);
40}
41
42TypeId
43NrRlcUm::GetTypeId()
44{
45 static TypeId tid =
46 TypeId("ns3::NrRlcUm")
47 .SetParent<NrRlc>()
48 .SetGroupName("Nr")
49 .AddConstructor<NrRlcUm>()
50 .AddAttribute("MaxTxBufferSize",
51 "Maximum Size of the Transmission Buffer (in Bytes)",
52 UintegerValue(10 * 1024),
53 MakeUintegerAccessor(&NrRlcUm::m_maxTxBufferSize),
54 MakeUintegerChecker<uint32_t>())
55 .AddAttribute("ReorderingTimer",
56 "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
57 TimeValue(MilliSeconds(100)),
58 MakeTimeAccessor(&NrRlcUm::m_reorderingTimerValue),
59 MakeTimeChecker())
60 .AddAttribute(
61 "EnablePdcpDiscarding",
62 "Whether to use the PDCP discarding, i.e., perform discarding at the moment "
63 "of passing the PDCP SDU to RLC)",
64 BooleanValue(true),
65 MakeBooleanAccessor(&NrRlcUm::m_enablePdcpDiscarding),
66 MakeBooleanChecker())
67 .AddAttribute("DiscardTimerMs",
68 "Discard timer in milliseconds to be used to discard packets. "
69 "If set to 0 then packet delay budget will be used as the discard "
70 "timer value, otherwise it will be used this value.",
71 UintegerValue(0),
72 MakeUintegerAccessor(&NrRlcUm::m_discardTimerMs),
73 MakeUintegerChecker<uint32_t>())
74 .AddAttribute("OutOfOfOrderDelivery",
75 "Whether to deliver RLC SDUs out of order without waiting for a "
76 "reordering timer to expire",
77 BooleanValue(false),
78 MakeBooleanAccessor(&NrRlcUm::m_outOfOrderDelivery),
79 MakeBooleanChecker());
80 return tid;
81}
82
83void
84NrRlcUm::DoDispose()
85{
86 NS_LOG_FUNCTION(this);
87 m_reorderingTimer.Cancel();
88 m_bsrTimer.Cancel();
89
90 NrRlc::DoDispose();
91}
92
97void
98NrRlcUm::DoTransmitPdcpPdu(Ptr<Packet> p)
99{
100 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << p->GetSize());
101 if (m_txBufferSize + p->GetSize() <= m_maxTxBufferSize)
102 {
103 if (m_enablePdcpDiscarding)
104 {
105 // discart the packet
106 uint32_t headOfLineDelayInMs = 0;
107 uint32_t discardTimerMs =
108 (m_discardTimerMs > 0) ? m_discardTimerMs : m_packetDelayBudgetMs;
109
110 if (!m_txBuffer.empty())
111 {
112 headOfLineDelayInMs =
113 (Simulator::Now() - m_txBuffer.begin()->m_waitingSince).GetMilliSeconds();
114 }
115 NS_LOG_DEBUG("head of line delay in MS:" << headOfLineDelayInMs);
116 if (headOfLineDelayInMs > discardTimerMs)
117 {
118 NS_LOG_INFO("Tx HOL is higher than this packet can allow. RLC SDU discarded");
119 NS_LOG_DEBUG("headOfLineDelayInMs = " << headOfLineDelayInMs);
120 NS_LOG_DEBUG("m_packetDelayBudgetMs = " << m_packetDelayBudgetMs);
121 NS_LOG_DEBUG("packet size = " << p->GetSize());
122 m_txDropTrace(p);
123 }
124 }
125
128 tag.SetStatus(NrRlcSduStatusTag::FULL_SDU);
129 p->AddPacketTag(tag);
130 NS_LOG_INFO("Adding RLC SDU to Tx Buffer after adding NrRlcSduStatusTag: FULL_SDU");
131 m_txBuffer.emplace_back(p, Simulator::Now());
132 m_txBufferSize += p->GetSize();
133 NS_LOG_LOGIC("NumOfBuffers = " << m_txBuffer.size());
134 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
135 }
136 else
137 {
138 // Discard full RLC SDU
139 NS_LOG_INFO("Tx Buffer is full. RLC SDU discarded");
140 NS_LOG_LOGIC("MaxTxBufferSize = " << m_maxTxBufferSize);
141 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
142 NS_LOG_LOGIC("packet size = " << p->GetSize());
143 m_txDropTrace(p);
144 }
145
147 DoTransmitBufferStatusReport();
148 m_bsrTimer.Cancel();
149}
150
155void
156NrRlcUm::DoNotifyTxOpportunity(NrMacSapUser::TxOpportunityParameters txOpParams)
157{
158 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << txOpParams.bytes);
159 NS_LOG_INFO("RLC layer is preparing data for the following Tx opportunity of "
160 << txOpParams.bytes << " bytes for RNTI=" << m_rnti << ", LCID=" << (uint32_t)m_lcid
161 << ", CCID=" << (uint32_t)txOpParams.componentCarrierId << ", HARQ ID="
162 << (uint32_t)txOpParams.harqId << ", MIMO Layer=" << (uint32_t)txOpParams.layer);
163
164 if (txOpParams.bytes <= 2)
165 {
166 // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
167 NS_LOG_INFO("TX opportunity too small - Only " << txOpParams.bytes << " bytes");
168 return;
169 }
170
171 Ptr<Packet> packet = Create<Packet>();
172 NrRlcHeader rlcHeader;
173
174 // Build Data field
175 uint32_t nextSegmentSize = txOpParams.bytes - 2;
176 uint32_t nextSegmentId = 1;
177 uint32_t dataFieldAddedSize = 0;
178 std::vector<Ptr<Packet>> dataField;
179
180 // Remove the first packet from the transmission buffer.
181 // If only a segment of the packet is taken, then the remaining is given back later
182 if (m_txBuffer.empty())
183 {
184 NS_LOG_LOGIC("No data pending");
185 return;
186 }
187
188 Ptr<Packet> firstSegment = m_txBuffer.begin()->m_pdu->Copy();
189 Time firstSegmentTime = m_txBuffer.begin()->m_waitingSince;
190
191 NS_LOG_LOGIC("SDUs in TxBuffer = " << m_txBuffer.size());
192 NS_LOG_LOGIC("First SDU buffer = " << firstSegment);
193 NS_LOG_LOGIC("First SDU size = " << firstSegment->GetSize());
194 NS_LOG_LOGIC("Next segment size = " << nextSegmentSize);
195 NS_LOG_LOGIC("Remove SDU from TxBuffer");
196 m_txBufferSize -= firstSegment->GetSize();
197 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
198 m_txBuffer.erase(m_txBuffer.begin());
199
200 while (firstSegment && (firstSegment->GetSize() > 0) && (nextSegmentSize > 0))
201 {
202 NS_LOG_LOGIC("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
203 NS_LOG_LOGIC(" firstSegment size = " << firstSegment->GetSize());
204 NS_LOG_LOGIC(" nextSegmentSize = " << nextSegmentSize);
205 if ((firstSegment->GetSize() > nextSegmentSize) ||
206 // Segment larger than 2047 octets can only be mapped to the end of the Data field
207 (firstSegment->GetSize() > 2047))
208 {
209 // Take the minimum size, due to the 2047-bytes 3GPP exception
210 // This exception is due to the length of the LI field (just 11 bits)
211 uint32_t currSegmentSize = std::min(firstSegment->GetSize(), nextSegmentSize);
212
213 NS_LOG_LOGIC(" IF ( firstSegment > nextSegmentSize ||");
214 NS_LOG_LOGIC(" firstSegment > 2047 )");
215
216 // Segment txBuffer.FirstBuffer and
217 // Give back the remaining segment to the transmission buffer
218 Ptr<Packet> newSegment = firstSegment->CreateFragment(0, currSegmentSize);
219 NS_LOG_LOGIC(" newSegment size = " << newSegment->GetSize());
220
221 // Status tag of the new and remaining segments
222 // Note: This is the only place where a PDU is segmented and
223 // therefore its status can change
224 NrRlcSduStatusTag oldTag;
225 NrRlcSduStatusTag newTag;
226 firstSegment->RemovePacketTag(oldTag);
227 newSegment->RemovePacketTag(newTag);
228 if (oldTag.GetStatus() == NrRlcSduStatusTag::FULL_SDU)
229 {
230 newTag.SetStatus(NrRlcSduStatusTag::FIRST_SEGMENT);
231 oldTag.SetStatus(NrRlcSduStatusTag::LAST_SEGMENT);
232 }
233 else if (oldTag.GetStatus() == NrRlcSduStatusTag::LAST_SEGMENT)
234 {
235 newTag.SetStatus(NrRlcSduStatusTag::MIDDLE_SEGMENT);
236 // oldTag.SetStatus (NrRlcSduStatusTag::LAST_SEGMENT);
237 }
238
239 // Give back the remaining segment to the transmission buffer
240 firstSegment->RemoveAtStart(currSegmentSize);
241 NS_LOG_LOGIC(
242 " firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize());
243 if (firstSegment->GetSize() > 0)
244 {
245 firstSegment->AddPacketTag(oldTag);
246
247 m_txBuffer.insert(m_txBuffer.begin(), TxPdu(firstSegment, firstSegmentTime));
248 m_txBufferSize += m_txBuffer.begin()->m_pdu->GetSize();
249
250 NS_LOG_LOGIC(" TX buffer: Give back the remaining segment");
251 NS_LOG_LOGIC(" TX buffers = " << m_txBuffer.size());
252 NS_LOG_LOGIC(" Front buffer size = " << m_txBuffer.begin()->m_pdu->GetSize());
253 NS_LOG_LOGIC(" txBufferSize = " << m_txBufferSize);
254 }
255 else
256 {
257 // Whole segment was taken, so adjust tag
258 if (newTag.GetStatus() == NrRlcSduStatusTag::FIRST_SEGMENT)
259 {
260 newTag.SetStatus(NrRlcSduStatusTag::FULL_SDU);
261 }
262 else if (newTag.GetStatus() == NrRlcSduStatusTag::MIDDLE_SEGMENT)
263 {
264 newTag.SetStatus(NrRlcSduStatusTag::LAST_SEGMENT);
265 }
266 }
267 // Segment is completely taken or
268 // the remaining segment is given back to the transmission buffer
269 firstSegment = nullptr;
270
271 // Put status tag once it has been adjusted
272 newSegment->AddPacketTag(newTag);
273
274 // Add Segment to Data field
275 dataFieldAddedSize = newSegment->GetSize();
276 dataField.push_back(newSegment);
277 newSegment = nullptr;
278
279 // ExtensionBit (Next_Segment - 1) = 0
280 rlcHeader.PushExtensionBit(NrRlcHeader::DATA_FIELD_FOLLOWS);
281
282 // no LengthIndicator for the last one
283
284 nextSegmentSize -= dataFieldAddedSize;
285 nextSegmentId++;
286
287 // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
288
289 // (NO more segments) → exit
290 // break;
291 }
292 else if ((nextSegmentSize - firstSegment->GetSize() <= 2) || m_txBuffer.empty())
293 {
294 NS_LOG_LOGIC(
295 " IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
296 // Add txBuffer.FirstBuffer to DataField
297 dataFieldAddedSize = firstSegment->GetSize();
298 dataField.push_back(firstSegment);
299 firstSegment = nullptr;
300
301 // ExtensionBit (Next_Segment - 1) = 0
302 rlcHeader.PushExtensionBit(NrRlcHeader::DATA_FIELD_FOLLOWS);
303
304 // no LengthIndicator for the last one
305
306 nextSegmentSize -= dataFieldAddedSize;
307 nextSegmentId++;
308
309 NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txBuffer.size());
310 if (!m_txBuffer.empty())
311 {
312 NS_LOG_LOGIC(" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
313 NS_LOG_LOGIC(
314 " First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize());
315 }
316 NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
317
318 // nextSegmentSize <= 2 (only if txBuffer is not empty)
319
320 // (NO more segments) → exit
321 // break;
322 }
323 else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
324 {
325 NS_LOG_LOGIC(" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
326 // Add txBuffer.FirstBuffer to DataField
327 dataFieldAddedSize = firstSegment->GetSize();
328 dataField.push_back(firstSegment);
329
330 // ExtensionBit (Next_Segment - 1) = 1
331 rlcHeader.PushExtensionBit(NrRlcHeader::E_LI_FIELDS_FOLLOWS);
332
333 // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
334 rlcHeader.PushLengthIndicator(firstSegment->GetSize());
335
336 nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
337 nextSegmentId++;
338
339 NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txBuffer.size());
340 if (!m_txBuffer.empty())
341 {
342 NS_LOG_LOGIC(" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
343 NS_LOG_LOGIC(
344 " First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize());
345 }
346 NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
347 NS_LOG_LOGIC(" Remove SDU from TxBuffer");
348
349 // (more segments)
350 firstSegment = m_txBuffer.begin()->m_pdu->Copy();
351 firstSegmentTime = m_txBuffer.begin()->m_waitingSince;
352 m_txBufferSize -= firstSegment->GetSize();
353 m_txBuffer.pop_front();
354 NS_LOG_LOGIC(" txBufferSize = " << m_txBufferSize);
355 }
356 }
357
358 // Build RLC header
359 rlcHeader.SetSequenceNumber(m_sequenceNumber++);
360
361 // Build RLC PDU with DataField and Header
362 auto it = dataField.begin();
363
364 uint8_t framingInfo = 0;
365
366 // FIRST SEGMENT
368 NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "NrRlcSduStatusTag is missing");
369 (*it)->PeekPacketTag(tag);
370 if ((tag.GetStatus() == NrRlcSduStatusTag::FULL_SDU) ||
371 (tag.GetStatus() == NrRlcSduStatusTag::FIRST_SEGMENT))
372 {
373 framingInfo |= NrRlcHeader::FIRST_BYTE;
374 }
375 else
376 {
377 framingInfo |= NrRlcHeader::NO_FIRST_BYTE;
378 }
379
380 while (it < dataField.end())
381 {
382 NS_LOG_LOGIC("Adding SDU/segment to packet, length = " << (*it)->GetSize());
383
384 NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "NrRlcSduStatusTag is missing");
385 (*it)->RemovePacketTag(tag);
386 if (packet->GetSize() > 0)
387 {
388 packet->AddAtEnd(*it);
389 }
390 else
391 {
392 packet = (*it);
393 }
394 it++;
395 }
396
397 // LAST SEGMENT (Note: There could be only one and be the first one)
398 it--;
399 if ((tag.GetStatus() == NrRlcSduStatusTag::FULL_SDU) ||
400 (tag.GetStatus() == NrRlcSduStatusTag::LAST_SEGMENT))
401 {
402 framingInfo |= NrRlcHeader::LAST_BYTE;
403 }
404 else
405 {
406 framingInfo |= NrRlcHeader::NO_LAST_BYTE;
407 }
408
409 rlcHeader.SetFramingInfo(framingInfo);
410
411 NS_LOG_LOGIC("RLC header: " << rlcHeader);
412 packet->AddHeader(rlcHeader);
413
414 // Sender timestamp
415 NrRlcTag rlcTag(Simulator::Now());
416 packet->AddByteTag(rlcTag, 1, rlcHeader.GetSerializedSize());
417 m_txPdu(m_rnti, m_lcid, packet->GetSize());
418
419 // Send RLC PDU to MAC layer
421 params.pdu = packet;
422 params.rnti = m_rnti;
423 params.lcid = m_lcid;
424 params.layer = txOpParams.layer;
425 params.harqProcessId = txOpParams.harqId;
426 params.componentCarrierId = txOpParams.componentCarrierId;
427
428 NS_LOG_INFO("Forward RLC PDU to MAC Layer");
429 m_macSapProvider->TransmitPdu(params);
430
431 if (!m_txBuffer.empty())
432 {
433 m_bsrTimer.Cancel();
434 m_bsrTimer = Simulator::Schedule(MilliSeconds(10), &NrRlcUm::ExpireBsrTimer, this);
435 }
436}
437
438void
439NrRlcUm::DoNotifyHarqDeliveryFailure()
440{
441 NS_LOG_FUNCTION(this);
442}
443
444void
445NrRlcUm::DoReceivePdu(NrMacSapUser::ReceivePduParameters rxPduParams)
446{
447 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << rxPduParams.p->GetSize());
448
449 // Receiver timestamp
450 NrRlcTag rlcTag;
451 Time delay;
452
453 bool ret = rxPduParams.p->FindFirstMatchingByteTag(rlcTag);
454 NS_ASSERT_MSG(ret, "NrRlcTag is missing");
455
456 delay = Simulator::Now() - rlcTag.GetSenderTimestamp();
457 m_rxPdu(m_rnti, m_lcid, rxPduParams.p->GetSize(), delay.GetNanoSeconds());
458
459 // 5.1.2.2 Receive operations
460
461 // Get RLC header parameters
462 NrRlcHeader rlcHeader;
463 rxPduParams.p->PeekHeader(rlcHeader);
464 NS_LOG_LOGIC("RLC header: " << rlcHeader);
465 nr::SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber();
466
467 // 5.1.2.2.1 General
468 // The receiving UM RLC entity shall maintain a reordering window according to state variable
469 // VR(UH) as follows:
470 // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
471 // - a SN falls outside of the reordering window otherwise.
472 // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
473 // - either discard the received UMD PDU or place it in the reception buffer (see sub
474 // clause 5.1.2.2.2);
475 // - if the received UMD PDU was placed in the reception buffer:
476 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop
477 // t-Reordering as needed (see sub clause 5.1.2.2.3); When t-Reordering expires, the receiving
478 // UM RLC entity shall:
479 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start
480 // t-Reordering as needed (see sub clause 5.1.2.2.4).
481
482 // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
483 // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
484 // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
485 // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
486 // - discard the received UMD PDU;
487 // - else:
488 // - place the received UMD PDU in the reception buffer.
489
490 NS_LOG_LOGIC("VR(UR) = " << m_vrUr);
491 NS_LOG_LOGIC("VR(UX) = " << m_vrUx);
492 NS_LOG_LOGIC("VR(UH) = " << m_vrUh);
493 NS_LOG_LOGIC("SN = " << seqNumber);
494
495 m_vrUr.SetModulusBase(m_vrUh - m_windowSize);
496 m_vrUh.SetModulusBase(m_vrUh - m_windowSize);
497 seqNumber.SetModulusBase(m_vrUh - m_windowSize);
498
499 if (((m_vrUr < seqNumber) && (seqNumber < m_vrUh) &&
500 (m_rxBuffer.count(seqNumber.GetValue()) > 0)) ||
501 (((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr)))
502 {
503 NS_LOG_LOGIC("PDU discarded");
504 rxPduParams.p = nullptr;
505 return;
506 }
507 else
508 {
509 NS_LOG_LOGIC("Place PDU in the reception buffer");
510 m_rxBuffer[seqNumber.GetValue()] = rxPduParams.p;
511 }
512
513 // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
514 // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity
515 // shall:
516 // - if rlc-OutOfOrderDelivery is configured:
517 // - if all byte segments of the UMD PDU are received:
518 // - reassemble the RLC SDU using the byte segments of the UMD PDU,
519 // remove RLC headers when doing so and deliver the reassembled RLC
520 // SDU to upper layer if not delivered before;
521
522 if (m_outOfOrderDelivery)
523 {
524 ReassembleOutsideWindow();
525 }
526
527 // - if x falls outside of the reordering window:
528 // - update VR(UH) to x + 1;
529 // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering
530 // window, remove
531 // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in
532 // ascending order of the RLC SN if not delivered before;
533 // - if VR(UR) falls outside of the reordering window:
534 // - set VR(UR) to (VR(UH) - UM_Window_Size);
535
536 if (!IsInsideReorderingWindow(seqNumber))
537 {
538 NS_LOG_LOGIC("SN is outside the reordering window");
539
540 m_vrUh = seqNumber + 1;
541 NS_LOG_LOGIC("New VR(UH) = " << m_vrUh);
542
543 ReassembleOutsideWindow();
544
545 if (!IsInsideReorderingWindow(m_vrUr))
546 {
547 m_vrUr = m_vrUh - m_windowSize;
548 NS_LOG_LOGIC("VR(UR) is outside the reordering window");
549 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
550 }
551 }
552
553 // - if the reception buffer contains an UMD PDU with SN = VR(UR):
554 // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been
555 // received;
556 // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when
557 // doing
558 // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN
559 // if not delivered before;
560
561 if (m_rxBuffer.count(m_vrUr.GetValue()) > 0)
562 {
563 NS_LOG_LOGIC("Reception buffer contains SN = " << m_vrUr);
564
565 uint16_t newVrUr;
566 nr::SequenceNumber10 oldVrUr = m_vrUr;
567
568 auto it = m_rxBuffer.find(m_vrUr.GetValue());
569 newVrUr = (it->first) + 1;
570 while (m_rxBuffer.count(newVrUr) > 0)
571 {
572 newVrUr++;
573 }
574 m_vrUr = newVrUr;
575 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
576
577 ReassembleSnInterval(oldVrUr, m_vrUr);
578 }
579
580 // m_vrUh can change previously, set new modulus base
581 // for the t-Reordering timer-related comparisons
582 m_vrUr.SetModulusBase(m_vrUh - m_windowSize);
583 m_vrUx.SetModulusBase(m_vrUh - m_windowSize);
584 m_vrUh.SetModulusBase(m_vrUh - m_windowSize);
585
586 // - if t-Reordering is running:
587 // - if VR(UX) <= VR(UR); or
588 // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
589 // - stop and reset t-Reordering;
590 if (m_reorderingTimer.IsPending())
591 {
592 NS_LOG_LOGIC("Reordering timer is running");
593
594 if ((m_vrUx <= m_vrUr) || ((!IsInsideReorderingWindow(m_vrUx)) && (m_vrUx != m_vrUh)))
595 {
596 NS_LOG_LOGIC("Stop reordering timer");
597 m_reorderingTimer.Cancel();
598 }
599 }
600
601 // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to
602 // actions above):
603 // - if VR(UH) > VR(UR):
604 // - start t-Reordering;
605 // - set VR(UX) to VR(UH).
606 if (!m_reorderingTimer.IsPending())
607 {
608 NS_LOG_LOGIC("Reordering timer is not running");
609
610 if (m_vrUh > m_vrUr)
611 {
612 NS_LOG_LOGIC("VR(UH) > VR(UR)");
613 NS_LOG_LOGIC("Start reordering timer");
614 m_reorderingTimer =
615 Simulator::Schedule(m_reorderingTimerValue, &NrRlcUm::ExpireReorderingTimer, this);
616 m_vrUx = m_vrUh;
617 NS_LOG_LOGIC("New VR(UX) = " << m_vrUx);
618 }
619 }
620}
621
622bool
623NrRlcUm::IsInsideReorderingWindow(nr::SequenceNumber10 seqNumber)
624{
625 NS_LOG_FUNCTION(this << seqNumber);
626 NS_LOG_LOGIC("Reordering Window: " << m_vrUh << " - " << m_windowSize << " <= " << seqNumber
627 << " < " << m_vrUh);
628
629 m_vrUh.SetModulusBase(m_vrUh - m_windowSize);
630 seqNumber.SetModulusBase(m_vrUh - m_windowSize);
631
632 if (((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
633 {
634 NS_LOG_LOGIC(seqNumber << " is INSIDE the reordering window");
635 return true;
636 }
637 else
638 {
639 NS_LOG_LOGIC(seqNumber << " is OUTSIDE the reordering window");
640 return false;
641 }
642}
643
644void
645NrRlcUm::ReassembleAndDeliver(Ptr<Packet> packet)
646{
647 NrRlcHeader rlcHeader;
648 packet->RemoveHeader(rlcHeader);
649 uint8_t framingInfo = rlcHeader.GetFramingInfo();
650 nr::SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber();
651 bool expectedSnLost;
652
653 if (currSeqNumber != m_expectedSeqNumber)
654 {
655 expectedSnLost = true;
656 NS_LOG_LOGIC("There are losses. Expected SN = " << m_expectedSeqNumber
657 << ". Current SN = " << currSeqNumber);
658 m_expectedSeqNumber = currSeqNumber + 1;
659 }
660 else
661 {
662 expectedSnLost = false;
663 NS_LOG_LOGIC("No losses. Expected SN = " << m_expectedSeqNumber
664 << ". Current SN = " << currSeqNumber);
665 m_expectedSeqNumber++;
666 }
667
668 // Build list of SDUs
669 uint8_t extensionBit;
670 uint16_t lengthIndicator;
671 do
672 {
673 extensionBit = rlcHeader.PopExtensionBit();
674 NS_LOG_LOGIC("E = " << (uint16_t)extensionBit);
675
676 if (extensionBit == 0)
677 {
678 m_sdusBuffer.push_back(packet);
679 }
680 else // extensionBit == 1
681 {
682 lengthIndicator = rlcHeader.PopLengthIndicator();
683 NS_LOG_LOGIC("LI = " << lengthIndicator);
684
685 // Check if there is enough data in the packet
686 if (lengthIndicator >= packet->GetSize())
687 {
688 NS_LOG_LOGIC("INTERNAL ERROR: Not enough data in the packet ("
689 << packet->GetSize() << "). Needed LI=" << lengthIndicator);
690 }
691
692 // Split packet in two fragments
693 Ptr<Packet> data_field = packet->CreateFragment(0, lengthIndicator);
694 packet->RemoveAtStart(lengthIndicator);
695
696 m_sdusBuffer.push_back(data_field);
697 }
698 } while (extensionBit == 1);
699
700 // Current reassembling state
701 if (m_reassemblingState == WAITING_S0_FULL)
702 {
703 NS_LOG_LOGIC("Reassembling State = 'WAITING_S0_FULL'");
704 }
705 else if (m_reassemblingState == WAITING_SI_SF)
706 {
707 NS_LOG_LOGIC("Reassembling State = 'WAITING_SI_SF'");
708 }
709 else
710 {
711 NS_LOG_LOGIC("Reassembling State = Unknown state");
712 }
713
714 // Received framing Info
715 NS_LOG_LOGIC("Framing Info = " << (uint16_t)framingInfo);
716
717 // Reassemble the list of SDUs (when there is no losses)
718 if (!expectedSnLost)
719 {
720 switch (m_reassemblingState)
721 {
722 case WAITING_S0_FULL:
723 switch (framingInfo)
724 {
725 case (NrRlcHeader::FIRST_BYTE | NrRlcHeader::LAST_BYTE):
726 m_reassemblingState = WAITING_S0_FULL;
727
731 for (auto it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
732 {
733 m_rlcSapUser->ReceivePdcpPdu(*it);
734 }
735 m_sdusBuffer.clear();
736 break;
737
738 case (NrRlcHeader::FIRST_BYTE | NrRlcHeader::NO_LAST_BYTE):
739 m_reassemblingState = WAITING_SI_SF;
740
744 while (m_sdusBuffer.size() > 1)
745 {
746 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
747 m_sdusBuffer.pop_front();
748 }
749
753 m_keepS0 = m_sdusBuffer.front();
754 m_sdusBuffer.pop_front();
755 break;
756
757 case (NrRlcHeader::NO_FIRST_BYTE | NrRlcHeader::LAST_BYTE):
758 m_reassemblingState = WAITING_S0_FULL;
759
763 m_sdusBuffer.pop_front();
764
768 while (!m_sdusBuffer.empty())
769 {
770 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
771 m_sdusBuffer.pop_front();
772 }
773 break;
774
775 case (NrRlcHeader::NO_FIRST_BYTE | NrRlcHeader::NO_LAST_BYTE):
776 if (m_sdusBuffer.size() == 1)
777 {
778 m_reassemblingState = WAITING_S0_FULL;
779 }
780 else
781 {
782 m_reassemblingState = WAITING_SI_SF;
783 }
784
788 m_sdusBuffer.pop_front();
789
790 if (!m_sdusBuffer.empty())
791 {
795 while (m_sdusBuffer.size() > 1)
796 {
797 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
798 m_sdusBuffer.pop_front();
799 }
800
804 m_keepS0 = m_sdusBuffer.front();
805 m_sdusBuffer.pop_front();
806 }
807 break;
808
809 default:
813 NS_LOG_LOGIC(
814 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
815 break;
816 }
817 break;
818
819 case WAITING_SI_SF:
820 switch (framingInfo)
821 {
822 case (NrRlcHeader::NO_FIRST_BYTE | NrRlcHeader::LAST_BYTE):
823 m_reassemblingState = WAITING_S0_FULL;
824
828 m_keepS0->AddAtEnd(m_sdusBuffer.front());
829 m_sdusBuffer.pop_front();
830 m_rlcSapUser->ReceivePdcpPdu(m_keepS0);
831
835 while (!m_sdusBuffer.empty())
836 {
837 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
838 m_sdusBuffer.pop_front();
839 }
840 break;
841
842 case (NrRlcHeader::NO_FIRST_BYTE | NrRlcHeader::NO_LAST_BYTE):
843 m_reassemblingState = WAITING_SI_SF;
844
848 if (m_sdusBuffer.size() == 1)
849 {
850 m_keepS0->AddAtEnd(m_sdusBuffer.front());
851 m_sdusBuffer.pop_front();
852 }
853 else // m_sdusBuffer.size () > 1
854 {
858 m_keepS0->AddAtEnd(m_sdusBuffer.front());
859 m_sdusBuffer.pop_front();
860 m_rlcSapUser->ReceivePdcpPdu(m_keepS0);
861
865 while (m_sdusBuffer.size() > 1)
866 {
867 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
868 m_sdusBuffer.pop_front();
869 }
870
874 m_keepS0 = m_sdusBuffer.front();
875 m_sdusBuffer.pop_front();
876 }
877 break;
878
879 case (NrRlcHeader::FIRST_BYTE | NrRlcHeader::LAST_BYTE):
880 case (NrRlcHeader::FIRST_BYTE | NrRlcHeader::NO_LAST_BYTE):
881 default:
885 NS_LOG_LOGIC(
886 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
887 break;
888 }
889 break;
890
891 default:
892 NS_LOG_LOGIC(
893 "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
894 break;
895 }
896 }
897 else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the
898 // expected one)
899 {
900 switch (m_reassemblingState)
901 {
902 case WAITING_S0_FULL:
903 switch (framingInfo)
904 {
905 case (NrRlcHeader::FIRST_BYTE | NrRlcHeader::LAST_BYTE):
906 m_reassemblingState = WAITING_S0_FULL;
907
911 for (auto it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
912 {
913 m_rlcSapUser->ReceivePdcpPdu(*it);
914 }
915 m_sdusBuffer.clear();
916 break;
917
918 case (NrRlcHeader::FIRST_BYTE | NrRlcHeader::NO_LAST_BYTE):
919 m_reassemblingState = WAITING_SI_SF;
920
924 while (m_sdusBuffer.size() > 1)
925 {
926 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
927 m_sdusBuffer.pop_front();
928 }
929
933 m_keepS0 = m_sdusBuffer.front();
934 m_sdusBuffer.pop_front();
935 break;
936
937 case (NrRlcHeader::NO_FIRST_BYTE | NrRlcHeader::LAST_BYTE):
938 m_reassemblingState = WAITING_S0_FULL;
939
943 m_sdusBuffer.pop_front();
944
948 while (!m_sdusBuffer.empty())
949 {
950 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
951 m_sdusBuffer.pop_front();
952 }
953 break;
954
955 case (NrRlcHeader::NO_FIRST_BYTE | NrRlcHeader::NO_LAST_BYTE):
956 if (m_sdusBuffer.size() == 1)
957 {
958 m_reassemblingState = WAITING_S0_FULL;
959 }
960 else
961 {
962 m_reassemblingState = WAITING_SI_SF;
963 }
964
968 m_sdusBuffer.pop_front();
969
970 if (!m_sdusBuffer.empty())
971 {
975 while (m_sdusBuffer.size() > 1)
976 {
977 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
978 m_sdusBuffer.pop_front();
979 }
980
984 m_keepS0 = m_sdusBuffer.front();
985 m_sdusBuffer.pop_front();
986 }
987 break;
988
989 default:
993 NS_LOG_LOGIC(
994 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
995 break;
996 }
997 break;
998
999 case WAITING_SI_SF:
1000 switch (framingInfo)
1001 {
1002 case (NrRlcHeader::FIRST_BYTE | NrRlcHeader::LAST_BYTE):
1003 m_reassemblingState = WAITING_S0_FULL;
1004
1008 m_keepS0 = nullptr;
1009
1013 while (!m_sdusBuffer.empty())
1014 {
1015 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
1016 m_sdusBuffer.pop_front();
1017 }
1018 break;
1019
1020 case (NrRlcHeader::FIRST_BYTE | NrRlcHeader::NO_LAST_BYTE):
1021 m_reassemblingState = WAITING_SI_SF;
1022
1026 m_keepS0 = nullptr;
1027
1031 while (m_sdusBuffer.size() > 1)
1032 {
1033 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
1034 m_sdusBuffer.pop_front();
1035 }
1036
1040 m_keepS0 = m_sdusBuffer.front();
1041 m_sdusBuffer.pop_front();
1042
1043 break;
1044
1045 case (NrRlcHeader::NO_FIRST_BYTE | NrRlcHeader::LAST_BYTE):
1046 m_reassemblingState = WAITING_S0_FULL;
1047
1051 m_keepS0 = nullptr;
1052
1056 m_sdusBuffer.pop_front();
1057
1061 while (!m_sdusBuffer.empty())
1062 {
1063 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
1064 m_sdusBuffer.pop_front();
1065 }
1066 break;
1067
1068 case (NrRlcHeader::NO_FIRST_BYTE | NrRlcHeader::NO_LAST_BYTE):
1069 if (m_sdusBuffer.size() == 1)
1070 {
1071 m_reassemblingState = WAITING_S0_FULL;
1072 }
1073 else
1074 {
1075 m_reassemblingState = WAITING_SI_SF;
1076 }
1077
1081 m_keepS0 = nullptr;
1082
1086 m_sdusBuffer.pop_front();
1087
1088 if (!m_sdusBuffer.empty())
1089 {
1093 while (m_sdusBuffer.size() > 1)
1094 {
1095 m_rlcSapUser->ReceivePdcpPdu(m_sdusBuffer.front());
1096 m_sdusBuffer.pop_front();
1097 }
1098
1102 m_keepS0 = m_sdusBuffer.front();
1103 m_sdusBuffer.pop_front();
1104 }
1105 break;
1106
1107 default:
1111 NS_LOG_LOGIC(
1112 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1113 break;
1114 }
1115 break;
1116
1117 default:
1118 NS_LOG_LOGIC(
1119 "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1120 break;
1121 }
1122 }
1123}
1124
1125void
1126NrRlcUm::ReassembleOutsideWindow()
1127{
1128 NS_LOG_LOGIC("Reassemble Outside Window");
1129
1130 auto it = m_rxBuffer.begin();
1131
1132 while ((it != m_rxBuffer.end()) && !IsInsideReorderingWindow(nr::SequenceNumber10(it->first)))
1133 {
1134 NS_LOG_LOGIC("SN = " << it->first);
1135
1136 // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1137 ReassembleAndDeliver(it->second);
1138
1139 auto it_tmp = it;
1140 ++it;
1141 m_rxBuffer.erase(it_tmp);
1142 }
1143
1144 if (it != m_rxBuffer.end())
1145 {
1146 NS_LOG_LOGIC("(SN = " << it->first << ") is inside the reordering window");
1147 }
1148}
1149
1150void
1151NrRlcUm::ReassembleSnInterval(nr::SequenceNumber10 lowSeqNumber, nr::SequenceNumber10 highSeqNumber)
1152{
1153 NS_LOG_LOGIC("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1154
1155 nr::SequenceNumber10 reassembleSn = lowSeqNumber;
1156 NS_LOG_LOGIC("reassembleSN = " << reassembleSn);
1157 NS_LOG_LOGIC("highSeqNumber = " << highSeqNumber);
1158 while (reassembleSn < highSeqNumber)
1159 {
1160 NS_LOG_LOGIC("reassembleSn < highSeqNumber");
1161 auto it = m_rxBuffer.find(reassembleSn.GetValue());
1162 NS_LOG_LOGIC("it->first = " << it->first);
1163 NS_LOG_LOGIC("it->second = " << it->second);
1164 if (it != m_rxBuffer.end())
1165 {
1166 NS_LOG_LOGIC("SN = " << it->first);
1167
1168 // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1169 ReassembleAndDeliver(it->second);
1170
1171 m_rxBuffer.erase(it);
1172 }
1173
1174 reassembleSn++;
1175 }
1176}
1177
1178void
1179NrRlcUm::DoTransmitBufferStatusReport()
1180{
1181 Time holDelay(0);
1182 uint32_t queueSize = 0;
1183
1184 if (!m_txBuffer.empty())
1185 {
1186 holDelay = Simulator::Now() - m_txBuffer.front().m_waitingSince;
1187
1188 queueSize =
1189 m_txBufferSize + 2 * m_txBuffer.size(); // Data in tx queue + estimated headers size
1190 }
1191
1192 NrMacSapProvider::BufferStatusReportParameters r;
1193 r.rnti = m_rnti;
1194 r.lcid = m_lcid;
1195 r.txQueueSize = queueSize;
1196 r.txQueueHolDelay = holDelay.GetMilliSeconds();
1197 r.retxQueueSize = 0;
1198 r.retxQueueHolDelay = 0;
1199 r.statusPduSize = 0;
1200 r.expBsrTimer = m_expBsrTimer;
1201
1202 m_expBsrTimer = false;
1203
1204 NS_LOG_LOGIC("Send BufferStatusReport = " << r.txQueueSize << ", " << r.txQueueHolDelay);
1205 m_macSapProvider->BufferStatusReport(r);
1206}
1207
1208void
1209NrRlcUm::ExpireReorderingTimer()
1210{
1211 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid);
1212 NS_LOG_LOGIC("Reordering timer has expired");
1213
1214 // 5.1.2.2.4 Actions when t-Reordering expires
1215 // When t-Reordering expires, the receiving UM RLC entity shall:
1216 // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1217 // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when
1218 // doing so
1219 // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not
1220 // delivered before;
1221 // - if VR(UH) > VR(UR):
1222 // - start t-Reordering;
1223 // - set VR(UX) to VR(UH).
1224
1225 nr::SequenceNumber10 newVrUr = m_vrUx;
1226
1227 while (m_rxBuffer.find(newVrUr.GetValue()) != m_rxBuffer.end())
1228 {
1229 newVrUr++;
1230 }
1231 nr::SequenceNumber10 oldVrUr = m_vrUr;
1232 m_vrUr = newVrUr;
1233 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
1234
1235 ReassembleSnInterval(oldVrUr, m_vrUr);
1236
1237 if (m_vrUh > m_vrUr)
1238 {
1239 NS_LOG_LOGIC("Start reordering timer");
1240 m_reorderingTimer =
1241 Simulator::Schedule(m_reorderingTimerValue, &NrRlcUm::ExpireReorderingTimer, this);
1242 m_vrUx = m_vrUh;
1243 NS_LOG_LOGIC("New VR(UX) = " << m_vrUx);
1244 }
1245}
1246
1247void
1248NrRlcUm::ExpireBsrTimer()
1249{
1250 NS_LOG_LOGIC("BSR Timer expires");
1251
1252 if (!m_txBuffer.empty())
1253 {
1254 m_expBsrTimer = true;
1255 DoTransmitBufferStatusReport();
1256 m_bsrTimer = Simulator::Schedule(MilliSeconds(10), &NrRlcUm::ExpireBsrTimer, this);
1257 }
1258}
1259
1260} // namespace ns3
The packet header for the Radio Link Control (RLC) protocol packets.
void PushExtensionBit(uint8_t extensionBit)
void PushLengthIndicator(uint16_t lengthIndicator)
void SetFramingInfo(uint8_t framingInfo)
void SetSequenceNumber(nr::SequenceNumber10 sequenceNumber)
nr::SequenceNumber10 GetSequenceNumber() const
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
void SetStatus(uint8_t status)
Time GetSenderTimestamp() const
Definition nr-rlc-tag.h:51
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
void SetModulusBase(SequenceNumber10 modulusBase)
Set modulus base.