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 
123  ;
124  return tid;
125 }
126 
127 void
129 {
130  NS_LOG_FUNCTION (this);
134  m_rbsTimer.Cancel ();
135 
136  m_txonBuffer.clear ();
137  m_txonBufferSize = 0;
138  m_txedBuffer.clear ();
139  m_txedBufferSize = 0;
140  m_retxBuffer.clear ();
141  m_retxBufferSize = 0;
142  m_rxonBuffer.clear ();
143  m_sdusBuffer.clear ();
144  m_keepS0 = 0;
145  m_controlPduBuffer = 0;
146 
148 }
149 
150 
155 void
157 {
158  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
159 
161  Time now = Simulator::Now ();
162  RlcTag timeTag (now);
163  p->AddPacketTag (timeTag);
164 
167  LteRlcSduStatusTag tag;
169  p->AddPacketTag (tag);
170 
171  NS_LOG_LOGIC ("Txon Buffer: New packet added");
172  m_txonBuffer.push_back (p);
173  m_txonBufferSize += p->GetSize ();
174  NS_LOG_LOGIC ("NumOfBuffers = " << m_txonBuffer.size() );
175  NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
176 
179  m_rbsTimer.Cancel ();
181 }
182 
183 
188 void
189 LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer, uint8_t harqId, uint8_t componentCarrierId, uint16_t rnti, uint8_t lcid)
190 {
191  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << bytes);
192 
193  if (bytes < 4)
194  {
195  // Stingy MAC: In general, we need more bytes.
196  // There are a more restrictive test for each particular case
197  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small");
198  NS_ASSERT_MSG (false, "TxOpportunity (size = " << bytes << ") too small.\n"
199  << "Your MAC scheduler is assigned too few resource blocks.");
200  return;
201  }
202 
204  {
205  if (bytes < m_statusPduBufferSize)
206  {
207  // Stingy MAC: We need more bytes for the STATUS PDU
208  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small for the STATUS PDU (size = " << m_statusPduBufferSize << ")");
209  NS_ASSERT_MSG (false, "TxOpportunity (size = " << bytes << ") too small for the STATUS PDU (size = " << m_statusPduBufferSize << ")\n"
210  << "Your MAC scheduler is assigned too few resource blocks.");
211  return;
212  }
213 
214  NS_LOG_LOGIC ("Sending STATUS PDU");
215 
216  Ptr<Packet> packet = Create<Packet> ();
217  LteRlcAmHeader rlcAmHeader;
219 
220  NS_LOG_LOGIC ("Check for SNs to NACK from " << m_vrR.GetValue() << " to " << m_vrMs.GetValue());
221  SequenceNumber10 sn;
222  sn.SetModulusBase (m_vrR);
223  std::map<uint16_t, PduBuffer>::iterator pduIt;
224  for (sn = m_vrR; sn < m_vrMs; sn++)
225  {
226  NS_LOG_LOGIC ("SN = " << sn);
227  if (!rlcAmHeader.OneMoreNackWouldFitIn (bytes))
228  {
229  NS_LOG_LOGIC ("Can't fit more NACKs in STATUS PDU");
230  break;
231  }
232  pduIt = m_rxonBuffer.find (sn.GetValue ());
233  if (pduIt == m_rxonBuffer.end () || (!(pduIt->second.m_pduComplete)))
234  {
235  NS_LOG_LOGIC ("adding NACK_SN " << sn.GetValue ());
236  rlcAmHeader.PushNack (sn.GetValue ());
237  }
238  }
239  NS_LOG_LOGIC ("SN at end of NACK loop = " << sn);
240  // 3GPP TS 36.322 section 6.2.2.1.4 ACK SN
241  // find the SN of the next not received RLC Data PDU
242  // which is not reported as missing in the STATUS PDU.
243  pduIt = m_rxonBuffer.find (sn.GetValue ());
244  while ((sn < m_vrMs) && (pduIt != m_rxonBuffer.end ()) && (pduIt->second.m_pduComplete))
245  {
246  NS_LOG_LOGIC ("SN = " << sn << " < " << m_vrMs << " = " << (sn < m_vrMs));
247  sn++;
248  NS_LOG_LOGIC ("SN = " << sn);
249  pduIt = m_rxonBuffer.find (sn.GetValue ());
250  }
251 
252  NS_ASSERT_MSG (sn <= m_vrMs, "first SN not reported as missing = " << sn << ", VR(MS) = " << m_vrMs);
253  rlcAmHeader.SetAckSn (sn);
254 
255 
256  NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
257  packet->AddHeader (rlcAmHeader);
258 
259  // Sender timestamp
260  RlcTag rlcTag (Simulator::Now ());
261  NS_ASSERT_MSG (!packet->PeekPacketTag (rlcTag), "RlcTag is already present");
262  packet->AddPacketTag (rlcTag);
263  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
264 
265  // Send RLC PDU to MAC layer
267  params.pdu = packet;
268  params.rnti = m_rnti;
269  params.lcid = m_lcid;
270  params.layer = layer;
271  params.harqProcessId = harqId;
272  params.componentCarrierId = componentCarrierId;
273 
274  m_macSapProvider->TransmitPdu (params);
275 
276  m_statusPduRequested = false;
280  return;
281  }
282  else if ( m_retxBufferSize > 0 )
283  {
284  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
285  NS_LOG_LOGIC ("Sending data from Retransmission Buffer");
286  NS_ASSERT (m_vtA < m_vtS);
287  SequenceNumber10 sn;
288  sn.SetModulusBase (m_vtA);
289  for (sn = m_vtA; sn < m_vtS; sn++)
290  {
291  uint16_t seqNumberValue = sn.GetValue ();
292  NS_LOG_LOGIC ("SN = " << seqNumberValue << " m_pdu " << m_retxBuffer.at (seqNumberValue).m_pdu);
293 
294  if (m_retxBuffer.at (seqNumberValue).m_pdu != 0)
295  {
296 
297  Ptr<Packet> packet = m_retxBuffer.at (seqNumberValue).m_pdu->Copy ();
298 
299  if (( packet->GetSize () <= bytes )
301  {
302  // According to 5.2.1, the data field is left as is, but we rebuild the header
303  LteRlcAmHeader rlcAmHeader;
304  packet->RemoveHeader (rlcAmHeader);
305  NS_LOG_LOGIC ("old AM RLC header: " << rlcAmHeader);
306 
307  // Calculate the Polling Bit (5.2.2.1)
309 
310  NS_LOG_LOGIC ("polling conditions: m_txonBuffer.empty=" << m_txonBuffer.empty ()
311  << " retxBufferSize=" << m_retxBufferSize
312  << " packet->GetSize ()=" << packet->GetSize ());
313  if (((m_txonBuffer.empty ()) && (m_retxBufferSize == packet->GetSize () + rlcAmHeader.GetSerializedSize ()))
314  || (m_vtS >= m_vtMs)
316  {
319  m_pduWithoutPoll = 0;
320  m_byteWithoutPoll = 0;
321 
322  m_pollSn = m_vtS - 1;
323  NS_LOG_LOGIC ("New POLL_SN = " << m_pollSn);
324 
326  {
327  NS_LOG_LOGIC ("Start PollRetransmit timer");
328 
331  }
332  else
333  {
334  NS_LOG_LOGIC ("Restart PollRetransmit timer");
335 
339  }
340  }
341 
342  packet->AddHeader (rlcAmHeader);
343  NS_LOG_LOGIC ("new AM RLC header: " << rlcAmHeader);
344 
345  // Sender timestamp
346  RlcTag rlcTag (Simulator::Now ());
347  NS_ASSERT_MSG (packet->PeekPacketTag (rlcTag), "RlcTag is missing");
348  packet->ReplacePacketTag (rlcTag);
349  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
350 
351  // Send RLC PDU to MAC layer
353  params.pdu = packet;
354  params.rnti = m_rnti;
355  params.lcid = m_lcid;
356  params.layer = layer;
357  params.harqProcessId = harqId;
358  params.componentCarrierId = componentCarrierId;
359 
360  m_macSapProvider->TransmitPdu (params);
361 
362  m_retxBuffer.at (seqNumberValue).m_retxCount++;
363  NS_LOG_INFO ("Incr RETX_COUNT for SN = " << seqNumberValue);
364  if (m_retxBuffer.at (seqNumberValue).m_retxCount >= m_maxRetxThreshold)
365  {
366  NS_LOG_INFO ("Max RETX_COUNT for SN = " << seqNumberValue);
367  }
368 
369  NS_LOG_INFO ("Move SN = " << seqNumberValue << " back to txedBuffer");
370  m_txedBuffer.at (seqNumberValue).m_pdu = m_retxBuffer.at (seqNumberValue).m_pdu->Copy ();
371  m_txedBuffer.at (seqNumberValue).m_retxCount = m_retxBuffer.at (seqNumberValue).m_retxCount;
372  m_txedBufferSize += m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
373 
374  m_retxBufferSize -= m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
375  m_retxBuffer.at (seqNumberValue).m_pdu = 0;
376  m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
377 
378  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
379 
380  return;
381  }
382  else
383  {
384  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small for retransmission of the packet (size = " << packet->GetSize () << ")");
385  NS_LOG_LOGIC ("Waiting for bigger TxOpportunity");
386  return;
387  }
388  }
389  }
390  NS_ASSERT_MSG (false, "m_retxBufferSize > 0, but no PDU considered for retx found");
391  }
392  else if ( m_txonBufferSize > 0 )
393  {
394  if (bytes < 7)
395  {
396  // Stingy MAC: We need more bytes for new DATA PDUs.
397  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small for DATA PDU");
398  NS_ASSERT_MSG (false, "TxOpportunity (size = " << bytes << ") too small for DATA PDU\n"
399  << "Your MAC scheduler is assigned too few resource blocks.");
400  return;
401  }
402 
403  NS_ASSERT (m_vtS <= m_vtMs);
404  if (m_vtS == m_vtMs)
405  {
406  NS_LOG_INFO ("cannot transmit new RLC PDU due to window stalling");
407  return;
408  }
409 
410  NS_LOG_LOGIC ("Sending data from Transmission Buffer");
411  }
412  else
413  {
414  NS_LOG_LOGIC ("No data pending");
415  return;
416  }
417 
418  //
419  //
420  // Build new PDU
421  //
422  //
423 
424  Ptr<Packet> packet = Create<Packet> ();
425  LteRlcAmHeader rlcAmHeader;
426  rlcAmHeader.SetDataPdu ();
427 
428  // Build Data field
429  uint32_t nextSegmentSize = bytes - 4;
430  uint32_t nextSegmentId = 1;
431  uint32_t dataFieldTotalSize = 0;
432  uint32_t dataFieldAddedSize = 0;
433  std::vector < Ptr<Packet> > dataField;
434 
435  // Remove the first packet from the transmission buffer.
436  // If only a segment of the packet is taken, then the remaining is given back later
437  if ( m_txonBuffer.size () == 0 )
438  {
439  NS_LOG_LOGIC ("No data pending");
440  return;
441  }
442 
443  NS_LOG_LOGIC ("SDUs in TxonBuffer = " << m_txonBuffer.size ());
444  NS_LOG_LOGIC ("First SDU buffer = " << *(m_txonBuffer.begin()));
445  NS_LOG_LOGIC ("First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
446  NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
447  NS_LOG_LOGIC ("Remove SDU from TxBuffer");
448  Ptr<Packet> firstSegment = (*(m_txonBuffer.begin ()))->Copy ();
449  m_txonBufferSize -= (*(m_txonBuffer.begin()))->GetSize ();
450  NS_LOG_LOGIC ("txBufferSize = " << m_txonBufferSize );
451  m_txonBuffer.erase (m_txonBuffer.begin ());
452 
453  while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
454  {
455  NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
456  NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
457  NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
458  if ( (firstSegment->GetSize () > nextSegmentSize) ||
459  // Segment larger than 2047 octets can only be mapped to the end of the Data field
460  (firstSegment->GetSize () > 2047)
461  )
462  {
463  // Take the minimum size, due to the 2047-bytes 3GPP exception
464  // This exception is due to the length of the LI field (just 11 bits)
465  uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
466 
467  NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
468  NS_LOG_LOGIC (" firstSegment > 2047 )");
469 
470  // Segment txBuffer.FirstBuffer and
471  // Give back the remaining segment to the transmission buffer
472  Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
473  NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
474 
475  // Status tag of the new and remaining segments
476  // Note: This is the only place where a PDU is segmented and
477  // therefore its status can change
478  LteRlcSduStatusTag oldTag, newTag;
479  firstSegment->RemovePacketTag (oldTag);
480  newSegment->RemovePacketTag (newTag);
481  if (oldTag.GetStatus () == LteRlcSduStatusTag::FULL_SDU)
482  {
483  newTag.SetStatus (LteRlcSduStatusTag::FIRST_SEGMENT);
484  oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
485  }
486  else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT)
487  {
488  newTag.SetStatus (LteRlcSduStatusTag::MIDDLE_SEGMENT);
489  //oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
490  }
491 
492  // Give back the remaining segment to the transmission buffer
493  firstSegment->RemoveAtStart (currSegmentSize);
494  NS_LOG_LOGIC (" firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize ());
495  if (firstSegment->GetSize () > 0)
496  {
497  firstSegment->AddPacketTag (oldTag);
498 
499  m_txonBuffer.insert (m_txonBuffer.begin (), firstSegment);
500  m_txonBufferSize += (*(m_txonBuffer.begin()))->GetSize ();
501 
502  NS_LOG_LOGIC (" Txon buffer: Give back the remaining segment");
503  NS_LOG_LOGIC (" Txon buffers = " << m_txonBuffer.size ());
504  NS_LOG_LOGIC (" Front buffer size = " << (*(m_txonBuffer.begin()))->GetSize ());
505  NS_LOG_LOGIC (" txonBufferSize = " << m_txonBufferSize );
506  }
507  else
508  {
509  // Whole segment was taken, so adjust tag
510  if (newTag.GetStatus () == LteRlcSduStatusTag::FIRST_SEGMENT)
511  {
512  newTag.SetStatus (LteRlcSduStatusTag::FULL_SDU);
513  }
514  else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
515  {
516  newTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
517  }
518  }
519  // Segment is completely taken or
520  // the remaining segment is given back to the transmission buffer
521  firstSegment = 0;
522 
523  // Put status tag once it has been adjusted
524  newSegment->AddPacketTag (newTag);
525 
526  // Add Segment to Data field
527  dataFieldAddedSize = newSegment->GetSize ();
528  dataFieldTotalSize += dataFieldAddedSize;
529  dataField.push_back (newSegment);
530  newSegment = 0;
531 
532  // ExtensionBit (Next_Segment - 1) = 0
533  rlcAmHeader.PushExtensionBit (LteRlcAmHeader::DATA_FIELD_FOLLOWS);
534 
535  // no LengthIndicator for the last one
536 
537  nextSegmentSize -= dataFieldAddedSize;
538  nextSegmentId++;
539 
540  // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
541 
542  // (NO more segments) ? exit
543  // break;
544  }
545  else if ( (nextSegmentSize - firstSegment->GetSize () <= 2) || (m_txonBuffer.size () == 0) )
546  {
547  NS_LOG_LOGIC (" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txonBuffer.size == 0");
548 
549  // Add txBuffer.FirstBuffer to DataField
550  dataFieldAddedSize = firstSegment->GetSize ();
551  dataFieldTotalSize += dataFieldAddedSize;
552  dataField.push_back (firstSegment);
553  firstSegment = 0;
554 
555  // ExtensionBit (Next_Segment - 1) = 0
556  rlcAmHeader.PushExtensionBit (LteRlcAmHeader::DATA_FIELD_FOLLOWS);
557 
558  // no LengthIndicator for the last one
559 
560  nextSegmentSize -= dataFieldAddedSize;
561  nextSegmentId++;
562 
563  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ());
564  if (m_txonBuffer.size () > 0)
565  {
566  NS_LOG_LOGIC (" First SDU buffer = " << *(m_txonBuffer.begin()));
567  NS_LOG_LOGIC (" First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
568  }
569  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
570 
571  // nextSegmentSize <= 2 (only if txBuffer is not empty)
572 
573  // (NO more segments) ? exit
574  // break;
575  }
576  else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
577  {
578  NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txonBuffer.size > 0");
579  // Add txBuffer.FirstBuffer to DataField
580  dataFieldAddedSize = firstSegment->GetSize ();
581  dataFieldTotalSize += dataFieldAddedSize;
582  dataField.push_back (firstSegment);
583 
584  // ExtensionBit (Next_Segment - 1) = 1
585  rlcAmHeader.PushExtensionBit (LteRlcAmHeader::E_LI_FIELDS_FOLLOWS);
586 
587  // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
588  rlcAmHeader.PushLengthIndicator (firstSegment->GetSize ());
589 
590  nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
591  nextSegmentId++;
592 
593  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ());
594  if (m_txonBuffer.size () > 0)
595  {
596  NS_LOG_LOGIC (" First SDU buffer = " << *(m_txonBuffer.begin()));
597  NS_LOG_LOGIC (" First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
598  }
599  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
600  NS_LOG_LOGIC (" Remove SDU from TxBuffer");
601 
602  // (more segments)
603  firstSegment = (*(m_txonBuffer.begin ()))->Copy ();
604  m_txonBufferSize -= (*(m_txonBuffer.begin()))->GetSize ();
605  m_txonBuffer.erase (m_txonBuffer.begin ());
606  NS_LOG_LOGIC (" txBufferSize = " << m_txonBufferSize );
607  }
608 
609  }
610 
611  //
612  // Build RLC header
613  //
614 
615  rlcAmHeader.SetSequenceNumber ( m_vtS++ );
616  rlcAmHeader.SetResegmentationFlag (LteRlcAmHeader::PDU);
617  rlcAmHeader.SetLastSegmentFlag (LteRlcAmHeader::LAST_PDU_SEGMENT);
618  rlcAmHeader.SetSegmentOffset (0);
619 
620  NS_ASSERT_MSG(rlcAmHeader.GetSequenceNumber () < m_vtMs, "SN above TX window");
621  NS_ASSERT_MSG(rlcAmHeader.GetSequenceNumber () >= m_vtA, "SN below TX window");
622 
623  // Calculate FramingInfo flag according the status of the SDUs in the DataField
624  uint8_t framingInfo = 0;
625  std::vector< Ptr<Packet> >::iterator it;
626  it = dataField.begin ();
627 
628  // FIRST SEGMENT
629  LteRlcSduStatusTag tag;
630  NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
631  (*it)->PeekPacketTag (tag);
632  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
634  )
635  {
636  framingInfo |= LteRlcAmHeader::FIRST_BYTE;
637  }
638  else
639  {
640  framingInfo |= LteRlcAmHeader::NO_FIRST_BYTE;
641  }
642 
643  // Add all SDUs (in DataField) to the Packet
644  while (it < dataField.end ())
645  {
646  NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ());
647 
648  NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
649  (*it)->RemovePacketTag (tag);
650  if (packet->GetSize () > 0)
651  {
652  packet->AddAtEnd (*it);
653  }
654  else
655  {
656  packet = (*it);
657  }
658  it++;
659  }
660 
661  // LAST SEGMENT (Note: There could be only one and be the first one)
662  it--;
663  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
665  {
666  framingInfo |= LteRlcAmHeader::LAST_BYTE;
667  }
668  else
669  {
670  framingInfo |= LteRlcAmHeader::NO_LAST_BYTE;
671  }
672 
673  // Set the FramingInfo flag after the calculation
674  rlcAmHeader.SetFramingInfo (framingInfo);
675 
676 
677  // Calculate the Polling Bit (5.2.2.1)
678  rlcAmHeader.SetPollingBit (LteRlcAmHeader::STATUS_REPORT_NOT_REQUESTED);
679 
681  NS_LOG_LOGIC ("PDU_WITHOUT_POLL = " << m_pduWithoutPoll);
682  m_byteWithoutPoll += packet->GetSize ();
683  NS_LOG_LOGIC ("BYTE_WITHOUT_POLL = " << m_byteWithoutPoll);
684 
686  ( (m_txonBuffer.empty ()) && (m_retxBufferSize == 0) ) ||
687  (m_vtS >= m_vtMs)
689  )
690  {
692  rlcAmHeader.SetPollingBit (LteRlcAmHeader::STATUS_REPORT_IS_REQUESTED);
693  m_pduWithoutPoll = 0;
694  m_byteWithoutPoll = 0;
695 
696  m_pollSn = m_vtS - 1;
697  NS_LOG_LOGIC ("New POLL_SN = " << m_pollSn);
698 
700  {
701  NS_LOG_LOGIC ("Start PollRetransmit timer");
702 
705  }
706  else
707  {
708  NS_LOG_LOGIC ("Restart PollRetransmit timer");
709 
713  }
714  }
715 
716 
717  // Build RLC PDU with DataField and Header
718  NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
719  packet->AddHeader (rlcAmHeader);
720 
721  // Store new PDU into the Transmitted PDU Buffer
722  NS_LOG_LOGIC ("Put transmitted PDU in the txedBuffer");
723  m_txedBufferSize += packet->GetSize ();
724  m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_pdu = packet->Copy ();
725  m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ).m_retxCount = 0;
726 
727  // Sender timestamp
728  RlcTag rlcTag (Simulator::Now ());
729  packet->ReplacePacketTag (rlcTag);
730  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
731 
732  // Send RLC PDU to MAC layer
734  params.pdu = packet;
735  params.rnti = m_rnti;
736  params.lcid = m_lcid;
737  params.layer = layer;
738  params.harqProcessId = harqId;
739  params.componentCarrierId = componentCarrierId;
740 
741  m_macSapProvider->TransmitPdu (params);
742 }
743 
744 void
746 {
747  NS_LOG_FUNCTION (this);
748 }
749 
750 
751 void
752 LteRlcAm::DoReceivePdu (Ptr<Packet> p, uint16_t rnti, uint8_t lcid)
753 {
754  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
755 
756  // Receiver timestamp
757  RlcTag rlcTag;
758  Time delay;
759  NS_ASSERT_MSG (p->PeekPacketTag (rlcTag), "RlcTag is missing");
760  p->RemovePacketTag (rlcTag);
761  delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
762  m_rxPdu (m_rnti, m_lcid, p->GetSize (), delay.GetNanoSeconds ());
763 
764  // Get RLC header parameters
765  LteRlcAmHeader rlcAmHeader;
766  p->PeekHeader (rlcAmHeader);
767  NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
768 
769  if ( rlcAmHeader.IsDataPdu () )
770  {
771 
772  // 5.1.3.1 Transmit operations
773 
774  // 5.1.3.1.1 General
775  //
776  // The transmitting side of an AM RLC entity shall prioritize transmission of RLC control PDUs
777  // over RLC data PDUs. The transmitting side of an AM RLC entity shall prioritize retransmission
778  // of RLC data PDUs over transmission of new AMD PDUs.
779  //
780  // The transmitting side of an AM RLC entity shall maintain a transmitting window according to
781  // state variables VT(A) and VT(MS) as follows:
782  // - a SN falls within the transmitting window if VT(A) <= SN < VT(MS);
783  // - a SN falls outside of the transmitting window otherwise.
784  //
785  // The transmitting side of an AM RLC entity shall not deliver to lower layer any RLC data PDU
786  // whose SN falls outside of the transmitting window.
787  //
788  // When delivering a new AMD PDU to lower layer, the transmitting side of an AM RLC entity shall:
789  // - set the SN of the AMD PDU to VT(S), and then increment VT(S) by one.
790  //
791  // The transmitting side of an AM RLC entity can receive a positive acknowledgement (confirmation
792  // of successful reception by its peer AM RLC entity) for a RLC data PDU by the following:
793  // - STATUS PDU from its peer AM RLC entity.
794  //
795  // When receiving a positive acknowledgement for an AMD PDU with SN = VT(A), the transmitting
796  // side of an AM RLC entity shall:
797  // - set VT(A) equal to the SN of the AMD PDU with the smallest SN, whose SN falls within the
798  // range VT(A) <= SN <= VT(S) and for which a positive acknowledgment has not been received yet.
799  // - if positive acknowledgements have been received for all AMD PDUs associated with
800  // a transmitted RLC SDU:
801  // - send an indication to the upper layers of successful delivery of the RLC SDU.
802 
803 
804  // 5.1.3.2 Receive operations
805  //
806  // 5.1.3.2.1 General
807  //
808  // The receiving side of an AM RLC entity shall maintain a receiving window according to state
809  // variables VR(R) and VR(MR) as follows:
810  // - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
811  // - a SN falls outside of the receiving window otherwise.
812  //
813  // When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity shall:
814  // - either discard the received RLC data PDU or place it in the reception buffer (see sub clause 5.1.3.2.2);
815  // - if the received RLC data PDU was placed in the reception buffer:
816  // - 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).
817  //
818  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
819  // - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
820 
821 
822  SequenceNumber10 seqNumber = rlcAmHeader.GetSequenceNumber ();
823  seqNumber.SetModulusBase (m_vrR);
824 
825  if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::SEGMENT )
826  {
827  NS_LOG_LOGIC ("PDU segment received ( SN = " << seqNumber << " )");
828  }
829  else if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::PDU )
830  {
831  NS_LOG_LOGIC ("PDU received ( SN = " << seqNumber << " )");
832  }
833  else
834  {
835  NS_ASSERT_MSG (false, "Neither a PDU segment nor a PDU received");
836  return ;
837  }
838 
839  // STATUS PDU is requested
840  if ( rlcAmHeader.GetPollingBit () == LteRlcAmHeader::STATUS_REPORT_IS_REQUESTED )
841  {
842  m_statusPduRequested = true;
844 
846  {
848  }
849  }
850 
851  // 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
852  //
853  // When a RLC data PDU is received from lower layer, where the RLC data PDU contains
854  // byte segment numbers y to z of an AMD PDU with SN = x, the receiving side of an AM RLC entity shall:
855  // - if x falls outside of the receiving window; or
856  // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
857  // - discard the received RLC data PDU;
858  // - else:
859  // - place the received RLC data PDU in the reception buffer;
860  // - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
861  // - discard the duplicate byte segments.
862 
863  NS_LOG_LOGIC ("VR(R) = " << m_vrR);
864  NS_LOG_LOGIC ("VR(MR) = " << m_vrMr);
865  NS_LOG_LOGIC ("VR(X) = " << m_vrX);
866  NS_LOG_LOGIC ("VR(MS) = " << m_vrMs);
867  NS_LOG_LOGIC ("VR(H) = " << m_vrH);
868 
869  // - if x falls outside of the receiving window; or
870  // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
871  if ( ! IsInsideReceivingWindow (seqNumber) )
872  {
873  NS_LOG_LOGIC ("PDU discarded");
874  return;
875  }
876  else
877  {
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  // note: re-segmentation of AMD PDU is currently not supported,
881  // so we just check that the segment was not received before
882  std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (seqNumber.GetValue ());
883  if (it != m_rxonBuffer.end () )
884  {
885  NS_ASSERT (it->second.m_byteSegments.size () > 0);
886  NS_ASSERT_MSG (it->second.m_byteSegments.size () == 1, "re-segmentation not supported");
887  NS_LOG_LOGIC ("PDU segment already received, discarded");
888  }
889  else
890  {
891  NS_LOG_LOGIC ("Place PDU in the reception buffer ( SN = " << seqNumber << " )");
892  m_rxonBuffer[ seqNumber.GetValue () ].m_byteSegments.push_back (p);
893  m_rxonBuffer[ seqNumber.GetValue () ].m_pduComplete = true;
894  }
895 
896 
897  }
898 
899  // 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception buffer
900  // When a RLC data PDU with SN = x is placed in the reception buffer,
901  // the receiving side of an AM RLC entity shall:
902 
903  // - if x >= VR(H)
904  // - update VR(H) to x+ 1;
905 
906  if ( seqNumber >= m_vrH )
907  {
908  m_vrH = seqNumber + 1;
909  NS_LOG_LOGIC ("New VR(H) = " << m_vrH);
910  }
911 
912  // - if all byte segments of the AMD PDU with SN = VR(MS) are received:
913  // - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for
914  // which not all byte segments have been received;
915 
916  std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (m_vrMs.GetValue ());
917  if ( it != m_rxonBuffer.end () &&
918  it->second.m_pduComplete )
919  {
920  int firstVrMs = m_vrMs.GetValue ();
921  while ( it != m_rxonBuffer.end () &&
922  it->second.m_pduComplete )
923  {
924  m_vrMs++;
925  it = m_rxonBuffer.find (m_vrMs.GetValue ());
926  NS_LOG_LOGIC ("Incr VR(MS) = " << m_vrMs);
927 
928  NS_ASSERT_MSG (firstVrMs != m_vrMs.GetValue (), "Infinite loop in RxonBuffer");
929  }
930  NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
931  }
932 
933  // - if x = VR(R):
934  // - if all byte segments of the AMD PDU with SN = VR(R) are received:
935  // - 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;
936  // - update VR(MR) to the updated VR(R) + AM_Window_Size;
937  // - 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;
938 
939  if ( seqNumber == m_vrR )
940  {
941  std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (seqNumber.GetValue ());
942  if ( it != m_rxonBuffer.end () &&
943  it->second.m_pduComplete )
944  {
945  it = m_rxonBuffer.find (m_vrR.GetValue ());
946  int firstVrR = m_vrR.GetValue ();
947  while ( it != m_rxonBuffer.end () &&
948  it->second.m_pduComplete )
949  {
950  NS_LOG_LOGIC ("Reassemble and Deliver ( SN = " << m_vrR << " )");
951  NS_ASSERT_MSG (it->second.m_byteSegments.size () == 1,
952  "Too many segments. PDU Reassembly process didn't work");
953  ReassembleAndDeliver (it->second.m_byteSegments.front ());
954  m_rxonBuffer.erase (m_vrR.GetValue ());
955 
956  m_vrR++;
961  it = m_rxonBuffer.find (m_vrR.GetValue ());
962 
963  NS_ASSERT_MSG (firstVrR != m_vrR.GetValue (), "Infinite loop in RxonBuffer");
964  }
965  NS_LOG_LOGIC ("New VR(R) = " << m_vrR);
967 
968  NS_LOG_LOGIC ("New VR(MR) = " << m_vrMr);
969  }
970 
971  }
972 
973  // - if t-Reordering is running:
974  // - if VR(X) = VR(R); or
975  // - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
976  // - stop and reset t-Reordering;
977 
978  if ( m_reorderingTimer.IsRunning () )
979  {
980  NS_LOG_LOGIC ("Reordering timer is running");
981  if ( (m_vrX == m_vrR) ||
982  ( (! IsInsideReceivingWindow (m_vrX)) && (m_vrX != m_vrMr) )
983  )
984  {
986  NS_LOG_LOGIC ("Stop reordering timer");
988  }
989  }
990 
991  // - if t-Reordering is not running (includes the case t-Reordering is stopped due to actions above):
992  // - if VR (H) > VR(R):
993  // - start t-Reordering;
994  // - set VR(X) to VR(H).
995 
996  if ( ! m_reorderingTimer.IsRunning () )
997  {
998  NS_LOG_LOGIC ("Reordering timer is not running");
999  if ( m_vrH > m_vrR )
1000  {
1001  NS_LOG_LOGIC ("Start reordering timer");
1004  m_vrX = m_vrH;
1005  NS_LOG_LOGIC ("New VR(X) = " << m_vrX);
1006  }
1007  }
1008  }
1009  else if ( rlcAmHeader.IsControlPdu () )
1010  {
1011  NS_LOG_INFO ("Control AM RLC PDU");
1012 
1013  SequenceNumber10 ackSn = rlcAmHeader.GetAckSn ();
1014  SequenceNumber10 sn;
1015 
1016  NS_LOG_INFO ("ackSn = " << ackSn);
1017  NS_LOG_INFO ("VT(A) = " << m_vtA);
1018  NS_LOG_INFO ("VT(S) = " << m_vtS);
1019  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1020  NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1021 
1025  ackSn.SetModulusBase (m_vtA);
1026  sn.SetModulusBase (m_vtA);
1027 
1028  bool incrementVtA = true;
1029 
1030  for (sn = m_vtA; sn < ackSn && sn < m_vtS; sn++)
1031  {
1032  NS_LOG_LOGIC ("sn = " << sn);
1033 
1034  uint16_t seqNumberValue = sn.GetValue ();
1035 
1037  && (seqNumberValue == m_pollSn.GetValue ()))
1038  {
1040  }
1041 
1042  if (rlcAmHeader.IsNackPresent (sn))
1043  {
1044  NS_LOG_LOGIC ("sn " << sn << " is NACKed");
1045 
1046  incrementVtA = false;
1047 
1048  if (m_txedBuffer.at (seqNumberValue).m_pdu != 0)
1049  {
1050  NS_LOG_INFO ("Move SN = " << seqNumberValue << " to retxBuffer");
1051  m_retxBuffer.at (seqNumberValue).m_pdu = m_txedBuffer.at (seqNumberValue).m_pdu->Copy ();
1052  m_retxBuffer.at (seqNumberValue).m_retxCount = m_txedBuffer.at (seqNumberValue).m_retxCount;
1053  m_retxBufferSize += m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
1054 
1055  m_txedBufferSize -= m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
1056  m_txedBuffer.at (seqNumberValue).m_pdu = 0;
1057  m_txedBuffer.at (seqNumberValue).m_retxCount = 0;
1058  }
1059 
1060  NS_ASSERT (m_retxBuffer.at (seqNumberValue).m_pdu != 0);
1061 
1062  }
1063  else
1064  {
1065  NS_LOG_LOGIC ("sn " << sn << " is ACKed");
1066 
1067  if (m_txedBuffer.at (seqNumberValue).m_pdu)
1068  {
1069  NS_LOG_INFO ("ACKed SN = " << seqNumberValue << " from txedBuffer");
1070  // NS_LOG_INFO ("m_txedBuffer( " << m_vtA << " )->GetSize = " << m_txedBuffer.at (m_vtA.GetValue ())->GetSize ());
1071  m_txedBufferSize -= m_txedBuffer.at (seqNumberValue).m_pdu->GetSize ();
1072  m_txedBuffer.at (seqNumberValue).m_pdu = 0;
1073  NS_ASSERT (m_retxBuffer.at (seqNumberValue).m_pdu == 0);
1074  }
1075 
1076  if (m_retxBuffer.at (seqNumberValue).m_pdu)
1077  {
1078  NS_LOG_INFO ("ACKed SN = " << seqNumberValue << " from retxBuffer");
1079  m_retxBufferSize -= m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
1080  m_retxBuffer.at (seqNumberValue).m_pdu = 0;
1081  m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
1082  }
1083 
1084  }
1085 
1086  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1087  NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1088 
1089  if (incrementVtA)
1090  {
1091  m_vtA++;
1093  NS_LOG_INFO ("New VT(A) = " << m_vtA);
1096  m_vtS.SetModulusBase (m_vtA);
1097  ackSn.SetModulusBase (m_vtA);
1098  sn.SetModulusBase (m_vtA);
1099  }
1100 
1101  } // loop over SN : VT(A) <= SN < ACK SN
1102 
1103  return;
1104 
1105  }
1106  else
1107  {
1108  NS_LOG_WARN ("Wrong AM RLC PDU type");
1109  return;
1110  }
1111 
1112 }
1113 
1114 
1115 bool
1117 {
1118  NS_LOG_FUNCTION (this << seqNumber);
1119  NS_LOG_LOGIC ("Receiving Window: " <<
1120  m_vrR << " <= " << seqNumber << " <= " << m_vrMr);
1121 
1124  seqNumber.SetModulusBase (m_vrR);
1125 
1126  if ( (m_vrR <= seqNumber) && (seqNumber < m_vrMr ) )
1127  {
1128  NS_LOG_LOGIC (seqNumber << " is INSIDE the receiving window");
1129  return true;
1130  }
1131  else
1132  {
1133  NS_LOG_LOGIC (seqNumber << " is OUTSIDE the receiving window");
1134  return false;
1135  }
1136 }
1137 
1138 
1139 void
1141 {
1142  LteRlcAmHeader rlcAmHeader;
1143  packet->RemoveHeader (rlcAmHeader);
1144  uint8_t framingInfo = rlcAmHeader.GetFramingInfo ();
1145  SequenceNumber10 currSeqNumber = rlcAmHeader.GetSequenceNumber ();
1146  bool expectedSnLost;
1147 
1148  if ( currSeqNumber != m_expectedSeqNumber )
1149  {
1150  expectedSnLost = true;
1151  NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
1152  m_expectedSeqNumber = currSeqNumber + 1;
1153  }
1154  else
1155  {
1156  expectedSnLost = false;
1157  NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
1159  }
1160 
1161  // Build list of SDUs
1162  uint8_t extensionBit;
1163  uint16_t lengthIndicator;
1164  do
1165  {
1166  extensionBit = rlcAmHeader.PopExtensionBit ();
1167  NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit);
1168 
1169  if ( extensionBit == 0 )
1170  {
1171  m_sdusBuffer.push_back (packet);
1172  }
1173  else // extensionBit == 1
1174  {
1175  lengthIndicator = rlcAmHeader.PopLengthIndicator ();
1176  NS_LOG_LOGIC ("LI = " << lengthIndicator);
1177 
1178  // Check if there is enough data in the packet
1179  if ( lengthIndicator >= packet->GetSize () )
1180  {
1181  NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator);
1183  }
1184 
1185  // Split packet in two fragments
1186  Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator);
1187  packet->RemoveAtStart (lengthIndicator);
1188 
1189  m_sdusBuffer.push_back (data_field);
1190  }
1191  }
1192  while ( extensionBit == 1 );
1193 
1194  std::list < Ptr<Packet> >::iterator it;
1195 
1196  // Current reassembling state
1197  if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'");
1198  else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'");
1199  else NS_LOG_LOGIC ("Reassembling State = Unknown state");
1200 
1201  // Received framing Info
1202  NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
1203  NS_LOG_LOGIC ("m_sdusBuffer = " << m_sdusBuffer.size ());
1204 
1205  // Reassemble the list of SDUs (when there is no losses)
1206  if (!expectedSnLost)
1207  {
1208  switch (m_reassemblingState)
1209  {
1210  case WAITING_S0_FULL:
1211  switch (framingInfo)
1212  {
1215 
1219  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
1220  {
1222  }
1223  m_sdusBuffer.clear ();
1224  break;
1225 
1228 
1232  while ( m_sdusBuffer.size () > 1 )
1233  {
1235  m_sdusBuffer.pop_front ();
1236  }
1237 
1241  m_keepS0 = m_sdusBuffer.front ();
1242  m_sdusBuffer.pop_front ();
1243  break;
1244 
1247  default:
1251  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1252  break;
1253  }
1254  break;
1255 
1256  case WAITING_SI_SF:
1257  switch (framingInfo)
1258  {
1261 
1265  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1266  m_sdusBuffer.pop_front ();
1268 
1272  while ( ! m_sdusBuffer.empty () )
1273  {
1275  m_sdusBuffer.pop_front ();
1276  }
1277  break;
1278 
1281 
1285  if ( m_sdusBuffer.size () == 1 )
1286  {
1287  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1288  m_sdusBuffer.pop_front ();
1289  }
1290  else // m_sdusBuffer.size () > 1
1291  {
1295  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1296  m_sdusBuffer.pop_front ();
1298 
1302  while ( m_sdusBuffer.size () > 1 )
1303  {
1305  m_sdusBuffer.pop_front ();
1306  }
1307 
1311  m_keepS0 = m_sdusBuffer.front ();
1312  m_sdusBuffer.pop_front ();
1313  }
1314  break;
1315 
1318  default:
1322  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1323  break;
1324  }
1325  break;
1326 
1327  default:
1328  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1329  break;
1330  }
1331  }
1332  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
1333  {
1334  switch (m_reassemblingState)
1335  {
1336  case WAITING_S0_FULL:
1337  switch (framingInfo)
1338  {
1341 
1345  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
1346  {
1348  }
1349  m_sdusBuffer.clear ();
1350  break;
1351 
1354 
1358  while ( m_sdusBuffer.size () > 1 )
1359  {
1361  m_sdusBuffer.pop_front ();
1362  }
1363 
1367  m_keepS0 = m_sdusBuffer.front ();
1368  m_sdusBuffer.pop_front ();
1369  break;
1370 
1373 
1377  m_sdusBuffer.pop_front ();
1378 
1382  while ( ! m_sdusBuffer.empty () )
1383  {
1385  m_sdusBuffer.pop_front ();
1386  }
1387  break;
1388 
1390  if ( m_sdusBuffer.size () == 1 )
1391  {
1393  }
1394  else
1395  {
1397  }
1398 
1402  m_sdusBuffer.pop_front ();
1403 
1404  if ( m_sdusBuffer.size () > 0 )
1405  {
1409  while ( m_sdusBuffer.size () > 1 )
1410  {
1412  m_sdusBuffer.pop_front ();
1413  }
1414 
1418  m_keepS0 = m_sdusBuffer.front ();
1419  m_sdusBuffer.pop_front ();
1420  }
1421  break;
1422 
1423  default:
1427  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1428  break;
1429  }
1430  break;
1431 
1432  case WAITING_SI_SF:
1433  switch (framingInfo)
1434  {
1437 
1441  m_keepS0 = 0;
1442 
1446  while ( ! m_sdusBuffer.empty () )
1447  {
1449  m_sdusBuffer.pop_front ();
1450  }
1451  break;
1452 
1455 
1459  m_keepS0 = 0;
1460 
1464  while ( m_sdusBuffer.size () > 1 )
1465  {
1467  m_sdusBuffer.pop_front ();
1468  }
1469 
1473  m_keepS0 = m_sdusBuffer.front ();
1474  m_sdusBuffer.pop_front ();
1475 
1476  break;
1477 
1480 
1484  m_keepS0 = 0;
1485 
1489  m_sdusBuffer.pop_front ();
1490 
1494  while ( ! m_sdusBuffer.empty () )
1495  {
1497  m_sdusBuffer.pop_front ();
1498  }
1499  break;
1500 
1502  if ( m_sdusBuffer.size () == 1 )
1503  {
1505  }
1506  else
1507  {
1509  }
1510 
1514  m_keepS0 = 0;
1515 
1519  m_sdusBuffer.pop_front ();
1520 
1521  if ( m_sdusBuffer.size () > 0 )
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 
1540  default:
1544  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1545  break;
1546  }
1547  break;
1548 
1549  default:
1550  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1551  break;
1552  }
1553  }
1554 
1555 }
1556 
1557 void
1559 {
1560  NS_LOG_FUNCTION (this);
1561 
1562  Time now = Simulator::Now ();
1563 
1564  NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
1565  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1566  NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1567  NS_LOG_LOGIC ("VT(A) = " << m_vtA);
1568  NS_LOG_LOGIC ("VT(S) = " << m_vtS);
1569 
1570  // Transmission Queue HOL time
1571  Time txonQueueHolDelay (0);
1572  if ( m_txonBufferSize > 0 )
1573  {
1574  RlcTag txonQueueHolTimeTag;
1575  m_txonBuffer.front ()->PeekPacketTag (txonQueueHolTimeTag);
1576  txonQueueHolDelay = now - txonQueueHolTimeTag.GetSenderTimestamp ();
1577  }
1578 
1579  // Retransmission Queue HOL time
1580  Time retxQueueHolDelay;
1581  RlcTag retxQueueHolTimeTag;
1582  if ( m_retxBufferSize > 0 )
1583  {
1584  if (m_retxBuffer.at (m_vtA.GetValue ()).m_pdu != 0)
1585  {
1586  m_retxBuffer.at (m_vtA.GetValue ()).m_pdu->PeekPacketTag (retxQueueHolTimeTag);
1587  }
1588  else
1589  {
1590  m_txedBuffer.at (m_vtA.GetValue ()).m_pdu->PeekPacketTag (retxQueueHolTimeTag);
1591  }
1592  retxQueueHolDelay = now - retxQueueHolTimeTag.GetSenderTimestamp ();
1593  }
1594  else
1595  {
1596  retxQueueHolDelay = Seconds (0);
1597  }
1598 
1600  r.rnti = m_rnti;
1601  r.lcid = m_lcid;
1603  r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds ();
1605  r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds ();
1606 
1608  {
1610  }
1611  else
1612  {
1613  r.statusPduSize = 0;
1614  }
1615 
1616  if ( r.txQueueSize != 0 || r.retxQueueSize != 0 || r.statusPduSize != 0 )
1617  {
1618  NS_LOG_INFO ("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay << ", "
1619  << r.retxQueueSize << ", " << r.retxQueueHolDelay << ", "
1620  << r.statusPduSize);
1622  }
1623  else
1624  {
1625  NS_LOG_INFO ("ReportBufferStatus don't needed");
1626  }
1627 }
1628 
1629 
1630 void
1632 {
1633  NS_LOG_FUNCTION (this);
1634  NS_LOG_LOGIC ("Reordering Timer has expired");
1635 
1636  // 5.1.3.2.4 Actions when t-Reordering expires
1637  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
1638  // - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte segments
1639  // have been received;
1640  // - if VR(H) > VR(MS):
1641  // - start t-Reordering;
1642  // - set VR(X) to VR(H).
1643 
1644  m_vrMs = m_vrX;
1645  int firstVrMs = m_vrMs.GetValue ();
1646  std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (m_vrMs.GetValue ());
1647  while ( it != m_rxonBuffer.end () &&
1648  it->second.m_pduComplete )
1649  {
1650  m_vrMs++;
1651  it = m_rxonBuffer.find (m_vrMs.GetValue ());
1652 
1653  NS_ASSERT_MSG (firstVrMs != m_vrMs.GetValue (), "Infinite loop in ExpireReorderingTimer");
1654  }
1655  NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
1656 
1657  if ( m_vrH > m_vrMs )
1658  {
1659  NS_LOG_LOGIC ("Start reordering timer");
1662  m_vrX = m_vrH;
1663  NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
1664  }
1665 
1666  // Section 5.2.3 Status Reporting:
1667  // - The receiving side of an AM RLC entity shall trigger a
1668  // STATUS report when T_reordering expires.
1669  m_statusPduRequested = true;
1670 }
1671 
1672 void
1674 {
1675  NS_LOG_FUNCTION (this);
1676  NS_LOG_LOGIC ("PollRetransmit Timer has expired");
1677 
1678  NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
1679  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1680  NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1681  NS_LOG_LOGIC ("statusPduRequested = " << m_statusPduRequested);
1682 
1684 
1685  // see section 5.2.2.3
1686  // note the difference between Rel 8 and Rel 11 specs; we follow Rel 11 here
1687  NS_ASSERT (m_vtS <= m_vtMs);
1688  if ((m_txonBufferSize == 0 && m_retxBufferSize == 0)
1689  || (m_vtS == m_vtMs))
1690  {
1691  NS_LOG_INFO ("txonBuffer and retxBuffer empty. Move PDUs up to = " << m_vtS.GetValue () - 1 << " to retxBuffer");
1692  for (SequenceNumber10 sn = m_vtA; sn < m_vtS; sn++)
1693  {
1694  bool pduAvailable = m_txedBuffer.at (sn.GetValue ()).m_pdu != 0;
1695 
1696  if ( pduAvailable )
1697  {
1698  uint16_t snValue = sn.GetValue ();
1699  NS_LOG_INFO ("Move PDU " << sn << " from txedBuffer to retxBuffer");
1700  m_retxBuffer.at (snValue).m_pdu = m_txedBuffer.at (snValue).m_pdu->Copy ();
1701  m_retxBuffer.at (snValue).m_retxCount = m_txedBuffer.at (snValue).m_retxCount;
1702  m_retxBufferSize += m_retxBuffer.at (snValue).m_pdu->GetSize ();
1703 
1704  m_txedBufferSize -= m_txedBuffer.at (snValue).m_pdu->GetSize ();
1705  m_txedBuffer.at (snValue).m_pdu = 0;
1706  m_txedBuffer.at (snValue).m_retxCount = 0;
1707  }
1708  }
1709  }
1710 
1712 }
1713 
1714 
1715 void
1717 {
1718  NS_LOG_FUNCTION (this);
1719 }
1720 
1721 void
1723 {
1724  NS_LOG_LOGIC ("RBS Timer expires");
1725 
1727  {
1730  }
1731 }
1732 
1733 } // namespace ns3
uint8_t PopExtensionBit(void)
Pop extension bit function.
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:267
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:181
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
EventId m_statusProhibitTimer
status prohibit timer
Definition: lte-rlc-am.h:188
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint32_t m_byteWithoutPoll
byte without poll
Definition: lte-rlc-am.h:174
AttributeValue implementation for Boolean.
Definition: boolean.h:36
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-am.h:190
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
#define min(a, b)
Definition: 80211b.c:44
uint32_t m_statusPduBufferSize
status PDU buffer size
Definition: lte-rlc-am.h:134
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:84
SequenceNumber10 m_vtS
VT(S)
Definition: lte-rlc-am.h:160
virtual void DoReceivePdu(Ptr< Packet > p, uint16_t rnti, uint8_t lcid)
Receive PDU function.
Definition: lte-rlc-am.cc:752
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-am.cc:1558
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:814
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
SequenceNumber10 m_vtMs
VT(MS)
Definition: lte-rlc-am.h:159
#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
Time m_reorderingTimerValue
reordering timer value
Definition: lte-rlc-am.h:187
void SetDataPdu(void)
Set data PDU function.
SequenceNumber10 m_vrMs
VR(MS)
Definition: lte-rlc-am.h:167
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
void SetPollingBit(uint8_t pollingBit)
Set polling bit function.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1001
Time m_pollRetransmitTimerValue
poll retransmit time value
Definition: lte-rlc-am.h:185
SequenceNumber10 m_vrR
VR(R)
Definition: lte-rlc-am.h:164
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:796
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-am.h:186
Time m_rbsTimerValue
RBS timer value.
Definition: lte-rlc-am.h:191
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
Definition: lte-mac-sap.h:73
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:277
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:175
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
bool IsInsideReceivingWindow(SequenceNumber10 seqNumber)
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1116
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:124
uint8_t m_lcid
LCID.
Definition: lte-rlc.h:176
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:69
EventId m_pollRetransmitTimer
Timers.
Definition: lte-rlc-am.h:184
void SetModulusBase(SequenceNumber10 modulusBase)
Set modulus base.
void ExpireRbsTimer(void)
Expire RBS timer.
Definition: lte-rlc-am.cc:1722
Parameters for LteMacSapProvider::ReportBufferStatus.
Definition: lte-mac-sap.h:67
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:446
uint32_t m_txonBufferSize
transmit on buffer size
Definition: lte-rlc-am.h:129
uint16_t txQueueHolDelay
the Head Of Line delay of the transmission queue
Definition: lte-mac-sap.h:72
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 AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:312
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:836
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-am.h:215
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
Definition: lte-rlc.h:144
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:339
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1375
virtual void DoNotifyTxOpportunity(uint32_t bytes, uint8_t layer, uint8_t harqId, uint8_t componentCarrierId, uint16_t rnti, uint8_t lcid)
MAC SAP.
Definition: lte-rlc-am.cc:189
std::map< uint16_t, PduBuffer > m_rxonBuffer
Reception buffer.
Definition: lte-rlc-am.h:145
AttributeValue implementation for Time.
Definition: nstime.h:1055
uint8_t GetFramingInfo() const
Get framing info.
virtual uint32_t GetSerializedSize(void) const
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:828
uint16_t m_pollPdu
poll PDU
Definition: lte-rlc-am.h:197
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...
uint8_t GetStatus(void) const
Get status function.
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-am.h:210
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc.cc:123
SequenceNumber10 m_pollSn
POLL_SN.
Definition: lte-rlc-am.h:161
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:173
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:277
void SetControlPdu(uint8_t controlPduType)
Set control PDU function.
The packet header for the AM Radio Link Control (RLC) protocol packets.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet (PDU)
Definition: lte-rlc-am.h:152
uint16_t m_pollByte
poll byte
Definition: lte-rlc-am.h:198
SequenceNumber10 m_vrH
VR(H)
Definition: lte-rlc-am.h:168
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
bool m_pollRetransmitTimerJustExpired
poll retransmit timer just expired?
Definition: lte-rlc-am.h:201
SequenceNumber10 m_vrMr
VR(MR)
Definition: lte-rlc-am.h:165
Time GetSenderTimestamp(void) const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Definition: lte-rlc-tag.h:65
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:1056
SequenceNumber10 m_vrX
VR(X)
Definition: lte-rlc-am.h:166
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:70
uint32_t m_pduWithoutPoll
Counters.
Definition: lte-rlc-am.h:173
uint32_t txQueueSize
the current size of the RLC transmission queue
Definition: lte-mac-sap.h:71
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:249
uint32_t m_txedBufferSize
transmit ed buffer size
Definition: lte-rlc-am.h:131
Time m_statusProhibitTimerValue
status prohibit timer value
Definition: lte-rlc-am.h:189
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
virtual void DoNotifyHarqDeliveryFailure()
Notify HARQ delivery failure.
Definition: lte-rlc-am.cc:745
uint16_t m_maxRetxThreshold
Configurable parameters.
Definition: lte-rlc-am.h:196
#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:90
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:353
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:75
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc-am.cc:128
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
void ExpireStatusProhibitTimer(void)
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1716
void ExpirePollRetransmitTimer(void)
Expire poll retransmitter.
Definition: lte-rlc-am.cc:1673
SequenceNumber10 m_vtA
State variables.
Definition: lte-rlc-am.h:158
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:821
uint16_t PopLengthIndicator(void)
Pop length indicator function.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:993
std::vector< RetxPdu > m_retxBuffer
Buffer for PDUs considered for retransmission.
Definition: lte-rlc-am.h:127
void SetStatus(uint8_t status)
Set status function.
uint16_t retxQueueHolDelay
the Head Of Line delay of the retransmission queue
Definition: lte-mac-sap.h:74
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
virtual void ReportBufferStatus(ReportBufferStatusParameters params)=0
Report the RLC buffer status to the MAC.
std::vector< Ptr< Packet > > m_txonBuffer
Transmission buffer.
Definition: lte-rlc-am.h:115
SequenceNumber10 class.
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:185
LTE RLC Acknowledged Mode (AM), see 3GPP TS 36.322.
Definition: lte-rlc-am.h:36
Ptr< Packet > m_controlPduBuffer
Control PDU buffer (just one PDU)
Definition: lte-rlc-am.h:147
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver.
Definition: lte-rlc-am.cc:1140
uint16_t m_windowSize
Constants.
Definition: lte-rlc-am.h:179
bool m_txOpportunityForRetxAlwaysBigEnough
transmit opportunity for retransmit?
Definition: lte-rlc-am.h:200
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
ReassemblingState_t m_reassemblingState
reassembling state
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:50
a unique identifier for an interface.
Definition: type-id.h:58
uint32_t m_retxBufferSize
retransmit buffer size
Definition: lte-rlc-am.h:130
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:345
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:914
static TypeId GetTypeId(void)
Get the type ID.
Definition: lte-rlc-am.cc:88
bool m_statusPduRequested
status PDU requested
Definition: lte-rlc-am.h:133
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:1631
virtual void DoTransmitPdcpPdu(Ptr< Packet > p)
RLC SAP.
Definition: lte-rlc-am.cc:156
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
virtual ~LteRlcAm()
Definition: lte-rlc-am.cc:82
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:45