A Discrete-Event Network Simulator
API
lte-rlc-um.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Manuel Requena <manuel.requena@cttc.es>
18  */
19 
20 #include "ns3/lte-rlc-um.h"
21 
22 #include "ns3/log.h"
23 #include "ns3/lte-rlc-header.h"
24 #include "ns3/lte-rlc-sdu-status-tag.h"
25 #include "ns3/lte-rlc-tag.h"
26 #include "ns3/simulator.h"
27 
28 namespace ns3
29 {
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 =
58  TypeId("ns3::LteRlcUm")
59  .SetParent<LteRlc>()
60  .SetGroupName("Lte")
61  .AddConstructor<LteRlcUm>()
62  .AddAttribute("MaxTxBufferSize",
63  "Maximum Size of the Transmission Buffer (in Bytes)",
64  UintegerValue(10 * 1024),
66  MakeUintegerChecker<uint32_t>())
67  .AddAttribute("ReorderingTimer",
68  "Value of the t-Reordering timer (See section 7.3 of 3GPP TS 36.322)",
69  TimeValue(MilliSeconds(100)),
71  MakeTimeChecker());
72  return tid;
73 }
74 
75 void
77 {
78  NS_LOG_FUNCTION(this);
81 
83 }
84 
89 void
91 {
92  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << p->GetSize());
93 
95  {
99  p->AddPacketTag(tag);
100 
101  NS_LOG_LOGIC("Tx Buffer: New packet added");
102  m_txBuffer.emplace_back(p, Simulator::Now());
103  m_txBufferSize += p->GetSize();
104  NS_LOG_LOGIC("NumOfBuffers = " << m_txBuffer.size());
105  NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
106  }
107  else
108  {
109  // Discard full RLC SDU
110  NS_LOG_LOGIC("TxBuffer is full. RLC SDU discarded");
111  NS_LOG_LOGIC("MaxTxBufferSize = " << m_maxTxBufferSize);
112  NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
113  NS_LOG_LOGIC("packet size = " << p->GetSize());
114  m_txDropTrace(p);
115  }
116 
119  m_rbsTimer.Cancel();
120 }
121 
126 void
128 {
129  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << txOpParams.bytes);
130 
131  if (txOpParams.bytes <= 2)
132  {
133  // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
134  NS_LOG_LOGIC("TX opportunity too small = " << txOpParams.bytes);
135  return;
136  }
137 
138  Ptr<Packet> packet = Create<Packet>();
139  LteRlcHeader rlcHeader;
140 
141  // Build Data field
142  uint32_t nextSegmentSize = txOpParams.bytes - 2;
143  uint32_t nextSegmentId = 1;
144  uint32_t 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.empty())
150  {
151  NS_LOG_LOGIC("No data pending");
152  return;
153  }
154 
155  Ptr<Packet> firstSegment = m_txBuffer.begin()->m_pdu->Copy();
156  Time firstSegmentTime = m_txBuffer.begin()->m_waitingSince;
157 
158  NS_LOG_LOGIC("SDUs in TxBuffer = " << m_txBuffer.size());
159  NS_LOG_LOGIC("First SDU buffer = " << firstSegment);
160  NS_LOG_LOGIC("First SDU size = " << firstSegment->GetSize());
161  NS_LOG_LOGIC("Next segment size = " << nextSegmentSize);
162  NS_LOG_LOGIC("Remove SDU from TxBuffer");
163  m_txBufferSize -= firstSegment->GetSize();
164  NS_LOG_LOGIC("txBufferSize = " << m_txBufferSize);
165  m_txBuffer.erase(m_txBuffer.begin());
166 
167  while (firstSegment && (firstSegment->GetSize() > 0) && (nextSegmentSize > 0))
168  {
169  NS_LOG_LOGIC("WHILE ( firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 )");
170  NS_LOG_LOGIC(" firstSegment size = " << firstSegment->GetSize());
171  NS_LOG_LOGIC(" nextSegmentSize = " << nextSegmentSize);
172  if ((firstSegment->GetSize() > nextSegmentSize) ||
173  // Segment larger than 2047 octets can only be mapped to the end of the Data field
174  (firstSegment->GetSize() > 2047))
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;
192  LteRlcSduStatusTag newTag;
193  firstSegment->RemovePacketTag(oldTag);
194  newSegment->RemovePacketTag(newTag);
195  if (oldTag.GetStatus() == LteRlcSduStatusTag::FULL_SDU)
196  {
199  }
200  else if (oldTag.GetStatus() == LteRlcSduStatusTag::LAST_SEGMENT)
201  {
203  // oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT);
204  }
205 
206  // Give back the remaining segment to the transmission buffer
207  firstSegment->RemoveAtStart(currSegmentSize);
208  NS_LOG_LOGIC(
209  " firstSegment size (after RemoveAtStart) = " << firstSegment->GetSize());
210  if (firstSegment->GetSize() > 0)
211  {
212  firstSegment->AddPacketTag(oldTag);
213 
214  m_txBuffer.insert(m_txBuffer.begin(), TxPdu(firstSegment, firstSegmentTime));
215  m_txBufferSize += m_txBuffer.begin()->m_pdu->GetSize();
216 
217  NS_LOG_LOGIC(" TX buffer: Give back the remaining segment");
218  NS_LOG_LOGIC(" TX buffers = " << m_txBuffer.size());
219  NS_LOG_LOGIC(" Front buffer size = " << m_txBuffer.begin()->m_pdu->GetSize());
220  NS_LOG_LOGIC(" txBufferSize = " << m_txBufferSize);
221  }
222  else
223  {
224  // Whole segment was taken, so adjust tag
226  {
228  }
229  else if (newTag.GetStatus() == LteRlcSduStatusTag::MIDDLE_SEGMENT)
230  {
232  }
233  }
234  // Segment is completely taken or
235  // the remaining segment is given back to the transmission buffer
236  firstSegment = nullptr;
237 
238  // Put status tag once it has been adjusted
239  newSegment->AddPacketTag(newTag);
240 
241  // Add Segment to Data field
242  dataFieldAddedSize = newSegment->GetSize();
243  dataField.push_back(newSegment);
244  newSegment = nullptr;
245 
246  // ExtensionBit (Next_Segment - 1) = 0
248 
249  // no LengthIndicator for the last one
250 
251  nextSegmentSize -= dataFieldAddedSize;
252  nextSegmentId++;
253 
254  // nextSegmentSize MUST be zero (only if segment is smaller or equal to 2047)
255 
256  // (NO more segments) → exit
257  // break;
258  }
259  else if ((nextSegmentSize - firstSegment->GetSize() <= 2) || m_txBuffer.empty())
260  {
261  NS_LOG_LOGIC(
262  " IF nextSegmentSize - firstSegment->GetSize () <= 2 || txBuffer.size == 0");
263  // Add txBuffer.FirstBuffer to DataField
264  dataFieldAddedSize = firstSegment->GetSize();
265  dataField.push_back(firstSegment);
266  firstSegment = nullptr;
267 
268  // ExtensionBit (Next_Segment - 1) = 0
270 
271  // no LengthIndicator for the last one
272 
273  nextSegmentSize -= dataFieldAddedSize;
274  nextSegmentId++;
275 
276  NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txBuffer.size());
277  if (!m_txBuffer.empty())
278  {
279  NS_LOG_LOGIC(" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
280  NS_LOG_LOGIC(
281  " First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize());
282  }
283  NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
284 
285  // nextSegmentSize <= 2 (only if txBuffer is not empty)
286 
287  // (NO more segments) → exit
288  // break;
289  }
290  else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0)
291  {
292  NS_LOG_LOGIC(" IF firstSegment < NextSegmentSize && txBuffer.size > 0");
293  // Add txBuffer.FirstBuffer to DataField
294  dataFieldAddedSize = firstSegment->GetSize();
295  dataField.push_back(firstSegment);
296 
297  // ExtensionBit (Next_Segment - 1) = 1
299 
300  // LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length()
301  rlcHeader.PushLengthIndicator(firstSegment->GetSize());
302 
303  nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize;
304  nextSegmentId++;
305 
306  NS_LOG_LOGIC(" SDUs in TxBuffer = " << m_txBuffer.size());
307  if (!m_txBuffer.empty())
308  {
309  NS_LOG_LOGIC(" First SDU buffer = " << m_txBuffer.begin()->m_pdu);
310  NS_LOG_LOGIC(
311  " First SDU size = " << m_txBuffer.begin()->m_pdu->GetSize());
312  }
313  NS_LOG_LOGIC(" Next segment size = " << nextSegmentSize);
314  NS_LOG_LOGIC(" Remove SDU from TxBuffer");
315 
316  // (more segments)
317  firstSegment = m_txBuffer.begin()->m_pdu->Copy();
318  firstSegmentTime = m_txBuffer.begin()->m_waitingSince;
319  m_txBufferSize -= firstSegment->GetSize();
320  m_txBuffer.erase(m_txBuffer.begin());
321  NS_LOG_LOGIC(" txBufferSize = " << m_txBufferSize);
322  }
323  }
324 
325  // Build RLC header
326  rlcHeader.SetSequenceNumber(m_sequenceNumber++);
327 
328  // Build RLC PDU with DataField and Header
329  std::vector<Ptr<Packet>>::iterator it;
330  it = dataField.begin();
331 
332  uint8_t framingInfo = 0;
333 
334  // FIRST SEGMENT
335  LteRlcSduStatusTag tag;
336  NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
337  (*it)->PeekPacketTag(tag);
338  if ((tag.GetStatus() == LteRlcSduStatusTag::FULL_SDU) ||
340  {
341  framingInfo |= LteRlcHeader::FIRST_BYTE;
342  }
343  else
344  {
345  framingInfo |= LteRlcHeader::NO_FIRST_BYTE;
346  }
347 
348  while (it < dataField.end())
349  {
350  NS_LOG_LOGIC("Adding SDU/segment to packet, length = " << (*it)->GetSize());
351 
352  NS_ASSERT_MSG((*it)->PeekPacketTag(tag), "LteRlcSduStatusTag is missing");
353  (*it)->RemovePacketTag(tag);
354  if (packet->GetSize() > 0)
355  {
356  packet->AddAtEnd(*it);
357  }
358  else
359  {
360  packet = (*it);
361  }
362  it++;
363  }
364 
365  // LAST SEGMENT (Note: There could be only one and be the first one)
366  it--;
367  if ((tag.GetStatus() == LteRlcSduStatusTag::FULL_SDU) ||
369  {
370  framingInfo |= LteRlcHeader::LAST_BYTE;
371  }
372  else
373  {
374  framingInfo |= LteRlcHeader::NO_LAST_BYTE;
375  }
376 
377  rlcHeader.SetFramingInfo(framingInfo);
378 
379  NS_LOG_LOGIC("RLC header: " << rlcHeader);
380  packet->AddHeader(rlcHeader);
381 
382  // Sender timestamp
383  RlcTag rlcTag(Simulator::Now());
384  packet->AddByteTag(rlcTag, 1, rlcHeader.GetSerializedSize());
385  m_txPdu(m_rnti, m_lcid, packet->GetSize());
386 
387  // Send RLC PDU to MAC layer
389  params.pdu = packet;
390  params.rnti = m_rnti;
391  params.lcid = m_lcid;
392  params.layer = txOpParams.layer;
393  params.harqProcessId = txOpParams.harqId;
394  params.componentCarrierId = txOpParams.componentCarrierId;
395 
397 
398  if (!m_txBuffer.empty())
399  {
400  m_rbsTimer.Cancel();
402  }
403 }
404 
405 void
407 {
408  NS_LOG_FUNCTION(this);
409 }
410 
411 void
413 {
414  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid << rxPduParams.p->GetSize());
415 
416  // Receiver timestamp
417  RlcTag rlcTag;
418  Time delay;
419 
420  bool ret = rxPduParams.p->FindFirstMatchingByteTag(rlcTag);
421  NS_ASSERT_MSG(ret, "RlcTag is missing");
422 
423  delay = Simulator::Now() - rlcTag.GetSenderTimestamp();
424  m_rxPdu(m_rnti, m_lcid, rxPduParams.p->GetSize(), delay.GetNanoSeconds());
425 
426  // 5.1.2.2 Receive operations
427 
428  // Get RLC header parameters
429  LteRlcHeader rlcHeader;
430  rxPduParams.p->PeekHeader(rlcHeader);
431  NS_LOG_LOGIC("RLC header: " << rlcHeader);
432  SequenceNumber10 seqNumber = rlcHeader.GetSequenceNumber();
433 
434  // 5.1.2.2.1 General
435  // The receiving UM RLC entity shall maintain a reordering window according to state variable
436  // VR(UH) as follows:
437  // - a SN falls within the reordering window if (VR(UH) - UM_Window_Size) <= SN < VR(UH);
438  // - a SN falls outside of the reordering window otherwise.
439  // When receiving an UMD PDU from lower layer, the receiving UM RLC entity shall:
440  // - either discard the received UMD PDU or place it in the reception buffer (see sub
441  // clause 5.1.2.2.2);
442  // - if the received UMD PDU was placed in the reception buffer:
443  // - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop
444  // t-Reordering as needed (see sub clause 5.1.2.2.3); When t-Reordering expires, the receiving
445  // UM RLC entity shall:
446  // - update state variables, reassemble and deliver RLC SDUs to upper layer and start
447  // t-Reordering as needed (see sub clause 5.1.2.2.4).
448 
449  // 5.1.2.2.2 Actions when an UMD PDU is received from lower layer
450  // When an UMD PDU with SN = x is received from lower layer, the receiving UM RLC entity shall:
451  // - if VR(UR) < x < VR(UH) and the UMD PDU with SN = x has been received before; or
452  // - if (VR(UH) - UM_Window_Size) <= x < VR(UR):
453  // - discard the received UMD PDU;
454  // - else:
455  // - place the received UMD PDU in the reception buffer.
456 
457  NS_LOG_LOGIC("VR(UR) = " << m_vrUr);
458  NS_LOG_LOGIC("VR(UX) = " << m_vrUx);
459  NS_LOG_LOGIC("VR(UH) = " << m_vrUh);
460  NS_LOG_LOGIC("SN = " << seqNumber);
461 
464  seqNumber.SetModulusBase(m_vrUh - m_windowSize);
465 
466  if (((m_vrUr < seqNumber) && (seqNumber < m_vrUh) &&
467  (m_rxBuffer.count(seqNumber.GetValue()) > 0)) ||
468  (((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUr)))
469  {
470  NS_LOG_LOGIC("PDU discarded");
471  rxPduParams.p = nullptr;
472  return;
473  }
474  else
475  {
476  NS_LOG_LOGIC("Place PDU in the reception buffer");
477  m_rxBuffer[seqNumber.GetValue()] = rxPduParams.p;
478  }
479 
480  // 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer
481  // When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity
482  // shall:
483 
484  // - if x falls outside of the reordering window:
485  // - update VR(UH) to x + 1;
486  // - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering
487  // window, remove
488  // RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in
489  // ascending order of the RLC SN if not delivered before;
490  // - if VR(UR) falls outside of the reordering window:
491  // - set VR(UR) to (VR(UH) - UM_Window_Size);
492 
493  if (!IsInsideReorderingWindow(seqNumber))
494  {
495  NS_LOG_LOGIC("SN is outside the reordering window");
496 
497  m_vrUh = seqNumber + 1;
498  NS_LOG_LOGIC("New VR(UH) = " << m_vrUh);
499 
501 
503  {
505  NS_LOG_LOGIC("VR(UR) is outside the reordering window");
506  NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
507  }
508  }
509 
510  // - if the reception buffer contains an UMD PDU with SN = VR(UR):
511  // - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been
512  // received;
513  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when
514  // doing
515  // so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN
516  // if not delivered before;
517 
518  if (m_rxBuffer.count(m_vrUr.GetValue()) > 0)
519  {
520  NS_LOG_LOGIC("Reception buffer contains SN = " << m_vrUr);
521 
522  std::map<uint16_t, Ptr<Packet>>::iterator it;
523  uint16_t newVrUr;
524  SequenceNumber10 oldVrUr = m_vrUr;
525 
526  it = m_rxBuffer.find(m_vrUr.GetValue());
527  newVrUr = (it->first) + 1;
528  while (m_rxBuffer.count(newVrUr) > 0)
529  {
530  newVrUr++;
531  }
532  m_vrUr = newVrUr;
533  NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
534 
535  ReassembleSnInterval(oldVrUr, m_vrUr);
536  }
537 
538  // m_vrUh can change previously, set new modulus base
539  // for the t-Reordering timer-related comparisons
543 
544  // - if t-Reordering is running:
545  // - if VR(UX) <= VR(UR); or
546  // - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH)::
547  // - stop and reset t-Reordering;
549  {
550  NS_LOG_LOGIC("Reordering timer is running");
551 
552  if ((m_vrUx <= m_vrUr) || ((!IsInsideReorderingWindow(m_vrUx)) && (m_vrUx != m_vrUh)))
553  {
554  NS_LOG_LOGIC("Stop reordering timer");
556  }
557  }
558 
559  // - if t-Reordering is not running (includes the case when t-Reordering is stopped due to
560  // actions above):
561  // - if VR(UH) > VR(UR):
562  // - start t-Reordering;
563  // - set VR(UX) to VR(UH).
565  {
566  NS_LOG_LOGIC("Reordering timer is not running");
567 
568  if (m_vrUh > m_vrUr)
569  {
570  NS_LOG_LOGIC("VR(UH) > VR(UR)");
571  NS_LOG_LOGIC("Start reordering timer");
574  m_vrUx = m_vrUh;
575  NS_LOG_LOGIC("New VR(UX) = " << m_vrUx);
576  }
577  }
578 }
579 
580 bool
582 {
583  NS_LOG_FUNCTION(this << seqNumber);
584  NS_LOG_LOGIC("Reordering Window: " << m_vrUh << " - " << m_windowSize << " <= " << seqNumber
585  << " < " << m_vrUh);
586 
588  seqNumber.SetModulusBase(m_vrUh - m_windowSize);
589 
590  if (((m_vrUh - m_windowSize) <= seqNumber) && (seqNumber < m_vrUh))
591  {
592  NS_LOG_LOGIC(seqNumber << " is INSIDE the reordering window");
593  return true;
594  }
595  else
596  {
597  NS_LOG_LOGIC(seqNumber << " is OUTSIDE the reordering window");
598  return false;
599  }
600 }
601 
602 void
604 {
605  LteRlcHeader rlcHeader;
606  packet->RemoveHeader(rlcHeader);
607  uint8_t framingInfo = rlcHeader.GetFramingInfo();
608  SequenceNumber10 currSeqNumber = rlcHeader.GetSequenceNumber();
609  bool expectedSnLost;
610 
611  if (currSeqNumber != m_expectedSeqNumber)
612  {
613  expectedSnLost = true;
614  NS_LOG_LOGIC("There are losses. Expected SN = " << m_expectedSeqNumber
615  << ". Current SN = " << currSeqNumber);
616  m_expectedSeqNumber = currSeqNumber + 1;
617  }
618  else
619  {
620  expectedSnLost = false;
621  NS_LOG_LOGIC("No losses. Expected SN = " << m_expectedSeqNumber
622  << ". Current SN = " << currSeqNumber);
624  }
625 
626  // Build list of SDUs
627  uint8_t extensionBit;
628  uint16_t lengthIndicator;
629  do
630  {
631  extensionBit = rlcHeader.PopExtensionBit();
632  NS_LOG_LOGIC("E = " << (uint16_t)extensionBit);
633 
634  if (extensionBit == 0)
635  {
636  m_sdusBuffer.push_back(packet);
637  }
638  else // extensionBit == 1
639  {
640  lengthIndicator = rlcHeader.PopLengthIndicator();
641  NS_LOG_LOGIC("LI = " << lengthIndicator);
642 
643  // Check if there is enough data in the packet
644  if (lengthIndicator >= packet->GetSize())
645  {
646  NS_LOG_LOGIC("INTERNAL ERROR: Not enough data in the packet ("
647  << packet->GetSize() << "). Needed LI=" << lengthIndicator);
648  }
649 
650  // Split packet in two fragments
651  Ptr<Packet> data_field = packet->CreateFragment(0, lengthIndicator);
652  packet->RemoveAtStart(lengthIndicator);
653 
654  m_sdusBuffer.push_back(data_field);
655  }
656  } while (extensionBit == 1);
657 
658  std::list<Ptr<Packet>>::iterator it;
659 
660  // Current reassembling state
662  NS_LOG_LOGIC("Reassembling State = 'WAITING_S0_FULL'");
664  NS_LOG_LOGIC("Reassembling State = 'WAITING_SI_SF'");
665  else
666  NS_LOG_LOGIC("Reassembling State = Unknown state");
667 
668  // Received framing Info
669  NS_LOG_LOGIC("Framing Info = " << (uint16_t)framingInfo);
670 
671  // Reassemble the list of SDUs (when there is no losses)
672  if (!expectedSnLost)
673  {
674  switch (m_reassemblingState)
675  {
676  case WAITING_S0_FULL:
677  switch (framingInfo)
678  {
681 
685  for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
686  {
688  }
689  m_sdusBuffer.clear();
690  break;
691 
694 
698  while (m_sdusBuffer.size() > 1)
699  {
701  m_sdusBuffer.pop_front();
702  }
703 
707  m_keepS0 = m_sdusBuffer.front();
708  m_sdusBuffer.pop_front();
709  break;
710 
713 
717  m_sdusBuffer.pop_front();
718 
722  while (!m_sdusBuffer.empty())
723  {
725  m_sdusBuffer.pop_front();
726  }
727  break;
728 
730  if (m_sdusBuffer.size() == 1)
731  {
733  }
734  else
735  {
737  }
738 
742  m_sdusBuffer.pop_front();
743 
744  if (!m_sdusBuffer.empty())
745  {
749  while (m_sdusBuffer.size() > 1)
750  {
752  m_sdusBuffer.pop_front();
753  }
754 
758  m_keepS0 = m_sdusBuffer.front();
759  m_sdusBuffer.pop_front();
760  }
761  break;
762 
763  default:
767  NS_LOG_LOGIC(
768  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
769  break;
770  }
771  break;
772 
773  case WAITING_SI_SF:
774  switch (framingInfo)
775  {
778 
782  m_keepS0->AddAtEnd(m_sdusBuffer.front());
783  m_sdusBuffer.pop_front();
785 
789  while (!m_sdusBuffer.empty())
790  {
792  m_sdusBuffer.pop_front();
793  }
794  break;
795 
798 
802  if (m_sdusBuffer.size() == 1)
803  {
804  m_keepS0->AddAtEnd(m_sdusBuffer.front());
805  m_sdusBuffer.pop_front();
806  }
807  else // m_sdusBuffer.size () > 1
808  {
812  m_keepS0->AddAtEnd(m_sdusBuffer.front());
813  m_sdusBuffer.pop_front();
815 
819  while (m_sdusBuffer.size() > 1)
820  {
822  m_sdusBuffer.pop_front();
823  }
824 
828  m_keepS0 = m_sdusBuffer.front();
829  m_sdusBuffer.pop_front();
830  }
831  break;
832 
835  default:
839  NS_LOG_LOGIC(
840  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
841  break;
842  }
843  break;
844 
845  default:
846  NS_LOG_LOGIC(
847  "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
848  break;
849  }
850  }
851  else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the
852  // expected one)
853  {
854  switch (m_reassemblingState)
855  {
856  case WAITING_S0_FULL:
857  switch (framingInfo)
858  {
861 
865  for (it = m_sdusBuffer.begin(); it != m_sdusBuffer.end(); it++)
866  {
868  }
869  m_sdusBuffer.clear();
870  break;
871 
874 
878  while (m_sdusBuffer.size() > 1)
879  {
881  m_sdusBuffer.pop_front();
882  }
883 
887  m_keepS0 = m_sdusBuffer.front();
888  m_sdusBuffer.pop_front();
889  break;
890 
893 
897  m_sdusBuffer.pop_front();
898 
902  while (!m_sdusBuffer.empty())
903  {
905  m_sdusBuffer.pop_front();
906  }
907  break;
908 
910  if (m_sdusBuffer.size() == 1)
911  {
913  }
914  else
915  {
917  }
918 
922  m_sdusBuffer.pop_front();
923 
924  if (!m_sdusBuffer.empty())
925  {
929  while (m_sdusBuffer.size() > 1)
930  {
932  m_sdusBuffer.pop_front();
933  }
934 
938  m_keepS0 = m_sdusBuffer.front();
939  m_sdusBuffer.pop_front();
940  }
941  break;
942 
943  default:
947  NS_LOG_LOGIC(
948  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
949  break;
950  }
951  break;
952 
953  case WAITING_SI_SF:
954  switch (framingInfo)
955  {
958 
962  m_keepS0 = nullptr;
963 
967  while (!m_sdusBuffer.empty())
968  {
970  m_sdusBuffer.pop_front();
971  }
972  break;
973 
976 
980  m_keepS0 = nullptr;
981 
985  while (m_sdusBuffer.size() > 1)
986  {
988  m_sdusBuffer.pop_front();
989  }
990 
994  m_keepS0 = m_sdusBuffer.front();
995  m_sdusBuffer.pop_front();
996 
997  break;
998 
1001 
1005  m_keepS0 = nullptr;
1006 
1010  m_sdusBuffer.pop_front();
1011 
1015  while (!m_sdusBuffer.empty())
1016  {
1018  m_sdusBuffer.pop_front();
1019  }
1020  break;
1021 
1023  if (m_sdusBuffer.size() == 1)
1024  {
1026  }
1027  else
1028  {
1030  }
1031 
1035  m_keepS0 = nullptr;
1036 
1040  m_sdusBuffer.pop_front();
1041 
1042  if (!m_sdusBuffer.empty())
1043  {
1047  while (m_sdusBuffer.size() > 1)
1048  {
1050  m_sdusBuffer.pop_front();
1051  }
1052 
1056  m_keepS0 = m_sdusBuffer.front();
1057  m_sdusBuffer.pop_front();
1058  }
1059  break;
1060 
1061  default:
1065  NS_LOG_LOGIC(
1066  "INTERNAL ERROR: Transition not possible. FI = " << (uint32_t)framingInfo);
1067  break;
1068  }
1069  break;
1070 
1071  default:
1072  NS_LOG_LOGIC(
1073  "INTERNAL ERROR: Wrong reassembling state = " << (uint32_t)m_reassemblingState);
1074  break;
1075  }
1076  }
1077 }
1078 
1079 void
1081 {
1082  NS_LOG_LOGIC("Reassemble Outside Window");
1083 
1084  std::map<uint16_t, Ptr<Packet>>::iterator it;
1085  it = m_rxBuffer.begin();
1086 
1087  while ((it != m_rxBuffer.end()) && !IsInsideReorderingWindow(SequenceNumber10(it->first)))
1088  {
1089  NS_LOG_LOGIC("SN = " << it->first);
1090 
1091  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1092  ReassembleAndDeliver(it->second);
1093 
1094  std::map<uint16_t, Ptr<Packet>>::iterator it_tmp = it;
1095  ++it;
1096  m_rxBuffer.erase(it_tmp);
1097  }
1098 
1099  if (it != m_rxBuffer.end())
1100  {
1101  NS_LOG_LOGIC("(SN = " << it->first << ") is inside the reordering window");
1102  }
1103 }
1104 
1105 void
1107 {
1108  NS_LOG_LOGIC("Reassemble SN between " << lowSeqNumber << " and " << highSeqNumber);
1109 
1110  std::map<uint16_t, Ptr<Packet>>::iterator it;
1111 
1112  SequenceNumber10 reassembleSn = lowSeqNumber;
1113  NS_LOG_LOGIC("reassembleSN = " << reassembleSn);
1114  NS_LOG_LOGIC("highSeqNumber = " << highSeqNumber);
1115  while (reassembleSn < highSeqNumber)
1116  {
1117  NS_LOG_LOGIC("reassembleSn < highSeqNumber");
1118  it = m_rxBuffer.find(reassembleSn.GetValue());
1119  NS_LOG_LOGIC("it->first = " << it->first);
1120  NS_LOG_LOGIC("it->second = " << it->second);
1121  if (it != m_rxBuffer.end())
1122  {
1123  NS_LOG_LOGIC("SN = " << it->first);
1124 
1125  // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer
1126  ReassembleAndDeliver(it->second);
1127 
1128  m_rxBuffer.erase(it);
1129  }
1130 
1131  reassembleSn++;
1132  }
1133 }
1134 
1135 void
1137 {
1138  Time holDelay(0);
1139  uint32_t queueSize = 0;
1140 
1141  if (!m_txBuffer.empty())
1142  {
1143  holDelay = Simulator::Now() - m_txBuffer.front().m_waitingSince;
1144 
1145  queueSize =
1146  m_txBufferSize + 2 * m_txBuffer.size(); // Data in tx queue + estimated headers size
1147  }
1148 
1150  r.rnti = m_rnti;
1151  r.lcid = m_lcid;
1152  r.txQueueSize = queueSize;
1153  r.txQueueHolDelay = holDelay.GetMilliSeconds();
1154  r.retxQueueSize = 0;
1155  r.retxQueueHolDelay = 0;
1156  r.statusPduSize = 0;
1157 
1158  NS_LOG_LOGIC("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay);
1160 }
1161 
1162 void
1164 {
1165  NS_LOG_FUNCTION(this << m_rnti << (uint32_t)m_lcid);
1166  NS_LOG_LOGIC("Reordering timer has expired");
1167 
1168  // 5.1.2.2.4 Actions when t-Reordering expires
1169  // When t-Reordering expires, the receiving UM RLC entity shall:
1170  // - update VR(UR) to the SN of the first UMD PDU with SN >= VR(UX) that has not been received;
1171  // - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when
1172  // doing so
1173  // and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not
1174  // delivered before;
1175  // - if VR(UH) > VR(UR):
1176  // - start t-Reordering;
1177  // - set VR(UX) to VR(UH).
1178 
1179  std::map<uint16_t, Ptr<Packet>>::iterator it;
1180  SequenceNumber10 newVrUr = m_vrUx;
1181 
1182  while ((it = m_rxBuffer.find(newVrUr.GetValue())) != m_rxBuffer.end())
1183  {
1184  newVrUr++;
1185  }
1186  SequenceNumber10 oldVrUr = m_vrUr;
1187  m_vrUr = newVrUr;
1188  NS_LOG_LOGIC("New VR(UR) = " << m_vrUr);
1189 
1190  ReassembleSnInterval(oldVrUr, m_vrUr);
1191 
1192  if (m_vrUh > m_vrUr)
1193  {
1194  NS_LOG_LOGIC("Start reordering timer");
1197  m_vrUx = m_vrUh;
1198  NS_LOG_LOGIC("New VR(UX) = " << m_vrUx);
1199  }
1200 }
1201 
1202 void
1204 {
1205  NS_LOG_LOGIC("RBS Timer expires");
1206 
1207  if (!m_txBuffer.empty())
1208  {
1211  }
1212 }
1213 
1214 } // namespace ns3
#define min(a, b)
Definition: 80211b.c:42
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
virtual void TransmitPdu(TransmitPduParameters params)=0
send an RLC PDU to the MAC for transmission.
virtual void ReportBufferStatus(ReportBufferStatusParameters params)=0
Report the RLC buffer status to the MAC.
The packet header for the Radio Link Control (RLC) protocol packets.
uint32_t GetSerializedSize() const override
void PushExtensionBit(uint8_t extensionBit)
Push extension bit.
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
void SetSequenceNumber(SequenceNumber10 sequenceNumber)
Set sequence number.
void SetFramingInfo(uint8_t framingInfo)
Set framing info.
uint8_t PopExtensionBit()
Pop extension bit.
uint16_t PopLengthIndicator()
Pop length indicator.
uint8_t GetFramingInfo() const
Get framing info.
void PushLengthIndicator(uint16_t lengthIndicator)
Push length indicator.
This abstract base class defines the API to interact with the Radio Link Control (LTE_RLC) in LTE,...
Definition: lte-rlc.h:48
LteRlcSapUser * m_rlcSapUser
RLC SAP user.
Definition: lte-rlc.h:142
uint8_t m_lcid
LCID.
Definition: lte-rlc.h:167
TracedCallback< Ptr< const Packet > > m_txDropTrace
The trace source fired when the RLC drops a packet before transmission.
Definition: lte-rlc.h:181
uint16_t m_rnti
RNTI.
Definition: lte-rlc.h:166
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:176
void DoDispose() override
Destructor implementation.
Definition: lte-rlc.cc:126
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition: lte-rlc.h:164
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:172
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.
This class implements a tag that carries the status of a RLC SDU for the fragmentation process Status...
uint8_t GetStatus() const
Get status function.
void SetStatus(uint8_t status)
Set status function.
LTE RLC Unacknowledged Mode (UM), see 3GPP TS 36.322.
Definition: lte-rlc-um.h:36
SequenceNumber10 m_vrUr
VR(UR)
Definition: lte-rlc-um.h:134
Ptr< Packet > m_keepS0
keep S0
Definition: lte-rlc-um.h:161
void ReassembleAndDeliver(Ptr< Packet > packet)
Reassemble and deliver function.
Definition: lte-rlc-um.cc:603
void DoReportBufferStatus()
Report buffer status.
Definition: lte-rlc-um.cc:1136
uint32_t m_txBufferSize
transmit buffer size
Definition: lte-rlc-um.h:99
static TypeId GetTypeId()
Get the type ID.
Definition: lte-rlc-um.cc:55
void ReassembleOutsideWindow()
Reassemble outside window.
Definition: lte-rlc-um.cc:1080
void DoDispose() override
Destructor implementation.
Definition: lte-rlc-um.cc:76
void ExpireReorderingTimer()
Expire reordering timer.
Definition: lte-rlc-um.cc:1163
std::vector< TxPdu > m_txBuffer
Transmission buffer.
Definition: lte-rlc-um.h:123
Time m_reorderingTimerValue
Timers.
Definition: lte-rlc-um.h:146
~LteRlcUm() override
Definition: lte-rlc-um.cc:49
SequenceNumber10 m_expectedSeqNumber
Expected Sequence Number.
Definition: lte-rlc-um.h:166
ReassemblingState_t m_reassemblingState
reassembling state
Definition: lte-rlc-um.h:160
void ReassembleSnInterval(SequenceNumber10 lowSeqNumber, SequenceNumber10 highSeqNumber)
Reassemble SN interval function.
Definition: lte-rlc-um.cc:1106
void ExpireRbsTimer()
Expire RBS timer.
Definition: lte-rlc-um.cc:1203
EventId m_rbsTimer
RBS timer.
Definition: lte-rlc-um.h:148
void DoNotifyTxOpportunity(LteMacSapUser::TxOpportunityParameters txOpParams) override
MAC SAP.
Definition: lte-rlc-um.cc:127
SequenceNumber10 m_vrUx
VR(UX)
Definition: lte-rlc-um.h:135
uint16_t m_windowSize
Constants.
Definition: lte-rlc-um.h:141
std::map< uint16_t, Ptr< Packet > > m_rxBuffer
Reception buffer.
Definition: lte-rlc-um.h:124
void DoNotifyHarqDeliveryFailure() override
Notify HARQ delivery failure.
Definition: lte-rlc-um.cc:406
SequenceNumber10 m_vrUh
VR(UH)
Definition: lte-rlc-um.h:136
void DoTransmitPdcpPdu(Ptr< Packet > p) override
RLC SAP.
Definition: lte-rlc-um.cc:90
void DoReceivePdu(LteMacSapUser::ReceivePduParameters rxPduParams) override
Receive PDU function.
Definition: lte-rlc-um.cc:412
uint32_t m_maxTxBufferSize
maximum transmit buffer status
Definition: lte-rlc-um.h:98
std::list< Ptr< Packet > > m_sdusBuffer
List of SDUs in a packet.
Definition: lte-rlc-um.h:127
EventId m_reorderingTimer
reordering timer
Definition: lte-rlc-um.h:147
bool IsInsideReorderingWindow(SequenceNumber10 seqNumber)
Is inside reordering window function.
Definition: lte-rlc-um.cc:581
SequenceNumber10 m_sequenceNumber
State variables.
Definition: lte-rlc-um.h:132
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:384
bool FindFirstMatchingByteTag(Tag &tag) const
Finds the first tag matching the parameter Tag type.
Definition: packet.cc:962
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
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:238
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:934
Tag to calculate the per-PDU delay from eNb RLC to UE RLC.
Definition: lte-rlc-tag.h:36
Time GetSenderTimestamp() const
Get the instant when the RLC delivers the PDU to the MAC SAP provider.
Definition: lte-rlc-tag.h:64
SequenceNumber10 class.
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
void SetModulusBase(SequenceNumber10 modulusBase)
Set modulus base.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetNanoSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:417
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:407
AttributeValue implementation for Time.
Definition: nstime.h:1423
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
#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:86
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
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:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
Parameters for LteMacSapProvider::ReportBufferStatus.
Definition: lte-mac-sap.h:69
uint32_t txQueueSize
the current size of the RLC transmission queue
Definition: lte-mac-sap.h:72
uint16_t retxQueueHolDelay
the Head Of Line delay of the retransmission queue
Definition: lte-mac-sap.h:75
uint16_t txQueueHolDelay
the Head Of Line delay of the transmission queue
Definition: lte-mac-sap.h:73
uint32_t retxQueueSize
the current size of the RLC retransmission queue in bytes
Definition: lte-mac-sap.h:74
uint8_t lcid
the logical channel id corresponding to the sending RLC instance
Definition: lte-mac-sap.h:71
uint16_t rnti
the C-RNTI identifying the UE
Definition: lte-mac-sap.h:70
uint16_t statusPduSize
the current size of the pending STATUS RLC PDU message in bytes
Definition: lte-mac-sap.h:77
Parameters for LteMacSapProvider::TransmitPdu.
Definition: lte-mac-sap.h:45
Parameters for LteMacSapUser::ReceivePdu.
Definition: lte-mac-sap.h:166
Ptr< Packet > p
the RLC PDU to be received
Definition: lte-mac-sap.h:187
Parameters for LteMacSapUser::NotifyTxOpportunity.
Definition: lte-mac-sap.h:105
uint32_t bytes
the number of bytes to transmit
Definition: lte-mac-sap.h:137
uint8_t componentCarrierId
the component carrier id
Definition: lte-mac-sap.h:140
uint8_t layer
the layer of transmission (MIMO)
Definition: lte-mac-sap.h:138
Store an incoming (from layer above us) PDU, waiting to transmit it.
Definition: lte-rlc-um.h:105