A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lte-rlc-am.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Manuel Requena <manuel.requena@cttc.es>
18 * Nicola Baldo <nbaldo@cttc.es>
19 */
20
21#include "lte-rlc-am.h"
22
23#include "lte-rlc-am-header.h"
25#include "lte-rlc-tag.h"
26
27#include "ns3/log.h"
28#include "ns3/simulator.h"
29
30namespace ns3
31{
32
33NS_LOG_COMPONENT_DEFINE("LteRlcAm");
34
36
38{
39 NS_LOG_FUNCTION(this);
40
41 // Buffers
43 m_retxBuffer.resize(1024);
45 m_txedBuffer.resize(1024);
47
50
51 // State variables: transmitting side
52 m_windowSize = 512;
53 m_vtA = 0;
55 m_vtS = 0;
56 m_pollSn = 0;
57
58 // State variables: receiving side
59 m_vrR = 0;
61 m_vrX = 0;
62 m_vrMs = 0;
63 m_vrH = 0;
64
65 // Counters
68
69 // Configurable parameters
71 m_pollPdu = 1;
72 m_pollByte = 50;
73
74 // SDU reassembling process
77
79}
80
82{
83 NS_LOG_FUNCTION(this);
84}
85
88{
89 static TypeId tid =
90 TypeId("ns3::LteRlcAm")
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)",
104 .AddAttribute("StatusProhibitTimer",
105 "Value of the t-StatusProhibit timer (See section 7.3 of 3GPP TS 36.322)",
109 .AddAttribute(
110 "ReportBufferStatusTimer",
111 "How much to wait to issue a new Report Buffer Status since the last time "
112 "a new SDU was received",
116 .AddAttribute("TxOpportunityForRetxAlwaysBigEnough",
117 "If true, always pretend that the size of a TxOpportunity is big enough "
118 "for retransmission. If false (default and realistic behavior), no retx "
119 "is performed unless the corresponding TxOpportunity is big enough.",
120 BooleanValue(false),
123 .AddAttribute("MaxTxBufferSize",
124 "Maximum Size of the Transmission Buffer (in Bytes). If zero is "
125 "configured, the buffer is unlimited.",
126 UintegerValue(10 * 1024),
128 MakeUintegerChecker<uint32_t>());
129 return tid;
130}
131
132void
134{
135 NS_LOG_FUNCTION(this);
140
142 m_txonBuffer.clear();
144 m_txedBuffer.clear();
146 m_retxBuffer.clear();
148 m_rxonBuffer.clear();
149 m_sdusBuffer.clear();
150 m_keepS0 = nullptr;
151 m_controlPduBuffer = nullptr;
152
154}
155
160void
162{
163 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << p->GetSize());
164
165 if (m_txonBufferSize + p->GetSize() <= m_maxTxBufferSize || (m_maxTxBufferSize == 0))
166 {
170 p->AddPacketTag(tag);
171
172 NS_LOG_LOGIC("Txon Buffer: New packet added");
173 m_txonBuffer.emplace_back(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
198void
200{
201 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << txOpParams.bytes);
202
203 if (txOpParams.bytes < 4)
204 {
205 // Stingy MAC: In general, we need more bytes.
206 // There are a more restrictive test for each particular case
207 NS_LOG_LOGIC("TxOpportunity (size = " << txOpParams.bytes << ") too small");
208 NS_ASSERT_MSG(false,
209 "TxOpportunity (size = "
210 << txOpParams.bytes << ") too small.\n"
211 << "Your MAC scheduler is assigned too few resource blocks.");
212 return;
213 }
214
216 {
217 if (txOpParams.bytes < m_statusPduBufferSize)
218 {
219 // Stingy MAC: We need more bytes for the STATUS PDU
220 NS_LOG_LOGIC("TxOpportunity (size = " << txOpParams.bytes
221 << ") too small for the STATUS PDU (size = "
222 << m_statusPduBufferSize << ")");
223 NS_ASSERT_MSG(false,
224 "TxOpportunity (size = "
225 << txOpParams.bytes << ") too small for the STATUS PDU (size = "
226 << m_statusPduBufferSize << ")\n"
227 << "Your MAC scheduler is assigned too few resource blocks.");
228 return;
229 }
230
231 NS_LOG_LOGIC("Sending STATUS PDU");
232
233 Ptr<Packet> packet = Create<Packet>();
234 LteRlcAmHeader rlcAmHeader;
236
237 NS_LOG_LOGIC("Check for SNs to NACK from " << m_vrR.GetValue() << " to "
238 << m_vrMs.GetValue());
241 std::map<uint16_t, PduBuffer>::iterator pduIt;
242 for (sn = m_vrR; sn < m_vrMs; sn++)
243 {
244 NS_LOG_LOGIC("SN = " << sn);
245 if (!rlcAmHeader.OneMoreNackWouldFitIn(txOpParams.bytes))
246 {
247 NS_LOG_LOGIC("Can't fit more NACKs in STATUS PDU");
248 break;
249 }
250 pduIt = m_rxonBuffer.find(sn.GetValue());
251 if (pduIt == m_rxonBuffer.end() || (!(pduIt->second.m_pduComplete)))
252 {
253 NS_LOG_LOGIC("adding NACK_SN " << sn.GetValue());
254 rlcAmHeader.PushNack(sn.GetValue());
255 }
256 }
257 NS_LOG_LOGIC("SN at end of NACK loop = " << sn);
258 // 3GPP TS 36.322 section 6.2.2.1.4 ACK SN
259 // find the SN of the next not received RLC Data PDU
260 // which is not reported as missing in the STATUS PDU.
261 pduIt = m_rxonBuffer.find(sn.GetValue());
262 while ((sn < m_vrMs) && (pduIt != m_rxonBuffer.end()) && (pduIt->second.m_pduComplete))
263 {
264 NS_LOG_LOGIC("SN = " << sn << " < " << m_vrMs << " = " << (sn < m_vrMs));
265 sn++;
266 NS_LOG_LOGIC("SN = " << sn);
267 pduIt = m_rxonBuffer.find(sn.GetValue());
268 }
269
270 NS_ASSERT_MSG(sn <= m_vrMs,
271 "first SN not reported as missing = " << sn << ", VR(MS) = " << m_vrMs);
272 rlcAmHeader.SetAckSn(sn);
273
274 NS_LOG_LOGIC("RLC header: " << rlcAmHeader);
275 packet->AddHeader(rlcAmHeader);
276
277 // Sender timestamp
278 RlcTag rlcTag(Simulator::Now());
279 packet->AddByteTag(rlcTag, 1, rlcAmHeader.GetSerializedSize());
280 m_txPdu(m_rnti, m_lcid, packet->GetSize());
281
282 // Send RLC PDU to MAC layer
284 params.pdu = packet;
285 params.rnti = m_rnti;
286 params.lcid = m_lcid;
287 params.layer = txOpParams.layer;
288 params.harqProcessId = txOpParams.harqId;
289 params.componentCarrierId = txOpParams.componentCarrierId;
290
292
293 m_statusPduRequested = false;
297 this);
298 return;
299 }
300 else if (m_retxBufferSize > 0)
301 {
302 NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
303 NS_LOG_LOGIC("Sending data from Retransmission Buffer");
307 for (sn = m_vtA; sn < m_vtS; sn++)
308 {
309 uint16_t seqNumberValue = sn.GetValue();
310 NS_LOG_LOGIC("SN = " << seqNumberValue << " m_pdu "
311 << m_retxBuffer.at(seqNumberValue).m_pdu);
312
313 if (m_retxBuffer.at(seqNumberValue).m_pdu)
314 {
315 Ptr<Packet> packet = m_retxBuffer.at(seqNumberValue).m_pdu->Copy();
316
317 if ((packet->GetSize() <= txOpParams.bytes) ||
319 {
320 // According to 5.2.1, the data field is left as is, but we rebuild the header
321 LteRlcAmHeader rlcAmHeader;
322 packet->RemoveHeader(rlcAmHeader);
323 NS_LOG_LOGIC("old AM RLC header: " << rlcAmHeader);
324
325 // Calculate the Polling Bit (5.2.2.1)
327
328 NS_LOG_LOGIC("polling conditions: m_txonBuffer.empty="
329 << m_txonBuffer.empty() << " retxBufferSize=" << m_retxBufferSize
330 << " packet->GetSize ()=" << packet->GetSize());
331 if (((m_txonBuffer.empty()) &&
333 packet->GetSize() + rlcAmHeader.GetSerializedSize())) ||
335 {
340
341 m_pollSn = m_vtS - 1;
342 NS_LOG_LOGIC("New POLL_SN = " << m_pollSn);
343
345 {
346 NS_LOG_LOGIC("Start PollRetransmit timer");
347
351 this);
352 }
353 else
354 {
355 NS_LOG_LOGIC("Restart PollRetransmit timer");
356
361 this);
362 }
363 }
364
365 packet->AddHeader(rlcAmHeader);
366
367 RlcTag rlcTag;
369
370 packet->AddByteTag(rlcTag, 1, rlcAmHeader.GetSerializedSize());
371
372 NS_LOG_LOGIC("new AM RLC header: " << rlcAmHeader);
373
374 m_txPdu(m_rnti, m_lcid, packet->GetSize());
375
376 // Send RLC PDU to MAC layer
378 params.pdu = packet;
379 params.rnti = m_rnti;
380 params.lcid = m_lcid;
381 params.layer = txOpParams.layer;
382 params.harqProcessId = txOpParams.harqId;
383 params.componentCarrierId = txOpParams.componentCarrierId;
384
386
387 m_retxBuffer.at(seqNumberValue).m_retxCount++;
388 m_retxBuffer.at(seqNumberValue).m_waitingSince = Simulator::Now();
389 NS_LOG_INFO("Incr RETX_COUNT for SN = " << seqNumberValue);
390 if (m_retxBuffer.at(seqNumberValue).m_retxCount >= m_maxRetxThreshold)
391 {
392 NS_LOG_INFO("Max RETX_COUNT for SN = " << seqNumberValue);
393 }
394
395 NS_LOG_INFO("Move SN = " << seqNumberValue << " back to txedBuffer");
396 m_txedBuffer.at(seqNumberValue).m_pdu =
397 m_retxBuffer.at(seqNumberValue).m_pdu->Copy();
398 m_txedBuffer.at(seqNumberValue).m_retxCount =
399 m_retxBuffer.at(seqNumberValue).m_retxCount;
400 m_txedBuffer.at(seqNumberValue).m_waitingSince =
401 m_retxBuffer.at(seqNumberValue).m_waitingSince;
402 m_txedBufferSize += m_txedBuffer.at(seqNumberValue).m_pdu->GetSize();
403
404 m_retxBufferSize -= m_retxBuffer.at(seqNumberValue).m_pdu->GetSize();
405 m_retxBuffer.at(seqNumberValue).m_pdu = nullptr;
406 m_retxBuffer.at(seqNumberValue).m_retxCount = 0;
407 m_retxBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
408
409 NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
410
411 return;
412 }
413 else
414 {
415 NS_LOG_LOGIC("TxOpportunity (size = "
416 << txOpParams.bytes
417 << ") too small for retransmission of the packet (size = "
418 << packet->GetSize() << ")");
419 NS_LOG_LOGIC("Waiting for bigger TxOpportunity");
420 return;
421 }
422 }
423 }
424 NS_ASSERT_MSG(false, "m_retxBufferSize > 0, but no PDU considered for retx found");
425 }
426 else if (m_txonBufferSize > 0)
427 {
428 if (txOpParams.bytes < 7)
429 {
430 // Stingy MAC: We need more bytes for new DATA PDUs.
431 NS_LOG_LOGIC("TxOpportunity (size = " << txOpParams.bytes
432 << ") too small for DATA PDU");
433 NS_ASSERT_MSG(false,
434 "TxOpportunity (size = "
435 << txOpParams.bytes << ") too small for DATA PDU\n"
436 << "Your MAC scheduler is assigned too few resource blocks.");
437 return;
438 }
439
441 if (m_vtS == m_vtMs)
442 {
443 NS_LOG_INFO("cannot transmit new RLC PDU due to window stalling");
444 return;
445 }
446
447 NS_LOG_LOGIC("Sending data from Transmission Buffer");
448 }
449 else
450 {
451 NS_LOG_LOGIC("No data pending");
452 return;
453 }
454
455 //
456 //
457 // Build new PDU
458 //
459 //
460
461 Ptr<Packet> packet = Create<Packet>();
462 LteRlcAmHeader rlcAmHeader;
463 rlcAmHeader.SetDataPdu();
464
465 // Build Data field
466 uint32_t nextSegmentSize = txOpParams.bytes - 4;
467 uint32_t nextSegmentId = 1;
468 uint32_t dataFieldAddedSize = 0;
469 std::vector<Ptr<Packet>> dataField;
470
471 // Remove the first packet from the transmission buffer.
472 // If only a segment of the packet is taken, then the remaining is given back later
473 if (m_txonBuffer.empty())
474 {
475 NS_LOG_LOGIC("No data pending");
476 return;
477 }
478
479 NS_LOG_LOGIC("SDUs in TxonBuffer = " << m_txonBuffer.size());
480 NS_LOG_LOGIC("First SDU buffer = " << m_txonBuffer.begin()->m_pdu);
481 NS_LOG_LOGIC("First SDU size = " << m_txonBuffer.begin()->m_pdu->GetSize());
482 NS_LOG_LOGIC("Next segment size = " << nextSegmentSize);
483 NS_LOG_LOGIC("Remove SDU from TxBuffer");
484 Time firstSegmentTime = m_txonBuffer.begin()->m_waitingSince;
485 Ptr<Packet> firstSegment = m_txonBuffer.begin()->m_pdu->Copy();
486 m_txonBufferSize -= m_txonBuffer.begin()->m_pdu->GetSize();
487 NS_LOG_LOGIC("txBufferSize = " << m_txonBufferSize);
488 m_txonBuffer.erase(m_txonBuffer.begin());
489
490 while (firstSegment && (firstSegment->GetSize() > 0) && (nextSegmentSize > 0))
491 {
492 NS_LOG_LOGIC("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
493 NS_LOG_LOGIC(" firstSegment size = " << firstSegment->GetSize());
494 NS_LOG_LOGIC(" nextSegmentSize = " << nextSegmentSize);
495 if ((firstSegment->GetSize() > nextSegmentSize) ||
496 // Segment larger than 2047 octets can only be mapped to the end of the Data field
497 (firstSegment->GetSize() > 2047))
498 {
499 // Take the minimum size, due to the 2047-bytes 3GPP exception
500 // This exception is due to the length of the LI field (just 11 bits)
501 uint32_t currSegmentSize = std::min(firstSegment->GetSize(), nextSegmentSize);
502
503 NS_LOG_LOGIC(" IF ( firstSegment > nextSegmentSize ||");
504 NS_LOG_LOGIC(" firstSegment > 2047 )");
505
506 // Segment txBuffer.FirstBuffer and
507 // Give back the remaining segment to the transmission buffer
508 Ptr<Packet> newSegment = firstSegment->CreateFragment(0, currSegmentSize);
509 NS_LOG_LOGIC(" newSegment size = " << newSegment->GetSize());
510
511 // Status tag of the new and remaining segments
512 // Note: This is the only place where a PDU is segmented and
513 // therefore its status can change
514 LteRlcSduStatusTag oldTag;
515 LteRlcSduStatusTag newTag;
516 firstSegment->RemovePacketTag(oldTag);
517 newSegment->RemovePacketTag(newTag);
519 {
522 }
523 else if (oldTag.GetStatus() == LteRlcSduStatusTag::LAST_SEGMENT)
524 {
526 // oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
527 }
528
529 // Give back the remaining segment to the transmission buffer
530 firstSegment->RemoveAtStart(currSegmentSize);
532 " firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize());
533 if (firstSegment->GetSize() > 0)
534 {
535 firstSegment->AddPacketTag(oldTag);
536
537 m_txonBuffer.insert(m_txonBuffer.begin(), TxPdu(firstSegment, firstSegmentTime));
538 m_txonBufferSize += m_txonBuffer.begin()->m_pdu->GetSize();
539
540 NS_LOG_LOGIC(" Txon buffer: Give back the remaining segment");
541 NS_LOG_LOGIC(" Txon buffers = " << m_txonBuffer.size());
542 NS_LOG_LOGIC(" Front buffer size = " << m_txonBuffer.begin()->m_pdu->GetSize());
543 NS_LOG_LOGIC(" txonBufferSize = " << m_txonBufferSize);
544 }
545 else
546 {
547 // Whole segment was taken, so adjust tag
549 {
551 }
553 {
555 }
556 }
557 // Segment is completely taken or
558 // the remaining segment is given back to the transmission buffer
559 firstSegment = nullptr;
560
561 // Put status tag once it has been adjusted
562 newSegment->AddPacketTag(newTag);
563
564 // Add Segment to Data field
565 dataFieldAddedSize = newSegment->GetSize();
566 dataField.push_back(newSegment);
567 newSegment = nullptr;
568
569 // ExtensionBit (Next_Segment - 1) = 0
571
572 // no LengthIndicator for the last one
573
574 nextSegmentSize -= dataFieldAddedSize;
575 nextSegmentId++;
576
577 // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
578
579 // (NO more segments) ? exit
580 // break;
581 }
582 else if ((nextSegmentSize - firstSegment->GetSize() <= 2) || m_txonBuffer.empty())
583 {
585 " IF nextSegmentSize - firstSegment->GetSize () <= 2 || txonBuffer.size == 0");
586
587 // Add txBuffer.FirstBuffer to DataField
588 dataFieldAddedSize = firstSegment->GetSize();
589 dataField.push_back(firstSegment);
590 firstSegment = nullptr;
591
592 // ExtensionBit (Next_Segment - 1) = 0
594
595 // no LengthIndicator for the last one
596
597 nextSegmentSize -= dataFieldAddedSize;
598 nextSegmentId++;
599
600 NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txonBuffer.size());
601 if (!m_txonBuffer.empty())
602 {
603 NS_LOG_LOGIC(" First SDU buffer = " << m_txonBuffer.begin()->m_pdu);
605 " First SDU size = " << m_txonBuffer.begin()->m_pdu->GetSize());
606 }
607 NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
608
609 // nextSegmentSize <= 2 (only if txBuffer is not empty)
610
611 // (NO more segments) ? exit
612 // break;
613 }
614 else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
615 {
616 NS_LOG_LOGIC(" IF firstSegment < NextSegmentSize && txonBuffer.size > 0");
617 // Add txBuffer.FirstBuffer to DataField
618 dataFieldAddedSize = firstSegment->GetSize();
619 dataField.push_back(firstSegment);
620
621 // ExtensionBit (Next_Segment - 1) = 1
623
624 // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
625 rlcAmHeader.PushLengthIndicator(firstSegment->GetSize());
626
627 nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
628 nextSegmentId++;
629
630 NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txonBuffer.size());
631 if (!m_txonBuffer.empty())
632 {
633 NS_LOG_LOGIC(" First SDU buffer = " << m_txonBuffer.begin()->m_pdu);
635 " First SDU size = " << m_txonBuffer.begin()->m_pdu->GetSize());
636 }
637 NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
638 NS_LOG_LOGIC(" Remove SDU from TxBuffer");
639
640 // (more segments)
641 firstSegment = m_txonBuffer.begin()->m_pdu->Copy();
642 firstSegmentTime = m_txonBuffer.begin()->m_waitingSince;
643 m_txonBufferSize -= m_txonBuffer.begin()->m_pdu->GetSize();
644 m_txonBuffer.erase(m_txonBuffer.begin());
645 NS_LOG_LOGIC(" txBufferSize = " << m_txonBufferSize);
646 }
647 }
648
649 //
650 // Build RLC header
651 //
652
653 rlcAmHeader.SetSequenceNumber(m_vtS++);
656 rlcAmHeader.SetSegmentOffset(0);
657
658 NS_ASSERT_MSG(rlcAmHeader.GetSequenceNumber() < m_vtMs, "SN above TX window");
659 NS_ASSERT_MSG(rlcAmHeader.GetSequenceNumber() >= m_vtA, "SN below TX window");
660
661 // Calculate FramingInfo flag according the status of the SDUs in the DataField
662 uint8_t framingInfo = 0;
663 std::vector<Ptr<Packet>>::iterator it;
664 it = dataField.begin();
665
666 // FIRST SEGMENT
668 NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
669 (*it)->PeekPacketTag(tag);
672 {
673 framingInfo |= LteRlcAmHeader::FIRST_BYTE;
674 }
675 else
676 {
677 framingInfo |= LteRlcAmHeader::NO_FIRST_BYTE;
678 }
679
680 // Add all SDUs (in DataField) to the Packet
681 while (it < dataField.end())
682 {
683 NS_LOG_LOGIC("Adding SDU/segment to packet, length = " << (*it)->GetSize());
684
685 NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
686 (*it)->RemovePacketTag(tag);
687 if (packet->GetSize() > 0)
688 {
689 packet->AddAtEnd(*it);
690 }
691 else
692 {
693 packet = (*it);
694 }
695 it++;
696 }
697
698 // LAST SEGMENT (Note: There could be only one and be the first one)
699 it--;
702 {
703 framingInfo |= LteRlcAmHeader::LAST_BYTE;
704 }
705 else
706 {
707 framingInfo |= LteRlcAmHeader::NO_LAST_BYTE;
708 }
709
710 // Set the FramingInfo flag after the calculation
711 rlcAmHeader.SetFramingInfo(framingInfo);
712
713 // Calculate the Polling Bit (5.2.2.1)
715
717 NS_LOG_LOGIC("PDU_WITHOUT_POLL = " << m_pduWithoutPoll);
718 m_byteWithoutPoll += packet->GetSize();
719 NS_LOG_LOGIC("BYTE_WITHOUT_POLL = " << m_byteWithoutPoll);
720
722 ((m_txonBuffer.empty()) && (m_retxBufferSize == 0)) || (m_vtS >= m_vtMs) ||
724 {
729
730 m_pollSn = m_vtS - 1;
731 NS_LOG_LOGIC("New POLL_SN = " << m_pollSn);
732
734 {
735 NS_LOG_LOGIC("Start PollRetransmit timer");
736
739 this);
740 }
741 else
742 {
743 NS_LOG_LOGIC("Restart PollRetransmit timer");
744
748 this);
749 }
750 }
751
752 // Build RLC PDU with DataField and Header
753 NS_LOG_LOGIC("AM RLC header: " << rlcAmHeader);
754
755 RlcTag rlcTag;
757
758 packet->AddHeader(rlcAmHeader);
759 packet->AddByteTag(rlcTag, 1, rlcAmHeader.GetSerializedSize());
760
761 // Store new PDU into the Transmitted PDU Buffer
762 NS_LOG_LOGIC("Put transmitted PDU in the txedBuffer");
763 m_txedBufferSize += packet->GetSize();
764 m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_pdu = packet->Copy();
765 m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_retxCount = 0;
766 m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_waitingSince = Simulator::Now();
767
768 m_txPdu(m_rnti, m_lcid, packet->GetSize());
769
770 // Send RLC PDU to MAC layer
772 params.pdu = packet;
773 params.rnti = m_rnti;
774 params.lcid = m_lcid;
775 params.layer = txOpParams.layer;
776 params.harqProcessId = txOpParams.harqId;
777 params.componentCarrierId = txOpParams.componentCarrierId;
778
780}
781
782void
784{
785 NS_LOG_FUNCTION(this);
786}
787
788void
790{
791 NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << rxPduParams.p->GetSize());
792
793 // Get RLC header parameters
794 LteRlcAmHeader rlcAmHeader;
795 rxPduParams.p->PeekHeader(rlcAmHeader);
796 NS_LOG_LOGIC("RLC header: " << rlcAmHeader);
797
798 // Receiver timestamp
799 Time delay;
800 RlcTag rlcTag;
801
802 bool ret = rxPduParams.p->FindFirstMatchingByteTag(rlcTag);
803 NS_ASSERT_MSG(ret, "RlcTag not found in RLC Header. The packet went into a real network?");
804
805 delay = Simulator::Now() - rlcTag.GetSenderTimestamp();
806
807 m_rxPdu(m_rnti, m_lcid, rxPduParams.p->GetSize(), delay.GetNanoSeconds());
808
809 if (rlcAmHeader.IsDataPdu())
810 {
811 // 5.1.3.1 Transmit operations
812
813 // 5.1.3.1.1 General
814 //
815 // The transmitting side of an AM RLC entity shall prioritize transmission of RLC control
816 // PDUs over RLC data PDUs. The transmitting side of an AM RLC entity shall prioritize
817 // retransmission of RLC data PDUs over transmission of new AMD PDUs.
818 //
819 // The transmitting side of an AM RLC entity shall maintain a transmitting window according
820 // to state variables VT(A) and VT(MS) as follows:
821 // - a SN falls within the transmitting window if VT(A) <= SN < VT(MS);
822 // - a SN falls outside of the transmitting window otherwise.
823 //
824 // The transmitting side of an AM RLC entity shall not deliver to lower layer any RLC data
825 // PDU whose SN falls outside of the transmitting window.
826 //
827 // When delivering a new AMD PDU to lower layer, the transmitting side of an AM RLC entity
828 // shall:
829 // - set the SN of the AMD PDU to VT(S), and then increment VT(S) by one.
830 //
831 // The transmitting side of an AM RLC entity can receive a positive acknowledgement
832 // (confirmation of successful reception by its peer AM RLC entity) for a RLC data PDU by
833 // the following:
834 // - STATUS PDU from its peer AM RLC entity.
835 //
836 // When receiving a positive acknowledgement for an AMD PDU with SN = VT(A), the
837 // transmitting side of an AM RLC entity shall:
838 // - set VT(A) equal to the SN of the AMD PDU with the smallest SN, whose SN falls within
839 // the
840 // range VT(A) <= SN <= VT(S) and for which a positive acknowledgment has not been
841 // received yet.
842 // - if positive acknowledgements have been received for all AMD PDUs associated with
843 // a transmitted RLC SDU:
844 // - send an indication to the upper layers of successful delivery of the RLC SDU.
845
846 // 5.1.3.2 Receive operations
847 //
848 // 5.1.3.2.1 General
849 //
850 // The receiving side of an AM RLC entity shall maintain a receiving window according to
851 // state variables VR(R) and VR(MR) as follows:
852 // - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
853 // - a SN falls outside of the receiving window otherwise.
854 //
855 // When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity
856 // shall:
857 // - either discard the received RLC data PDU or place it in the reception buffer (see sub
858 // clause 5.1.3.2.2);
859 // - if the received RLC data PDU was placed in the reception buffer:
860 // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop
861 // t-Reordering as needed (see sub clause 5.1.3.2.3).
862 //
863 // When t-Reordering expires, the receiving side of an AM RLC entity shall:
864 // - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
865
866 SequenceNumber10 seqNumber = rlcAmHeader.GetSequenceNumber();
867 seqNumber.SetModulusBase(m_vrR);
868
870 {
871 NS_LOG_LOGIC("PDU segment received ( SN = " << seqNumber << " )");
872 }
873 else if (rlcAmHeader.GetResegmentationFlag() == LteRlcAmHeader::PDU)
874 {
875 NS_LOG_LOGIC("PDU received ( SN = " << seqNumber << " )");
876 }
877 else
878 {
879 NS_ASSERT_MSG(false, "Neither a PDU segment nor a PDU received");
880 return;
881 }
882
883 // STATUS PDU is requested
885 {
888
890 {
892 }
893 }
894
895 // 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
896 //
897 // When a RLC data PDU is received from lower layer, where the RLC data PDU contains
898 // byte segment numbers y to z of an AMD PDU with SN = x, the receiving side of an AM RLC
899 // entity shall:
900 // - if x falls outside of the receiving window; or
901 // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
902 // - discard the received RLC data PDU;
903 // - else:
904 // - place the received RLC data PDU in the reception buffer;
905 // - if some byte segments of the AMD PDU contained in the RLC data PDU have been
906 // received before:
907 // - discard the duplicate byte segments.
908
909 NS_LOG_LOGIC("VR(R) = " << m_vrR);
910 NS_LOG_LOGIC("VR(MR) = " << m_vrMr);
911 NS_LOG_LOGIC("VR(X) = " << m_vrX);
912 NS_LOG_LOGIC("VR(MS) = " << m_vrMs);
913 NS_LOG_LOGIC("VR(H) = " << m_vrH);
914
915 // - if x falls outside of the receiving window; or
916 // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
917 if (!IsInsideReceivingWindow(seqNumber))
918 {
919 NS_LOG_LOGIC("PDU discarded");
920 return;
921 }
922 else
923 {
924 // - if some byte segments of the AMD PDU contained in the RLC data PDU have been
925 // received before:
926 // - discard the duplicate byte segments.
927 // note: re-segmentation of AMD PDU is currently not supported,
928 // so we just check that the segment was not received before
929 std::map<uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find(seqNumber.GetValue());
930 if (it != m_rxonBuffer.end())
931 {
932 NS_ASSERT(!it->second.m_byteSegments.empty());
933 NS_ASSERT_MSG(it->second.m_byteSegments.size() == 1,
934 "re-segmentation not supported");
935 NS_LOG_LOGIC("PDU segment already received, discarded");
936 }
937 else
938 {
939 NS_LOG_LOGIC("Place PDU in the reception buffer ( SN = " << seqNumber << " )");
940 m_rxonBuffer[seqNumber.GetValue()].m_byteSegments.push_back(rxPduParams.p);
941 m_rxonBuffer[seqNumber.GetValue()].m_pduComplete = true;
942 }
943 }
944
945 // 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception buffer
946 // When a RLC data PDU with SN = x is placed in the reception buffer,
947 // the receiving side of an AM RLC entity shall:
948
949 // - if x >= VR(H)
950 // - update VR(H) to x+ 1;
951
952 if (seqNumber >= m_vrH)
953 {
954 m_vrH = seqNumber + 1;
955 NS_LOG_LOGIC("New VR(H) = " << m_vrH);
956 }
957
958 // - if all byte segments of the AMD PDU with SN = VR(MS) are received:
959 // - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for
960 // which not all byte segments have been received;
961
962 std::map<uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find(m_vrMs.GetValue());
963 if (it != m_rxonBuffer.end() && it->second.m_pduComplete)
964 {
965 int firstVrMs = m_vrMs.GetValue();
966 while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
967 {
968 m_vrMs++;
969 it = m_rxonBuffer.find(m_vrMs.GetValue());
970 NS_LOG_LOGIC("Incr VR(MS) = " << m_vrMs);
971
972 NS_ASSERT_MSG(firstVrMs != m_vrMs.GetValue(), "Infinite loop in RxonBuffer");
973 }
974 NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
975 }
976
977 // - if x = VR(R):
978 // - if all byte segments of the AMD PDU with SN = VR(R) are received:
979 // - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which
980 // not all byte segments have been received;
981 // - update VR(MR) to the updated VR(R) + AM_Window_Size;
982 // - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside
983 // of the receiving window and in-sequence byte segments of the AMD PDU with SN = VR(R),
984 // remove RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer
985 // in sequence if not delivered before;
986
987 if (seqNumber == m_vrR)
988 {
989 std::map<uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find(seqNumber.GetValue());
990 if (it != m_rxonBuffer.end() && it->second.m_pduComplete)
991 {
992 it = m_rxonBuffer.find(m_vrR.GetValue());
993 int firstVrR = m_vrR.GetValue();
994 while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
995 {
996 NS_LOG_LOGIC("Reassemble and Deliver ( SN = " << m_vrR << " )");
997 NS_ASSERT_MSG(it->second.m_byteSegments.size() == 1,
998 "Too many segments. PDU Reassembly process didn't work");
999 ReassembleAndDeliver(it->second.m_byteSegments.front());
1000 m_rxonBuffer.erase(m_vrR.GetValue());
1001
1002 m_vrR++;
1007 it = m_rxonBuffer.find(m_vrR.GetValue());
1008
1009 NS_ASSERT_MSG(firstVrR != m_vrR.GetValue(), "Infinite loop in RxonBuffer");
1010 }
1011 NS_LOG_LOGIC("New VR(R) = " << m_vrR);
1013
1014 NS_LOG_LOGIC("New VR(MR) = " << m_vrMr);
1015 }
1016 }
1017
1018 // - if t-Reordering is running:
1019 // - if VR(X) = VR(R); or
1020 // - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
1021 // - stop and reset t-Reordering;
1022
1024 {
1025 NS_LOG_LOGIC("Reordering timer is running");
1026 if ((m_vrX == m_vrR) || ((!IsInsideReceivingWindow(m_vrX)) && (m_vrX != m_vrMr)))
1027 {
1029 NS_LOG_LOGIC("Stop reordering timer");
1031 }
1032 }
1033
1034 // - if t-Reordering is not running (includes the case t-Reordering is stopped due to
1035 // actions above):
1036 // - if VR (H) > VR(R):
1037 // - start t-Reordering;
1038 // - set VR(X) to VR(H).
1039
1041 {
1042 NS_LOG_LOGIC("Reordering timer is not running");
1043 if (m_vrH > m_vrR)
1044 {
1045 NS_LOG_LOGIC("Start reordering timer");
1048 this);
1049 m_vrX = m_vrH;
1050 NS_LOG_LOGIC("New VR(X) = " << m_vrX);
1051 }
1052 }
1053 }
1054 else if (rlcAmHeader.IsControlPdu())
1055 {
1056 NS_LOG_INFO("Control AM RLC PDU");
1057
1058 SequenceNumber10 ackSn = rlcAmHeader.GetAckSn();
1060
1061 NS_LOG_INFO("ackSn = " << ackSn);
1062 NS_LOG_INFO("VT(A) = " << m_vtA);
1063 NS_LOG_INFO("VT(S) = " << m_vtS);
1064 NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1065 NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1066
1070 ackSn.SetModulusBase(m_vtA);
1072
1073 bool incrementVtA = true;
1074
1075 for (sn = m_vtA; sn < ackSn && sn < m_vtS; sn++)
1076 {
1077 NS_LOG_LOGIC("sn = " << sn);
1078
1079 uint16_t seqNumberValue = sn.GetValue();
1080
1081 if (m_pollRetransmitTimer.IsRunning() && (seqNumberValue == m_pollSn.GetValue()))
1082 {
1084 }
1085
1086 if (rlcAmHeader.IsNackPresent(sn))
1087 {
1088 NS_LOG_LOGIC("sn " << sn << " is NACKed");
1089
1090 incrementVtA = false;
1091
1092 if (m_txedBuffer.at(seqNumberValue).m_pdu)
1093 {
1094 NS_LOG_INFO("Move SN = " << seqNumberValue << " to retxBuffer");
1095 m_retxBuffer.at(seqNumberValue).m_pdu =
1096 m_txedBuffer.at(seqNumberValue).m_pdu->Copy();
1097 m_retxBuffer.at(seqNumberValue).m_retxCount =
1098 m_txedBuffer.at(seqNumberValue).m_retxCount;
1099 m_retxBuffer.at(seqNumberValue).m_waitingSince =
1100 m_txedBuffer.at(seqNumberValue).m_waitingSince;
1101 m_retxBufferSize += m_retxBuffer.at(seqNumberValue).m_pdu->GetSize();
1102
1103 m_txedBufferSize -= m_txedBuffer.at(seqNumberValue).m_pdu->GetSize();
1104 m_txedBuffer.at(seqNumberValue).m_pdu = nullptr;
1105 m_txedBuffer.at(seqNumberValue).m_retxCount = 0;
1106 m_txedBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1107 }
1108
1109 NS_ASSERT(m_retxBuffer.at(seqNumberValue).m_pdu);
1110 }
1111 else
1112 {
1113 NS_LOG_LOGIC("sn " << sn << " is ACKed");
1114
1115 if (m_txedBuffer.at(seqNumberValue).m_pdu)
1116 {
1117 NS_LOG_INFO("ACKed SN = " << seqNumberValue << " from txedBuffer");
1118 // NS_LOG_INFO ("m_txedBuffer( " << m_vtA << " )->GetSize = " <<
1119 // m_txedBuffer.at (m_vtA.GetValue ())->GetSize ());
1120 m_txedBufferSize -= m_txedBuffer.at(seqNumberValue).m_pdu->GetSize();
1121 m_txedBuffer.at(seqNumberValue).m_pdu = nullptr;
1122 m_txedBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1123 NS_ASSERT(!m_retxBuffer.at(seqNumberValue).m_pdu);
1124 }
1125
1126 if (m_retxBuffer.at(seqNumberValue).m_pdu)
1127 {
1128 NS_LOG_INFO("ACKed SN = " << seqNumberValue << " from retxBuffer");
1129 m_retxBufferSize -= m_retxBuffer.at(seqNumberValue).m_pdu->GetSize();
1130 m_retxBuffer.at(seqNumberValue).m_pdu = nullptr;
1131 m_retxBuffer.at(seqNumberValue).m_retxCount = 0;
1132 m_retxBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1133 }
1134 }
1135
1136 NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1137 NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1138
1139 if (incrementVtA)
1140 {
1141 m_vtA++;
1143 NS_LOG_INFO("New VT(A) = " << m_vtA);
1147 ackSn.SetModulusBase(m_vtA);
1149 }
1150
1151 } // loop over SN : VT(A) <= SN < ACK SN
1152
1153 return;
1154 }
1155 else
1156 {
1157 NS_LOG_WARN("Wrong AM RLC PDU type");
1158 return;
1159 }
1160}
1161
1162bool
1164{
1165 NS_LOG_FUNCTION(this << seqNumber);
1166 NS_LOG_LOGIC("Receiving Window: " << m_vrR << " <= " << seqNumber << " <= " << m_vrMr);
1167
1170 seqNumber.SetModulusBase(m_vrR);
1171
1172 if ((m_vrR <= seqNumber) && (seqNumber < m_vrMr))
1173 {
1174 NS_LOG_LOGIC(seqNumber << " is INSIDE the receiving window");
1175 return true;
1176 }
1177 else
1178 {
1179 NS_LOG_LOGIC(seqNumber << " is OUTSIDE the receiving window");
1180 return false;
1181 }
1182}
1183
1184void
1186{
1187 LteRlcAmHeader rlcAmHeader;
1188 RlcTag rlcTag;
1189 bool ret = packet->FindFirstMatchingByteTag(rlcTag);
1190 NS_ASSERT(ret);
1191 packet->RemoveHeader(rlcAmHeader);
1192 ret = packet->FindFirstMatchingByteTag(rlcTag);
1193 NS_ASSERT(!ret);
1194 uint8_t framingInfo = rlcAmHeader.GetFramingInfo();
1195 SequenceNumber10 currSeqNumber = rlcAmHeader.GetSequenceNumber();
1196 bool expectedSnLost;
1197
1198 if (currSeqNumber != m_expectedSeqNumber)
1199 {
1200 expectedSnLost = true;
1201 NS_LOG_LOGIC("There are losses. Expected SN = " << m_expectedSeqNumber
1202 << ". Current SN = " << currSeqNumber);
1203 m_expectedSeqNumber = currSeqNumber + 1;
1204 }
1205 else
1206 {
1207 expectedSnLost = false;
1208 NS_LOG_LOGIC("No losses. Expected SN = " << m_expectedSeqNumber
1209 << ". Current SN = " << currSeqNumber);
1211 }
1212
1213 // Build list of SDUs
1214 uint8_t extensionBit;
1215 uint16_t lengthIndicator;
1216 do
1217 {
1218 extensionBit = rlcAmHeader.PopExtensionBit();
1219 NS_LOG_LOGIC("E = " << (uint16_t)extensionBit);
1220
1221 if (extensionBit == 0)
1222 {
1223 m_sdusBuffer.push_back(packet);
1224 }
1225 else // extensionBit == 1
1226 {
1227 lengthIndicator = rlcAmHeader.PopLengthIndicator();
1228 NS_LOG_LOGIC("LI = " << lengthIndicator);
1229
1230 // Check if there is enough data in the packet
1231 if (lengthIndicator >= packet->GetSize())
1232 {
1233 NS_LOG_LOGIC("INTERNAL ERROR: Not enough data in the packet ("
1234 << packet->GetSize() << "). Needed LI=" << lengthIndicator);
1236 }
1237
1238 // Split packet in two fragments
1239 Ptr<Packet> data_field = packet->CreateFragment(0, lengthIndicator);
1240 packet->RemoveAtStart(lengthIndicator);
1241
1242 m_sdusBuffer.push_back(data_field);
1243 }
1244 } while (extensionBit == 1);
1245
1246 std::list<Ptr<Packet>>::iterator it;
1247
1248 // Current reassembling state
1250 NS_LOG_LOGIC("Reassembling State = 'WAITING_S0_FULL'");
1252 NS_LOG_LOGIC("Reassembling State = 'WAITING_SI_SF'");
1253 else
1254 NS_LOG_LOGIC("Reassembling State = Unknown state");
1255
1256 // Received framing Info
1257 NS_LOG_LOGIC("Framing Info = " << (uint16_t)framingInfo);
1258 NS_LOG_LOGIC("m_sdusBuffer = " << m_sdusBuffer.size());
1259
1260 // Reassemble the list of SDUs (when there is no losses)
1261 if (!expectedSnLost)
1262 {
1263 switch (m_reassemblingState)
1264 {
1265 case WAITING_S0_FULL:
1266 switch (framingInfo)
1267 {
1270
1274 for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
1275 {
1277 }
1278 m_sdusBuffer.clear();
1279 break;
1280
1283
1287 while (m_sdusBuffer.size() > 1)
1288 {
1290 m_sdusBuffer.pop_front();
1291 }
1292
1296 m_keepS0 = m_sdusBuffer.front();
1297 m_sdusBuffer.pop_front();
1298 break;
1299
1302 default:
1307 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1308 break;
1309 }
1310 break;
1311
1312 case WAITING_SI_SF:
1313 switch (framingInfo)
1314 {
1317
1321 m_keepS0->AddAtEnd(m_sdusBuffer.front());
1322 m_sdusBuffer.pop_front();
1324
1328 while (!m_sdusBuffer.empty())
1329 {
1331 m_sdusBuffer.pop_front();
1332 }
1333 break;
1334
1337
1341 if (m_sdusBuffer.size() == 1)
1342 {
1343 m_keepS0->AddAtEnd(m_sdusBuffer.front());
1344 m_sdusBuffer.pop_front();
1345 }
1346 else // m_sdusBuffer.size () > 1
1347 {
1351 m_keepS0->AddAtEnd(m_sdusBuffer.front());
1352 m_sdusBuffer.pop_front();
1354
1358 while (m_sdusBuffer.size() > 1)
1359 {
1361 m_sdusBuffer.pop_front();
1362 }
1363
1367 m_keepS0 = m_sdusBuffer.front();
1368 m_sdusBuffer.pop_front();
1369 }
1370 break;
1371
1374 default:
1379 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1380 break;
1381 }
1382 break;
1383
1384 default:
1386 "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1387 break;
1388 }
1389 }
1390 else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the
1391 // expected one)
1392 {
1393 switch (m_reassemblingState)
1394 {
1395 case WAITING_S0_FULL:
1396 switch (framingInfo)
1397 {
1400
1404 for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
1405 {
1407 }
1408 m_sdusBuffer.clear();
1409 break;
1410
1413
1417 while (m_sdusBuffer.size() > 1)
1418 {
1420 m_sdusBuffer.pop_front();
1421 }
1422
1426 m_keepS0 = m_sdusBuffer.front();
1427 m_sdusBuffer.pop_front();
1428 break;
1429
1432
1436 m_sdusBuffer.pop_front();
1437
1441 while (!m_sdusBuffer.empty())
1442 {
1444 m_sdusBuffer.pop_front();
1445 }
1446 break;
1447
1449 if (m_sdusBuffer.size() == 1)
1450 {
1452 }
1453 else
1454 {
1456 }
1457
1461 m_sdusBuffer.pop_front();
1462
1463 if (!m_sdusBuffer.empty())
1464 {
1468 while (m_sdusBuffer.size() > 1)
1469 {
1471 m_sdusBuffer.pop_front();
1472 }
1473
1477 m_keepS0 = m_sdusBuffer.front();
1478 m_sdusBuffer.pop_front();
1479 }
1480 break;
1481
1482 default:
1487 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1488 break;
1489 }
1490 break;
1491
1492 case WAITING_SI_SF:
1493 switch (framingInfo)
1494 {
1497
1501 m_keepS0 = nullptr;
1502
1506 while (!m_sdusBuffer.empty())
1507 {
1509 m_sdusBuffer.pop_front();
1510 }
1511 break;
1512
1515
1519 m_keepS0 = nullptr;
1520
1524 while (m_sdusBuffer.size() > 1)
1525 {
1527 m_sdusBuffer.pop_front();
1528 }
1529
1533 m_keepS0 = m_sdusBuffer.front();
1534 m_sdusBuffer.pop_front();
1535
1536 break;
1537
1540
1544 m_keepS0 = nullptr;
1545
1549 m_sdusBuffer.pop_front();
1550
1554 while (!m_sdusBuffer.empty())
1555 {
1557 m_sdusBuffer.pop_front();
1558 }
1559 break;
1560
1562 if (m_sdusBuffer.size() == 1)
1563 {
1565 }
1566 else
1567 {
1569 }
1570
1574 m_keepS0 = nullptr;
1575
1579 m_sdusBuffer.pop_front();
1580
1581 if (!m_sdusBuffer.empty())
1582 {
1586 while (m_sdusBuffer.size() > 1)
1587 {
1589 m_sdusBuffer.pop_front();
1590 }
1591
1595 m_keepS0 = m_sdusBuffer.front();
1596 m_sdusBuffer.pop_front();
1597 }
1598 break;
1599
1600 default:
1605 "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1606 break;
1607 }
1608 break;
1609
1610 default:
1612 "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1613 break;
1614 }
1615 }
1616}
1617
1618void
1620{
1621 NS_LOG_FUNCTION(this);
1622
1623 Time now = Simulator::Now();
1624
1625 NS_LOG_LOGIC("txonBufferSize = " << m_txonBufferSize);
1626 NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1627 NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1628 NS_LOG_LOGIC("VT(A) = " << m_vtA);
1629 NS_LOG_LOGIC("VT(S) = " << m_vtS);
1630
1631 // Transmission Queue HOL time
1632 Time txonQueueHolDelay(0);
1633 if (m_txonBufferSize > 0)
1634 {
1635 txonQueueHolDelay = now - m_txonBuffer.front().m_waitingSince;
1636 }
1637
1638 // Retransmission Queue HOL time
1639 Time retxQueueHolDelay;
1640 if (m_retxBufferSize > 0)
1641 {
1642 Time senderTimestamp;
1643 if (m_retxBuffer.at(m_vtA.GetValue()).m_pdu)
1644 {
1645 senderTimestamp = m_retxBuffer.at(m_vtA.GetValue()).m_waitingSince;
1646 }
1647 else
1648 {
1649 senderTimestamp = m_txedBuffer.at(m_vtA.GetValue()).m_waitingSince;
1650 }
1651 retxQueueHolDelay = now - senderTimestamp;
1652 }
1653 else
1654 {
1655 retxQueueHolDelay = Seconds(0);
1656 }
1657
1659 r.rnti = m_rnti;
1660 r.lcid = m_lcid;
1662 r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds();
1664 r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds();
1665
1667 {
1669 }
1670 else
1671 {
1672 r.statusPduSize = 0;
1673 }
1674
1675 if (r.txQueueSize != 0 || r.retxQueueSize != 0 || r.statusPduSize != 0)
1676 {
1677 NS_LOG_INFO("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay
1678 << ", " << r.retxQueueSize << ", "
1679 << r.retxQueueHolDelay << ", " << r.statusPduSize);
1681 }
1682 else
1683 {
1684 NS_LOG_INFO("ReportBufferStatus don't needed");
1685 }
1686}
1687
1688void
1690{
1691 NS_LOG_FUNCTION(this);
1692 NS_LOG_LOGIC("Reordering Timer has expired");
1693
1694 // 5.1.3.2.4 Actions when t-Reordering expires
1695 // When t-Reordering expires, the receiving side of an AM RLC entity shall:
1696 // - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte
1697 // segments
1698 // have been received;
1699 // - if VR(H) > VR(MS):
1700 // - start t-Reordering;
1701 // - set VR(X) to VR(H).
1702
1703 m_vrMs = m_vrX;
1704 int firstVrMs = m_vrMs.GetValue();
1705 std::map<uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find(m_vrMs.GetValue());
1706 while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
1707 {
1708 m_vrMs++;
1709 it = m_rxonBuffer.find(m_vrMs.GetValue());
1710
1711 NS_ASSERT_MSG(firstVrMs != m_vrMs.GetValue(), "Infinite loop in ExpireReorderingTimer");
1712 }
1713 NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
1714
1715 if (m_vrH > m_vrMs)
1716 {
1717 NS_LOG_LOGIC("Start reordering timer");
1720 m_vrX = m_vrH;
1721 NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
1722 }
1723
1724 // Section 5.2.3 Status Reporting:
1725 // - The receiving side of an AM RLC entity shall trigger a
1726 // STATUS report when T_reordering expires.
1727 m_statusPduRequested = true;
1728}
1729
1730void
1732{
1733 NS_LOG_FUNCTION(this);
1734 NS_LOG_LOGIC("PollRetransmit Timer has expired");
1735
1736 NS_LOG_LOGIC("txonBufferSize = " << m_txonBufferSize);
1737 NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1738 NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1739 NS_LOG_LOGIC("statusPduRequested = " << m_statusPduRequested);
1740
1742
1743 // see section 5.2.2.3
1744 // note the difference between Rel 8 and Rel 11 specs; we follow Rel 11 here
1746 if ((m_txonBufferSize == 0 && m_retxBufferSize == 0) || (m_vtS == m_vtMs))
1747 {
1748 NS_LOG_INFO("txonBuffer and retxBuffer empty. Move PDUs up to = " << m_vtS.GetValue() - 1
1749 << " to retxBuffer");
1750 for (SequenceNumber10 sn = m_vtA; sn < m_vtS; sn++)
1751 {
1752 bool pduAvailable = (bool)m_txedBuffer.at(sn.GetValue()).m_pdu;
1753
1754 if (pduAvailable)
1755 {
1756 uint16_t snValue = sn.GetValue();
1757 NS_LOG_INFO("Move PDU " << sn << " from txedBuffer to retxBuffer");
1758 m_retxBuffer.at(snValue).m_pdu = m_txedBuffer.at(snValue).m_pdu->Copy();
1759 m_retxBuffer.at(snValue).m_retxCount = m_txedBuffer.at(snValue).m_retxCount;
1760 m_retxBuffer.at(snValue).m_waitingSince = m_txedBuffer.at(snValue).m_waitingSince;
1761 m_retxBufferSize += m_retxBuffer.at(snValue).m_pdu->GetSize();
1762
1763 m_txedBufferSize -= m_txedBuffer.at(snValue).m_pdu->GetSize();
1764 m_txedBuffer.at(snValue).m_pdu = nullptr;
1765 m_txedBuffer.at(snValue).m_retxCount = 0;
1766 m_txedBuffer.at(snValue).m_waitingSince = MilliSeconds(0);
1767 }
1768 }
1769 }
1770
1772}
1773
1774void
1776{
1777 NS_LOG_FUNCTION(this);
1778}
1779
1780void
1782{
1783 NS_LOG_LOGIC("RBS Timer expires");
1784
1786 {
1789 }
1790}
1791
1792} // namespace ns3
AttributeValue implementation for Boolean.
Definition: boolean.h:37
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
virtual void ReportBufferStatus(ReportBufferStatusParameters params)=0
Report the RLC buffer status to the MAC.
The packet header for the AM Radio Link Control (RLC) protocol packets.
uint8_t GetPollingBit() const
Get polling bit function.
uint8_t PopExtensionBit()
Pop extension bit function.
void SetSegmentOffset(uint16_t segmentOffset)
Set segment offset function.
void PushExtensionBit(uint8_t extensionBit)
Push extension bit function.
bool IsDataPdu() const
Is data PDU function.
SequenceNumber10 GetAckSn() const
Get ack sn function.
void SetPollingBit(uint8_t pollingBit)
Set polling bit function.
bool OneMoreNackWouldFitIn(uint16_t bytes)
uint32_t GetSerializedSize() const override
void SetLastSegmentFlag(uint8_t lsf)
Set last segment flag function.
void PushNack(int nack)
Add one more NACK to the CONTROL PDU.
void SetFramingInfo(uint8_t framingInfo)
Set sequence number.
static constexpr uint8_t STATUS_PDU
Control PDU type status.
uint16_t PopLengthIndicator()
Pop length indicator function.
void SetAckSn(SequenceNumber10 ackSn)
Set ack sn function.
bool IsControlPdu() const
Is control PDU function.
void SetDataPdu()
Set data PDU 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:38
ReassemblingState_t m_reassemblingState
reassembling state
Definition: lte-rlc-am.h:233
void ExpireStatusProhibitTimer()
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1775
SequenceNumber10 m_vrMr
VR(MR)
Definition: lte-rlc-am.h:185
Time m_statusProhibitTimerValue
status prohibit timer value
Definition: lte-rlc-am.h:209
bool IsInsideReceivingWindow(SequenceNumber10 seqNumber)
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1163
uint16_t m_windowSize
Constants.
Definition: lte-rlc-am.h:199
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-am.h:234
void DoNotifyHarqDeliveryFailure() override
Notify HARQ delivery failure.
Definition: lte-rlc-am.cc:783
SequenceNumber10 m_vrH
VR(H)
Definition: lte-rlc-am.h:188
uint32_t m_txonBufferSize
transmit on buffer size
Definition: lte-rlc-am.h:149
std::vector< TxPdu > m_txonBuffer
Transmission buffer.
Definition: lte-rlc-am.h:133
SequenceNumber10 m_vrMs
VR(MS)
Definition: lte-rlc-am.h:187
uint16_t m_pollByte
poll byte
Definition: lte-rlc-am.h:218
SequenceNumber10 m_vtS
VT(S)
Definition: lte-rlc-am.h:180
void DoDispose() override
Destructor implementation.
Definition: lte-rlc-am.cc:133
SequenceNumber10 m_pollSn
POLL_SN.
Definition: lte-rlc-am.h:181
SequenceNumber10 m_vtA
State variables.
Definition: lte-rlc-am.h:178
void ExpireReorderingTimer()
This method will schedule a timeout at WaitReplyTimeout interval in the future, unless a timer is alr...
Definition: lte-rlc-am.cc:1689
SequenceNumber10 m_vtMs
VT(MS)
Definition: lte-rlc-am.h:179
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-am.h:210
~LteRlcAm() override
Definition: lte-rlc-am.cc:81
uint32_t m_statusPduBufferSize
status PDU buffer size
Definition: lte-rlc-am.h:154
Ptr< Packet > m_controlPduBuffer
Control PDU buffer (just one PDU)
Definition: lte-rlc-am.h:167
bool m_txOpportunityForRetxAlwaysBigEnough
transmit opportunity for retransmit?
Definition: lte-rlc-am.h:220
bool m_pollRetransmitTimerJustExpired
poll retransmit timer just expired?
Definition: lte-rlc-am.h:221
void DoTransmitPdcpPdu(Ptr< Packet > p) override
RLC SAP.
Definition: lte-rlc-am.cc:161
Time m_reorderingTimerValue
reordering timer value
Definition: lte-rlc-am.h:207
uint32_t m_maxTxBufferSize
maximum transmission buffer size
Definition: lte-rlc-am.h:148
void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams) override
Receive PDU function.
Definition: lte-rlc-am.cc:789
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet (PDU)
Definition: lte-rlc-am.h:172
EventId m_pollRetransmitTimer
Timers.
Definition: lte-rlc-am.h:204
uint16_t m_maxRetxThreshold
Configurable parameters.
Definition: lte-rlc-am.h:216
SequenceNumber10 m_vrX
VR(X)
Definition: lte-rlc-am.h:186
std::vector< RetxPdu > m_retxBuffer
Buffer for PDUs considered for retransmission.
Definition: lte-rlc-am.h:146
uint32_t m_byteWithoutPoll
byte without poll
Definition: lte-rlc-am.h:194
void ExpireRbsTimer()
Expire RBS timer.
Definition: lte-rlc-am.cc:1781
uint32_t m_pduWithoutPoll
Counters.
Definition: lte-rlc-am.h:193
static TypeId GetTypeId()
Get the type ID.
Definition: lte-rlc-am.cc:87
void DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams) override
MAC SAP.
Definition: lte-rlc-am.cc:199
Time m_pollRetransmitTimerValue
poll retransmit time value
Definition: lte-rlc-am.h:205
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-am.cc:1619
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver.
Definition: lte-rlc-am.cc:1185
std::map< uint16_t, PduBuffer > m_rxonBuffer
Reception buffer.
Definition: lte-rlc-am.h:165
uint32_t m_txedBufferSize
transmit ed buffer size
Definition: lte-rlc-am.h:151
uint16_t m_pollPdu
poll PDU
Definition: lte-rlc-am.h:217
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-am.h:206
void ExpirePollRetransmitTimer()
Expire poll retransmitter.
Definition: lte-rlc-am.cc:1731
SequenceNumber10 m_vrR
VR(R)
Definition: lte-rlc-am.h:184
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-am.h:239
uint32_t m_retxBufferSize
retransmit buffer size
Definition: lte-rlc-am.h:150
EventId m_statusProhibitTimer
status prohibit timer
Definition: lte-rlc-am.h:208
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:143
bool m_statusPduRequested
status PDU requested
Definition: lte-rlc-am.h:153
Time m_rbsTimerValue
RBS timer value.
Definition: lte-rlc-am.h:211
This abstract base class defines the API to interact with the Radio Link Control (LTE_RLC) in LTE,...
Definition: lte-rlc.h:49
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
Definition: lte-rlc.h:148
uint8_t m_lcid
LCID.
Definition: lte-rlc.h:173
TracedCallback< Ptr< const Packet > > m_txDropTrace
The trace source fired when the RLC drops a packet before transmission.
Definition: lte-rlc.h:189
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:172
TracedCallback< uint16_t, uint8_t, uint32_t, uint64_t > m_rxPdu
Used to inform of a PDU reception from the MAC SAP user.
Definition: lte-rlc.h:184
void DoDispose() override
Destructor implementation.
Definition: lte-rlc.cc:126
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:170
TracedCallback< uint16_t, uint8_t, uint32_t > m_txPdu
Used to inform of a PDU delivery to the MAC SAP provider.
Definition: lte-rlc.h:180
virtual void ReceivePdcpPdu(Ptr< Packet > p)=0
Called by the RLC entity to notify the PDCP entity of the reception of a new PDCP PDU.
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
uint8_t GetStatus() const
Get status function.
void SetStatus(uint8_t status)
Set status function.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:962
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
Time GetSenderTimestamp() const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Definition: lte-rlc-tag.h:64
void SetSenderTimestamp(Time senderTimestamp)
Set the sender timestamp.
Definition: lte-rlc-tag.h:74
SequenceNumber10 class.
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
void SetModulusBase(SequenceNumber10 modulusBase)
Set modulus base.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:417
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:407
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition: nstime.h:1444
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Parameters for LteMacSapProvider::ReportBufferStatus.
Definition: lte-mac-sap.h:69
uint32_t txQueueSize
the current size of the RLC transmission queue
Definition: lte-mac-sap.h:72
uint16_t retxQueueHolDelay
the Head Of Line delay of the retransmission queue
Definition: lte-mac-sap.h:75
uint16_t txQueueHolDelay
the Head Of Line delay of the transmission queue
Definition: lte-mac-sap.h:73
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
Definition: lte-mac-sap.h:74
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:71
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:70
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:77
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:45
Parameters for LteMacSapUser::ReceivePdu.
Definition: lte-mac-sap.h:166
Ptr< Packet > p
the RLC PDU to be received
Definition: lte-mac-sap.h:187
Parameters for LteMacSapUser::NotifyTxOpportunity.
Definition: lte-mac-sap.h:105
uint32_t bytes
the number of bytes to transmit
Definition: lte-mac-sap.h:137
uint8_t componentCarrierId
the component carrier id
Definition: lte-mac-sap.h:140
uint8_t layer
the layer of transmission (MIMO)
Definition: lte-mac-sap.h:138
Store an incoming (from layer above us) PDU, waiting to transmit it.
Definition: lte-rlc-am.h:115