A Discrete-Event Network Simulator
API
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 "ns3/lte-rlc-um.h"
21
22#include "ns3/log.h"
23#include "ns3/lte-rlc-header.h"
24#include "ns3/lte-rlc-sdu-status-tag.h"
25#include "ns3/lte-rlc-tag.h"
26#include "ns3/simulator.h"
27
28namespace ns3
29{
30
31NS_LOG_COMPONENT_DEFINE("LteRlcUm");
32
34
36 : m_maxTxBufferSize(10 * 1024),
37 m_txBufferSize(0),
38 m_sequenceNumber(0),
39 m_vrUr(0),
40 m_vrUx(0),
41 m_vrUh(0),
42 m_windowSize(512),
43 m_expectedSeqNumber(0)
44{
45 NS_LOG_FUNCTION(this);
47}
48
50{
51 NS_LOG_FUNCTION(this);
52}
53
56{
57 static TypeId tid =
58 TypeId("ns3::LteRlcUm")
60 .SetGroupName("Lte")
61 .AddConstructor<LteRlcUm>()
62 .AddAttribute("MaxTxBufferSize",
63 "Maximum Size of the Transmission Buffer (in Bytes)",
64 UintegerValue(10 * 1024),
66 MakeUintegerChecker<uint32_t>())
67 .AddAttribute("ReorderingTimer",
68 "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
72 return tid;
73}
74
75void
77{
78 NS_LOG_FUNCTION(this);
81
83}
84
89void
91{
92 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << p->GetSize());
93
95 {
99 p->AddPacketTag(tag);
100
101 NS_LOG_LOGIC("Tx Buffer: New packet added");
102 m_txBuffer.emplace_back(p, Simulator::Now());
103 m_txBufferSize += p->GetSize();
104 NS_LOG_LOGIC("NumOfBuffers = " << m_txBuffer.size());
105 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
106 }
107 else
108 {
109 // Discard full RLC SDU
110 NS_LOG_LOGIC("TxBuffer is full. RLC SDU discarded");
111 NS_LOG_LOGIC("MaxTxBufferSize = " << m_maxTxBufferSize);
112 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
113 NS_LOG_LOGIC("packet size = " << p->GetSize());
114 m_txDropTrace(p);
115 }
116
120}
121
126void
128{
129 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << txOpParams.bytes);
130
131 if (txOpParams.bytes <= 2)
132 {
133 // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
134 NS_LOG_LOGIC("TX opportunity too small = " << txOpParams.bytes);
135 return;
136 }
137
138 Ptr<Packet> packet = Create<Packet>();
139 LteRlcHeader rlcHeader;
140
141 // Build Data field
142 uint32_t nextSegmentSize = txOpParams.bytes - 2;
143 uint32_t nextSegmentId = 1;
144 uint32_t dataFieldAddedSize = 0;
145 std::vector<Ptr<Packet>> dataField;
146
147 // Remove the first packet from the transmission buffer.
148 // If only a segment of the packet is taken, then the remaining is given back later
149 if (m_txBuffer.size() == 0)
150 {
151 NS_LOG_LOGIC("No data pending");
152 return;
153 }
154
155 Ptr<Packet> firstSegment = m_txBuffer.begin()->m_pdu->Copy();
156 Time firstSegmentTime = m_txBuffer.begin()->m_waitingSince;
157
158 NS_LOG_LOGIC("SDUs in TxBuffer = " << m_txBuffer.size());
159 NS_LOG_LOGIC("First SDU buffer = " << firstSegment);
160 NS_LOG_LOGIC("First SDU size = " << firstSegment->GetSize());
161 NS_LOG_LOGIC("Next segment size = " << nextSegmentSize);
162 NS_LOG_LOGIC("Remove SDU from TxBuffer");
163 m_txBufferSize -= firstSegment->GetSize();
164 NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
165 m_txBuffer.erase(m_txBuffer.begin());
166
167 while (firstSegment && (firstSegment->GetSize() > 0) && (nextSegmentSize > 0))
168 {
169 NS_LOG_LOGIC("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
170 NS_LOG_LOGIC(" firstSegment size = " << firstSegment->GetSize());
171 NS_LOG_LOGIC(" nextSegmentSize = " << nextSegmentSize);
172 if ((firstSegment->GetSize() > nextSegmentSize) ||
173 // Segment larger than 2047 octets can only be mapped to the end of the Data field
174 (firstSegment->GetSize() > 2047))
175 {
176 // Take the minimum size, due to the 2047-bytes 3GPP exception
177 // This exception is due to the length of the LI field (just 11 bits)
178 uint32_t currSegmentSize = std::min(firstSegment->GetSize(), nextSegmentSize);
179
180 NS_LOG_LOGIC(" IF ( firstSegment > nextSegmentSize ||");
181 NS_LOG_LOGIC(" firstSegment > 2047 )");
182
183 // Segment txBuffer.FirstBuffer and
184 // Give back the remaining segment to the transmission buffer
185 Ptr<Packet> newSegment = firstSegment->CreateFragment(0, currSegmentSize);
186 NS_LOG_LOGIC(" newSegment size = " << newSegment->GetSize());
187
188 // Status tag of the new and remaining segments
189 // Note: This is the only place where a PDU is segmented and
190 // therefore its status can change
191 LteRlcSduStatusTag oldTag;
192 LteRlcSduStatusTag newTag;
193 firstSegment->RemovePacketTag(oldTag);
194 newSegment->RemovePacketTag(newTag);
196 {
199 }
200 else if (oldTag.GetStatus() == LteRlcSduStatusTag::LAST_SEGMENT)
201 {
203 // oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
204 }
205
206 // Give back the remaining segment to the transmission buffer
207 firstSegment->RemoveAtStart(currSegmentSize);
209 " firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize());
210 if (firstSegment->GetSize() > 0)
211 {
212 firstSegment->AddPacketTag(oldTag);
213
214 m_txBuffer.insert(m_txBuffer.begin(), TxPdu(firstSegment, firstSegmentTime));
215 m_txBufferSize += m_txBuffer.begin()->m_pdu->GetSize();
216
217 NS_LOG_LOGIC(" TX buffer: Give back the remaining segment");
218 NS_LOG_LOGIC(" TX buffers = " << m_txBuffer.size());
219 NS_LOG_LOGIC(" Front buffer size = " << m_txBuffer.begin()->m_pdu->GetSize());
220 NS_LOG_LOGIC(" txBufferSize = " << m_txBufferSize);
221 }
222 else
223 {
224 // Whole segment was taken, so adjust tag
226 {
228 }
230 {
232 }
233 }
234 // Segment is completely taken or
235 // the remaining segment is given back to the transmission buffer
236 firstSegment = nullptr;
237
238 // Put status tag once it has been adjusted
239 newSegment->AddPacketTag(newTag);
240
241 // Add Segment to Data field
242 dataFieldAddedSize = newSegment->GetSize();
243 dataField.push_back(newSegment);
244 newSegment = nullptr;
245
246 // ExtensionBit (Next_Segment - 1) = 0
248
249 // no LengthIndicator for the last one
250
251 nextSegmentSize -= dataFieldAddedSize;
252 nextSegmentId++;
253
254 // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
255
256 // (NO more segments) → exit
257 // break;
258 }
259 else if ((nextSegmentSize - firstSegment->GetSize() <= 2) || (m_txBuffer.size() == 0))
260 {
262 " IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
263 // Add txBuffer.FirstBuffer to DataField
264 dataFieldAddedSize = firstSegment->GetSize();
265 dataField.push_back(firstSegment);
266 firstSegment = nullptr;
267
268 // ExtensionBit (Next_Segment - 1) = 0
270
271 // no LengthIndicator for the last one
272
273 nextSegmentSize -= dataFieldAddedSize;
274 nextSegmentId++;
275
276 NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txBuffer.size());
277 if (m_txBuffer.size() > 0)
278 {
279 NS_LOG_LOGIC(" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
281 " First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize());
282 }
283 NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
284
285 // nextSegmentSize <= 2 (only if txBuffer is not empty)
286
287 // (NO more segments) → exit
288 // break;
289 }
290 else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
291 {
292 NS_LOG_LOGIC(" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
293 // Add txBuffer.FirstBuffer to DataField
294 dataFieldAddedSize = firstSegment->GetSize();
295 dataField.push_back(firstSegment);
296
297 // ExtensionBit (Next_Segment - 1) = 1
299
300 // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
301 rlcHeader.PushLengthIndicator(firstSegment->GetSize());
302
303 nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
304 nextSegmentId++;
305
306 NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txBuffer.size());
307 if (m_txBuffer.size() > 0)
308 {
309 NS_LOG_LOGIC(" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
311 " First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize());
312 }
313 NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
314 NS_LOG_LOGIC(" Remove SDU from TxBuffer");
315
316 // (more segments)
317 firstSegment = m_txBuffer.begin()->m_pdu->Copy();
318 firstSegmentTime = m_txBuffer.begin()->m_waitingSince;
319 m_txBufferSize -= firstSegment->GetSize();
320 m_txBuffer.erase(m_txBuffer.begin());
321 NS_LOG_LOGIC(" txBufferSize = " << m_txBufferSize);
322 }
323 }
324
325 // Build RLC header
327
328 // Build RLC PDU with DataField and Header
329 std::vector<Ptr<Packet>>::iterator it;
330 it = dataField.begin();
331
332 uint8_t framingInfo = 0;
333
334 // FIRST SEGMENT
336 NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
337 (*it)->PeekPacketTag(tag);
340 {
341 framingInfo |= LteRlcHeader::FIRST_BYTE;
342 }
343 else
344 {
345 framingInfo |= LteRlcHeader::NO_FIRST_BYTE;
346 }
347
348 while (it < dataField.end())
349 {
350 NS_LOG_LOGIC("Adding SDU/segment to packet, length = " << (*it)->GetSize());
351
352 NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
353 (*it)->RemovePacketTag(tag);
354 if (packet->GetSize() > 0)
355 {
356 packet->AddAtEnd(*it);
357 }
358 else
359 {
360 packet = (*it);
361 }
362 it++;
363 }
364
365 // LAST SEGMENT (Note: There could be only one and be the first one)
366 it--;
369 {
370 framingInfo |= LteRlcHeader::LAST_BYTE;
371 }
372 else
373 {
374 framingInfo |= LteRlcHeader::NO_LAST_BYTE;
375 }
376
377 rlcHeader.SetFramingInfo(framingInfo);
378
379 NS_LOG_LOGIC("RLC header: " << rlcHeader);
380 packet->AddHeader(rlcHeader);
381
382 // Sender timestamp
383 RlcTag rlcTag(Simulator::Now());
384 packet->AddByteTag(rlcTag, 1, rlcHeader.GetSerializedSize());
385 m_txPdu(m_rnti, m_lcid, packet->GetSize());
386
387 // Send RLC PDU to MAC layer
389 params.pdu = packet;
390 params.rnti = m_rnti;
391 params.lcid = m_lcid;
392 params.layer = txOpParams.layer;
393 params.harqProcessId = txOpParams.harqId;
394 params.componentCarrierId = txOpParams.componentCarrierId;
395
397
398 if (!m_txBuffer.empty())
399 {
402 }
403}
404
405void
407{
408 NS_LOG_FUNCTION(this);
409}
410
411void
413{
414 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << rxPduParams.p->GetSize());
415
416 // Receiver timestamp
417 RlcTag rlcTag;
418 Time delay;
419
420 bool ret = rxPduParams.p->FindFirstMatchingByteTag(rlcTag);
421 NS_ASSERT_MSG(ret, "RlcTag is missing");
422
423 delay = Simulator::Now() - rlcTag.GetSenderTimestamp();
424 m_rxPdu(m_rnti, m_lcid, rxPduParams.p->GetSize(), delay.GetNanoSeconds());
425
426 // 5.1.2.2 Receive operations
427
428 // Get RLC header parameters
429 LteRlcHeader rlcHeader;
430 rxPduParams.p->PeekHeader(rlcHeader);
431 NS_LOG_LOGIC("RLC header: " << rlcHeader);
432 SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber();
433
434 // 5.1.2.2.1 General
435 // The receiving UM RLC entity shall maintain a reordering window according to state variable
436 // VR(UH) as follows:
437 // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
438 // - a SN falls outside of the reordering window otherwise.
439 // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
440 // - either discard the received UMD PDU or place it in the reception buffer (see sub
441 // clause 5.1.2.2.2);
442 // - if the received UMD PDU was placed in the reception buffer:
443 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop
444 // t-Reordering as needed (see sub clause 5.1.2.2.3); When t-Reordering expires, the receiving
445 // UM RLC entity shall:
446 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start
447 // t-Reordering as needed (see sub clause 5.1.2.2.4).
448
449 // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
450 // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
451 // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
452 // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
453 // - discard the received UMD PDU;
454 // - else:
455 // - place the received UMD PDU in the reception buffer.
456
457 NS_LOG_LOGIC("VR(UR) = " << m_vrUr);
458 NS_LOG_LOGIC("VR(UX) = " << m_vrUx);
459 NS_LOG_LOGIC("VR(UH) = " << m_vrUh);
460 NS_LOG_LOGIC("SN = " << seqNumber);
461
465
466 if (((m_vrUr < seqNumber) && (seqNumber < m_vrUh) &&
467 (m_rxBuffer.count(seqNumber.GetValue()) > 0)) ||
468 (((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr)))
469 {
470 NS_LOG_LOGIC("PDU discarded");
471 rxPduParams.p = nullptr;
472 return;
473 }
474 else
475 {
476 NS_LOG_LOGIC("Place PDU in the reception buffer");
477 m_rxBuffer[seqNumber.GetValue()] = rxPduParams.p;
478 }
479
480 // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
481 // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity
482 // shall:
483
484 // - if x falls outside of the reordering window:
485 // - update VR(UH) to x + 1;
486 // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering
487 // window, remove
488 // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in
489 // ascending order of the RLC SN if not delivered before;
490 // - if VR(UR) falls outside of the reordering window:
491 // - set VR(UR) to (VR(UH) - UM_Window_Size);
492
493 if (!IsInsideReorderingWindow(seqNumber))
494 {
495 NS_LOG_LOGIC("SN is outside the reordering window");
496
497 m_vrUh = seqNumber + 1;
498 NS_LOG_LOGIC("New VR(UH) = " << m_vrUh);
499
501
503 {
505 NS_LOG_LOGIC("VR(UR) is outside the reordering window");
506 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
507 }
508 }
509
510 // - if the reception buffer contains an UMD PDU with SN = VR(UR):
511 // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been
512 // received;
513 // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when
514 // doing
515 // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN
516 // if not delivered before;
517
518 if (m_rxBuffer.count(m_vrUr.GetValue()) > 0)
519 {
520 NS_LOG_LOGIC("Reception buffer contains SN = " << m_vrUr);
521
522 std::map<uint16_t, Ptr<Packet>>::iterator it;
523 uint16_t newVrUr;
524 SequenceNumber10 oldVrUr = m_vrUr;
525
526 it = m_rxBuffer.find(m_vrUr.GetValue());
527 newVrUr = (it->first) + 1;
528 while (m_rxBuffer.count(newVrUr) > 0)
529 {
530 newVrUr++;
531 }
532 m_vrUr = newVrUr;
533 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
534
536 }
537
538 // m_vrUh can change previously, set new modulus base
539 // for the t-Reordering timer-related comparisons
543
544 // - if t-Reordering is running:
545 // - if VR(UX) <= VR(UR); or
546 // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
547 // - stop and reset t-Reordering;
549 {
550 NS_LOG_LOGIC("Reordering timer is running");
551
552 if ((m_vrUx <= m_vrUr) || ((!IsInsideReorderingWindow(m_vrUx)) && (m_vrUx != m_vrUh)))
553 {
554 NS_LOG_LOGIC("Stop reordering timer");
556 }
557 }
558
559 // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to
560 // actions above):
561 // - if VR(UH) > VR(UR):
562 // - start t-Reordering;
563 // - set VR(UX) to VR(UH).
565 {
566 NS_LOG_LOGIC("Reordering timer is not running");
567
568 if (m_vrUh > m_vrUr)
569 {
570 NS_LOG_LOGIC("VR(UH) > VR(UR)");
571 NS_LOG_LOGIC("Start reordering timer");
574 m_vrUx = m_vrUh;
575 NS_LOG_LOGIC("New VR(UX) = " << m_vrUx);
576 }
577 }
578}
579
580bool
582{
583 NS_LOG_FUNCTION(this << seqNumber);
584 NS_LOG_LOGIC("Reordering Window: " << m_vrUh << " - " << m_windowSize << " <= " << seqNumber
585 << " < " << m_vrUh);
586
589
590 if (((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
591 {
592 NS_LOG_LOGIC(seqNumber << " is INSIDE the reordering window");
593 return true;
594 }
595 else
596 {
597 NS_LOG_LOGIC(seqNumber << " is OUTSIDE the reordering window");
598 return false;
599 }
600}
601
602void
604{
605 LteRlcHeader rlcHeader;
606 packet->RemoveHeader(rlcHeader);
607 uint8_t framingInfo = rlcHeader.GetFramingInfo();
608 SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber();
609 bool expectedSnLost;
610
611 if (currSeqNumber != m_expectedSeqNumber)
612 {
613 expectedSnLost = true;
614 NS_LOG_LOGIC("There are losses. Expected SN = " << m_expectedSeqNumber
615 << ". Current SN = " << currSeqNumber);
616 m_expectedSeqNumber = currSeqNumber + 1;
617 }
618 else
619 {
620 expectedSnLost = false;
621 NS_LOG_LOGIC("No losses. Expected SN = " << m_expectedSeqNumber
622 << ". Current SN = " << currSeqNumber);
624 }
625
626 // Build list of SDUs
627 uint8_t extensionBit;
628 uint16_t lengthIndicator;
629 do
630 {
631 extensionBit = rlcHeader.PopExtensionBit();
632 NS_LOG_LOGIC("E = " << (uint16_t)extensionBit);
633
634 if (extensionBit == 0)
635 {
636 m_sdusBuffer.push_back(packet);
637 }
638 else // extensionBit == 1
639 {
640 lengthIndicator = rlcHeader.PopLengthIndicator();
641 NS_LOG_LOGIC("LI = " << lengthIndicator);
642
643 // Check if there is enough data in the packet
644 if (lengthIndicator >= packet->GetSize())
645 {
646 NS_LOG_LOGIC("INTERNAL ERROR: Not enough data in the packet ("
647 << packet->GetSize() << "). Needed LI=" << lengthIndicator);
648 }
649
650 // Split packet in two fragments
651 Ptr<Packet> data_field = packet->CreateFragment(0, lengthIndicator);
652 packet->RemoveAtStart(lengthIndicator);
653
654 m_sdusBuffer.push_back(data_field);
655 }
656 } while (extensionBit == 1);
657
658 std::list<Ptr<Packet>>::iterator it;
659
660 // Current reassembling state
662 NS_LOG_LOGIC("Reassembling State = 'WAITING_S0_FULL'");
664 NS_LOG_LOGIC("Reassembling State = 'WAITING_SI_SF'");
665 else
666 NS_LOG_LOGIC("Reassembling State = Unknown state");
667
668 // Received framing Info
669 NS_LOG_LOGIC("Framing Info = " << (uint16_t)framingInfo);
670
671 // Reassemble the list of SDUs (when there is no losses)
672 if (!expectedSnLost)
673 {
674 switch (m_reassemblingState)
675 {
676 case WAITING_S0_FULL:
677 switch (framingInfo)
678 {
681
685 for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
686 {
688 }
689 m_sdusBuffer.clear();
690 break;
691
694
698 while (m_sdusBuffer.size() > 1)
699 {
701 m_sdusBuffer.pop_front();
702 }
703
707 m_keepS0 = m_sdusBuffer.front();
708 m_sdusBuffer.pop_front();
709 break;
710
713
717 m_sdusBuffer.pop_front();
718
722 while (!m_sdusBuffer.empty())
723 {
725 m_sdusBuffer.pop_front();
726 }
727 break;
728
730 if (m_sdusBuffer.size() == 1)
731 {
733 }
734 else
735 {
737 }
738
742 m_sdusBuffer.pop_front();
743
744 if (m_sdusBuffer.size() > 0)
745 {
749 while (m_sdusBuffer.size() > 1)
750 {
752 m_sdusBuffer.pop_front();
753 }
754
758 m_keepS0 = m_sdusBuffer.front();
759 m_sdusBuffer.pop_front();
760 }
761 break;
762
763 default:
768 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
769 break;
770 }
771 break;
772
773 case WAITING_SI_SF:
774 switch (framingInfo)
775 {
778
783 m_sdusBuffer.pop_front();
785
789 while (!m_sdusBuffer.empty())
790 {
792 m_sdusBuffer.pop_front();
793 }
794 break;
795
798
802 if (m_sdusBuffer.size() == 1)
803 {
805 m_sdusBuffer.pop_front();
806 }
807 else // m_sdusBuffer.size () > 1
808 {
813 m_sdusBuffer.pop_front();
815
819 while (m_sdusBuffer.size() > 1)
820 {
822 m_sdusBuffer.pop_front();
823 }
824
828 m_keepS0 = m_sdusBuffer.front();
829 m_sdusBuffer.pop_front();
830 }
831 break;
832
835 default:
840 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
841 break;
842 }
843 break;
844
845 default:
847 "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
848 break;
849 }
850 }
851 else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the
852 // expected one)
853 {
854 switch (m_reassemblingState)
855 {
856 case WAITING_S0_FULL:
857 switch (framingInfo)
858 {
861
865 for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
866 {
868 }
869 m_sdusBuffer.clear();
870 break;
871
874
878 while (m_sdusBuffer.size() > 1)
879 {
881 m_sdusBuffer.pop_front();
882 }
883
887 m_keepS0 = m_sdusBuffer.front();
888 m_sdusBuffer.pop_front();
889 break;
890
893
897 m_sdusBuffer.pop_front();
898
902 while (!m_sdusBuffer.empty())
903 {
905 m_sdusBuffer.pop_front();
906 }
907 break;
908
910 if (m_sdusBuffer.size() == 1)
911 {
913 }
914 else
915 {
917 }
918
922 m_sdusBuffer.pop_front();
923
924 if (m_sdusBuffer.size() > 0)
925 {
929 while (m_sdusBuffer.size() > 1)
930 {
932 m_sdusBuffer.pop_front();
933 }
934
938 m_keepS0 = m_sdusBuffer.front();
939 m_sdusBuffer.pop_front();
940 }
941 break;
942
943 default:
948 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
949 break;
950 }
951 break;
952
953 case WAITING_SI_SF:
954 switch (framingInfo)
955 {
958
962 m_keepS0 = nullptr;
963
967 while (!m_sdusBuffer.empty())
968 {
970 m_sdusBuffer.pop_front();
971 }
972 break;
973
976
980 m_keepS0 = nullptr;
981
985 while (m_sdusBuffer.size() > 1)
986 {
988 m_sdusBuffer.pop_front();
989 }
990
994 m_keepS0 = m_sdusBuffer.front();
995 m_sdusBuffer.pop_front();
996
997 break;
998
1001
1005 m_keepS0 = nullptr;
1006
1010 m_sdusBuffer.pop_front();
1011
1015 while (!m_sdusBuffer.empty())
1016 {
1018 m_sdusBuffer.pop_front();
1019 }
1020 break;
1021
1023 if (m_sdusBuffer.size() == 1)
1024 {
1026 }
1027 else
1028 {
1030 }
1031
1035 m_keepS0 = nullptr;
1036
1040 m_sdusBuffer.pop_front();
1041
1042 if (m_sdusBuffer.size() > 0)
1043 {
1047 while (m_sdusBuffer.size() > 1)
1048 {
1050 m_sdusBuffer.pop_front();
1051 }
1052
1056 m_keepS0 = m_sdusBuffer.front();
1057 m_sdusBuffer.pop_front();
1058 }
1059 break;
1060
1061 default:
1066 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1067 break;
1068 }
1069 break;
1070
1071 default:
1073 "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1074 break;
1075 }
1076 }
1077}
1078
1079void
1081{
1082 NS_LOG_LOGIC("Reassemble Outside Window");
1083
1084 std::map<uint16_t, Ptr<Packet>>::iterator it;
1085 it = m_rxBuffer.begin();
1086
1087 while ((it != m_rxBuffer.end()) && !IsInsideReorderingWindow(SequenceNumber10(it->first)))
1088 {
1089 NS_LOG_LOGIC("SN = " << it->first);
1090
1091 // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1092 ReassembleAndDeliver(it->second);
1093
1094 std::map<uint16_t, Ptr<Packet>>::iterator it_tmp = it;
1095 ++it;
1096 m_rxBuffer.erase(it_tmp);
1097 }
1098
1099 if (it != m_rxBuffer.end())
1100 {
1101 NS_LOG_LOGIC("(SN = " << it->first << ") is inside the reordering window");
1102 }
1103}
1104
1105void
1107{
1108 NS_LOG_LOGIC("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1109
1110 std::map<uint16_t, Ptr<Packet>>::iterator it;
1111
1112 SequenceNumber10 reassembleSn = lowSeqNumber;
1113 NS_LOG_LOGIC("reassembleSN = " << reassembleSn);
1114 NS_LOG_LOGIC("highSeqNumber = " << highSeqNumber);
1115 while (reassembleSn < highSeqNumber)
1116 {
1117 NS_LOG_LOGIC("reassembleSn < highSeqNumber");
1118 it = m_rxBuffer.find(reassembleSn.GetValue());
1119 NS_LOG_LOGIC("it->first = " << it->first);
1120 NS_LOG_LOGIC("it->second = " << it->second);
1121 if (it != m_rxBuffer.end())
1122 {
1123 NS_LOG_LOGIC("SN = " << it->first);
1124
1125 // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1126 ReassembleAndDeliver(it->second);
1127
1128 m_rxBuffer.erase(it);
1129 }
1130
1131 reassembleSn++;
1132 }
1133}
1134
1135void
1137{
1138 Time holDelay(0);
1139 uint32_t queueSize = 0;
1140
1141 if (!m_txBuffer.empty())
1142 {
1143 holDelay = Simulator::Now() - m_txBuffer.front().m_waitingSince;
1144
1145 queueSize =
1146 m_txBufferSize + 2 * m_txBuffer.size(); // Data in tx queue + estimated headers size
1147 }
1148
1150 r.rnti = m_rnti;
1151 r.lcid = m_lcid;
1152 r.txQueueSize = queueSize;
1153 r.txQueueHolDelay = holDelay.GetMilliSeconds();
1154 r.retxQueueSize = 0;
1155 r.retxQueueHolDelay = 0;
1156 r.statusPduSize = 0;
1157
1158 NS_LOG_LOGIC("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay);
1160}
1161
1162void
1164{
1166 NS_LOG_LOGIC("Reordering timer has expired");
1167
1168 // 5.1.2.2.4 Actions when t-Reordering expires
1169 // When t-Reordering expires, the receiving UM RLC entity shall:
1170 // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1171 // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when
1172 // doing so
1173 // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not
1174 // delivered before;
1175 // - if VR(UH) > VR(UR):
1176 // - start t-Reordering;
1177 // - set VR(UX) to VR(UH).
1178
1179 std::map<uint16_t, Ptr<Packet>>::iterator it;
1180 SequenceNumber10 newVrUr = m_vrUx;
1181
1182 while ((it = m_rxBuffer.find(newVrUr.GetValue())) != m_rxBuffer.end())
1183 {
1184 newVrUr++;
1185 }
1186 SequenceNumber10 oldVrUr = m_vrUr;
1187 m_vrUr = newVrUr;
1188 NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
1189
1190 ReassembleSnInterval(oldVrUr, m_vrUr);
1191
1192 if (m_vrUh > m_vrUr)
1193 {
1194 NS_LOG_LOGIC("Start reordering timer");
1197 m_vrUx = m_vrUh;
1198 NS_LOG_LOGIC("New VR(UX) = " << m_vrUx);
1199 }
1200}
1201
1202void
1204{
1205 NS_LOG_LOGIC("RBS Timer expires");
1206
1207 if (!m_txBuffer.empty())
1208 {
1211 }
1212}
1213
1214} // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
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:48
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
Definition: lte-rlc.h:142
uint8_t m_lcid
LCID.
Definition: lte-rlc.h:167
TracedCallback< Ptr< const Packet > > m_txDropTrace
The trace source fired when the RLC drops a packet before transmission.
Definition: lte-rlc.h:181
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:166
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:176
void DoDispose() override
Destructor implementation.
Definition: lte-rlc.cc:126
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:164
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:172
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:36
SequenceNumber10 m_vrUr
VR(UR)
Definition: lte-rlc-um.h:134
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-um.h:161
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver function.
Definition: lte-rlc-um.cc:603
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-um.cc:1136
uint32_t m_txBufferSize
transmit buffer size
Definition: lte-rlc-um.h:99
static TypeId GetTypeId()
Get the type ID.
Definition: lte-rlc-um.cc:55
void ReassembleOutsideWindow()
Reassemble outside window.
Definition: lte-rlc-um.cc:1080
void DoDispose() override
Destructor implementation.
Definition: lte-rlc-um.cc:76
void ExpireReorderingTimer()
Expire reordering timer.
Definition: lte-rlc-um.cc:1163
std::vector< TxPdu > m_txBuffer
Transmission buffer.
Definition: lte-rlc-um.h:123
Time m_reorderingTimerValue
Timers.
Definition: lte-rlc-um.h:146
~LteRlcUm() override
Definition: lte-rlc-um.cc:49
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-um.h:166
ReassemblingState_t m_reassemblingState
reassembling state
Definition: lte-rlc-um.h:160
void ReassembleSnInterval(SequenceNumber10 lowSeqNumber, SequenceNumber10 highSeqNumber)
Reassemble SN interval function.
Definition: lte-rlc-um.cc:1106
void ExpireRbsTimer()
Expire RBS timer.
Definition: lte-rlc-um.cc:1203
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-um.h:148
void DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams) override
MAC SAP.
Definition: lte-rlc-um.cc:127
SequenceNumber10 m_vrUx
VR(UX)
Definition: lte-rlc-um.h:135
uint16_t m_windowSize
Constants.
Definition: lte-rlc-um.h:141
std::map< uint16_t, Ptr< Packet > > m_rxBuffer
Reception buffer.
Definition: lte-rlc-um.h:124
void DoNotifyHarqDeliveryFailure() override
Notify HARQ delivery failure.
Definition: lte-rlc-um.cc:406
SequenceNumber10 m_vrUh
VR(UH)
Definition: lte-rlc-um.h:136
void DoTransmitPdcpPdu(Ptr< Packet > p) override
RLC SAP.
Definition: lte-rlc-um.cc:90
void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams) override
Receive PDU function.
Definition: lte-rlc-um.cc:412
uint32_t m_maxTxBufferSize
maximum transmit buffer status
Definition: lte-rlc-um.h:98
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet.
Definition: lte-rlc-um.h:127
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-um.h:147
bool IsInsideReorderingWindow(SequenceNumber10 seqNumber)
Is inside reordering window function.
Definition: lte-rlc-um.cc:581
SequenceNumber10 m_sequenceNumber
State variables.
Definition: lte-rlc-um.h:132
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:384
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:962
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:238
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:934
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:1425
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
#define 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 > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1426
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_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:45
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
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
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:47
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:48
uint8_t componentCarrierId
the component carrier id corresponding to the sending Mac istance
Definition: lte-mac-sap.h:53
uint8_t harqProcessId
the HARQ process id that was passed by the MAC in the call to NotifyTxOpportunity that generated this...
Definition: lte-mac-sap.h:51
uint8_t layer
the layer value that was passed by the MAC in the call to NotifyTxOpportunity that generated this PDU
Definition: lte-mac-sap.h:49
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:105