A Discrete-Event Network Simulator
API
lte-rlc-am.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 * Nicola Baldo <nbaldo@cttc.es>
20 */
21
22#include "ns3/simulator.h"
23#include "ns3/log.h"
24
25#include "ns3/lte-rlc-am-header.h"
26#include "ns3/lte-rlc-am.h"
27#include "ns3/lte-rlc-sdu-status-tag.h"
28#include "ns3/lte-rlc-tag.h"
29
30
31namespace ns3 {
32
33NS_LOG_COMPONENT_DEFINE ("LteRlcAm");
34
36
37
39{
40 NS_LOG_FUNCTION (this);
41
42 // Buffers
44 m_retxBuffer.resize (1024);
46 m_txedBuffer.resize (1024);
48
51
52 // State variables: transmitting side
53 m_windowSize = 512;
54 m_vtA = 0;
56 m_vtS = 0;
57 m_pollSn = 0;
58
59 // State variables: receiving side
60 m_vrR = 0;
62 m_vrX = 0;
63 m_vrMs = 0;
64 m_vrH = 0;
65
66 // Counters
69
70 // Configurable parameters
72 m_pollPdu = 1;
73 m_pollByte = 50;
74
75 // SDU reassembling process
78
80}
81
83{
84 NS_LOG_FUNCTION (this);
85}
86
89{
90 static TypeId tid = TypeId ("ns3::LteRlcAm")
91 .SetParent<LteRlc> ()
92 .SetGroupName("Lte")
93 .AddConstructor<LteRlcAm> ()
94 .AddAttribute ("PollRetransmitTimer",
95 "Value of the t-PollRetransmit timer (See section 7.3 of 3GPP TS 36.322)",
99 .AddAttribute ("ReorderingTimer",
100 "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
101 TimeValue (MilliSeconds (10)),
104 .AddAttribute ("StatusProhibitTimer",
105 "Value of the t-StatusProhibit timer (See section 7.3 of 3GPP TS 36.322)",
106 TimeValue (MilliSeconds (10)),
109 .AddAttribute ("ReportBufferStatusTimer",
110 "How much to wait to issue a new Report Buffer Status since the last time "
111 "a new SDU was received",
112 TimeValue (MilliSeconds (20)),
115 .AddAttribute ("TxOpportunityForRetxAlwaysBigEnough",
116 "If true, always pretend that the size of a TxOpportunity is big enough "
117 "for retransmission. If false (default and realistic behavior), no retx "
118 "is performed unless the corresponding TxOpportunity is big enough.",
119 BooleanValue (false),
122 .AddAttribute ("MaxTxBufferSize",
123 "Maximum Size of the Transmission Buffer (in Bytes). If zero is configured, the buffer is unlimited.",
124 UintegerValue (10 * 1024),
126 MakeUintegerChecker<uint32_t> ())
127 ;
128 return tid;
129}
130
131void
133{
134 NS_LOG_FUNCTION (this);
139
141 m_txonBuffer.clear ();
143 m_txedBuffer.clear ();
145 m_retxBuffer.clear ();
147 m_rxonBuffer.clear ();
148 m_sdusBuffer.clear ();
149 m_keepS0 = 0;
151
153}
154
155
160void
162{
163 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
164
166 {
170 p->AddPacketTag (tag);
171
172 NS_LOG_LOGIC ("Txon Buffer: New packet added");
173 m_txonBuffer.push_back (TxPdu (p, Simulator::Now ()));
174 m_txonBufferSize += p->GetSize ();
175 NS_LOG_LOGIC ("NumOfBuffers = " << m_txonBuffer.size() );
176 NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
177 }
178 else
179 {
180 // Discard full RLC SDU
181 NS_LOG_LOGIC ("TxonBuffer is full. RLC SDU discarded");
182 NS_LOG_LOGIC ("MaxTxBufferSize = " << m_maxTxBufferSize);
183 NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
184 NS_LOG_LOGIC ("packet size = " << p->GetSize ());
185 m_txDropTrace (p);
186 }
187
192}
193
194
199void
201{
202 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << txOpParams.bytes);
203
204 if (txOpParams.bytes < 4)
205 {
206 // Stingy MAC: In general, we need more bytes.
207 // There are a more restrictive test for each particular case
208 NS_LOG_LOGIC ("TxOpportunity (size = " << txOpParams.bytes << ") too small");
209 NS_ASSERT_MSG (false, "TxOpportunity (size = " << txOpParams.bytes << ") too small.\n"
210 << "Your MAC scheduler is assigned too few resource blocks.");
211 return;
212 }
213
215 {
216 if (txOpParams.bytes < m_statusPduBufferSize)
217 {
218 // Stingy MAC: We need more bytes for the STATUS PDU
219 NS_LOG_LOGIC ("TxOpportunity (size = " << txOpParams.bytes << ") too small for the STATUS PDU (size = " << m_statusPduBufferSize << ")");
220 NS_ASSERT_MSG (false, "TxOpportunity (size = " << txOpParams.bytes << ") too small for the STATUS PDU (size = " << m_statusPduBufferSize << ")\n"
221 << "Your MAC scheduler is assigned too few resource blocks.");
222 return;
223 }
224
225 NS_LOG_LOGIC ("Sending STATUS PDU");
226
227 Ptr<Packet> packet = Create<Packet> ();
228 LteRlcAmHeader rlcAmHeader;
230
231 NS_LOG_LOGIC ("Check for SNs to NACK from " << m_vrR.GetValue() << " to " << m_vrMs.GetValue());
234 std::map<uint16_t, PduBuffer>::iterator pduIt;
235 for (sn = m_vrR; sn < m_vrMs; sn++)
236 {
237 NS_LOG_LOGIC ("SN = " << sn);
238 if (!rlcAmHeader.OneMoreNackWouldFitIn (txOpParams.bytes))
239 {
240 NS_LOG_LOGIC ("Can't fit more NACKs in STATUS PDU");
241 break;
242 }
243 pduIt = m_rxonBuffer.find (sn.GetValue ());
244 if (pduIt == m_rxonBuffer.end () || (!(pduIt->second.m_pduComplete)))
245 {
246 NS_LOG_LOGIC ("adding NACK_SN " << sn.GetValue ());
247 rlcAmHeader.PushNack (sn.GetValue ());
248 }
249 }
250 NS_LOG_LOGIC ("SN at end of NACK loop = " << sn);
251 // 3GPP TS 36.322 section 6.2.2.1.4 ACK SN
252 // find the SN of the next not received RLC Data PDU
253 // which is not reported as missing in the STATUS PDU.
254 pduIt = m_rxonBuffer.find (sn.GetValue ());
255 while ((sn < m_vrMs) && (pduIt != m_rxonBuffer.end ()) && (pduIt->second.m_pduComplete))
256 {
257 NS_LOG_LOGIC ("SN = " << sn << " < " << m_vrMs << " = " << (sn < m_vrMs));
258 sn++;
259 NS_LOG_LOGIC ("SN = " << sn);
260 pduIt = m_rxonBuffer.find (sn.GetValue ());
261 }
262
263 NS_ASSERT_MSG (sn <= m_vrMs, "first SN not reported as missing = " << sn << ", VR(MS) = " << m_vrMs);
264 rlcAmHeader.SetAckSn (sn);
265
266
267 NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
268 packet->AddHeader (rlcAmHeader);
269
270 // Sender timestamp
271 RlcTag rlcTag (Simulator::Now ());
272 packet->AddByteTag (rlcTag, 1, rlcAmHeader.GetSerializedSize ());
273 m_txPdu (m_rnti, m_lcid, packet->GetSize ());
274
275 // Send RLC PDU to MAC layer
277 params.pdu = packet;
278 params.rnti = m_rnti;
279 params.lcid = m_lcid;
280 params.layer = txOpParams.layer;
281 params.harqProcessId = txOpParams.harqId;
282 params.componentCarrierId = txOpParams.componentCarrierId;
283
285
286 m_statusPduRequested = false;
290 return;
291 }
292 else if ( m_retxBufferSize > 0 )
293 {
294 NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
295 NS_LOG_LOGIC ("Sending data from Retransmission Buffer");
299 for (sn = m_vtA; sn < m_vtS; sn++)
300 {
301 uint16_t seqNumberValue = sn.GetValue ();
302 NS_LOG_LOGIC ("SN = " << seqNumberValue << " m_pdu " << m_retxBuffer.at (seqNumberValue).m_pdu);
303
304 if (m_retxBuffer.at (seqNumberValue).m_pdu != 0)
305 {
306 Ptr<Packet> packet = m_retxBuffer.at (seqNumberValue).m_pdu->Copy ();
307
308 if (( packet->GetSize () <= txOpParams.bytes )
310 {
311 // According to 5.2.1, the data field is left as is, but we rebuild the header
312 LteRlcAmHeader rlcAmHeader;
313 packet->RemoveHeader (rlcAmHeader);
314 NS_LOG_LOGIC ("old AM RLC header: " << rlcAmHeader);
315
316 // Calculate the Polling Bit (5.2.2.1)
318
319 NS_LOG_LOGIC ("polling conditions: m_txonBuffer.empty=" << m_txonBuffer.empty ()
320 << " retxBufferSize=" << m_retxBufferSize
321 << " packet->GetSize ()=" << packet->GetSize ());
322 if (((m_txonBuffer.empty ()) && (m_retxBufferSize == packet->GetSize () + rlcAmHeader.GetSerializedSize ()))
323 || (m_vtS >= m_vtMs)
325 {
330
331 m_pollSn = m_vtS - 1;
332 NS_LOG_LOGIC ("New POLL_SN = " << m_pollSn);
333
335 {
336 NS_LOG_LOGIC ("Start PollRetransmit timer");
337
340 }
341 else
342 {
343 NS_LOG_LOGIC ("Restart PollRetransmit timer");
344
348 }
349 }
350
351 packet->AddHeader (rlcAmHeader);
352
353 RlcTag rlcTag;
355
356 packet->AddByteTag (rlcTag, 1, rlcAmHeader.GetSerializedSize ());
357
358 NS_LOG_LOGIC ("new AM RLC header: " << rlcAmHeader);
359
360 m_txPdu (m_rnti, m_lcid, packet->GetSize ());
361
362 // Send RLC PDU to MAC layer
364 params.pdu = packet;
365 params.rnti = m_rnti;
366 params.lcid = m_lcid;
367 params.layer = txOpParams.layer;
368 params.harqProcessId = txOpParams.harqId;
369 params.componentCarrierId = txOpParams.componentCarrierId;
370
372
373 m_retxBuffer.at (seqNumberValue).m_retxCount++;
374 m_retxBuffer.at (seqNumberValue).m_waitingSince = Simulator::Now ();
375 NS_LOG_INFO ("Incr RETX_COUNT for SN = " << seqNumberValue);
376 if (m_retxBuffer.at (seqNumberValue).m_retxCount >= m_maxRetxThreshold)
377 {
378 NS_LOG_INFO ("Max RETX_COUNT for SN = " << seqNumberValue);
379 }
380
381 NS_LOG_INFO ("Move SN = " << seqNumberValue << " back to txedBuffer");
382 m_txedBuffer.at (seqNumberValue).m_pdu = m_retxBuffer.at (seqNumberValue).m_pdu->Copy ();
383 m_txedBuffer.at (seqNumberValue).m_retxCount = m_retxBuffer.at (seqNumberValue).m_retxCount;
384 m_txedBuffer.at (seqNumberValue).m_waitingSince = m_retxBuffer.at (seqNumberValue).m_waitingSince;
385 m_txedBufferSize += m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
386
387 m_retxBufferSize -= m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
388 m_retxBuffer.at (seqNumberValue).m_pdu = 0;
389 m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
390 m_retxBuffer.at (seqNumberValue).m_waitingSince = MilliSeconds (0);
391
392 NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
393
394 return;
395 }
396 else
397 {
398 NS_LOG_LOGIC ("TxOpportunity (size = " << txOpParams.bytes << ") too small for retransmission of the packet (size = " << packet->GetSize () << ")");
399 NS_LOG_LOGIC ("Waiting for bigger TxOpportunity");
400 return;
401 }
402 }
403 }
404 NS_ASSERT_MSG (false, "m_retxBufferSize > 0, but no PDU considered for retx found");
405 }
406 else if ( m_txonBufferSize > 0 )
407 {
408 if (txOpParams.bytes < 7)
409 {
410 // Stingy MAC: We need more bytes for new DATA PDUs.
411 NS_LOG_LOGIC ("TxOpportunity (size = " << txOpParams.bytes << ") too small for DATA PDU");
412 NS_ASSERT_MSG (false, "TxOpportunity (size = " << txOpParams.bytes << ") too small for DATA PDU\n"
413 << "Your MAC scheduler is assigned too few resource blocks.");
414 return;
415 }
416
418 if (m_vtS == m_vtMs)
419 {
420 NS_LOG_INFO ("cannot transmit new RLC PDU due to window stalling");
421 return;
422 }
423
424 NS_LOG_LOGIC ("Sending data from Transmission Buffer");
425 }
426 else
427 {
428 NS_LOG_LOGIC ("No data pending");
429 return;
430 }
431
432 //
433 //
434 // Build new PDU
435 //
436 //
437
438 Ptr<Packet> packet = Create<Packet> ();
439 LteRlcAmHeader rlcAmHeader;
440 rlcAmHeader.SetDataPdu ();
441
442 // Build Data field
443 uint32_t nextSegmentSize = txOpParams.bytes - 4;
444 uint32_t nextSegmentId = 1;
445 uint32_t dataFieldAddedSize = 0;
446 std::vector < Ptr<Packet> > dataField;
447
448 // Remove the first packet from the transmission buffer.
449 // If only a segment of the packet is taken, then the remaining is given back later
450 if ( m_txonBuffer.size () == 0 )
451 {
452 NS_LOG_LOGIC ("No data pending");
453 return;
454 }
455
456 NS_LOG_LOGIC ("SDUs in TxonBuffer = " << m_txonBuffer.size ());
457 NS_LOG_LOGIC ("First SDU buffer = " << m_txonBuffer.begin ()->m_pdu);
458 NS_LOG_LOGIC ("First SDU size = " << m_txonBuffer.begin ()->m_pdu->GetSize ());
459 NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
460 NS_LOG_LOGIC ("Remove SDU from TxBuffer");
461 Time firstSegmentTime = m_txonBuffer.begin ()->m_waitingSince;
462 Ptr<Packet> firstSegment = m_txonBuffer.begin ()->m_pdu->Copy ();
463 m_txonBufferSize -= m_txonBuffer.begin ()->m_pdu->GetSize ();
464 NS_LOG_LOGIC ("txBufferSize = " << m_txonBufferSize );
465 m_txonBuffer.erase (m_txonBuffer.begin ());
466
467 while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
468 {
469 NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
470 NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
471 NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
472 if ( (firstSegment->GetSize () > nextSegmentSize) ||
473 // Segment larger than 2047 octets can only be mapped to the end of the Data field
474 (firstSegment->GetSize () > 2047)
475 )
476 {
477 // Take the minimum size, due to the 2047-bytes 3GPP exception
478 // This exception is due to the length of the LI field (just 11 bits)
479 uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
480
481 NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
482 NS_LOG_LOGIC (" firstSegment > 2047 )");
483
484 // Segment txBuffer.FirstBuffer and
485 // Give back the remaining segment to the transmission buffer
486 Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
487 NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
488
489 // Status tag of the new and remaining segments
490 // Note: This is the only place where a PDU is segmented and
491 // therefore its status can change
492 LteRlcSduStatusTag oldTag, newTag;
493 firstSegment->RemovePacketTag (oldTag);
494 newSegment->RemovePacketTag (newTag);
496 {
499 }
500 else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT)
501 {
503 //oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
504 }
505
506 // Give back the remaining segment to the transmission buffer
507 firstSegment->RemoveAtStart (currSegmentSize);
508 NS_LOG_LOGIC (" firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize ());
509 if (firstSegment->GetSize () > 0)
510 {
511 firstSegment->AddPacketTag (oldTag);
512
513 m_txonBuffer.insert (m_txonBuffer.begin (), TxPdu (firstSegment, firstSegmentTime));
514 m_txonBufferSize += m_txonBuffer.begin ()->m_pdu->GetSize ();
515
516 NS_LOG_LOGIC (" Txon buffer: Give back the remaining segment");
517 NS_LOG_LOGIC (" Txon buffers = " << m_txonBuffer.size ());
518 NS_LOG_LOGIC (" Front buffer size = " << m_txonBuffer.begin ()->m_pdu->GetSize ());
519 NS_LOG_LOGIC (" txonBufferSize = " << m_txonBufferSize );
520 }
521 else
522 {
523 // Whole segment was taken, so adjust tag
525 {
527 }
528 else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
529 {
531 }
532 }
533 // Segment is completely taken or
534 // the remaining segment is given back to the transmission buffer
535 firstSegment = 0;
536
537 // Put status tag once it has been adjusted
538 newSegment->AddPacketTag (newTag);
539
540 // Add Segment to Data field
541 dataFieldAddedSize = newSegment->GetSize ();
542 dataField.push_back (newSegment);
543 newSegment = 0;
544
545 // ExtensionBit (Next_Segment - 1) = 0
547
548 // no LengthIndicator for the last one
549
550 nextSegmentSize -= dataFieldAddedSize;
551 nextSegmentId++;
552
553 // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
554
555 // (NO more segments) ? exit
556 // break;
557 }
558 else if ( (nextSegmentSize - firstSegment->GetSize () <= 2) || (m_txonBuffer.size () == 0) )
559 {
560 NS_LOG_LOGIC (" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txonBuffer.size == 0");
561
562 // Add txBuffer.FirstBuffer to DataField
563 dataFieldAddedSize = firstSegment->GetSize ();
564 dataField.push_back (firstSegment);
565 firstSegment = 0;
566
567 // ExtensionBit (Next_Segment - 1) = 0
569
570 // no LengthIndicator for the last one
571
572 nextSegmentSize -= dataFieldAddedSize;
573 nextSegmentId++;
574
575 NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ());
576 if (m_txonBuffer.size () > 0)
577 {
578 NS_LOG_LOGIC (" First SDU buffer = " << m_txonBuffer.begin ()->m_pdu);
579 NS_LOG_LOGIC (" First SDU size = " << m_txonBuffer.begin ()->m_pdu->GetSize ());
580 }
581 NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
582
583 // nextSegmentSize <= 2 (only if txBuffer is not empty)
584
585 // (NO more segments) ? exit
586 // break;
587 }
588 else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
589 {
590 NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txonBuffer.size > 0");
591 // Add txBuffer.FirstBuffer to DataField
592 dataFieldAddedSize = firstSegment->GetSize ();
593 dataField.push_back (firstSegment);
594
595 // ExtensionBit (Next_Segment - 1) = 1
597
598 // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
599 rlcAmHeader.PushLengthIndicator (firstSegment->GetSize ());
600
601 nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
602 nextSegmentId++;
603
604 NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ());
605 if (m_txonBuffer.size () > 0)
606 {
607 NS_LOG_LOGIC (" First SDU buffer = " << m_txonBuffer.begin ()->m_pdu);
608 NS_LOG_LOGIC (" First SDU size = " << m_txonBuffer.begin ()->m_pdu->GetSize ());
609 }
610 NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
611 NS_LOG_LOGIC (" Remove SDU from TxBuffer");
612
613 // (more segments)
614 firstSegment = m_txonBuffer.begin ()->m_pdu->Copy ();
615 firstSegmentTime = m_txonBuffer.begin ()->m_waitingSince;
616 m_txonBufferSize -= m_txonBuffer.begin ()->m_pdu->GetSize ();
617 m_txonBuffer.erase (m_txonBuffer.begin ());
618 NS_LOG_LOGIC (" txBufferSize = " << m_txonBufferSize );
619 }
620
621 }
622
623 //
624 // Build RLC header
625 //
626
627 rlcAmHeader.SetSequenceNumber ( m_vtS++ );
630 rlcAmHeader.SetSegmentOffset (0);
631
632 NS_ASSERT_MSG(rlcAmHeader.GetSequenceNumber () < m_vtMs, "SN above TX window");
633 NS_ASSERT_MSG(rlcAmHeader.GetSequenceNumber () >= m_vtA, "SN below TX window");
634
635 // Calculate FramingInfo flag according the status of the SDUs in the DataField
636 uint8_t framingInfo = 0;
637 std::vector< Ptr<Packet> >::iterator it;
638 it = dataField.begin ();
639
640 // FIRST SEGMENT
642 NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
643 (*it)->PeekPacketTag (tag);
644 if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
646 )
647 {
648 framingInfo |= LteRlcAmHeader::FIRST_BYTE;
649 }
650 else
651 {
652 framingInfo |= LteRlcAmHeader::NO_FIRST_BYTE;
653 }
654
655 // Add all SDUs (in DataField) to the Packet
656 while (it < dataField.end ())
657 {
658 NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ());
659
660 NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
661 (*it)->RemovePacketTag (tag);
662 if (packet->GetSize () > 0)
663 {
664 packet->AddAtEnd (*it);
665 }
666 else
667 {
668 packet = (*it);
669 }
670 it++;
671 }
672
673 // LAST SEGMENT (Note: There could be only one and be the first one)
674 it--;
675 if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
677 {
678 framingInfo |= LteRlcAmHeader::LAST_BYTE;
679 }
680 else
681 {
682 framingInfo |= LteRlcAmHeader::NO_LAST_BYTE;
683 }
684
685 // Set the FramingInfo flag after the calculation
686 rlcAmHeader.SetFramingInfo (framingInfo);
687
688
689 // Calculate the Polling Bit (5.2.2.1)
691
693 NS_LOG_LOGIC ("PDU_WITHOUT_POLL = " << m_pduWithoutPoll);
694 m_byteWithoutPoll += packet->GetSize ();
695 NS_LOG_LOGIC ("BYTE_WITHOUT_POLL = " << m_byteWithoutPoll);
696
698 ( (m_txonBuffer.empty ()) && (m_retxBufferSize == 0) ) ||
699 (m_vtS >= m_vtMs)
701 )
702 {
707
708 m_pollSn = m_vtS - 1;
709 NS_LOG_LOGIC ("New POLL_SN = " << m_pollSn);
710
712 {
713 NS_LOG_LOGIC ("Start PollRetransmit timer");
714
717 }
718 else
719 {
720 NS_LOG_LOGIC ("Restart PollRetransmit timer");
721
725 }
726 }
727
728
729 // Build RLC PDU with DataField and Header
730 NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
731
732 RlcTag rlcTag;
734
735 packet->AddHeader (rlcAmHeader);
736 packet->AddByteTag (rlcTag, 1, rlcAmHeader.GetSerializedSize ());
737
738 // Store new PDU into the Transmitted PDU Buffer
739 NS_LOG_LOGIC ("Put transmitted PDU in the txedBuffer");
740 m_txedBufferSize += packet->GetSize ();
741 m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_pdu = packet->Copy ();
742 m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_retxCount = 0;
743 m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_waitingSince = Simulator::Now ();
744
745 m_txPdu (m_rnti, m_lcid, packet->GetSize ());
746
747 // Send RLC PDU to MAC layer
749 params.pdu = packet;
750 params.rnti = m_rnti;
751 params.lcid = m_lcid;
752 params.layer = txOpParams.layer;
753 params.harqProcessId = txOpParams.harqId;
754 params.componentCarrierId = txOpParams.componentCarrierId;
755
757}
758
759void
761{
762 NS_LOG_FUNCTION (this);
763}
764
765
766void
768{
769 NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << rxPduParams.p->GetSize ());
770
771 // Get RLC header parameters
772 LteRlcAmHeader rlcAmHeader;
773 rxPduParams.p->PeekHeader (rlcAmHeader);
774 NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
775
776 // Receiver timestamp
777 Time delay;
778 RlcTag rlcTag;
779
780 bool ret = rxPduParams.p->FindFirstMatchingByteTag (rlcTag);
781 NS_ASSERT_MSG(ret, "RlcTag not found in RLC Header. The packet went into a real network?");
782
783 delay = Simulator::Now () - rlcTag.GetSenderTimestamp ();
784
785 m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), delay.GetNanoSeconds ());
786
787 if ( rlcAmHeader.IsDataPdu () )
788 {
789
790 // 5.1.3.1 Transmit operations
791
792 // 5.1.3.1.1 General
793 //
794 // The transmitting side of an AM RLC entity shall prioritize transmission of RLC control PDUs
795 // over RLC data PDUs. The transmitting side of an AM RLC entity shall prioritize retransmission
796 // of RLC data PDUs over transmission of new AMD PDUs.
797 //
798 // The transmitting side of an AM RLC entity shall maintain a transmitting window according to
799 // state variables VT(A) and VT(MS) as follows:
800 // - a SN falls within the transmitting window if VT(A) <= SN < VT(MS);
801 // - a SN falls outside of the transmitting window otherwise.
802 //
803 // The transmitting side of an AM RLC entity shall not deliver to lower layer any RLC data PDU
804 // whose SN falls outside of the transmitting window.
805 //
806 // When delivering a new AMD PDU to lower layer, the transmitting side of an AM RLC entity shall:
807 // - set the SN of the AMD PDU to VT(S), and then increment VT(S) by one.
808 //
809 // The transmitting side of an AM RLC entity can receive a positive acknowledgement (confirmation
810 // of successful reception by its peer AM RLC entity) for a RLC data PDU by the following:
811 // - STATUS PDU from its peer AM RLC entity.
812 //
813 // When receiving a positive acknowledgement for an AMD PDU with SN = VT(A), the transmitting
814 // side of an AM RLC entity shall:
815 // - set VT(A) equal to the SN of the AMD PDU with the smallest SN, whose SN falls within the
816 // range VT(A) <= SN <= VT(S) and for which a positive acknowledgment has not been received yet.
817 // - if positive acknowledgements have been received for all AMD PDUs associated with
818 // a transmitted RLC SDU:
819 // - send an indication to the upper layers of successful delivery of the RLC SDU.
820
821
822 // 5.1.3.2 Receive operations
823 //
824 // 5.1.3.2.1 General
825 //
826 // The receiving side of an AM RLC entity shall maintain a receiving window according to state
827 // variables VR(R) and VR(MR) as follows:
828 // - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
829 // - a SN falls outside of the receiving window otherwise.
830 //
831 // When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity shall:
832 // - either discard the received RLC data PDU or place it in the reception buffer (see sub clause 5.1.3.2.2);
833 // - if the received RLC data PDU was placed in the reception buffer:
834 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop t-Reordering as needed (see sub clause 5.1.3.2.3).
835 //
836 // When t-Reordering expires, the receiving side of an AM RLC entity shall:
837 // - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
838
839
840 SequenceNumber10 seqNumber = rlcAmHeader.GetSequenceNumber ();
841 seqNumber.SetModulusBase (m_vrR);
842
843 if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::SEGMENT )
844 {
845 NS_LOG_LOGIC ("PDU segment received ( SN = " << seqNumber << " )");
846 }
847 else if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::PDU )
848 {
849 NS_LOG_LOGIC ("PDU received ( SN = " << seqNumber << " )");
850 }
851 else
852 {
853 NS_ASSERT_MSG (false, "Neither a PDU segment nor a PDU received");
854 return ;
855 }
856
857 // STATUS PDU is requested
859 {
862
864 {
866 }
867 }
868
869 // 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
870 //
871 // When a RLC data PDU is received from lower layer, where the RLC data PDU contains
872 // byte segment numbers y to z of an AMD PDU with SN = x, the receiving side of an AM RLC entity shall:
873 // - if x falls outside of the receiving window; or
874 // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
875 // - discard the received RLC data PDU;
876 // - else:
877 // - place the received RLC data PDU in the reception buffer;
878 // - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
879 // - discard the duplicate byte segments.
880
881 NS_LOG_LOGIC ("VR(R) = " << m_vrR);
882 NS_LOG_LOGIC ("VR(MR) = " << m_vrMr);
883 NS_LOG_LOGIC ("VR(X) = " << m_vrX);
884 NS_LOG_LOGIC ("VR(MS) = " << m_vrMs);
885 NS_LOG_LOGIC ("VR(H) = " << m_vrH);
886
887 // - if x falls outside of the receiving window; or
888 // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
889 if ( ! IsInsideReceivingWindow (seqNumber) )
890 {
891 NS_LOG_LOGIC ("PDU discarded");
892 return;
893 }
894 else
895 {
896 // - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
897 // - discard the duplicate byte segments.
898 // note: re-segmentation of AMD PDU is currently not supported,
899 // so we just check that the segment was not received before
900 std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (seqNumber.GetValue ());
901 if (it != m_rxonBuffer.end () )
902 {
903 NS_ASSERT (it->second.m_byteSegments.size () > 0);
904 NS_ASSERT_MSG (it->second.m_byteSegments.size () == 1, "re-segmentation not supported");
905 NS_LOG_LOGIC ("PDU segment already received, discarded");
906 }
907 else
908 {
909 NS_LOG_LOGIC ("Place PDU in the reception buffer ( SN = " << seqNumber << " )");
910 m_rxonBuffer[ seqNumber.GetValue () ].m_byteSegments.push_back (rxPduParams.p);
911 m_rxonBuffer[ seqNumber.GetValue () ].m_pduComplete = true;
912 }
913
914
915 }
916
917 // 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception buffer
918 // When a RLC data PDU with SN = x is placed in the reception buffer,
919 // the receiving side of an AM RLC entity shall:
920
921 // - if x >= VR(H)
922 // - update VR(H) to x+ 1;
923
924 if ( seqNumber >= m_vrH )
925 {
926 m_vrH = seqNumber + 1;
927 NS_LOG_LOGIC ("New VR(H) = " << m_vrH);
928 }
929
930 // - if all byte segments of the AMD PDU with SN = VR(MS) are received:
931 // - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for
932 // which not all byte segments have been received;
933
934 std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (m_vrMs.GetValue ());
935 if ( it != m_rxonBuffer.end () &&
936 it->second.m_pduComplete )
937 {
938 int firstVrMs = m_vrMs.GetValue ();
939 while ( it != m_rxonBuffer.end () &&
940 it->second.m_pduComplete )
941 {
942 m_vrMs++;
943 it = m_rxonBuffer.find (m_vrMs.GetValue ());
944 NS_LOG_LOGIC ("Incr VR(MS) = " << m_vrMs);
945
946 NS_ASSERT_MSG (firstVrMs != m_vrMs.GetValue (), "Infinite loop in RxonBuffer");
947 }
948 NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
949 }
950
951 // - if x = VR(R):
952 // - if all byte segments of the AMD PDU with SN = VR(R) are received:
953 // - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which not all byte segments have been received;
954 // - update VR(MR) to the updated VR(R) + AM_Window_Size;
955 // - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside of the receiving window and in-sequence byte segments of the AMD PDU with SN = VR(R), remove RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in sequence if not delivered before;
956
957 if ( seqNumber == m_vrR )
958 {
959 std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (seqNumber.GetValue ());
960 if ( it != m_rxonBuffer.end () &&
961 it->second.m_pduComplete )
962 {
963 it = m_rxonBuffer.find (m_vrR.GetValue ());
964 int firstVrR = m_vrR.GetValue ();
965 while ( it != m_rxonBuffer.end () &&
966 it->second.m_pduComplete )
967 {
968 NS_LOG_LOGIC ("Reassemble and Deliver ( SN = " << m_vrR << " )");
969 NS_ASSERT_MSG (it->second.m_byteSegments.size () == 1,
970 "Too many segments. PDU Reassembly process didn't work");
971 ReassembleAndDeliver (it->second.m_byteSegments.front ());
972 m_rxonBuffer.erase (m_vrR.GetValue ());
973
974 m_vrR++;
979 it = m_rxonBuffer.find (m_vrR.GetValue ());
980
981 NS_ASSERT_MSG (firstVrR != m_vrR.GetValue (), "Infinite loop in RxonBuffer");
982 }
983 NS_LOG_LOGIC ("New VR(R) = " << m_vrR);
985
986 NS_LOG_LOGIC ("New VR(MR) = " << m_vrMr);
987 }
988
989 }
990
991 // - if t-Reordering is running:
992 // - if VR(X) = VR(R); or
993 // - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
994 // - stop and reset t-Reordering;
995
997 {
998 NS_LOG_LOGIC ("Reordering timer is running");
999 if ( (m_vrX == m_vrR) ||
1000 ( (! IsInsideReceivingWindow (m_vrX)) && (m_vrX != m_vrMr) )
1001 )
1002 {
1004 NS_LOG_LOGIC ("Stop reordering timer");
1006 }
1007 }
1008
1009 // - if t-Reordering is not running (includes the case t-Reordering is stopped due to actions above):
1010 // - if VR (H) > VR(R):
1011 // - start t-Reordering;
1012 // - set VR(X) to VR(H).
1013
1014 if ( ! m_reorderingTimer.IsRunning () )
1015 {
1016 NS_LOG_LOGIC ("Reordering timer is not running");
1017 if ( m_vrH > m_vrR )
1018 {
1019 NS_LOG_LOGIC ("Start reordering timer");
1022 m_vrX = m_vrH;
1023 NS_LOG_LOGIC ("New VR(X) = " << m_vrX);
1024 }
1025 }
1026 }
1027 else if ( rlcAmHeader.IsControlPdu () )
1028 {
1029 NS_LOG_INFO ("Control AM RLC PDU");
1030
1031 SequenceNumber10 ackSn = rlcAmHeader.GetAckSn ();
1033
1034 NS_LOG_INFO ("ackSn = " << ackSn);
1035 NS_LOG_INFO ("VT(A) = " << m_vtA);
1036 NS_LOG_INFO ("VT(S) = " << m_vtS);
1037 NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1038 NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1039
1043 ackSn.SetModulusBase (m_vtA);
1044 sn.SetModulusBase (m_vtA);
1045
1046 bool incrementVtA = true;
1047
1048 for (sn = m_vtA; sn < ackSn && sn < m_vtS; sn++)
1049 {
1050 NS_LOG_LOGIC ("sn = " << sn);
1051
1052 uint16_t seqNumberValue = sn.GetValue ();
1053
1055 && (seqNumberValue == m_pollSn.GetValue ()))
1056 {
1058 }
1059
1060 if (rlcAmHeader.IsNackPresent (sn))
1061 {
1062 NS_LOG_LOGIC ("sn " << sn << " is NACKed");
1063
1064 incrementVtA = false;
1065
1066 if (m_txedBuffer.at (seqNumberValue).m_pdu != 0)
1067 {
1068 NS_LOG_INFO ("Move SN = " << seqNumberValue << " to retxBuffer");
1069 m_retxBuffer.at (seqNumberValue).m_pdu = m_txedBuffer.at (seqNumberValue).m_pdu->Copy ();
1070 m_retxBuffer.at (seqNumberValue).m_retxCount = m_txedBuffer.at (seqNumberValue).m_retxCount;
1071 m_retxBuffer.at (seqNumberValue).m_waitingSince = m_txedBuffer.at (seqNumberValue).m_waitingSince;
1072 m_retxBufferSize += m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
1073
1074 m_txedBufferSize -= m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
1075 m_txedBuffer.at (seqNumberValue).m_pdu = 0;
1076 m_txedBuffer.at (seqNumberValue).m_retxCount = 0;
1077 m_txedBuffer.at (seqNumberValue).m_waitingSince = MilliSeconds (0);
1078 }
1079
1080 NS_ASSERT (m_retxBuffer.at (seqNumberValue).m_pdu != 0);
1081
1082 }
1083 else
1084 {
1085 NS_LOG_LOGIC ("sn " << sn << " is ACKed");
1086
1087 if (m_txedBuffer.at (seqNumberValue).m_pdu)
1088 {
1089 NS_LOG_INFO ("ACKed SN = " << seqNumberValue << " from txedBuffer");
1090 // NS_LOG_INFO ("m_txedBuffer( " << m_vtA << " )->GetSize = " << m_txedBuffer.at (m_vtA.GetValue ())->GetSize ());
1091 m_txedBufferSize -= m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
1092 m_txedBuffer.at (seqNumberValue).m_pdu = 0;
1093 m_txedBuffer.at (seqNumberValue).m_waitingSince = MilliSeconds (0);
1094 NS_ASSERT (m_retxBuffer.at (seqNumberValue).m_pdu == 0);
1095 }
1096
1097 if (m_retxBuffer.at (seqNumberValue).m_pdu)
1098 {
1099 NS_LOG_INFO ("ACKed SN = " << seqNumberValue << " from retxBuffer");
1100 m_retxBufferSize -= m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
1101 m_retxBuffer.at (seqNumberValue).m_pdu = 0;
1102 m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
1103 m_retxBuffer.at (seqNumberValue).m_waitingSince = MilliSeconds (0);
1104 }
1105
1106 }
1107
1108 NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1109 NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1110
1111 if (incrementVtA)
1112 {
1113 m_vtA++;
1115 NS_LOG_INFO ("New VT(A) = " << m_vtA);
1119 ackSn.SetModulusBase (m_vtA);
1120 sn.SetModulusBase (m_vtA);
1121 }
1122
1123 } // loop over SN : VT(A) <= SN < ACK SN
1124
1125 return;
1126
1127 }
1128 else
1129 {
1130 NS_LOG_WARN ("Wrong AM RLC PDU type");
1131 return;
1132 }
1133
1134}
1135
1136
1137bool
1139{
1140 NS_LOG_FUNCTION (this << seqNumber);
1141 NS_LOG_LOGIC ("Receiving Window: " <<
1142 m_vrR << " <= " << seqNumber << " <= " << m_vrMr);
1143
1146 seqNumber.SetModulusBase (m_vrR);
1147
1148 if ( (m_vrR <= seqNumber) && (seqNumber < m_vrMr ) )
1149 {
1150 NS_LOG_LOGIC (seqNumber << " is INSIDE the receiving window");
1151 return true;
1152 }
1153 else
1154 {
1155 NS_LOG_LOGIC (seqNumber << " is OUTSIDE the receiving window");
1156 return false;
1157 }
1158}
1159
1160
1161void
1163{
1164 LteRlcAmHeader rlcAmHeader;
1165 RlcTag rlcTag;
1166 bool ret = packet->FindFirstMatchingByteTag (rlcTag);
1167 NS_ASSERT(ret);
1168 packet->RemoveHeader (rlcAmHeader);
1169 ret = packet->FindFirstMatchingByteTag (rlcTag);
1170 NS_ASSERT(!ret);
1171 uint8_t framingInfo = rlcAmHeader.GetFramingInfo ();
1172 SequenceNumber10 currSeqNumber = rlcAmHeader.GetSequenceNumber ();
1173 bool expectedSnLost;
1174
1175 if ( currSeqNumber != m_expectedSeqNumber )
1176 {
1177 expectedSnLost = true;
1178 NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
1179 m_expectedSeqNumber = currSeqNumber + 1;
1180 }
1181 else
1182 {
1183 expectedSnLost = false;
1184 NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
1186 }
1187
1188 // Build list of SDUs
1189 uint8_t extensionBit;
1190 uint16_t lengthIndicator;
1191 do
1192 {
1193 extensionBit = rlcAmHeader.PopExtensionBit ();
1194 NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit);
1195
1196 if ( extensionBit == 0 )
1197 {
1198 m_sdusBuffer.push_back (packet);
1199 }
1200 else // extensionBit == 1
1201 {
1202 lengthIndicator = rlcAmHeader.PopLengthIndicator ();
1203 NS_LOG_LOGIC ("LI = " << lengthIndicator);
1204
1205 // Check if there is enough data in the packet
1206 if ( lengthIndicator >= packet->GetSize () )
1207 {
1208 NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator);
1210 }
1211
1212 // Split packet in two fragments
1213 Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator);
1214 packet->RemoveAtStart (lengthIndicator);
1215
1216 m_sdusBuffer.push_back (data_field);
1217 }
1218 }
1219 while ( extensionBit == 1 );
1220
1221 std::list < Ptr<Packet> >::iterator it;
1222
1223 // Current reassembling state
1224 if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'");
1225 else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'");
1226 else NS_LOG_LOGIC ("Reassembling State = Unknown state");
1227
1228
1229 // Received framing Info
1230 NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
1231 NS_LOG_LOGIC ("m_sdusBuffer = " << m_sdusBuffer.size ());
1232
1233 // Reassemble the list of SDUs (when there is no losses)
1234 if (!expectedSnLost)
1235 {
1236 switch (m_reassemblingState)
1237 {
1238 case WAITING_S0_FULL:
1239 switch (framingInfo)
1240 {
1243
1247 for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
1248 {
1250 }
1251 m_sdusBuffer.clear ();
1252 break;
1253
1256
1260 while ( m_sdusBuffer.size () > 1 )
1261 {
1263 m_sdusBuffer.pop_front ();
1264 }
1265
1269 m_keepS0 = m_sdusBuffer.front ();
1270 m_sdusBuffer.pop_front ();
1271 break;
1272
1275 default:
1279 NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1280 break;
1281 }
1282 break;
1283
1284 case WAITING_SI_SF:
1285 switch (framingInfo)
1286 {
1289
1293 m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1294 m_sdusBuffer.pop_front ();
1296
1300 while ( ! m_sdusBuffer.empty () )
1301 {
1303 m_sdusBuffer.pop_front ();
1304 }
1305 break;
1306
1309
1313 if ( m_sdusBuffer.size () == 1 )
1314 {
1315 m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1316 m_sdusBuffer.pop_front ();
1317 }
1318 else // m_sdusBuffer.size () > 1
1319 {
1323 m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1324 m_sdusBuffer.pop_front ();
1326
1330 while ( m_sdusBuffer.size () > 1 )
1331 {
1333 m_sdusBuffer.pop_front ();
1334 }
1335
1339 m_keepS0 = m_sdusBuffer.front ();
1340 m_sdusBuffer.pop_front ();
1341 }
1342 break;
1343
1346 default:
1350 NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1351 break;
1352 }
1353 break;
1354
1355 default:
1356 NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1357 break;
1358 }
1359 }
1360 else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
1361 {
1362 switch (m_reassemblingState)
1363 {
1364 case WAITING_S0_FULL:
1365 switch (framingInfo)
1366 {
1369
1373 for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
1374 {
1376 }
1377 m_sdusBuffer.clear ();
1378 break;
1379
1382
1386 while ( m_sdusBuffer.size () > 1 )
1387 {
1389 m_sdusBuffer.pop_front ();
1390 }
1391
1395 m_keepS0 = m_sdusBuffer.front ();
1396 m_sdusBuffer.pop_front ();
1397 break;
1398
1401
1405 m_sdusBuffer.pop_front ();
1406
1410 while ( ! m_sdusBuffer.empty () )
1411 {
1413 m_sdusBuffer.pop_front ();
1414 }
1415 break;
1416
1418 if ( m_sdusBuffer.size () == 1 )
1419 {
1421 }
1422 else
1423 {
1425 }
1426
1430 m_sdusBuffer.pop_front ();
1431
1432 if ( m_sdusBuffer.size () > 0 )
1433 {
1437 while ( m_sdusBuffer.size () > 1 )
1438 {
1440 m_sdusBuffer.pop_front ();
1441 }
1442
1446 m_keepS0 = m_sdusBuffer.front ();
1447 m_sdusBuffer.pop_front ();
1448 }
1449 break;
1450
1451 default:
1455 NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1456 break;
1457 }
1458 break;
1459
1460 case WAITING_SI_SF:
1461 switch (framingInfo)
1462 {
1465
1469 m_keepS0 = 0;
1470
1474 while ( ! m_sdusBuffer.empty () )
1475 {
1477 m_sdusBuffer.pop_front ();
1478 }
1479 break;
1480
1483
1487 m_keepS0 = 0;
1488
1492 while ( m_sdusBuffer.size () > 1 )
1493 {
1495 m_sdusBuffer.pop_front ();
1496 }
1497
1501 m_keepS0 = m_sdusBuffer.front ();
1502 m_sdusBuffer.pop_front ();
1503
1504 break;
1505
1508
1512 m_keepS0 = 0;
1513
1517 m_sdusBuffer.pop_front ();
1518
1522 while ( ! m_sdusBuffer.empty () )
1523 {
1525 m_sdusBuffer.pop_front ();
1526 }
1527 break;
1528
1530 if ( m_sdusBuffer.size () == 1 )
1531 {
1533 }
1534 else
1535 {
1537 }
1538
1542 m_keepS0 = 0;
1543
1547 m_sdusBuffer.pop_front ();
1548
1549 if ( m_sdusBuffer.size () > 0 )
1550 {
1554 while ( m_sdusBuffer.size () > 1 )
1555 {
1557 m_sdusBuffer.pop_front ();
1558 }
1559
1563 m_keepS0 = m_sdusBuffer.front ();
1564 m_sdusBuffer.pop_front ();
1565 }
1566 break;
1567
1568 default:
1572 NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1573 break;
1574 }
1575 break;
1576
1577 default:
1578 NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1579 break;
1580 }
1581 }
1582
1583}
1584
1585void
1587{
1588 NS_LOG_FUNCTION (this);
1589
1590 Time now = Simulator::Now ();
1591
1592 NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
1593 NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1594 NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1595 NS_LOG_LOGIC ("VT(A) = " << m_vtA);
1596 NS_LOG_LOGIC ("VT(S) = " << m_vtS);
1597
1598 // Transmission Queue HOL time
1599 Time txonQueueHolDelay (0);
1600 if ( m_txonBufferSize > 0 )
1601 {
1602 txonQueueHolDelay = now - m_txonBuffer.front ().m_waitingSince;
1603 }
1604
1605 // Retransmission Queue HOL time
1606 Time retxQueueHolDelay;
1607 if ( m_retxBufferSize > 0 )
1608 {
1609 Time senderTimestamp;
1610 if (m_retxBuffer.at (m_vtA.GetValue ()).m_pdu != 0)
1611 {
1612 senderTimestamp = m_retxBuffer.at (m_vtA.GetValue ()).m_waitingSince;
1613 }
1614 else
1615 {
1616 senderTimestamp = m_txedBuffer.at (m_vtA.GetValue ()).m_waitingSince;
1617 }
1618 retxQueueHolDelay = now - senderTimestamp;
1619 }
1620 else
1621 {
1622 retxQueueHolDelay = Seconds (0);
1623 }
1624
1626 r.rnti = m_rnti;
1627 r.lcid = m_lcid;
1629 r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds ();
1631 r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds ();
1632
1634 {
1636 }
1637 else
1638 {
1639 r.statusPduSize = 0;
1640 }
1641
1642 if ( r.txQueueSize != 0 || r.retxQueueSize != 0 || r.statusPduSize != 0 )
1643 {
1644 NS_LOG_INFO ("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay << ", "
1645 << r.retxQueueSize << ", " << r.retxQueueHolDelay << ", "
1646 << r.statusPduSize);
1648 }
1649 else
1650 {
1651 NS_LOG_INFO ("ReportBufferStatus don't needed");
1652 }
1653}
1654
1655
1656void
1658{
1659 NS_LOG_FUNCTION (this);
1660 NS_LOG_LOGIC ("Reordering Timer has expired");
1661
1662 // 5.1.3.2.4 Actions when t-Reordering expires
1663 // When t-Reordering expires, the receiving side of an AM RLC entity shall:
1664 // - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte segments
1665 // have been received;
1666 // - if VR(H) > VR(MS):
1667 // - start t-Reordering;
1668 // - set VR(X) to VR(H).
1669
1670 m_vrMs = m_vrX;
1671 int firstVrMs = m_vrMs.GetValue ();
1672 std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (m_vrMs.GetValue ());
1673 while ( it != m_rxonBuffer.end () &&
1674 it->second.m_pduComplete )
1675 {
1676 m_vrMs++;
1677 it = m_rxonBuffer.find (m_vrMs.GetValue ());
1678
1679 NS_ASSERT_MSG (firstVrMs != m_vrMs.GetValue (), "Infinite loop in ExpireReorderingTimer");
1680 }
1681 NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
1682
1683 if ( m_vrH > m_vrMs )
1684 {
1685 NS_LOG_LOGIC ("Start reordering timer");
1688 m_vrX = m_vrH;
1689 NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
1690 }
1691
1692 // Section 5.2.3 Status Reporting:
1693 // - The receiving side of an AM RLC entity shall trigger a
1694 // STATUS report when T_reordering expires.
1695 m_statusPduRequested = true;
1696}
1697
1698void
1700{
1701 NS_LOG_FUNCTION (this);
1702 NS_LOG_LOGIC ("PollRetransmit Timer has expired");
1703
1704 NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
1705 NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1706 NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1707 NS_LOG_LOGIC ("statusPduRequested = " << m_statusPduRequested);
1708
1710
1711 // see section 5.2.2.3
1712 // note the difference between Rel 8 and Rel 11 specs; we follow Rel 11 here
1713 NS_ASSERT (m_vtS <= m_vtMs);
1714 if ((m_txonBufferSize == 0 && m_retxBufferSize == 0)
1715 || (m_vtS == m_vtMs))
1716 {
1717 NS_LOG_INFO ("txonBuffer and retxBuffer empty. Move PDUs up to = " << m_vtS.GetValue () - 1 << " to retxBuffer");
1718 for (SequenceNumber10 sn = m_vtA; sn < m_vtS; sn++)
1719 {
1720 bool pduAvailable = m_txedBuffer.at (sn.GetValue ()).m_pdu != 0;
1721
1722 if ( pduAvailable )
1723 {
1724 uint16_t snValue = sn.GetValue ();
1725 NS_LOG_INFO ("Move PDU " << sn << " from txedBuffer to retxBuffer");
1726 m_retxBuffer.at (snValue).m_pdu = m_txedBuffer.at (snValue).m_pdu->Copy ();
1727 m_retxBuffer.at (snValue).m_retxCount = m_txedBuffer.at (snValue).m_retxCount;
1728 m_retxBuffer.at (snValue).m_waitingSince = m_txedBuffer.at (snValue).m_waitingSince;
1729 m_retxBufferSize += m_retxBuffer.at (snValue).m_pdu->GetSize ();
1730
1731 m_txedBufferSize -= m_txedBuffer.at (snValue).m_pdu->GetSize ();
1732 m_txedBuffer.at (snValue).m_pdu = 0;
1733 m_txedBuffer.at (snValue).m_retxCount = 0;
1734 m_txedBuffer.at (snValue).m_waitingSince = MilliSeconds (0);
1735 }
1736 }
1737 }
1738
1740}
1741
1742
1743void
1745{
1746 NS_LOG_FUNCTION (this);
1747}
1748
1749void
1751{
1752 NS_LOG_LOGIC ("RBS Timer expires");
1753
1755 {
1758 }
1759}
1760
1761} // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
AttributeValue implementation for Boolean.
Definition: boolean.h:37
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 AM Radio Link Control (RLC) protocol packets.
uint8_t GetPollingBit() const
Get polling bit function.
void SetSegmentOffset(uint16_t segmentOffset)
Set segment offset function.
void PushExtensionBit(uint8_t extensionBit)
Push extension bit function.
SequenceNumber10 GetAckSn() const
Get ack sn function.
void SetPollingBit(uint8_t pollingBit)
Set polling bit function.
bool OneMoreNackWouldFitIn(uint16_t bytes)
void SetLastSegmentFlag(uint8_t lsf)
Set last segment flag function.
uint8_t PopExtensionBit(void)
Pop extension bit function.
void PushNack(int nack)
Add one more NACK to the CONTROL PDU.
bool IsControlPdu(void) const
Is control PDU function.
void SetDataPdu(void)
Set data PDU function.
void SetFramingInfo(uint8_t framingInfo)
Set sequence number.
virtual uint32_t GetSerializedSize(void) const
bool IsDataPdu(void) const
Is data PDU function.
uint16_t PopLengthIndicator(void)
Pop length indicator function.
void SetAckSn(SequenceNumber10 ackSn)
Set ack sn function.
void PushLengthIndicator(uint16_t lengthIndicator)
Push length indicator function.
uint8_t GetResegmentationFlag() const
Get resegmentation flag function.
void SetResegmentationFlag(uint8_t resegFlag)
Pop extension bit function.
bool IsNackPresent(SequenceNumber10 nack)
uint8_t GetFramingInfo() const
Get framing info.
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
void SetControlPdu(uint8_t controlPduType)
Set control PDU function.
void SetSequenceNumber(SequenceNumber10 sequenceNumber)
Set sequence number.
LTE RLC Acknowledged Mode (AM), see 3GPP TS 36.322.
Definition: lte-rlc-am.h:37
virtual void DoTransmitPdcpPdu(Ptr< Packet > p)
RLC SAP.
Definition: lte-rlc-am.cc:161
ReassemblingState_t m_reassemblingState
reassembling state
Definition: lte-rlc-am.h:227
std::vector< TxPdu > m_txonBuffer
Transmission buffer.
Definition: lte-rlc-am.h:131
SequenceNumber10 m_vrMr
VR(MR)
Definition: lte-rlc-am.h:183
Time m_statusProhibitTimerValue
status prohibit timer value
Definition: lte-rlc-am.h:207
virtual void DoNotifyHarqDeliveryFailure()
Notify HARQ delivery failure.
Definition: lte-rlc-am.cc:760
void ExpirePollRetransmitTimer(void)
Expire poll retransmitter.
Definition: lte-rlc-am.cc:1699
bool IsInsideReceivingWindow(SequenceNumber10 seqNumber)
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1138
static TypeId GetTypeId(void)
Get the type ID.
Definition: lte-rlc-am.cc:88
uint16_t m_windowSize
Constants.
Definition: lte-rlc-am.h:197
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-am.h:228
SequenceNumber10 m_vrH
VR(H)
Definition: lte-rlc-am.h:186
uint32_t m_txonBufferSize
transmit on buffer size
Definition: lte-rlc-am.h:147
SequenceNumber10 m_vrMs
VR(MS)
Definition: lte-rlc-am.h:185
uint16_t m_pollByte
poll byte
Definition: lte-rlc-am.h:216
SequenceNumber10 m_vtS
VT(S)
Definition: lte-rlc-am.h:178
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc-am.cc:132
SequenceNumber10 m_pollSn
POLL_SN.
Definition: lte-rlc-am.h:179
virtual void DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams)
MAC SAP.
Definition: lte-rlc-am.cc:200
SequenceNumber10 m_vtA
State variables.
Definition: lte-rlc-am.h:176
void ExpireReorderingTimer(void)
This method will schedule a timeout at WaitReplyTimeout interval in the future, unless a timer is alr...
Definition: lte-rlc-am.cc:1657
SequenceNumber10 m_vtMs
VT(MS)
Definition: lte-rlc-am.h:177
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-am.h:208
uint32_t m_statusPduBufferSize
status PDU buffer size
Definition: lte-rlc-am.h:152
Ptr< Packet > m_controlPduBuffer
Control PDU buffer (just one PDU)
Definition: lte-rlc-am.h:165
std::map< uint16_t, PduBuffer > m_rxonBuffer
Reception buffer.
Definition: lte-rlc-am.h:163
bool m_txOpportunityForRetxAlwaysBigEnough
transmit opportunity for retransmit?
Definition: lte-rlc-am.h:218
bool m_pollRetransmitTimerJustExpired
poll retransmit timer just expired?
Definition: lte-rlc-am.h:219
void ExpireStatusProhibitTimer(void)
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1744
Time m_reorderingTimerValue
reordering timer value
Definition: lte-rlc-am.h:205
uint32_t m_maxTxBufferSize
maximum transmission buffer size
Definition: lte-rlc-am.h:146
EventId m_pollRetransmitTimer
Timers.
Definition: lte-rlc-am.h:202
uint16_t m_maxRetxThreshold
Configurable parameters.
Definition: lte-rlc-am.h:214
SequenceNumber10 m_vrX
VR(X)
Definition: lte-rlc-am.h:184
void ExpireRbsTimer(void)
Expire RBS timer.
Definition: lte-rlc-am.cc:1750
std::vector< RetxPdu > m_retxBuffer
Buffer for PDUs considered for retransmission.
Definition: lte-rlc-am.h:144
uint32_t m_byteWithoutPoll
byte without poll
Definition: lte-rlc-am.h:192
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet (PDU)
Definition: lte-rlc-am.h:170
uint32_t m_pduWithoutPoll
Counters.
Definition: lte-rlc-am.h:191
virtual ~LteRlcAm()
Definition: lte-rlc-am.cc:82
Time m_pollRetransmitTimerValue
poll retransmit time value
Definition: lte-rlc-am.h:203
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-am.cc:1586
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver.
Definition: lte-rlc-am.cc:1162
uint32_t m_txedBufferSize
transmit ed buffer size
Definition: lte-rlc-am.h:149
uint16_t m_pollPdu
poll PDU
Definition: lte-rlc-am.h:215
virtual void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams)
Receive PDU function.
Definition: lte-rlc-am.cc:767
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-am.h:204
SequenceNumber10 m_vrR
VR(R)
Definition: lte-rlc-am.h:182
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-am.h:233
uint32_t m_retxBufferSize
retransmit buffer size
Definition: lte-rlc-am.h:148
EventId m_statusProhibitTimer
status prohibit timer
Definition: lte-rlc-am.h:206
std::vector< RetxPdu > m_txedBuffer
Buffer for transmitted and retransmitted PDUs that have not been acked but are not considered for ret...
Definition: lte-rlc-am.h:141
bool m_statusPduRequested
status PDU requested
Definition: lte-rlc-am.h:151
Time m_rbsTimerValue
RBS timer value.
Definition: lte-rlc-am.h:209
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.
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
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
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
void SetSenderTimestamp(Time senderTimestamp)
Set the sender timestamp.
Definition: lte-rlc-tag.h:74
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(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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 AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:85
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_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
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-am.h:114