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  ;
67  return tid;
68 }
69 
70 void
72 {
73  NS_LOG_FUNCTION (this);
75  m_rbsTimer.Cancel ();
76 
78 }
79 
84 void
86 {
87  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
88 
90  {
92  RlcTag timeTag (Simulator::Now ());
93  p->AddPacketTag (timeTag);
94 
99  p->AddPacketTag (tag);
100 
101  NS_LOG_LOGIC ("Tx Buffer: New packet added");
102  m_txBuffer.push_back (p);
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
127 LteRlcUm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer, uint8_t harqId)
128 {
129  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << bytes);
130 
131  if (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 = " << bytes);
135  return;
136  }
137 
138  Ptr<Packet> packet = Create<Packet> ();
139  LteRlcHeader rlcHeader;
140 
141  // Build Data field
142  uint32_t nextSegmentSize = 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  NS_LOG_LOGIC ("SDUs in TxBuffer = " << m_txBuffer.size ());
157  NS_LOG_LOGIC ("First SDU buffer = " << *(m_txBuffer.begin()));
158  NS_LOG_LOGIC ("First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
159  NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
160  NS_LOG_LOGIC ("Remove SDU from TxBuffer");
161  Ptr<Packet> firstSegment = (*(m_txBuffer.begin ()))->Copy ();
162  m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
163  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize );
164  m_txBuffer.erase (m_txBuffer.begin ());
165 
166  while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
167  {
168  NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
169  NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
170  NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
171  if ( (firstSegment->GetSize () > nextSegmentSize) ||
172  // Segment larger than 2047 octets can only be mapped to the end of the Data field
173  (firstSegment->GetSize () > 2047)
174  )
175  {
176  // Take the minimum size, due to the 2047-bytes 3GPP exception
177  // This exception is due to the length of the LI field (just 11 bits)
178  uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
179 
180  NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
181  NS_LOG_LOGIC (" firstSegment > 2047 )");
182 
183  // Segment txBuffer.FirstBuffer and
184  // Give back the remaining segment to the transmission buffer
185  Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
186  NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
187 
188  // Status tag of the new and remaining segments
189  // Note: This is the only place where a PDU is segmented and
190  // therefore its status can change
191  LteRlcSduStatusTag oldTag, newTag;
192  firstSegment->RemovePacketTag (oldTag);
193  newSegment->RemovePacketTag (newTag);
194  if (oldTag.GetStatus () == LteRlcSduStatusTag::FULL_SDU)
195  {
196  newTag.SetStatus (LteRlcSduStatusTag::FIRST_SEGMENT);
197  oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
198  }
199  else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT)
200  {
201  newTag.SetStatus (LteRlcSduStatusTag::MIDDLE_SEGMENT);
202  //oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
203  }
204 
205  // Give back the remaining segment to the transmission buffer
206  firstSegment->RemoveAtStart (currSegmentSize);
207  NS_LOG_LOGIC (" firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize ());
208  if (firstSegment->GetSize () > 0)
209  {
210  firstSegment->AddPacketTag (oldTag);
211 
212  m_txBuffer.insert (m_txBuffer.begin (), firstSegment);
213  m_txBufferSize += (*(m_txBuffer.begin()))->GetSize ();
214 
215  NS_LOG_LOGIC (" TX buffer: Give back the remaining segment");
216  NS_LOG_LOGIC (" TX buffers = " << m_txBuffer.size ());
217  NS_LOG_LOGIC (" Front buffer size = " << (*(m_txBuffer.begin()))->GetSize ());
218  NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
219  }
220  else
221  {
222  // Whole segment was taken, so adjust tag
223  if (newTag.GetStatus () == LteRlcSduStatusTag::FIRST_SEGMENT)
224  {
225  newTag.SetStatus (LteRlcSduStatusTag::FULL_SDU);
226  }
227  else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
228  {
229  newTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
230  }
231  }
232  // Segment is completely taken or
233  // the remaining segment is given back to the transmission buffer
234  firstSegment = 0;
235 
236  // Put status tag once it has been adjusted
237  newSegment->AddPacketTag (newTag);
238 
239  // Add Segment to Data field
240  dataFieldAddedSize = newSegment->GetSize ();
241  dataFieldTotalSize += dataFieldAddedSize;
242  dataField.push_back (newSegment);
243  newSegment = 0;
244 
245  // ExtensionBit (Next_Segment - 1) = 0
246  rlcHeader.PushExtensionBit (LteRlcHeader::DATA_FIELD_FOLLOWS);
247 
248  // no LengthIndicator for the last one
249 
250  nextSegmentSize -= dataFieldAddedSize;
251  nextSegmentId++;
252 
253  // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
254 
255  // (NO more segments) → exit
256  // break;
257  }
258  else if ( (nextSegmentSize - firstSegment->GetSize () <= 2) || (m_txBuffer.size () == 0) )
259  {
260  NS_LOG_LOGIC (" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
261  // Add txBuffer.FirstBuffer to DataField
262  dataFieldAddedSize = firstSegment->GetSize ();
263  dataFieldTotalSize += dataFieldAddedSize;
264  dataField.push_back (firstSegment);
265  firstSegment = 0;
266 
267  // ExtensionBit (Next_Segment - 1) = 0
268  rlcHeader.PushExtensionBit (LteRlcHeader::DATA_FIELD_FOLLOWS);
269 
270  // no LengthIndicator for the last one
271 
272  nextSegmentSize -= dataFieldAddedSize;
273  nextSegmentId++;
274 
275  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
276  if (m_txBuffer.size () > 0)
277  {
278  NS_LOG_LOGIC (" First SDU buffer = " << *(m_txBuffer.begin()));
279  NS_LOG_LOGIC (" First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
280  }
281  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
282 
283  // nextSegmentSize <= 2 (only if txBuffer is not empty)
284 
285  // (NO more segments) → exit
286  // break;
287  }
288  else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
289  {
290  NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
291  // Add txBuffer.FirstBuffer to DataField
292  dataFieldAddedSize = firstSegment->GetSize ();
293  dataFieldTotalSize += dataFieldAddedSize;
294  dataField.push_back (firstSegment);
295 
296  // ExtensionBit (Next_Segment - 1) = 1
297  rlcHeader.PushExtensionBit (LteRlcHeader::E_LI_FIELDS_FOLLOWS);
298 
299  // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
300  rlcHeader.PushLengthIndicator (firstSegment->GetSize ());
301 
302  nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
303  nextSegmentId++;
304 
305  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
306  if (m_txBuffer.size () > 0)
307  {
308  NS_LOG_LOGIC (" First SDU buffer = " << *(m_txBuffer.begin()));
309  NS_LOG_LOGIC (" First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
310  }
311  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
312  NS_LOG_LOGIC (" Remove SDU from TxBuffer");
313 
314  // (more segments)
315  firstSegment = (*(m_txBuffer.begin ()))->Copy ();
316  m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
317  m_txBuffer.erase (m_txBuffer.begin ());
318  NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
319  }
320 
321  }
322 
323  // Build RLC header
324  rlcHeader.SetSequenceNumber (m_sequenceNumber++);
325 
326  // Build RLC PDU with DataField and Header
327  std::vector< Ptr<Packet> >::iterator it;
328  it = dataField.begin ();
329 
330  uint8_t framingInfo = 0;
331 
332  // FIRST SEGMENT
333  LteRlcSduStatusTag tag;
334  NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
335  (*it)->PeekPacketTag (tag);
336  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
338  {
339  framingInfo |= LteRlcHeader::FIRST_BYTE;
340  }
341  else
342  {
343  framingInfo |= LteRlcHeader::NO_FIRST_BYTE;
344  }
345 
346  while (it < dataField.end ())
347  {
348  NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ());
349 
350  NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
351  (*it)->RemovePacketTag (tag);
352  if (packet->GetSize () > 0)
353  {
354  packet->AddAtEnd (*it);
355  }
356  else
357  {
358  packet = (*it);
359  }
360  it++;
361  }
362 
363  // LAST SEGMENT (Note: There could be only one and be the first one)
364  it--;
365  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
367  {
368  framingInfo |= LteRlcHeader::LAST_BYTE;
369  }
370  else
371  {
372  framingInfo |= LteRlcHeader::NO_LAST_BYTE;
373  }
374 
375  rlcHeader.SetFramingInfo (framingInfo);
376 
377  NS_LOG_LOGIC ("RLC header: " << rlcHeader);
378  packet->AddHeader (rlcHeader);
379 
380  // Sender timestamp
381  RlcTag rlcTag (Simulator::Now ());
382  packet->ReplacePacketTag (rlcTag);
383  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
384 
385  // Send RLC PDU to MAC layer
387  params.pdu = packet;
388  params.rnti = m_rnti;
389  params.lcid = m_lcid;
390  params.layer = layer;
391  params.harqProcessId = harqId;
392 
393  m_macSapProvider->TransmitPdu (params);
394 
395  if (! m_txBuffer.empty ())
396  {
397  m_rbsTimer.Cancel ();
399  }
400 }
401 
402 void
404 {
405  NS_LOG_FUNCTION (this);
406 }
407 
408 void
410 {
411  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
412 
413  // Receiver timestamp
414  RlcTag rlcTag;
415  Time delay;
416  NS_ASSERT_MSG (p->PeekPacketTag (rlcTag), "RlcTag is missing");
417  p->RemovePacketTag (rlcTag);
418  delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
419  m_rxPdu (m_rnti, m_lcid, p->GetSize (), delay.GetNanoSeconds ());
420 
421  // 5.1.2.2 Receive operations
422 
423  // Get RLC header parameters
424  LteRlcHeader rlcHeader;
425  p->PeekHeader (rlcHeader);
426  NS_LOG_LOGIC ("RLC header: " << rlcHeader);
427  SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber ();
428 
429  // 5.1.2.2.1 General
430  // The receiving UM RLC entity shall maintain a reordering window according to state variable VR(UH) as follows:
431  // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
432  // - a SN falls outside of the reordering window otherwise.
433  // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
434  // - either discard the received UMD PDU or place it in the reception buffer (see sub clause 5.1.2.2.2);
435  // - if the received UMD PDU was placed in the reception buffer:
436  // - 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);
437  // When t-Reordering expires, the receiving UM RLC entity shall:
438  // - 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).
439 
440  // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
441  // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
442  // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
443  // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
444  // - discard the received UMD PDU;
445  // - else:
446  // - place the received UMD PDU in the reception buffer.
447 
448  NS_LOG_LOGIC ("VR(UR) = " << m_vrUr);
449  NS_LOG_LOGIC ("VR(UX) = " << m_vrUx);
450  NS_LOG_LOGIC ("VR(UH) = " << m_vrUh);
451  NS_LOG_LOGIC ("SN = " << seqNumber);
452 
455  seqNumber.SetModulusBase (m_vrUh - m_windowSize);
456 
457  if ( ( (m_vrUr < seqNumber) && (seqNumber < m_vrUh) && (m_rxBuffer.count (seqNumber.GetValue ()) > 0) ) ||
458  ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr) )
459  )
460  {
461  NS_LOG_LOGIC ("PDU discarded");
462  p = 0;
463  return;
464  }
465  else
466  {
467  NS_LOG_LOGIC ("Place PDU in the reception buffer");
468  m_rxBuffer[seqNumber.GetValue ()] = p;
469  }
470 
471 
472  // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
473  // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity shall:
474 
475  // - if x falls outside of the reordering window:
476  // - update VR(UH) to x + 1;
477  // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering window, remove
478  // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in ascending order of the
479  // RLC SN if not delivered before;
480  // - if VR(UR) falls outside of the reordering window:
481  // - set VR(UR) to (VR(UH) - UM_Window_Size);
482 
483  if ( ! IsInsideReorderingWindow (seqNumber))
484  {
485  NS_LOG_LOGIC ("SN is outside the reordering window");
486 
487  m_vrUh = seqNumber + 1;
488  NS_LOG_LOGIC ("New VR(UH) = " << m_vrUh);
489 
491 
493  {
495  NS_LOG_LOGIC ("VR(UR) is outside the reordering window");
496  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
497  }
498  }
499 
500  // - if the reception buffer contains an UMD PDU with SN = VR(UR):
501  // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been received;
502  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing
503  // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered
504  // before;
505 
506  if ( m_rxBuffer.count (m_vrUr.GetValue ()) > 0 )
507  {
508  NS_LOG_LOGIC ("Reception buffer contains SN = " << m_vrUr);
509 
510  std::map <uint16_t, Ptr<Packet> >::iterator it;
511  uint16_t newVrUr;
512  SequenceNumber10 oldVrUr = m_vrUr;
513 
514  it = m_rxBuffer.find (m_vrUr.GetValue ());
515  newVrUr = (it->first) + 1;
516  while ( m_rxBuffer.count (newVrUr) > 0 )
517  {
518  newVrUr++;
519  }
520  m_vrUr = newVrUr;
521  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
522 
523  ReassembleSnInterval (oldVrUr, m_vrUr);
524  }
525 
526  // m_vrUh can change previously, set new modulus base
527  // for the t-Reordering timer-related comparisons
531 
532  // - if t-Reordering is running:
533  // - if VR(UX) <= VR(UR); or
534  // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
535  // - stop and reset t-Reordering;
536  if ( m_reorderingTimer.IsRunning () )
537  {
538  NS_LOG_LOGIC ("Reordering timer is running");
539 
540  if ( (m_vrUx <= m_vrUr) ||
541  ((! IsInsideReorderingWindow (m_vrUx)) && (m_vrUx != m_vrUh)) )
542  {
543  NS_LOG_LOGIC ("Stop reordering timer");
545  }
546  }
547 
548  // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to actions above):
549  // - if VR(UH) > VR(UR):
550  // - start t-Reordering;
551  // - set VR(UX) to VR(UH).
552  if ( ! m_reorderingTimer.IsRunning () )
553  {
554  NS_LOG_LOGIC ("Reordering timer is not running");
555 
556  if ( m_vrUh > m_vrUr )
557  {
558  NS_LOG_LOGIC ("VR(UH) > VR(UR)");
559  NS_LOG_LOGIC ("Start reordering timer");
562  m_vrUx = m_vrUh;
563  NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
564  }
565  }
566 
567 }
568 
569 
570 bool
572 {
573  NS_LOG_FUNCTION (this << seqNumber);
574  NS_LOG_LOGIC ("Reordering Window: " <<
575  m_vrUh << " - " << m_windowSize << " <= " << seqNumber << " < " << m_vrUh);
576 
578  seqNumber.SetModulusBase (m_vrUh - m_windowSize);
579 
580  if ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
581  {
582  NS_LOG_LOGIC (seqNumber << " is INSIDE the reordering window");
583  return true;
584  }
585  else
586  {
587  NS_LOG_LOGIC (seqNumber << " is OUTSIDE the reordering window");
588  return false;
589  }
590 }
591 
592 
593 void
595 {
596  LteRlcHeader rlcHeader;
597  packet->RemoveHeader (rlcHeader);
598  uint8_t framingInfo = rlcHeader.GetFramingInfo ();
599  SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber ();
600  bool expectedSnLost;
601 
602  if ( currSeqNumber != m_expectedSeqNumber )
603  {
604  expectedSnLost = true;
605  NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
606  m_expectedSeqNumber = currSeqNumber + 1;
607  }
608  else
609  {
610  expectedSnLost = false;
611  NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
613  }
614 
615  // Build list of SDUs
616  uint8_t extensionBit;
617  uint16_t lengthIndicator;
618  do
619  {
620  extensionBit = rlcHeader.PopExtensionBit ();
621  NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit);
622 
623  if ( extensionBit == 0 )
624  {
625  m_sdusBuffer.push_back (packet);
626  }
627  else // extensionBit == 1
628  {
629  lengthIndicator = rlcHeader.PopLengthIndicator ();
630  NS_LOG_LOGIC ("LI = " << lengthIndicator);
631 
632  // Check if there is enough data in the packet
633  if ( lengthIndicator >= packet->GetSize () )
634  {
635  NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator);
636  }
637 
638  // Split packet in two fragments
639  Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator);
640  packet->RemoveAtStart (lengthIndicator);
641 
642  m_sdusBuffer.push_back (data_field);
643  }
644  }
645  while ( extensionBit == 1 );
646 
647  std::list < Ptr<Packet> >::iterator it;
648 
649  // Current reassembling state
650  if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'");
651  else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'");
652  else NS_LOG_LOGIC ("Reassembling State = Unknown state");
653 
654  // Received framing Info
655  NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
656 
657  // Reassemble the list of SDUs (when there is no losses)
658  if (!expectedSnLost)
659  {
660  switch (m_reassemblingState)
661  {
662  case WAITING_S0_FULL:
663  switch (framingInfo)
664  {
667 
671  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
672  {
674  }
675  m_sdusBuffer.clear ();
676  break;
677 
680 
684  while ( m_sdusBuffer.size () > 1 )
685  {
687  m_sdusBuffer.pop_front ();
688  }
689 
693  m_keepS0 = m_sdusBuffer.front ();
694  m_sdusBuffer.pop_front ();
695  break;
696 
699 
703  m_sdusBuffer.pop_front ();
704 
708  while ( ! m_sdusBuffer.empty () )
709  {
711  m_sdusBuffer.pop_front ();
712  }
713  break;
714 
716  if ( m_sdusBuffer.size () == 1 )
717  {
719  }
720  else
721  {
723  }
724 
728  m_sdusBuffer.pop_front ();
729 
730  if ( m_sdusBuffer.size () > 0 )
731  {
735  while ( m_sdusBuffer.size () > 1 )
736  {
738  m_sdusBuffer.pop_front ();
739  }
740 
744  m_keepS0 = m_sdusBuffer.front ();
745  m_sdusBuffer.pop_front ();
746  }
747  break;
748 
749  default:
753  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
754  break;
755  }
756  break;
757 
758  case WAITING_SI_SF:
759  switch (framingInfo)
760  {
763 
767  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
768  m_sdusBuffer.pop_front ();
770 
774  while ( ! m_sdusBuffer.empty () )
775  {
777  m_sdusBuffer.pop_front ();
778  }
779  break;
780 
783 
787  if ( m_sdusBuffer.size () == 1 )
788  {
789  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
790  m_sdusBuffer.pop_front ();
791  }
792  else // m_sdusBuffer.size () > 1
793  {
797  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
798  m_sdusBuffer.pop_front ();
800 
804  while ( m_sdusBuffer.size () > 1 )
805  {
807  m_sdusBuffer.pop_front ();
808  }
809 
813  m_keepS0 = m_sdusBuffer.front ();
814  m_sdusBuffer.pop_front ();
815  }
816  break;
817 
820  default:
824  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
825  break;
826  }
827  break;
828 
829  default:
830  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
831  break;
832  }
833  }
834  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
835  {
836  switch (m_reassemblingState)
837  {
838  case WAITING_S0_FULL:
839  switch (framingInfo)
840  {
843 
847  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
848  {
850  }
851  m_sdusBuffer.clear ();
852  break;
853 
856 
860  while ( m_sdusBuffer.size () > 1 )
861  {
863  m_sdusBuffer.pop_front ();
864  }
865 
869  m_keepS0 = m_sdusBuffer.front ();
870  m_sdusBuffer.pop_front ();
871  break;
872 
875 
879  m_sdusBuffer.pop_front ();
880 
884  while ( ! m_sdusBuffer.empty () )
885  {
887  m_sdusBuffer.pop_front ();
888  }
889  break;
890 
892  if ( m_sdusBuffer.size () == 1 )
893  {
895  }
896  else
897  {
899  }
900 
904  m_sdusBuffer.pop_front ();
905 
906  if ( m_sdusBuffer.size () > 0 )
907  {
911  while ( m_sdusBuffer.size () > 1 )
912  {
914  m_sdusBuffer.pop_front ();
915  }
916 
920  m_keepS0 = m_sdusBuffer.front ();
921  m_sdusBuffer.pop_front ();
922  }
923  break;
924 
925  default:
929  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
930  break;
931  }
932  break;
933 
934  case WAITING_SI_SF:
935  switch (framingInfo)
936  {
939 
943  m_keepS0 = 0;
944 
948  while ( ! m_sdusBuffer.empty () )
949  {
951  m_sdusBuffer.pop_front ();
952  }
953  break;
954 
957 
961  m_keepS0 = 0;
962 
966  while ( m_sdusBuffer.size () > 1 )
967  {
969  m_sdusBuffer.pop_front ();
970  }
971 
975  m_keepS0 = m_sdusBuffer.front ();
976  m_sdusBuffer.pop_front ();
977 
978  break;
979 
982 
986  m_keepS0 = 0;
987 
991  m_sdusBuffer.pop_front ();
992 
996  while ( ! m_sdusBuffer.empty () )
997  {
999  m_sdusBuffer.pop_front ();
1000  }
1001  break;
1002 
1004  if ( m_sdusBuffer.size () == 1 )
1005  {
1007  }
1008  else
1009  {
1011  }
1012 
1016  m_keepS0 = 0;
1017 
1021  m_sdusBuffer.pop_front ();
1022 
1023  if ( m_sdusBuffer.size () > 0 )
1024  {
1028  while ( m_sdusBuffer.size () > 1 )
1029  {
1031  m_sdusBuffer.pop_front ();
1032  }
1033 
1037  m_keepS0 = m_sdusBuffer.front ();
1038  m_sdusBuffer.pop_front ();
1039  }
1040  break;
1041 
1042  default:
1046  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1047  break;
1048  }
1049  break;
1050 
1051  default:
1052  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1053  break;
1054  }
1055  }
1056 
1057 }
1058 
1059 
1060 void
1062 {
1063  NS_LOG_LOGIC ("Reassemble Outside Window");
1064 
1065  std::map <uint16_t, Ptr<Packet> >::iterator it;
1066  it = m_rxBuffer.begin ();
1067 
1068  while ( (it != m_rxBuffer.end ()) && ! IsInsideReorderingWindow (SequenceNumber10 (it->first)) )
1069  {
1070  NS_LOG_LOGIC ("SN = " << it->first);
1071 
1072  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1073  ReassembleAndDeliver (it->second);
1074 
1075  std::map <uint16_t, Ptr<Packet> >::iterator it_tmp = it;
1076  ++it;
1077  m_rxBuffer.erase (it_tmp);
1078  }
1079 
1080  if (it != m_rxBuffer.end ())
1081  {
1082  NS_LOG_LOGIC ("(SN = " << it->first << ") is inside the reordering window");
1083  }
1084 }
1085 
1086 void
1088 {
1089  NS_LOG_LOGIC ("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1090 
1091  std::map <uint16_t, Ptr<Packet> >::iterator it;
1092 
1093  SequenceNumber10 reassembleSn = lowSeqNumber;
1094  NS_LOG_LOGIC ("reassembleSN = " << reassembleSn);
1095  NS_LOG_LOGIC ("highSeqNumber = " << highSeqNumber);
1096  while (reassembleSn < highSeqNumber)
1097  {
1098  NS_LOG_LOGIC ("reassembleSn < highSeqNumber");
1099  it = m_rxBuffer.find (reassembleSn.GetValue ());
1100  NS_LOG_LOGIC ("it->first = " << it->first);
1101  NS_LOG_LOGIC ("it->second = " << it->second);
1102  if (it != m_rxBuffer.end () )
1103  {
1104  NS_LOG_LOGIC ("SN = " << it->first);
1105 
1106  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1107  ReassembleAndDeliver (it->second);
1108 
1109  m_rxBuffer.erase (it);
1110  }
1111 
1112  reassembleSn++;
1113  }
1114 }
1115 
1116 
1117 void
1119 {
1120  Time holDelay (0);
1121  uint32_t queueSize = 0;
1122 
1123  if (! m_txBuffer.empty ())
1124  {
1125  RlcTag holTimeTag;
1126  NS_ASSERT_MSG (m_txBuffer.front ()->PeekPacketTag (holTimeTag), "RlcTag is missing");
1127  m_txBuffer.front ()->PeekPacketTag (holTimeTag);
1128  holDelay = Simulator::Now () - holTimeTag.GetSenderTimestamp ();
1129 
1130  queueSize = m_txBufferSize + 2 * m_txBuffer.size (); // Data in tx queue + estimated headers size
1131  }
1132 
1134  r.rnti = m_rnti;
1135  r.lcid = m_lcid;
1136  r.txQueueSize = queueSize;
1137  r.txQueueHolDelay = holDelay.GetMilliSeconds () ;
1138  r.retxQueueSize = 0;
1139  r.retxQueueHolDelay = 0;
1140  r.statusPduSize = 0;
1141 
1142  NS_LOG_LOGIC ("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay );
1144 }
1145 
1146 
1147 void
1149 {
1150  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid);
1151  NS_LOG_LOGIC ("Reordering timer has expired");
1152 
1153  // 5.1.2.2.4 Actions when t-Reordering expires
1154  // When t-Reordering expires, the receiving UM RLC entity shall:
1155  // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1156  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing so
1157  // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered before;
1158  // - if VR(UH) > VR(UR):
1159  // - start t-Reordering;
1160  // - set VR(UX) to VR(UH).
1161 
1162  std::map <uint16_t, Ptr<Packet> >::iterator it;
1163  SequenceNumber10 newVrUr = m_vrUx;
1164 
1165  while ( (it = m_rxBuffer.find (newVrUr.GetValue ())) != m_rxBuffer.end () )
1166  {
1167  newVrUr++;
1168  }
1169  SequenceNumber10 oldVrUr = m_vrUr;
1170  m_vrUr = newVrUr;
1171  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
1172 
1173  ReassembleSnInterval (oldVrUr, m_vrUr);
1174 
1175  if ( m_vrUh > m_vrUr)
1176  {
1177  NS_LOG_LOGIC ("Start reordering timer");
1180  m_vrUx = m_vrUh;
1181  NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
1182  }
1183 }
1184 
1185 
1186 void
1188 {
1189  NS_LOG_LOGIC ("RBS Timer expires");
1190 
1191  if (! m_txBuffer.empty ())
1192  {
1195  }
1196 }
1197 
1198 } // namespace ns3
uint32_t m_maxTxBufferSize
Definition: lte-rlc-um.h:69
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:150
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
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:44
#define min(a, b)
Definition: 80211b.c:44
void ReassembleAndDeliver(Ptr< Packet > packet)
Definition: lte-rlc-um.cc:594
void DoReportBufferStatus()
Definition: lte-rlc-um.cc:1118
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:824
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:903
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:792
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
Definition: lte-mac-sap.h:72
virtual void DoTransmitPdcpPdu(Ptr< Packet > p)
RLC SAP.
Definition: lte-rlc-um.cc:85
uint8_t PopExtensionBit(void)
uint16_t m_rnti
Definition: lte-rlc.h:144
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
uint8_t m_lcid
Definition: lte-rlc.h:145
virtual void DoNotifyHarqDeliveryFailure()
Definition: lte-rlc-um.cc:403
SequenceNumber10 m_vrUr
Definition: lte-rlc-um.h:82
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:68
SequenceNumber10 m_sequenceNumber
State variables.
Definition: lte-rlc-um.h:80
void ReassembleSnInterval(SequenceNumber10 lowSeqNumber, SequenceNumber10 highSeqNumber)
Definition: lte-rlc-um.cc:1087
void SetModulusBase(SequenceNumber10 modulusBase)
The packet header for the Radio Link Control (RLC) protocol packets.
Parameters for LteMacSapProvider::ReportBufferStatus.
Definition: lte-mac-sap.h:66
SequenceNumber10 m_vrUh
Definition: lte-rlc-um.h:84
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
virtual void DoReceivePdu(Ptr< Packet > p)
Definition: lte-rlc-um.cc:409
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:313
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:846
uint16_t PopLengthIndicator(void)
LteRlcSapUser * m_rlcSapUser
Definition: lte-rlc.h:133
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-um.h:109
std::vector< Ptr< Packet > > m_txBuffer
Definition: lte-rlc-um.h:71
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:340
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1238
virtual void DoNotifyTxOpportunity(uint32_t bytes, uint8_t layer, uint8_t harqId)
MAC SAP.
Definition: lte-rlc-um.cc:127
static TypeId GetTypeId(void)
Definition: lte-rlc-um.cc:55
Hold an unsigned integer type.
Definition: uinteger.h:44
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:838
ReassemblingState_t m_reassemblingState
Definition: lte-rlc-um.h:103
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
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc.cc:119
LteMacSapProvider * m_macSapProvider
Definition: lte-rlc.h:142
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
Ptr< Packet > m_keepS0
Definition: lte-rlc-um.h:104
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:122
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:278
Every class exported by the ns3 library is enclosed in the ns3 namespace.
SequenceNumber10 m_vrUx
Definition: lte-rlc-um.h:83
uint16_t m_windowSize
Constants.
Definition: lte-rlc-um.h:89
void ExpireReorderingTimer(void)
Definition: lte-rlc-um.cc:1148
Time GetSenderTimestamp(void) const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Definition: lte-rlc-tag.h:60
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:69
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 virtual time.
Definition: simulator.cc:224
std::map< uint16_t, Ptr< Packet > > m_rxBuffer
Definition: lte-rlc-um.h:72
EventId m_reorderingTimer
Timers.
Definition: lte-rlc-um.h:94
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:90
int64_t GetNanoSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:353
SequenceNumber10 GetSequenceNumber() const
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:74
std::list< Ptr< Packet > > m_sdusBuffer
Definition: lte-rlc-um.h:75
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
uint8_t GetFramingInfo() const
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:831
void ReassembleOutsideWindow(void)
Definition: lte-rlc-um.cc:1061
bool IsInsideReorderingWindow(SequenceNumber10 seqNumber)
Definition: lte-rlc-um.cc:571
void SetStatus(uint8_t status)
virtual void DoDispose()
Destructor implementation.
Definition: lte-rlc-um.cc:71
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:53
virtual void ReportBufferStatus(ReportBufferStatusParameters params)=0
Report the RLC buffer status to the MAC.
uint32_t m_txBufferSize
Definition: lte-rlc-um.h:70
void ExpireRbsTimer(void)
Definition: lte-rlc-um.cc:1187
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:154
EventId m_rbsTimer
Definition: lte-rlc-um.h:95
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
int64_t GetMilliSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:345
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:904
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:257
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:45