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 "lte-rlc-am.h"
22 
23 #include "lte-rlc-am-header.h"
24 #include "lte-rlc-sdu-status-tag.h"
25 #include "lte-rlc-tag.h"
26 
27 #include "ns3/log.h"
28 #include "ns3/simulator.h"
29 
30 namespace ns3
31 {
32 
33 NS_LOG_COMPONENT_DEFINE("LteRlcAm");
34 
36 
38 {
39  NS_LOG_FUNCTION(this);
40 
41  // Buffers
42  m_txonBufferSize = 0;
43  m_retxBuffer.resize(1024);
44  m_retxBufferSize = 0;
45  m_txedBuffer.resize(1024);
46  m_txedBufferSize = 0;
47 
48  m_statusPduRequested = false;
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
66  m_pduWithoutPoll = 0;
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 
86 TypeId
88 {
89  static TypeId tid =
90  TypeId("ns3::LteRlcAm")
91  .SetParent<LteRlc>()
92  .SetGroupName("Lte")
93  .AddConstructor<LteRlcAm>()
94  .AddAttribute("PollRetransmitTimer",
95  "Value of the t-PollRetransmit timer (See section 7.3 of 3GPP TS 36.322)",
99  .AddAttribute("ReorderingTimer",
100  "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
101  TimeValue(MilliSeconds(10)),
103  MakeTimeChecker())
104  .AddAttribute("StatusProhibitTimer",
105  "Value of the t-StatusProhibit timer (See section 7.3 of 3GPP TS 36.322)",
106  TimeValue(MilliSeconds(10)),
108  MakeTimeChecker())
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",
113  TimeValue(MilliSeconds(20)),
115  MakeTimeChecker())
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 
132 void
134 {
135  NS_LOG_FUNCTION(this);
139  m_rbsTimer.Cancel();
140 
141  m_maxTxBufferSize = 0;
142  m_txonBuffer.clear();
143  m_txonBufferSize = 0;
144  m_txedBuffer.clear();
145  m_txedBufferSize = 0;
146  m_retxBuffer.clear();
147  m_retxBufferSize = 0;
148  m_rxonBuffer.clear();
149  m_sdusBuffer.clear();
150  m_keepS0 = nullptr;
151  m_controlPduBuffer = nullptr;
152 
154 }
155 
160 void
162 {
163  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << p->GetSize());
164 
166  {
168  LteRlcSduStatusTag tag;
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 
190  m_rbsTimer.Cancel();
192 }
193 
198 void
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());
239  SequenceNumber10 sn;
240  sn.SetModulusBase(m_vrR);
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  auto 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  auto 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  auto it = dataField.begin();
663 
664  // FIRST SEGMENT
665  LteRlcSduStatusTag tag;
666  NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
667  (*it)->PeekPacketTag(tag);
668  if ((tag.GetStatus() == LteRlcSduStatusTag::FULL_SDU) ||
670  {
671  framingInfo |= LteRlcAmHeader::FIRST_BYTE;
672  }
673  else
674  {
675  framingInfo |= LteRlcAmHeader::NO_FIRST_BYTE;
676  }
677 
678  // Add all SDUs (in DataField) to the Packet
679  while (it < dataField.end())
680  {
681  NS_LOG_LOGIC("Adding SDU/segment to packet, length = " << (*it)->GetSize());
682 
683  NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
684  (*it)->RemovePacketTag(tag);
685  if (packet->GetSize() > 0)
686  {
687  packet->AddAtEnd(*it);
688  }
689  else
690  {
691  packet = (*it);
692  }
693  it++;
694  }
695 
696  // LAST SEGMENT (Note: There could be only one and be the first one)
697  it--;
698  if ((tag.GetStatus() == LteRlcSduStatusTag::FULL_SDU) ||
700  {
701  framingInfo |= LteRlcAmHeader::LAST_BYTE;
702  }
703  else
704  {
705  framingInfo |= LteRlcAmHeader::NO_LAST_BYTE;
706  }
707 
708  // Set the FramingInfo flag after the calculation
709  rlcAmHeader.SetFramingInfo(framingInfo);
710 
711  // Calculate the Polling Bit (5.2.2.1)
713 
715  NS_LOG_LOGIC("PDU_WITHOUT_POLL = " << m_pduWithoutPoll);
716  m_byteWithoutPoll += packet->GetSize();
717  NS_LOG_LOGIC("BYTE_WITHOUT_POLL = " << m_byteWithoutPoll);
718 
720  ((m_txonBuffer.empty()) && (m_retxBufferSize == 0)) || (m_vtS >= m_vtMs) ||
722  {
725  m_pduWithoutPoll = 0;
726  m_byteWithoutPoll = 0;
727 
728  m_pollSn = m_vtS - 1;
729  NS_LOG_LOGIC("New POLL_SN = " << m_pollSn);
730 
732  {
733  NS_LOG_LOGIC("Start PollRetransmit timer");
734 
737  this);
738  }
739  else
740  {
741  NS_LOG_LOGIC("Restart PollRetransmit timer");
742 
746  this);
747  }
748  }
749 
750  // Build RLC PDU with DataField and Header
751  NS_LOG_LOGIC("AM RLC header: " << rlcAmHeader);
752 
753  RlcTag rlcTag;
755 
756  packet->AddHeader(rlcAmHeader);
757  packet->AddByteTag(rlcTag, 1, rlcAmHeader.GetSerializedSize());
758 
759  // Store new PDU into the Transmitted PDU Buffer
760  NS_LOG_LOGIC("Put transmitted PDU in the txedBuffer");
761  m_txedBufferSize += packet->GetSize();
762  m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_pdu = packet->Copy();
763  m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_retxCount = 0;
764  m_txedBuffer.at(rlcAmHeader.GetSequenceNumber().GetValue()).m_waitingSince = Simulator::Now();
765 
766  m_txPdu(m_rnti, m_lcid, packet->GetSize());
767 
768  // Send RLC PDU to MAC layer
770  params.pdu = packet;
771  params.rnti = m_rnti;
772  params.lcid = m_lcid;
773  params.layer = txOpParams.layer;
774  params.harqProcessId = txOpParams.harqId;
775  params.componentCarrierId = txOpParams.componentCarrierId;
776 
778 }
779 
780 void
782 {
783  NS_LOG_FUNCTION(this);
784 }
785 
786 void
788 {
789  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << rxPduParams.p->GetSize());
790 
791  // Get RLC header parameters
792  LteRlcAmHeader rlcAmHeader;
793  rxPduParams.p->PeekHeader(rlcAmHeader);
794  NS_LOG_LOGIC("RLC header: " << rlcAmHeader);
795 
796  // Receiver timestamp
797  Time delay;
798  RlcTag rlcTag;
799 
800  bool ret = rxPduParams.p->FindFirstMatchingByteTag(rlcTag);
801  NS_ASSERT_MSG(ret, "RlcTag not found in RLC Header. The packet went into a real network?");
802 
803  delay = Simulator::Now() - rlcTag.GetSenderTimestamp();
804 
805  m_rxPdu(m_rnti, m_lcid, rxPduParams.p->GetSize(), delay.GetNanoSeconds());
806 
807  if (rlcAmHeader.IsDataPdu())
808  {
809  // 5.1.3.1 Transmit operations
810 
811  // 5.1.3.1.1 General
812  //
813  // The transmitting side of an AM RLC entity shall prioritize transmission of RLC control
814  // PDUs over RLC data PDUs. The transmitting side of an AM RLC entity shall prioritize
815  // retransmission of RLC data PDUs over transmission of new AMD PDUs.
816  //
817  // The transmitting side of an AM RLC entity shall maintain a transmitting window according
818  // to state variables VT(A) and VT(MS) as follows:
819  // - a SN falls within the transmitting window if VT(A) <= SN < VT(MS);
820  // - a SN falls outside of the transmitting window otherwise.
821  //
822  // The transmitting side of an AM RLC entity shall not deliver to lower layer any RLC data
823  // PDU whose SN falls outside of the transmitting window.
824  //
825  // When delivering a new AMD PDU to lower layer, the transmitting side of an AM RLC entity
826  // shall:
827  // - set the SN of the AMD PDU to VT(S), and then increment VT(S) by one.
828  //
829  // The transmitting side of an AM RLC entity can receive a positive acknowledgement
830  // (confirmation of successful reception by its peer AM RLC entity) for a RLC data PDU by
831  // the following:
832  // - STATUS PDU from its peer AM RLC entity.
833  //
834  // When receiving a positive acknowledgement for an AMD PDU with SN = VT(A), the
835  // transmitting side of an AM RLC entity shall:
836  // - set VT(A) equal to the SN of the AMD PDU with the smallest SN, whose SN falls within
837  // the
838  // range VT(A) <= SN <= VT(S) and for which a positive acknowledgment has not been
839  // received yet.
840  // - if positive acknowledgements have been received for all AMD PDUs associated with
841  // a transmitted RLC SDU:
842  // - send an indication to the upper layers of successful delivery of the RLC SDU.
843 
844  // 5.1.3.2 Receive operations
845  //
846  // 5.1.3.2.1 General
847  //
848  // The receiving side of an AM RLC entity shall maintain a receiving window according to
849  // state variables VR(R) and VR(MR) as follows:
850  // - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
851  // - a SN falls outside of the receiving window otherwise.
852  //
853  // When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity
854  // shall:
855  // - either discard the received RLC data PDU or place it in the reception buffer (see sub
856  // clause 5.1.3.2.2);
857  // - if the received RLC data PDU was placed in the reception buffer:
858  // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop
859  // t-Reordering as needed (see sub clause 5.1.3.2.3).
860  //
861  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
862  // - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
863 
864  SequenceNumber10 seqNumber = rlcAmHeader.GetSequenceNumber();
865  seqNumber.SetModulusBase(m_vrR);
866 
867  if (rlcAmHeader.GetResegmentationFlag() == LteRlcAmHeader::SEGMENT)
868  {
869  NS_LOG_LOGIC("PDU segment received ( SN = " << seqNumber << " )");
870  }
871  else if (rlcAmHeader.GetResegmentationFlag() == LteRlcAmHeader::PDU)
872  {
873  NS_LOG_LOGIC("PDU received ( SN = " << seqNumber << " )");
874  }
875  else
876  {
877  NS_ASSERT_MSG(false, "Neither a PDU segment nor a PDU received");
878  return;
879  }
880 
881  // STATUS PDU is requested
883  {
884  m_statusPduRequested = true;
886 
888  {
890  }
891  }
892 
893  // 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
894  //
895  // When a RLC data PDU is received from lower layer, where the RLC data PDU contains
896  // byte segment numbers y to z of an AMD PDU with SN = x, the receiving side of an AM RLC
897  // entity shall:
898  // - if x falls outside of the receiving window; or
899  // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
900  // - discard the received RLC data PDU;
901  // - else:
902  // - place the received RLC data PDU in the reception buffer;
903  // - if some byte segments of the AMD PDU contained in the RLC data PDU have been
904  // received before:
905  // - discard the duplicate byte segments.
906 
907  NS_LOG_LOGIC("VR(R) = " << m_vrR);
908  NS_LOG_LOGIC("VR(MR) = " << m_vrMr);
909  NS_LOG_LOGIC("VR(X) = " << m_vrX);
910  NS_LOG_LOGIC("VR(MS) = " << m_vrMs);
911  NS_LOG_LOGIC("VR(H) = " << m_vrH);
912 
913  // - if x falls outside of the receiving window; or
914  // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
915  if (!IsInsideReceivingWindow(seqNumber))
916  {
917  NS_LOG_LOGIC("PDU discarded");
918  return;
919  }
920  else
921  {
922  // - if some byte segments of the AMD PDU contained in the RLC data PDU have been
923  // received before:
924  // - discard the duplicate byte segments.
925  // note: re-segmentation of AMD PDU is currently not supported,
926  // so we just check that the segment was not received before
927  auto it = m_rxonBuffer.find(seqNumber.GetValue());
928  if (it != m_rxonBuffer.end())
929  {
930  NS_ASSERT(!it->second.m_byteSegments.empty());
931  NS_ASSERT_MSG(it->second.m_byteSegments.size() == 1,
932  "re-segmentation not supported");
933  NS_LOG_LOGIC("PDU segment already received, discarded");
934  }
935  else
936  {
937  NS_LOG_LOGIC("Place PDU in the reception buffer ( SN = " << seqNumber << " )");
938  m_rxonBuffer[seqNumber.GetValue()].m_byteSegments.push_back(rxPduParams.p);
939  m_rxonBuffer[seqNumber.GetValue()].m_pduComplete = true;
940  }
941  }
942 
943  // 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception buffer
944  // When a RLC data PDU with SN = x is placed in the reception buffer,
945  // the receiving side of an AM RLC entity shall:
946 
947  // - if x >= VR(H)
948  // - update VR(H) to x+ 1;
949 
950  if (seqNumber >= m_vrH)
951  {
952  m_vrH = seqNumber + 1;
953  NS_LOG_LOGIC("New VR(H) = " << m_vrH);
954  }
955 
956  // - if all byte segments of the AMD PDU with SN = VR(MS) are received:
957  // - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for
958  // which not all byte segments have been received;
959 
960  auto it = m_rxonBuffer.find(m_vrMs.GetValue());
961  if (it != m_rxonBuffer.end() && it->second.m_pduComplete)
962  {
963  int firstVrMs = m_vrMs.GetValue();
964  while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
965  {
966  m_vrMs++;
967  it = m_rxonBuffer.find(m_vrMs.GetValue());
968  NS_LOG_LOGIC("Incr VR(MS) = " << m_vrMs);
969 
970  NS_ASSERT_MSG(firstVrMs != m_vrMs.GetValue(), "Infinite loop in RxonBuffer");
971  }
972  NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
973  }
974 
975  // - if x = VR(R):
976  // - if all byte segments of the AMD PDU with SN = VR(R) are received:
977  // - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which
978  // not all byte segments have been received;
979  // - update VR(MR) to the updated VR(R) + AM_Window_Size;
980  // - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside
981  // of the receiving window and in-sequence byte segments of the AMD PDU with SN = VR(R),
982  // remove RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer
983  // in sequence if not delivered before;
984 
985  if (seqNumber == m_vrR)
986  {
987  auto it = m_rxonBuffer.find(seqNumber.GetValue());
988  if (it != m_rxonBuffer.end() && it->second.m_pduComplete)
989  {
990  it = m_rxonBuffer.find(m_vrR.GetValue());
991  int firstVrR = m_vrR.GetValue();
992  while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
993  {
994  NS_LOG_LOGIC("Reassemble and Deliver ( SN = " << m_vrR << " )");
995  NS_ASSERT_MSG(it->second.m_byteSegments.size() == 1,
996  "Too many segments. PDU Reassembly process didn't work");
997  ReassembleAndDeliver(it->second.m_byteSegments.front());
998  m_rxonBuffer.erase(m_vrR.GetValue());
999 
1000  m_vrR++;
1005  it = m_rxonBuffer.find(m_vrR.GetValue());
1006 
1007  NS_ASSERT_MSG(firstVrR != m_vrR.GetValue(), "Infinite loop in RxonBuffer");
1008  }
1009  NS_LOG_LOGIC("New VR(R) = " << m_vrR);
1011 
1012  NS_LOG_LOGIC("New VR(MR) = " << m_vrMr);
1013  }
1014  }
1015 
1016  // - if t-Reordering is running:
1017  // - if VR(X) = VR(R); or
1018  // - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
1019  // - stop and reset t-Reordering;
1020 
1022  {
1023  NS_LOG_LOGIC("Reordering timer is running");
1024  if ((m_vrX == m_vrR) || ((!IsInsideReceivingWindow(m_vrX)) && (m_vrX != m_vrMr)))
1025  {
1027  NS_LOG_LOGIC("Stop reordering timer");
1029  }
1030  }
1031 
1032  // - if t-Reordering is not running (includes the case t-Reordering is stopped due to
1033  // actions above):
1034  // - if VR (H) > VR(R):
1035  // - start t-Reordering;
1036  // - set VR(X) to VR(H).
1037 
1039  {
1040  NS_LOG_LOGIC("Reordering timer is not running");
1041  if (m_vrH > m_vrR)
1042  {
1043  NS_LOG_LOGIC("Start reordering timer");
1046  this);
1047  m_vrX = m_vrH;
1048  NS_LOG_LOGIC("New VR(X) = " << m_vrX);
1049  }
1050  }
1051  }
1052  else if (rlcAmHeader.IsControlPdu())
1053  {
1054  NS_LOG_INFO("Control AM RLC PDU");
1055 
1056  SequenceNumber10 ackSn = rlcAmHeader.GetAckSn();
1057  SequenceNumber10 sn;
1058 
1059  NS_LOG_INFO("ackSn = " << ackSn);
1060  NS_LOG_INFO("VT(A) = " << m_vtA);
1061  NS_LOG_INFO("VT(S) = " << m_vtS);
1062  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1063  NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1064 
1068  ackSn.SetModulusBase(m_vtA);
1069  sn.SetModulusBase(m_vtA);
1070 
1071  bool incrementVtA = true;
1072 
1073  for (sn = m_vtA; sn < ackSn && sn < m_vtS; sn++)
1074  {
1075  NS_LOG_LOGIC("sn = " << sn);
1076 
1077  uint16_t seqNumberValue = sn.GetValue();
1078 
1079  if (m_pollRetransmitTimer.IsRunning() && (seqNumberValue == m_pollSn.GetValue()))
1080  {
1082  }
1083 
1084  if (rlcAmHeader.IsNackPresent(sn))
1085  {
1086  NS_LOG_LOGIC("sn " << sn << " is NACKed");
1087 
1088  incrementVtA = false;
1089 
1090  if (m_txedBuffer.at(seqNumberValue).m_pdu)
1091  {
1092  NS_LOG_INFO("Move SN = " << seqNumberValue << " to retxBuffer");
1093  m_retxBuffer.at(seqNumberValue).m_pdu =
1094  m_txedBuffer.at(seqNumberValue).m_pdu->Copy();
1095  m_retxBuffer.at(seqNumberValue).m_retxCount =
1096  m_txedBuffer.at(seqNumberValue).m_retxCount;
1097  m_retxBuffer.at(seqNumberValue).m_waitingSince =
1098  m_txedBuffer.at(seqNumberValue).m_waitingSince;
1099  m_retxBufferSize += m_retxBuffer.at(seqNumberValue).m_pdu->GetSize();
1100 
1101  m_txedBufferSize -= m_txedBuffer.at(seqNumberValue).m_pdu->GetSize();
1102  m_txedBuffer.at(seqNumberValue).m_pdu = nullptr;
1103  m_txedBuffer.at(seqNumberValue).m_retxCount = 0;
1104  m_txedBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1105  }
1106 
1107  NS_ASSERT(m_retxBuffer.at(seqNumberValue).m_pdu);
1108  }
1109  else
1110  {
1111  NS_LOG_LOGIC("sn " << sn << " is ACKed");
1112 
1113  if (m_txedBuffer.at(seqNumberValue).m_pdu)
1114  {
1115  NS_LOG_INFO("ACKed SN = " << seqNumberValue << " from txedBuffer");
1116  // NS_LOG_INFO ("m_txedBuffer( " << m_vtA << " )->GetSize = " <<
1117  // m_txedBuffer.at (m_vtA.GetValue ())->GetSize ());
1118  m_txedBufferSize -= m_txedBuffer.at(seqNumberValue).m_pdu->GetSize();
1119  m_txedBuffer.at(seqNumberValue).m_pdu = nullptr;
1120  m_txedBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1121  NS_ASSERT(!m_retxBuffer.at(seqNumberValue).m_pdu);
1122  }
1123 
1124  if (m_retxBuffer.at(seqNumberValue).m_pdu)
1125  {
1126  NS_LOG_INFO("ACKed SN = " << seqNumberValue << " from retxBuffer");
1127  m_retxBufferSize -= m_retxBuffer.at(seqNumberValue).m_pdu->GetSize();
1128  m_retxBuffer.at(seqNumberValue).m_pdu = nullptr;
1129  m_retxBuffer.at(seqNumberValue).m_retxCount = 0;
1130  m_retxBuffer.at(seqNumberValue).m_waitingSince = MilliSeconds(0);
1131  }
1132  }
1133 
1134  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1135  NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1136 
1137  if (incrementVtA)
1138  {
1139  m_vtA++;
1141  NS_LOG_INFO("New VT(A) = " << m_vtA);
1145  ackSn.SetModulusBase(m_vtA);
1146  sn.SetModulusBase(m_vtA);
1147  }
1148 
1149  } // loop over SN : VT(A) <= SN < ACK SN
1150 
1151  return;
1152  }
1153  else
1154  {
1155  NS_LOG_WARN("Wrong AM RLC PDU type");
1156  return;
1157  }
1158 }
1159 
1160 bool
1162 {
1163  NS_LOG_FUNCTION(this << seqNumber);
1164  NS_LOG_LOGIC("Receiving Window: " << m_vrR << " <= " << seqNumber << " <= " << m_vrMr);
1165 
1168  seqNumber.SetModulusBase(m_vrR);
1169 
1170  if ((m_vrR <= seqNumber) && (seqNumber < m_vrMr))
1171  {
1172  NS_LOG_LOGIC(seqNumber << " is INSIDE the receiving window");
1173  return true;
1174  }
1175  else
1176  {
1177  NS_LOG_LOGIC(seqNumber << " is OUTSIDE the receiving window");
1178  return false;
1179  }
1180 }
1181 
1182 void
1184 {
1185  LteRlcAmHeader rlcAmHeader;
1186  RlcTag rlcTag;
1187  bool ret = packet->FindFirstMatchingByteTag(rlcTag);
1188  NS_ASSERT(ret);
1189  packet->RemoveHeader(rlcAmHeader);
1190  ret = packet->FindFirstMatchingByteTag(rlcTag);
1191  NS_ASSERT(!ret);
1192  uint8_t framingInfo = rlcAmHeader.GetFramingInfo();
1193  SequenceNumber10 currSeqNumber = rlcAmHeader.GetSequenceNumber();
1194  bool expectedSnLost;
1195 
1196  if (currSeqNumber != m_expectedSeqNumber)
1197  {
1198  expectedSnLost = true;
1199  NS_LOG_LOGIC("There are losses. Expected SN = " << m_expectedSeqNumber
1200  << ". Current SN = " << currSeqNumber);
1201  m_expectedSeqNumber = currSeqNumber + 1;
1202  }
1203  else
1204  {
1205  expectedSnLost = false;
1206  NS_LOG_LOGIC("No losses. Expected SN = " << m_expectedSeqNumber
1207  << ". Current SN = " << currSeqNumber);
1209  }
1210 
1211  // Build list of SDUs
1212  uint8_t extensionBit;
1213  uint16_t lengthIndicator;
1214  do
1215  {
1216  extensionBit = rlcAmHeader.PopExtensionBit();
1217  NS_LOG_LOGIC("E = " << (uint16_t)extensionBit);
1218 
1219  if (extensionBit == 0)
1220  {
1221  m_sdusBuffer.push_back(packet);
1222  }
1223  else // extensionBit == 1
1224  {
1225  lengthIndicator = rlcAmHeader.PopLengthIndicator();
1226  NS_LOG_LOGIC("LI = " << lengthIndicator);
1227 
1228  // Check if there is enough data in the packet
1229  if (lengthIndicator >= packet->GetSize())
1230  {
1231  NS_LOG_LOGIC("INTERNAL ERROR: Not enough data in the packet ("
1232  << packet->GetSize() << "). Needed LI=" << lengthIndicator);
1234  }
1235 
1236  // Split packet in two fragments
1237  Ptr<Packet> data_field = packet->CreateFragment(0, lengthIndicator);
1238  packet->RemoveAtStart(lengthIndicator);
1239 
1240  m_sdusBuffer.push_back(data_field);
1241  }
1242  } while (extensionBit == 1);
1243 
1244  // Current reassembling state
1246  {
1247  NS_LOG_LOGIC("Reassembling State = 'WAITING_S0_FULL'");
1248  }
1249  else if (m_reassemblingState == WAITING_SI_SF)
1250  {
1251  NS_LOG_LOGIC("Reassembling State = 'WAITING_SI_SF'");
1252  }
1253  else
1254  {
1255  NS_LOG_LOGIC("Reassembling State = Unknown state");
1256  }
1257 
1258  // Received framing Info
1259  NS_LOG_LOGIC("Framing Info = " << (uint16_t)framingInfo);
1260  NS_LOG_LOGIC("m_sdusBuffer = " << m_sdusBuffer.size());
1261 
1262  // Reassemble the list of SDUs (when there is no losses)
1263  if (!expectedSnLost)
1264  {
1265  switch (m_reassemblingState)
1266  {
1267  case WAITING_S0_FULL:
1268  switch (framingInfo)
1269  {
1272 
1276  for (auto it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
1277  {
1279  }
1280  m_sdusBuffer.clear();
1281  break;
1282 
1285 
1289  while (m_sdusBuffer.size() > 1)
1290  {
1292  m_sdusBuffer.pop_front();
1293  }
1294 
1298  m_keepS0 = m_sdusBuffer.front();
1299  m_sdusBuffer.pop_front();
1300  break;
1301 
1304  default:
1308  NS_LOG_LOGIC(
1309  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1310  break;
1311  }
1312  break;
1313 
1314  case WAITING_SI_SF:
1315  switch (framingInfo)
1316  {
1319 
1323  m_keepS0->AddAtEnd(m_sdusBuffer.front());
1324  m_sdusBuffer.pop_front();
1326 
1330  while (!m_sdusBuffer.empty())
1331  {
1333  m_sdusBuffer.pop_front();
1334  }
1335  break;
1336 
1339 
1343  if (m_sdusBuffer.size() == 1)
1344  {
1345  m_keepS0->AddAtEnd(m_sdusBuffer.front());
1346  m_sdusBuffer.pop_front();
1347  }
1348  else // m_sdusBuffer.size () > 1
1349  {
1353  m_keepS0->AddAtEnd(m_sdusBuffer.front());
1354  m_sdusBuffer.pop_front();
1356 
1360  while (m_sdusBuffer.size() > 1)
1361  {
1363  m_sdusBuffer.pop_front();
1364  }
1365 
1369  m_keepS0 = m_sdusBuffer.front();
1370  m_sdusBuffer.pop_front();
1371  }
1372  break;
1373 
1376  default:
1380  NS_LOG_LOGIC(
1381  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1382  break;
1383  }
1384  break;
1385 
1386  default:
1387  NS_LOG_LOGIC(
1388  "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1389  break;
1390  }
1391  }
1392  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the
1393  // expected one)
1394  {
1395  switch (m_reassemblingState)
1396  {
1397  case WAITING_S0_FULL:
1398  switch (framingInfo)
1399  {
1402 
1406  for (auto it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
1407  {
1409  }
1410  m_sdusBuffer.clear();
1411  break;
1412 
1415 
1419  while (m_sdusBuffer.size() > 1)
1420  {
1422  m_sdusBuffer.pop_front();
1423  }
1424 
1428  m_keepS0 = m_sdusBuffer.front();
1429  m_sdusBuffer.pop_front();
1430  break;
1431 
1434 
1438  m_sdusBuffer.pop_front();
1439 
1443  while (!m_sdusBuffer.empty())
1444  {
1446  m_sdusBuffer.pop_front();
1447  }
1448  break;
1449 
1451  if (m_sdusBuffer.size() == 1)
1452  {
1454  }
1455  else
1456  {
1458  }
1459 
1463  m_sdusBuffer.pop_front();
1464 
1465  if (!m_sdusBuffer.empty())
1466  {
1470  while (m_sdusBuffer.size() > 1)
1471  {
1473  m_sdusBuffer.pop_front();
1474  }
1475 
1479  m_keepS0 = m_sdusBuffer.front();
1480  m_sdusBuffer.pop_front();
1481  }
1482  break;
1483 
1484  default:
1488  NS_LOG_LOGIC(
1489  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1490  break;
1491  }
1492  break;
1493 
1494  case WAITING_SI_SF:
1495  switch (framingInfo)
1496  {
1499 
1503  m_keepS0 = nullptr;
1504 
1508  while (!m_sdusBuffer.empty())
1509  {
1511  m_sdusBuffer.pop_front();
1512  }
1513  break;
1514 
1517 
1521  m_keepS0 = nullptr;
1522 
1526  while (m_sdusBuffer.size() > 1)
1527  {
1529  m_sdusBuffer.pop_front();
1530  }
1531 
1535  m_keepS0 = m_sdusBuffer.front();
1536  m_sdusBuffer.pop_front();
1537 
1538  break;
1539 
1542 
1546  m_keepS0 = nullptr;
1547 
1551  m_sdusBuffer.pop_front();
1552 
1556  while (!m_sdusBuffer.empty())
1557  {
1559  m_sdusBuffer.pop_front();
1560  }
1561  break;
1562 
1564  if (m_sdusBuffer.size() == 1)
1565  {
1567  }
1568  else
1569  {
1571  }
1572 
1576  m_keepS0 = nullptr;
1577 
1581  m_sdusBuffer.pop_front();
1582 
1583  if (!m_sdusBuffer.empty())
1584  {
1588  while (m_sdusBuffer.size() > 1)
1589  {
1591  m_sdusBuffer.pop_front();
1592  }
1593 
1597  m_keepS0 = m_sdusBuffer.front();
1598  m_sdusBuffer.pop_front();
1599  }
1600  break;
1601 
1602  default:
1606  NS_LOG_LOGIC(
1607  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1608  break;
1609  }
1610  break;
1611 
1612  default:
1613  NS_LOG_LOGIC(
1614  "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1615  break;
1616  }
1617  }
1618 }
1619 
1620 void
1622 {
1623  NS_LOG_FUNCTION(this);
1624 
1625  Time now = Simulator::Now();
1626 
1627  NS_LOG_LOGIC("txonBufferSize = " << m_txonBufferSize);
1628  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1629  NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1630  NS_LOG_LOGIC("VT(A) = " << m_vtA);
1631  NS_LOG_LOGIC("VT(S) = " << m_vtS);
1632 
1633  // Transmission Queue HOL time
1634  Time txonQueueHolDelay(0);
1635  if (m_txonBufferSize > 0)
1636  {
1637  txonQueueHolDelay = now - m_txonBuffer.front().m_waitingSince;
1638  }
1639 
1640  // Retransmission Queue HOL time
1641  Time retxQueueHolDelay;
1642  if (m_retxBufferSize > 0)
1643  {
1644  Time senderTimestamp;
1645  if (m_retxBuffer.at(m_vtA.GetValue()).m_pdu)
1646  {
1647  senderTimestamp = m_retxBuffer.at(m_vtA.GetValue()).m_waitingSince;
1648  }
1649  else
1650  {
1651  senderTimestamp = m_txedBuffer.at(m_vtA.GetValue()).m_waitingSince;
1652  }
1653  retxQueueHolDelay = now - senderTimestamp;
1654  }
1655  else
1656  {
1657  retxQueueHolDelay = Seconds(0);
1658  }
1659 
1661  r.rnti = m_rnti;
1662  r.lcid = m_lcid;
1664  r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds();
1666  r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds();
1667 
1669  {
1671  }
1672  else
1673  {
1674  r.statusPduSize = 0;
1675  }
1676 
1677  if (r.txQueueSize != 0 || r.retxQueueSize != 0 || r.statusPduSize != 0)
1678  {
1679  NS_LOG_INFO("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay
1680  << ", " << r.retxQueueSize << ", "
1681  << r.retxQueueHolDelay << ", " << r.statusPduSize);
1683  }
1684  else
1685  {
1686  NS_LOG_INFO("ReportBufferStatus don't needed");
1687  }
1688 }
1689 
1690 void
1692 {
1693  NS_LOG_FUNCTION(this);
1694  NS_LOG_LOGIC("Reordering Timer has expired");
1695 
1696  // 5.1.3.2.4 Actions when t-Reordering expires
1697  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
1698  // - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte
1699  // segments
1700  // have been received;
1701  // - if VR(H) > VR(MS):
1702  // - start t-Reordering;
1703  // - set VR(X) to VR(H).
1704 
1705  m_vrMs = m_vrX;
1706  int firstVrMs = m_vrMs.GetValue();
1707  auto it = m_rxonBuffer.find(m_vrMs.GetValue());
1708  while (it != m_rxonBuffer.end() && it->second.m_pduComplete)
1709  {
1710  m_vrMs++;
1711  it = m_rxonBuffer.find(m_vrMs.GetValue());
1712 
1713  NS_ASSERT_MSG(firstVrMs != m_vrMs.GetValue(), "Infinite loop in ExpireReorderingTimer");
1714  }
1715  NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
1716 
1717  if (m_vrH > m_vrMs)
1718  {
1719  NS_LOG_LOGIC("Start reordering timer");
1722  m_vrX = m_vrH;
1723  NS_LOG_LOGIC("New VR(MS) = " << m_vrMs);
1724  }
1725 
1726  // Section 5.2.3 Status Reporting:
1727  // - The receiving side of an AM RLC entity shall trigger a
1728  // STATUS report when T_reordering expires.
1729  m_statusPduRequested = true;
1730 }
1731 
1732 void
1734 {
1735  NS_LOG_FUNCTION(this);
1736  NS_LOG_LOGIC("PollRetransmit Timer has expired");
1737 
1738  NS_LOG_LOGIC("txonBufferSize = " << m_txonBufferSize);
1739  NS_LOG_LOGIC("retxBufferSize = " << m_retxBufferSize);
1740  NS_LOG_LOGIC("txedBufferSize = " << m_txedBufferSize);
1741  NS_LOG_LOGIC("statusPduRequested = " << m_statusPduRequested);
1742 
1744 
1745  // see section 5.2.2.3
1746  // note the difference between Rel 8 and Rel 11 specs; we follow Rel 11 here
1747  NS_ASSERT(m_vtS <= m_vtMs);
1748  if ((m_txonBufferSize == 0 && m_retxBufferSize == 0) || (m_vtS == m_vtMs))
1749  {
1750  NS_LOG_INFO("txonBuffer and retxBuffer empty. Move PDUs up to = " << m_vtS.GetValue() - 1
1751  << " to retxBuffer");
1752  for (SequenceNumber10 sn = m_vtA; sn < m_vtS; sn++)
1753  {
1754  bool pduAvailable = (bool)m_txedBuffer.at(sn.GetValue()).m_pdu;
1755 
1756  if (pduAvailable)
1757  {
1758  uint16_t snValue = sn.GetValue();
1759  NS_LOG_INFO("Move PDU " << sn << " from txedBuffer to retxBuffer");
1760  m_retxBuffer.at(snValue).m_pdu = m_txedBuffer.at(snValue).m_pdu->Copy();
1761  m_retxBuffer.at(snValue).m_retxCount = m_txedBuffer.at(snValue).m_retxCount;
1762  m_retxBuffer.at(snValue).m_waitingSince = m_txedBuffer.at(snValue).m_waitingSince;
1763  m_retxBufferSize += m_retxBuffer.at(snValue).m_pdu->GetSize();
1764 
1765  m_txedBufferSize -= m_txedBuffer.at(snValue).m_pdu->GetSize();
1766  m_txedBuffer.at(snValue).m_pdu = nullptr;
1767  m_txedBuffer.at(snValue).m_retxCount = 0;
1768  m_txedBuffer.at(snValue).m_waitingSince = MilliSeconds(0);
1769  }
1770  }
1771  }
1772 
1774 }
1775 
1776 void
1778 {
1779  NS_LOG_FUNCTION(this);
1780 }
1781 
1782 void
1784 {
1785  NS_LOG_LOGIC("RBS Timer expires");
1786 
1788  {
1791  }
1792 }
1793 
1794 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:41
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:1777
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:1161
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:781
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:1691
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:787
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:1783
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:1621
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver.
Definition: lte-rlc-am.cc:1183
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:1733
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.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:967
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:861
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:943
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:960
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:915
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:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
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:418
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:408
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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
#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:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
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:115