A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  */
20 
21 #include "ns3/simulator.h"
22 #include "ns3/log.h"
23 
24 #include "ns3/lte-rlc-am-header.h"
25 #include "ns3/lte-rlc-am.h"
26 #include "ns3/lte-rlc-sdu-status-tag.h"
27 #include "ns3/lte-rlc-tag.h"
28 
29 NS_LOG_COMPONENT_DEFINE ("LteRlcAm");
30 
31 namespace ns3 {
32 
34 
36 {
37  NS_LOG_FUNCTION (this);
38 
39  // Buffers
40  m_txonBufferSize = 0;
41  m_retxBuffer.resize (1024);
42  m_retxBufferSize = 0;
43  m_txedBuffer.resize (1024);
44  m_txedBufferSize = 0;
45 
46  m_statusPduRequested = false;
48 
49  // State variables: transmitting side
50  m_windowSize = 512;
51  m_vtA = 0;
53  m_vtS = 0;
54  m_pollSn = 0;
55 
56  // State variables: receiving side
57  m_vrR = 0;
59  m_vrX = 0;
60  m_vrMs = 0;
61  m_vrH = 0;
62 
63  // Counters
64  m_pduWithoutPoll = 0;
66 
67  // Configurable parameters
69  m_pollPdu = 1;
70  m_pollByte = 50;
71 
72  // SDU reassembling process
75 
76  // Timers
77  m_pollRetransmitTimerValue = MilliSeconds (100);
78 }
79 
81 {
82  NS_LOG_FUNCTION (this);
83 }
84 
85 TypeId
87 {
88  static TypeId tid = TypeId ("ns3::LteRlcAm")
89  .SetParent<LteRlc> ()
90  .AddConstructor<LteRlcAm> ()
91  .AddAttribute ("PollRetransmitTimer",
92  "Value of the t-PollRetransmit (See section 7.3 of 3GPP TS 36.322)",
93  TimeValue (MilliSeconds (100)),
94  MakeTimeAccessor (&LteRlcAm::m_pollRetransmitTimerValue),
95  MakeTimeChecker ())
96  .AddAttribute ("TxOpportunityForRetxAlwaysBigEnough",
97  "If true, always pretend that the size of a TxOpportunity is big enough "
98  "for retransmission. If false (default and realistic behavior), no retx "
99  "is performed unless the corresponding TxOpportunity is big enough.",
100  BooleanValue (false),
102  MakeBooleanChecker ())
103 
104  ;
105  return tid;
106 }
107 
108 void
110 {
111  NS_LOG_FUNCTION (this);
115 
116  m_txonBuffer.clear ();
117  m_txonBufferSize = 0;
118  m_txedBuffer.clear ();
119  m_txedBufferSize = 0;
120  m_retxBuffer.clear ();
121  m_retxBufferSize = 0;
122  m_rxonBuffer.clear ();
123  m_sdusBuffer.clear ();
124  m_keepS0 = 0;
125  m_controlPduBuffer = 0;
126 
128 }
129 
130 
135 void
137 {
138  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
139 
141  Time now = Simulator::Now ();
142  RlcTag timeTag (now);
143  p->AddPacketTag (timeTag);
144 
147  LteRlcSduStatusTag tag;
149  p->AddPacketTag (tag);
150 
151  NS_LOG_LOGIC ("Txon Buffer: New packet added");
152  m_txonBuffer.push_back (p);
153  m_txonBufferSize += p->GetSize ();
154  NS_LOG_LOGIC ("NumOfBuffers = " << m_txonBuffer.size() );
155  NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
156 
159 }
160 
161 
166 void
167 LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer, uint8_t harqId)
168 {
169  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << bytes);
170 
171  if (bytes < 4)
172  {
173  // Stingy MAC: In general, we need more bytes.
174  // There are a more restrictive test for each particular case
175  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small");
176  NS_ASSERT_MSG (false, "TxOpportunity (size = " << bytes << ") too small.\n"
177  << "Your MAC scheduler is assigned too few resource blocks.");
178  return;
179  }
180 
182  {
183  if (bytes < m_statusPduBufferSize)
184  {
185  // Stingy MAC: We need more bytes for the STATUS PDU
186  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small for the STATUS PDU (size = " << m_statusPduBufferSize << ")");
187  NS_ASSERT_MSG (false, "TxOpportunity (size = " << bytes << ") too small for the STATUS PDU (size = " << m_statusPduBufferSize << ")\n"
188  << "Your MAC scheduler is assigned too few resource blocks.");
189  return;
190  }
191 
192  NS_LOG_LOGIC ("Sending STATUS PDU");
193 
194  Ptr<Packet> packet = Create<Packet> ();
195  LteRlcAmHeader rlcAmHeader;
197  rlcAmHeader.SetAckSn (m_vrR);
198 
199  NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
200  packet->AddHeader (rlcAmHeader);
201 
202  // Send RLC PDU to MAC layer
204  params.pdu = packet;
205  params.rnti = m_rnti;
206  params.lcid = m_lcid;
207  params.layer = layer;
208  params.harqProcessId = harqId;
209 
210  m_macSapProvider->TransmitPdu (params);
211 
212  m_statusPduRequested = false;
214  return;
215  }
216  else if ( m_retxBufferSize > 0 )
217  {
218  NS_LOG_LOGIC ("Sending data from Retransmission Buffer");
219 
220  Ptr<Packet> packet = m_retxBuffer.at (m_vtA.GetValue ()).m_pdu->Copy ();
221 
222  if (( packet->GetSize () <= bytes )
224  {
225  LteRlcAmHeader rlcAmHeader;
226  packet->PeekHeader (rlcAmHeader);
227  NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
228 
229  // Send RLC PDU to MAC layer
231  params.pdu = packet;
232  params.rnti = m_rnti;
233  params.lcid = m_lcid;
234  params.layer = layer;
235  params.harqProcessId = harqId;
236 
237  m_macSapProvider->TransmitPdu (params);
238  return;
239  }
240  else
241  {
242  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small for retransmission of the packet (size = " << packet->GetSize () << ")");
243  NS_LOG_LOGIC ("Waiting for bigger TxOpportunity");
244  return;
245  }
246  }
247  else if ( m_txonBufferSize > 0 )
248  {
249  if (bytes < 7)
250  {
251  // Stingy MAC: We need more bytes for new DATA PDUs.
252  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small for DATA PDU");
253  NS_ASSERT_MSG (false, "TxOpportunity (size = " << bytes << ") too small for DATA PDU\n"
254  << "Your MAC scheduler is assigned too few resource blocks.");
255  return;
256  }
257 
258  NS_LOG_LOGIC ("Sending data from Transmission Buffer");
259  }
260  else if ( m_txedBufferSize > 0 )
261  {
262  NS_LOG_LOGIC ("Sending data from Transmitted Buffer");
263 
264  NS_LOG_INFO ("VT(A) = " << m_vtA);
265  NS_LOG_INFO ("VT(S) = " << m_vtS);
266 
267  uint16_t vta = m_vtA.GetValue ();
268  Ptr<Packet> packet = m_txedBuffer.at (vta)->Copy ();
269 
270  if (( packet->GetSize () <= bytes )
272  {
273  NS_LOG_INFO ("Move SN = " << vta << " to retxBuffer");
274  m_retxBuffer.at (vta).m_pdu = m_txedBuffer.at (vta)->Copy ();
275  m_retxBuffer.at (vta).m_retxCount = 1;
276  m_retxBufferSize += m_retxBuffer.at (vta).m_pdu->GetSize ();
277 
278  m_txedBufferSize -= m_txedBuffer.at (vta)->GetSize ();
279  m_txedBuffer.at (vta) = 0;
280 
281  LteRlcAmHeader rlcAmHeader;
282  packet->PeekHeader (rlcAmHeader);
283  NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
284 
285  // Send RLC PDU to MAC layer
287  params.pdu = packet;
288  params.rnti = m_rnti;
289  params.lcid = m_lcid;
290  params.layer = layer;
291  params.harqProcessId = harqId;
292 
293  m_macSapProvider->TransmitPdu (params);
294  return;
295  }
296  else
297  {
298  NS_LOG_LOGIC ("TxOpportunity (size = " << bytes << ") too small for retransmission of the packet (size = " << packet->GetSize () << ")");
299  NS_LOG_LOGIC ("Waiting for bigger TxOpportunity");
300  return;
301  }
302  }
303  else
304  {
305  NS_LOG_LOGIC ("No data pending");
306  return;
307  }
308 
309  //
310  //
311  // Build new PDU
312  //
313  //
314 
315  Ptr<Packet> packet = Create<Packet> ();
316  LteRlcAmHeader rlcAmHeader;
317  rlcAmHeader.SetDataPdu ();
318 
319  // Build Data field
320  uint32_t nextSegmentSize = bytes - 4;
321  uint32_t nextSegmentId = 1;
322  uint32_t dataFieldTotalSize = 0;
323  uint32_t dataFieldAddedSize = 0;
324  std::vector < Ptr<Packet> > dataField;
325 
326  // Remove the first packet from the transmission buffer.
327  // If only a segment of the packet is taken, then the remaining is given back later
328  if ( m_txonBuffer.size () == 0 )
329  {
330  NS_LOG_LOGIC ("No data pending");
331  return;
332  }
333 
334  NS_LOG_LOGIC ("SDUs in TxonBuffer = " << m_txonBuffer.size ());
335  NS_LOG_LOGIC ("First SDU buffer = " << *(m_txonBuffer.begin()));
336  NS_LOG_LOGIC ("First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
337  NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
338  NS_LOG_LOGIC ("Remove SDU from TxBuffer");
339  Ptr<Packet> firstSegment = (*(m_txonBuffer.begin ()))->Copy ();
340  m_txonBufferSize -= (*(m_txonBuffer.begin()))->GetSize ();
341  NS_LOG_LOGIC ("txBufferSize = " << m_txonBufferSize );
342  m_txonBuffer.erase (m_txonBuffer.begin ());
343 
344  while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
345  {
346  NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
347  NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
348  NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
349  if ( (firstSegment->GetSize () > nextSegmentSize) ||
350  // Segment larger than 2047 octets can only be mapped to the end of the Data field
351  (firstSegment->GetSize () > 2047)
352  )
353  {
354  // Take the minimum size, due to the 2047-bytes 3GPP exception
355  // This exception is due to the length of the LI field (just 11 bits)
356  uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
357 
358  NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
359  NS_LOG_LOGIC (" firstSegment > 2047 )");
360 
361  // Segment txBuffer.FirstBuffer and
362  // Give back the remaining segment to the transmission buffer
363  Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
364  NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
365 
366  // Status tag of the new and remaining segments
367  // Note: This is the only place where a PDU is segmented and
368  // therefore its status can change
369  LteRlcSduStatusTag oldTag, newTag;
370  firstSegment->RemovePacketTag (oldTag);
371  newSegment->RemovePacketTag (newTag);
372  if (oldTag.GetStatus () == LteRlcSduStatusTag::FULL_SDU)
373  {
374  newTag.SetStatus (LteRlcSduStatusTag::FIRST_SEGMENT);
375  oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
376  }
377  else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT)
378  {
379  newTag.SetStatus (LteRlcSduStatusTag::MIDDLE_SEGMENT);
380  //oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
381  }
382 
383  // Give back the remaining segment to the transmission buffer
384  firstSegment->RemoveAtStart (currSegmentSize);
385  NS_LOG_LOGIC (" firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize ());
386  if (firstSegment->GetSize () > 0)
387  {
388  firstSegment->AddPacketTag (oldTag);
389 
390  m_txonBuffer.insert (m_txonBuffer.begin (), firstSegment);
391  m_txonBufferSize += (*(m_txonBuffer.begin()))->GetSize ();
392 
393  NS_LOG_LOGIC (" Txon buffer: Give back the remaining segment");
394  NS_LOG_LOGIC (" Txon buffers = " << m_txonBuffer.size ());
395  NS_LOG_LOGIC (" Front buffer size = " << (*(m_txonBuffer.begin()))->GetSize ());
396  NS_LOG_LOGIC (" txonBufferSize = " << m_txonBufferSize );
397  }
398  else
399  {
400  // Whole segment was taken, so adjust tag
401  if (newTag.GetStatus () == LteRlcSduStatusTag::FIRST_SEGMENT)
402  {
403  newTag.SetStatus (LteRlcSduStatusTag::FULL_SDU);
404  }
405  else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
406  {
407  newTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
408  }
409  }
410  // Segment is completely taken or
411  // the remaining segment is given back to the transmission buffer
412  firstSegment = 0;
413 
414  // Put status tag once it has been adjusted
415  newSegment->AddPacketTag (newTag);
416 
417  // Add Segment to Data field
418  dataFieldAddedSize = newSegment->GetSize ();
419  dataFieldTotalSize += dataFieldAddedSize;
420  dataField.push_back (newSegment);
421  newSegment = 0;
422 
423  // ExtensionBit (Next_Segment - 1) = 0
424  rlcAmHeader.PushExtensionBit (LteRlcAmHeader::DATA_FIELD_FOLLOWS);
425 
426  // no LengthIndicator for the last one
427 
428  nextSegmentSize -= dataFieldAddedSize;
429  nextSegmentId++;
430 
431  // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
432 
433  // (NO more segments) → exit
434  // break;
435  }
436  else if ( (nextSegmentSize - firstSegment->GetSize () <= 2) || (m_txonBuffer.size () == 0) )
437  {
438  NS_LOG_LOGIC (" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txonBuffer.size == 0");
439 
440  // Add txBuffer.FirstBuffer to DataField
441  dataFieldAddedSize = firstSegment->GetSize ();
442  dataFieldTotalSize += dataFieldAddedSize;
443  dataField.push_back (firstSegment);
444  firstSegment = 0;
445 
446  // ExtensionBit (Next_Segment - 1) = 0
447  rlcAmHeader.PushExtensionBit (LteRlcAmHeader::DATA_FIELD_FOLLOWS);
448 
449  // no LengthIndicator for the last one
450 
451  nextSegmentSize -= dataFieldAddedSize;
452  nextSegmentId++;
453 
454  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ());
455  if (m_txonBuffer.size () > 0)
456  {
457  NS_LOG_LOGIC (" First SDU buffer = " << *(m_txonBuffer.begin()));
458  NS_LOG_LOGIC (" First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
459  }
460  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
461 
462  // nextSegmentSize <= 2 (only if txBuffer is not empty)
463 
464  // (NO more segments) → exit
465  // break;
466  }
467  else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
468  {
469  NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txonBuffer.size > 0");
470  // Add txBuffer.FirstBuffer to DataField
471  dataFieldAddedSize = firstSegment->GetSize ();
472  dataFieldTotalSize += dataFieldAddedSize;
473  dataField.push_back (firstSegment);
474 
475  // ExtensionBit (Next_Segment - 1) = 1
476  rlcAmHeader.PushExtensionBit (LteRlcAmHeader::E_LI_FIELDS_FOLLOWS);
477 
478  // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
479  rlcAmHeader.PushLengthIndicator (firstSegment->GetSize ());
480 
481  nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
482  nextSegmentId++;
483 
484  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ());
485  if (m_txonBuffer.size () > 0)
486  {
487  NS_LOG_LOGIC (" First SDU buffer = " << *(m_txonBuffer.begin()));
488  NS_LOG_LOGIC (" First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ());
489  }
490  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
491  NS_LOG_LOGIC (" Remove SDU from TxBuffer");
492 
493  // (more segments)
494  firstSegment = (*(m_txonBuffer.begin ()))->Copy ();
495  m_txonBufferSize -= (*(m_txonBuffer.begin()))->GetSize ();
496  m_txonBuffer.erase (m_txonBuffer.begin ());
497  NS_LOG_LOGIC (" txBufferSize = " << m_txonBufferSize );
498  }
499 
500  }
501 
502  //
503  // Build RLC header
504  //
505 
506  rlcAmHeader.SetSequenceNumber ( m_vtS++ );
507  rlcAmHeader.SetResegmentationFlag (LteRlcAmHeader::PDU);
508  rlcAmHeader.SetLastSegmentFlag (LteRlcAmHeader::LAST_PDU_SEGMENT);
509  rlcAmHeader.SetSegmentOffset (0);
510 
511  // Calculate FramingInfo flag according the status of the SDUs in the DataField
512  uint8_t framingInfo = 0;
513  std::vector< Ptr<Packet> >::iterator it;
514  it = dataField.begin ();
515 
516  // FIRST SEGMENT
517  LteRlcSduStatusTag tag;
518  (*it)->RemovePacketTag (tag);
519  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
521  )
522  {
523  framingInfo |= LteRlcAmHeader::FIRST_BYTE;
524  }
525  else
526  {
527  framingInfo |= LteRlcAmHeader::NO_FIRST_BYTE;
528  }
529  (*it)->AddPacketTag (tag);
530 
531  // Add all SDUs (in DataField) to the Packet
532  while (it < dataField.end ())
533  {
534  NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ());
535 
536  packet->AddAtEnd (*it);
537  it++;
538  }
539 
540  // LAST SEGMENT (Note: There could be only one and be the first one)
541  it--;
542  (*it)->RemovePacketTag (tag);
543  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
545  {
546  framingInfo |= LteRlcAmHeader::LAST_BYTE;
547  }
548  else
549  {
550  framingInfo |= LteRlcAmHeader::NO_LAST_BYTE;
551  }
552  (*it)->AddPacketTag (tag);
553 
554  // Set the FramingInfo flag after the calculation
555  rlcAmHeader.SetFramingInfo (framingInfo);
556 
557 
558  // Calculate the Polling Bit (5.2.2.1)
559  rlcAmHeader.SetPollingBit (LteRlcAmHeader::STATUS_REPORT_NOT_REQUESTED);
560 
562  NS_LOG_LOGIC ("PDU_WITHOUT_POLL = " << m_pduWithoutPoll);
563  m_byteWithoutPoll += packet->GetSize ();
564  NS_LOG_LOGIC ("BYTE_WITHOUT_POLL = " << m_byteWithoutPoll);
565 
567  ( (m_txonBuffer.empty ()) && (m_retxBuffer.empty ()) ) ||
568  (m_vtS >= m_vtMs)
569  )
570  {
571  rlcAmHeader.SetPollingBit (LteRlcAmHeader::STATUS_REPORT_IS_REQUESTED);
572  m_pduWithoutPoll = 0;
573  m_byteWithoutPoll = 0;
574 
575  m_pollSn = m_vtS - 1;
576  NS_LOG_LOGIC ("New POLL_SN = " << m_pollSn);
577 
579  {
580  NS_LOG_LOGIC ("Start PollRetransmit timer");
581 
584  }
585  else
586  {
587  NS_LOG_LOGIC ("Restart PollRetransmit timer");
588 
592  }
593  }
594 
595 
596  // Build RLC PDU with DataField and Header
597  NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader);
598  packet->AddHeader (rlcAmHeader);
599 
600  // Store new PDU into the Transmitted PDU Buffer
601  NS_LOG_LOGIC ("Put transmitted PDU in the txedBuffer");
602  m_txedBufferSize += packet->GetSize ();
603  m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber ().GetValue () ) = packet->Copy ();
604 
605  // Sender timestamp
606  RlcTag rlcTag (Simulator::Now ());
607  packet->AddByteTag (rlcTag);
608  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
609 
610  // Send RLC PDU to MAC layer
612  params.pdu = packet;
613  params.rnti = m_rnti;
614  params.lcid = m_lcid;
615  params.layer = layer;
616  params.harqProcessId = harqId;
617 
618  m_macSapProvider->TransmitPdu (params);
619 }
620 
621 void
623 {
624  NS_LOG_FUNCTION (this);
625 }
626 
627 void
629 {
630  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
631 
632  // Receiver timestamp
633  RlcTag rlcTag;
634  Time delay;
635  if (p->FindFirstMatchingByteTag (rlcTag))
636  {
637  delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
638  }
639  m_rxPdu (m_rnti, m_lcid, p->GetSize (), delay.GetNanoSeconds ());
640 
641  // Get RLC header parameters
642  LteRlcAmHeader rlcAmHeader;
643  p->PeekHeader (rlcAmHeader);
644  NS_LOG_LOGIC ("RLC header: " << rlcAmHeader);
645 
646  if ( rlcAmHeader.IsDataPdu () )
647  {
648 
649  // 5.1.3.1 Transmit operations
650 
651  // 5.1.3.1.1 General
652  //
653  // The transmitting side of an AM RLC entity shall prioritize transmission of RLC control PDUs
654  // over RLC data PDUs. The transmitting side of an AM RLC entity shall prioritize retransmission
655  // of RLC data PDUs over transmission of new AMD PDUs.
656  //
657  // The transmitting side of an AM RLC entity shall maintain a transmitting window according to
658  // state variables VT(A) and VT(MS) as follows:
659  // - a SN falls within the transmitting window if VT(A) <= SN < VT(MS);
660  // - a SN falls outside of the transmitting window otherwise.
661  //
662  // The transmitting side of an AM RLC entity shall not deliver to lower layer any RLC data PDU
663  // whose SN falls outside of the transmitting window.
664  //
665  // When delivering a new AMD PDU to lower layer, the transmitting side of an AM RLC entity shall:
666  // - set the SN of the AMD PDU to VT(S), and then increment VT(S) by one.
667  //
668  // The transmitting side of an AM RLC entity can receive a positive acknowledgement (confirmation
669  // of successful reception by its peer AM RLC entity) for a RLC data PDU by the following:
670  // - STATUS PDU from its peer AM RLC entity.
671  //
672  // When receiving a positive acknowledgement for an AMD PDU with SN = VT(A), the transmitting
673  // side of an AM RLC entity shall:
674  // - set VT(A) equal to the SN of the AMD PDU with the smallest SN, whose SN falls within the
675  // range VT(A) <= SN <= VT(S) and for which a positive acknowledgment has not been received yet.
676  // - if positive acknowledgements have been received for all AMD PDUs associated with
677  // a transmitted RLC SDU:
678  // - send an indication to the upper layers of successful delivery of the RLC SDU.
679 
680 
681  // 5.1.3.2 Receive operations
682  //
683  // 5.1.3.2.1 General
684  //
685  // The receiving side of an AM RLC entity shall maintain a receiving window according to state
686  // variables VR(R) and VR(MR) as follows:
687  // - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
688  // - a SN falls outside of the receiving window otherwise.
689  //
690  // When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity shall:
691  // - either discard the received RLC data PDU or place it in the reception buffer (see sub clause 5.1.3.2.2);
692  // - if the received RLC data PDU was placed in the reception buffer:
693  // - 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).
694  //
695  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
696  // - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
697 
698 
699  SequenceNumber10 seqNumber = rlcAmHeader.GetSequenceNumber ();
700 
701  if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::SEGMENT )
702  {
703  NS_LOG_LOGIC ("PDU segment received ( SN = " << seqNumber << " )");
704  }
705  else if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::PDU )
706  {
707  NS_LOG_LOGIC ("PDU received ( SN = " << seqNumber << " )");
708  }
709  else
710  {
711  NS_ASSERT_MSG (false, "Neither a PDU segment nor a PDU received");
712  return ;
713  }
714 
715  // STATUS PDU is requested
716  if ( rlcAmHeader.GetPollingBit () == LteRlcAmHeader::STATUS_REPORT_IS_REQUESTED )
717  {
718  m_statusPduRequested = true;
720 
722  {
724  }
725  }
726 
727  // 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
728  //
729  // When a RLC data PDU is received from lower layer, where the RLC data PDU contains
730  // byte segment numbers y to z of an AMD PDU with SN = x, the receiving side of an AM RLC entity shall:
731  // - if x falls outside of the receiving window; or
732  // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
733  // - discard the received RLC data PDU;
734  // - else:
735  // - place the received RLC data PDU in the reception buffer;
736  // - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
737  // - discard the duplicate byte segments.
738 
739  NS_LOG_LOGIC ("VR(R) = " << m_vrR);
740  NS_LOG_LOGIC ("VR(MR) = " << m_vrMr);
741  NS_LOG_LOGIC ("VR(X) = " << m_vrX);
742  NS_LOG_LOGIC ("VR(MS) = " << m_vrMs);
743  NS_LOG_LOGIC ("VR(H) = " << m_vrH);
744 
745  // - if x falls outside of the receiving window; or
746  // - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
747  if ( ! IsInsideReceivingWindow (seqNumber) )
748  {
749  NS_LOG_LOGIC ("PDU discarded");
750  return;
751  }
752  else
753  {
754  NS_LOG_LOGIC ("Place PDU in the reception buffer ( SN = " << seqNumber << " )");
755  m_rxonBuffer[ seqNumber.GetValue () ].m_byteSegments.push_back (p);
756  m_rxonBuffer[ seqNumber.GetValue () ].m_pduComplete = true;
757 
758  // - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
759  // - discard the duplicate byte segments.
760  }
761 
762  // 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception buffer
763  // When a RLC data PDU with SN = x is placed in the reception buffer,
764  // the receiving side of an AM RLC entity shall:
765 
766  // - if x >= VR(H)
767  // - update VR(H) to x+ 1;
768 
769  if ( seqNumber >= m_vrH )
770  {
771  m_vrH = seqNumber + 1;
772  NS_LOG_LOGIC ("New VR(H) = " << m_vrH);
773  }
774 
775  // - if all byte segments of the AMD PDU with SN = VR(MS) are received:
776  // - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for
777  // which not all byte segments have been received;
778 
779  std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (m_vrMs.GetValue ());
780  if ( it != m_rxonBuffer.end () &&
781  m_rxonBuffer[ m_vrMs.GetValue () ].m_pduComplete )
782  {
783  int firstVrMs = m_vrMs.GetValue ();
784  while ( it != m_rxonBuffer.end () &&
785  m_rxonBuffer[ m_vrMs.GetValue () ].m_pduComplete )
786  {
787  m_vrMs++;
788  it = m_rxonBuffer.find (m_vrMs.GetValue ());
789  NS_LOG_LOGIC ("Incr VR(MS) = " << m_vrMs);
790 
791  NS_ASSERT_MSG (firstVrMs != m_vrMs.GetValue (), "Infinite loop in RxonBuffer");
792  }
793  NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
794  }
795 
796  // - if x = VR(R):
797  // - if all byte segments of the AMD PDU with SN = VR(R) are received:
798  // - 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;
799  // - update VR(MR) to the updated VR(R) + AM_Window_Size;
800  // - 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;
801 
802  if ( seqNumber == m_vrR )
803  {
804  std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (seqNumber.GetValue ());
805  if ( it != m_rxonBuffer.end () &&
806  m_rxonBuffer[ seqNumber.GetValue () ].m_pduComplete )
807  {
808  it = m_rxonBuffer.find (m_vrR.GetValue ());
809  int firstVrR = m_vrR.GetValue ();
810  while ( it != m_rxonBuffer.end () &&
811  m_rxonBuffer[ m_vrR.GetValue () ].m_pduComplete )
812  {
813  NS_LOG_LOGIC ("Reassemble and Deliver ( SN = " << m_vrR << " )");
814  NS_ASSERT_MSG (m_rxonBuffer[ m_vrR.GetValue () ].m_byteSegments.size () == 1,
815  "Too many segments. PDU Reassembly process didn't work");
816  ReassembleAndDeliver (m_rxonBuffer[ m_vrR.GetValue () ].m_byteSegments.front ());
817  m_rxonBuffer.erase (m_vrR.GetValue ());
818 
819  m_vrR++;
820  it = m_rxonBuffer.find (m_vrR.GetValue ());
821 
822  NS_ASSERT_MSG (firstVrR != m_vrR.GetValue (), "Infinite loop in RxonBuffer");
823  }
824  NS_LOG_LOGIC ("New VR(R) = " << m_vrR);
826  NS_LOG_LOGIC ("New VR(MR) = " << m_vrMr);
827  }
828 
829 // NS_LOG_LOGIC ("Reassemble and Deliver ( SN = " << seqNumber << " )");
830 // NS_ASSERT_MSG (m_rxonBuffer[ seqNumber.GetValue () ].m_byteSegments.size () == 1,
831 // "Too many segments. PDU Reassembly process didn't work");
832 // ReassembleAndDeliver (m_rxonBuffer[ seqNumber.GetValue () ].m_byteSegments.front ());
833 // m_rxonBuffer.erase (seqNumber.GetValue ());
834  }
835 
836  // - if t-Reordering is running:
837  // - if VR(X) = VR(R); or
838  // - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
839  // - stop and reset t-Reordering;
840 
841  if ( m_reorderingTimer.IsRunning () )
842  {
843  NS_LOG_LOGIC ("Reordering timer is running");
844  if ( (m_vrX == m_vrR) ||
845  ( (! IsInsideReceivingWindow (m_vrX)) && (m_vrX != m_vrMr) )
846  )
847  {
849  NS_LOG_LOGIC ("Stop reordering timer");
851  }
852  }
853 
854  // - if t-Reordering is not running (includes the case t-Reordering is stopped due to actions above):
855  // - if VR (H) > VR(R):
856  // - start t-Reordering;
857  // - set VR(X) to VR(H).
858 
859  if ( ! m_reorderingTimer.IsRunning () )
860  {
861  NS_LOG_LOGIC ("Reordering timer is not running");
862  if ( m_vrH > m_vrR )
863  {
864  NS_LOG_LOGIC ("Start reordering timer");
867  m_vrX = m_vrH;
868  NS_LOG_LOGIC ("New VR(X) = " << m_vrX);
869  }
870  }
871 
872 
873 
875 
876  // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
877  // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity shall:
878 
879  // - if x falls outside of the reordering window:
880  // - update VR(UH) to x + 1;
881  // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering window, remove
882  // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in ascending order of the
883  // RLC SN if not delivered before;
884  // - if VR(UR) falls outside of the reordering window:
885  // - set VR(UR) to (VR(UH) - UM_Window_Size);
886 
887 // if ( ! IsInsideReorderingWindow (seqNumber))
888 // {
889 // NS_LOG_LOGIC ("SN outside the reordering window");
890 //
891 // m_vrUh = seqNumber + 1;
892 // NS_LOG_LOGIC ("New VR(UH) = " << m_vrUh);
893 //
894 // ReassembleOutsideWindow ();
895 //
896 // if ( ! IsInsideReorderingWindow (m_vrUr) )
897 // {
898 // m_vrUr = m_vrUh - m_windowSize;
899 // NS_LOG_LOGIC ("VR(UR) outside the reordering window");
900 // NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
901 // }
902 // }
903 
904  // - if the reception buffer contains an UMD PDU with SN = VR(UR):
905  // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been received;
906  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing
907  // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered
908  // before;
909 
910 // if ( m_rxBuffer.count (m_vrUr) > 0 )
911 // {
912 // NS_LOG_LOGIC ("Reception buffer contains SN = " << m_vrUr);
913 //
914 // std::map <uint16_t, Ptr<Packet> >::iterator it;
915 // uint16_t newVrUr;
916 //
917 // it = m_rxBuffer.find (m_vrUr);
918 // newVrUr = (it->first) + 1;
919 // while ( m_rxBuffer.count (newVrUr) > 0 )
920 // {
921 // newVrUr++;
922 // }
923 // m_vrUr = newVrUr;
924 // NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
925 //
926 // ReassembleSnLessThan (m_vrUr);
927 // }
928 
929  // - if t-Reordering is running:
930  // - if VR(UX) <= VR(UR); or
931  // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
932  // - stop and reset t-Reordering;
933 // if ( m_reorderingTimer.IsRunning () )
934 // {
935 // NS_LOG_LOGIC ("Reordering timer is running");
936 //
937 // if ( (m_vrUx <= m_vrUr) ||
938 // ((! IsInsideReorderingWindow (m_vrUx)) && (m_vrUx != m_vrUh)) )
939 // {
940 // NS_LOG_LOGIC ("Stop reordering timer");
941 // m_reorderingTimer.Cancel ();
942 // }
943 // }
944 
945  // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to actions above):
946  // - if VR(UH) > VR(UR):
947  // - start t-Reordering;
948  // - set VR(UX) to VR(UH).
949 // if ( ! m_reorderingTimer.IsRunning () )
950 // {
951 // NS_LOG_LOGIC ("Reordering timer is not running");
952 //
953 // if ( m_vrUx > m_vrUr )
954 // {
955 // NS_LOG_LOGIC ("VR(UX) > VR(UR). " << m_vrUx << " > " << m_vrUr);
956 // NS_LOG_LOGIC ("Start reordering timer");
957 // m_reorderingTimer = Simulator::Schedule (Time ("1.0s"),
958 // &LteRlcAm::ExpireReorderingTimer ,this);
959 // m_vrUx = m_vrUh;
960 // NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
961 // }
962 // }
963 
964  }
965  else if ( rlcAmHeader.IsControlPdu () )
966  {
967  NS_LOG_INFO ("Control AM RLC PDU");
968 
969  SequenceNumber10 ackSn = rlcAmHeader.GetAckSn ();
970 // SequenceNumber10 seqNumber = m_vtA;
971 
972  NS_LOG_INFO ("ackSn = " << ackSn);
973  NS_LOG_INFO ("VT(A) = " << m_vtA);
974  NS_LOG_INFO ("VT(S) = " << m_vtS);
975 
978  ackSn.SetModulusBase (m_vtA);
979  while (m_vtA < ackSn && m_vtA < m_vtS)
980  {
981 // NS_LOG_INFO ("seqNumber = " << seqNumber);
982 // NS_LOG_INFO ("m_txedBuffer( VT(A) ).size = " << m_txedBuffer.size ());
983 
984  uint16_t seqNumberValue = m_vtA.GetValue ();
986  && (seqNumberValue == m_pollSn.GetValue ()))
987  {
989  }
990 
991  if (m_txedBuffer.at (seqNumberValue))
992  {
993  NS_LOG_INFO ("ACKed SN = " << seqNumberValue << " from txedBuffer");
994 // NS_LOG_INFO ("m_txedBuffer( " << m_vtA << " )->GetSize = " << m_txedBuffer.at (m_vtA.GetValue ())->GetSize ());
995  m_txedBufferSize -= m_txedBuffer.at (seqNumberValue)->GetSize ();
996  m_txedBuffer.at (seqNumberValue) = 0;
997  }
998 
999  if (m_retxBuffer.at (seqNumberValue).m_pdu)
1000  {
1001  NS_LOG_INFO ("ACKed SN = " << seqNumberValue << " from retxBuffer");
1002  m_retxBufferSize -= m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
1003  m_retxBuffer.at (seqNumberValue).m_pdu = 0;
1004  m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
1005  }
1006 
1007  m_vtA++;
1010  ackSn.SetModulusBase (m_vtA);
1011  }
1012 
1013  NS_LOG_INFO ("New VT(A) = " << m_vtA);
1014 
1015  SequenceNumber10 seqNumber = m_vtA;
1016  uint16_t seqNumberValue;
1017  while (seqNumber < m_vtS)
1018  {
1019  seqNumberValue = seqNumber.GetValue ();
1020  if (m_txedBuffer.at (seqNumberValue))
1021  {
1022  NS_LOG_INFO ("Move SN = " << seqNumberValue << " to retxBuffer");
1023  m_retxBuffer.at (seqNumberValue).m_pdu = m_txedBuffer.at (seqNumberValue)->Copy ();
1024  m_retxBuffer.at (seqNumberValue).m_retxCount = 0;
1025  m_retxBufferSize += m_retxBuffer.at (seqNumberValue).m_pdu->GetSize ();
1026 
1027  m_txedBufferSize -= m_txedBuffer.at (seqNumberValue)->GetSize ();
1028  m_txedBuffer.at (seqNumberValue) = 0;
1029  }
1030  else if (m_retxBuffer.at (seqNumberValue).m_pdu)
1031  {
1032  m_retxBuffer.at (seqNumberValue).m_retxCount++;
1033  NS_LOG_INFO ("Incr RETX_COUNT for SN = " << seqNumberValue);
1034  if (m_retxBuffer.at (seqNumberValue).m_retxCount >= m_maxRetxThreshold)
1035  {
1036  NS_LOG_INFO ("Max RETX_COUNT for SN = " << seqNumberValue);
1037  }
1038  }
1039 
1040  seqNumber++;
1041  }
1042 
1043  return;
1044  }
1045  else
1046  {
1047  NS_LOG_WARN ("Wrong AM RLC PDU type");
1048  return;
1049  }
1050 
1051 }
1052 
1053 
1054 bool
1056 {
1057  NS_LOG_FUNCTION (this << seqNumber);
1058  NS_LOG_LOGIC ("Receiving Window: " <<
1059  m_vrR << " <= " << seqNumber << " <= " << m_vrMr);
1060 
1063  seqNumber.SetModulusBase (m_vrR);
1064 
1065  if ( (m_vrR <= seqNumber) && (seqNumber < m_vrMr ) )
1066  {
1067  NS_LOG_LOGIC (seqNumber << " is INSIDE the receiving window");
1068  return true;
1069  }
1070  else
1071  {
1072  NS_LOG_LOGIC (seqNumber << " is OUTSIDE the receiving window");
1073  return false;
1074  }
1075 }
1076 
1077 
1078 void
1080 {
1081  LteRlcAmHeader rlcAmHeader;
1082  packet->RemoveHeader (rlcAmHeader);
1083  uint8_t framingInfo = rlcAmHeader.GetFramingInfo ();
1084  SequenceNumber10 currSeqNumber = rlcAmHeader.GetSequenceNumber ();
1085  bool expectedSnLost;
1086 
1087  if ( currSeqNumber != m_expectedSeqNumber )
1088  {
1089  expectedSnLost = true;
1090  NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
1091  m_expectedSeqNumber = currSeqNumber + 1;
1092  }
1093  else
1094  {
1095  expectedSnLost = false;
1096  NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
1098  }
1099 
1100  // Build list of SDUs
1101  uint8_t extensionBit;
1102  uint16_t lengthIndicator;
1103  do
1104  {
1105  extensionBit = rlcAmHeader.PopExtensionBit ();
1106  NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit);
1107 
1108  if ( extensionBit == 0 )
1109  {
1110  m_sdusBuffer.push_back (packet);
1111  }
1112  else // extensionBit == 1
1113  {
1114  lengthIndicator = rlcAmHeader.PopLengthIndicator ();
1115  NS_LOG_LOGIC ("LI = " << lengthIndicator);
1116 
1117  // Check if there is enough data in the packet
1118  if ( lengthIndicator >= packet->GetSize () )
1119  {
1120  NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator);
1122  }
1123 
1124  // Split packet in two fragments
1125  Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator);
1126  packet->RemoveAtStart (lengthIndicator);
1127 
1128  m_sdusBuffer.push_back (data_field);
1129  }
1130  }
1131  while ( extensionBit == 1 );
1132 
1133  std::list < Ptr<Packet> >::iterator it;
1134 
1135  // Current reassembling state
1136  if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'");
1137  else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'");
1138  else NS_LOG_LOGIC ("Reassembling State = Unknown state");
1139 
1140  // Received framing Info
1141  NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
1142  NS_LOG_LOGIC ("m_sdusBuffer = " << m_sdusBuffer.size ());
1143 
1144  // Reassemble the list of SDUs (when there is no losses)
1145  if (!expectedSnLost)
1146  {
1147  switch (m_reassemblingState)
1148  {
1149  case WAITING_S0_FULL:
1150  switch (framingInfo)
1151  {
1154 
1158  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
1159  {
1161  }
1162  m_sdusBuffer.clear ();
1163  break;
1164 
1167 
1171  while ( m_sdusBuffer.size () > 1 )
1172  {
1174  m_sdusBuffer.pop_front ();
1175  }
1176 
1180  m_keepS0 = m_sdusBuffer.front ();
1181  m_sdusBuffer.pop_front ();
1182  break;
1183 
1186  default:
1190  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1191  break;
1192  }
1193  break;
1194 
1195  case WAITING_SI_SF:
1196  switch (framingInfo)
1197  {
1200 
1204  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1205  m_sdusBuffer.pop_front ();
1207 
1211  while ( ! m_sdusBuffer.empty () )
1212  {
1214  m_sdusBuffer.pop_front ();
1215  }
1216  break;
1217 
1220 
1224  if ( m_sdusBuffer.size () == 1 )
1225  {
1226  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1227  m_sdusBuffer.pop_front ();
1228  }
1229  else // m_sdusBuffer.size () > 1
1230  {
1234  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
1235  m_sdusBuffer.pop_front ();
1237 
1241  while ( m_sdusBuffer.size () > 1 )
1242  {
1244  m_sdusBuffer.pop_front ();
1245  }
1246 
1250  m_keepS0 = m_sdusBuffer.front ();
1251  m_sdusBuffer.pop_front ();
1252  }
1253  break;
1254 
1257  default:
1261  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1262  break;
1263  }
1264  break;
1265 
1266  default:
1267  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1268  break;
1269  }
1270  }
1271  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
1272  {
1273  switch (m_reassemblingState)
1274  {
1275  case WAITING_S0_FULL:
1276  switch (framingInfo)
1277  {
1280 
1284  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
1285  {
1287  }
1288  m_sdusBuffer.clear ();
1289  break;
1290 
1293 
1297  while ( m_sdusBuffer.size () > 1 )
1298  {
1300  m_sdusBuffer.pop_front ();
1301  }
1302 
1306  m_keepS0 = m_sdusBuffer.front ();
1307  m_sdusBuffer.pop_front ();
1308  break;
1309 
1312 
1316  m_sdusBuffer.pop_front ();
1317 
1321  while ( ! m_sdusBuffer.empty () )
1322  {
1324  m_sdusBuffer.pop_front ();
1325  }
1326  break;
1327 
1329  if ( m_sdusBuffer.size () == 1 )
1330  {
1332  }
1333  else
1334  {
1336  }
1337 
1341  m_sdusBuffer.pop_front ();
1342 
1343  if ( m_sdusBuffer.size () > 0 )
1344  {
1348  while ( m_sdusBuffer.size () > 1 )
1349  {
1351  m_sdusBuffer.pop_front ();
1352  }
1353 
1357  m_keepS0 = m_sdusBuffer.front ();
1358  m_sdusBuffer.pop_front ();
1359  }
1360  break;
1361 
1362  default:
1366  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1367  break;
1368  }
1369  break;
1370 
1371  case WAITING_SI_SF:
1372  switch (framingInfo)
1373  {
1376 
1380  m_keepS0 = 0;
1381 
1385  while ( ! m_sdusBuffer.empty () )
1386  {
1388  m_sdusBuffer.pop_front ();
1389  }
1390  break;
1391 
1394 
1398  m_keepS0 = 0;
1399 
1403  while ( m_sdusBuffer.size () > 1 )
1404  {
1406  m_sdusBuffer.pop_front ();
1407  }
1408 
1412  m_keepS0 = m_sdusBuffer.front ();
1413  m_sdusBuffer.pop_front ();
1414 
1415  break;
1416 
1419 
1423  m_keepS0 = 0;
1424 
1428  m_sdusBuffer.pop_front ();
1429 
1433  while ( ! m_sdusBuffer.empty () )
1434  {
1436  m_sdusBuffer.pop_front ();
1437  }
1438  break;
1439 
1441  if ( m_sdusBuffer.size () == 1 )
1442  {
1444  }
1445  else
1446  {
1448  }
1449 
1453  m_keepS0 = 0;
1454 
1458  m_sdusBuffer.pop_front ();
1459 
1460  if ( m_sdusBuffer.size () > 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 
1479  default:
1483  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1484  break;
1485  }
1486  break;
1487 
1488  default:
1489  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1490  break;
1491  }
1492  }
1493 
1494 }
1495 
1496 
1498 // void
1499 // LteRlcAm::ReassembleOutsideWindow (void)
1500 // {
1501 // NS_LOG_LOGIC ("Reassemble Outside Window");
1502 //
1503 // std::map <uint16_t, Ptr<Packet> >::iterator it;
1504 // it = m_rxBuffer.begin ();
1505 //
1506 // while ( (it != m_rxBuffer.end ()) && ! IsInsideReorderingWindow (it->first) )
1507 // {
1508 // NS_LOG_LOGIC ("SN = " << it->first);
1509 //
1510 // // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1511 // ReassembleAndDeliver (it->second);
1512 // m_rxBuffer.erase (it);
1513 // it++;
1514 // }
1515 //
1516 // if (it != m_rxBuffer.end ())
1517 // {
1518 // NS_LOG_LOGIC ("(SN = " << it->first << ") is inside the reordering window");
1519 // }
1520 // }
1521 
1522 
1524 // void
1525 // LteRlcAm::ReassembleSnLessThan (uint16_t seqNumber)
1526 // {
1527 // NS_LOG_LOGIC ("Reassemble SN < updated VR(UR)" );
1528 //
1529 // std::map <uint16_t, Ptr<Packet> >::iterator it;
1530 // it = m_rxBuffer.begin ();
1531 //
1532 // while ( (it != m_rxBuffer.end ()) && (it->first < seqNumber) )
1533 // {
1534 // NS_LOG_LOGIC ("SN = " << it->first);
1535 //
1536 // // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1537 // ReassembleAndDeliver (it->second);
1538 // m_rxBuffer.erase (it);
1539 // it++;
1540 // }
1541 //
1542 // if (it != m_rxBuffer.end ())
1543 // {
1544 // NS_LOG_LOGIC ("(SN = " << it->first << ") >= " << m_vrUr);
1545 // }
1546 // }
1547 
1548 
1549 void
1551 {
1552  NS_LOG_FUNCTION (this);
1553 
1554  Time now = Simulator::Now ();
1555 
1556  NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
1557  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1558  NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1559  NS_LOG_LOGIC ("VT(A) = " << m_vtA);
1560  NS_LOG_LOGIC ("VT(S) = " << m_vtS);
1561 
1562  // Transmission Queue HOL time
1563  Time txonQueueHolDelay (0);
1564  if ( m_txonBufferSize > 0 )
1565  {
1566  RlcTag txonQueueHolTimeTag;
1567  m_txonBuffer.front ()->PeekPacketTag (txonQueueHolTimeTag);
1568  txonQueueHolDelay = now - txonQueueHolTimeTag.GetSenderTimestamp ();
1569  }
1570 
1571  // Retransmission Queue HOL time
1572  Time retxQueueHolDelay (0);
1573  RlcTag retxQueueHolTimeTag;
1574  if ( m_retxBufferSize > 0 )
1575  {
1576  m_retxBuffer.at (m_vtA.GetValue ()).m_pdu->PeekPacketTag (retxQueueHolTimeTag);
1577  retxQueueHolDelay = now - retxQueueHolTimeTag.GetSenderTimestamp ();
1578  }
1579  else if ( m_txedBufferSize > 0 )
1580  {
1581  m_txedBuffer.at (m_vtA.GetValue ())->PeekPacketTag (retxQueueHolTimeTag);
1582  retxQueueHolDelay = now - retxQueueHolTimeTag.GetSenderTimestamp ();
1583  }
1584 
1586  r.rnti = m_rnti;
1587  r.lcid = m_lcid;
1589  r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds ();
1591  r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds ();
1592 
1594  {
1596  }
1597  else
1598  {
1599  r.statusPduSize = 0;
1600  }
1601 
1602  if ( r.txQueueSize != 0 || r.retxQueueSize != 0 || r.statusPduSize != 0 )
1603  {
1604  NS_LOG_INFO ("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay << ", "
1605  << r.retxQueueSize << ", " << r.retxQueueHolDelay << ", "
1606  << r.statusPduSize);
1608  }
1609  else
1610  {
1611  NS_LOG_INFO ("ReportBufferStatus don't needed");
1612  }
1613 }
1614 
1615 
1616 void
1618 {
1619  NS_LOG_FUNCTION (this);
1620  NS_LOG_LOGIC ("Reordering Timer has expired");
1621 
1622  // 5.1.3.2.4 Actions when t-Reordering expires
1623  // When t-Reordering expires, the receiving side of an AM RLC entity shall:
1624  // - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte segments
1625  // have been received;
1626  // - if VR(H) > VR(MS):
1627  // - start t-Reordering;
1628  // - set VR(X) to VR(H).
1629 
1630  m_vrMs = m_vrX;
1631  int firstVrMs = m_vrMs.GetValue ();
1632  std::map <uint16_t, PduBuffer>::iterator it = m_rxonBuffer.find (m_vrMs.GetValue ());
1633  while ( it != m_rxonBuffer.end () &&
1634  m_rxonBuffer[ m_vrMs.GetValue () ].m_pduComplete )
1635  {
1636  m_vrMs++;
1637  it = m_rxonBuffer.find (m_vrMs.GetValue ());
1638 
1639  NS_ASSERT_MSG (firstVrMs != m_vrMs.GetValue (), "Infinite loop in ExpireReorderingTimer");
1640  }
1641  NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
1642 
1643  if ( m_vrH > m_vrMs )
1644  {
1645  NS_LOG_LOGIC ("Start reordering timer");
1648  m_vrX = m_vrH;
1649  NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs);
1650  }
1651 }
1652 
1653 void
1655 {
1656  NS_LOG_FUNCTION (this);
1657  NS_LOG_LOGIC ("PollRetransmit Timer has expired");
1658 
1659  NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize);
1660  NS_LOG_LOGIC ("retxBufferSize = " << m_retxBufferSize);
1661  NS_LOG_LOGIC ("txedBufferSize = " << m_txedBufferSize);
1662  NS_LOG_LOGIC ("statusPduRequested = " << m_statusPduRequested);
1663 
1665 }
1666 
1667 
1668 
1669 } // namespace ns3
uint8_t PopExtensionBit(void)
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
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:128
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:824
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
EventId m_statusProhibitTimer
Definition: lte-rlc-am.h:145
#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
Definition: lte-rlc-am.h:132
Hold a bool native type.
Definition: boolean.h:38
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
virtual void DoReceivePdu(Ptr< Packet > p)
Definition: lte-rlc-am.cc:628
std::vector< RetxBuffer > m_retxBuffer
Definition: lte-rlc-am.h:84
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register the class in the ns-3 factory.
Definition: object-base.h:38
virtual void DoNotifyTxOpportunity(uint32_t bytes, uint8_t layer, uint8_t harqId)
MAC SAP.
Definition: lte-rlc-am.cc:167
uint32_t m_statusPduBufferSize
Definition: lte-rlc-am.h:91
SequenceNumber10 m_vtS
Definition: lte-rlc-am.h:118
void DoReportBufferStatus()
Definition: lte-rlc-am.cc:1550
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:841
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
SequenceNumber10 m_vtMs
Definition: lte-rlc-am.h:117
SequenceNumber10 m_vrMs
Definition: lte-rlc-am.h:125
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
Time m_pollRetransmitTimerValue
Definition: lte-rlc-am.h:143
SequenceNumber10 m_vrR
Definition: lte-rlc-am.h:122
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:744
EventId m_reorderingTimer
Definition: lte-rlc-am.h:144
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
Definition: lte-mac-sap.h:72
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:223
uint16_t m_rnti
Definition: lte-rlc.h:122
bool IsRunning(void) const
This method is syntactic sugar for the ns3::Simulator::isExpired method.
Definition: event-id.cc:59
bool IsInsideReceivingWindow(SequenceNumber10 seqNumber)
Definition: lte-rlc-am.cc:1055
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
uint8_t m_lcid
Definition: lte-rlc.h:123
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:49
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:68
EventId m_pollRetransmitTimer
Timers.
Definition: lte-rlc-am.h:142
void SetModulusBase(SequenceNumber10 modulusBase)
Parameters for LteMacSapProvider::ReportBufferStatus.
Definition: lte-mac-sap.h:66
uint32_t m_txonBufferSize
Definition: lte-rlc-am.h:86
uint16_t txQueueHolDelay
the Head Of Line delay of the transmission queue
Definition: lte-mac-sap.h:71
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:228
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:317
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-am.h:168
LteRlcSapUser * m_rlcSapUser
Definition: lte-rlc.h:111
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:353
std::map< uint16_t, PduBuffer > m_rxonBuffer
Definition: lte-rlc-am.h:103
hold objects of type ns3::Time
Definition: nstime.h:1008
uint8_t GetFramingInfo() const
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:48
uint16_t m_pollPdu
Definition: lte-rlc-am.h:151
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
Ptr< Packet > m_keepS0
Definition: lte-rlc-am.h:163
virtual void DoDispose()
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: lte-rlc.cc:117
SequenceNumber10 m_pollSn
Definition: lte-rlc-am.h:119
LteMacSapProvider * m_macSapProvider
Definition: lte-rlc.h:120
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
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)
The packet header for the AM Radio Link Control (RLC) protocol packets.
uint8_t layer
the layer value that was passed by the MAC in the call to NotifyTxOpportunity that generated this PDU...
Definition: lte-mac-sap.h:50
std::list< Ptr< Packet > > m_sdusBuffer
Definition: lte-rlc-am.h:110
uint16_t m_pollByte
Definition: lte-rlc-am.h:152
SequenceNumber10 m_vrH
Definition: lte-rlc-am.h:126
SequenceNumber10 m_vrMr
Definition: lte-rlc-am.h:123
Time GetSenderTimestamp(void) const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Definition: lte-rlc-tag.h:60
SequenceNumber10 m_vrX
Definition: lte-rlc-am.h:124
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:69
uint32_t m_pduWithoutPoll
Counters.
Definition: lte-rlc-am.h:131
uint32_t txQueueSize
the current size of the RLC transmission queue
Definition: lte-mac-sap.h:70
static Time Now(void)
Return the "current simulation time".
Definition: simulator.cc:180
uint32_t m_txedBufferSize
Definition: lte-rlc-am.h:88
virtual void DoNotifyHarqDeliveryFailure()
Definition: lte-rlc-am.cc:622
uint16_t m_maxRetxThreshold
Configurable parameters.
Definition: lte-rlc-am.h:150
#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:84
int64_t GetNanoSeconds(void) const
Definition: nstime.h:297
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:74
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
virtual void DoDispose()
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: lte-rlc-am.cc:109
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:203
void ExpirePollRetransmitTimer(void)
Definition: lte-rlc-am.cc:1654
SequenceNumber10 m_vtA
State variables.
Definition: lte-rlc-am.h:116
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:848
uint16_t PopLengthIndicator(void)
void SetStatus(uint8_t status)
uint16_t retxQueueHolDelay
the Head Of Line delay of the retransmission queue
Definition: lte-mac-sap.h:73
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::cancel method.
Definition: event-id.cc:47
virtual void ReportBufferStatus(ReportBufferStatusParameters params)=0
Report the RLC buffer status to the MAC.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:441
std::vector< Ptr< Packet > > m_txonBuffer
Definition: lte-rlc-am.h:75
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:132
Ptr< Packet > m_controlPduBuffer
Definition: lte-rlc-am.h:105
void ReassembleAndDeliver(Ptr< Packet > packet)
Definition: lte-rlc-am.cc:1079
uint16_t m_windowSize
Constants.
Definition: lte-rlc-am.h:137
uint8_t harqProcessId
the HARQ process id that was passed by the MAC in the call to NotifyTxOpportunity that generated this...
Definition: lte-mac-sap.h:51
bool m_txOpportunityForRetxAlwaysBigEnough
Definition: lte-rlc-am.h:154
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
ReassemblingState_t m_reassemblingState
Definition: lte-rlc-am.h:162
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:49
uint32_t m_retxBufferSize
Definition: lte-rlc-am.h:87
int64_t GetMilliSeconds(void) const
Definition: nstime.h:281
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
static TypeId GetTypeId(void)
Definition: lte-rlc-am.cc:86
bool m_statusPduRequested
Definition: lte-rlc-am.h:90
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:1617
std::vector< Ptr< Packet > > m_txedBuffer
Definition: lte-rlc-am.h:76
virtual void DoTransmitPdcpPdu(Ptr< Packet > p)
RLC SAP.
Definition: lte-rlc-am.cc:136
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
virtual ~LteRlcAm()
Definition: lte-rlc-am.cc:80
SequenceNumber10 GetSequenceNumber() const
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:808
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:45