A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 NS_LOG_COMPONENT_DEFINE ("LteRlcUm");
30 
31 namespace ns3 {
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  .AddConstructor<LteRlcUm> ()
60  .AddAttribute ("MaxTxBufferSize",
61  "Maximum Size of the Transmission Buffer (in Bytes)",
62  UintegerValue (10 * 1024),
63  MakeUintegerAccessor (&LteRlcUm::m_maxTxBufferSize),
64  MakeUintegerChecker<uint32_t> ())
65  ;
66  return tid;
67 }
68 
69 void
71 {
72  NS_LOG_FUNCTION (this);
74  m_rbsTimer.Cancel ();
75 
77 }
78 
83 void
85 {
86  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
87 
89  {
91  RlcTag timeTag (Simulator::Now ());
92  p->AddPacketTag (timeTag);
93 
98  p->AddPacketTag (tag);
99 
100  NS_LOG_LOGIC ("Tx Buffer: New packet added");
101  m_txBuffer.push_back (p);
102  m_txBufferSize += p->GetSize ();
103  NS_LOG_LOGIC ("NumOfBuffers = " << m_txBuffer.size() );
104  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
105  }
106  else
107  {
108  // Discard full RLC SDU
109  NS_LOG_LOGIC ("TxBuffer is full. RLC SDU discarded");
110  NS_LOG_LOGIC ("MaxTxBufferSize = " << m_maxTxBufferSize);
111  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
112  NS_LOG_LOGIC ("packet size = " << p->GetSize ());
113  }
114 
117  m_rbsTimer.Cancel ();
118 }
119 
120 
125 void
126 LteRlcUm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer, uint8_t harqId)
127 {
128  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << bytes);
129 
130  if (bytes <= 2)
131  {
132  // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
133  NS_LOG_LOGIC ("TX opportunity too small = " << bytes);
134  return;
135  }
136 
137  Ptr<Packet> packet = Create<Packet> ();
138  LteRlcHeader rlcHeader;
139 
140  // Build Data field
141  uint32_t nextSegmentSize = bytes - 2;
142  uint32_t nextSegmentId = 1;
143  uint32_t dataFieldTotalSize = 0;
144  uint32_t dataFieldAddedSize = 0;
145  std::vector < Ptr<Packet> > dataField;
146 
147  // Remove the first packet from the transmission buffer.
148  // If only a segment of the packet is taken, then the remaining is given back later
149  if ( m_txBuffer.size () == 0 )
150  {
151  NS_LOG_LOGIC ("No data pending");
152  return;
153  }
154 
155  NS_LOG_LOGIC ("SDUs in TxBuffer = " << m_txBuffer.size ());
156  NS_LOG_LOGIC ("First SDU buffer = " << *(m_txBuffer.begin()));
157  NS_LOG_LOGIC ("First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
158  NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
159  NS_LOG_LOGIC ("Remove SDU from TxBuffer");
160  Ptr<Packet> firstSegment = (*(m_txBuffer.begin ()))->Copy ();
161  m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
162  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize );
163  m_txBuffer.erase (m_txBuffer.begin ());
164 
165  while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
166  {
167  NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
168  NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
169  NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
170  if ( (firstSegment->GetSize () > nextSegmentSize) ||
171  // Segment larger than 2047 octets can only be mapped to the end of the Data field
172  (firstSegment->GetSize () > 2047)
173  )
174  {
175  // Take the minimum size, due to the 2047-bytes 3GPP exception
176  // This exception is due to the length of the LI field (just 11 bits)
177  uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
178 
179  NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
180  NS_LOG_LOGIC (" firstSegment > 2047 )");
181 
182  // Segment txBuffer.FirstBuffer and
183  // Give back the remaining segment to the transmission buffer
184  Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
185  NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
186 
187  // Status tag of the new and remaining segments
188  // Note: This is the only place where a PDU is segmented and
189  // therefore its status can change
190  LteRlcSduStatusTag oldTag, newTag;
191  firstSegment->RemovePacketTag (oldTag);
192  newSegment->RemovePacketTag (newTag);
193  if (oldTag.GetStatus () == LteRlcSduStatusTag::FULL_SDU)
194  {
195  newTag.SetStatus (LteRlcSduStatusTag::FIRST_SEGMENT);
196  oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
197  }
198  else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT)
199  {
200  newTag.SetStatus (LteRlcSduStatusTag::MIDDLE_SEGMENT);
201  //oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
202  }
203 
204  // Give back the remaining segment to the transmission buffer
205  firstSegment->RemoveAtStart (currSegmentSize);
206  NS_LOG_LOGIC (" firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize ());
207  if (firstSegment->GetSize () > 0)
208  {
209  firstSegment->AddPacketTag (oldTag);
210 
211  m_txBuffer.insert (m_txBuffer.begin (), firstSegment);
212  m_txBufferSize += (*(m_txBuffer.begin()))->GetSize ();
213 
214  NS_LOG_LOGIC (" TX buffer: Give back the remaining segment");
215  NS_LOG_LOGIC (" TX buffers = " << m_txBuffer.size ());
216  NS_LOG_LOGIC (" Front buffer size = " << (*(m_txBuffer.begin()))->GetSize ());
217  NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
218  }
219  else
220  {
221  // Whole segment was taken, so adjust tag
222  if (newTag.GetStatus () == LteRlcSduStatusTag::FIRST_SEGMENT)
223  {
224  newTag.SetStatus (LteRlcSduStatusTag::FULL_SDU);
225  }
226  else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
227  {
228  newTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
229  }
230  }
231  // Segment is completely taken or
232  // the remaining segment is given back to the transmission buffer
233  firstSegment = 0;
234 
235  // Put status tag once it has been adjusted
236  newSegment->AddPacketTag (newTag);
237 
238  // Add Segment to Data field
239  dataFieldAddedSize = newSegment->GetSize ();
240  dataFieldTotalSize += dataFieldAddedSize;
241  dataField.push_back (newSegment);
242  newSegment = 0;
243 
244  // ExtensionBit (Next_Segment - 1) = 0
245  rlcHeader.PushExtensionBit (LteRlcHeader::DATA_FIELD_FOLLOWS);
246 
247  // no LengthIndicator for the last one
248 
249  nextSegmentSize -= dataFieldAddedSize;
250  nextSegmentId++;
251 
252  // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
253 
254  // (NO more segments) → exit
255  // break;
256  }
257  else if ( (nextSegmentSize - firstSegment->GetSize () <= 2) || (m_txBuffer.size () == 0) )
258  {
259  NS_LOG_LOGIC (" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
260  // Add txBuffer.FirstBuffer to DataField
261  dataFieldAddedSize = firstSegment->GetSize ();
262  dataFieldTotalSize += dataFieldAddedSize;
263  dataField.push_back (firstSegment);
264  firstSegment = 0;
265 
266  // ExtensionBit (Next_Segment - 1) = 0
267  rlcHeader.PushExtensionBit (LteRlcHeader::DATA_FIELD_FOLLOWS);
268 
269  // no LengthIndicator for the last one
270 
271  nextSegmentSize -= dataFieldAddedSize;
272  nextSegmentId++;
273 
274  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
275  if (m_txBuffer.size () > 0)
276  {
277  NS_LOG_LOGIC (" First SDU buffer = " << *(m_txBuffer.begin()));
278  NS_LOG_LOGIC (" First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
279  }
280  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
281 
282  // nextSegmentSize <= 2 (only if txBuffer is not empty)
283 
284  // (NO more segments) → exit
285  // break;
286  }
287  else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
288  {
289  NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
290  // Add txBuffer.FirstBuffer to DataField
291  dataFieldAddedSize = firstSegment->GetSize ();
292  dataFieldTotalSize += dataFieldAddedSize;
293  dataField.push_back (firstSegment);
294 
295  // ExtensionBit (Next_Segment - 1) = 1
296  rlcHeader.PushExtensionBit (LteRlcHeader::E_LI_FIELDS_FOLLOWS);
297 
298  // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
299  rlcHeader.PushLengthIndicator (firstSegment->GetSize ());
300 
301  nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
302  nextSegmentId++;
303 
304  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
305  if (m_txBuffer.size () > 0)
306  {
307  NS_LOG_LOGIC (" First SDU buffer = " << *(m_txBuffer.begin()));
308  NS_LOG_LOGIC (" First SDU size = " << (*(m_txBuffer.begin()))->GetSize ());
309  }
310  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
311  NS_LOG_LOGIC (" Remove SDU from TxBuffer");
312 
313  // (more segments)
314  firstSegment = (*(m_txBuffer.begin ()))->Copy ();
315  m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
316  m_txBuffer.erase (m_txBuffer.begin ());
317  NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
318  }
319 
320  }
321 
322  // Build RLC header
323  rlcHeader.SetSequenceNumber (m_sequenceNumber++);
324 
325  // Build RLC PDU with DataField and Header
326  std::vector< Ptr<Packet> >::iterator it;
327  it = dataField.begin ();
328 
329  uint8_t framingInfo = 0;
330 
331  // FIRST SEGMENT
332  LteRlcSduStatusTag tag;
333  (*it)->RemovePacketTag (tag);
334  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
336  {
337  framingInfo |= LteRlcHeader::FIRST_BYTE;
338  }
339  else
340  {
341  framingInfo |= LteRlcHeader::NO_FIRST_BYTE;
342  }
343  (*it)->AddPacketTag (tag);
344 
345  while (it < dataField.end ())
346  {
347  NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ());
348 
349  packet->AddAtEnd (*it);
350  it++;
351  }
352 
353  // LAST SEGMENT (Note: There could be only one and be the first one)
354  it--;
355  (*it)->RemovePacketTag (tag);
356  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
358  {
359  framingInfo |= LteRlcHeader::LAST_BYTE;
360  }
361  else
362  {
363  framingInfo |= LteRlcHeader::NO_LAST_BYTE;
364  }
365  (*it)->AddPacketTag (tag);
366 
367  rlcHeader.SetFramingInfo (framingInfo);
368 
369  NS_LOG_LOGIC ("RLC header: " << rlcHeader);
370  packet->AddHeader (rlcHeader);
371 
372  // Sender timestamp
373  RlcTag rlcTag (Simulator::Now ());
374  packet->AddByteTag (rlcTag);
375  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
376 
377  // Send RLC PDU to MAC layer
379  params.pdu = packet;
380  params.rnti = m_rnti;
381  params.lcid = m_lcid;
382  params.layer = layer;
383  params.harqProcessId = harqId;
384 
385  m_macSapProvider->TransmitPdu (params);
386 
387  if (! m_txBuffer.empty ())
388  {
389  m_rbsTimer.Cancel ();
390  m_rbsTimer = Simulator::Schedule (MilliSeconds (10), &LteRlcUm::ExpireRbsTimer, this);
391  }
392 }
393 
394 void
396 {
397  NS_LOG_FUNCTION (this);
398 }
399 
400 void
402 {
403  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
404 
405  // Receiver timestamp
406  RlcTag rlcTag;
407  Time delay;
408  if (p->FindFirstMatchingByteTag (rlcTag))
409  {
410  delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
411  }
412  m_rxPdu (m_rnti, m_lcid, p->GetSize (), delay.GetNanoSeconds ());
413 
414  // 5.1.2.2 Receive operations
415 
416  // Get RLC header parameters
417  LteRlcHeader rlcHeader;
418  p->PeekHeader (rlcHeader);
419  NS_LOG_LOGIC ("RLC header: " << rlcHeader);
420  SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber ();
421 
422  // 5.1.2.2.1 General
423  // The receiving UM RLC entity shall maintain a reordering window according to state variable VR(UH) as follows:
424  // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
425  // - a SN falls outside of the reordering window otherwise.
426  // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
427  // - either discard the received UMD PDU or place it in the reception buffer (see sub clause 5.1.2.2.2);
428  // - if the received UMD PDU was placed in the reception buffer:
429  // - 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);
430  // When t-Reordering expires, the receiving UM RLC entity shall:
431  // - 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).
432 
433  // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
434  // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
435  // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
436  // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
437  // - discard the received UMD PDU;
438  // - else:
439  // - place the received UMD PDU in the reception buffer.
440 
441  NS_LOG_LOGIC ("VR(UR) = " << m_vrUr);
442  NS_LOG_LOGIC ("VR(UX) = " << m_vrUx);
443  NS_LOG_LOGIC ("VR(UH) = " << m_vrUh);
444  NS_LOG_LOGIC ("SN = " << seqNumber);
445 
448  seqNumber.SetModulusBase (m_vrUh - m_windowSize);
449 
450  if ( ( (m_vrUr < seqNumber) && (seqNumber < m_vrUh) && (m_rxBuffer.count (seqNumber.GetValue ()) > 0) ) ||
451  ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr) )
452  )
453  {
454  NS_LOG_LOGIC ("PDU discarded");
455  p = 0;
456  return;
457  }
458  else
459  {
460  NS_LOG_LOGIC ("Place PDU in the reception buffer");
461  m_rxBuffer[seqNumber.GetValue ()] = p;
462  }
463 
464 
465  // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
466  // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity shall:
467 
468  // - if x falls outside of the reordering window:
469  // - update VR(UH) to x + 1;
470  // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering window, remove
471  // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in ascending order of the
472  // RLC SN if not delivered before;
473  // - if VR(UR) falls outside of the reordering window:
474  // - set VR(UR) to (VR(UH) - UM_Window_Size);
475 
476  if ( ! IsInsideReorderingWindow (seqNumber))
477  {
478  NS_LOG_LOGIC ("SN is outside the reordering window");
479 
480  m_vrUh = seqNumber + 1;
481  NS_LOG_LOGIC ("New VR(UH) = " << m_vrUh);
482 
484 
486  {
488  NS_LOG_LOGIC ("VR(UR) is outside the reordering window");
489  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
490  }
491  }
492 
493  // - if the reception buffer contains an UMD PDU with SN = VR(UR):
494  // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been received;
495  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing
496  // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered
497  // before;
498 
499  if ( m_rxBuffer.count (m_vrUr.GetValue ()) > 0 )
500  {
501  NS_LOG_LOGIC ("Reception buffer contains SN = " << m_vrUr);
502 
503  std::map <uint16_t, Ptr<Packet> >::iterator it;
504  uint16_t newVrUr;
505  SequenceNumber10 oldVrUr = m_vrUr;
506 
507  it = m_rxBuffer.find (m_vrUr.GetValue ());
508  newVrUr = (it->first) + 1;
509  while ( m_rxBuffer.count (newVrUr) > 0 )
510  {
511  newVrUr++;
512  }
513  m_vrUr = newVrUr;
514  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
515 
516  ReassembleSnInterval (oldVrUr, m_vrUr);
517  }
518 
519  // m_vrUh can change previously, set new modulus base
520  // for the t-Reordering timer-related comparisons
524 
525  // - if t-Reordering is running:
526  // - if VR(UX) <= VR(UR); or
527  // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
528  // - stop and reset t-Reordering;
529  if ( m_reorderingTimer.IsRunning () )
530  {
531  NS_LOG_LOGIC ("Reordering timer is running");
532 
533  if ( (m_vrUx <= m_vrUr) ||
534  ((! IsInsideReorderingWindow (m_vrUx)) && (m_vrUx != m_vrUh)) )
535  {
536  NS_LOG_LOGIC ("Stop reordering timer");
538  }
539  }
540 
541  // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to actions above):
542  // - if VR(UH) > VR(UR):
543  // - start t-Reordering;
544  // - set VR(UX) to VR(UH).
545  if ( ! m_reorderingTimer.IsRunning () )
546  {
547  NS_LOG_LOGIC ("Reordering timer is not running");
548 
549  if ( m_vrUh > m_vrUr )
550  {
551  NS_LOG_LOGIC ("VR(UH) > VR(UR)");
552  NS_LOG_LOGIC ("Start reordering timer");
555  m_vrUx = m_vrUh;
556  NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
557  }
558  }
559 
560 }
561 
562 
563 bool
565 {
566  NS_LOG_FUNCTION (this << seqNumber);
567  NS_LOG_LOGIC ("Reordering Window: " <<
568  m_vrUh << " - " << m_windowSize << " <= " << seqNumber << " < " << m_vrUh);
569 
571  seqNumber.SetModulusBase (m_vrUh - m_windowSize);
572 
573  if ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
574  {
575  NS_LOG_LOGIC (seqNumber << " is INSIDE the reordering window");
576  return true;
577  }
578  else
579  {
580  NS_LOG_LOGIC (seqNumber << " is OUTSIDE the reordering window");
581  return false;
582  }
583 }
584 
585 
586 void
588 {
589  LteRlcHeader rlcHeader;
590  packet->RemoveHeader (rlcHeader);
591  uint8_t framingInfo = rlcHeader.GetFramingInfo ();
592  SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber ();
593  bool expectedSnLost;
594 
595  if ( currSeqNumber != m_expectedSeqNumber )
596  {
597  expectedSnLost = true;
598  NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
599  m_expectedSeqNumber = currSeqNumber + 1;
600  }
601  else
602  {
603  expectedSnLost = false;
604  NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
606  }
607 
608  // Build list of SDUs
609  uint8_t extensionBit;
610  uint16_t lengthIndicator;
611  do
612  {
613  extensionBit = rlcHeader.PopExtensionBit ();
614  NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit);
615 
616  if ( extensionBit == 0 )
617  {
618  m_sdusBuffer.push_back (packet);
619  }
620  else // extensionBit == 1
621  {
622  lengthIndicator = rlcHeader.PopLengthIndicator ();
623  NS_LOG_LOGIC ("LI = " << lengthIndicator);
624 
625  // Check if there is enough data in the packet
626  if ( lengthIndicator >= packet->GetSize () )
627  {
628  NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator);
629  }
630 
631  // Split packet in two fragments
632  Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator);
633  packet->RemoveAtStart (lengthIndicator);
634 
635  m_sdusBuffer.push_back (data_field);
636  }
637  }
638  while ( extensionBit == 1 );
639 
640  std::list < Ptr<Packet> >::iterator it;
641 
642  // Current reassembling state
643  if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'");
644  else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'");
645  else NS_LOG_LOGIC ("Reassembling State = Unknown state");
646 
647  // Received framing Info
648  NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
649 
650  // Reassemble the list of SDUs (when there is no losses)
651  if (!expectedSnLost)
652  {
653  switch (m_reassemblingState)
654  {
655  case WAITING_S0_FULL:
656  switch (framingInfo)
657  {
660 
664  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
665  {
667  }
668  m_sdusBuffer.clear ();
669  break;
670 
673 
677  while ( m_sdusBuffer.size () > 1 )
678  {
680  m_sdusBuffer.pop_front ();
681  }
682 
686  m_keepS0 = m_sdusBuffer.front ();
687  m_sdusBuffer.pop_front ();
688  break;
689 
692 
696  m_sdusBuffer.pop_front ();
697 
701  while ( ! m_sdusBuffer.empty () )
702  {
704  m_sdusBuffer.pop_front ();
705  }
706  break;
707 
709  if ( m_sdusBuffer.size () == 1 )
710  {
712  }
713  else
714  {
716  }
717 
721  m_sdusBuffer.pop_front ();
722 
723  if ( m_sdusBuffer.size () > 0 )
724  {
728  while ( m_sdusBuffer.size () > 1 )
729  {
731  m_sdusBuffer.pop_front ();
732  }
733 
737  m_keepS0 = m_sdusBuffer.front ();
738  m_sdusBuffer.pop_front ();
739  }
740  break;
741 
742  default:
746  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
747  break;
748  }
749  break;
750 
751  case WAITING_SI_SF:
752  switch (framingInfo)
753  {
756 
760  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
761  m_sdusBuffer.pop_front ();
763 
767  while ( ! m_sdusBuffer.empty () )
768  {
770  m_sdusBuffer.pop_front ();
771  }
772  break;
773 
776 
780  if ( m_sdusBuffer.size () == 1 )
781  {
782  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
783  m_sdusBuffer.pop_front ();
784  }
785  else // m_sdusBuffer.size () > 1
786  {
790  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
791  m_sdusBuffer.pop_front ();
793 
797  while ( m_sdusBuffer.size () > 1 )
798  {
800  m_sdusBuffer.pop_front ();
801  }
802 
806  m_keepS0 = m_sdusBuffer.front ();
807  m_sdusBuffer.pop_front ();
808  }
809  break;
810 
813  default:
817  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
818  break;
819  }
820  break;
821 
822  default:
823  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
824  break;
825  }
826  }
827  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
828  {
829  switch (m_reassemblingState)
830  {
831  case WAITING_S0_FULL:
832  switch (framingInfo)
833  {
836 
840  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
841  {
843  }
844  m_sdusBuffer.clear ();
845  break;
846 
849 
853  while ( m_sdusBuffer.size () > 1 )
854  {
856  m_sdusBuffer.pop_front ();
857  }
858 
862  m_keepS0 = m_sdusBuffer.front ();
863  m_sdusBuffer.pop_front ();
864  break;
865 
868 
872  m_sdusBuffer.pop_front ();
873 
877  while ( ! m_sdusBuffer.empty () )
878  {
880  m_sdusBuffer.pop_front ();
881  }
882  break;
883 
885  if ( m_sdusBuffer.size () == 1 )
886  {
888  }
889  else
890  {
892  }
893 
897  m_sdusBuffer.pop_front ();
898 
899  if ( m_sdusBuffer.size () > 0 )
900  {
904  while ( m_sdusBuffer.size () > 1 )
905  {
907  m_sdusBuffer.pop_front ();
908  }
909 
913  m_keepS0 = m_sdusBuffer.front ();
914  m_sdusBuffer.pop_front ();
915  }
916  break;
917 
918  default:
922  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
923  break;
924  }
925  break;
926 
927  case WAITING_SI_SF:
928  switch (framingInfo)
929  {
932 
936  m_keepS0 = 0;
937 
941  while ( ! m_sdusBuffer.empty () )
942  {
944  m_sdusBuffer.pop_front ();
945  }
946  break;
947 
950 
954  m_keepS0 = 0;
955 
959  while ( m_sdusBuffer.size () > 1 )
960  {
962  m_sdusBuffer.pop_front ();
963  }
964 
968  m_keepS0 = m_sdusBuffer.front ();
969  m_sdusBuffer.pop_front ();
970 
971  break;
972 
975 
979  m_keepS0 = 0;
980 
984  m_sdusBuffer.pop_front ();
985 
989  while ( ! m_sdusBuffer.empty () )
990  {
992  m_sdusBuffer.pop_front ();
993  }
994  break;
995 
997  if ( m_sdusBuffer.size () == 1 )
998  {
1000  }
1001  else
1002  {
1004  }
1005 
1009  m_keepS0 = 0;
1010 
1014  m_sdusBuffer.pop_front ();
1015 
1016  if ( m_sdusBuffer.size () > 0 )
1017  {
1021  while ( m_sdusBuffer.size () > 1 )
1022  {
1024  m_sdusBuffer.pop_front ();
1025  }
1026 
1030  m_keepS0 = m_sdusBuffer.front ();
1031  m_sdusBuffer.pop_front ();
1032  }
1033  break;
1034 
1035  default:
1039  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1040  break;
1041  }
1042  break;
1043 
1044  default:
1045  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1046  break;
1047  }
1048  }
1049 
1050 }
1051 
1052 
1053 void
1055 {
1056  NS_LOG_LOGIC ("Reassemble Outside Window");
1057 
1058  std::map <uint16_t, Ptr<Packet> >::iterator it;
1059  it = m_rxBuffer.begin ();
1060 
1061  while ( (it != m_rxBuffer.end ()) && ! IsInsideReorderingWindow (SequenceNumber10 (it->first)) )
1062  {
1063  NS_LOG_LOGIC ("SN = " << it->first);
1064 
1065  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1066  ReassembleAndDeliver (it->second);
1067 
1068  std::map <uint16_t, Ptr<Packet> >::iterator it_tmp = it;
1069  ++it;
1070  m_rxBuffer.erase (it_tmp);
1071  }
1072 
1073  if (it != m_rxBuffer.end ())
1074  {
1075  NS_LOG_LOGIC ("(SN = " << it->first << ") is inside the reordering window");
1076  }
1077 }
1078 
1079 void
1081 {
1082  NS_LOG_LOGIC ("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1083 
1084  std::map <uint16_t, Ptr<Packet> >::iterator it;
1085 
1086  SequenceNumber10 reassembleSn = lowSeqNumber;
1087  NS_LOG_LOGIC ("reassembleSN = " << reassembleSn);
1088  NS_LOG_LOGIC ("highSeqNumber = " << highSeqNumber);
1089  while (reassembleSn < highSeqNumber)
1090  {
1091  NS_LOG_LOGIC ("reassembleSn < highSeqNumber");
1092  it = m_rxBuffer.find (reassembleSn.GetValue ());
1093  NS_LOG_LOGIC ("it->first = " << it->first);
1094  NS_LOG_LOGIC ("it->second = " << it->second);
1095  if (it != m_rxBuffer.end () )
1096  {
1097  NS_LOG_LOGIC ("SN = " << it->first);
1098 
1099  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1100  ReassembleAndDeliver (it->second);
1101 
1102  m_rxBuffer.erase (it);
1103  }
1104 
1105  reassembleSn++;
1106  }
1107 }
1108 
1109 
1110 void
1112 {
1113  Time holDelay (0);
1114  uint32_t queueSize = 0;
1115 
1116  if (! m_txBuffer.empty ())
1117  {
1118  RlcTag holTimeTag;
1119  m_txBuffer.front ()->PeekPacketTag (holTimeTag);
1120  holDelay = Simulator::Now () - holTimeTag.GetSenderTimestamp ();
1121 
1122  queueSize = m_txBufferSize + 2 * m_txBuffer.size (); // Data in tx queue + estimated headers size
1123  }
1124 
1126  r.rnti = m_rnti;
1127  r.lcid = m_lcid;
1128  r.txQueueSize = queueSize;
1129  r.txQueueHolDelay = holDelay.GetMilliSeconds () ;
1130  r.retxQueueSize = 0;
1131  r.retxQueueHolDelay = 0;
1132  r.statusPduSize = 0;
1133 
1134  NS_LOG_LOGIC ("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay );
1136 }
1137 
1138 
1139 void
1141 {
1142  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid);
1143  NS_LOG_LOGIC ("Reordering timer has expired");
1144 
1145  // 5.1.2.2.4 Actions when t-Reordering expires
1146  // When t-Reordering expires, the receiving UM RLC entity shall:
1147  // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1148  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing so
1149  // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered before;
1150  // - if VR(UH) > VR(UR):
1151  // - start t-Reordering;
1152  // - set VR(UX) to VR(UH).
1153 
1154  std::map <uint16_t, Ptr<Packet> >::iterator it;
1155  SequenceNumber10 newVrUr = m_vrUx;
1156 
1157  while ( (it = m_rxBuffer.find (newVrUr.GetValue ())) != m_rxBuffer.end () )
1158  {
1159  newVrUr++;
1160  }
1161  SequenceNumber10 oldVrUr = m_vrUr;
1162  m_vrUr = newVrUr;
1163  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
1164 
1165  ReassembleSnInterval (oldVrUr, m_vrUr);
1166 
1167  if ( m_vrUh > m_vrUr)
1168  {
1169  NS_LOG_LOGIC ("Start reordering timer");
1172  m_vrUx = m_vrUh;
1173  NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
1174  }
1175 }
1176 
1177 
1178 void
1180 {
1181  NS_LOG_LOGIC ("RBS Timer expires");
1182 
1183  if (! m_txBuffer.empty ())
1184  {
1186  m_rbsTimer = Simulator::Schedule (MilliSeconds (10), &LteRlcUm::ExpireRbsTimer, this);
1187  }
1188 }
1189 
1190 } // 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:128
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:824
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:79
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
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 the class in the ns-3 factory.
Definition: object-base.h:38
void ReassembleAndDeliver(Ptr< Packet > packet)
Definition: lte-rlc-um.cc:587
void DoReportBufferStatus()
Definition: lte-rlc-um.cc:1111
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
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:744
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:84
uint8_t PopExtensionBit(void)
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
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:825
uint8_t m_lcid
Definition: lte-rlc.h:123
virtual void DoNotifyHarqDeliveryFailure()
Definition: lte-rlc-um.cc:395
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:1080
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:401
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:317
uint16_t PopLengthIndicator(void)
LteRlcSapUser * m_rlcSapUser
Definition: lte-rlc.h:111
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:353
virtual void DoNotifyTxOpportunity(uint32_t bytes, uint8_t layer, uint8_t harqId)
MAC SAP.
Definition: lte-rlc-um.cc:126
static TypeId GetTypeId(void)
Definition: lte-rlc-um.cc:55
Hold an unsigned integer type.
Definition: uinteger.h:46
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()
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: lte-rlc.cc:117
LteMacSapProvider * m_macSapProvider
Definition: lte-rlc.h:120
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:233
Ptr< Packet > 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:277
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:1140
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 time".
Definition: simulator.cc:180
std::map< uint16_t, Ptr< Packet > > m_rxBuffer
Definition: lte-rlc-um.h:72
EventId m_reorderingTimer
Timers.
Definition: lte-rlc-um.h:94
int64_t GetNanoSeconds(void) const
Definition: nstime.h:297
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:848
void ReassembleOutsideWindow(void)
Definition: lte-rlc-um.cc:1054
bool IsInsideReorderingWindow(SequenceNumber10 seqNumber)
Definition: lte-rlc-um.cc:564
void SetStatus(uint8_t status)
virtual void DoDispose()
This method is called by Object::Dispose or by the object's destructor, whichever comes first...
Definition: lte-rlc-um.cc:70
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.
uint32_t m_txBufferSize
Definition: lte-rlc-um.h:70
void ExpireRbsTimer(void)
Definition: lte-rlc-um.cc:1179
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
EventId m_rbsTimer
Definition: lte-rlc-um.h:95
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
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
int64_t GetMilliSeconds(void) const
Definition: nstime.h:281
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
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