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