A Discrete-Event Network Simulator
API
lte-rlc-um.cc
Go to the documentation of this file.
1/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Manuel Requena <manuel.requena@cttc.es>
19 */
20
21#include "ns3/simulator.h"
22#include "ns3/log.h"
23
24#include "ns3/lte-rlc-header.h"
25#include "ns3/lte-rlc-um.h"
26#include "ns3/lte-rlc-sdu-status-tag.h"
27#include "ns3/lte-rlc-tag.h"
28
29namespace ns3 {
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 = TypeId ("ns3::LteRlcUm")
58 .SetParent<LteRlc> ()
59 .SetGroupName("Lte")
60 .AddConstructor<LteRlcUm> ()
61 .AddAttribute ("MaxTxBufferSize",
62 "Maximum Size of the Transmission Buffer (in Bytes)",
63 UintegerValue (10 * 1024),
65 MakeUintegerChecker<uint32_t> ())
66 .AddAttribute ("ReorderingTimer",
67 "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
68 TimeValue (MilliSeconds (100)),
71 ;
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.push_back (TxPdu (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
122
127void
129{
130 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << txOpParams.bytes);
131
132 if (txOpParams.bytes <= 2)
133 {
134 // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
135 NS_LOG_LOGIC ("TX opportunity too small = " << txOpParams.bytes);
136 return;
137 }
138
139 Ptr<Packet> packet = Create<Packet> ();
140 LteRlcHeader rlcHeader;
141
142 // Build Data field
143 uint32_t nextSegmentSize = txOpParams.bytes - 2;
144 uint32_t nextSegmentId = 1;
145 uint32_t dataFieldAddedSize = 0;
146 std::vector < Ptr<Packet> > dataField;
147
148 // Remove the first packet from the transmission buffer.
149 // If only a segment of the packet is taken, then the remaining is given back later
150 if ( m_txBuffer.size () == 0 )
151 {
152 NS_LOG_LOGIC ("No data pending");
153 return;
154 }
155
156 Ptr<Packet> firstSegment = m_txBuffer.begin ()->m_pdu->Copy ();
157 Time firstSegmentTime = m_txBuffer.begin ()->m_waitingSince;
158
159 NS_LOG_LOGIC ("SDUs in TxBuffer = " << m_txBuffer.size ());
160 NS_LOG_LOGIC ("First SDU buffer = " << firstSegment);
161 NS_LOG_LOGIC ("First SDU size = " << firstSegment->GetSize ());
162 NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
163 NS_LOG_LOGIC ("Remove SDU from TxBuffer");
164 m_txBufferSize -= firstSegment->GetSize ();
165 NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize );
166 m_txBuffer.erase (m_txBuffer.begin ());
167
168 while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
169 {
170 NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
171 NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
172 NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
173 if ( (firstSegment->GetSize () > nextSegmentSize) ||
174 // Segment larger than 2047 octets can only be mapped to the end of the Data field
175 (firstSegment->GetSize () > 2047)
176 )
177 {
178 // Take the minimum size, due to the 2047-bytes 3GPP exception
179 // This exception is due to the length of the LI field (just 11 bits)
180 uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
181
182 NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
183 NS_LOG_LOGIC (" firstSegment > 2047 )");
184
185 // Segment txBuffer.FirstBuffer and
186 // Give back the remaining segment to the transmission buffer
187 Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
188 NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
189
190 // Status tag of the new and remaining segments
191 // Note: This is the only place where a PDU is segmented and
192 // therefore its status can change
193 LteRlcSduStatusTag oldTag, newTag;
194 firstSegment->RemovePacketTag (oldTag);
195 newSegment->RemovePacketTag (newTag);
197 {
200 }
201 else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT)
202 {
204 //oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
205 }
206
207 // Give back the remaining segment to the transmission buffer
208 firstSegment->RemoveAtStart (currSegmentSize);
209 NS_LOG_LOGIC (" 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 }
229 else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
230 {
232 }
233 }
234 // Segment is completely taken or
235 // the remaining segment is given back to the transmission buffer
236 firstSegment = 0;
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 = 0;
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 {
261 NS_LOG_LOGIC (" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
262 // Add txBuffer.FirstBuffer to DataField
263 dataFieldAddedSize = firstSegment->GetSize ();
264 dataField.push_back (firstSegment);
265 firstSegment = 0;
266
267 // ExtensionBit (Next_Segment - 1) = 0
269
270 // no LengthIndicator for the last one
271
272 nextSegmentSize -= dataFieldAddedSize;
273 nextSegmentId++;
274
275 NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
276 if (m_txBuffer.size () > 0)
277 {
278 NS_LOG_LOGIC (" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
279 NS_LOG_LOGIC (" First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize ());
280 }
281 NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
282
283 // nextSegmentSize <= 2 (only if txBuffer is not empty)
284
285 // (NO more segments) → exit
286 // break;
287 }
288 else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
289 {
290 NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
291 // Add txBuffer.FirstBuffer to DataField
292 dataFieldAddedSize = firstSegment->GetSize ();
293 dataField.push_back (firstSegment);
294
295 // ExtensionBit (Next_Segment - 1) = 1
297
298 // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
299 rlcHeader.PushLengthIndicator (firstSegment->GetSize ());
300
301 nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
302 nextSegmentId++;
303
304 NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
305 if (m_txBuffer.size () > 0)
306 {
307 NS_LOG_LOGIC (" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
308 NS_LOG_LOGIC (" First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize ());
309 }
310 NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
311 NS_LOG_LOGIC (" Remove SDU from TxBuffer");
312
313 // (more segments)
314 firstSegment = m_txBuffer.begin ()->m_pdu->Copy ();
315 firstSegmentTime = m_txBuffer.begin ()->m_waitingSince;
316 m_txBufferSize -= firstSegment->GetSize ();
317 m_txBuffer.erase (m_txBuffer.begin ());
318 NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
319 }
320
321 }
322
323 // Build RLC header
325
326 // Build RLC PDU with DataField and Header
327 std::vector< Ptr<Packet> >::iterator it;
328 it = dataField.begin ();
329
330 uint8_t framingInfo = 0;
331
332 // FIRST SEGMENT
334 NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
335 (*it)->PeekPacketTag (tag);
336 if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
338 {
339 framingInfo |= LteRlcHeader::FIRST_BYTE;
340 }
341 else
342 {
343 framingInfo |= LteRlcHeader::NO_FIRST_BYTE;
344 }
345
346 while (it < dataField.end ())
347 {
348 NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ());
349
350 NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
351 (*it)->RemovePacketTag (tag);
352 if (packet->GetSize () > 0)
353 {
354 packet->AddAtEnd (*it);
355 }
356 else
357 {
358 packet = (*it);
359 }
360 it++;
361 }
362
363 // LAST SEGMENT (Note: There could be only one and be the first one)
364 it--;
365 if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
367 {
368 framingInfo |= LteRlcHeader::LAST_BYTE;
369 }
370 else
371 {
372 framingInfo |= LteRlcHeader::NO_LAST_BYTE;
373 }
374
375 rlcHeader.SetFramingInfo (framingInfo);
376
377 NS_LOG_LOGIC ("RLC header: " << rlcHeader);
378 packet->AddHeader (rlcHeader);
379
380 // Sender timestamp
381 RlcTag rlcTag (Simulator::Now ());
382 packet->AddByteTag (rlcTag, 1, rlcHeader.GetSerializedSize ());
383 m_txPdu (m_rnti, m_lcid, packet->GetSize ());
384
385 // Send RLC PDU to MAC layer
387 params.pdu = packet;
388 params.rnti = m_rnti;
389 params.lcid = m_lcid;
390 params.layer = txOpParams.layer;
391 params.harqProcessId = txOpParams.harqId;
392 params.componentCarrierId = txOpParams.componentCarrierId;
393
395
396 if (! m_txBuffer.empty ())
397 {
400 }
401}
402
403void
405{
406 NS_LOG_FUNCTION (this);
407}
408
409void
411{
412 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << rxPduParams.p->GetSize ());
413
414 // Receiver timestamp
415 RlcTag rlcTag;
416 Time delay;
417
418 bool ret = rxPduParams.p->FindFirstMatchingByteTag (rlcTag);
419 NS_ASSERT_MSG (ret, "RlcTag is missing");
420
421 delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
422 m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), delay.GetNanoSeconds ());
423
424 // 5.1.2.2 Receive operations
425
426 // Get RLC header parameters
427 LteRlcHeader rlcHeader;
428 rxPduParams.p->PeekHeader (rlcHeader);
429 NS_LOG_LOGIC ("RLC header: " << rlcHeader);
430 SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber ();
431
432 // 5.1.2.2.1 General
433 // The receiving UM RLC entity shall maintain a reordering window according to state variable VR(UH) as follows:
434 // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
435 // - a SN falls outside of the reordering window otherwise.
436 // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
437 // - either discard the received UMD PDU or place it in the reception buffer (see sub clause 5.1.2.2.2);
438 // - if the received UMD PDU was placed in the reception buffer:
439 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop t-Reordering as needed (see sub clause 5.1.2.2.3);
440 // When t-Reordering expires, the receiving UM RLC entity shall:
441 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start t-Reordering as needed (see sub clause 5.1.2.2.4).
442
443 // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
444 // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
445 // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
446 // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
447 // - discard the received UMD PDU;
448 // - else:
449 // - place the received UMD PDU in the reception buffer.
450
451 NS_LOG_LOGIC ("VR(UR) = " << m_vrUr);
452 NS_LOG_LOGIC ("VR(UX) = " << m_vrUx);
453 NS_LOG_LOGIC ("VR(UH) = " << m_vrUh);
454 NS_LOG_LOGIC ("SN = " << seqNumber);
455
458 seqNumber.SetModulusBase (m_vrUh - m_windowSize);
459
460 if ( ( (m_vrUr < seqNumber) && (seqNumber < m_vrUh) && (m_rxBuffer.count (seqNumber.GetValue ()) > 0) ) ||
461 ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr) )
462 )
463 {
464 NS_LOG_LOGIC ("PDU discarded");
465 rxPduParams.p = 0;
466 return;
467 }
468 else
469 {
470 NS_LOG_LOGIC ("Place PDU in the reception buffer");
471 m_rxBuffer[seqNumber.GetValue ()] = rxPduParams.p;
472 }
473
474
475 // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
476 // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity shall:
477
478 // - if x falls outside of the reordering window:
479 // - update VR(UH) to x + 1;
480 // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering window, remove
481 // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in ascending order of the
482 // RLC SN if not delivered before;
483 // - if VR(UR) falls outside of the reordering window:
484 // - set VR(UR) to (VR(UH) - UM_Window_Size);
485
486 if ( ! IsInsideReorderingWindow (seqNumber))
487 {
488 NS_LOG_LOGIC ("SN is outside the reordering window");
489
490 m_vrUh = seqNumber + 1;
491 NS_LOG_LOGIC ("New VR(UH) = " << m_vrUh);
492
494
496 {
498 NS_LOG_LOGIC ("VR(UR) is outside the reordering window");
499 NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
500 }
501 }
502
503 // - if the reception buffer contains an UMD PDU with SN = VR(UR):
504 // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been received;
505 // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing
506 // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered
507 // before;
508
509 if ( m_rxBuffer.count (m_vrUr.GetValue ()) > 0 )
510 {
511 NS_LOG_LOGIC ("Reception buffer contains SN = " << m_vrUr);
512
513 std::map <uint16_t, Ptr<Packet> >::iterator it;
514 uint16_t newVrUr;
515 SequenceNumber10 oldVrUr = m_vrUr;
516
517 it = m_rxBuffer.find (m_vrUr.GetValue ());
518 newVrUr = (it->first) + 1;
519 while ( m_rxBuffer.count (newVrUr) > 0 )
520 {
521 newVrUr++;
522 }
523 m_vrUr = newVrUr;
524 NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
525
526 ReassembleSnInterval (oldVrUr, m_vrUr);
527 }
528
529 // m_vrUh can change previously, set new modulus base
530 // for the t-Reordering timer-related comparisons
534
535 // - if t-Reordering is running:
536 // - if VR(UX) <= VR(UR); or
537 // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
538 // - stop and reset t-Reordering;
540 {
541 NS_LOG_LOGIC ("Reordering timer is running");
542
543 if ( (m_vrUx <= m_vrUr) ||
545 {
546 NS_LOG_LOGIC ("Stop reordering timer");
548 }
549 }
550
551 // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to actions above):
552 // - if VR(UH) > VR(UR):
553 // - start t-Reordering;
554 // - set VR(UX) to VR(UH).
555 if ( ! m_reorderingTimer.IsRunning () )
556 {
557 NS_LOG_LOGIC ("Reordering timer is not running");
558
559 if ( m_vrUh > m_vrUr )
560 {
561 NS_LOG_LOGIC ("VR(UH) > VR(UR)");
562 NS_LOG_LOGIC ("Start reordering timer");
565 m_vrUx = m_vrUh;
566 NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
567 }
568 }
569
570}
571
572
573bool
575{
576 NS_LOG_FUNCTION (this << seqNumber);
577 NS_LOG_LOGIC ("Reordering Window: " <<
578 m_vrUh << " - " << m_windowSize << " <= " << seqNumber << " < " << m_vrUh);
579
581 seqNumber.SetModulusBase (m_vrUh - m_windowSize);
582
583 if ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
584 {
585 NS_LOG_LOGIC (seqNumber << " is INSIDE the reordering window");
586 return true;
587 }
588 else
589 {
590 NS_LOG_LOGIC (seqNumber << " is OUTSIDE the reordering window");
591 return false;
592 }
593}
594
595
596void
598{
599 LteRlcHeader rlcHeader;
600 packet->RemoveHeader (rlcHeader);
601 uint8_t framingInfo = rlcHeader.GetFramingInfo ();
602 SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber ();
603 bool expectedSnLost;
604
605 if ( currSeqNumber != m_expectedSeqNumber )
606 {
607 expectedSnLost = true;
608 NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
609 m_expectedSeqNumber = currSeqNumber + 1;
610 }
611 else
612 {
613 expectedSnLost = false;
614 NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
616 }
617
618 // Build list of SDUs
619 uint8_t extensionBit;
620 uint16_t lengthIndicator;
621 do
622 {
623 extensionBit = rlcHeader.PopExtensionBit ();
624 NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit);
625
626 if ( extensionBit == 0 )
627 {
628 m_sdusBuffer.push_back (packet);
629 }
630 else // extensionBit == 1
631 {
632 lengthIndicator = rlcHeader.PopLengthIndicator ();
633 NS_LOG_LOGIC ("LI = " << lengthIndicator);
634
635 // Check if there is enough data in the packet
636 if ( lengthIndicator >= packet->GetSize () )
637 {
638 NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator);
639 }
640
641 // Split packet in two fragments
642 Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator);
643 packet->RemoveAtStart (lengthIndicator);
644
645 m_sdusBuffer.push_back (data_field);
646 }
647 }
648 while ( extensionBit == 1 );
649
650 std::list < Ptr<Packet> >::iterator it;
651
652 // Current reassembling state
653 if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'");
654 else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'");
655 else NS_LOG_LOGIC ("Reassembling State = Unknown state");
656
657 // Received framing Info
658 NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
659
660 // Reassemble the list of SDUs (when there is no losses)
661 if (!expectedSnLost)
662 {
663 switch (m_reassemblingState)
664 {
665 case WAITING_S0_FULL:
666 switch (framingInfo)
667 {
670
674 for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
675 {
677 }
678 m_sdusBuffer.clear ();
679 break;
680
683
687 while ( m_sdusBuffer.size () > 1 )
688 {
690 m_sdusBuffer.pop_front ();
691 }
692
696 m_keepS0 = m_sdusBuffer.front ();
697 m_sdusBuffer.pop_front ();
698 break;
699
702
706 m_sdusBuffer.pop_front ();
707
711 while ( ! m_sdusBuffer.empty () )
712 {
714 m_sdusBuffer.pop_front ();
715 }
716 break;
717
719 if ( m_sdusBuffer.size () == 1 )
720 {
722 }
723 else
724 {
726 }
727
731 m_sdusBuffer.pop_front ();
732
733 if ( m_sdusBuffer.size () > 0 )
734 {
738 while ( m_sdusBuffer.size () > 1 )
739 {
741 m_sdusBuffer.pop_front ();
742 }
743
747 m_keepS0 = m_sdusBuffer.front ();
748 m_sdusBuffer.pop_front ();
749 }
750 break;
751
752 default:
756 NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
757 break;
758 }
759 break;
760
761 case WAITING_SI_SF:
762 switch (framingInfo)
763 {
766
770 m_keepS0->AddAtEnd (m_sdusBuffer.front ());
771 m_sdusBuffer.pop_front ();
773
777 while ( ! m_sdusBuffer.empty () )
778 {
780 m_sdusBuffer.pop_front ();
781 }
782 break;
783
786
790 if ( m_sdusBuffer.size () == 1 )
791 {
792 m_keepS0->AddAtEnd (m_sdusBuffer.front ());
793 m_sdusBuffer.pop_front ();
794 }
795 else // m_sdusBuffer.size () > 1
796 {
800 m_keepS0->AddAtEnd (m_sdusBuffer.front ());
801 m_sdusBuffer.pop_front ();
803
807 while ( m_sdusBuffer.size () > 1 )
808 {
810 m_sdusBuffer.pop_front ();
811 }
812
816 m_keepS0 = m_sdusBuffer.front ();
817 m_sdusBuffer.pop_front ();
818 }
819 break;
820
823 default:
827 NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
828 break;
829 }
830 break;
831
832 default:
833 NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
834 break;
835 }
836 }
837 else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
838 {
839 switch (m_reassemblingState)
840 {
841 case WAITING_S0_FULL:
842 switch (framingInfo)
843 {
846
850 for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
851 {
853 }
854 m_sdusBuffer.clear ();
855 break;
856
859
863 while ( m_sdusBuffer.size () > 1 )
864 {
866 m_sdusBuffer.pop_front ();
867 }
868
872 m_keepS0 = m_sdusBuffer.front ();
873 m_sdusBuffer.pop_front ();
874 break;
875
878
882 m_sdusBuffer.pop_front ();
883
887 while ( ! m_sdusBuffer.empty () )
888 {
890 m_sdusBuffer.pop_front ();
891 }
892 break;
893
895 if ( m_sdusBuffer.size () == 1 )
896 {
898 }
899 else
900 {
902 }
903
907 m_sdusBuffer.pop_front ();
908
909 if ( m_sdusBuffer.size () > 0 )
910 {
914 while ( m_sdusBuffer.size () > 1 )
915 {
917 m_sdusBuffer.pop_front ();
918 }
919
923 m_keepS0 = m_sdusBuffer.front ();
924 m_sdusBuffer.pop_front ();
925 }
926 break;
927
928 default:
932 NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
933 break;
934 }
935 break;
936
937 case WAITING_SI_SF:
938 switch (framingInfo)
939 {
942
946 m_keepS0 = 0;
947
951 while ( ! m_sdusBuffer.empty () )
952 {
954 m_sdusBuffer.pop_front ();
955 }
956 break;
957
960
964 m_keepS0 = 0;
965
969 while ( m_sdusBuffer.size () > 1 )
970 {
972 m_sdusBuffer.pop_front ();
973 }
974
978 m_keepS0 = m_sdusBuffer.front ();
979 m_sdusBuffer.pop_front ();
980
981 break;
982
985
989 m_keepS0 = 0;
990
994 m_sdusBuffer.pop_front ();
995
999 while ( ! m_sdusBuffer.empty () )
1000 {
1002 m_sdusBuffer.pop_front ();
1003 }
1004 break;
1005
1007 if ( m_sdusBuffer.size () == 1 )
1008 {
1010 }
1011 else
1012 {
1014 }
1015
1019 m_keepS0 = 0;
1020
1024 m_sdusBuffer.pop_front ();
1025
1026 if ( m_sdusBuffer.size () > 0 )
1027 {
1031 while ( m_sdusBuffer.size () > 1 )
1032 {
1034 m_sdusBuffer.pop_front ();
1035 }
1036
1040 m_keepS0 = m_sdusBuffer.front ();
1041 m_sdusBuffer.pop_front ();
1042 }
1043 break;
1044
1045 default:
1049 NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1050 break;
1051 }
1052 break;
1053
1054 default:
1055 NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1056 break;
1057 }
1058 }
1059
1060}
1061
1062
1063void
1065{
1066 NS_LOG_LOGIC ("Reassemble Outside Window");
1067
1068 std::map <uint16_t, Ptr<Packet> >::iterator it;
1069 it = m_rxBuffer.begin ();
1070
1071 while ( (it != m_rxBuffer.end ()) && ! IsInsideReorderingWindow (SequenceNumber10 (it->first)) )
1072 {
1073 NS_LOG_LOGIC ("SN = " << it->first);
1074
1075 // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1076 ReassembleAndDeliver (it->second);
1077
1078 std::map <uint16_t, Ptr<Packet> >::iterator it_tmp = it;
1079 ++it;
1080 m_rxBuffer.erase (it_tmp);
1081 }
1082
1083 if (it != m_rxBuffer.end ())
1084 {
1085 NS_LOG_LOGIC ("(SN = " << it->first << ") is inside the reordering window");
1086 }
1087}
1088
1089void
1091{
1092 NS_LOG_LOGIC ("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1093
1094 std::map <uint16_t, Ptr<Packet> >::iterator it;
1095
1096 SequenceNumber10 reassembleSn = lowSeqNumber;
1097 NS_LOG_LOGIC ("reassembleSN = " << reassembleSn);
1098 NS_LOG_LOGIC ("highSeqNumber = " << highSeqNumber);
1099 while (reassembleSn < highSeqNumber)
1100 {
1101 NS_LOG_LOGIC ("reassembleSn < highSeqNumber");
1102 it = m_rxBuffer.find (reassembleSn.GetValue ());
1103 NS_LOG_LOGIC ("it->first = " << it->first);
1104 NS_LOG_LOGIC ("it->second = " << it->second);
1105 if (it != m_rxBuffer.end () )
1106 {
1107 NS_LOG_LOGIC ("SN = " << it->first);
1108
1109 // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1110 ReassembleAndDeliver (it->second);
1111
1112 m_rxBuffer.erase (it);
1113 }
1114
1115 reassembleSn++;
1116 }
1117}
1118
1119
1120void
1122{
1123 Time holDelay (0);
1124 uint32_t queueSize = 0;
1125
1126 if (! m_txBuffer.empty ())
1127 {
1128 holDelay = Simulator::Now () - m_txBuffer.front().m_waitingSince;
1129
1130 queueSize = m_txBufferSize + 2 * m_txBuffer.size (); // Data in tx queue + estimated headers size
1131 }
1132
1134 r.rnti = m_rnti;
1135 r.lcid = m_lcid;
1136 r.txQueueSize = queueSize;
1137 r.txQueueHolDelay = holDelay.GetMilliSeconds () ;
1138 r.retxQueueSize = 0;
1139 r.retxQueueHolDelay = 0;
1140 r.statusPduSize = 0;
1141
1142 NS_LOG_LOGIC ("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay );
1144}
1145
1146
1147void
1149{
1150 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid);
1151 NS_LOG_LOGIC ("Reordering timer has expired");
1152
1153 // 5.1.2.2.4 Actions when t-Reordering expires
1154 // When t-Reordering expires, the receiving UM RLC entity shall:
1155 // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1156 // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing so
1157 // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered before;
1158 // - if VR(UH) > VR(UR):
1159 // - start t-Reordering;
1160 // - set VR(UX) to VR(UH).
1161
1162 std::map <uint16_t, Ptr<Packet> >::iterator it;
1163 SequenceNumber10 newVrUr = m_vrUx;
1164
1165 while ( (it = m_rxBuffer.find (newVrUr.GetValue ())) != m_rxBuffer.end () )
1166 {
1167 newVrUr++;
1168 }
1169 SequenceNumber10 oldVrUr = m_vrUr;
1170 m_vrUr = newVrUr;
1171 NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
1172
1173 ReassembleSnInterval (oldVrUr, m_vrUr);
1174
1175 if ( m_vrUh > m_vrUr)
1176 {
1177 NS_LOG_LOGIC ("Start reordering timer");
1180 m_vrUx = m_vrUh;
1181 NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
1182 }
1183}
1184
1185
1186void
1188{
1189 NS_LOG_LOGIC ("RBS Timer expires");
1190
1191 if (! m_txBuffer.empty ())
1192 {
1195 }
1196}
1197
1198} // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
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.
void PushExtensionBit(uint8_t extensionBit)
Push extension bit.
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
uint8_t PopExtensionBit(void)
Pop extension bit.
void SetSequenceNumber(SequenceNumber10 sequenceNumber)
Set sequence number.
void SetFramingInfo(uint8_t framingInfo)
Set framing info.
uint16_t PopLengthIndicator(void)
Pop length indicator.
virtual uint32_t GetSerializedSize(void) const
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:51
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
Definition: lte-rlc.h:144
uint8_t m_lcid
LCID.
Definition: lte-rlc.h:169
TracedCallback< Ptr< const Packet > > m_txDropTrace
The trace source fired when the RLC drops a packet before transmission.
Definition: lte-rlc.h:183
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:168
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:178
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:166
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc.cc:125
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:174
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...
void SetStatus(uint8_t status)
Set status function.
uint8_t GetStatus(void) const
Get status function.
LTE RLC Unacknowledged Mode (UM), see 3GPP TS 36.322.
Definition: lte-rlc-um.h:36
std::vector< TxPdu > m_txBuffer
Transmission buffer.
Definition: lte-rlc-um.h:121
SequenceNumber10 m_vrUr
VR(UR)
Definition: lte-rlc-um.h:132
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-um.h:155
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver function.
Definition: lte-rlc-um.cc:597
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-um.cc:1121
static TypeId GetTypeId(void)
Get the type ID.
Definition: lte-rlc-um.cc:55
uint32_t m_txBufferSize
transmit buffer size
Definition: lte-rlc-um.h:99
virtual void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams)
Receive PDU function.
Definition: lte-rlc-um.cc:410
virtual ~LteRlcUm()
Definition: lte-rlc-um.cc:49
void ReassembleOutsideWindow(void)
Reassemble outside window.
Definition: lte-rlc-um.cc:1064
Time m_reorderingTimerValue
Timers.
Definition: lte-rlc-um.h:144
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-um.h:160
ReassemblingState_t m_reassemblingState
reassembling state
Definition: lte-rlc-um.h:154
void ReassembleSnInterval(SequenceNumber10 lowSeqNumber, SequenceNumber10 highSeqNumber)
Reassemble SN interval function.
Definition: lte-rlc-um.cc:1090
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-um.h:146
SequenceNumber10 m_vrUx
VR(UX)
Definition: lte-rlc-um.h:133
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet.
Definition: lte-rlc-um.h:125
virtual void DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams)
MAC SAP.
Definition: lte-rlc-um.cc:128
uint16_t m_windowSize
Constants.
Definition: lte-rlc-um.h:139
virtual void DoNotifyHarqDeliveryFailure()
Notify HARQ delivery failure.
Definition: lte-rlc-um.cc:404
std::map< uint16_t, Ptr< Packet > > m_rxBuffer
Reception buffer.
Definition: lte-rlc-um.h:122
SequenceNumber10 m_vrUh
VR(UH)
Definition: lte-rlc-um.h:134
void ExpireRbsTimer(void)
Expire RBS timer.
Definition: lte-rlc-um.cc:1187
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc-um.cc:76
virtual void DoTransmitPdcpPdu(Ptr< Packet > p)
RLC SAP.
Definition: lte-rlc-um.cc:90
uint32_t m_maxTxBufferSize
maximum transmit buffer status
Definition: lte-rlc-um.h:98
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-um.h:145
void ExpireReorderingTimer(void)
Expire reordering timer.
Definition: lte-rlc-um.cc:1148
bool IsInsideReorderingWindow(SequenceNumber10 seqNumber)
Is inside reordering window function.
Definition: lte-rlc-um.cc:574
SequenceNumber10 m_sequenceNumber
State variables.
Definition: lte-rlc-um.h:130
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:939
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
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:227
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:912
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:37
Time GetSenderTimestamp(void) const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Definition: lte-rlc-tag.h:65
SequenceNumber10 class.
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
void SetModulusBase(SequenceNumber10 modulusBase)
Set modulus base.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:383
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:391
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#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:88
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1309
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:45
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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:1252
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:536
Parameters for LteMacSapProvider::ReportBufferStatus.
Definition: lte-mac-sap.h:68
uint32_t txQueueSize
the current size of the RLC transmission queue
Definition: lte-mac-sap.h:71
uint16_t retxQueueHolDelay
the Head Of Line delay of the retransmission queue
Definition: lte-mac-sap.h:74
uint16_t txQueueHolDelay
the Head Of Line delay of the transmission queue
Definition: lte-mac-sap.h:72
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
Definition: lte-mac-sap.h:73
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:70
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:69
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:75
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:46
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:48
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:49
uint8_t componentCarrierId
the component carrier id corresponding to the sending Mac istance
Definition: lte-mac-sap.h:52
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:50
Parameters for LteMacSapUser::ReceivePdu.
Definition: lte-mac-sap.h:157
Ptr< Packet > p
the RLC PDU to be received
Definition: lte-mac-sap.h:175
Parameters for LteMacSapUser::NotifyTxOpportunity.
Definition: lte-mac-sap.h:104
uint32_t bytes
the number of bytes to transmit
Definition: lte-mac-sap.h:129
uint8_t componentCarrierId
the component carrier id
Definition: lte-mac-sap.h:132
uint8_t layer
the layer of transmission (MIMO)
Definition: lte-mac-sap.h:130
Store an incoming (from layer above us) PDU, waiting to transmit it.
Definition: lte-rlc-um.h:104