A Discrete-Event Network Simulator
API
lte-rlc-um.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-header.h"
25 #include "ns3/lte-rlc-um.h"
26 #include "ns3/lte-rlc-sdu-status-tag.h"
27 #include "ns3/lte-rlc-tag.h"
28 
29 namespace ns3 {
30 
31 NS_LOG_COMPONENT_DEFINE ("LteRlcUm");
32 
34 
36  : m_maxTxBufferSize (10 * 1024),
37  m_txBufferSize (0),
38  m_sequenceNumber (0),
39  m_vrUr (0),
40  m_vrUx (0),
41  m_vrUh (0),
42  m_windowSize (512),
43  m_expectedSeqNumber (0)
44 {
45  NS_LOG_FUNCTION (this);
47 }
48 
50 {
51  NS_LOG_FUNCTION (this);
52 }
53 
54 TypeId
56 {
57  static TypeId tid = TypeId ("ns3::LteRlcUm")
58  .SetParent<LteRlc> ()
59  .SetGroupName("Lte")
60  .AddConstructor<LteRlcUm> ()
61  .AddAttribute ("MaxTxBufferSize",
62  "Maximum Size of the Transmission Buffer (in Bytes)",
63  UintegerValue (10 * 1024),
65  MakeUintegerChecker<uint32_t> ())
66  .AddAttribute ("ReorderingTimer",
67  "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
68  TimeValue (MilliSeconds (100)),
70  MakeTimeChecker ())
71  ;
72  return tid;
73 }
74 
75 void
77 {
78  NS_LOG_FUNCTION (this);
80  m_rbsTimer.Cancel ();
81 
83 }
84 
89 void
91 {
92  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
93 
95  {
99  p->AddPacketTag (tag);
100 
101  NS_LOG_LOGIC ("Tx Buffer: New packet added");
102  m_txBuffer.push_back (TxPdu (p, Simulator::Now ()));
103  m_txBufferSize += p->GetSize ();
104  NS_LOG_LOGIC ("NumOfBuffers = " << m_txBuffer.size() );
105  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
106  }
107  else
108  {
109  // Discard full RLC SDU
110  NS_LOG_LOGIC ("TxBuffer is full. RLC SDU discarded");
111  NS_LOG_LOGIC ("MaxTxBufferSize = " << m_maxTxBufferSize);
112  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
113  NS_LOG_LOGIC ("packet size = " << p->GetSize ());
114  }
115 
118  m_rbsTimer.Cancel ();
119 }
120 
121 
126 void
128 {
129  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << txOpParams.bytes);
130 
131  if (txOpParams.bytes <= 2)
132  {
133  // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
134  NS_LOG_LOGIC ("TX opportunity too small = " << txOpParams.bytes);
135  return;
136  }
137 
138  Ptr<Packet> packet = Create<Packet> ();
139  LteRlcHeader rlcHeader;
140 
141  // Build Data field
142  uint32_t nextSegmentSize = txOpParams.bytes - 2;
143  uint32_t nextSegmentId = 1;
144  uint32_t dataFieldTotalSize = 0;
145  uint32_t dataFieldAddedSize = 0;
146  std::vector < Ptr<Packet> > dataField;
147 
148  // Remove the first packet from the transmission buffer.
149  // If only a segment of the packet is taken, then the remaining is given back later
150  if ( m_txBuffer.size () == 0 )
151  {
152  NS_LOG_LOGIC ("No data pending");
153  return;
154  }
155 
156  Ptr<Packet> firstSegment = m_txBuffer.begin ()->m_pdu->Copy ();
157  Time firstSegmentTime = m_txBuffer.begin ()->m_waitingSince;
158 
159  NS_LOG_LOGIC ("SDUs in TxBuffer = " << m_txBuffer.size ());
160  NS_LOG_LOGIC ("First SDU buffer = " << firstSegment);
161  NS_LOG_LOGIC ("First SDU size = " << firstSegment->GetSize ());
162  NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
163  NS_LOG_LOGIC ("Remove SDU from TxBuffer");
164  m_txBufferSize -= firstSegment->GetSize ();
165  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize );
166  m_txBuffer.erase (m_txBuffer.begin ());
167 
168  while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
169  {
170  NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
171  NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
172  NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
173  if ( (firstSegment->GetSize () > nextSegmentSize) ||
174  // Segment larger than 2047 octets can only be mapped to the end of the Data field
175  (firstSegment->GetSize () > 2047)
176  )
177  {
178  // Take the minimum size, due to the 2047-bytes 3GPP exception
179  // This exception is due to the length of the LI field (just 11 bits)
180  uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
181 
182  NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
183  NS_LOG_LOGIC (" firstSegment > 2047 )");
184 
185  // Segment txBuffer.FirstBuffer and
186  // Give back the remaining segment to the transmission buffer
187  Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
188  NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
189 
190  // Status tag of the new and remaining segments
191  // Note: This is the only place where a PDU is segmented and
192  // therefore its status can change
193  LteRlcSduStatusTag oldTag, newTag;
194  firstSegment->RemovePacketTag (oldTag);
195  newSegment->RemovePacketTag (newTag);
196  if (oldTag.GetStatus () == LteRlcSduStatusTag::FULL_SDU)
197  {
198  newTag.SetStatus (LteRlcSduStatusTag::FIRST_SEGMENT);
199  oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
200  }
201  else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT)
202  {
203  newTag.SetStatus (LteRlcSduStatusTag::MIDDLE_SEGMENT);
204  //oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
205  }
206 
207  // Give back the remaining segment to the transmission buffer
208  firstSegment->RemoveAtStart (currSegmentSize);
209  NS_LOG_LOGIC (" firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize ());
210  if (firstSegment->GetSize () > 0)
211  {
212  firstSegment->AddPacketTag (oldTag);
213 
214  m_txBuffer.insert (m_txBuffer.begin (), TxPdu (firstSegment, firstSegmentTime));
215  m_txBufferSize += m_txBuffer.begin()->m_pdu->GetSize ();
216 
217  NS_LOG_LOGIC (" TX buffer: Give back the remaining segment");
218  NS_LOG_LOGIC (" TX buffers = " << m_txBuffer.size ());
219  NS_LOG_LOGIC (" Front buffer size = " << m_txBuffer.begin()->m_pdu->GetSize ());
220  NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
221  }
222  else
223  {
224  // Whole segment was taken, so adjust tag
225  if (newTag.GetStatus () == LteRlcSduStatusTag::FIRST_SEGMENT)
226  {
227  newTag.SetStatus (LteRlcSduStatusTag::FULL_SDU);
228  }
229  else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
230  {
231  newTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
232  }
233  }
234  // Segment is completely taken or
235  // the remaining segment is given back to the transmission buffer
236  firstSegment = 0;
237 
238  // Put status tag once it has been adjusted
239  newSegment->AddPacketTag (newTag);
240 
241  // Add Segment to Data field
242  dataFieldAddedSize = newSegment->GetSize ();
243  dataFieldTotalSize += dataFieldAddedSize;
244  dataField.push_back (newSegment);
245  newSegment = 0;
246 
247  // ExtensionBit (Next_Segment - 1) = 0
248  rlcHeader.PushExtensionBit (LteRlcHeader::DATA_FIELD_FOLLOWS);
249 
250  // no LengthIndicator for the last one
251 
252  nextSegmentSize -= dataFieldAddedSize;
253  nextSegmentId++;
254 
255  // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
256 
257  // (NO more segments) → exit
258  // break;
259  }
260  else if ( (nextSegmentSize - firstSegment->GetSize () <= 2) || (m_txBuffer.size () == 0) )
261  {
262  NS_LOG_LOGIC (" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
263  // Add txBuffer.FirstBuffer to DataField
264  dataFieldAddedSize = firstSegment->GetSize ();
265  dataFieldTotalSize += dataFieldAddedSize;
266  dataField.push_back (firstSegment);
267  firstSegment = 0;
268 
269  // ExtensionBit (Next_Segment - 1) = 0
270  rlcHeader.PushExtensionBit (LteRlcHeader::DATA_FIELD_FOLLOWS);
271 
272  // no LengthIndicator for the last one
273 
274  nextSegmentSize -= dataFieldAddedSize;
275  nextSegmentId++;
276 
277  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
278  if (m_txBuffer.size () > 0)
279  {
280  NS_LOG_LOGIC (" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
281  NS_LOG_LOGIC (" First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize ());
282  }
283  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
284 
285  // nextSegmentSize <= 2 (only if txBuffer is not empty)
286 
287  // (NO more segments) → exit
288  // break;
289  }
290  else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
291  {
292  NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
293  // Add txBuffer.FirstBuffer to DataField
294  dataFieldAddedSize = firstSegment->GetSize ();
295  dataFieldTotalSize += dataFieldAddedSize;
296  dataField.push_back (firstSegment);
297 
298  // ExtensionBit (Next_Segment - 1) = 1
299  rlcHeader.PushExtensionBit (LteRlcHeader::E_LI_FIELDS_FOLLOWS);
300 
301  // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
302  rlcHeader.PushLengthIndicator (firstSegment->GetSize ());
303 
304  nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
305  nextSegmentId++;
306 
307  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
308  if (m_txBuffer.size () > 0)
309  {
310  NS_LOG_LOGIC (" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
311  NS_LOG_LOGIC (" First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize ());
312  }
313  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
314  NS_LOG_LOGIC (" Remove SDU from TxBuffer");
315 
316  // (more segments)
317  firstSegment = m_txBuffer.begin ()->m_pdu->Copy ();
318  firstSegmentTime = m_txBuffer.begin ()->m_waitingSince;
319  m_txBufferSize -= firstSegment->GetSize ();
320  m_txBuffer.erase (m_txBuffer.begin ());
321  NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
322  }
323 
324  }
325 
326  // Build RLC header
327  rlcHeader.SetSequenceNumber (m_sequenceNumber++);
328 
329  // Build RLC PDU with DataField and Header
330  std::vector< Ptr<Packet> >::iterator it;
331  it = dataField.begin ();
332 
333  uint8_t framingInfo = 0;
334 
335  // FIRST SEGMENT
336  LteRlcSduStatusTag tag;
337  NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
338  (*it)->PeekPacketTag (tag);
339  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
341  {
342  framingInfo |= LteRlcHeader::FIRST_BYTE;
343  }
344  else
345  {
346  framingInfo |= LteRlcHeader::NO_FIRST_BYTE;
347  }
348 
349  while (it < dataField.end ())
350  {
351  NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ());
352 
353  NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
354  (*it)->RemovePacketTag (tag);
355  if (packet->GetSize () > 0)
356  {
357  packet->AddAtEnd (*it);
358  }
359  else
360  {
361  packet = (*it);
362  }
363  it++;
364  }
365 
366  // LAST SEGMENT (Note: There could be only one and be the first one)
367  it--;
368  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
370  {
371  framingInfo |= LteRlcHeader::LAST_BYTE;
372  }
373  else
374  {
375  framingInfo |= LteRlcHeader::NO_LAST_BYTE;
376  }
377 
378  rlcHeader.SetFramingInfo (framingInfo);
379 
380  NS_LOG_LOGIC ("RLC header: " << rlcHeader);
381  packet->AddHeader (rlcHeader);
382 
383  // Sender timestamp
384  RlcTag rlcTag (Simulator::Now ());
385  packet->AddByteTag (rlcTag, 1, rlcHeader.GetSerializedSize ());
386  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
387 
388  // Send RLC PDU to MAC layer
390  params.pdu = packet;
391  params.rnti = m_rnti;
392  params.lcid = m_lcid;
393  params.layer = txOpParams.layer;
394  params.harqProcessId = txOpParams.harqId;
395  params.componentCarrierId = txOpParams.componentCarrierId;
396 
397  m_macSapProvider->TransmitPdu (params);
398 
399  if (! m_txBuffer.empty ())
400  {
401  m_rbsTimer.Cancel ();
403  }
404 }
405 
406 void
408 {
409  NS_LOG_FUNCTION (this);
410 }
411 
412 void
414 {
415  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << rxPduParams.p->GetSize ());
416 
417  // Receiver timestamp
418  RlcTag rlcTag;
419  Time delay;
420 
421  bool ret = rxPduParams.p->FindFirstMatchingByteTag (rlcTag);
422  NS_ASSERT_MSG (ret, "RlcTag is missing");
423 
424  delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
425  m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), delay.GetNanoSeconds ());
426 
427  // 5.1.2.2 Receive operations
428 
429  // Get RLC header parameters
430  LteRlcHeader rlcHeader;
431  rxPduParams.p->PeekHeader (rlcHeader);
432  NS_LOG_LOGIC ("RLC header: " << rlcHeader);
433  SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber ();
434 
435  // 5.1.2.2.1 General
436  // The receiving UM RLC entity shall maintain a reordering window according to state variable VR(UH) as follows:
437  // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
438  // - a SN falls outside of the reordering window otherwise.
439  // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
440  // - either discard the received UMD PDU or place it in the reception buffer (see sub clause 5.1.2.2.2);
441  // - if the received UMD PDU was placed in the reception buffer:
442  // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop t-Reordering as needed (see sub clause 5.1.2.2.3);
443  // When t-Reordering expires, the receiving UM RLC entity shall:
444  // - update state variables, reassemble and deliver RLC SDUs to upper layer and start t-Reordering as needed (see sub clause 5.1.2.2.4).
445 
446  // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
447  // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
448  // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
449  // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
450  // - discard the received UMD PDU;
451  // - else:
452  // - place the received UMD PDU in the reception buffer.
453 
454  NS_LOG_LOGIC ("VR(UR) = " << m_vrUr);
455  NS_LOG_LOGIC ("VR(UX) = " << m_vrUx);
456  NS_LOG_LOGIC ("VR(UH) = " << m_vrUh);
457  NS_LOG_LOGIC ("SN = " << seqNumber);
458 
461  seqNumber.SetModulusBase (m_vrUh - m_windowSize);
462 
463  if ( ( (m_vrUr < seqNumber) && (seqNumber < m_vrUh) && (m_rxBuffer.count (seqNumber.GetValue ()) > 0) ) ||
464  ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr) )
465  )
466  {
467  NS_LOG_LOGIC ("PDU discarded");
468  rxPduParams.p = 0;
469  return;
470  }
471  else
472  {
473  NS_LOG_LOGIC ("Place PDU in the reception buffer");
474  m_rxBuffer[seqNumber.GetValue ()] = rxPduParams.p;
475  }
476 
477 
478  // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
479  // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity shall:
480 
481  // - if x falls outside of the reordering window:
482  // - update VR(UH) to x + 1;
483  // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering window, remove
484  // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in ascending order of the
485  // RLC SN if not delivered before;
486  // - if VR(UR) falls outside of the reordering window:
487  // - set VR(UR) to (VR(UH) - UM_Window_Size);
488 
489  if ( ! IsInsideReorderingWindow (seqNumber))
490  {
491  NS_LOG_LOGIC ("SN is outside the reordering window");
492 
493  m_vrUh = seqNumber + 1;
494  NS_LOG_LOGIC ("New VR(UH) = " << m_vrUh);
495 
497 
499  {
501  NS_LOG_LOGIC ("VR(UR) is outside the reordering window");
502  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
503  }
504  }
505 
506  // - if the reception buffer contains an UMD PDU with SN = VR(UR):
507  // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been received;
508  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing
509  // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered
510  // before;
511 
512  if ( m_rxBuffer.count (m_vrUr.GetValue ()) > 0 )
513  {
514  NS_LOG_LOGIC ("Reception buffer contains SN = " << m_vrUr);
515 
516  std::map <uint16_t, Ptr<Packet> >::iterator it;
517  uint16_t newVrUr;
518  SequenceNumber10 oldVrUr = m_vrUr;
519 
520  it = m_rxBuffer.find (m_vrUr.GetValue ());
521  newVrUr = (it->first) + 1;
522  while ( m_rxBuffer.count (newVrUr) > 0 )
523  {
524  newVrUr++;
525  }
526  m_vrUr = newVrUr;
527  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
528 
529  ReassembleSnInterval (oldVrUr, m_vrUr);
530  }
531 
532  // m_vrUh can change previously, set new modulus base
533  // for the t-Reordering timer-related comparisons
537 
538  // - if t-Reordering is running:
539  // - if VR(UX) <= VR(UR); or
540  // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
541  // - stop and reset t-Reordering;
542  if ( m_reorderingTimer.IsRunning () )
543  {
544  NS_LOG_LOGIC ("Reordering timer is running");
545 
546  if ( (m_vrUx <= m_vrUr) ||
547  ((! IsInsideReorderingWindow (m_vrUx)) && (m_vrUx != m_vrUh)) )
548  {
549  NS_LOG_LOGIC ("Stop reordering timer");
551  }
552  }
553 
554  // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to actions above):
555  // - if VR(UH) > VR(UR):
556  // - start t-Reordering;
557  // - set VR(UX) to VR(UH).
558  if ( ! m_reorderingTimer.IsRunning () )
559  {
560  NS_LOG_LOGIC ("Reordering timer is not running");
561 
562  if ( m_vrUh > m_vrUr )
563  {
564  NS_LOG_LOGIC ("VR(UH) > VR(UR)");
565  NS_LOG_LOGIC ("Start reordering timer");
568  m_vrUx = m_vrUh;
569  NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
570  }
571  }
572 
573 }
574 
575 
576 bool
578 {
579  NS_LOG_FUNCTION (this << seqNumber);
580  NS_LOG_LOGIC ("Reordering Window: " <<
581  m_vrUh << " - " << m_windowSize << " <= " << seqNumber << " < " << m_vrUh);
582 
584  seqNumber.SetModulusBase (m_vrUh - m_windowSize);
585 
586  if ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
587  {
588  NS_LOG_LOGIC (seqNumber << " is INSIDE the reordering window");
589  return true;
590  }
591  else
592  {
593  NS_LOG_LOGIC (seqNumber << " is OUTSIDE the reordering window");
594  return false;
595  }
596 }
597 
598 
599 void
601 {
602  LteRlcHeader rlcHeader;
603  packet->RemoveHeader (rlcHeader);
604  uint8_t framingInfo = rlcHeader.GetFramingInfo ();
605  SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber ();
606  bool expectedSnLost;
607 
608  if ( currSeqNumber != m_expectedSeqNumber )
609  {
610  expectedSnLost = true;
611  NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
612  m_expectedSeqNumber = currSeqNumber + 1;
613  }
614  else
615  {
616  expectedSnLost = false;
617  NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
619  }
620 
621  // Build list of SDUs
622  uint8_t extensionBit;
623  uint16_t lengthIndicator;
624  do
625  {
626  extensionBit = rlcHeader.PopExtensionBit ();
627  NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit);
628 
629  if ( extensionBit == 0 )
630  {
631  m_sdusBuffer.push_back (packet);
632  }
633  else // extensionBit == 1
634  {
635  lengthIndicator = rlcHeader.PopLengthIndicator ();
636  NS_LOG_LOGIC ("LI = " << lengthIndicator);
637 
638  // Check if there is enough data in the packet
639  if ( lengthIndicator >= packet->GetSize () )
640  {
641  NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator);
642  }
643 
644  // Split packet in two fragments
645  Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator);
646  packet->RemoveAtStart (lengthIndicator);
647 
648  m_sdusBuffer.push_back (data_field);
649  }
650  }
651  while ( extensionBit == 1 );
652 
653  std::list < Ptr<Packet> >::iterator it;
654 
655  // Current reassembling state
656  if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'");
657  else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'");
658  else NS_LOG_LOGIC ("Reassembling State = Unknown state");
659 
660  // Received framing Info
661  NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
662 
663  // Reassemble the list of SDUs (when there is no losses)
664  if (!expectedSnLost)
665  {
666  switch (m_reassemblingState)
667  {
668  case WAITING_S0_FULL:
669  switch (framingInfo)
670  {
673 
677  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
678  {
680  }
681  m_sdusBuffer.clear ();
682  break;
683 
686 
690  while ( m_sdusBuffer.size () > 1 )
691  {
693  m_sdusBuffer.pop_front ();
694  }
695 
699  m_keepS0 = m_sdusBuffer.front ();
700  m_sdusBuffer.pop_front ();
701  break;
702 
705 
709  m_sdusBuffer.pop_front ();
710 
714  while ( ! m_sdusBuffer.empty () )
715  {
717  m_sdusBuffer.pop_front ();
718  }
719  break;
720 
722  if ( m_sdusBuffer.size () == 1 )
723  {
725  }
726  else
727  {
729  }
730 
734  m_sdusBuffer.pop_front ();
735 
736  if ( m_sdusBuffer.size () > 0 )
737  {
741  while ( m_sdusBuffer.size () > 1 )
742  {
744  m_sdusBuffer.pop_front ();
745  }
746 
750  m_keepS0 = m_sdusBuffer.front ();
751  m_sdusBuffer.pop_front ();
752  }
753  break;
754 
755  default:
759  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
760  break;
761  }
762  break;
763 
764  case WAITING_SI_SF:
765  switch (framingInfo)
766  {
769 
773  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
774  m_sdusBuffer.pop_front ();
776 
780  while ( ! m_sdusBuffer.empty () )
781  {
783  m_sdusBuffer.pop_front ();
784  }
785  break;
786 
789 
793  if ( m_sdusBuffer.size () == 1 )
794  {
795  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
796  m_sdusBuffer.pop_front ();
797  }
798  else // m_sdusBuffer.size () > 1
799  {
803  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
804  m_sdusBuffer.pop_front ();
806 
810  while ( m_sdusBuffer.size () > 1 )
811  {
813  m_sdusBuffer.pop_front ();
814  }
815 
819  m_keepS0 = m_sdusBuffer.front ();
820  m_sdusBuffer.pop_front ();
821  }
822  break;
823 
826  default:
830  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
831  break;
832  }
833  break;
834 
835  default:
836  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
837  break;
838  }
839  }
840  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
841  {
842  switch (m_reassemblingState)
843  {
844  case WAITING_S0_FULL:
845  switch (framingInfo)
846  {
849 
853  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
854  {
856  }
857  m_sdusBuffer.clear ();
858  break;
859 
862 
866  while ( m_sdusBuffer.size () > 1 )
867  {
869  m_sdusBuffer.pop_front ();
870  }
871 
875  m_keepS0 = m_sdusBuffer.front ();
876  m_sdusBuffer.pop_front ();
877  break;
878 
881 
885  m_sdusBuffer.pop_front ();
886 
890  while ( ! m_sdusBuffer.empty () )
891  {
893  m_sdusBuffer.pop_front ();
894  }
895  break;
896 
898  if ( m_sdusBuffer.size () == 1 )
899  {
901  }
902  else
903  {
905  }
906 
910  m_sdusBuffer.pop_front ();
911 
912  if ( m_sdusBuffer.size () > 0 )
913  {
917  while ( m_sdusBuffer.size () > 1 )
918  {
920  m_sdusBuffer.pop_front ();
921  }
922 
926  m_keepS0 = m_sdusBuffer.front ();
927  m_sdusBuffer.pop_front ();
928  }
929  break;
930 
931  default:
935  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
936  break;
937  }
938  break;
939 
940  case WAITING_SI_SF:
941  switch (framingInfo)
942  {
945 
949  m_keepS0 = 0;
950 
954  while ( ! m_sdusBuffer.empty () )
955  {
957  m_sdusBuffer.pop_front ();
958  }
959  break;
960 
963 
967  m_keepS0 = 0;
968 
972  while ( m_sdusBuffer.size () > 1 )
973  {
975  m_sdusBuffer.pop_front ();
976  }
977 
981  m_keepS0 = m_sdusBuffer.front ();
982  m_sdusBuffer.pop_front ();
983 
984  break;
985 
988 
992  m_keepS0 = 0;
993 
997  m_sdusBuffer.pop_front ();
998 
1002  while ( ! m_sdusBuffer.empty () )
1003  {
1005  m_sdusBuffer.pop_front ();
1006  }
1007  break;
1008 
1010  if ( m_sdusBuffer.size () == 1 )
1011  {
1013  }
1014  else
1015  {
1017  }
1018 
1022  m_keepS0 = 0;
1023 
1027  m_sdusBuffer.pop_front ();
1028 
1029  if ( m_sdusBuffer.size () > 0 )
1030  {
1034  while ( m_sdusBuffer.size () > 1 )
1035  {
1037  m_sdusBuffer.pop_front ();
1038  }
1039 
1043  m_keepS0 = m_sdusBuffer.front ();
1044  m_sdusBuffer.pop_front ();
1045  }
1046  break;
1047 
1048  default:
1052  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1053  break;
1054  }
1055  break;
1056 
1057  default:
1058  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1059  break;
1060  }
1061  }
1062 
1063 }
1064 
1065 
1066 void
1068 {
1069  NS_LOG_LOGIC ("Reassemble Outside Window");
1070 
1071  std::map <uint16_t, Ptr<Packet> >::iterator it;
1072  it = m_rxBuffer.begin ();
1073 
1074  while ( (it != m_rxBuffer.end ()) && ! IsInsideReorderingWindow (SequenceNumber10 (it->first)) )
1075  {
1076  NS_LOG_LOGIC ("SN = " << it->first);
1077 
1078  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1079  ReassembleAndDeliver (it->second);
1080 
1081  std::map <uint16_t, Ptr<Packet> >::iterator it_tmp = it;
1082  ++it;
1083  m_rxBuffer.erase (it_tmp);
1084  }
1085 
1086  if (it != m_rxBuffer.end ())
1087  {
1088  NS_LOG_LOGIC ("(SN = " << it->first << ") is inside the reordering window");
1089  }
1090 }
1091 
1092 void
1094 {
1095  NS_LOG_LOGIC ("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1096 
1097  std::map <uint16_t, Ptr<Packet> >::iterator it;
1098 
1099  SequenceNumber10 reassembleSn = lowSeqNumber;
1100  NS_LOG_LOGIC ("reassembleSN = " << reassembleSn);
1101  NS_LOG_LOGIC ("highSeqNumber = " << highSeqNumber);
1102  while (reassembleSn < highSeqNumber)
1103  {
1104  NS_LOG_LOGIC ("reassembleSn < highSeqNumber");
1105  it = m_rxBuffer.find (reassembleSn.GetValue ());
1106  NS_LOG_LOGIC ("it->first = " << it->first);
1107  NS_LOG_LOGIC ("it->second = " << it->second);
1108  if (it != m_rxBuffer.end () )
1109  {
1110  NS_LOG_LOGIC ("SN = " << it->first);
1111 
1112  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1113  ReassembleAndDeliver (it->second);
1114 
1115  m_rxBuffer.erase (it);
1116  }
1117 
1118  reassembleSn++;
1119  }
1120 }
1121 
1122 
1123 void
1125 {
1126  Time holDelay (0);
1127  uint32_t queueSize = 0;
1128 
1129  if (! m_txBuffer.empty ())
1130  {
1131  holDelay = Simulator::Now () - m_txBuffer.front().m_waitingSince;
1132 
1133  queueSize = m_txBufferSize + 2 * m_txBuffer.size (); // Data in tx queue + estimated headers size
1134  }
1135 
1137  r.rnti = m_rnti;
1138  r.lcid = m_lcid;
1139  r.txQueueSize = queueSize;
1140  r.txQueueHolDelay = holDelay.GetMilliSeconds () ;
1141  r.retxQueueSize = 0;
1142  r.retxQueueHolDelay = 0;
1143  r.statusPduSize = 0;
1144 
1145  NS_LOG_LOGIC ("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay );
1147 }
1148 
1149 
1150 void
1152 {
1153  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid);
1154  NS_LOG_LOGIC ("Reordering timer has expired");
1155 
1156  // 5.1.2.2.4 Actions when t-Reordering expires
1157  // When t-Reordering expires, the receiving UM RLC entity shall:
1158  // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1159  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing so
1160  // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered before;
1161  // - if VR(UH) > VR(UR):
1162  // - start t-Reordering;
1163  // - set VR(UX) to VR(UH).
1164 
1165  std::map <uint16_t, Ptr<Packet> >::iterator it;
1166  SequenceNumber10 newVrUr = m_vrUx;
1167 
1168  while ( (it = m_rxBuffer.find (newVrUr.GetValue ())) != m_rxBuffer.end () )
1169  {
1170  newVrUr++;
1171  }
1172  SequenceNumber10 oldVrUr = m_vrUr;
1173  m_vrUr = newVrUr;
1174  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
1175 
1176  ReassembleSnInterval (oldVrUr, m_vrUr);
1177 
1178  if ( m_vrUh > m_vrUr)
1179  {
1180  NS_LOG_LOGIC ("Start reordering timer");
1183  m_vrUx = m_vrUh;
1184  NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
1185  }
1186 }
1187 
1188 
1189 void
1191 {
1192  NS_LOG_LOGIC ("RBS Timer expires");
1193 
1194  if (! m_txBuffer.empty ())
1195  {
1198  }
1199 }
1200 
1201 } // namespace ns3
uint32_t m_maxTxBufferSize
maximum transmit buffer status
Definition: lte-rlc-um.h:98
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:939
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
TracedCallback< uint16_t, uint8_t, uint32_t > m_txPdu
Used to inform of a PDU delivery to the MAC SAP provider.
Definition: lte-rlc.h:174
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
virtual uint32_t GetSerializedSize() const
Definition: lte-rlc-tag.cc:60
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Store an incoming (from layer above us) PDU, waiting to transmit it.
Definition: lte-rlc-um.h:103
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Parameters for LteMacSapUser::NotifyTxOpportunity.
Definition: lte-mac-sap.h:103
LTE RLC Unacknowledged Mode (UM), see 3GPP TS 36.322.
Definition: lte-rlc-um.h:35
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
virtual ~LteRlcUm()
Definition: lte-rlc-um.cc:49
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
#define min(a, b)
Definition: 80211b.c:42
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver function.
Definition: lte-rlc-um.cc:600
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-um.cc:1124
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1286
Time m_reorderingTimerValue
Timers.
Definition: lte-rlc-um.h:144
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
Definition: lte-mac-sap.h:73
virtual void DoTransmitPdcpPdu(Ptr< Packet > p)
RLC SAP.
Definition: lte-rlc-um.cc:90
std::vector< TxPdu > m_txBuffer
Transmission buffer.
Definition: lte-rlc-um.h:121
uint8_t PopExtensionBit(void)
Pop extension bit.
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:168
uint8_t m_lcid
LCID.
Definition: lte-rlc.h:169
virtual void DoNotifyHarqDeliveryFailure()
Notify HARQ delivery failure.
Definition: lte-rlc-um.cc:407
SequenceNumber10 m_vrUr
VR(UR)
Definition: lte-rlc-um.h:132
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:69
SequenceNumber10 m_sequenceNumber
State variables.
Definition: lte-rlc-um.h:130
void ReassembleSnInterval(SequenceNumber10 lowSeqNumber, SequenceNumber10 highSeqNumber)
Reassemble SN interval function.
Definition: lte-rlc-um.cc:1093
void SetModulusBase(SequenceNumber10 modulusBase)
Set modulus base.
The packet header for the Radio Link Control (RLC) protocol packets.
Parameters for LteMacSapProvider::ReportBufferStatus.
Definition: lte-mac-sap.h:67
virtual void DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams)
MAC SAP.
Definition: lte-rlc-um.cc:127
SequenceNumber10 m_vrUh
VR(UH)
Definition: lte-rlc-um.h:134
uint16_t txQueueHolDelay
the Head Of Line delay of the transmission queue
Definition: lte-mac-sap.h:72
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
uint16_t PopLengthIndicator(void)
Pop length indicator.
uint8_t GetStatus(void) const
Get status function.
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
Definition: lte-rlc.h:144
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-um.h:160
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
AttributeValue implementation for Time.
Definition: nstime.h:1342
static TypeId GetTypeId(void)
Get the type ID.
Definition: lte-rlc-um.cc:55
Hold an unsigned integer type.
Definition: uinteger.h:44
ReassemblingState_t m_reassemblingState
reassembling state
Definition: lte-rlc-um.h:154
uint8_t componentCarrierId
the component carrier id
Definition: lte-mac-sap.h:132
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...
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc.cc:122
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:166
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-um.h:155
Every class exported by the ns3 library is enclosed in the ns3 namespace.
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:391
SequenceNumber10 m_vrUx
VR(UX)
Definition: lte-rlc-um.h:133
uint16_t m_windowSize
Constants.
Definition: lte-rlc-um.h:139
void ExpireReorderingTimer(void)
Expire reordering timer.
Definition: lte-rlc-um.cc:1151
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: nstime.h:1343
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:70
uint32_t txQueueSize
the current size of the RLC transmission queue
Definition: lte-mac-sap.h:71
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
std::map< uint16_t, Ptr< Packet > > m_rxBuffer
Reception buffer.
Definition: lte-rlc-um.h:122
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-um.h:145
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
uint32_t bytes
the number of bytes to transmit
Definition: lte-mac-sap.h:129
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:75
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet.
Definition: lte-rlc-um.h:125
uint8_t layer
the layer of transmission (MIMO)
Definition: lte-mac-sap.h:130
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:383
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
void ReassembleOutsideWindow(void)
Reassemble outside window.
Definition: lte-rlc-um.cc:1067
bool IsInsideReorderingWindow(SequenceNumber10 seqNumber)
Is inside reordering window function.
Definition: lte-rlc-um.cc:577
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void SetStatus(uint8_t status)
Set status function.
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc-um.cc:76
uint16_t retxQueueHolDelay
the Head Of Line delay of the retransmission queue
Definition: lte-mac-sap.h:74
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
virtual void ReportBufferStatus(ReportBufferStatusParameters params)=0
Report the RLC buffer status to the MAC.
uint32_t m_txBufferSize
transmit buffer size
Definition: lte-rlc-um.h:99
Parameters for LteMacSapUser::ReceivePdu.
Definition: lte-mac-sap.h:156
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:472
virtual void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams)
Receive PDU function.
Definition: lte-rlc-um.cc:413
void ExpireRbsTimer(void)
Expire RBS timer.
Definition: lte-rlc-um.cc:1190
SequenceNumber10 class.
TracedCallback< uint16_t, uint8_t, uint32_t, uint64_t > m_rxPdu
Used to inform of a PDU reception from the MAC SAP user.
Definition: lte-rlc.h:178
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-um.h:146
uint8_t GetFramingInfo() const
Get framing info.
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: uinteger.h:45
This abstract base class defines the API to interact with the Radio Link Control (LTE_RLC) in LTE...
Definition: lte-rlc.h:50
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:912
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
Ptr< Packet > p
the RLC PDU to be received
Definition: lte-mac-sap.h:175
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:45