author | Marco Miozzo <marco.miozzo@cttc.es> |
Thu, 22 Mar 2012 18:16:01 +0100 | |
changeset 8714 | 398bbcbb3f42 |
parent 8456 | 782a47ccaf2a |
child 8726 | f6f0e2531457 |
permissions | -rw-r--r-- |
8448 | 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-am-header.h" |
|
25 |
#include "ns3/lte-rlc-am.h" |
|
26 |
#include "ns3/lte-rlc-sdu-status-tag.h" |
|
27 |
#include "ns3/lte-rlc-tag.h" |
|
28 |
||
29 |
NS_LOG_COMPONENT_DEFINE ("LteRlcAm"); |
|
30 |
||
31 |
namespace ns3 { |
|
32 |
||
33 |
NS_OBJECT_ENSURE_REGISTERED (LteRlcAm); |
|
34 |
||
35 |
LteRlcAm::LteRlcAm () |
|
36 |
{ |
|
37 |
NS_LOG_FUNCTION (this); |
|
38 |
||
39 |
// Buffers |
|
40 |
m_txonBufferSize = 0; |
|
41 |
m_retxBuffer.resize (512); |
|
42 |
m_retxBufferSize = 0; |
|
43 |
m_txedBuffer.resize (512); |
|
44 |
m_txedBufferSize = 0; |
|
45 |
||
46 |
m_statusPduRequested = false; |
|
47 |
m_statusPduBufferSize = 0; |
|
48 |
||
49 |
// State variables: transmitting side |
|
50 |
m_windowSize = 512; |
|
51 |
m_vtA = 0; |
|
52 |
m_vtMs = m_vtA + m_windowSize; |
|
53 |
m_vtS = 0; |
|
54 |
m_pollSn = 0; |
|
55 |
||
56 |
// State variables: receiving side |
|
57 |
m_vrR = 0; |
|
58 |
m_vrMr = m_vrR + m_windowSize; |
|
59 |
m_vrX = 0; |
|
60 |
m_vrMs = 0; |
|
61 |
m_vrH = 0; |
|
62 |
||
63 |
// Counters |
|
64 |
m_pduWithoutPoll = 0; |
|
65 |
m_byteWithoutPoll = 0; |
|
66 |
||
67 |
// Configurable parameters |
|
68 |
m_maxRetxThreshold = 5; |
|
69 |
m_pollPdu = 1; |
|
70 |
m_pollByte = 50; |
|
71 |
||
72 |
// SDU reassembling process |
|
73 |
m_reassemblingState = WAITING_S0_FULL; |
|
74 |
m_expectedSeqNumber = 0; |
|
75 |
||
76 |
Simulator::ScheduleNow (&LteRlcAm::Start, this); |
|
77 |
} |
|
78 |
||
79 |
LteRlcAm::~LteRlcAm () |
|
80 |
{ |
|
81 |
} |
|
82 |
||
83 |
TypeId |
|
84 |
LteRlcAm::GetTypeId (void) |
|
85 |
{ |
|
86 |
static TypeId tid = TypeId ("ns3::LteRlcAm") |
|
87 |
.SetParent<LteRlc> () |
|
88 |
.AddConstructor<LteRlcAm> () |
|
89 |
; |
|
90 |
return tid; |
|
91 |
} |
|
92 |
||
93 |
||
94 |
/** |
|
95 |
* RLC SAP |
|
96 |
*/ |
|
97 |
||
98 |
void |
|
99 |
LteRlcAm::DoTransmitPdcpPdu (Ptr<Packet> p) |
|
100 |
{ |
|
101 |
NS_LOG_FUNCTION (this); |
|
102 |
||
103 |
/** Store arrival time */ |
|
104 |
Time now = Simulator::Now (); |
|
105 |
RlcTag timeTag (now); |
|
106 |
p->AddPacketTag (timeTag); |
|
107 |
||
108 |
/** Store PDCP PDU */ |
|
109 |
||
110 |
LteRlcSduStatusTag tag; |
|
111 |
tag.SetStatus (LteRlcSduStatusTag::FULL_SDU); |
|
112 |
p->AddPacketTag (tag); |
|
113 |
||
114 |
NS_LOG_LOGIC ("Txon Buffer: New packet added"); |
|
115 |
m_txonBuffer.push_back (p); |
|
116 |
m_txonBufferSize += p->GetSize (); |
|
117 |
NS_LOG_LOGIC ("NumOfBuffers = " << m_txonBuffer.size() ); |
|
118 |
NS_LOG_LOGIC ("txonBufferSize = " << m_txonBufferSize); |
|
119 |
||
120 |
/** Report Buffer Status */ |
|
121 |
||
122 |
// Transmission Queue HOL time |
|
123 |
RlcTag txonQueueHolTimeTag; |
|
124 |
m_txonBuffer.front ()->PeekPacketTag (txonQueueHolTimeTag); |
|
125 |
Time txonQueueHolDelay = now - txonQueueHolTimeTag.GetSenderTimestamp (); |
|
126 |
||
127 |
// Retransmission Queue HOL time |
|
128 |
RlcTag retxQueueHolTimeTag; |
|
129 |
Time retxQueueHolDelay (0); |
|
130 |
if ( m_retxBufferSize ) |
|
131 |
{ |
|
132 |
m_retxBuffer.front ().m_pdu->PeekPacketTag (retxQueueHolTimeTag); |
|
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
133 |
retxQueueHolDelay = now - retxQueueHolTimeTag.GetSenderTimestamp (); |
8448 | 134 |
} |
135 |
||
136 |
LteMacSapProvider::ReportBufferStatusParameters r; |
|
137 |
r.rnti = m_rnti; |
|
138 |
r.lcid = m_lcid; |
|
139 |
r.txQueueSize = m_txonBufferSize; |
|
140 |
r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds (); |
|
141 |
r.retxQueueSize = m_retxBufferSize; |
|
142 |
r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds (); |
|
143 |
||
144 |
if ( m_statusPduRequested && ! m_statusProhibitTimer.IsRunning () ) |
|
145 |
{ |
|
146 |
r.statusPduSize = m_statusPduBufferSize; |
|
147 |
} |
|
148 |
else |
|
149 |
{ |
|
150 |
r.statusPduSize = 0; |
|
151 |
} |
|
152 |
||
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
153 |
NS_LOG_INFO ("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay << ", " |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
154 |
<< r.retxQueueSize << ", " << r.retxQueueHolDelay << ", " |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
155 |
<< r.statusPduSize); |
8448 | 156 |
m_macSapProvider->ReportBufferStatus (r); |
157 |
} |
|
158 |
||
159 |
||
160 |
/** |
|
161 |
* MAC SAP |
|
162 |
*/ |
|
163 |
||
164 |
void |
|
8714
398bbcbb3f42
Add MIMO model, test and documentation
Marco Miozzo <marco.miozzo@cttc.es>
parents:
8456
diff
changeset
|
165 |
LteRlcAm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer) |
8448 | 166 |
{ |
167 |
NS_LOG_FUNCTION (this << bytes); |
|
168 |
NS_ASSERT_MSG (bytes > 2, "Tx opportunity too small = " << bytes); |
|
169 |
||
170 |
if ( m_statusPduRequested && ! m_statusProhibitTimer.IsRunning () ) |
|
171 |
{ |
|
172 |
NS_LOG_LOGIC ("Sending STATUS PDU"); |
|
173 |
||
174 |
Ptr<Packet> packet = Create<Packet> (); |
|
175 |
LteRlcAmHeader rlcAmHeader; |
|
176 |
rlcAmHeader.SetControlPdu (LteRlcAmHeader::STATUS_PDU); |
|
177 |
rlcAmHeader.SetAckSn (m_vrR); |
|
178 |
||
179 |
NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader); |
|
180 |
packet->AddHeader (rlcAmHeader); |
|
181 |
||
182 |
// Send RLC PDU to MAC layer |
|
183 |
LteMacSapProvider::TransmitPduParameters params; |
|
184 |
params.pdu = packet; |
|
185 |
params.rnti = m_rnti; |
|
186 |
params.lcid = m_lcid; |
|
187 |
||
188 |
m_macSapProvider->TransmitPdu (params); |
|
189 |
} |
|
190 |
else if ( m_retxBufferSize > 0 ) |
|
191 |
{ |
|
192 |
NS_LOG_LOGIC ("Sending data from Retransmission Buffer"); |
|
193 |
} |
|
194 |
else if ( m_txonBufferSize > 0 ) |
|
195 |
{ |
|
196 |
NS_LOG_LOGIC ("Sending data from Transmission Buffer"); |
|
197 |
} |
|
198 |
else |
|
199 |
{ |
|
200 |
NS_LOG_LOGIC ("No data pending"); |
|
201 |
return; |
|
202 |
} |
|
203 |
||
204 |
// |
|
205 |
// |
|
206 |
// Build new PDU |
|
207 |
// |
|
208 |
// |
|
209 |
||
210 |
Ptr<Packet> packet = Create<Packet> (); |
|
211 |
LteRlcAmHeader rlcAmHeader; |
|
212 |
rlcAmHeader.SetDataPdu (); |
|
213 |
||
214 |
// Build Data field |
|
215 |
uint32_t nextSegmentSize = bytes - 2; |
|
216 |
uint32_t nextSegmentId = 1; |
|
217 |
uint32_t dataFieldTotalSize = 0; |
|
218 |
uint32_t dataFieldAddedSize = 0; |
|
219 |
std::vector < Ptr<Packet> > dataField; |
|
220 |
||
221 |
// Remove the first packet from the transmission buffer. |
|
222 |
// If only a segment of the packet is taken, then the remaining is given back later |
|
223 |
if ( m_txonBuffer.size () == 0 ) |
|
224 |
{ |
|
225 |
NS_LOG_LOGIC ("No data pending"); |
|
226 |
return; |
|
227 |
} |
|
228 |
||
229 |
NS_LOG_LOGIC ("SDUs in TxonBuffer = " << m_txonBuffer.size ()); |
|
230 |
NS_LOG_LOGIC ("First SDU buffer = " << *(m_txonBuffer.begin())); |
|
231 |
NS_LOG_LOGIC ("First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ()); |
|
232 |
NS_LOG_LOGIC ("Next segment size = " << nextSegmentSize); |
|
233 |
NS_LOG_LOGIC ("Remove SDU from TxBuffer"); |
|
234 |
Ptr<Packet> firstSegment = (*(m_txonBuffer.begin ()))->Copy (); |
|
235 |
m_txonBufferSize -= (*(m_txonBuffer.begin()))->GetSize (); |
|
236 |
NS_LOG_LOGIC ("txBufferSize = " << m_txonBufferSize ); |
|
237 |
m_txonBuffer.erase (m_txonBuffer.begin ()); |
|
238 |
||
239 |
while ( firstSegment && (firstSegment->GetSize () > 0) && (nextSegmentSize > 0) ) |
|
240 |
{ |
|
241 |
NS_LOG_LOGIC ("WHILE .. firstSegment && firstSegment->GetSize > 0 && nextSegmentSize > 0 .."); |
|
242 |
NS_LOG_LOGIC (" FirstSegment size = " << firstSegment->GetSize ()); |
|
243 |
NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize); |
|
244 |
if ( firstSegment->GetSize () > nextSegmentSize ) |
|
245 |
{ |
|
246 |
NS_LOG_LOGIC (" IF firstSegment > NextSegmentSize"); |
|
247 |
// Segment txBuffer.FirstBuffer and |
|
248 |
// Give back the remaining segment to the transmission buffer |
|
249 |
Ptr<Packet> newSegment = firstSegment->CreateFragment (0, nextSegmentSize); |
|
250 |
||
251 |
// Status tag of the new and remaining segments |
|
252 |
// Note: This is the only place where a PDU is segmented and |
|
253 |
// therefore its status can change |
|
254 |
LteRlcSduStatusTag oldTag, newTag; // TODO CreateFragment copy the tag??? |
|
255 |
firstSegment->RemovePacketTag (oldTag); |
|
256 |
newSegment->RemovePacketTag (newTag); |
|
257 |
if (oldTag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) |
|
258 |
{ |
|
259 |
newTag.SetStatus (LteRlcSduStatusTag::FIRST_SEGMENT); |
|
260 |
oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT); |
|
261 |
} |
|
262 |
else if (oldTag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT) |
|
263 |
{ |
|
264 |
newTag.SetStatus (LteRlcSduStatusTag::MIDDLE_SEGMENT); |
|
265 |
//oldTag.SetStatus (LteRlcSduStatusTag::LAST_SEGMENT); |
|
266 |
} |
|
267 |
firstSegment->AddPacketTag (oldTag); |
|
268 |
newSegment->AddPacketTag (newTag); // TODO What happens if we add two tags??? |
|
269 |
||
270 |
// Give back the remaining segment to the transmission buffer |
|
271 |
firstSegment->RemoveAtStart (nextSegmentSize); |
|
272 |
m_txonBuffer.insert (m_txonBuffer.begin (), firstSegment); |
|
273 |
m_txonBufferSize += (*(m_txonBuffer.begin()))->GetSize (); |
|
274 |
firstSegment = 0; // TODO how to put a null ptr to Packet? |
|
275 |
||
276 |
NS_LOG_LOGIC (" TX buffer: Give back the remaining segment"); |
|
277 |
NS_LOG_LOGIC (" TX buffers = " << m_txonBuffer.size ()); |
|
278 |
NS_LOG_LOGIC (" Front buffer size = " << (*(m_txonBuffer.begin()))->GetSize ()); |
|
279 |
NS_LOG_LOGIC (" txBufferSize = " << m_txonBufferSize ); |
|
280 |
||
281 |
// Add Segment to Data field |
|
282 |
dataFieldAddedSize = newSegment->GetSize (); |
|
283 |
dataFieldTotalSize += dataFieldAddedSize; |
|
284 |
dataField.push_back (newSegment); |
|
285 |
newSegment = 0; // TODO how to put a null ptr to Packet? |
|
286 |
||
287 |
// ExtensionBit (Next_Segment - 1) = 0 |
|
288 |
rlcAmHeader.PushExtensionBit (LteRlcAmHeader::DATA_FIELD_FOLLOWS); |
|
289 |
||
290 |
// no LengthIndicator for the last one |
|
291 |
||
292 |
nextSegmentSize -= dataFieldAddedSize; |
|
293 |
nextSegmentId++; |
|
294 |
||
295 |
// nextSegmentSize MUST be zero |
|
296 |
||
297 |
// (NO more segments) → exit |
|
298 |
// break; |
|
299 |
} |
|
300 |
else if ( (firstSegment->GetSize () == nextSegmentSize) || (m_txonBuffer.size () == 0) ) |
|
301 |
{ |
|
302 |
NS_LOG_LOGIC (" IF firstSegment == NextSegmentSize || txonBuffer.size == 0"); |
|
303 |
// Add txBuffer.FirstBuffer to DataField |
|
304 |
dataFieldAddedSize = firstSegment->GetSize (); |
|
305 |
dataFieldTotalSize += dataFieldAddedSize; |
|
306 |
dataField.push_back (firstSegment); |
|
307 |
firstSegment = 0; // TODO how to put a null ptr to Packet? |
|
308 |
||
309 |
// ExtensionBit (Next_Segment - 1) = 0 |
|
310 |
rlcAmHeader.PushExtensionBit (LteRlcAmHeader::DATA_FIELD_FOLLOWS); |
|
311 |
||
312 |
// no LengthIndicator for the last one |
|
313 |
||
314 |
nextSegmentSize -= dataFieldAddedSize; |
|
315 |
nextSegmentId++; |
|
316 |
||
317 |
NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ()); |
|
318 |
if (m_txonBuffer.size () > 0) |
|
319 |
{ |
|
320 |
NS_LOG_LOGIC (" First SDU buffer = " << *(m_txonBuffer.begin())); |
|
321 |
NS_LOG_LOGIC (" First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ()); |
|
322 |
} |
|
323 |
NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize << " (should be 0)"); |
|
324 |
||
325 |
// nextSegmentSize MUST be zero |
|
326 |
||
327 |
// (NO more segments) → exit |
|
328 |
// break; |
|
329 |
} |
|
330 |
else // (firstSegment->GetSize () < m_nextSegmentSize) && (m_txBuffer.size () > 0) |
|
331 |
{ |
|
332 |
NS_LOG_LOGIC (" IF firstSegment < NextSegmentSize && txonBuffer.size > 0"); |
|
333 |
// Add txBuffer.FirstBuffer to DataField |
|
334 |
dataFieldAddedSize = firstSegment->GetSize (); |
|
335 |
dataFieldTotalSize += dataFieldAddedSize; |
|
336 |
dataField.push_back (firstSegment); |
|
337 |
||
338 |
// ExtensionBit (Next_Segment - 1) = 1 |
|
339 |
rlcAmHeader.PushExtensionBit (LteRlcAmHeader::E_LI_FIELDS_FOLLOWS); |
|
340 |
||
341 |
// LengthIndicator (Next_Segment) = txBuffer.FirstBuffer.length() |
|
342 |
rlcAmHeader.PushLengthIndicator (firstSegment->GetSize ()); |
|
343 |
||
344 |
nextSegmentSize -= ((nextSegmentId % 2) ? (2) : (1)) + dataFieldAddedSize; // TODO??? |
|
345 |
nextSegmentId++; |
|
346 |
||
347 |
NS_LOG_LOGIC (" SDUs in TxBuffer = " << m_txonBuffer.size ()); |
|
348 |
if (m_txonBuffer.size () > 0) |
|
349 |
{ |
|
350 |
NS_LOG_LOGIC (" First SDU buffer = " << *(m_txonBuffer.begin())); |
|
351 |
NS_LOG_LOGIC (" First SDU size = " << (*(m_txonBuffer.begin()))->GetSize ()); |
|
352 |
} |
|
353 |
NS_LOG_LOGIC (" Next segment size = " << nextSegmentSize); |
|
354 |
NS_LOG_LOGIC (" Remove SDU from TxBuffer"); |
|
355 |
||
356 |
// (more segments) |
|
357 |
firstSegment = (*(m_txonBuffer.begin ()))->Copy (); |
|
358 |
m_txonBufferSize -= (*(m_txonBuffer.begin()))->GetSize (); |
|
359 |
m_txonBuffer.erase (m_txonBuffer.begin ()); |
|
360 |
NS_LOG_LOGIC (" txBufferSize = " << m_txonBufferSize ); |
|
361 |
} |
|
362 |
||
363 |
} |
|
364 |
||
365 |
// |
|
366 |
// Build RLC header |
|
367 |
// |
|
368 |
||
369 |
rlcAmHeader.SetSequenceNumber ( m_vtS ); |
|
370 |
m_vtS = (m_vtS + 1) % 1024; |
|
371 |
||
372 |
rlcAmHeader.SetResegmentationFlag (LteRlcAmHeader::PDU); |
|
373 |
rlcAmHeader.SetLastSegmentFlag (LteRlcAmHeader::LAST_PDU_SEGMENT); |
|
374 |
rlcAmHeader.SetSegmentOffset (0); |
|
375 |
||
376 |
// Calculate FramingInfo flag according the status of the SDUs in the DataField |
|
377 |
uint8_t framingInfo = 0; |
|
378 |
std::vector< Ptr<Packet> >::iterator it; |
|
379 |
it = dataField.begin (); |
|
380 |
||
381 |
// FIRST SEGMENT |
|
382 |
LteRlcSduStatusTag tag; |
|
383 |
(*it)->RemovePacketTag (tag); |
|
384 |
if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) || |
|
385 |
(tag.GetStatus () == LteRlcSduStatusTag::FIRST_SEGMENT) |
|
386 |
) |
|
387 |
{ |
|
388 |
framingInfo |= LteRlcAmHeader::FIRST_BYTE; |
|
389 |
} |
|
390 |
else |
|
391 |
{ |
|
392 |
framingInfo |= LteRlcAmHeader::NO_FIRST_BYTE; |
|
393 |
} |
|
394 |
(*it)->AddPacketTag (tag); |
|
395 |
||
396 |
// Add all SDUs (in DataField) to the Packet |
|
397 |
while (it < dataField.end ()) |
|
398 |
{ |
|
399 |
NS_LOG_LOGIC ("Adding SDU/segment to packet, length = " << (*it)->GetSize ()); |
|
400 |
||
401 |
packet->AddAtEnd (*it); |
|
402 |
it++; |
|
403 |
} |
|
404 |
||
405 |
// LAST SEGMENT (Note: There could be only one and be the first one) |
|
406 |
it--; |
|
407 |
(*it)->RemovePacketTag (tag); |
|
408 |
if ( (tag.GetStatus () == LteRlcSduStatusTag::FULL_SDU) || |
|
409 |
(tag.GetStatus () == LteRlcSduStatusTag::LAST_SEGMENT) ) |
|
410 |
{ |
|
411 |
framingInfo |= LteRlcAmHeader::LAST_BYTE; |
|
412 |
} |
|
413 |
else |
|
414 |
{ |
|
415 |
framingInfo |= LteRlcAmHeader::NO_LAST_BYTE; |
|
416 |
} |
|
417 |
(*it)->AddPacketTag (tag); |
|
418 |
||
419 |
// Set the FramingInfo flag after the calculation |
|
420 |
rlcAmHeader.SetFramingInfo (framingInfo); |
|
421 |
||
422 |
||
423 |
// Calculate the Polling Bit (5.2.2.1) |
|
424 |
rlcAmHeader.SetPollingBit (LteRlcAmHeader::STATUS_REPORT_NOT_REQUESTED); |
|
425 |
||
426 |
m_pduWithoutPoll++; |
|
427 |
NS_LOG_LOGIC ("PDU_WITHOUT_POLL = " << m_pduWithoutPoll); |
|
428 |
m_byteWithoutPoll += packet->GetSize (); |
|
429 |
NS_LOG_LOGIC ("BYTE_WITHOUT_POLL = " << m_byteWithoutPoll); |
|
430 |
||
431 |
if ( (m_pduWithoutPoll >= m_pollPdu) || (m_byteWithoutPoll >= m_pollByte) || |
|
432 |
( (m_txonBuffer.empty ()) && (m_retxBuffer.empty ()) ) || |
|
433 |
(m_vtS >= m_vtMs) |
|
434 |
) |
|
435 |
{ |
|
436 |
rlcAmHeader.SetPollingBit (LteRlcAmHeader::STATUS_REPORT_IS_REQUESTED); |
|
437 |
m_pduWithoutPoll = 0; |
|
438 |
m_byteWithoutPoll = 0; |
|
439 |
||
440 |
m_pollSn = m_vtS - 1; |
|
441 |
NS_LOG_LOGIC ("New POLL_SN = " << m_pollSn); |
|
442 |
||
443 |
if (! m_pollRetransmitTimer.IsRunning () ) |
|
444 |
{ |
|
445 |
NS_LOG_LOGIC ("Start PollRetransmit timer"); |
|
446 |
||
447 |
m_pollRetransmitTimer = Simulator::Schedule (Time ("1.0s"), |
|
448 |
&LteRlcAm::ExpirePollRetransmitTimer, this); |
|
449 |
} |
|
450 |
else |
|
451 |
{ |
|
452 |
NS_LOG_LOGIC ("Restart PollRetransmit timer"); |
|
453 |
||
454 |
m_pollRetransmitTimer.Cancel (); |
|
455 |
m_pollRetransmitTimer = Simulator::Schedule (Time ("1.0s"), |
|
456 |
&LteRlcAm::ExpirePollRetransmitTimer, this); |
|
457 |
} |
|
458 |
} |
|
459 |
||
460 |
||
461 |
// Build RLC PDU with DataField and Header |
|
462 |
NS_LOG_LOGIC ("AM RLC header: " << rlcAmHeader); |
|
463 |
packet->AddHeader (rlcAmHeader); |
|
464 |
||
465 |
// Store new PDU into the Transmitted PDU Buffer |
|
466 |
NS_LOG_LOGIC ("Put transmitted PDU in the txedBuffer"); |
|
467 |
m_txedBufferSize += packet->GetSize (); |
|
468 |
m_txedBuffer.at ( rlcAmHeader.GetSequenceNumber () ) = packet; |
|
469 |
||
470 |
// Send RLC PDU to MAC layer |
|
471 |
LteMacSapProvider::TransmitPduParameters params; |
|
472 |
params.pdu = packet; |
|
473 |
params.rnti = m_rnti; |
|
474 |
params.lcid = m_lcid; |
|
8714
398bbcbb3f42
Add MIMO model, test and documentation
Marco Miozzo <marco.miozzo@cttc.es>
parents:
8456
diff
changeset
|
475 |
params.layer = layer; |
8448 | 476 |
|
477 |
m_macSapProvider->TransmitPdu (params); |
|
478 |
} |
|
479 |
||
480 |
void |
|
481 |
LteRlcAm::DoNotifyHarqDeliveryFailure () |
|
482 |
{ |
|
483 |
NS_LOG_FUNCTION (this); |
|
484 |
} |
|
485 |
||
486 |
void |
|
487 |
LteRlcAm::DoReceivePdu (Ptr<Packet> p) |
|
488 |
{ |
|
489 |
NS_LOG_FUNCTION (this); |
|
490 |
||
491 |
// Get RLC header parameters |
|
492 |
LteRlcAmHeader rlcAmHeader; |
|
493 |
p->PeekHeader (rlcAmHeader); |
|
494 |
||
495 |
if ( rlcAmHeader.IsDataPdu () ) |
|
496 |
{ |
|
497 |
||
498 |
// 5.1.3.1 Transmit operations |
|
499 |
||
500 |
// 5.1.3.1.1 General |
|
501 |
// |
|
502 |
// The transmitting side of an AM RLC entity shall prioritize transmission of RLC control PDUs |
|
503 |
// over RLC data PDUs. The transmitting side of an AM RLC entity shall prioritize retransmission |
|
504 |
// of RLC data PDUs over transmission of new AMD PDUs. |
|
505 |
// |
|
506 |
// The transmitting side of an AM RLC entity shall maintain a transmitting window according to |
|
507 |
// state variables VT(A) and VT(MS) as follows: |
|
508 |
// - a SN falls within the transmitting window if VT(A) <= SN < VT(MS); |
|
509 |
// - a SN falls outside of the transmitting window otherwise. |
|
510 |
// |
|
511 |
// The transmitting side of an AM RLC entity shall not deliver to lower layer any RLC data PDU |
|
512 |
// whose SN falls outside of the transmitting window. |
|
513 |
// |
|
514 |
// When delivering a new AMD PDU to lower layer, the transmitting side of an AM RLC entity shall: |
|
515 |
// - set the SN of the AMD PDU to VT(S), and then increment VT(S) by one. |
|
516 |
// |
|
517 |
// The transmitting side of an AM RLC entity can receive a positive acknowledgement (confirmation |
|
518 |
// of successful reception by its peer AM RLC entity) for a RLC data PDU by the following: |
|
519 |
// - STATUS PDU from its peer AM RLC entity. |
|
520 |
// |
|
521 |
// When receiving a positive acknowledgement for an AMD PDU with SN = VT(A), the transmitting |
|
522 |
// side of an AM RLC entity shall: |
|
523 |
// - set VT(A) equal to the SN of the AMD PDU with the smallest SN, whose SN falls within the |
|
524 |
// range VT(A) <= SN <= VT(S) and for which a positive acknowledgment has not been received yet. |
|
525 |
// - if positive acknowledgements have been received for all AMD PDUs associated with |
|
526 |
// a transmitted RLC SDU: |
|
527 |
// - send an indication to the upper layers of successful delivery of the RLC SDU. |
|
528 |
||
529 |
||
530 |
// 5.1.3.2 Receive operations |
|
531 |
// |
|
532 |
// 5.1.3.2.1 General |
|
533 |
// |
|
534 |
// The receiving side of an AM RLC entity shall maintain a receiving window according to state |
|
535 |
// variables VR(R) and VR(MR) as follows: |
|
536 |
// - a SN falls within the receiving window if VR(R) <= SN < VR(MR); |
|
537 |
// - a SN falls outside of the receiving window otherwise. |
|
538 |
// |
|
539 |
// When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity shall: |
|
540 |
// - either discard the received RLC data PDU or place it in the reception buffer (see sub clause 5.1.3.2.2); |
|
541 |
// - if the received RLC data PDU was placed in the reception buffer: |
|
542 |
// - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop t-Reordering as needed (see sub clause 5.1.3.2.3). |
|
543 |
// |
|
544 |
// When t-Reordering expires, the receiving side of an AM RLC entity shall: |
|
545 |
// - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4). |
|
546 |
||
547 |
||
548 |
uint16_t seqNumber = rlcAmHeader.GetSequenceNumber (); |
|
549 |
||
550 |
if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::SEGMENT ) |
|
551 |
{ |
|
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
552 |
NS_LOG_LOGIC ("AMD PDU segment received ( SN = " << seqNumber << " )"); |
8448 | 553 |
} |
554 |
else if ( rlcAmHeader.GetResegmentationFlag () == LteRlcAmHeader::PDU ) |
|
555 |
{ |
|
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
556 |
NS_LOG_LOGIC ("AMD PDU received ( SN = " << seqNumber << " )"); |
8448 | 557 |
} |
558 |
else |
|
559 |
{ |
|
560 |
NS_ASSERT_MSG (false, "Neither an AMD PDU segment nor a AMD PDU received"); |
|
561 |
return ; |
|
562 |
} |
|
563 |
||
564 |
// STATUS PDU is requested |
|
565 |
if ( rlcAmHeader.GetPollingBit () == LteRlcAmHeader::STATUS_REPORT_IS_REQUESTED ) |
|
566 |
{ |
|
567 |
m_statusPduRequested = true; |
|
568 |
m_statusPduBufferSize = 4; |
|
569 |
||
570 |
if (! m_statusProhibitTimer.IsRunning ()) |
|
571 |
{ |
|
572 |
Time now = Simulator::Now (); |
|
573 |
||
574 |
// Transmission Queue HOL time |
|
575 |
RlcTag txonQueueHolTimeTag; |
|
576 |
Time txonQueueHolDelay (0); |
|
577 |
if ( ! m_txonBuffer.empty () ) |
|
578 |
{ |
|
579 |
m_txonBuffer.front ()->PeekPacketTag (txonQueueHolTimeTag); |
|
580 |
txonQueueHolDelay = now - txonQueueHolTimeTag.GetSenderTimestamp (); |
|
581 |
} |
|
582 |
||
583 |
// Retransmission Queue HOL time |
|
584 |
RlcTag retxQueueHolTimeTag; |
|
585 |
Time retxQueueHolDelay (0); |
|
586 |
if ( m_retxBufferSize ) |
|
587 |
{ |
|
588 |
m_retxBuffer.front ().m_pdu->PeekPacketTag (retxQueueHolTimeTag); |
|
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
589 |
retxQueueHolDelay = now - retxQueueHolTimeTag.GetSenderTimestamp (); |
8448 | 590 |
} |
591 |
||
592 |
LteMacSapProvider::ReportBufferStatusParameters r; |
|
593 |
r.rnti = m_rnti; |
|
594 |
r.lcid = m_lcid; |
|
595 |
r.txQueueSize = m_txonBufferSize; |
|
596 |
r.txQueueHolDelay = txonQueueHolDelay.GetMilliSeconds (); |
|
597 |
r.retxQueueSize = m_retxBufferSize; |
|
598 |
r.retxQueueHolDelay = retxQueueHolDelay.GetMilliSeconds (); |
|
599 |
||
600 |
if ( m_statusPduRequested && ! m_statusProhibitTimer.IsRunning () ) |
|
601 |
{ |
|
602 |
r.statusPduSize = m_statusPduBufferSize; |
|
603 |
} |
|
604 |
else |
|
605 |
{ |
|
606 |
r.statusPduSize = 0; |
|
607 |
} |
|
608 |
||
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
609 |
NS_LOG_INFO ("Send ReportBufferStatus: " << r.txQueueSize << ", " << r.txQueueHolDelay << ", " |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
610 |
<< r.retxQueueSize << ", " << r.retxQueueHolDelay << ", " |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
611 |
<< r.statusPduSize ); |
8448 | 612 |
m_macSapProvider->ReportBufferStatus (r); |
613 |
} |
|
614 |
} |
|
615 |
||
616 |
// 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer |
|
617 |
// |
|
618 |
// When a RLC data PDU is received from lower layer, where the RLC data PDU contains |
|
619 |
// byte segment numbers y to z of an AMD PDU with SN = x, the receiving side of an AM RLC entity shall: |
|
620 |
// - if x falls outside of the receiving window; or |
|
621 |
// - if byte segment numbers y to z of the AMD PDU with SN = x have been received before: |
|
622 |
// - discard the received RLC data PDU; |
|
623 |
// - else: |
|
624 |
// - place the received RLC data PDU in the reception buffer; |
|
625 |
// - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before: |
|
626 |
// - discard the duplicate byte segments. |
|
627 |
||
628 |
NS_LOG_LOGIC ("VR(R) = " << m_vrR); |
|
629 |
NS_LOG_LOGIC ("VR(MR) = " << m_vrMr); |
|
630 |
NS_LOG_LOGIC ("VR(X) = " << m_vrX); |
|
631 |
NS_LOG_LOGIC ("VR(MS) = " << m_vrMs); |
|
632 |
NS_LOG_LOGIC ("VR(H) = " << m_vrH); |
|
633 |
||
634 |
// - if x falls outside of the receiving window; or |
|
635 |
// - if byte segment numbers y to z of the AMD PDU with SN = x have been received before: |
|
636 |
if ( ! IsInsideReceivingWindow (seqNumber) ) |
|
637 |
{ |
|
638 |
NS_LOG_LOGIC ("AMD PDU discarded"); |
|
639 |
return; |
|
640 |
} |
|
641 |
else |
|
642 |
{ |
|
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
643 |
NS_LOG_LOGIC ("Place AMD PDU in the reception buffer ( SN = " << seqNumber << " )"); |
8448 | 644 |
m_rxonBuffer[ seqNumber ].m_byteSegments.push_back (p); |
645 |
m_rxonBuffer[ seqNumber ].m_pduComplete = true; |
|
646 |
||
647 |
// - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before: |
|
648 |
// - discard the duplicate byte segments. |
|
649 |
} |
|
650 |
||
651 |
// 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception buffer |
|
652 |
// When a RLC data PDU with SN = x is placed in the reception buffer, |
|
653 |
// the receiving side of an AM RLC entity shall: |
|
654 |
||
655 |
// - if x >= VR(H) |
|
656 |
// - update VR(H) to x+ 1; |
|
657 |
||
658 |
if ( seqNumber >= m_vrH ) |
|
659 |
{ |
|
660 |
m_vrH = (seqNumber + 1) % 1024; |
|
661 |
NS_LOG_LOGIC ("New VR(H) = " << m_vrH); |
|
662 |
} |
|
663 |
||
664 |
// - if all byte segments of the AMD PDU with SN = VR(MS) are received: |
|
665 |
// - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for |
|
666 |
// which not all byte segments have been received; |
|
667 |
||
668 |
if ( m_rxonBuffer[ m_vrMs ].m_pduComplete ) |
|
669 |
{ |
|
670 |
while ( m_rxonBuffer[ m_vrMs ].m_pduComplete ) |
|
671 |
{ |
|
672 |
m_vrMs = (m_vrMs + 1) % 1024; |
|
673 |
} |
|
674 |
NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs); |
|
675 |
} |
|
676 |
||
677 |
// - if x = VR(R): |
|
678 |
// - if all byte segments of the AMD PDU with SN = VR(R) are received: |
|
679 |
// - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which not all byte segments have been received; |
|
680 |
// - update VR(MR) to the updated VR(R) + AM_Window_Size; |
|
681 |
// - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside of the receiving window and in-sequence byte segments of the AMD PDU with SN = VR(R), remove RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in sequence if not delivered before; |
|
682 |
||
683 |
if ( seqNumber == m_vrR ) |
|
684 |
{ |
|
685 |
if ( m_rxonBuffer[ seqNumber ].m_pduComplete ) |
|
686 |
{ |
|
687 |
while ( m_rxonBuffer[ m_vrR ].m_pduComplete ) |
|
688 |
{ |
|
689 |
m_vrR = (m_vrR + 1) % 1024; |
|
690 |
} |
|
691 |
NS_LOG_LOGIC ("New VR(R) = " << m_vrR); |
|
692 |
m_vrMr = m_vrR + m_windowSize; |
|
693 |
NS_LOG_LOGIC ("New VR(MR) = " << m_vrMr); |
|
694 |
} |
|
695 |
||
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
696 |
NS_LOG_LOGIC ("Reassemble and Deliver ( SN = " << seqNumber << " )"); |
8448 | 697 |
NS_ASSERT_MSG (m_rxonBuffer[ seqNumber ].m_byteSegments.size () == 1, |
698 |
"Too many segments. PDU Reassembly process didn't work"); |
|
699 |
ReassembleAndDeliver (m_rxonBuffer[ seqNumber ].m_byteSegments.front ()); |
|
700 |
} |
|
701 |
||
702 |
// - if t-Reordering is running: |
|
703 |
// - if VR(X) = VR(R); or |
|
704 |
// - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR): |
|
705 |
// - stop and reset t-Reordering; |
|
706 |
||
707 |
if ( m_reorderingTimer.IsRunning () ) |
|
708 |
{ |
|
709 |
NS_LOG_LOGIC ("Reordering timer is running"); |
|
710 |
if ( (m_vrX == m_vrR) || |
|
711 |
( (! IsInsideReceivingWindow (m_vrX)) && (m_vrX != m_vrMr) ) |
|
712 |
) |
|
713 |
{ |
|
714 |
// TODO stop and reset the t-Reordering |
|
715 |
NS_LOG_LOGIC ("Stop reordering timer"); |
|
716 |
m_reorderingTimer.Cancel (); |
|
717 |
} |
|
718 |
} |
|
719 |
||
720 |
// - if t-Reordering is not running (includes the case t-Reordering is stopped due to actions above): |
|
721 |
// - if VR (H) > VR(R): |
|
722 |
// - start t-Reordering; |
|
723 |
// - set VR(X) to VR(H). |
|
724 |
||
725 |
if ( ! m_reorderingTimer.IsRunning () ) |
|
726 |
{ |
|
727 |
NS_LOG_LOGIC ("Reordering timer is not running"); |
|
728 |
if ( m_vrH > m_vrR ) |
|
729 |
{ |
|
730 |
NS_LOG_LOGIC ("Start reordering timer"); |
|
731 |
m_reorderingTimer = Simulator::Schedule (Time ("1.0s"), |
|
732 |
&LteRlcAm::ExpireReorderingTimer ,this); |
|
733 |
m_vrX = m_vrH; |
|
734 |
NS_LOG_LOGIC ("New VR(X) = " << m_vrX); |
|
735 |
} |
|
736 |
} |
|
737 |
||
738 |
||
739 |
||
740 |
// TODO To remove |
|
741 |
||
742 |
// 5.1.2.2.3 Actions when an UMD PDU is placed in the reception buffer |
|
743 |
// When an UMD PDU with SN = x is placed in the reception buffer, the receiving UM RLC entity shall: |
|
744 |
||
745 |
// - if x falls outside of the reordering window: |
|
746 |
// - update VR(UH) to x + 1; |
|
747 |
// - reassemble RLC SDUs from any UMD PDUs with SN that falls outside of the reordering window, remove |
|
748 |
// RLC headers when doing so and deliver the reassembled RLC SDUs to upper layer in ascending order of the |
|
749 |
// RLC SN if not delivered before; |
|
750 |
// - if VR(UR) falls outside of the reordering window: |
|
751 |
// - set VR(UR) to (VR(UH) - UM_Window_Size); |
|
752 |
||
753 |
// if ( ! IsInsideReorderingWindow (seqNumber)) |
|
754 |
// { |
|
755 |
// NS_LOG_LOGIC ("SN outside the reordering window"); |
|
756 |
// |
|
757 |
// m_vrUh = seqNumber + 1; |
|
758 |
// NS_LOG_LOGIC ("New VR(UH) = " << m_vrUh); |
|
759 |
// |
|
760 |
// ReassembleOutsideWindow (); |
|
761 |
// |
|
762 |
// if ( ! IsInsideReorderingWindow (m_vrUr) ) |
|
763 |
// { |
|
764 |
// m_vrUr = m_vrUh - m_windowSize; |
|
765 |
// NS_LOG_LOGIC ("VR(UR) outside the reordering window"); |
|
766 |
// NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr); |
|
767 |
// } |
|
768 |
// } |
|
769 |
||
770 |
// - if the reception buffer contains an UMD PDU with SN = VR(UR): |
|
771 |
// - update VR(UR) to the SN of the first UMD PDU with SN > current VR(UR) that has not been received; |
|
772 |
// - reassemble RLC SDUs from any UMD PDUs with SN < updated VR(UR), remove RLC headers when doing |
|
773 |
// so and deliver the reassembled RLC SDUs to upper layer in ascending order of the RLC SN if not delivered |
|
774 |
// before; |
|
775 |
||
776 |
// if ( m_rxBuffer.count (m_vrUr) > 0 ) |
|
777 |
// { |
|
778 |
// NS_LOG_LOGIC ("Reception buffer contains SN = " << m_vrUr); |
|
779 |
// |
|
780 |
// std::map <uint16_t, Ptr<Packet> >::iterator it; |
|
781 |
// uint16_t newVrUr; |
|
782 |
// |
|
783 |
// it = m_rxBuffer.find (m_vrUr); |
|
784 |
// newVrUr = (it->first) + 1; |
|
785 |
// while ( m_rxBuffer.count (newVrUr) > 0 ) |
|
786 |
// { |
|
787 |
// newVrUr++; |
|
788 |
// } |
|
789 |
// m_vrUr = newVrUr; |
|
790 |
// NS_LOG_LOGIC ("New VR(UR) = " << m_vrUr); |
|
791 |
// |
|
792 |
// ReassembleSnLessThan (m_vrUr); |
|
793 |
// } |
|
794 |
||
795 |
// - if t-Reordering is running: |
|
796 |
// - if VR(UX) <= VR(UR); or |
|
797 |
// - if VR(UX) falls outside of the reordering window and VR(UX) is not equal to VR(UH):: |
|
798 |
// - stop and reset t-Reordering; |
|
799 |
// if ( m_reorderingTimer.IsRunning () ) |
|
800 |
// { |
|
801 |
// NS_LOG_LOGIC ("Reordering timer is running"); |
|
802 |
// |
|
803 |
// if ( (m_vrUx <= m_vrUr) || |
|
804 |
// ((! IsInsideReorderingWindow (m_vrUx)) && (m_vrUx != m_vrUh)) ) |
|
805 |
// { |
|
806 |
// NS_LOG_LOGIC ("Stop reordering timer"); |
|
807 |
// m_reorderingTimer.Cancel (); |
|
808 |
// } |
|
809 |
// } |
|
810 |
||
811 |
// - if t-Reordering is not running (includes the case when t-Reordering is stopped due to actions above): |
|
812 |
// - if VR(UH) > VR(UR): |
|
813 |
// - start t-Reordering; |
|
814 |
// - set VR(UX) to VR(UH). |
|
815 |
// if ( ! m_reorderingTimer.IsRunning () ) |
|
816 |
// { |
|
817 |
// NS_LOG_LOGIC ("Reordering timer is not running"); |
|
818 |
// |
|
819 |
// if ( m_vrUx > m_vrUr ) |
|
820 |
// { |
|
821 |
// NS_LOG_LOGIC ("VR(UX) > VR(UR). " << m_vrUx << " > " << m_vrUr); |
|
822 |
// NS_LOG_LOGIC ("Start reordering timer"); |
|
823 |
// m_reorderingTimer = Simulator::Schedule (Time ("1.0s"), |
|
824 |
// &LteRlcAm::ExpireReorderingTimer ,this); |
|
825 |
// m_vrUx = m_vrUh; |
|
826 |
// NS_LOG_LOGIC ("New VR(UX) = " << m_vrUx); |
|
827 |
// } |
|
828 |
// } |
|
829 |
||
830 |
} |
|
831 |
else if ( rlcAmHeader.IsControlPdu () ) |
|
832 |
{ |
|
833 |
NS_LOG_INFO ("Control AM RLC PDU"); |
|
834 |
||
835 |
uint16_t ackSn = rlcAmHeader.GetAckSn (); |
|
836 |
uint16_t seqNumber = m_vtA; |
|
837 |
||
838 |
while (seqNumber < ackSn) |
|
839 |
{ |
|
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
840 |
NS_LOG_INFO ("seqNumber = " << seqNumber); |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
841 |
NS_LOG_INFO ("ackSn = " << ackSn); |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
842 |
NS_LOG_INFO ("m_txedBuffer(seqNumber).size = " << m_txedBuffer.size ()); |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
843 |
if (m_txedBuffer.at (seqNumber)) |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
844 |
{ |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
845 |
NS_LOG_INFO ("m_txedBuffer(seqNumber)->GetSize = " << m_txedBuffer.at (seqNumber)->GetSize ()); |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
846 |
m_txedBufferSize -= m_txedBuffer.at (seqNumber)->GetSize (); |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
847 |
m_txedBuffer.at (seqNumber) = 0; |
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
848 |
} |
8448 | 849 |
seqNumber++; |
850 |
} |
|
851 |
||
852 |
while (seqNumber < m_vtS) |
|
853 |
{ |
|
854 |
if (m_txedBuffer.at (seqNumber)) |
|
855 |
{ |
|
856 |
m_retxBuffer.at (seqNumber).m_pdu = m_txedBuffer.at (seqNumber); |
|
857 |
m_retxBuffer.at (seqNumber).m_retxCount = 0; |
|
858 |
m_retxBufferSize += m_retxBuffer.at (seqNumber).m_pdu->GetSize (); |
|
859 |
||
860 |
m_txedBufferSize -= m_txedBuffer.at (seqNumber)->GetSize (); |
|
861 |
m_txedBuffer.at (seqNumber) = 0; |
|
862 |
} |
|
863 |
else if (m_retxBuffer.at (seqNumber).m_pdu) |
|
864 |
{ |
|
865 |
m_retxBuffer.at (seqNumber).m_retxCount++; |
|
866 |
if (m_retxBuffer.at (seqNumber).m_retxCount >= m_maxRetxThreshold) |
|
867 |
{ |
|
868 |
NS_LOG_INFO ("Max RETX_COUNT for SN = " << seqNumber); |
|
869 |
} |
|
870 |
} |
|
871 |
||
872 |
seqNumber++; |
|
873 |
} |
|
874 |
||
875 |
return; |
|
876 |
} |
|
877 |
else |
|
878 |
{ |
|
879 |
NS_LOG_WARN ("Wrong AM RLC PDU type"); |
|
880 |
return; |
|
881 |
} |
|
882 |
||
883 |
} |
|
884 |
||
885 |
||
886 |
void |
|
887 |
LteRlcAm::Start () |
|
888 |
{ |
|
889 |
NS_LOG_FUNCTION (this); |
|
890 |
||
891 |
LteMacSapProvider::ReportBufferStatusParameters p; |
|
892 |
p.rnti = m_rnti; |
|
893 |
p.lcid = m_lcid; |
|
894 |
p.txQueueSize = 0; |
|
895 |
p.txQueueHolDelay = 0; |
|
896 |
p.retxQueueSize = 0; |
|
897 |
p.retxQueueHolDelay = 0; |
|
898 |
p.statusPduSize = 0; |
|
899 |
||
900 |
m_macSapProvider->ReportBufferStatus (p); |
|
901 |
} |
|
902 |
||
903 |
||
904 |
bool |
|
905 |
LteRlcAm::IsInsideReceivingWindow (uint16_t seqNumber) |
|
906 |
{ |
|
907 |
if ( ( ((m_vrR - m_vrR) % 1024) <= ((seqNumber - m_vrR) % 1024) ) && |
|
908 |
( ((seqNumber - m_vrR) % 1024) < ((m_vrMr - m_vrR) % 1024) ) |
|
909 |
) |
|
910 |
{ |
|
911 |
return true; |
|
912 |
} |
|
913 |
else |
|
914 |
{ |
|
915 |
return false; |
|
916 |
} |
|
917 |
} |
|
918 |
||
919 |
||
920 |
void |
|
921 |
LteRlcAm::ReassembleAndDeliver (Ptr<Packet> packet) |
|
922 |
{ |
|
923 |
LteRlcAmHeader rlcAmHeader; |
|
924 |
packet->RemoveHeader (rlcAmHeader); |
|
925 |
uint8_t framingInfo = rlcAmHeader.GetFramingInfo (); |
|
926 |
uint16_t currSeqNumber = rlcAmHeader.GetSequenceNumber (); |
|
927 |
bool expectedSnLost; |
|
928 |
||
929 |
if ( currSeqNumber != m_expectedSeqNumber ) |
|
930 |
{ |
|
931 |
expectedSnLost = true; |
|
932 |
NS_LOG_LOGIC ("There are losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber); |
|
933 |
m_expectedSeqNumber = (currSeqNumber + 1) % 1024; |
|
934 |
} |
|
935 |
else |
|
936 |
{ |
|
937 |
expectedSnLost = false; |
|
938 |
NS_LOG_LOGIC ("No losses. Expected SN = " << m_expectedSeqNumber << ". Current SN = " << currSeqNumber); |
|
939 |
m_expectedSeqNumber = (m_expectedSeqNumber + 1) % 1024; |
|
940 |
} |
|
941 |
||
942 |
// Build list of SDUs |
|
943 |
uint8_t extensionBit; |
|
944 |
uint16_t lengthIndicator; |
|
945 |
do |
|
946 |
{ |
|
947 |
extensionBit = rlcAmHeader.PopExtensionBit (); |
|
948 |
NS_LOG_LOGIC ("E = " << (uint16_t)extensionBit); |
|
949 |
||
950 |
if ( extensionBit == 0 ) |
|
951 |
{ |
|
952 |
m_sdusBuffer.push_back (packet); |
|
953 |
} |
|
954 |
else // extensionBit == 1 |
|
955 |
{ |
|
956 |
lengthIndicator = rlcAmHeader.PopLengthIndicator (); |
|
957 |
NS_LOG_LOGIC ("LI = " << lengthIndicator); |
|
958 |
||
959 |
// Check if there is enough data in the packet |
|
960 |
if ( lengthIndicator >= packet->GetSize () ) |
|
961 |
{ |
|
962 |
NS_LOG_LOGIC ("INTERNAL ERROR: Not enough data in the packet (" << packet->GetSize () << "). Needed LI=" << lengthIndicator); |
|
963 |
// TODO What to do in this case? Discard packet and continue? Or Assert? |
|
964 |
} |
|
965 |
||
966 |
// Split packet in two fragments |
|
967 |
Ptr<Packet> data_field = packet->CreateFragment (0, lengthIndicator); |
|
968 |
packet->RemoveAtStart (lengthIndicator); |
|
969 |
||
970 |
m_sdusBuffer.push_back (data_field); |
|
971 |
} |
|
972 |
} |
|
973 |
while ( extensionBit == 1 ); |
|
974 |
||
975 |
std::list < Ptr<Packet> >::iterator it; |
|
976 |
||
977 |
// Current reassembling state |
|
978 |
if (m_reassemblingState == WAITING_S0_FULL) NS_LOG_LOGIC ("Reassembling State = 'WAITING_S0_FULL'"); |
|
979 |
else if (m_reassemblingState == WAITING_SI_SF) NS_LOG_LOGIC ("Reassembling State = 'WAITING_SI_SF'"); |
|
980 |
else NS_LOG_LOGIC ("Reassembling State = Unknown state"); |
|
981 |
||
982 |
// Received framing Info |
|
983 |
NS_LOG_LOGIC ("Framing Info = " << (uint16_t)framingInfo); |
|
8456
782a47ccaf2a
Fix unused variable
Manuel Requena <manuel.requena@cttc.es>
parents:
8448
diff
changeset
|
984 |
NS_LOG_LOGIC ("m_sdusBuffer = " << m_sdusBuffer.size ()); |
8448 | 985 |
|
986 |
// Reassemble the list of SDUs (when there is no losses) |
|
987 |
if (!expectedSnLost) |
|
988 |
{ |
|
989 |
switch (m_reassemblingState) |
|
990 |
{ |
|
991 |
case WAITING_S0_FULL: |
|
992 |
switch (framingInfo) |
|
993 |
{ |
|
994 |
case (LteRlcAmHeader::FIRST_BYTE | LteRlcAmHeader::LAST_BYTE): |
|
995 |
m_reassemblingState = WAITING_S0_FULL; |
|
996 |
||
997 |
/** |
|
998 |
* Deliver one or multiple PDUs |
|
999 |
*/ |
|
1000 |
for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ ) |
|
1001 |
{ |
|
1002 |
m_rlcSapUser->ReceivePdcpPdu (*it); |
|
1003 |
} |
|
1004 |
m_sdusBuffer.clear (); |
|
1005 |
break; |
|
1006 |
||
1007 |
case (LteRlcAmHeader::FIRST_BYTE | LteRlcAmHeader::NO_LAST_BYTE): |
|
1008 |
m_reassemblingState = WAITING_SI_SF; |
|
1009 |
||
1010 |
/** |
|
1011 |
* Deliver full PDUs |
|
1012 |
*/ |
|
1013 |
while ( m_sdusBuffer.size () > 1 ) |
|
1014 |
{ |
|
1015 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1016 |
m_sdusBuffer.pop_front (); |
|
1017 |
} |
|
1018 |
||
1019 |
/** |
|
1020 |
* Keep S0 |
|
1021 |
*/ |
|
1022 |
m_keepS0 = m_sdusBuffer.front (); |
|
1023 |
m_sdusBuffer.pop_front (); |
|
1024 |
break; |
|
1025 |
||
1026 |
case (LteRlcAmHeader::NO_FIRST_BYTE | LteRlcAmHeader::LAST_BYTE): |
|
1027 |
case (LteRlcAmHeader::NO_FIRST_BYTE | LteRlcAmHeader::NO_LAST_BYTE): |
|
1028 |
default: |
|
1029 |
/** |
|
1030 |
* ERROR: Transition not possible |
|
1031 |
*/ |
|
1032 |
NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << framingInfo); |
|
1033 |
break; |
|
1034 |
} |
|
1035 |
break; |
|
1036 |
||
1037 |
case WAITING_SI_SF: |
|
1038 |
switch (framingInfo) |
|
1039 |
{ |
|
1040 |
case (LteRlcAmHeader::NO_FIRST_BYTE | LteRlcAmHeader::LAST_BYTE): |
|
1041 |
m_reassemblingState = WAITING_S0_FULL; |
|
1042 |
||
1043 |
/** |
|
1044 |
* Deliver (Kept)S0 + SN |
|
1045 |
*/ |
|
1046 |
m_keepS0->AddAtEnd (m_sdusBuffer.front ()); |
|
1047 |
m_sdusBuffer.pop_front (); |
|
1048 |
m_rlcSapUser->ReceivePdcpPdu (m_keepS0); |
|
1049 |
||
1050 |
/** |
|
1051 |
* Deliver zero, one or multiple PDUs |
|
1052 |
*/ |
|
1053 |
while ( ! m_sdusBuffer.empty () ) |
|
1054 |
{ |
|
1055 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1056 |
m_sdusBuffer.pop_front (); |
|
1057 |
} |
|
1058 |
break; |
|
1059 |
||
1060 |
case (LteRlcAmHeader::NO_FIRST_BYTE | LteRlcAmHeader::NO_LAST_BYTE): |
|
1061 |
m_reassemblingState = WAITING_SI_SF; |
|
1062 |
||
1063 |
/** |
|
1064 |
* Keep SI |
|
1065 |
*/ |
|
1066 |
if ( m_sdusBuffer.size () == 1 ) |
|
1067 |
{ |
|
1068 |
m_keepS0->AddAtEnd (m_sdusBuffer.front ()); |
|
1069 |
m_sdusBuffer.pop_front (); |
|
1070 |
} |
|
1071 |
else // m_sdusBuffer.size () > 1 |
|
1072 |
{ |
|
1073 |
/** |
|
1074 |
* Deliver (Kept)S0 + SN |
|
1075 |
*/ |
|
1076 |
m_keepS0->AddAtEnd (m_sdusBuffer.front ()); |
|
1077 |
m_sdusBuffer.pop_front (); |
|
1078 |
m_rlcSapUser->ReceivePdcpPdu (m_keepS0); |
|
1079 |
||
1080 |
/** |
|
1081 |
* Deliver zero, one or multiple PDUs |
|
1082 |
*/ |
|
1083 |
while ( m_sdusBuffer.size () > 1 ) |
|
1084 |
{ |
|
1085 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1086 |
m_sdusBuffer.pop_front (); |
|
1087 |
} |
|
1088 |
||
1089 |
/** |
|
1090 |
* Keep S0 |
|
1091 |
*/ |
|
1092 |
m_keepS0 = m_sdusBuffer.front (); |
|
1093 |
m_sdusBuffer.pop_front (); |
|
1094 |
} |
|
1095 |
break; |
|
1096 |
||
1097 |
case (LteRlcAmHeader::FIRST_BYTE | LteRlcAmHeader::LAST_BYTE): |
|
1098 |
case (LteRlcAmHeader::FIRST_BYTE | LteRlcAmHeader::NO_LAST_BYTE): |
|
1099 |
default: |
|
1100 |
/** |
|
1101 |
* ERROR: Transition not possible |
|
1102 |
*/ |
|
1103 |
NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << framingInfo); |
|
1104 |
break; |
|
1105 |
} |
|
1106 |
break; |
|
1107 |
||
1108 |
default: |
|
1109 |
NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << m_reassemblingState); |
|
1110 |
break; |
|
1111 |
} |
|
1112 |
} |
|
1113 |
else // Reassemble the list of SDUs (when there are losses, i.e. the received SN is not the expected one) |
|
1114 |
{ |
|
1115 |
switch (m_reassemblingState) |
|
1116 |
{ |
|
1117 |
case WAITING_S0_FULL: |
|
1118 |
switch (framingInfo) |
|
1119 |
{ |
|
1120 |
case (LteRlcAmHeader::FIRST_BYTE | LteRlcAmHeader::LAST_BYTE): |
|
1121 |
m_reassemblingState = WAITING_S0_FULL; |
|
1122 |
||
1123 |
/** |
|
1124 |
* Deliver one or multiple PDUs |
|
1125 |
*/ |
|
1126 |
for ( it = m_sdusBuffer.begin () ; it != m_sdusBuffer.end () ; it++ ) |
|
1127 |
{ |
|
1128 |
m_rlcSapUser->ReceivePdcpPdu (*it); |
|
1129 |
} |
|
1130 |
m_sdusBuffer.clear (); |
|
1131 |
break; |
|
1132 |
||
1133 |
case (LteRlcAmHeader::FIRST_BYTE | LteRlcAmHeader::NO_LAST_BYTE): |
|
1134 |
m_reassemblingState = WAITING_SI_SF; |
|
1135 |
||
1136 |
/** |
|
1137 |
* Deliver full PDUs |
|
1138 |
*/ |
|
1139 |
while ( m_sdusBuffer.size () > 1 ) |
|
1140 |
{ |
|
1141 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1142 |
m_sdusBuffer.pop_front (); |
|
1143 |
} |
|
1144 |
||
1145 |
/** |
|
1146 |
* Keep S0 |
|
1147 |
*/ |
|
1148 |
m_keepS0 = m_sdusBuffer.front (); |
|
1149 |
m_sdusBuffer.pop_front (); |
|
1150 |
break; |
|
1151 |
||
1152 |
case (LteRlcAmHeader::NO_FIRST_BYTE | LteRlcAmHeader::LAST_BYTE): |
|
1153 |
m_reassemblingState = WAITING_S0_FULL; |
|
1154 |
||
1155 |
/** |
|
1156 |
* Discard SN |
|
1157 |
*/ |
|
1158 |
m_sdusBuffer.pop_front (); |
|
1159 |
||
1160 |
/** |
|
1161 |
* Deliver zero, one or multiple PDUs |
|
1162 |
*/ |
|
1163 |
while ( ! m_sdusBuffer.empty () ) |
|
1164 |
{ |
|
1165 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1166 |
m_sdusBuffer.pop_front (); |
|
1167 |
} |
|
1168 |
break; |
|
1169 |
||
1170 |
case (LteRlcAmHeader::NO_FIRST_BYTE | LteRlcAmHeader::NO_LAST_BYTE): |
|
1171 |
if ( m_sdusBuffer.size () == 1 ) |
|
1172 |
{ |
|
1173 |
m_reassemblingState = WAITING_S0_FULL; |
|
1174 |
} |
|
1175 |
else |
|
1176 |
{ |
|
1177 |
m_reassemblingState = WAITING_SI_SF; |
|
1178 |
} |
|
1179 |
||
1180 |
/** |
|
1181 |
* Discard SI or SN |
|
1182 |
*/ |
|
1183 |
m_sdusBuffer.pop_front (); |
|
1184 |
||
1185 |
if ( m_sdusBuffer.size () > 0 ) |
|
1186 |
{ |
|
1187 |
/** |
|
1188 |
* Deliver zero, one or multiple PDUs |
|
1189 |
*/ |
|
1190 |
while ( m_sdusBuffer.size () > 1 ) |
|
1191 |
{ |
|
1192 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1193 |
m_sdusBuffer.pop_front (); |
|
1194 |
} |
|
1195 |
||
1196 |
/** |
|
1197 |
* Keep S0 |
|
1198 |
*/ |
|
1199 |
m_keepS0 = m_sdusBuffer.front (); |
|
1200 |
m_sdusBuffer.pop_front (); |
|
1201 |
} |
|
1202 |
break; |
|
1203 |
||
1204 |
default: |
|
1205 |
/** |
|
1206 |
* ERROR: Transition not possible |
|
1207 |
*/ |
|
1208 |
NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << framingInfo); |
|
1209 |
break; |
|
1210 |
} |
|
1211 |
break; |
|
1212 |
||
1213 |
case WAITING_SI_SF: |
|
1214 |
switch (framingInfo) |
|
1215 |
{ |
|
1216 |
case (LteRlcAmHeader::FIRST_BYTE | LteRlcAmHeader::LAST_BYTE): |
|
1217 |
m_reassemblingState = WAITING_S0_FULL; |
|
1218 |
||
1219 |
/** |
|
1220 |
* Discard S0 |
|
1221 |
*/ |
|
1222 |
m_keepS0 = 0; |
|
1223 |
||
1224 |
/** |
|
1225 |
* Deliver one or multiple PDUs |
|
1226 |
*/ |
|
1227 |
while ( ! m_sdusBuffer.empty () ) |
|
1228 |
{ |
|
1229 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1230 |
m_sdusBuffer.pop_front (); |
|
1231 |
} |
|
1232 |
break; |
|
1233 |
||
1234 |
case (LteRlcAmHeader::FIRST_BYTE | LteRlcAmHeader::NO_LAST_BYTE): |
|
1235 |
m_reassemblingState = WAITING_SI_SF; |
|
1236 |
||
1237 |
/** |
|
1238 |
* Discard S0 |
|
1239 |
*/ |
|
1240 |
m_keepS0 = 0; |
|
1241 |
||
1242 |
/** |
|
1243 |
* Deliver zero, one or multiple PDUs |
|
1244 |
*/ |
|
1245 |
while ( m_sdusBuffer.size () > 1 ) |
|
1246 |
{ |
|
1247 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1248 |
m_sdusBuffer.pop_front (); |
|
1249 |
} |
|
1250 |
||
1251 |
/** |
|
1252 |
* Keep S0 |
|
1253 |
*/ |
|
1254 |
m_keepS0 = m_sdusBuffer.front (); |
|
1255 |
m_sdusBuffer.pop_front (); |
|
1256 |
||
1257 |
break; |
|
1258 |
||
1259 |
case (LteRlcAmHeader::NO_FIRST_BYTE | LteRlcAmHeader::LAST_BYTE): |
|
1260 |
m_reassemblingState = WAITING_S0_FULL; |
|
1261 |
||
1262 |
/** |
|
1263 |
* Discard S0 |
|
1264 |
*/ |
|
1265 |
m_keepS0 = 0; |
|
1266 |
||
1267 |
/** |
|
1268 |
* Discard SI or SN |
|
1269 |
*/ |
|
1270 |
m_sdusBuffer.pop_front (); |
|
1271 |
||
1272 |
/** |
|
1273 |
* Deliver zero, one or multiple PDUs |
|
1274 |
*/ |
|
1275 |
while ( ! m_sdusBuffer.empty () ) |
|
1276 |
{ |
|
1277 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1278 |
m_sdusBuffer.pop_front (); |
|
1279 |
} |
|
1280 |
break; |
|
1281 |
||
1282 |
case (LteRlcAmHeader::NO_FIRST_BYTE | LteRlcAmHeader::NO_LAST_BYTE): |
|
1283 |
if ( m_sdusBuffer.size () == 1 ) |
|
1284 |
{ |
|
1285 |
m_reassemblingState = WAITING_S0_FULL; |
|
1286 |
} |
|
1287 |
else |
|
1288 |
{ |
|
1289 |
m_reassemblingState = WAITING_SI_SF; |
|
1290 |
} |
|
1291 |
||
1292 |
/** |
|
1293 |
* Discard S0 |
|
1294 |
*/ |
|
1295 |
m_keepS0 = 0; |
|
1296 |
||
1297 |
/** |
|
1298 |
* Discard SI or SN |
|
1299 |
*/ |
|
1300 |
m_sdusBuffer.pop_front (); |
|
1301 |
||
1302 |
if ( m_sdusBuffer.size () > 0 ) |
|
1303 |
{ |
|
1304 |
/** |
|
1305 |
* Deliver zero, one or multiple PDUs |
|
1306 |
*/ |
|
1307 |
while ( m_sdusBuffer.size () > 1 ) |
|
1308 |
{ |
|
1309 |
m_rlcSapUser->ReceivePdcpPdu (m_sdusBuffer.front ()); |
|
1310 |
m_sdusBuffer.pop_front (); |
|
1311 |
} |
|
1312 |
||
1313 |
/** |
|
1314 |
* Keep S0 |
|
1315 |
*/ |
|
1316 |
m_keepS0 = m_sdusBuffer.front (); |
|
1317 |
m_sdusBuffer.pop_front (); |
|
1318 |
} |
|
1319 |
break; |
|
1320 |
||
1321 |
default: |
|
1322 |
/** |
|
1323 |
* ERROR: Transition not possible |
|
1324 |
*/ |
|
1325 |
NS_LOG_LOGIC ("INTERNAL ERROR: Transition not possible. FI = " << framingInfo); |
|
1326 |
break; |
|
1327 |
} |
|
1328 |
break; |
|
1329 |
||
1330 |
default: |
|
1331 |
NS_LOG_LOGIC ("INTERNAL ERROR: Wrong reassembling state = " << m_reassemblingState); |
|
1332 |
break; |
|
1333 |
} |
|
1334 |
} |
|
1335 |
||
1336 |
} |
|
1337 |
||
1338 |
||
1339 |
// TODO To remove |
|
1340 |
// void |
|
1341 |
// LteRlcAm::ReassembleOutsideWindow (void) |
|
1342 |
// { |
|
1343 |
// NS_LOG_LOGIC ("Reassemble Outside Window"); |
|
1344 |
// |
|
1345 |
// std::map <uint16_t, Ptr<Packet> >::iterator it; |
|
1346 |
// it = m_rxBuffer.begin (); |
|
1347 |
// |
|
1348 |
// while ( (it != m_rxBuffer.end ()) && ! IsInsideReorderingWindow (it->first) ) |
|
1349 |
// { |
|
1350 |
// NS_LOG_LOGIC ("SN = " << it->first); |
|
1351 |
// |
|
1352 |
// // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer |
|
1353 |
// ReassembleAndDeliver (it->second); |
|
1354 |
// m_rxBuffer.erase (it); |
|
1355 |
// it++; |
|
1356 |
// } |
|
1357 |
// |
|
1358 |
// if (it != m_rxBuffer.end ()) |
|
1359 |
// { |
|
1360 |
// NS_LOG_LOGIC ("(SN = " << it->first << ") is inside the reordering window"); |
|
1361 |
// } |
|
1362 |
// } |
|
1363 |
||
1364 |
||
1365 |
// TODO To remove |
|
1366 |
// void |
|
1367 |
// LteRlcAm::ReassembleSnLessThan (uint16_t seqNumber) |
|
1368 |
// { |
|
1369 |
// NS_LOG_LOGIC ("Reassemble SN < updated VR(UR)" ); |
|
1370 |
// |
|
1371 |
// std::map <uint16_t, Ptr<Packet> >::iterator it; |
|
1372 |
// it = m_rxBuffer.begin (); |
|
1373 |
// |
|
1374 |
// while ( (it != m_rxBuffer.end ()) && (it->first < seqNumber) ) |
|
1375 |
// { |
|
1376 |
// NS_LOG_LOGIC ("SN = " << it->first); |
|
1377 |
// |
|
1378 |
// // Reassemble RLC SDUs and deliver the PDCP PDU to upper layer |
|
1379 |
// ReassembleAndDeliver (it->second); |
|
1380 |
// m_rxBuffer.erase (it); |
|
1381 |
// it++; |
|
1382 |
// } |
|
1383 |
// |
|
1384 |
// if (it != m_rxBuffer.end ()) |
|
1385 |
// { |
|
1386 |
// NS_LOG_LOGIC ("(SN = " << it->first << ") >= " << m_vrUr); |
|
1387 |
// } |
|
1388 |
// } |
|
1389 |
||
1390 |
||
1391 |
// TODO To check |
|
1392 |
void |
|
1393 |
LteRlcAm::ExpireReorderingTimer (void) |
|
1394 |
{ |
|
1395 |
NS_LOG_LOGIC ("Reordering Timer has expired"); |
|
1396 |
||
1397 |
// 5.1.3.2.4 Actions when t-Reordering expires |
|
1398 |
// When t-Reordering expires, the receiving side of an AM RLC entity shall: |
|
1399 |
// - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte segments |
|
1400 |
// have been received; |
|
1401 |
// - if VR(H) > VR(MS): |
|
1402 |
// - start t-Reordering; |
|
1403 |
// - set VR(X) to VR(H). |
|
1404 |
||
1405 |
m_vrMs = m_vrX; |
|
1406 |
while ( m_rxonBuffer[ m_vrMs ].m_pduComplete ) |
|
1407 |
{ |
|
1408 |
m_vrMs = (m_vrMs + 1) % 1024; |
|
1409 |
} |
|
1410 |
NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs); |
|
1411 |
||
1412 |
if ( m_vrH > m_vrMs ) |
|
1413 |
{ |
|
1414 |
NS_LOG_LOGIC ("Start reordering timer"); |
|
1415 |
m_reorderingTimer = Simulator::Schedule (Time ("1.0s"), |
|
1416 |
&LteRlcAm::ExpireReorderingTimer ,this); |
|
1417 |
m_vrX = m_vrH; |
|
1418 |
NS_LOG_LOGIC ("New VR(MS) = " << m_vrMs); |
|
1419 |
} |
|
1420 |
} |
|
1421 |
||
1422 |
// TODO To check |
|
1423 |
void |
|
1424 |
LteRlcAm::ExpirePollRetransmitTimer (void) |
|
1425 |
{ |
|
1426 |
NS_LOG_LOGIC ("PollRetransmit Timer has expired"); |
|
1427 |
NS_LOG_LOGIC ("TODO To Check"); |
|
1428 |
} |
|
1429 |
||
1430 |
||
1431 |
||
1432 |
} // namespace ns3 |