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