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  {
94  p->AddPacketTag (tag);
95 
96  NS_LOG_LOGIC ("Tx Buffer: New packet added");
97  m_txBuffer.push_back (TxPdu (p, Simulator::Now ()));
98  m_txBufferSize += p->GetSize ();
99  NS_LOG_LOGIC ("NumOfBuffers = " << m_txBuffer.size() );
100  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
101  }
102  else
103  {
104  // Discard full RLC SDU
105  NS_LOG_LOGIC ("TxBuffer is full. RLC SDU discarded");
106  NS_LOG_LOGIC ("MaxTxBufferSize = " << m_maxTxBufferSize);
107  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
108  NS_LOG_LOGIC ("packet size = " << p->GetSize ());
109  }
110 
113  m_rbsTimer.Cancel ();
114 }
115 
116 
121 void
123 {
124  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << txOpParams.bytes);
125 
126  if (txOpParams.bytes <= 2)
127  {
128  // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
129  NS_LOG_LOGIC ("TX opportunity too small = " << txOpParams.bytes);
130  return;
131  }
132 
133  Ptr<Packet> packet = Create<Packet> ();
134  LteRlcHeader rlcHeader;
135 
136  // Build Data field
137  uint32_t nextSegmentSize = txOpParams.bytes - 2;
138  uint32_t nextSegmentId = 1;
139  uint32_t dataFieldTotalSize = 0;
140  uint32_t dataFieldAddedSize = 0;
141  std::vector < Ptr<Packet> > dataField;
142 
143  // Remove the first packet from the transmission buffer.
144  // If only a segment of the packet is taken, then the remaining is given back later
145  if ( m_txBuffer.size () == 0 )
146  {
147  NS_LOG_LOGIC ("No data pending");
148  return;
149  }
150 
151  Ptr<Packet> firstSegment = m_txBuffer.begin ()->m_pdu->Copy ();
152  Time firstSegmentTime = m_txBuffer.begin ()->m_waitingSince;
153 
154  NS_LOG_LOGIC ("SDUs in TxBuffer = " << m_txBuffer.size ());
155  NS_LOG_LOGIC ("First SDU buffer = " << firstSegment);
156  NS_LOG_LOGIC ("First SDU size = " << firstSegment->GetSize ());
157  NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize);
158  NS_LOG_LOGIC ("Remove SDU from TxBuffer");
159  m_txBufferSize -= firstSegment->GetSize ();
160  NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize );
161  m_txBuffer.erase (m_txBuffer.begin ());
162 
163  while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) )
164  {
165  NS_LOG_LOGIC ("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
166  NS_LOG_LOGIC (" firstSegment size = " << firstSegment->GetSize ());
167  NS_LOG_LOGIC (" nextSegmentSize = " << nextSegmentSize);
168  if ( (firstSegment->GetSize () > nextSegmentSize) ||
169  // Segment larger than 2047 octets can only be mapped to the end of the Data field
170  (firstSegment->GetSize () > 2047)
171  )
172  {
173  // Take the minimum size, due to the 2047-bytes 3GPP exception
174  // This exception is due to the length of the LI field (just 11 bits)
175  uint32_t currSegmentSize = std::min (firstSegment->GetSize (), nextSegmentSize);
176 
177  NS_LOG_LOGIC (" IF ( firstSegment > nextSegmentSize ||");
178  NS_LOG_LOGIC (" firstSegment > 2047 )");
179 
180  // Segment txBuffer.FirstBuffer and
181  // Give back the remaining segment to the transmission buffer
182  Ptr<Packet> newSegment = firstSegment->CreateFragment (0, currSegmentSize);
183  NS_LOG_LOGIC (" newSegment size = " << newSegment->GetSize ());
184 
185  // Status tag of the new and remaining segments
186  // Note: This is the only place where a PDU is segmented and
187  // therefore its status can change
188  LteRlcSduStatusTag oldTag, newTag;
189  firstSegment->RemovePacketTag (oldTag);
190  newSegment->RemovePacketTag (newTag);
191  if (oldTag.GetStatus () == LteRlcSduStatusTag::FULL_SDU)
192  {
193  newTag.SetStatus (LteRlcSduStatusTag::FIRST_SEGMENT);
194  oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
195  }
196  else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT)
197  {
198  newTag.SetStatus (LteRlcSduStatusTag::MIDDLE_SEGMENT);
199  //oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
200  }
201 
202  // Give back the remaining segment to the transmission buffer
203  firstSegment->RemoveAtStart (currSegmentSize);
204  NS_LOG_LOGIC (" firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize ());
205  if (firstSegment->GetSize () > 0)
206  {
207  firstSegment->AddPacketTag (oldTag);
208 
209  m_txBuffer.insert (m_txBuffer.begin (), TxPdu (firstSegment, firstSegmentTime));
210  m_txBufferSize += m_txBuffer.begin()->m_pdu->GetSize ();
211 
212  NS_LOG_LOGIC (" TX buffer: Give back the remaining segment");
213  NS_LOG_LOGIC (" TX buffers = " << m_txBuffer.size ());
214  NS_LOG_LOGIC (" Front buffer size = " << m_txBuffer.begin()->m_pdu->GetSize ());
215  NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
216  }
217  else
218  {
219  // Whole segment was taken, so adjust tag
220  if (newTag.GetStatus () == LteRlcSduStatusTag::FIRST_SEGMENT)
221  {
222  newTag.SetStatus (LteRlcSduStatusTag::FULL_SDU);
223  }
224  else if (newTag.GetStatus () == LteRlcSduStatusTag::MIDDLE_SEGMENT)
225  {
226  newTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
227  }
228  }
229  // Segment is completely taken or
230  // the remaining segment is given back to the transmission buffer
231  firstSegment = 0;
232 
233  // Put status tag once it has been adjusted
234  newSegment->AddPacketTag (newTag);
235 
236  // Add Segment to Data field
237  dataFieldAddedSize = newSegment->GetSize ();
238  dataFieldTotalSize += dataFieldAddedSize;
239  dataField.push_back (newSegment);
240  newSegment = 0;
241 
242  // ExtensionBit (Next_Segment - 1) = 0
243  rlcHeader.PushExtensionBit (LteRlcHeader::DATA_FIELD_FOLLOWS);
244 
245  // no LengthIndicator for the last one
246 
247  nextSegmentSize -= dataFieldAddedSize;
248  nextSegmentId++;
249 
250  // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
251 
252  // (NO more segments) → exit
253  // break;
254  }
255  else if ( (nextSegmentSize - firstSegment->GetSize () <= 2) || (m_txBuffer.size () == 0) )
256  {
257  NS_LOG_LOGIC (" IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
258  // Add txBuffer.FirstBuffer to DataField
259  dataFieldAddedSize = firstSegment->GetSize ();
260  dataFieldTotalSize += dataFieldAddedSize;
261  dataField.push_back (firstSegment);
262  firstSegment = 0;
263 
264  // ExtensionBit (Next_Segment - 1) = 0
265  rlcHeader.PushExtensionBit (LteRlcHeader::DATA_FIELD_FOLLOWS);
266 
267  // no LengthIndicator for the last one
268 
269  nextSegmentSize -= dataFieldAddedSize;
270  nextSegmentId++;
271 
272  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
273  if (m_txBuffer.size () > 0)
274  {
275  NS_LOG_LOGIC (" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
276  NS_LOG_LOGIC (" First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize ());
277  }
278  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
279 
280  // nextSegmentSize <= 2 (only if txBuffer is not empty)
281 
282  // (NO more segments) → exit
283  // break;
284  }
285  else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
286  {
287  NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
288  // Add txBuffer.FirstBuffer to DataField
289  dataFieldAddedSize = firstSegment->GetSize ();
290  dataFieldTotalSize += dataFieldAddedSize;
291  dataField.push_back (firstSegment);
292 
293  // ExtensionBit (Next_Segment - 1) = 1
294  rlcHeader.PushExtensionBit (LteRlcHeader::E_LI_FIELDS_FOLLOWS);
295 
296  // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
297  rlcHeader.PushLengthIndicator (firstSegment->GetSize ());
298 
299  nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
300  nextSegmentId++;
301 
302  NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txBuffer.size ());
303  if (m_txBuffer.size () > 0)
304  {
305  NS_LOG_LOGIC (" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
306  NS_LOG_LOGIC (" First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize ());
307  }
308  NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize);
309  NS_LOG_LOGIC (" Remove SDU from TxBuffer");
310 
311  // (more segments)
312  firstSegment = m_txBuffer.begin ()->m_pdu->Copy ();
313  firstSegmentTime = m_txBuffer.begin ()->m_waitingSince;
314  m_txBufferSize -= firstSegment->GetSize ();
315  m_txBuffer.erase (m_txBuffer.begin ());
316  NS_LOG_LOGIC (" txBufferSize = " << m_txBufferSize );
317  }
318 
319  }
320 
321  // Build RLC header
322  rlcHeader.SetSequenceNumber (m_sequenceNumber++);
323 
324  // Build RLC PDU with DataField and Header
325  std::vector< Ptr<Packet> >::iterator it;
326  it = dataField.begin ();
327 
328  uint8_t framingInfo = 0;
329 
330  // FIRST SEGMENT
331  LteRlcSduStatusTag tag;
332  NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
333  (*it)->PeekPacketTag (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 
344  while (it < dataField.end ())
345  {
346  NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ());
347 
348  NS_ASSERT_MSG ((*it)->PeekPacketTag (tag), "LteRlcSduStatusTag is missing");
349  (*it)->RemovePacketTag (tag);
350  if (packet->GetSize () > 0)
351  {
352  packet->AddAtEnd (*it);
353  }
354  else
355  {
356  packet = (*it);
357  }
358  it++;
359  }
360 
361  // LAST SEGMENT (Note: There could be only one and be the first one)
362  it--;
363  if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) ||
365  {
366  framingInfo |= LteRlcHeader::LAST_BYTE;
367  }
368  else
369  {
370  framingInfo |= LteRlcHeader::NO_LAST_BYTE;
371  }
372 
373  rlcHeader.SetFramingInfo (framingInfo);
374 
375  NS_LOG_LOGIC ("RLC header: " << rlcHeader);
376  packet->AddHeader (rlcHeader);
377 
378  // Sender timestamp
379  RlcTag rlcTag (Simulator::Now ());
380  packet->AddByteTag (rlcTag, 1, rlcHeader.GetSerializedSize ());
381  m_txPdu (m_rnti, m_lcid, packet->GetSize ());
382 
383  // Send RLC PDU to MAC layer
385  params.pdu = packet;
386  params.rnti = m_rnti;
387  params.lcid = m_lcid;
388  params.layer = txOpParams.layer;
389  params.harqProcessId = txOpParams.harqId;
390  params.componentCarrierId = txOpParams.componentCarrierId;
391 
392  m_macSapProvider->TransmitPdu (params);
393 
394  if (! m_txBuffer.empty ())
395  {
396  m_rbsTimer.Cancel ();
398  }
399 }
400 
401 void
403 {
404  NS_LOG_FUNCTION (this);
405 }
406 
407 void
409 {
410  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << rxPduParams.p->GetSize ());
411 
412  // Receiver timestamp
413  RlcTag rlcTag;
414  Time delay;
415 
416  bool ret = rxPduParams.p->FindFirstMatchingByteTag (rlcTag);
417  NS_ASSERT_MSG (ret, "RlcTag is missing");
418 
419  delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
420  m_rxPdu (m_rnti, m_lcid, rxPduParams.p->GetSize (), delay.GetNanoSeconds ());
421 
422  // 5.1.2.2 Receive operations
423 
424  // Get RLC header parameters
425  LteRlcHeader rlcHeader;
426  rxPduParams.p->PeekHeader (rlcHeader);
427  NS_LOG_LOGIC ("RLC header: " << rlcHeader);
428  SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber ();
429 
430  // 5.1.2.2.1 General
431  // The receiving UM RLC entity shall maintain a reordering window according to state variable VR(UH) as follows:
432  // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
433  // - a SN falls outside of the reordering window otherwise.
434  // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
435  // - either discard the received UMD PDU or place it in the reception buffer (see sub clause 5.1.2.2.2);
436  // - if the received UMD PDU was placed in the reception buffer:
437  // - 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);
438  // When t-Reordering expires, the receiving UM RLC entity shall:
439  // - 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).
440 
441  // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
442  // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
443  // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
444  // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
445  // - discard the received UMD PDU;
446  // - else:
447  // - place the received UMD PDU in the reception buffer.
448 
449  NS_LOG_LOGIC ("VR(UR) = " << m_vrUr);
450  NS_LOG_LOGIC ("VR(UX) = " << m_vrUx);
451  NS_LOG_LOGIC ("VR(UH) = " << m_vrUh);
452  NS_LOG_LOGIC ("SN = " << seqNumber);
453 
456  seqNumber.SetModulusBase (m_vrUh - m_windowSize);
457 
458  if ( ( (m_vrUr < seqNumber) && (seqNumber < m_vrUh) && (m_rxBuffer.count (seqNumber.GetValue ()) > 0) ) ||
459  ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr) )
460  )
461  {
462  NS_LOG_LOGIC ("PDU discarded");
463  rxPduParams.p = 0;
464  return;
465  }
466  else
467  {
468  NS_LOG_LOGIC ("Place PDU in the reception buffer");
469  m_rxBuffer[seqNumber.GetValue ()] = rxPduParams.p;
470  }
471 
472 
473  // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
474  // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity shall:
475 
476  // - if x falls outside of the reordering window:
477  // - update VR(UH) to x + 1;
478  // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering window, remove
479  // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in ascending order of the
480  // RLC SN if not delivered before;
481  // - if VR(UR) falls outside of the reordering window:
482  // - set VR(UR) to (VR(UH) - UM_Window_Size);
483 
484  if ( ! IsInsideReorderingWindow (seqNumber))
485  {
486  NS_LOG_LOGIC ("SN is outside the reordering window");
487 
488  m_vrUh = seqNumber + 1;
489  NS_LOG_LOGIC ("New VR(UH) = " << m_vrUh);
490 
492 
494  {
496  NS_LOG_LOGIC ("VR(UR) is outside the reordering window");
497  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
498  }
499  }
500 
501  // - if the reception buffer contains an UMD PDU with SN = VR(UR):
502  // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been received;
503  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing
504  // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered
505  // before;
506 
507  if ( m_rxBuffer.count (m_vrUr.GetValue ()) > 0 )
508  {
509  NS_LOG_LOGIC ("Reception buffer contains SN = " << m_vrUr);
510 
511  std::map <uint16_t, Ptr<Packet> >::iterator it;
512  uint16_t newVrUr;
513  SequenceNumber10 oldVrUr = m_vrUr;
514 
515  it = m_rxBuffer.find (m_vrUr.GetValue ());
516  newVrUr = (it->first) + 1;
517  while ( m_rxBuffer.count (newVrUr) > 0 )
518  {
519  newVrUr++;
520  }
521  m_vrUr = newVrUr;
522  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
523 
524  ReassembleSnInterval (oldVrUr, m_vrUr);
525  }
526 
527  // m_vrUh can change previously, set new modulus base
528  // for the t-Reordering timer-related comparisons
532 
533  // - if t-Reordering is running:
534  // - if VR(UX) <= VR(UR); or
535  // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
536  // - stop and reset t-Reordering;
537  if ( m_reorderingTimer.IsRunning () )
538  {
539  NS_LOG_LOGIC ("Reordering timer is running");
540 
541  if ( (m_vrUx <= m_vrUr) ||
542  ((! IsInsideReorderingWindow (m_vrUx)) && (m_vrUx != m_vrUh)) )
543  {
544  NS_LOG_LOGIC ("Stop reordering timer");
546  }
547  }
548 
549  // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to actions above):
550  // - if VR(UH) > VR(UR):
551  // - start t-Reordering;
552  // - set VR(UX) to VR(UH).
553  if ( ! m_reorderingTimer.IsRunning () )
554  {
555  NS_LOG_LOGIC ("Reordering timer is not running");
556 
557  if ( m_vrUh > m_vrUr )
558  {
559  NS_LOG_LOGIC ("VR(UH) > VR(UR)");
560  NS_LOG_LOGIC ("Start reordering timer");
563  m_vrUx = m_vrUh;
564  NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
565  }
566  }
567 
568 }
569 
570 
571 bool
573 {
574  NS_LOG_FUNCTION (this << seqNumber);
575  NS_LOG_LOGIC ("Reordering Window: " <<
576  m_vrUh << " - " << m_windowSize << " <= " << seqNumber << " < " << m_vrUh);
577 
579  seqNumber.SetModulusBase (m_vrUh - m_windowSize);
580 
581  if ( ((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
582  {
583  NS_LOG_LOGIC (seqNumber << " is INSIDE the reordering window");
584  return true;
585  }
586  else
587  {
588  NS_LOG_LOGIC (seqNumber << " is OUTSIDE the reordering window");
589  return false;
590  }
591 }
592 
593 
594 void
596 {
597  LteRlcHeader rlcHeader;
598  packet->RemoveHeader (rlcHeader);
599  uint8_t framingInfo = rlcHeader.GetFramingInfo ();
600  SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber ();
601  bool expectedSnLost;
602 
603  if ( currSeqNumber != m_expectedSeqNumber )
604  {
605  expectedSnLost = true;
606  NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
607  m_expectedSeqNumber = currSeqNumber + 1;
608  }
609  else
610  {
611  expectedSnLost = false;
612  NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber);
614  }
615 
616  // Build list of SDUs
617  uint8_t extensionBit;
618  uint16_t lengthIndicator;
619  do
620  {
621  extensionBit = rlcHeader.PopExtensionBit ();
622  NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit);
623 
624  if ( extensionBit == 0 )
625  {
626  m_sdusBuffer.push_back (packet);
627  }
628  else // extensionBit == 1
629  {
630  lengthIndicator = rlcHeader.PopLengthIndicator ();
631  NS_LOG_LOGIC ("LI = " << lengthIndicator);
632 
633  // Check if there is enough data in the packet
634  if ( lengthIndicator >= packet->GetSize () )
635  {
636  NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator);
637  }
638 
639  // Split packet in two fragments
640  Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator);
641  packet->RemoveAtStart (lengthIndicator);
642 
643  m_sdusBuffer.push_back (data_field);
644  }
645  }
646  while ( extensionBit == 1 );
647 
648  std::list < Ptr<Packet> >::iterator it;
649 
650  // Current reassembling state
651  if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'");
652  else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'");
653  else NS_LOG_LOGIC ("Reassembling State = Unknown state");
654 
655  // Received framing Info
656  NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo);
657 
658  // Reassemble the list of SDUs (when there is no losses)
659  if (!expectedSnLost)
660  {
661  switch (m_reassemblingState)
662  {
663  case WAITING_S0_FULL:
664  switch (framingInfo)
665  {
668 
672  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
673  {
675  }
676  m_sdusBuffer.clear ();
677  break;
678 
681 
685  while ( m_sdusBuffer.size () > 1 )
686  {
688  m_sdusBuffer.pop_front ();
689  }
690 
694  m_keepS0 = m_sdusBuffer.front ();
695  m_sdusBuffer.pop_front ();
696  break;
697 
700 
704  m_sdusBuffer.pop_front ();
705 
709  while ( ! m_sdusBuffer.empty () )
710  {
712  m_sdusBuffer.pop_front ();
713  }
714  break;
715 
717  if ( m_sdusBuffer.size () == 1 )
718  {
720  }
721  else
722  {
724  }
725 
729  m_sdusBuffer.pop_front ();
730 
731  if ( m_sdusBuffer.size () > 0 )
732  {
736  while ( m_sdusBuffer.size () > 1 )
737  {
739  m_sdusBuffer.pop_front ();
740  }
741 
745  m_keepS0 = m_sdusBuffer.front ();
746  m_sdusBuffer.pop_front ();
747  }
748  break;
749 
750  default:
754  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
755  break;
756  }
757  break;
758 
759  case WAITING_SI_SF:
760  switch (framingInfo)
761  {
764 
768  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
769  m_sdusBuffer.pop_front ();
771 
775  while ( ! m_sdusBuffer.empty () )
776  {
778  m_sdusBuffer.pop_front ();
779  }
780  break;
781 
784 
788  if ( m_sdusBuffer.size () == 1 )
789  {
790  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
791  m_sdusBuffer.pop_front ();
792  }
793  else // m_sdusBuffer.size () > 1
794  {
798  m_keepS0->AddAtEnd (m_sdusBuffer.front ());
799  m_sdusBuffer.pop_front ();
801 
805  while ( m_sdusBuffer.size () > 1 )
806  {
808  m_sdusBuffer.pop_front ();
809  }
810 
814  m_keepS0 = m_sdusBuffer.front ();
815  m_sdusBuffer.pop_front ();
816  }
817  break;
818 
821  default:
825  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
826  break;
827  }
828  break;
829 
830  default:
831  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
832  break;
833  }
834  }
835  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one)
836  {
837  switch (m_reassemblingState)
838  {
839  case WAITING_S0_FULL:
840  switch (framingInfo)
841  {
844 
848  for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ )
849  {
851  }
852  m_sdusBuffer.clear ();
853  break;
854 
857 
861  while ( m_sdusBuffer.size () > 1 )
862  {
864  m_sdusBuffer.pop_front ();
865  }
866 
870  m_keepS0 = m_sdusBuffer.front ();
871  m_sdusBuffer.pop_front ();
872  break;
873 
876 
880  m_sdusBuffer.pop_front ();
881 
885  while ( ! m_sdusBuffer.empty () )
886  {
888  m_sdusBuffer.pop_front ();
889  }
890  break;
891 
893  if ( m_sdusBuffer.size () == 1 )
894  {
896  }
897  else
898  {
900  }
901 
905  m_sdusBuffer.pop_front ();
906 
907  if ( m_sdusBuffer.size () > 0 )
908  {
912  while ( m_sdusBuffer.size () > 1 )
913  {
915  m_sdusBuffer.pop_front ();
916  }
917 
921  m_keepS0 = m_sdusBuffer.front ();
922  m_sdusBuffer.pop_front ();
923  }
924  break;
925 
926  default:
930  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
931  break;
932  }
933  break;
934 
935  case WAITING_SI_SF:
936  switch (framingInfo)
937  {
940 
944  m_keepS0 = 0;
945 
949  while ( ! m_sdusBuffer.empty () )
950  {
952  m_sdusBuffer.pop_front ();
953  }
954  break;
955 
958 
962  m_keepS0 = 0;
963 
967  while ( m_sdusBuffer.size () > 1 )
968  {
970  m_sdusBuffer.pop_front ();
971  }
972 
976  m_keepS0 = m_sdusBuffer.front ();
977  m_sdusBuffer.pop_front ();
978 
979  break;
980 
983 
987  m_keepS0 = 0;
988 
992  m_sdusBuffer.pop_front ();
993 
997  while ( ! m_sdusBuffer.empty () )
998  {
1000  m_sdusBuffer.pop_front ();
1001  }
1002  break;
1003 
1005  if ( m_sdusBuffer.size () == 1 )
1006  {
1008  }
1009  else
1010  {
1012  }
1013 
1017  m_keepS0 = 0;
1018 
1022  m_sdusBuffer.pop_front ();
1023 
1024  if ( m_sdusBuffer.size () > 0 )
1025  {
1029  while ( m_sdusBuffer.size () > 1 )
1030  {
1032  m_sdusBuffer.pop_front ();
1033  }
1034 
1038  m_keepS0 = m_sdusBuffer.front ();
1039  m_sdusBuffer.pop_front ();
1040  }
1041  break;
1042 
1043  default:
1047  NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << (uint32_t) framingInfo);
1048  break;
1049  }
1050  break;
1051 
1052  default:
1053  NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << (uint32_t) m_reassemblingState);
1054  break;
1055  }
1056  }
1057 
1058 }
1059 
1060 
1061 void
1063 {
1064  NS_LOG_LOGIC ("Reassemble Outside Window");
1065 
1066  std::map <uint16_t, Ptr<Packet> >::iterator it;
1067  it = m_rxBuffer.begin ();
1068 
1069  while ( (it != m_rxBuffer.end ()) && ! IsInsideReorderingWindow (SequenceNumber10 (it->first)) )
1070  {
1071  NS_LOG_LOGIC ("SN = " << it->first);
1072 
1073  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1074  ReassembleAndDeliver (it->second);
1075 
1076  std::map <uint16_t, Ptr<Packet> >::iterator it_tmp = it;
1077  ++it;
1078  m_rxBuffer.erase (it_tmp);
1079  }
1080 
1081  if (it != m_rxBuffer.end ())
1082  {
1083  NS_LOG_LOGIC ("(SN = " << it->first << ") is inside the reordering window");
1084  }
1085 }
1086 
1087 void
1089 {
1090  NS_LOG_LOGIC ("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1091 
1092  std::map <uint16_t, Ptr<Packet> >::iterator it;
1093 
1094  SequenceNumber10 reassembleSn = lowSeqNumber;
1095  NS_LOG_LOGIC ("reassembleSN = " << reassembleSn);
1096  NS_LOG_LOGIC ("highSeqNumber = " << highSeqNumber);
1097  while (reassembleSn < highSeqNumber)
1098  {
1099  NS_LOG_LOGIC ("reassembleSn < highSeqNumber");
1100  it = m_rxBuffer.find (reassembleSn.GetValue ());
1101  NS_LOG_LOGIC ("it->first = " << it->first);
1102  NS_LOG_LOGIC ("it->second = " << it->second);
1103  if (it != m_rxBuffer.end () )
1104  {
1105  NS_LOG_LOGIC ("SN = " << it->first);
1106 
1107  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1108  ReassembleAndDeliver (it->second);
1109 
1110  m_rxBuffer.erase (it);
1111  }
1112 
1113  reassembleSn++;
1114  }
1115 }
1116 
1117 
1118 void
1120 {
1121  Time holDelay (0);
1122  uint32_t queueSize = 0;
1123 
1124  if (! m_txBuffer.empty ())
1125  {
1126  holDelay = Simulator::Now () - m_txBuffer.front().m_waitingSince;
1127 
1128  queueSize = m_txBufferSize + 2 * m_txBuffer.size (); // Data in tx queue + estimated headers size
1129  }
1130 
1132  r.rnti = m_rnti;
1133  r.lcid = m_lcid;
1134  r.txQueueSize = queueSize;
1135  r.txQueueHolDelay = holDelay.GetMilliSeconds () ;
1136  r.retxQueueSize = 0;
1137  r.retxQueueHolDelay = 0;
1138  r.statusPduSize = 0;
1139 
1140  NS_LOG_LOGIC ("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay );
1142 }
1143 
1144 
1145 void
1147 {
1148  NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid);
1149  NS_LOG_LOGIC ("Reordering timer has expired");
1150 
1151  // 5.1.2.2.4 Actions when t-Reordering expires
1152  // When t-Reordering expires, the receiving UM RLC entity shall:
1153  // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1154  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing so
1155  // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered before;
1156  // - if VR(UH) > VR(UR):
1157  // - start t-Reordering;
1158  // - set VR(UX) to VR(UH).
1159 
1160  std::map <uint16_t, Ptr<Packet> >::iterator it;
1161  SequenceNumber10 newVrUr = m_vrUx;
1162 
1163  while ( (it = m_rxBuffer.find (newVrUr.GetValue ())) != m_rxBuffer.end () )
1164  {
1165  newVrUr++;
1166  }
1167  SequenceNumber10 oldVrUr = m_vrUr;
1168  m_vrUr = newVrUr;
1169  NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr);
1170 
1171  ReassembleSnInterval (oldVrUr, m_vrUr);
1172 
1173  if ( m_vrUh > m_vrUr)
1174  {
1175  NS_LOG_LOGIC ("Start reordering timer");
1178  m_vrUx = m_vrUh;
1179  NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx);
1180  }
1181 }
1182 
1183 
1184 void
1186 {
1187  NS_LOG_LOGIC ("RBS Timer expires");
1188 
1189  if (! m_txBuffer.empty ())
1190  {
1193  }
1194 }
1195 
1196 } // 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:846
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
virtual uint32_t GetSerializedSize() const
Definition: lte-rlc-tag.cc:60
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
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
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
#define min(a, b)
Definition: 80211b.c:42
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver function.
Definition: lte-rlc-um.cc:595
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-um.cc:1119
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:204
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1070
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:85
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:402
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:1088
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:122
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:159
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1389
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:153
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
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-um.h:154
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:367
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:1146
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
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:193
std::map< uint16_t, Ptr< Packet > > m_rxBuffer
Reception buffer.
Definition: lte-rlc-um.h:122
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
EventId m_reorderingTimer
Timers.
Definition: lte-rlc-um.h:144
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:863
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:359
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:870
void ReassembleOutsideWindow(void)
Reassemble outside window.
Definition: lte-rlc-um.cc:1062
bool IsInsideReorderingWindow(SequenceNumber10 seqNumber)
Is inside reordering window function.
Definition: lte-rlc-um.cc:572
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
void SetStatus(uint8_t status)
Set status function.
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: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
virtual void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams)
Receive PDU function.
Definition: lte-rlc-um.cc:408
void ExpireRbsTimer(void)
Expire RBS timer.
Definition: lte-rlc-um.cc:1185
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:145
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:915
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:819
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