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