A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lte-rlc-um.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
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: Manuel Requena <manuel.requena@cttc.es>
18 */
19
20#include "lte-rlc-um.h"
21
22#include "lte-rlc-header.h"
24#include "lte-rlc-tag.h"
25
26#include "ns3/log.h"
27#include "ns3/simulator.h"
28
29namespace ns3
30{
31
32NS_LOG_COMPONENT_DEFINE("LteRlcUm");
33
35
37 : m_maxTxBufferSize(10 * 1024),
38 m_txBufferSize(0),
39 m_sequenceNumber(0),
40 m_vrUr(0),
41 m_vrUx(0),
42 m_vrUh(0),
43 m_windowSize(512),
44 m_expectedSeqNumber(0)
45{
46 NS_LOG_FUNCTION(this);
48}
49
51{
52 NS_LOG_FUNCTION(this);
53}
54
57{
58 static TypeId tid =
59 TypeId("ns3::LteRlcUm")
61 .SetGroupName("Lte")
62 .AddConstructor<LteRlcUm>()
63 .AddAttribute("MaxTxBufferSize",
64 "Maximum Size of the Transmission Buffer (in Bytes)",
65 UintegerValue(10 * 1024),
67 MakeUintegerChecker<uint32_t>())
68 .AddAttribute("ReorderingTimer",
69 "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
73 .AddAttribute(
74 "EnablePdcpDiscarding",
75 "Whether to use the PDCP discarding, i.e., perform discarding at the moment "
76 "of passing the PDCP SDU to RLC)",
77 BooleanValue(true),
80 .AddAttribute("DiscardTimerMs",
81 "Discard timer in milliseconds to be used to discard packets. "
82 "If set to 0 then packet delay budget will be used as the discard "
83 "timer value, otherwise it will be used this value.",
86 MakeUintegerChecker<uint32_t>());
87 return tid;
88}
89
90void
92{
93 NS_LOG_FUNCTION(this);
96
98}
99
104void
106{
107 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << p->GetSize());
108
109 if (m_txBufferSize + p->GetSize() <= m_maxTxBufferSize)
110 {
112 {
113 // discart the packet
114 uint32_t headOfLineDelayInMs = 0;
115 uint32_t discardTimerMs =
117
118 if (!m_txBuffer.empty())
119 {
120 headOfLineDelayInMs =
121 (Simulator::Now() - m_txBuffer.begin()->m_waitingSince).GetMilliSeconds();
122 }
123 NS_LOG_DEBUG("head of line delay in MS:" << headOfLineDelayInMs);
124 if (headOfLineDelayInMs > discardTimerMs)
125 {
126 NS_LOG_DEBUG("Tx HOL is higher than this packet can allow. RLC SDU discarded");
127 NS_LOG_DEBUG("headOfLineDelayInMs = " << headOfLineDelayInMs);
128 NS_LOG_DEBUG("m_packetDelayBudgetMs = " << m_packetDelayBudgetMs);
129 NS_LOG_DEBUG("packet size = " << p->GetSize());
130 m_txDropTrace(p);
131 }
132 }
133
137 p->AddPacketTag(tag);
138
139 NS_LOG_LOGIC("Tx Buffer: New packet added");
140 m_txBuffer.emplace_back(p, Simulator::Now());
141 m_txBufferSize += p->GetSize();
142 NS_LOG_LOGIC("NumOfBuffers = " << m_txBuffer.size());
143 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
144 }
145 else
146 {
147 // Discard full RLC SDU
148 NS_LOG_LOGIC("TxBuffer is full. RLC SDU discarded");
149 NS_LOG_LOGIC("MaxTxBufferSize = " << m_maxTxBufferSize);
150 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
151 NS_LOG_LOGIC("packet size = " << p->GetSize());
152 m_txDropTrace(p);
153 }
154
158}
159
164void
166{
167 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << txOpParams.bytes);
168
169 if (txOpParams.bytes <= 2)
170 {
171 // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
172 NS_LOG_LOGIC("TX opportunity too small = " << txOpParams.bytes);
173 return;
174 }
175
176 Ptr<Packet> packet = Create<Packet>();
177 LteRlcHeader rlcHeader;
178
179 // Build Data field
180 uint32_t nextSegmentSize = txOpParams.bytes - 2;
181 uint32_t nextSegmentId = 1;
182 uint32_t dataFieldAddedSize = 0;
183 std::vector<Ptr<Packet>> dataField;
184
185 // Remove the first packet from the transmission buffer.
186 // If only a segment of the packet is taken, then the remaining is given back later
187 if (m_txBuffer.empty())
188 {
189 NS_LOG_LOGIC("No data pending");
190 return;
191 }
192
193 Ptr<Packet> firstSegment = m_txBuffer.begin()->m_pdu->Copy();
194 Time firstSegmentTime = m_txBuffer.begin()->m_waitingSince;
195
196 NS_LOG_LOGIC("SDUs in TxBuffer = " << m_txBuffer.size());
197 NS_LOG_LOGIC("First SDU buffer = " << firstSegment);
198 NS_LOG_LOGIC("First SDU size = " << firstSegment->GetSize());
199 NS_LOG_LOGIC("Next segment size = " << nextSegmentSize);
200 NS_LOG_LOGIC("Remove SDU from TxBuffer");
201 m_txBufferSize -= firstSegment->GetSize();
202 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
203 m_txBuffer.erase(m_txBuffer.begin());
204
205 while (firstSegment && (firstSegment->GetSize() > 0) && (nextSegmentSize > 0))
206 {
207 NS_LOG_LOGIC("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
208 NS_LOG_LOGIC(" firstSegment size = " << firstSegment->GetSize());
209 NS_LOG_LOGIC(" nextSegmentSize = " << nextSegmentSize);
210 if ((firstSegment->GetSize() > nextSegmentSize) ||
211 // Segment larger than 2047 octets can only be mapped to the end of the Data field
212 (firstSegment->GetSize() > 2047))
213 {
214 // Take the minimum size, due to the 2047-bytes 3GPP exception
215 // This exception is due to the length of the LI field (just 11 bits)
216 uint32_t currSegmentSize = std::min(firstSegment->GetSize(), nextSegmentSize);
217
218 NS_LOG_LOGIC(" IF ( firstSegment > nextSegmentSize ||");
219 NS_LOG_LOGIC(" firstSegment > 2047 )");
220
221 // Segment txBuffer.FirstBuffer and
222 // Give back the remaining segment to the transmission buffer
223 Ptr<Packet> newSegment = firstSegment->CreateFragment(0, currSegmentSize);
224 NS_LOG_LOGIC(" newSegment size = " << newSegment->GetSize());
225
226 // Status tag of the new and remaining segments
227 // Note: This is the only place where a PDU is segmented and
228 // therefore its status can change
229 LteRlcSduStatusTag oldTag;
230 LteRlcSduStatusTag newTag;
231 firstSegment->RemovePacketTag(oldTag);
232 newSegment->RemovePacketTag(newTag);
234 {
237 }
238 else if (oldTag.GetStatus() == LteRlcSduStatusTag::LAST_SEGMENT)
239 {
241 // oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
242 }
243
244 // Give back the remaining segment to the transmission buffer
245 firstSegment->RemoveAtStart(currSegmentSize);
247 " firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize());
248 if (firstSegment->GetSize() > 0)
249 {
250 firstSegment->AddPacketTag(oldTag);
251
252 m_txBuffer.insert(m_txBuffer.begin(), TxPdu(firstSegment, firstSegmentTime));
253 m_txBufferSize += m_txBuffer.begin()->m_pdu->GetSize();
254
255 NS_LOG_LOGIC(" TX buffer: Give back the remaining segment");
256 NS_LOG_LOGIC(" TX buffers = " << m_txBuffer.size());
257 NS_LOG_LOGIC(" Front buffer size = " << m_txBuffer.begin()->m_pdu->GetSize());
258 NS_LOG_LOGIC(" txBufferSize = " << m_txBufferSize);
259 }
260 else
261 {
262 // Whole segment was taken, so adjust tag
264 {
266 }
268 {
270 }
271 }
272 // Segment is completely taken or
273 // the remaining segment is given back to the transmission buffer
274 firstSegment = nullptr;
275
276 // Put status tag once it has been adjusted
277 newSegment->AddPacketTag(newTag);
278
279 // Add Segment to Data field
280 dataFieldAddedSize = newSegment->GetSize();
281 dataField.push_back(newSegment);
282 newSegment = nullptr;
283
284 // ExtensionBit (Next_Segment - 1) = 0
286
287 // no LengthIndicator for the last one
288
289 nextSegmentSize -= dataFieldAddedSize;
290 nextSegmentId++;
291
292 // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
293
294 // (NO more segments) → exit
295 // break;
296 }
297 else if ((nextSegmentSize - firstSegment->GetSize() <= 2) || m_txBuffer.empty())
298 {
300 " IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
301 // Add txBuffer.FirstBuffer to DataField
302 dataFieldAddedSize = firstSegment->GetSize();
303 dataField.push_back(firstSegment);
304 firstSegment = nullptr;
305
306 // ExtensionBit (Next_Segment - 1) = 0
308
309 // no LengthIndicator for the last one
310
311 nextSegmentSize -= dataFieldAddedSize;
312 nextSegmentId++;
313
314 NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txBuffer.size());
315 if (!m_txBuffer.empty())
316 {
317 NS_LOG_LOGIC(" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
319 " First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize());
320 }
321 NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
322
323 // nextSegmentSize <= 2 (only if txBuffer is not empty)
324
325 // (NO more segments) → exit
326 // break;
327 }
328 else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
329 {
330 NS_LOG_LOGIC(" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
331 // Add txBuffer.FirstBuffer to DataField
332 dataFieldAddedSize = firstSegment->GetSize();
333 dataField.push_back(firstSegment);
334
335 // ExtensionBit (Next_Segment - 1) = 1
337
338 // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
339 rlcHeader.PushLengthIndicator(firstSegment->GetSize());
340
341 nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
342 nextSegmentId++;
343
344 NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txBuffer.size());
345 if (!m_txBuffer.empty())
346 {
347 NS_LOG_LOGIC(" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
349 " First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize());
350 }
351 NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
352 NS_LOG_LOGIC(" Remove SDU from TxBuffer");
353
354 // (more segments)
355 firstSegment = m_txBuffer.begin()->m_pdu->Copy();
356 firstSegmentTime = m_txBuffer.begin()->m_waitingSince;
357 m_txBufferSize -= firstSegment->GetSize();
358 m_txBuffer.erase(m_txBuffer.begin());
359 NS_LOG_LOGIC(" txBufferSize = " << m_txBufferSize);
360 }
361 }
362
363 // Build RLC header
365
366 // Build RLC PDU with DataField and Header
367 std::vector<Ptr<Packet>>::iterator it;
368 it = dataField.begin();
369
370 uint8_t framingInfo = 0;
371
372 // FIRST SEGMENT
374 NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
375 (*it)->PeekPacketTag(tag);
378 {
379 framingInfo |= LteRlcHeader::FIRST_BYTE;
380 }
381 else
382 {
383 framingInfo |= LteRlcHeader::NO_FIRST_BYTE;
384 }
385
386 while (it < dataField.end())
387 {
388 NS_LOG_LOGIC("Adding SDU/segment to packet, length = " << (*it)->GetSize());
389
390 NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
391 (*it)->RemovePacketTag(tag);
392 if (packet->GetSize() > 0)
393 {
394 packet->AddAtEnd(*it);
395 }
396 else
397 {
398 packet = (*it);
399 }
400 it++;
401 }
402
403 // LAST SEGMENT (Note: There could be only one and be the first one)
404 it--;
407 {
408 framingInfo |= LteRlcHeader::LAST_BYTE;
409 }
410 else
411 {
412 framingInfo |= LteRlcHeader::NO_LAST_BYTE;
413 }
414
415 rlcHeader.SetFramingInfo(framingInfo);
416
417 NS_LOG_LOGIC("RLC header: " << rlcHeader);
418 packet->AddHeader(rlcHeader);
419
420 // Sender timestamp
421 RlcTag rlcTag(Simulator::Now());
422 packet->AddByteTag(rlcTag, 1, rlcHeader.GetSerializedSize());
423 m_txPdu(m_rnti, m_lcid, packet->GetSize());
424
425 // Send RLC PDU to MAC layer
427 params.pdu = packet;
428 params.rnti = m_rnti;
429 params.lcid = m_lcid;
430 params.layer = txOpParams.layer;
431 params.harqProcessId = txOpParams.harqId;
432 params.componentCarrierId = txOpParams.componentCarrierId;
433
435
436 if (!m_txBuffer.empty())
437 {
440 }
441}
442
443void
445{
446 NS_LOG_FUNCTION(this);
447}
448
449void
451{
452 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << rxPduParams.p->GetSize());
453
454 // Receiver timestamp
455 RlcTag rlcTag;
456 Time delay;
457
458 bool ret = rxPduParams.p->FindFirstMatchingByteTag(rlcTag);
459 NS_ASSERT_MSG(ret, "RlcTag is missing");
460
461 delay = Simulator::Now() - rlcTag.GetSenderTimestamp();
462 m_rxPdu(m_rnti, m_lcid, rxPduParams.p->GetSize(), delay.GetNanoSeconds());
463
464 // 5.1.2.2 Receive operations
465
466 // Get RLC header parameters
467 LteRlcHeader rlcHeader;
468 rxPduParams.p->PeekHeader(rlcHeader);
469 NS_LOG_LOGIC("RLC header: " << rlcHeader);
470 SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber();
471
472 // 5.1.2.2.1 General
473 // The receiving UM RLC entity shall maintain a reordering window according to state variable
474 // VR(UH) as follows:
475 // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
476 // - a SN falls outside of the reordering window otherwise.
477 // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
478 // - either discard the received UMD PDU or place it in the reception buffer (see sub
479 // clause 5.1.2.2.2);
480 // - if the received UMD PDU was placed in the reception buffer:
481 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop
482 // t-Reordering as needed (see sub clause 5.1.2.2.3); When t-Reordering expires, the receiving
483 // UM RLC entity shall:
484 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start
485 // t-Reordering as needed (see sub clause 5.1.2.2.4).
486
487 // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
488 // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
489 // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
490 // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
491 // - discard the received UMD PDU;
492 // - else:
493 // - place the received UMD PDU in the reception buffer.
494
495 NS_LOG_LOGIC("VR(UR) = " << m_vrUr);
496 NS_LOG_LOGIC("VR(UX) = " << m_vrUx);
497 NS_LOG_LOGIC("VR(UH) = " << m_vrUh);
498 NS_LOG_LOGIC("SN = " << seqNumber);
499
503
504 if (((m_vrUr < seqNumber) && (seqNumber < m_vrUh) &&
505 (m_rxBuffer.count(seqNumber.GetValue()) > 0)) ||
506 (((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr)))
507 {
508 NS_LOG_LOGIC("PDU discarded");
509 rxPduParams.p = nullptr;
510 return;
511 }
512 else
513 {
514 NS_LOG_LOGIC("Place PDU in the reception buffer");
515 m_rxBuffer[seqNumber.GetValue()] = rxPduParams.p;
516 }
517
518 // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
519 // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity
520 // shall:
521
522 // - if x falls outside of the reordering window:
523 // - update VR(UH) to x + 1;
524 // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering
525 // window, remove
526 // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in
527 // ascending order of the RLC SN if not delivered before;
528 // - if VR(UR) falls outside of the reordering window:
529 // - set VR(UR) to (VR(UH) - UM_Window_Size);
530
531 if (!IsInsideReorderingWindow(seqNumber))
532 {
533 NS_LOG_LOGIC("SN is outside the reordering window");
534
535 m_vrUh = seqNumber + 1;
536 NS_LOG_LOGIC("New VR(UH) = " << m_vrUh);
537
539
541 {
543 NS_LOG_LOGIC("VR(UR) is outside the reordering window");
544 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
545 }
546 }
547
548 // - if the reception buffer contains an UMD PDU with SN = VR(UR):
549 // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been
550 // received;
551 // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when
552 // doing
553 // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN
554 // if not delivered before;
555
556 if (m_rxBuffer.count(m_vrUr.GetValue()) > 0)
557 {
558 NS_LOG_LOGIC("Reception buffer contains SN = " << m_vrUr);
559
560 std::map<uint16_t, Ptr<Packet>>::iterator it;
561 uint16_t newVrUr;
562 SequenceNumber10 oldVrUr = m_vrUr;
563
564 it = m_rxBuffer.find(m_vrUr.GetValue());
565 newVrUr = (it->first) + 1;
566 while (m_rxBuffer.count(newVrUr) > 0)
567 {
568 newVrUr++;
569 }
570 m_vrUr = newVrUr;
571 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
572
574 }
575
576 // m_vrUh can change previously, set new modulus base
577 // for the t-Reordering timer-related comparisons
581
582 // - if t-Reordering is running:
583 // - if VR(UX) <= VR(UR); or
584 // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
585 // - stop and reset t-Reordering;
587 {
588 NS_LOG_LOGIC("Reordering timer is running");
589
590 if ((m_vrUx <= m_vrUr) || ((!IsInsideReorderingWindow(m_vrUx)) && (m_vrUx != m_vrUh)))
591 {
592 NS_LOG_LOGIC("Stop reordering timer");
594 }
595 }
596
597 // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to
598 // actions above):
599 // - if VR(UH) > VR(UR):
600 // - start t-Reordering;
601 // - set VR(UX) to VR(UH).
603 {
604 NS_LOG_LOGIC("Reordering timer is not running");
605
606 if (m_vrUh > m_vrUr)
607 {
608 NS_LOG_LOGIC("VR(UH) > VR(UR)");
609 NS_LOG_LOGIC("Start reordering timer");
612 m_vrUx = m_vrUh;
613 NS_LOG_LOGIC("New VR(UX) = " << m_vrUx);
614 }
615 }
616}
617
618bool
620{
621 NS_LOG_FUNCTION(this << seqNumber);
622 NS_LOG_LOGIC("Reordering Window: " << m_vrUh << " - " << m_windowSize << " <= " << seqNumber
623 << " < " << m_vrUh);
624
627
628 if (((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
629 {
630 NS_LOG_LOGIC(seqNumber << " is INSIDE the reordering window");
631 return true;
632 }
633 else
634 {
635 NS_LOG_LOGIC(seqNumber << " is OUTSIDE the reordering window");
636 return false;
637 }
638}
639
640void
642{
643 LteRlcHeader rlcHeader;
644 packet->RemoveHeader(rlcHeader);
645 uint8_t framingInfo = rlcHeader.GetFramingInfo();
646 SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber();
647 bool expectedSnLost;
648
649 if (currSeqNumber != m_expectedSeqNumber)
650 {
651 expectedSnLost = true;
652 NS_LOG_LOGIC("There are losses. Expected SN = " << m_expectedSeqNumber
653 << ". Current SN = " << currSeqNumber);
654 m_expectedSeqNumber = currSeqNumber + 1;
655 }
656 else
657 {
658 expectedSnLost = false;
659 NS_LOG_LOGIC("No losses. Expected SN = " << m_expectedSeqNumber
660 << ". Current SN = " << currSeqNumber);
662 }
663
664 // Build list of SDUs
665 uint8_t extensionBit;
666 uint16_t lengthIndicator;
667 do
668 {
669 extensionBit = rlcHeader.PopExtensionBit();
670 NS_LOG_LOGIC("E = " << (uint16_t)extensionBit);
671
672 if (extensionBit == 0)
673 {
674 m_sdusBuffer.push_back(packet);
675 }
676 else // extensionBit == 1
677 {
678 lengthIndicator = rlcHeader.PopLengthIndicator();
679 NS_LOG_LOGIC("LI = " << lengthIndicator);
680
681 // Check if there is enough data in the packet
682 if (lengthIndicator >= packet->GetSize())
683 {
684 NS_LOG_LOGIC("INTERNAL ERROR: Not enough data in the packet ("
685 << packet->GetSize() << "). Needed LI=" << lengthIndicator);
686 }
687
688 // Split packet in two fragments
689 Ptr<Packet> data_field = packet->CreateFragment(0, lengthIndicator);
690 packet->RemoveAtStart(lengthIndicator);
691
692 m_sdusBuffer.push_back(data_field);
693 }
694 } while (extensionBit == 1);
695
696 std::list<Ptr<Packet>>::iterator it;
697
698 // Current reassembling state
700 NS_LOG_LOGIC("Reassembling State = 'WAITING_S0_FULL'");
702 NS_LOG_LOGIC("Reassembling State = 'WAITING_SI_SF'");
703 else
704 NS_LOG_LOGIC("Reassembling State = Unknown state");
705
706 // Received framing Info
707 NS_LOG_LOGIC("Framing Info = " << (uint16_t)framingInfo);
708
709 // Reassemble the list of SDUs (when there is no losses)
710 if (!expectedSnLost)
711 {
712 switch (m_reassemblingState)
713 {
714 case WAITING_S0_FULL:
715 switch (framingInfo)
716 {
719
723 for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
724 {
726 }
727 m_sdusBuffer.clear();
728 break;
729
732
736 while (m_sdusBuffer.size() > 1)
737 {
739 m_sdusBuffer.pop_front();
740 }
741
745 m_keepS0 = m_sdusBuffer.front();
746 m_sdusBuffer.pop_front();
747 break;
748
751
755 m_sdusBuffer.pop_front();
756
760 while (!m_sdusBuffer.empty())
761 {
763 m_sdusBuffer.pop_front();
764 }
765 break;
766
768 if (m_sdusBuffer.size() == 1)
769 {
771 }
772 else
773 {
775 }
776
780 m_sdusBuffer.pop_front();
781
782 if (!m_sdusBuffer.empty())
783 {
787 while (m_sdusBuffer.size() > 1)
788 {
790 m_sdusBuffer.pop_front();
791 }
792
796 m_keepS0 = m_sdusBuffer.front();
797 m_sdusBuffer.pop_front();
798 }
799 break;
800
801 default:
806 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
807 break;
808 }
809 break;
810
811 case WAITING_SI_SF:
812 switch (framingInfo)
813 {
816
821 m_sdusBuffer.pop_front();
823
827 while (!m_sdusBuffer.empty())
828 {
830 m_sdusBuffer.pop_front();
831 }
832 break;
833
836
840 if (m_sdusBuffer.size() == 1)
841 {
843 m_sdusBuffer.pop_front();
844 }
845 else // m_sdusBuffer.size () > 1
846 {
851 m_sdusBuffer.pop_front();
853
857 while (m_sdusBuffer.size() > 1)
858 {
860 m_sdusBuffer.pop_front();
861 }
862
866 m_keepS0 = m_sdusBuffer.front();
867 m_sdusBuffer.pop_front();
868 }
869 break;
870
873 default:
878 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
879 break;
880 }
881 break;
882
883 default:
885 "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
886 break;
887 }
888 }
889 else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the
890 // expected one)
891 {
892 switch (m_reassemblingState)
893 {
894 case WAITING_S0_FULL:
895 switch (framingInfo)
896 {
899
903 for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
904 {
906 }
907 m_sdusBuffer.clear();
908 break;
909
912
916 while (m_sdusBuffer.size() > 1)
917 {
919 m_sdusBuffer.pop_front();
920 }
921
925 m_keepS0 = m_sdusBuffer.front();
926 m_sdusBuffer.pop_front();
927 break;
928
931
935 m_sdusBuffer.pop_front();
936
940 while (!m_sdusBuffer.empty())
941 {
943 m_sdusBuffer.pop_front();
944 }
945 break;
946
948 if (m_sdusBuffer.size() == 1)
949 {
951 }
952 else
953 {
955 }
956
960 m_sdusBuffer.pop_front();
961
962 if (!m_sdusBuffer.empty())
963 {
967 while (m_sdusBuffer.size() > 1)
968 {
970 m_sdusBuffer.pop_front();
971 }
972
976 m_keepS0 = m_sdusBuffer.front();
977 m_sdusBuffer.pop_front();
978 }
979 break;
980
981 default:
986 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
987 break;
988 }
989 break;
990
991 case WAITING_SI_SF:
992 switch (framingInfo)
993 {
996
1000 m_keepS0 = nullptr;
1001
1005 while (!m_sdusBuffer.empty())
1006 {
1008 m_sdusBuffer.pop_front();
1009 }
1010 break;
1011
1014
1018 m_keepS0 = nullptr;
1019
1023 while (m_sdusBuffer.size() > 1)
1024 {
1026 m_sdusBuffer.pop_front();
1027 }
1028
1032 m_keepS0 = m_sdusBuffer.front();
1033 m_sdusBuffer.pop_front();
1034
1035 break;
1036
1039
1043 m_keepS0 = nullptr;
1044
1048 m_sdusBuffer.pop_front();
1049
1053 while (!m_sdusBuffer.empty())
1054 {
1056 m_sdusBuffer.pop_front();
1057 }
1058 break;
1059
1061 if (m_sdusBuffer.size() == 1)
1062 {
1064 }
1065 else
1066 {
1068 }
1069
1073 m_keepS0 = nullptr;
1074
1078 m_sdusBuffer.pop_front();
1079
1080 if (!m_sdusBuffer.empty())
1081 {
1085 while (m_sdusBuffer.size() > 1)
1086 {
1088 m_sdusBuffer.pop_front();
1089 }
1090
1094 m_keepS0 = m_sdusBuffer.front();
1095 m_sdusBuffer.pop_front();
1096 }
1097 break;
1098
1099 default:
1104 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1105 break;
1106 }
1107 break;
1108
1109 default:
1111 "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1112 break;
1113 }
1114 }
1115}
1116
1117void
1119{
1120 NS_LOG_LOGIC("Reassemble Outside Window");
1121
1122 std::map<uint16_t, Ptr<Packet>>::iterator it;
1123 it = m_rxBuffer.begin();
1124
1125 while ((it != m_rxBuffer.end()) && !IsInsideReorderingWindow(SequenceNumber10(it->first)))
1126 {
1127 NS_LOG_LOGIC("SN = " << it->first);
1128
1129 // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1130 ReassembleAndDeliver(it->second);
1131
1132 std::map<uint16_t, Ptr<Packet>>::iterator it_tmp = it;
1133 ++it;
1134 m_rxBuffer.erase(it_tmp);
1135 }
1136
1137 if (it != m_rxBuffer.end())
1138 {
1139 NS_LOG_LOGIC("(SN = " << it->first << ") is inside the reordering window");
1140 }
1141}
1142
1143void
1145{
1146 NS_LOG_LOGIC("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1147
1148 std::map<uint16_t, Ptr<Packet>>::iterator it;
1149
1150 SequenceNumber10 reassembleSn = lowSeqNumber;
1151 NS_LOG_LOGIC("reassembleSN = " << reassembleSn);
1152 NS_LOG_LOGIC("highSeqNumber = " << highSeqNumber);
1153 while (reassembleSn < highSeqNumber)
1154 {
1155 NS_LOG_LOGIC("reassembleSn < highSeqNumber");
1156 it = m_rxBuffer.find(reassembleSn.GetValue());
1157 NS_LOG_LOGIC("it->first = " << it->first);
1158 NS_LOG_LOGIC("it->second = " << it->second);
1159 if (it != m_rxBuffer.end())
1160 {
1161 NS_LOG_LOGIC("SN = " << it->first);
1162
1163 // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1164 ReassembleAndDeliver(it->second);
1165
1166 m_rxBuffer.erase(it);
1167 }
1168
1169 reassembleSn++;
1170 }
1171}
1172
1173void
1175{
1176 Time holDelay(0);
1177 uint32_t queueSize = 0;
1178
1179 if (!m_txBuffer.empty())
1180 {
1181 holDelay = Simulator::Now() - m_txBuffer.front().m_waitingSince;
1182
1183 queueSize =
1184 m_txBufferSize + 2 * m_txBuffer.size(); // Data in tx queue + estimated headers size
1185 }
1186
1188 r.rnti = m_rnti;
1189 r.lcid = m_lcid;
1190 r.txQueueSize = queueSize;
1191 r.txQueueHolDelay = holDelay.GetMilliSeconds();
1192 r.retxQueueSize = 0;
1193 r.retxQueueHolDelay = 0;
1194 r.statusPduSize = 0;
1195
1196 NS_LOG_LOGIC("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay);
1198}
1199
1200void
1202{
1204 NS_LOG_LOGIC("Reordering timer has expired");
1205
1206 // 5.1.2.2.4 Actions when t-Reordering expires
1207 // When t-Reordering expires, the receiving UM RLC entity shall:
1208 // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1209 // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when
1210 // doing so
1211 // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not
1212 // delivered before;
1213 // - if VR(UH) > VR(UR):
1214 // - start t-Reordering;
1215 // - set VR(UX) to VR(UH).
1216
1217 std::map<uint16_t, Ptr<Packet>>::iterator it;
1218 SequenceNumber10 newVrUr = m_vrUx;
1219
1220 while ((it = m_rxBuffer.find(newVrUr.GetValue())) != m_rxBuffer.end())
1221 {
1222 newVrUr++;
1223 }
1224 SequenceNumber10 oldVrUr = m_vrUr;
1225 m_vrUr = newVrUr;
1226 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
1227
1228 ReassembleSnInterval(oldVrUr, m_vrUr);
1229
1230 if (m_vrUh > m_vrUr)
1231 {
1232 NS_LOG_LOGIC("Start reordering timer");
1235 m_vrUx = m_vrUh;
1236 NS_LOG_LOGIC("New VR(UX) = " << m_vrUx);
1237 }
1238}
1239
1240void
1242{
1243 NS_LOG_LOGIC("RBS Timer expires");
1244
1245 if (!m_txBuffer.empty())
1246 {
1249 }
1250}
1251
1252} // namespace ns3
AttributeValue implementation for Boolean.
Definition: boolean.h:37
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
virtual void ReportBufferStatus(ReportBufferStatusParameters params)=0
Report the RLC buffer status to the MAC.
The packet header for the Radio Link Control (RLC) protocol packets.
uint32_t GetSerializedSize() const override
void PushExtensionBit(uint8_t extensionBit)
Push extension bit.
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
void SetSequenceNumber(SequenceNumber10 sequenceNumber)
Set sequence number.
void SetFramingInfo(uint8_t framingInfo)
Set framing info.
uint8_t PopExtensionBit()
Pop extension bit.
uint16_t PopLengthIndicator()
Pop length indicator.
uint8_t GetFramingInfo() const
Get framing info.
void PushLengthIndicator(uint16_t lengthIndicator)
Push length indicator.
This abstract base class defines the API to interact with the Radio Link Control (LTE_RLC) in LTE,...
Definition: lte-rlc.h:49
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
Definition: lte-rlc.h:148
uint8_t m_lcid
LCID.
Definition: lte-rlc.h:173
TracedCallback< Ptr< const Packet > > m_txDropTrace
The trace source fired when the RLC drops a packet before transmission.
Definition: lte-rlc.h:189
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:172
TracedCallback< uint16_t, uint8_t, uint32_t, uint64_t > m_rxPdu
Used to inform of a PDU reception from the MAC SAP user.
Definition: lte-rlc.h:184
void DoDispose() override
Destructor implementation.
Definition: lte-rlc.cc:126
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:170
uint16_t m_packetDelayBudgetMs
the packet delay budget in ms of the corresponding logical channel
Definition: lte-rlc.h:174
TracedCallback< uint16_t, uint8_t, uint32_t > m_txPdu
Used to inform of a PDU delivery to the MAC SAP provider.
Definition: lte-rlc.h:180
virtual void ReceivePdcpPdu(Ptr< Packet > p)=0
Called by the RLC entity to notify the PDCP entity of the reception of a new PDCP PDU.
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
uint8_t GetStatus() const
Get status function.
void SetStatus(uint8_t status)
Set status function.
LTE RLC Unacknowledged Mode (UM), see 3GPP TS 36.322.
Definition: lte-rlc-um.h:37
SequenceNumber10 m_vrUr
VR(UR)
Definition: lte-rlc-um.h:135
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-um.h:165
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver function.
Definition: lte-rlc-um.cc:641
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-um.cc:1174
uint32_t m_txBufferSize
transmit buffer size
Definition: lte-rlc-um.h:100
static TypeId GetTypeId()
Get the type ID.
Definition: lte-rlc-um.cc:56
void ReassembleOutsideWindow()
Reassemble outside window.
Definition: lte-rlc-um.cc:1118
void DoDispose() override
Destructor implementation.
Definition: lte-rlc-um.cc:91
void ExpireReorderingTimer()
Expire reordering timer.
Definition: lte-rlc-um.cc:1201
std::vector< TxPdu > m_txBuffer
Transmission buffer.
Definition: lte-rlc-um.h:124
Time m_reorderingTimerValue
Timers.
Definition: lte-rlc-um.h:147
~LteRlcUm() override
Definition: lte-rlc-um.cc:50
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-um.h:170
ReassemblingState_t m_reassemblingState
reassembling state
Definition: lte-rlc-um.h:164
void ReassembleSnInterval(SequenceNumber10 lowSeqNumber, SequenceNumber10 highSeqNumber)
Reassemble SN interval function.
Definition: lte-rlc-um.cc:1144
void ExpireRbsTimer()
Expire RBS timer.
Definition: lte-rlc-um.cc:1241
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-um.h:149
void DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams) override
MAC SAP.
Definition: lte-rlc-um.cc:165
SequenceNumber10 m_vrUx
VR(UX)
Definition: lte-rlc-um.h:136
uint16_t m_windowSize
Constants.
Definition: lte-rlc-um.h:142
std::map< uint16_t, Ptr< Packet > > m_rxBuffer
Reception buffer.
Definition: lte-rlc-um.h:125
uint32_t m_discardTimerMs
the discard timer value in milliseconds
Definition: lte-rlc-um.h:152
void DoNotifyHarqDeliveryFailure() override
Notify HARQ delivery failure.
Definition: lte-rlc-um.cc:444
SequenceNumber10 m_vrUh
VR(UH)
Definition: lte-rlc-um.h:137
void DoTransmitPdcpPdu(Ptr< Packet > p) override
RLC SAP.
Definition: lte-rlc-um.cc:105
void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams) override
Receive PDU function.
Definition: lte-rlc-um.cc:450
uint32_t m_maxTxBufferSize
maximum transmit buffer status
Definition: lte-rlc-um.h:99
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet.
Definition: lte-rlc-um.h:128
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-um.h:148
bool IsInsideReorderingWindow(SequenceNumber10 seqNumber)
Is inside reordering window function.
Definition: lte-rlc-um.cc:619
SequenceNumber10 m_sequenceNumber
State variables.
Definition: lte-rlc-um.h:133
bool m_enablePdcpDiscarding
whether to use the PDCP discarding (perform discarding at the moment of passing the PDCP SDU to RLC)
Definition: lte-rlc-um.h:150
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:962
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
Time GetSenderTimestamp() const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Definition: lte-rlc-tag.h:64
SequenceNumber10 class.
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
void SetModulusBase(SequenceNumber10 modulusBase)
Set modulus base.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:417
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:407
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1444
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Parameters for LteMacSapProvider::ReportBufferStatus.
Definition: lte-mac-sap.h:69
uint32_t txQueueSize
the current size of the RLC transmission queue
Definition: lte-mac-sap.h:72
uint16_t retxQueueHolDelay
the Head Of Line delay of the retransmission queue
Definition: lte-mac-sap.h:75
uint16_t txQueueHolDelay
the Head Of Line delay of the transmission queue
Definition: lte-mac-sap.h:73
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
Definition: lte-mac-sap.h:74
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:71
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:70
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:77
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:45
Parameters for LteMacSapUser::ReceivePdu.
Definition: lte-mac-sap.h:166
Ptr< Packet > p
the RLC PDU to be received
Definition: lte-mac-sap.h:187
Parameters for LteMacSapUser::NotifyTxOpportunity.
Definition: lte-mac-sap.h:105
uint32_t bytes
the number of bytes to transmit
Definition: lte-mac-sap.h:137
uint8_t componentCarrierId
the component carrier id
Definition: lte-mac-sap.h:140
uint8_t layer
the layer of transmission (MIMO)
Definition: lte-mac-sap.h:138
Store an incoming (from layer above us) PDU, waiting to transmit it.
Definition: lte-rlc-um.h:106