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);
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 
1202  // Received framing Info
1203  NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
1204  NS_LOG_LOGIC ("m_sdusBuffer = " << m_sdusBuffer.size ());
1205 
1206  // Reassemble the list of SDUs (when there is no losses)
1207  if (!expectedSnLost)
1208  {
1209  switch (m_reassemblingState)
1210  {
1211  case WAITING_S0_FULL:
1212  switch (framingInfo)
1213  {
1216 
1220  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
1221  {
1223  }
1224  m_sdusBuffer.clear ();
1225  break;
1226 
1229 
1233  while ( m_sdusBuffer.size () > 1 )
1234  {
1236  m_sdusBuffer.pop_front ();
1237  }
1238 
1242  m_keepS0 = m_sdusBuffer.front ();
1243  m_sdusBuffer.pop_front ();
1244  break;
1245 
1248  default:
1252  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1253  break;
1254  }
1255  break;
1256 
1257  case WAITING_SI_SF:
1258  switch (framingInfo)
1259  {
1262 
1266  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1267  m_sdusBuffer.pop_front ();
1269 
1273  while ( ! m_sdusBuffer.empty () )
1274  {
1276  m_sdusBuffer.pop_front ();
1277  }
1278  break;
1279 
1282 
1286  if ( m_sdusBuffer.size () == 1 )
1287  {
1288  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1289  m_sdusBuffer.pop_front ();
1290  }
1291  else // m_sdusBuffer.size () > 1
1292  {
1296  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1297  m_sdusBuffer.pop_front ();
1299 
1303  while ( m_sdusBuffer.size () > 1 )
1304  {
1306  m_sdusBuffer.pop_front ();
1307  }
1308 
1312  m_keepS0 = m_sdusBuffer.front ();
1313  m_sdusBuffer.pop_front ();
1314  }
1315  break;
1316 
1319  default:
1323  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1324  break;
1325  }
1326  break;
1327 
1328  default:
1329  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1330  break;
1331  }
1332  }
1333  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
1334  {
1335  switch (m_reassemblingState)
1336  {
1337  case WAITING_S0_FULL:
1338  switch (framingInfo)
1339  {
1342 
1346  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
1347  {
1349  }
1350  m_sdusBuffer.clear ();
1351  break;
1352 
1355 
1359  while ( m_sdusBuffer.size () > 1 )
1360  {
1362  m_sdusBuffer.pop_front ();
1363  }
1364 
1368  m_keepS0 = m_sdusBuffer.front ();
1369  m_sdusBuffer.pop_front ();
1370  break;
1371 
1374 
1378  m_sdusBuffer.pop_front ();
1379 
1383  while ( ! m_sdusBuffer.empty () )
1384  {
1386  m_sdusBuffer.pop_front ();
1387  }
1388  break;
1389 
1391  if ( m_sdusBuffer.size () == 1 )
1392  {
1394  }
1395  else
1396  {
1398  }
1399 
1403  m_sdusBuffer.pop_front ();
1404 
1405  if ( m_sdusBuffer.size () > 0 )
1406  {
1410  while ( m_sdusBuffer.size () > 1 )
1411  {
1413  m_sdusBuffer.pop_front ();
1414  }
1415 
1419  m_keepS0 = m_sdusBuffer.front ();
1420  m_sdusBuffer.pop_front ();
1421  }
1422  break;
1423 
1424  default:
1428  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1429  break;
1430  }
1431  break;
1432 
1433  case WAITING_SI_SF:
1434  switch (framingInfo)
1435  {
1438 
1442  m_keepS0 = 0;
1443 
1447  while ( ! m_sdusBuffer.empty () )
1448  {
1450  m_sdusBuffer.pop_front ();
1451  }
1452  break;
1453 
1456 
1460  m_keepS0 = 0;
1461 
1465  while ( m_sdusBuffer.size () > 1 )
1466  {
1468  m_sdusBuffer.pop_front ();
1469  }
1470 
1474  m_keepS0 = m_sdusBuffer.front ();
1475  m_sdusBuffer.pop_front ();
1476 
1477  break;
1478 
1481 
1485  m_keepS0 = 0;
1486 
1490  m_sdusBuffer.pop_front ();
1491 
1495  while ( ! m_sdusBuffer.empty () )
1496  {
1498  m_sdusBuffer.pop_front ();
1499  }
1500  break;
1501 
1503  if ( m_sdusBuffer.size () == 1 )
1504  {
1506  }
1507  else
1508  {
1510  }
1511 
1515  m_keepS0 = 0;
1516 
1520  m_sdusBuffer.pop_front ();
1521 
1522  if ( m_sdusBuffer.size () > 0 )
1523  {
1527  while ( m_sdusBuffer.size () > 1 )
1528  {
1530  m_sdusBuffer.pop_front ();
1531  }
1532 
1536  m_keepS0 = m_sdusBuffer.front ();
1537  m_sdusBuffer.pop_front ();
1538  }
1539  break;
1540 
1541  default:
1545  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1546  break;
1547  }
1548  break;
1549 
1550  default:
1551  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1552  break;
1553  }
1554  }
1555 
1556 }
1557 
1558 void
1560 {
1561  NS_LOG_FUNCTION (this);
1562 
1563  Time now = Simulator::Now ();
1564 
1565  NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
1566  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1567  NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1568  NS_LOG_LOGIC ("VT(A) = " << m_vtA);
1569  NS_LOG_LOGIC ("VT(S) = " << m_vtS);
1570 
1571  // Transmission Queue HOL time
1572  Time txonQueueHolDelay (0);
1573  if ( m_txonBufferSize > 0 )
1574  {
1575  RlcTag txonQueueHolTimeTag;
1576  m_txonBuffer.front ()->PeekPacketTag (txonQueueHolTimeTag);
1577  txonQueueHolDelay = now - txonQueueHolTimeTag.GetSenderTimestamp ();
1578  }
1579 
1580  // Retransmission Queue HOL time
1581  Time retxQueueHolDelay;
1582  RlcTag retxQueueHolTimeTag;
1583  if ( m_retxBufferSize > 0 )
1584  {
1585  if (m_retxBuffer.at (m_vtA.GetValue ()).m_pdu != 0)
1586  {
1587  m_retxBuffer.at (m_vtA.GetValue ()).m_pdu->PeekPacketTag (retxQueueHolTimeTag);
1588  }
1589  else
1590  {
1591  m_txedBuffer.at (m_vtA.GetValue ()).m_pdu->PeekPacketTag (retxQueueHolTimeTag);
1592  }
1593  retxQueueHolDelay = now - retxQueueHolTimeTag.GetSenderTimestamp ();
1594  }
1595  else
1596  {
1597  retxQueueHolDelay = Seconds (0);
1598  }
1599 
1601  r.rnti = m_rnti;
1602  r.lcid = m_lcid;
1604  r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds ();
1606  r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds ();
1607 
1609  {
1611  }
1612  else
1613  {
1614  r.statusPduSize = 0;
1615  }
1616 
1617  if ( r.txQueueSize != 0 || r.retxQueueSize != 0 || r.statusPduSize != 0 )
1618  {
1619  NS_LOG_INFO ("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay << ", "
1620  << r.retxQueueSize << ", " << r.retxQueueHolDelay << ", "
1621  << r.statusPduSize);
1623  }
1624  else
1625  {
1626  NS_LOG_INFO ("ReportBufferStatus don't needed");
1627  }
1628 }
1629 
1630 
1631 void
1633 {
1634  NS_LOG_FUNCTION (this);
1635  NS_LOG_LOGIC ("Reordering Timer has expired");
1636 
1637  // 5.1.3.2.4 Actions when t-Reordering expires
1638  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
1639  // - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte segments
1640  // have been received;
1641  // - if VR(H) > VR(MS):
1642  // - start t-Reordering;
1643  // - set VR(X) to VR(H).
1644 
1645  m_vrMs = m_vrX;
1646  int firstVrMs = m_vrMs.GetValue ();
1647  std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (m_vrMs.GetValue ());
1648  while ( it != m_rxonBuffer.end () &&
1649  it->second.m_pduComplete )
1650  {
1651  m_vrMs++;
1652  it = m_rxonBuffer.find (m_vrMs.GetValue ());
1653 
1654  NS_ASSERT_MSG (firstVrMs != m_vrMs.GetValue (), "Infinite loop in ExpireReorderingTimer");
1655  }
1656  NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
1657 
1658  if ( m_vrH > m_vrMs )
1659  {
1660  NS_LOG_LOGIC ("Start reordering timer");
1663  m_vrX = m_vrH;
1664  NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
1665  }
1666 
1667  // Section 5.2.3 Status Reporting:
1668  // - The receiving side of an AM RLC entity shall trigger a
1669  // STATUS report when T_reordering expires.
1670  m_statusPduRequested = true;
1671 }
1672 
1673 void
1675 {
1676  NS_LOG_FUNCTION (this);
1677  NS_LOG_LOGIC ("PollRetransmit Timer has expired");
1678 
1679  NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
1680  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1681  NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1682  NS_LOG_LOGIC ("statusPduRequested = " << m_statusPduRequested);
1683 
1685 
1686  // see section 5.2.2.3
1687  // note the difference between Rel 8 and Rel 11 specs; we follow Rel 11 here
1688  NS_ASSERT (m_vtS <= m_vtMs);
1689  if ((m_txonBufferSize == 0 && m_retxBufferSize == 0)
1690  || (m_vtS == m_vtMs))
1691  {
1692  NS_LOG_INFO ("txonBuffer and retxBuffer empty. Move PDUs up to = " << m_vtS.GetValue () - 1 << " to retxBuffer");
1693  for (SequenceNumber10 sn = m_vtA; sn < m_vtS; sn++)
1694  {
1695  bool pduAvailable = m_txedBuffer.at (sn.GetValue ()).m_pdu != 0;
1696 
1697  if ( pduAvailable )
1698  {
1699  uint16_t snValue = sn.GetValue ();
1700  NS_LOG_INFO ("Move PDU " << sn << " from txedBuffer to retxBuffer");
1701  m_retxBuffer.at (snValue).m_pdu = m_txedBuffer.at (snValue).m_pdu->Copy ();
1702  m_retxBuffer.at (snValue).m_retxCount = m_txedBuffer.at (snValue).m_retxCount;
1703  m_retxBufferSize += m_retxBuffer.at (snValue).m_pdu->GetSize ();
1704 
1705  m_txedBufferSize -= m_txedBuffer.at (snValue).m_pdu->GetSize ();
1706  m_txedBuffer.at (snValue).m_pdu = 0;
1707  m_txedBuffer.at (snValue).m_retxCount = 0;
1708  }
1709  }
1710  }
1711 
1713 }
1714 
1715 
1716 void
1718 {
1719  NS_LOG_FUNCTION (this);
1720 }
1721 
1722 void
1724 {
1725  NS_LOG_LOGIC ("RBS Timer expires");
1726 
1728  {
1731  }
1732 }
1733 
1734 } // 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:280
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
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
AttributeValue implementation for Boolean.
Definition: boolean.h:36
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
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:831
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
#define min(a, b)
Definition: 80211b.c:42
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:1559
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
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
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:202
void SetPollingBit(uint8_t pollingBit)
Set polling bit function.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1022
Time m_pollRetransmitTimerValue
poll retransmit time value
Definition: lte-rlc-am.h:185
SequenceNumber10 m_vrR
VR(R)
Definition: lte-rlc-am.h:164
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:278
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:175
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
virtual uint32_t GetSerializedSize(void) const
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:1723
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
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-am.h:215
uint8_t GetStatus(void) const
Get status function.
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:362
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1381
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:1076
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:866
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...
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-am.h:210
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc.cc:123
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
SequenceNumber10 m_pollSn
POLL_SN.
Definition: lte-rlc-am.h:161
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:173
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
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:367
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
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
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:1077
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
uint8_t GetFramingInfo() const
Get framing info.
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
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:75
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:852
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:262
void ExpireStatusProhibitTimer(void)
method called when the T_status_prohibit timer expires
Definition: lte-rlc-am.cc:1717
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:359
void ExpirePollRetransmitTimer(void)
Expire poll retransmitter.
Definition: lte-rlc-am.cc:1674
SequenceNumber10 m_vtA
State variables.
Definition: lte-rlc-am.h:158
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:859
uint16_t PopLengthIndicator(void)
Pop length indicator function.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1014
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
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
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:874
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
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:915
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:1632
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
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:45