A Discrete-Event Network Simulator
API
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 "ns3/lte-rlc-am.h"
22 
23 #include "ns3/log.h"
24 #include "ns3/lte-rlc-am-header.h"
25 #include "ns3/lte-rlc-sdu-status-tag.h"
26 #include "ns3/lte-rlc-tag.h"
27 #include "ns3/simulator.h"
28 
29 namespace ns3
30 {
31 
32 NS_LOG_COMPONENT_DEFINE("LteRlcAm");
33 
35 
37 {
38  NS_LOG_FUNCTION(this);
39 
40  // Buffers
41  m_txonBufferSize = 0;
42  m_retxBuffer.resize(1024);
43  m_retxBufferSize = 0;
44  m_txedBuffer.resize(1024);
45  m_txedBufferSize = 0;
46 
47  m_statusPduRequested = false;
49 
50  // State variables: transmitting side
51  m_windowSize = 512;
52  m_vtA = 0;
54  m_vtS = 0;
55  m_pollSn = 0;
56 
57  // State variables: receiving side
58  m_vrR = 0;
60  m_vrX = 0;
61  m_vrMs = 0;
62  m_vrH = 0;
63 
64  // Counters
65  m_pduWithoutPoll = 0;
67 
68  // Configurable parameters
70  m_pollPdu = 1;
71  m_pollByte = 50;
72 
73  // SDU reassembling process
76 
78 }
79 
81 {
82  NS_LOG_FUNCTION(this);
83 }
84 
85 TypeId
87 {
88  static TypeId tid =
89  TypeId("ns3::LteRlcAm")
90  .SetParent<LteRlc>()
91  .SetGroupName("Lte")
92  .AddConstructor<LteRlcAm>()
93  .AddAttribute("PollRetransmitTimer",
94  "Value of the t-PollRetransmit timer (See section 7.3 of 3GPP TS 36.322)",
98  .AddAttribute("ReorderingTimer",
99  "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
100  TimeValue(MilliSeconds(10)),
102  MakeTimeChecker())
103  .AddAttribute("StatusProhibitTimer",
104  "Value of the t-StatusProhibit timer (See section 7.3 of 3GPP TS 36.322)",
105  TimeValue(MilliSeconds(10)),
107  MakeTimeChecker())
108  .AddAttribute(
109  "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)),
114  MakeTimeChecker())
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 "
124  "configured, the buffer is unlimited.",
125  UintegerValue(10 * 1024),
127  MakeUintegerChecker<uint32_t>());
128  return tid;
129 }
130 
131 void
133 {
134  NS_LOG_FUNCTION(this);
138  m_rbsTimer.Cancel();
139 
140  m_maxTxBufferSize = 0;
141  m_txonBuffer.clear();
142  m_txonBufferSize = 0;
143  m_txedBuffer.clear();
144  m_txedBufferSize = 0;
145  m_retxBuffer.clear();
146  m_retxBufferSize = 0;
147  m_rxonBuffer.clear();
148  m_sdusBuffer.clear();
149  m_keepS0 = nullptr;
150  m_controlPduBuffer = nullptr;
151 
153 }
154 
159 void
161 {
162  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << p->GetSize());
163 
165  {
167  LteRlcSduStatusTag tag;
169  p->AddPacketTag(tag);
170 
171  NS_LOG_LOGIC("Txon Buffer: New packet added");
172  m_txonBuffer.emplace_back(p, Simulator::Now());
173  m_txonBufferSize += p->GetSize();
174  NS_LOG_LOGIC("NumOfBuffers = " << m_txonBuffer.size());
175  NS_LOG_LOGIC("txonBufferSize = " << m_txonBufferSize);
176  }
177  else
178  {
179  // Discard full RLC SDU
180  NS_LOG_LOGIC("TxonBuffer is full. RLC SDU discarded");
181  NS_LOG_LOGIC("MaxTxBufferSize = " << m_maxTxBufferSize);
182  NS_LOG_LOGIC("txonBufferSize = " << m_txonBufferSize);
183  NS_LOG_LOGIC("packet size = " << p->GetSize());
184  m_txDropTrace(p);
185  }
186 
189  m_rbsTimer.Cancel();
191 }
192 
197 void
199 {
200  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << txOpParams.bytes);
201 
202  if (txOpParams.bytes < 4)
203  {
204  // Stingy MAC: In general, we need more bytes.
205  // There are a more restrictive test for each particular case
206  NS_LOG_LOGIC("TxOpportunity (size = " << txOpParams.bytes << ") too small");
207  NS_ASSERT_MSG(false,
208  "TxOpportunity (size = "
209  << 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
220  << ") too small for the STATUS PDU (size = "
221  << m_statusPduBufferSize << ")");
222  NS_ASSERT_MSG(false,
223  "TxOpportunity (size = "
224  << txOpParams.bytes << ") too small for the STATUS PDU (size = "
225  << m_statusPduBufferSize << ")\n"
226  << "Your MAC scheduler is assigned too few resource blocks.");
227  return;
228  }
229 
230  NS_LOG_LOGIC("Sending STATUS PDU");
231 
232  Ptr<Packet> packet = Create<Packet>();
233  LteRlcAmHeader rlcAmHeader;
235 
236  NS_LOG_LOGIC("Check for SNs to NACK from " << m_vrR.GetValue() << " to "
237  << m_vrMs.GetValue());
238  SequenceNumber10 sn;
239  sn.SetModulusBase(m_vrR);
240  std::map<uint16_t, PduBuffer>::iterator pduIt;
241  for (sn = m_vrR; sn < m_vrMs; sn++)
242  {
243  NS_LOG_LOGIC("SN = " << sn);
244  if (!rlcAmHeader.OneMoreNackWouldFitIn(txOpParams.bytes))
245  {
246  NS_LOG_LOGIC("Can't fit more NACKs in STATUS PDU");
247  break;
248  }
249  pduIt = m_rxonBuffer.find(sn.GetValue());
250  if (pduIt == m_rxonBuffer.end() || (!(pduIt->second.m_pduComplete)))
251  {
252  NS_LOG_LOGIC("adding NACK_SN " << sn.GetValue());
253  rlcAmHeader.PushNack(sn.GetValue());
254  }
255  }
256  NS_LOG_LOGIC("SN at end of NACK loop = " << sn);
257  // 3GPP TS 36.322 section 6.2.2.1.4 ACK SN
258  // find the SN of the next not received RLC Data PDU
259  // which is not reported as missing in the STATUS PDU.
260  pduIt = m_rxonBuffer.find(sn.GetValue());
261  while ((sn < m_vrMs) && (pduIt != m_rxonBuffer.end()) && (pduIt->second.m_pduComplete))
262  {
263  NS_LOG_LOGIC("SN = " << sn << " < " << m_vrMs << " = " << (sn < m_vrMs));
264  sn++;
265  NS_LOG_LOGIC("SN = " << sn);
266  pduIt = m_rxonBuffer.find(sn.GetValue());
267  }
268 
269  NS_ASSERT_MSG(sn <= m_vrMs,
270  "first SN not reported as missing = " << sn << ", VR(MS) = " << m_vrMs);
271  rlcAmHeader.SetAckSn(sn);
272 
273  NS_LOG_LOGIC("RLC header: " << rlcAmHeader);
274  packet->AddHeader(rlcAmHeader);
275 
276  // Sender timestamp
277  RlcTag rlcTag(Simulator::Now());
278  packet->AddByteTag(rlcTag, 1, rlcAmHeader.GetSerializedSize());
279  m_txPdu(m_rnti, m_lcid, packet->GetSize());
280 
281  // Send RLC PDU to MAC layer
283  params.pdu = packet;
284  params.rnti = m_rnti;
285  params.lcid = m_lcid;
286  params.layer = txOpParams.layer;
287  params.harqProcessId = txOpParams.harqId;
288  params.componentCarrierId = txOpParams.componentCarrierId;
289 
291 
292  m_statusPduRequested = false;
296  this);
297  return;
298  }
299  else if (m_retxBufferSize > 0)
300  {
301  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
302  NS_LOG_LOGIC("Sending data from Retransmission Buffer");
303  NS_ASSERT(m_vtA < m_vtS);
304  SequenceNumber10 sn;
305  sn.SetModulusBase(m_vtA);
306  for (sn = m_vtA; sn < m_vtS; sn++)
307  {
308  uint16_t seqNumberValue = sn.GetValue();
309  NS_LOG_LOGIC("SN = " << seqNumberValue << " m_pdu "
310  << m_retxBuffer.at(seqNumberValue).m_pdu);
311 
312  if (m_retxBuffer.at(seqNumberValue).m_pdu)
313  {
314  Ptr<Packet> packet = m_retxBuffer.at(seqNumberValue).m_pdu->Copy();
315 
316  if ((packet->GetSize() <= txOpParams.bytes) ||
318  {
319  // According to 5.2.1, the data field is left as is, but we rebuild the header
320  LteRlcAmHeader rlcAmHeader;
321  packet->RemoveHeader(rlcAmHeader);
322  NS_LOG_LOGIC("old AM RLC header: " << rlcAmHeader);
323 
324  // Calculate the Polling Bit (5.2.2.1)
326 
327  NS_LOG_LOGIC("polling conditions: m_txonBuffer.empty="
328  << m_txonBuffer.empty() << " retxBufferSize=" << m_retxBufferSize
329  << " packet->GetSize ()=" << packet->GetSize());
330  if (((m_txonBuffer.empty()) &&
331  (m_retxBufferSize ==
332  packet->GetSize() + rlcAmHeader.GetSerializedSize())) ||
334  {
337  m_pduWithoutPoll = 0;
338  m_byteWithoutPoll = 0;
339 
340  m_pollSn = m_vtS - 1;
341  NS_LOG_LOGIC("New POLL_SN = " << m_pollSn);
342 
344  {
345  NS_LOG_LOGIC("Start PollRetransmit timer");
346 
350  this);
351  }
352  else
353  {
354  NS_LOG_LOGIC("Restart PollRetransmit timer");
355 
360  this);
361  }
362  }
363 
364  packet->AddHeader(rlcAmHeader);
365 
366  RlcTag rlcTag;
368 
369  packet->AddByteTag(rlcTag, 1, rlcAmHeader.GetSerializedSize());
370 
371  NS_LOG_LOGIC("new AM RLC header: " << rlcAmHeader);
372 
373  m_txPdu(m_rnti, m_lcid, packet->GetSize());
374 
375  // Send RLC PDU to MAC layer
377  params.pdu = packet;
378  params.rnti = m_rnti;
379  params.lcid = m_lcid;
380  params.layer = txOpParams.layer;
381  params.harqProcessId = txOpParams.harqId;
382  params.componentCarrierId = txOpParams.componentCarrierId;
383 
385 
386  m_retxBuffer.at(seqNumberValue).m_retxCount++;
387  m_retxBuffer.at(seqNumberValue).m_waitingSince = Simulator::Now();
388  NS_LOG_INFO("Incr RETX_COUNT for SN = " << seqNumberValue);
389  if (m_retxBuffer.at(seqNumberValue).m_retxCount >= m_maxRetxThreshold)
390  {
391  NS_LOG_INFO("Max RETX_COUNT for SN = " << seqNumberValue);
392  }
393 
394  NS_LOG_INFO("Move SN = " << seqNumberValue << " back to txedBuffer");
395  m_txedBuffer.at(seqNumberValue).m_pdu =
396  m_retxBuffer.at(seqNumberValue).m_pdu->Copy();
397  m_txedBuffer.at(seqNumberValue).m_retxCount =
398  m_retxBuffer.at(seqNumberValue).m_retxCount;
399  m_txedBuffer.at(seqNumberValue).m_waitingSince =
400  m_retxBuffer.at(seqNumberValue).m_waitingSince;
401  m_txedBufferSize += m_txedBuffer.at(seqNumberValue).m_pdu->GetSize();
402 
403  m_retxBufferSize -= m_retxBuffer.at(seqNumberValue).m_pdu->GetSize();
404  m_retxBuffer.at(seqNumberValue).m_pdu = nullptr;
405  m_retxBuffer.at(seqNumberValue).m_retxCount = 0;
406  m_retxBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
407 
408  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
409 
410  return;
411  }
412  else
413  {
414  NS_LOG_LOGIC("TxOpportunity (size = "
415  << txOpParams.bytes
416  << ") too small for retransmission of the packet (size = "
417  << packet->GetSize() << ")");
418  NS_LOG_LOGIC("Waiting for bigger TxOpportunity");
419  return;
420  }
421  }
422  }
423  NS_ASSERT_MSG(false, "m_retxBufferSize > 0, but no PDU considered for retx found");
424  }
425  else if (m_txonBufferSize > 0)
426  {
427  if (txOpParams.bytes < 7)
428  {
429  // Stingy MAC: We need more bytes for new DATA PDUs.
430  NS_LOG_LOGIC("TxOpportunity (size = " << txOpParams.bytes
431  << ") too small for DATA PDU");
432  NS_ASSERT_MSG(false,
433  "TxOpportunity (size = "
434  << txOpParams.bytes << ") too small for DATA PDU\n"
435  << "Your MAC scheduler is assigned too few resource blocks.");
436  return;
437  }
438 
439  NS_ASSERT(m_vtS <= m_vtMs);
440  if (m_vtS == m_vtMs)
441  {
442  NS_LOG_INFO("cannot transmit new RLC PDU due to window stalling");
443  return;
444  }
445 
446  NS_LOG_LOGIC("Sending data from Transmission Buffer");
447  }
448  else
449  {
450  NS_LOG_LOGIC("No data pending");
451  return;
452  }
453 
454  //
455  //
456  // Build new PDU
457  //
458  //
459 
460  Ptr<Packet> packet = Create<Packet>();
461  LteRlcAmHeader rlcAmHeader;
462  rlcAmHeader.SetDataPdu();
463 
464  // Build Data field
465  uint32_t nextSegmentSize = txOpParams.bytes - 4;
466  uint32_t nextSegmentId = 1;
467  uint32_t dataFieldAddedSize = 0;
468  std::vector<Ptr<Packet>> dataField;
469 
470  // Remove the first packet from the transmission buffer.
471  // If only a segment of the packet is taken, then the remaining is given back later
472  if (m_txonBuffer.empty())
473  {
474  NS_LOG_LOGIC("No data pending");
475  return;
476  }
477 
478  NS_LOG_LOGIC("SDUs in TxonBuffer = " << m_txonBuffer.size());
479  NS_LOG_LOGIC("First SDU buffer = " << m_txonBuffer.begin()->m_pdu);
480  NS_LOG_LOGIC("First SDU size = " << m_txonBuffer.begin()->m_pdu->GetSize());
481  NS_LOG_LOGIC("Next segment size = " << nextSegmentSize);
482  NS_LOG_LOGIC("Remove SDU from TxBuffer");
483  Time firstSegmentTime = m_txonBuffer.begin()->m_waitingSince;
484  Ptr<Packet> firstSegment = m_txonBuffer.begin()->m_pdu->Copy();
485  m_txonBufferSize -= m_txonBuffer.begin()->m_pdu->GetSize();
486  NS_LOG_LOGIC("txBufferSize = " << m_txonBufferSize);
487  m_txonBuffer.erase(m_txonBuffer.begin());
488 
489  while (firstSegment && (firstSegment->GetSize() > 0) && (nextSegmentSize > 0))
490  {
491  NS_LOG_LOGIC("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
492  NS_LOG_LOGIC(" firstSegment size = " << firstSegment->GetSize());
493  NS_LOG_LOGIC(" nextSegmentSize = " << nextSegmentSize);
494  if ((firstSegment->GetSize() > nextSegmentSize) ||
495  // Segment larger than 2047 octets can only be mapped to the end of the Data field
496  (firstSegment->GetSize() > 2047))
497  {
498  // Take the minimum size, due to the 2047-bytes 3GPP exception
499  // This exception is due to the length of the LI field (just 11 bits)
500  uint32_t currSegmentSize = std::min(firstSegment->GetSize(), nextSegmentSize);
501 
502  NS_LOG_LOGIC(" IF ( firstSegment > nextSegmentSize ||");
503  NS_LOG_LOGIC(" firstSegment > 2047 )");
504 
505  // Segment txBuffer.FirstBuffer and
506  // Give back the remaining segment to the transmission buffer
507  Ptr<Packet> newSegment = firstSegment->CreateFragment(0, currSegmentSize);
508  NS_LOG_LOGIC(" newSegment size = " << newSegment->GetSize());
509 
510  // Status tag of the new and remaining segments
511  // Note: This is the only place where a PDU is segmented and
512  // therefore its status can change
513  LteRlcSduStatusTag oldTag;
514  LteRlcSduStatusTag newTag;
515  firstSegment->RemovePacketTag(oldTag);
516  newSegment->RemovePacketTag(newTag);
517  if (oldTag.GetStatus() == LteRlcSduStatusTag::FULL_SDU)
518  {
521  }
522  else if (oldTag.GetStatus() == LteRlcSduStatusTag::LAST_SEGMENT)
523  {
525  // oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
526  }
527 
528  // Give back the remaining segment to the transmission buffer
529  firstSegment->RemoveAtStart(currSegmentSize);
530  NS_LOG_LOGIC(
531  " firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize());
532  if (firstSegment->GetSize() > 0)
533  {
534  firstSegment->AddPacketTag(oldTag);
535 
536  m_txonBuffer.insert(m_txonBuffer.begin(), TxPdu(firstSegment, firstSegmentTime));
537  m_txonBufferSize += m_txonBuffer.begin()->m_pdu->GetSize();
538 
539  NS_LOG_LOGIC(" Txon buffer: Give back the remaining segment");
540  NS_LOG_LOGIC(" Txon buffers = " << m_txonBuffer.size());
541  NS_LOG_LOGIC(" Front buffer size = " << m_txonBuffer.begin()->m_pdu->GetSize());
542  NS_LOG_LOGIC(" txonBufferSize = " << m_txonBufferSize);
543  }
544  else
545  {
546  // Whole segment was taken, so adjust tag
548  {
550  }
551  else if (newTag.GetStatus() == LteRlcSduStatusTag::MIDDLE_SEGMENT)
552  {
554  }
555  }
556  // Segment is completely taken or
557  // the remaining segment is given back to the transmission buffer
558  firstSegment = nullptr;
559 
560  // Put status tag once it has been adjusted
561  newSegment->AddPacketTag(newTag);
562 
563  // Add Segment to Data field
564  dataFieldAddedSize = newSegment->GetSize();
565  dataField.push_back(newSegment);
566  newSegment = nullptr;
567 
568  // ExtensionBit (Next_Segment - 1) = 0
570 
571  // no LengthIndicator for the last one
572 
573  nextSegmentSize -= dataFieldAddedSize;
574  nextSegmentId++;
575 
576  // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
577 
578  // (NO more segments) ? exit
579  // break;
580  }
581  else if ((nextSegmentSize - firstSegment->GetSize() <= 2) || m_txonBuffer.empty())
582  {
583  NS_LOG_LOGIC(
584  " IF nextSegmentSize - firstSegment->GetSize () <= 2 || txonBuffer.size == 0");
585 
586  // Add txBuffer.FirstBuffer to DataField
587  dataFieldAddedSize = firstSegment->GetSize();
588  dataField.push_back(firstSegment);
589  firstSegment = nullptr;
590 
591  // ExtensionBit (Next_Segment - 1) = 0
593 
594  // no LengthIndicator for the last one
595 
596  nextSegmentSize -= dataFieldAddedSize;
597  nextSegmentId++;
598 
599  NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txonBuffer.size());
600  if (!m_txonBuffer.empty())
601  {
602  NS_LOG_LOGIC(" First SDU buffer = " << m_txonBuffer.begin()->m_pdu);
603  NS_LOG_LOGIC(
604  " First SDU size = " << m_txonBuffer.begin()->m_pdu->GetSize());
605  }
606  NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
607 
608  // nextSegmentSize <= 2 (only if txBuffer is not empty)
609 
610  // (NO more segments) ? exit
611  // break;
612  }
613  else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
614  {
615  NS_LOG_LOGIC(" IF firstSegment < NextSegmentSize && txonBuffer.size > 0");
616  // Add txBuffer.FirstBuffer to DataField
617  dataFieldAddedSize = firstSegment->GetSize();
618  dataField.push_back(firstSegment);
619 
620  // ExtensionBit (Next_Segment - 1) = 1
622 
623  // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
624  rlcAmHeader.PushLengthIndicator(firstSegment->GetSize());
625 
626  nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
627  nextSegmentId++;
628 
629  NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txonBuffer.size());
630  if (!m_txonBuffer.empty())
631  {
632  NS_LOG_LOGIC(" First SDU buffer = " << m_txonBuffer.begin()->m_pdu);
633  NS_LOG_LOGIC(
634  " First SDU size = " << m_txonBuffer.begin()->m_pdu->GetSize());
635  }
636  NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
637  NS_LOG_LOGIC(" Remove SDU from TxBuffer");
638 
639  // (more segments)
640  firstSegment = m_txonBuffer.begin()->m_pdu->Copy();
641  firstSegmentTime = m_txonBuffer.begin()->m_waitingSince;
642  m_txonBufferSize -= m_txonBuffer.begin()->m_pdu->GetSize();
643  m_txonBuffer.erase(m_txonBuffer.begin());
644  NS_LOG_LOGIC(" txBufferSize = " << m_txonBufferSize);
645  }
646  }
647 
648  //
649  // Build RLC header
650  //
651 
652  rlcAmHeader.SetSequenceNumber(m_vtS++);
655  rlcAmHeader.SetSegmentOffset(0);
656 
657  NS_ASSERT_MSG(rlcAmHeader.GetSequenceNumber() < m_vtMs, "SN above TX window");
658  NS_ASSERT_MSG(rlcAmHeader.GetSequenceNumber() >= m_vtA, "SN below TX window");
659 
660  // Calculate FramingInfo flag according the status of the SDUs in the DataField
661  uint8_t framingInfo = 0;
662  std::vector<Ptr<Packet>>::iterator it;
663  it = dataField.begin();
664 
665  // FIRST SEGMENT
666  LteRlcSduStatusTag tag;
667  NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
668  (*it)->PeekPacketTag(tag);
669  if ((tag.GetStatus() == LteRlcSduStatusTag::FULL_SDU) ||
671  {
672  framingInfo |= LteRlcAmHeader::FIRST_BYTE;
673  }
674  else
675  {
676  framingInfo |= LteRlcAmHeader::NO_FIRST_BYTE;
677  }
678 
679  // Add all SDUs (in DataField) to the Packet
680  while (it < dataField.end())
681  {
682  NS_LOG_LOGIC("Adding SDU/segment to packet, length = " << (*it)->GetSize());
683 
684  NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
685  (*it)->RemovePacketTag(tag);
686  if (packet->GetSize() > 0)
687  {
688  packet->AddAtEnd(*it);
689  }
690  else
691  {
692  packet = (*it);
693  }
694  it++;
695  }
696 
697  // LAST SEGMENT (Note: There could be only one and be the first one)
698  it--;
699  if ((tag.GetStatus() == LteRlcSduStatusTag::FULL_SDU) ||
701  {
702  framingInfo |= LteRlcAmHeader::LAST_BYTE;
703  }
704  else
705  {
706  framingInfo |= LteRlcAmHeader::NO_LAST_BYTE;
707  }
708 
709  // Set the FramingInfo flag after the calculation
710  rlcAmHeader.SetFramingInfo(framingInfo);
711 
712  // Calculate the Polling Bit (5.2.2.1)
714 
716  NS_LOG_LOGIC("PDU_WITHOUT_POLL = " << m_pduWithoutPoll);
717  m_byteWithoutPoll += packet->GetSize();
718  NS_LOG_LOGIC("BYTE_WITHOUT_POLL = " << m_byteWithoutPoll);
719 
721  ((m_txonBuffer.empty()) && (m_retxBufferSize == 0)) || (m_vtS >= m_vtMs) ||
723  {
726  m_pduWithoutPoll = 0;
727  m_byteWithoutPoll = 0;
728 
729  m_pollSn = m_vtS - 1;
730  NS_LOG_LOGIC("New POLL_SN = " << m_pollSn);
731 
733  {
734  NS_LOG_LOGIC("Start PollRetransmit timer");
735 
738  this);
739  }
740  else
741  {
742  NS_LOG_LOGIC("Restart PollRetransmit timer");
743 
747  this);
748  }
749  }
750 
751  // Build RLC PDU with DataField and Header
752  NS_LOG_LOGIC("AM RLC header: " << rlcAmHeader);
753 
754  RlcTag rlcTag;
756 
757  packet->AddHeader(rlcAmHeader);
758  packet->AddByteTag(rlcTag, 1, rlcAmHeader.GetSerializedSize());
759 
760  // Store new PDU into the Transmitted PDU Buffer
761  NS_LOG_LOGIC("Put transmitted PDU in the txedBuffer");
762  m_txedBufferSize += packet->GetSize();
763  m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_pdu = packet->Copy();
764  m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_retxCount = 0;
765  m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_waitingSince = Simulator::Now();
766 
767  m_txPdu(m_rnti, m_lcid, packet->GetSize());
768 
769  // Send RLC PDU to MAC layer
771  params.pdu = packet;
772  params.rnti = m_rnti;
773  params.lcid = m_lcid;
774  params.layer = txOpParams.layer;
775  params.harqProcessId = txOpParams.harqId;
776  params.componentCarrierId = txOpParams.componentCarrierId;
777 
779 }
780 
781 void
783 {
784  NS_LOG_FUNCTION(this);
785 }
786 
787 void
789 {
790  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << rxPduParams.p->GetSize());
791 
792  // Get RLC header parameters
793  LteRlcAmHeader rlcAmHeader;
794  rxPduParams.p->PeekHeader(rlcAmHeader);
795  NS_LOG_LOGIC("RLC header: " << rlcAmHeader);
796 
797  // Receiver timestamp
798  Time delay;
799  RlcTag rlcTag;
800 
801  bool ret = rxPduParams.p->FindFirstMatchingByteTag(rlcTag);
802  NS_ASSERT_MSG(ret, "RlcTag not found in RLC Header. The packet went into a real network?");
803 
804  delay = Simulator::Now() - rlcTag.GetSenderTimestamp();
805 
806  m_rxPdu(m_rnti, m_lcid, rxPduParams.p->GetSize(), delay.GetNanoSeconds());
807 
808  if (rlcAmHeader.IsDataPdu())
809  {
810  // 5.1.3.1 Transmit operations
811 
812  // 5.1.3.1.1 General
813  //
814  // The transmitting side of an AM RLC entity shall prioritize transmission of RLC control
815  // PDUs over RLC data PDUs. The transmitting side of an AM RLC entity shall prioritize
816  // retransmission of RLC data PDUs over transmission of new AMD PDUs.
817  //
818  // The transmitting side of an AM RLC entity shall maintain a transmitting window according
819  // to state variables VT(A) and VT(MS) as follows:
820  // - a SN falls within the transmitting window if VT(A) <= SN < VT(MS);
821  // - a SN falls outside of the transmitting window otherwise.
822  //
823  // The transmitting side of an AM RLC entity shall not deliver to lower layer any RLC data
824  // PDU whose SN falls outside of the transmitting window.
825  //
826  // When delivering a new AMD PDU to lower layer, the transmitting side of an AM RLC entity
827  // shall:
828  // - set the SN of the AMD PDU to VT(S), and then increment VT(S) by one.
829  //
830  // The transmitting side of an AM RLC entity can receive a positive acknowledgement
831  // (confirmation of successful reception by its peer AM RLC entity) for a RLC data PDU by
832  // the following:
833  // - STATUS PDU from its peer AM RLC entity.
834  //
835  // When receiving a positive acknowledgement for an AMD PDU with SN = VT(A), the
836  // transmitting side of an AM RLC entity shall:
837  // - set VT(A) equal to the SN of the AMD PDU with the smallest SN, whose SN falls within
838  // the
839  // range VT(A) <= SN <= VT(S) and for which a positive acknowledgment has not been
840  // received yet.
841  // - if positive acknowledgements have been received for all AMD PDUs associated with
842  // a transmitted RLC SDU:
843  // - send an indication to the upper layers of successful delivery of the RLC SDU.
844 
845  // 5.1.3.2 Receive operations
846  //
847  // 5.1.3.2.1 General
848  //
849  // The receiving side of an AM RLC entity shall maintain a receiving window according to
850  // state variables VR(R) and VR(MR) as follows:
851  // - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
852  // - a SN falls outside of the receiving window otherwise.
853  //
854  // When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity
855  // shall:
856  // - either discard the received RLC data PDU or place it in the reception buffer (see sub
857  // clause 5.1.3.2.2);
858  // - if the received RLC data PDU was placed in the reception buffer:
859  // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop
860  // t-Reordering as needed (see sub clause 5.1.3.2.3).
861  //
862  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
863  // - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
864 
865  SequenceNumber10 seqNumber = rlcAmHeader.GetSequenceNumber();
866  seqNumber.SetModulusBase(m_vrR);
867 
868  if (rlcAmHeader.GetResegmentationFlag() == LteRlcAmHeader::SEGMENT)
869  {
870  NS_LOG_LOGIC("PDU segment received ( SN = " << seqNumber << " )");
871  }
872  else if (rlcAmHeader.GetResegmentationFlag() == LteRlcAmHeader::PDU)
873  {
874  NS_LOG_LOGIC("PDU received ( SN = " << seqNumber << " )");
875  }
876  else
877  {
878  NS_ASSERT_MSG(false, "Neither a PDU segment nor a PDU received");
879  return;
880  }
881 
882  // STATUS PDU is requested
884  {
885  m_statusPduRequested = true;
887 
889  {
891  }
892  }
893 
894  // 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
895  //
896  // When a RLC data PDU is received from lower layer, where the RLC data PDU contains
897  // byte segment numbers y to z of an AMD PDU with SN = x, the receiving side of an AM RLC
898  // entity shall:
899  // - if x falls outside of the receiving window; or
900  // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
901  // - discard the received RLC data PDU;
902  // - else:
903  // - place the received RLC data PDU in the reception buffer;
904  // - if some byte segments of the AMD PDU contained in the RLC data PDU have been
905  // received before:
906  // - discard the duplicate byte segments.
907 
908  NS_LOG_LOGIC("VR(R) = " << m_vrR);
909  NS_LOG_LOGIC("VR(MR) = " << m_vrMr);
910  NS_LOG_LOGIC("VR(X) = " << m_vrX);
911  NS_LOG_LOGIC("VR(MS) = " << m_vrMs);
912  NS_LOG_LOGIC("VR(H) = " << m_vrH);
913 
914  // - if x falls outside of the receiving window; or
915  // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
916  if (!IsInsideReceivingWindow(seqNumber))
917  {
918  NS_LOG_LOGIC("PDU discarded");
919  return;
920  }
921  else
922  {
923  // - if some byte segments of the AMD PDU contained in the RLC data PDU have been
924  // received before:
925  // - discard the duplicate byte segments.
926  // note: re-segmentation of AMD PDU is currently not supported,
927  // so we just check that the segment was not received before
928  std::map<uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find(seqNumber.GetValue());
929  if (it != m_rxonBuffer.end())
930  {
931  NS_ASSERT(!it->second.m_byteSegments.empty());
932  NS_ASSERT_MSG(it->second.m_byteSegments.size() == 1,
933  "re-segmentation not supported");
934  NS_LOG_LOGIC("PDU segment already received, discarded");
935  }
936  else
937  {
938  NS_LOG_LOGIC("Place PDU in the reception buffer ( SN = " << seqNumber << " )");
939  m_rxonBuffer[seqNumber.GetValue()].m_byteSegments.push_back(rxPduParams.p);
940  m_rxonBuffer[seqNumber.GetValue()].m_pduComplete = true;
941  }
942  }
943 
944  // 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception buffer
945  // When a RLC data PDU with SN = x is placed in the reception buffer,
946  // the receiving side of an AM RLC entity shall:
947 
948  // - if x >= VR(H)
949  // - update VR(H) to x+ 1;
950 
951  if (seqNumber >= m_vrH)
952  {
953  m_vrH = seqNumber + 1;
954  NS_LOG_LOGIC("New VR(H) = " << m_vrH);
955  }
956 
957  // - if all byte segments of the AMD PDU with SN = VR(MS) are received:
958  // - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for
959  // which not all byte segments have been received;
960 
961  std::map<uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find(m_vrMs.GetValue());
962  if (it != m_rxonBuffer.end() && it->second.m_pduComplete)
963  {
964  int firstVrMs = m_vrMs.GetValue();
965  while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
966  {
967  m_vrMs++;
968  it = m_rxonBuffer.find(m_vrMs.GetValue());
969  NS_LOG_LOGIC("Incr VR(MS) = " << m_vrMs);
970 
971  NS_ASSERT_MSG(firstVrMs != m_vrMs.GetValue(), "Infinite loop in RxonBuffer");
972  }
973  NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
974  }
975 
976  // - if x = VR(R):
977  // - if all byte segments of the AMD PDU with SN = VR(R) are received:
978  // - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which
979  // not all byte segments have been received;
980  // - update VR(MR) to the updated VR(R) + AM_Window_Size;
981  // - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside
982  // of the receiving window and in-sequence byte segments of the AMD PDU with SN = VR(R),
983  // remove RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer
984  // in sequence if not delivered before;
985 
986  if (seqNumber == m_vrR)
987  {
988  std::map<uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find(seqNumber.GetValue());
989  if (it != m_rxonBuffer.end() && it->second.m_pduComplete)
990  {
991  it = m_rxonBuffer.find(m_vrR.GetValue());
992  int firstVrR = m_vrR.GetValue();
993  while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
994  {
995  NS_LOG_LOGIC("Reassemble and Deliver ( SN = " << m_vrR << " )");
996  NS_ASSERT_MSG(it->second.m_byteSegments.size() == 1,
997  "Too many segments. PDU Reassembly process didn't work");
998  ReassembleAndDeliver(it->second.m_byteSegments.front());
999  m_rxonBuffer.erase(m_vrR.GetValue());
1000 
1001  m_vrR++;
1006  it = m_rxonBuffer.find(m_vrR.GetValue());
1007 
1008  NS_ASSERT_MSG(firstVrR != m_vrR.GetValue(), "Infinite loop in RxonBuffer");
1009  }
1010  NS_LOG_LOGIC("New VR(R) = " << m_vrR);
1012 
1013  NS_LOG_LOGIC("New VR(MR) = " << m_vrMr);
1014  }
1015  }
1016 
1017  // - if t-Reordering is running:
1018  // - if VR(X) = VR(R); or
1019  // - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
1020  // - stop and reset t-Reordering;
1021 
1023  {
1024  NS_LOG_LOGIC("Reordering timer is running");
1025  if ((m_vrX == m_vrR) || ((!IsInsideReceivingWindow(m_vrX)) && (m_vrX != m_vrMr)))
1026  {
1028  NS_LOG_LOGIC("Stop reordering timer");
1030  }
1031  }
1032 
1033  // - if t-Reordering is not running (includes the case t-Reordering is stopped due to
1034  // actions above):
1035  // - if VR (H) > VR(R):
1036  // - start t-Reordering;
1037  // - set VR(X) to VR(H).
1038 
1040  {
1041  NS_LOG_LOGIC("Reordering timer is not running");
1042  if (m_vrH > m_vrR)
1043  {
1044  NS_LOG_LOGIC("Start reordering timer");
1047  this);
1048  m_vrX = m_vrH;
1049  NS_LOG_LOGIC("New VR(X) = " << m_vrX);
1050  }
1051  }
1052  }
1053  else if (rlcAmHeader.IsControlPdu())
1054  {
1055  NS_LOG_INFO("Control AM RLC PDU");
1056 
1057  SequenceNumber10 ackSn = rlcAmHeader.GetAckSn();
1058  SequenceNumber10 sn;
1059 
1060  NS_LOG_INFO("ackSn = " << ackSn);
1061  NS_LOG_INFO("VT(A) = " << m_vtA);
1062  NS_LOG_INFO("VT(S) = " << m_vtS);
1063  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1064  NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1065 
1069  ackSn.SetModulusBase(m_vtA);
1070  sn.SetModulusBase(m_vtA);
1071 
1072  bool incrementVtA = true;
1073 
1074  for (sn = m_vtA; sn < ackSn && sn < m_vtS; sn++)
1075  {
1076  NS_LOG_LOGIC("sn = " << sn);
1077 
1078  uint16_t seqNumberValue = sn.GetValue();
1079 
1080  if (m_pollRetransmitTimer.IsRunning() && (seqNumberValue == m_pollSn.GetValue()))
1081  {
1083  }
1084 
1085  if (rlcAmHeader.IsNackPresent(sn))
1086  {
1087  NS_LOG_LOGIC("sn " << sn << " is NACKed");
1088 
1089  incrementVtA = false;
1090 
1091  if (m_txedBuffer.at(seqNumberValue).m_pdu)
1092  {
1093  NS_LOG_INFO("Move SN = " << seqNumberValue << " to retxBuffer");
1094  m_retxBuffer.at(seqNumberValue).m_pdu =
1095  m_txedBuffer.at(seqNumberValue).m_pdu->Copy();
1096  m_retxBuffer.at(seqNumberValue).m_retxCount =
1097  m_txedBuffer.at(seqNumberValue).m_retxCount;
1098  m_retxBuffer.at(seqNumberValue).m_waitingSince =
1099  m_txedBuffer.at(seqNumberValue).m_waitingSince;
1100  m_retxBufferSize += m_retxBuffer.at(seqNumberValue).m_pdu->GetSize();
1101 
1102  m_txedBufferSize -= m_txedBuffer.at(seqNumberValue).m_pdu->GetSize();
1103  m_txedBuffer.at(seqNumberValue).m_pdu = nullptr;
1104  m_txedBuffer.at(seqNumberValue).m_retxCount = 0;
1105  m_txedBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1106  }
1107 
1108  NS_ASSERT(m_retxBuffer.at(seqNumberValue).m_pdu);
1109  }
1110  else
1111  {
1112  NS_LOG_LOGIC("sn " << sn << " is ACKed");
1113 
1114  if (m_txedBuffer.at(seqNumberValue).m_pdu)
1115  {
1116  NS_LOG_INFO("ACKed SN = " << seqNumberValue << " from txedBuffer");
1117  // NS_LOG_INFO ("m_txedBuffer( " << m_vtA << " )->GetSize = " <<
1118  // m_txedBuffer.at (m_vtA.GetValue ())->GetSize ());
1119  m_txedBufferSize -= m_txedBuffer.at(seqNumberValue).m_pdu->GetSize();
1120  m_txedBuffer.at(seqNumberValue).m_pdu = nullptr;
1121  m_txedBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1122  NS_ASSERT(!m_retxBuffer.at(seqNumberValue).m_pdu);
1123  }
1124 
1125  if (m_retxBuffer.at(seqNumberValue).m_pdu)
1126  {
1127  NS_LOG_INFO("ACKed SN = " << seqNumberValue << " from retxBuffer");
1128  m_retxBufferSize -= m_retxBuffer.at(seqNumberValue).m_pdu->GetSize();
1129  m_retxBuffer.at(seqNumberValue).m_pdu = nullptr;
1130  m_retxBuffer.at(seqNumberValue).m_retxCount = 0;
1131  m_retxBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1132  }
1133  }
1134 
1135  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1136  NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1137 
1138  if (incrementVtA)
1139  {
1140  m_vtA++;
1142  NS_LOG_INFO("New VT(A) = " << m_vtA);
1146  ackSn.SetModulusBase(m_vtA);
1147  sn.SetModulusBase(m_vtA);
1148  }
1149 
1150  } // loop over SN : VT(A) <= SN < ACK SN
1151 
1152  return;
1153  }
1154  else
1155  {
1156  NS_LOG_WARN("Wrong AM RLC PDU type");
1157  return;
1158  }
1159 }
1160 
1161 bool
1163 {
1164  NS_LOG_FUNCTION(this << seqNumber);
1165  NS_LOG_LOGIC("Receiving Window: " << m_vrR << " <= " << seqNumber << " <= " << m_vrMr);
1166 
1169  seqNumber.SetModulusBase(m_vrR);
1170 
1171  if ((m_vrR <= seqNumber) && (seqNumber < m_vrMr))
1172  {
1173  NS_LOG_LOGIC(seqNumber << " is INSIDE the receiving window");
1174  return true;
1175  }
1176  else
1177  {
1178  NS_LOG_LOGIC(seqNumber << " is OUTSIDE the receiving window");
1179  return false;
1180  }
1181 }
1182 
1183 void
1185 {
1186  LteRlcAmHeader rlcAmHeader;
1187  RlcTag rlcTag;
1188  bool ret = packet->FindFirstMatchingByteTag(rlcTag);
1189  NS_ASSERT(ret);
1190  packet->RemoveHeader(rlcAmHeader);
1191  ret = packet->FindFirstMatchingByteTag(rlcTag);
1192  NS_ASSERT(!ret);
1193  uint8_t framingInfo = rlcAmHeader.GetFramingInfo();
1194  SequenceNumber10 currSeqNumber = rlcAmHeader.GetSequenceNumber();
1195  bool expectedSnLost;
1196 
1197  if (currSeqNumber != m_expectedSeqNumber)
1198  {
1199  expectedSnLost = true;
1200  NS_LOG_LOGIC("There are losses. Expected SN = " << m_expectedSeqNumber
1201  << ". Current SN = " << currSeqNumber);
1202  m_expectedSeqNumber = currSeqNumber + 1;
1203  }
1204  else
1205  {
1206  expectedSnLost = false;
1207  NS_LOG_LOGIC("No losses. Expected SN = " << m_expectedSeqNumber
1208  << ". Current SN = " << currSeqNumber);
1210  }
1211 
1212  // Build list of SDUs
1213  uint8_t extensionBit;
1214  uint16_t lengthIndicator;
1215  do
1216  {
1217  extensionBit = rlcAmHeader.PopExtensionBit();
1218  NS_LOG_LOGIC("E = " << (uint16_t)extensionBit);
1219 
1220  if (extensionBit == 0)
1221  {
1222  m_sdusBuffer.push_back(packet);
1223  }
1224  else // extensionBit == 1
1225  {
1226  lengthIndicator = rlcAmHeader.PopLengthIndicator();
1227  NS_LOG_LOGIC("LI = " << lengthIndicator);
1228 
1229  // Check if there is enough data in the packet
1230  if (lengthIndicator >= packet->GetSize())
1231  {
1232  NS_LOG_LOGIC("INTERNAL ERROR: Not enough data in the packet ("
1233  << packet->GetSize() << "). Needed LI=" << lengthIndicator);
1235  }
1236 
1237  // Split packet in two fragments
1238  Ptr<Packet> data_field = packet->CreateFragment(0, lengthIndicator);
1239  packet->RemoveAtStart(lengthIndicator);
1240 
1241  m_sdusBuffer.push_back(data_field);
1242  }
1243  } while (extensionBit == 1);
1244 
1245  std::list<Ptr<Packet>>::iterator it;
1246 
1247  // Current reassembling state
1249  NS_LOG_LOGIC("Reassembling State = 'WAITING_S0_FULL'");
1250  else if (m_reassemblingState == WAITING_SI_SF)
1251  NS_LOG_LOGIC("Reassembling State = 'WAITING_SI_SF'");
1252  else
1253  NS_LOG_LOGIC("Reassembling State = Unknown state");
1254 
1255  // Received framing Info
1256  NS_LOG_LOGIC("Framing Info = " << (uint16_t)framingInfo);
1257  NS_LOG_LOGIC("m_sdusBuffer = " << m_sdusBuffer.size());
1258 
1259  // Reassemble the list of SDUs (when there is no losses)
1260  if (!expectedSnLost)
1261  {
1262  switch (m_reassemblingState)
1263  {
1264  case WAITING_S0_FULL:
1265  switch (framingInfo)
1266  {
1269 
1273  for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
1274  {
1276  }
1277  m_sdusBuffer.clear();
1278  break;
1279 
1282 
1286  while (m_sdusBuffer.size() > 1)
1287  {
1289  m_sdusBuffer.pop_front();
1290  }
1291 
1295  m_keepS0 = m_sdusBuffer.front();
1296  m_sdusBuffer.pop_front();
1297  break;
1298 
1301  default:
1305  NS_LOG_LOGIC(
1306  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1307  break;
1308  }
1309  break;
1310 
1311  case WAITING_SI_SF:
1312  switch (framingInfo)
1313  {
1316 
1320  m_keepS0->AddAtEnd(m_sdusBuffer.front());
1321  m_sdusBuffer.pop_front();
1323 
1327  while (!m_sdusBuffer.empty())
1328  {
1330  m_sdusBuffer.pop_front();
1331  }
1332  break;
1333 
1336 
1340  if (m_sdusBuffer.size() == 1)
1341  {
1342  m_keepS0->AddAtEnd(m_sdusBuffer.front());
1343  m_sdusBuffer.pop_front();
1344  }
1345  else // m_sdusBuffer.size () > 1
1346  {
1350  m_keepS0->AddAtEnd(m_sdusBuffer.front());
1351  m_sdusBuffer.pop_front();
1353 
1357  while (m_sdusBuffer.size() > 1)
1358  {
1360  m_sdusBuffer.pop_front();
1361  }
1362 
1366  m_keepS0 = m_sdusBuffer.front();
1367  m_sdusBuffer.pop_front();
1368  }
1369  break;
1370 
1373  default:
1377  NS_LOG_LOGIC(
1378  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1379  break;
1380  }
1381  break;
1382 
1383  default:
1384  NS_LOG_LOGIC(
1385  "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1386  break;
1387  }
1388  }
1389  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the
1390  // expected one)
1391  {
1392  switch (m_reassemblingState)
1393  {
1394  case WAITING_S0_FULL:
1395  switch (framingInfo)
1396  {
1399 
1403  for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
1404  {
1406  }
1407  m_sdusBuffer.clear();
1408  break;
1409 
1412 
1416  while (m_sdusBuffer.size() > 1)
1417  {
1419  m_sdusBuffer.pop_front();
1420  }
1421 
1425  m_keepS0 = m_sdusBuffer.front();
1426  m_sdusBuffer.pop_front();
1427  break;
1428 
1431 
1435  m_sdusBuffer.pop_front();
1436 
1440  while (!m_sdusBuffer.empty())
1441  {
1443  m_sdusBuffer.pop_front();
1444  }
1445  break;
1446 
1448  if (m_sdusBuffer.size() == 1)
1449  {
1451  }
1452  else
1453  {
1455  }
1456 
1460  m_sdusBuffer.pop_front();
1461 
1462  if (!m_sdusBuffer.empty())
1463  {
1467  while (m_sdusBuffer.size() > 1)
1468  {
1470  m_sdusBuffer.pop_front();
1471  }
1472 
1476  m_keepS0 = m_sdusBuffer.front();
1477  m_sdusBuffer.pop_front();
1478  }
1479  break;
1480 
1481  default:
1485  NS_LOG_LOGIC(
1486  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1487  break;
1488  }
1489  break;
1490 
1491  case WAITING_SI_SF:
1492  switch (framingInfo)
1493  {
1496 
1500  m_keepS0 = nullptr;
1501 
1505  while (!m_sdusBuffer.empty())
1506  {
1508  m_sdusBuffer.pop_front();
1509  }
1510  break;
1511 
1514 
1518  m_keepS0 = nullptr;
1519 
1523  while (m_sdusBuffer.size() > 1)
1524  {
1526  m_sdusBuffer.pop_front();
1527  }
1528 
1532  m_keepS0 = m_sdusBuffer.front();
1533  m_sdusBuffer.pop_front();
1534 
1535  break;
1536 
1539 
1543  m_keepS0 = nullptr;
1544 
1548  m_sdusBuffer.pop_front();
1549 
1553  while (!m_sdusBuffer.empty())
1554  {
1556  m_sdusBuffer.pop_front();
1557  }
1558  break;
1559 
1561  if (m_sdusBuffer.size() == 1)
1562  {
1564  }
1565  else
1566  {
1568  }
1569 
1573  m_keepS0 = nullptr;
1574 
1578  m_sdusBuffer.pop_front();
1579 
1580  if (!m_sdusBuffer.empty())
1581  {
1585  while (m_sdusBuffer.size() > 1)
1586  {
1588  m_sdusBuffer.pop_front();
1589  }
1590 
1594  m_keepS0 = m_sdusBuffer.front();
1595  m_sdusBuffer.pop_front();
1596  }
1597  break;
1598 
1599  default:
1603  NS_LOG_LOGIC(
1604  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1605  break;
1606  }
1607  break;
1608 
1609  default:
1610  NS_LOG_LOGIC(
1611  "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1612  break;
1613  }
1614  }
1615 }
1616 
1617 void
1619 {
1620  NS_LOG_FUNCTION(this);
1621 
1622  Time now = Simulator::Now();
1623 
1624  NS_LOG_LOGIC("txonBufferSize = " << m_txonBufferSize);
1625  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1626  NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1627  NS_LOG_LOGIC("VT(A) = " << m_vtA);
1628  NS_LOG_LOGIC("VT(S) = " << m_vtS);
1629 
1630  // Transmission Queue HOL time
1631  Time txonQueueHolDelay(0);
1632  if (m_txonBufferSize > 0)
1633  {
1634  txonQueueHolDelay = now - m_txonBuffer.front().m_waitingSince;
1635  }
1636 
1637  // Retransmission Queue HOL time
1638  Time retxQueueHolDelay;
1639  if (m_retxBufferSize > 0)
1640  {
1641  Time senderTimestamp;
1642  if (m_retxBuffer.at(m_vtA.GetValue()).m_pdu)
1643  {
1644  senderTimestamp = m_retxBuffer.at(m_vtA.GetValue()).m_waitingSince;
1645  }
1646  else
1647  {
1648  senderTimestamp = m_txedBuffer.at(m_vtA.GetValue()).m_waitingSince;
1649  }
1650  retxQueueHolDelay = now - senderTimestamp;
1651  }
1652  else
1653  {
1654  retxQueueHolDelay = Seconds(0);
1655  }
1656 
1658  r.rnti = m_rnti;
1659  r.lcid = m_lcid;
1661  r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds();
1663  r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds();
1664 
1666  {
1668  }
1669  else
1670  {
1671  r.statusPduSize = 0;
1672  }
1673 
1674  if (r.txQueueSize != 0 || r.retxQueueSize != 0 || r.statusPduSize != 0)
1675  {
1676  NS_LOG_INFO("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay
1677  << ", " << r.retxQueueSize << ", "
1678  << r.retxQueueHolDelay << ", " << r.statusPduSize);
1680  }
1681  else
1682  {
1683  NS_LOG_INFO("ReportBufferStatus don't needed");
1684  }
1685 }
1686 
1687 void
1689 {
1690  NS_LOG_FUNCTION(this);
1691  NS_LOG_LOGIC("Reordering Timer has expired");
1692 
1693  // 5.1.3.2.4 Actions when t-Reordering expires
1694  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
1695  // - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte
1696  // segments
1697  // have been received;
1698  // - if VR(H) > VR(MS):
1699  // - start t-Reordering;
1700  // - set VR(X) to VR(H).
1701 
1702  m_vrMs = m_vrX;
1703  int firstVrMs = m_vrMs.GetValue();
1704  std::map<uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find(m_vrMs.GetValue());
1705  while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
1706  {
1707  m_vrMs++;
1708  it = m_rxonBuffer.find(m_vrMs.GetValue());
1709 
1710  NS_ASSERT_MSG(firstVrMs != m_vrMs.GetValue(), "Infinite loop in ExpireReorderingTimer");
1711  }
1712  NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
1713 
1714  if (m_vrH > m_vrMs)
1715  {
1716  NS_LOG_LOGIC("Start reordering timer");
1719  m_vrX = m_vrH;
1720  NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
1721  }
1722 
1723  // Section 5.2.3 Status Reporting:
1724  // - The receiving side of an AM RLC entity shall trigger a
1725  // STATUS report when T_reordering expires.
1726  m_statusPduRequested = true;
1727 }
1728 
1729 void
1731 {
1732  NS_LOG_FUNCTION(this);
1733  NS_LOG_LOGIC("PollRetransmit Timer has expired");
1734 
1735  NS_LOG_LOGIC("txonBufferSize = " << m_txonBufferSize);
1736  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1737  NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1738  NS_LOG_LOGIC("statusPduRequested = " << m_statusPduRequested);
1739 
1741 
1742  // see section 5.2.2.3
1743  // note the difference between Rel 8 and Rel 11 specs; we follow Rel 11 here
1744  NS_ASSERT(m_vtS <= m_vtMs);
1745  if ((m_txonBufferSize == 0 && m_retxBufferSize == 0) || (m_vtS == m_vtMs))
1746  {
1747  NS_LOG_INFO("txonBuffer and retxBuffer empty. Move PDUs up to = " << m_vtS.GetValue() - 1
1748  << " to retxBuffer");
1749  for (SequenceNumber10 sn = m_vtA; sn < m_vtS; sn++)
1750  {
1751  bool pduAvailable = (bool)m_txedBuffer.at(sn.GetValue()).m_pdu;
1752 
1753  if (pduAvailable)
1754  {
1755  uint16_t snValue = sn.GetValue();
1756  NS_LOG_INFO("Move PDU " << sn << " from txedBuffer to retxBuffer");
1757  m_retxBuffer.at(snValue).m_pdu = m_txedBuffer.at(snValue).m_pdu->Copy();
1758  m_retxBuffer.at(snValue).m_retxCount = m_txedBuffer.at(snValue).m_retxCount;
1759  m_retxBuffer.at(snValue).m_waitingSince = m_txedBuffer.at(snValue).m_waitingSince;
1760  m_retxBufferSize += m_retxBuffer.at(snValue).m_pdu->GetSize();
1761 
1762  m_txedBufferSize -= m_txedBuffer.at(snValue).m_pdu->GetSize();
1763  m_txedBuffer.at(snValue).m_pdu = nullptr;
1764  m_txedBuffer.at(snValue).m_retxCount = 0;
1765  m_txedBuffer.at(snValue).m_waitingSince = MilliSeconds(0);
1766  }
1767  }
1768  }
1769 
1771 }
1772 
1773 void
1775 {
1776  NS_LOG_FUNCTION(this);
1777 }
1778 
1779 void
1781 {
1782  NS_LOG_LOGIC("RBS Timer expires");
1783 
1785  {
1788  }
1789 }
1790 
1791 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
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.
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:37
ReassemblingState_t m_reassemblingState
reassembling state
Definition: lte-rlc-am.h:232
void ExpireStatusProhibitTimer()
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1774
SequenceNumber10 m_vrMr
VR(MR)
Definition: lte-rlc-am.h:184
Time m_statusProhibitTimerValue
status prohibit timer value
Definition: lte-rlc-am.h:208
bool IsInsideReceivingWindow(SequenceNumber10 seqNumber)
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1162
uint16_t m_windowSize
Constants.
Definition: lte-rlc-am.h:198
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-am.h:233
void DoNotifyHarqDeliveryFailure() override
Notify HARQ delivery failure.
Definition: lte-rlc-am.cc:782
SequenceNumber10 m_vrH
VR(H)
Definition: lte-rlc-am.h:187
uint32_t m_txonBufferSize
transmit on buffer size
Definition: lte-rlc-am.h:148
std::vector< TxPdu > m_txonBuffer
Transmission buffer.
Definition: lte-rlc-am.h:132
SequenceNumber10 m_vrMs
VR(MS)
Definition: lte-rlc-am.h:186
uint16_t m_pollByte
poll byte
Definition: lte-rlc-am.h:217
SequenceNumber10 m_vtS
VT(S)
Definition: lte-rlc-am.h:179
void DoDispose() override
Destructor implementation.
Definition: lte-rlc-am.cc:132
SequenceNumber10 m_pollSn
POLL_SN.
Definition: lte-rlc-am.h:180
SequenceNumber10 m_vtA
State variables.
Definition: lte-rlc-am.h:177
void ExpireReorderingTimer()
This method will schedule a timeout at WaitReplyTimeout interval in the future, unless a timer is alr...
Definition: lte-rlc-am.cc:1688
SequenceNumber10 m_vtMs
VT(MS)
Definition: lte-rlc-am.h:178
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-am.h:209
~LteRlcAm() override
Definition: lte-rlc-am.cc:80
uint32_t m_statusPduBufferSize
status PDU buffer size
Definition: lte-rlc-am.h:153
Ptr< Packet > m_controlPduBuffer
Control PDU buffer (just one PDU)
Definition: lte-rlc-am.h:166
bool m_txOpportunityForRetxAlwaysBigEnough
transmit opportunity for retransmit?
Definition: lte-rlc-am.h:219
bool m_pollRetransmitTimerJustExpired
poll retransmit timer just expired?
Definition: lte-rlc-am.h:220
void DoTransmitPdcpPdu(Ptr< Packet > p) override
RLC SAP.
Definition: lte-rlc-am.cc:160
Time m_reorderingTimerValue
reordering timer value
Definition: lte-rlc-am.h:206
uint32_t m_maxTxBufferSize
maximum transmission buffer size
Definition: lte-rlc-am.h:147
void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams) override
Receive PDU function.
Definition: lte-rlc-am.cc:788
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet (PDU)
Definition: lte-rlc-am.h:171
EventId m_pollRetransmitTimer
Timers.
Definition: lte-rlc-am.h:203
uint16_t m_maxRetxThreshold
Configurable parameters.
Definition: lte-rlc-am.h:215
SequenceNumber10 m_vrX
VR(X)
Definition: lte-rlc-am.h:185
std::vector< RetxPdu > m_retxBuffer
Buffer for PDUs considered for retransmission.
Definition: lte-rlc-am.h:145
uint32_t m_byteWithoutPoll
byte without poll
Definition: lte-rlc-am.h:193
void ExpireRbsTimer()
Expire RBS timer.
Definition: lte-rlc-am.cc:1780
uint32_t m_pduWithoutPoll
Counters.
Definition: lte-rlc-am.h:192
static TypeId GetTypeId()
Get the type ID.
Definition: lte-rlc-am.cc:86
void DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams) override
MAC SAP.
Definition: lte-rlc-am.cc:198
Time m_pollRetransmitTimerValue
poll retransmit time value
Definition: lte-rlc-am.h:204
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-am.cc:1618
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver.
Definition: lte-rlc-am.cc:1184
std::map< uint16_t, PduBuffer > m_rxonBuffer
Reception buffer.
Definition: lte-rlc-am.h:164
uint32_t m_txedBufferSize
transmit ed buffer size
Definition: lte-rlc-am.h:150
uint16_t m_pollPdu
poll PDU
Definition: lte-rlc-am.h:216
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-am.h:205
void ExpirePollRetransmitTimer()
Expire poll retransmitter.
Definition: lte-rlc-am.cc:1730
SequenceNumber10 m_vrR
VR(R)
Definition: lte-rlc-am.h:183
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-am.h:238
uint32_t m_retxBufferSize
retransmit buffer size
Definition: lte-rlc-am.h:149
EventId m_statusProhibitTimer
status prohibit timer
Definition: lte-rlc-am.h:207
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:142
bool m_statusPduRequested
status PDU requested
Definition: lte-rlc-am.h:152
Time m_rbsTimerValue
RBS timer value.
Definition: lte-rlc-am.h:210
This abstract base class defines the API to interact with the Radio Link Control (LTE_RLC) in LTE,...
Definition: lte-rlc.h:48
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
Definition: lte-rlc.h:142
uint8_t m_lcid
LCID.
Definition: lte-rlc.h:167
TracedCallback< Ptr< const Packet > > m_txDropTrace
The trace source fired when the RLC drops a packet before transmission.
Definition: lte-rlc.h:181
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:166
TracedCallback< uint16_t, uint8_t, uint32_t, uint64_t > m_rxPdu
Used to inform of a PDU reception from the MAC SAP user.
Definition: lte-rlc.h:176
void DoDispose() override
Destructor implementation.
Definition: lte-rlc.cc:126
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:164
TracedCallback< uint16_t, uint8_t, uint32_t > m_txPdu
Used to inform of a PDU delivery to the MAC SAP provider.
Definition: lte-rlc.h:172
virtual void ReceivePdcpPdu(Ptr< Packet > p)=0
Called by the RLC entity to notify the PDCP entity of the reception of a new PDCP PDU.
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
uint8_t GetStatus() const
Get status function.
void SetStatus(uint8_t status)
Set status function.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:384
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:962
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:238
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:934
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
Time GetSenderTimestamp() const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Definition: lte-rlc-tag.h:64
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:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
#define NS_ASSERT(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)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
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.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
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:114