A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lte-rlc-am-header.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Manuel Requena <manuel.requena@cttc.es>
7 */
8
9#include "lte-rlc-am-header.h"
10
11#include "ns3/log.h"
12
13namespace ns3
14{
15
16NS_LOG_COMPONENT_DEFINE("LteRlcAmHeader");
17
18NS_OBJECT_ENSURE_REGISTERED(LteRlcAmHeader);
19
21 : m_headerLength(0),
22 m_dataControlBit(0xff),
23 m_resegmentationFlag(0xff),
24 m_pollingBit(0xff),
25 m_framingInfo(0xff),
26 m_sequenceNumber(0xfffa),
27 m_segmentOffset(0xffff),
28 m_lastOffset(0xffff),
29 m_controlPduType(0xff),
30 m_ackSn(0xffff)
31{
32}
33
35{
37 m_dataControlBit = 0xff;
39 m_pollingBit = 0xff;
40 m_framingInfo = 0xff;
41 m_sequenceNumber = 0xfffb;
42 m_segmentOffset = 0xffff;
43 m_lastOffset = 0xffff;
44 m_controlPduType = 0xff;
45 m_ackSn = 0xffff;
46}
47
48void
54
55void
56LteRlcAmHeader::SetControlPdu(uint8_t controlPduType)
57{
60 m_controlPduType = controlPduType;
61}
62
63bool
68
69bool
74
75void
77{
78 m_framingInfo = framingInfo & 0x03;
79}
80
81void
83{
84 m_sequenceNumber = sequenceNumber;
85}
86
87uint8_t
92
98
99void
101{
102 m_extensionBits.push_back(extensionBit);
103 if (m_extensionBits.size() > 1)
104 {
105 if (m_extensionBits.size() % 2)
106 {
107 m_headerLength += 1;
108 }
109 else
110 {
111 m_headerLength += 2;
112 }
113 }
114}
115
116void
117LteRlcAmHeader::PushLengthIndicator(uint16_t lengthIndicator)
118{
119 m_lengthIndicators.push_back(lengthIndicator);
120}
121
122uint8_t
124{
125 uint8_t extensionBit = m_extensionBits.front();
126 m_extensionBits.pop_front();
127
128 return extensionBit;
129}
130
131uint16_t
133{
134 uint16_t lengthIndicator = m_lengthIndicators.front();
135 m_lengthIndicators.pop_front();
136
137 return lengthIndicator;
138}
139
140void
142{
143 m_resegmentationFlag = resegFlag & 0x01;
144}
145
146uint8_t
151
152void
154{
155 m_pollingBit = pollingBit & 0x01;
156}
157
158uint8_t
160{
161 return m_pollingBit;
162}
163
164void
166{
167 m_lastSegmentFlag = lsf & 0x01;
168}
169
170uint8_t
175
176void
177LteRlcAmHeader::SetSegmentOffset(uint16_t segmentOffset)
178{
179 m_segmentOffset = segmentOffset & 0x7FFF;
180}
181
182uint16_t
187
188uint16_t
190{
191 return m_lastOffset;
192}
193
194void
199
200bool
202{
203 NS_LOG_FUNCTION(this << bytes);
205 "method allowed only for STATUS PDUs");
206 if (m_nackSnList.size() % 2 == 0)
207 {
208 return (m_headerLength < bytes);
209 }
210 else
211 {
212 return (m_headerLength < (bytes - 1));
213 }
214}
215
216void
218{
219 NS_LOG_FUNCTION(this << nack);
221 "method allowed only for STATUS PDUs");
222 m_nackSnList.push_back(nack);
223
224 if (m_nackSnList.size() % 2 == 0)
225 {
227 }
228 else
229 {
230 m_headerLength += 2;
231 }
232}
233
234bool
236{
237 NS_LOG_FUNCTION(this);
239 "method allowed only for STATUS PDUs");
240 for (auto nackIt = m_nackSnList.begin(); nackIt != m_nackSnList.end(); ++nackIt)
241 {
242 if ((*nackIt) == nack.GetValue())
243 {
244 return true;
245 }
246 }
247 return false;
248}
249
250int
252{
253 NS_LOG_FUNCTION(this);
255 "method allowed only for STATUS PDUs");
256 if (m_nackSnList.empty())
257 {
258 return -1;
259 }
260
261 int nack = m_nackSnList.front();
262 m_nackSnList.pop_front();
263
264 return nack;
265}
266
269{
270 return m_ackSn;
271}
272
273TypeId
275{
276 static TypeId tid = TypeId("ns3::LteRlcAmHeader")
277 .SetParent<Header>()
278 .SetGroupName("Lte")
279 .AddConstructor<LteRlcAmHeader>();
280 return tid;
281}
282
283TypeId
285{
286 return GetTypeId();
287}
288
289void
290LteRlcAmHeader::Print(std::ostream& os) const
291{
292 auto it1 = m_extensionBits.begin();
293 auto it2 = m_lengthIndicators.begin();
294 auto it3 = m_nackSnList.begin();
295
296 os << "Len=" << m_headerLength;
297 os << " D/C=" << (uint16_t)m_dataControlBit;
298
300 {
301 os << " RF=" << (uint16_t)m_resegmentationFlag;
302 os << " P=" << (uint16_t)m_pollingBit;
303 os << " FI=" << (uint16_t)m_framingInfo;
304 os << " E=" << (uint16_t)(*it1);
305 os << " SN=" << m_sequenceNumber;
306 os << " LSF=" << (uint16_t)(m_lastSegmentFlag);
307 os << " SO=" << m_segmentOffset;
308
309 it1++;
310 if (it1 != m_extensionBits.end())
311 {
312 os << " E=";
313 }
314 while (it1 != m_extensionBits.end())
315 {
316 os << (uint16_t)(*it1);
317 it1++;
318 }
319
320 if (it2 != m_lengthIndicators.end())
321 {
322 os << " LI=";
323 }
324 while (it2 != m_lengthIndicators.end())
325 {
326 os << (uint16_t)(*it2) << " ";
327 it2++;
328 }
329 }
330 else // if ( m_dataControlBit == CONTROL_PDU )
331 {
332 os << " ACK_SN=" << m_ackSn;
333
334 while (it3 != m_nackSnList.end())
335 {
336 os << " NACK_SN=" << (int)(*it3);
337 it3++;
338 }
339 }
340}
341
347
348void
350{
351 Buffer::Iterator i = start;
352
353 auto it1 = m_extensionBits.begin();
354 auto it2 = m_lengthIndicators.begin();
355 auto it3 = m_nackSnList.begin();
356
358 {
359 i.WriteU8(((DATA_PDU << 7) & 0x80) | ((m_resegmentationFlag << 6) & 0x40) |
360 ((m_pollingBit << 5) & 0x20) | ((m_framingInfo << 3) & 0x18) |
361 (((*it1) << 2) & 0x04) | ((m_sequenceNumber.GetValue() >> 8) & 0x0003));
362 i.WriteU8(m_sequenceNumber.GetValue() & 0x00FF);
363 i.WriteU8(((m_lastSegmentFlag << 7) & 0x80) | ((m_segmentOffset >> 8) & 0x007F));
364 i.WriteU8(m_segmentOffset & 0x00FF);
365 it1++;
366
367 while (it1 != m_extensionBits.end() && it2 != m_lengthIndicators.end())
368 {
369 uint16_t oddLi;
370 uint16_t evenLi;
371 uint8_t oddE;
372 uint8_t evenE;
373
374 oddE = *it1;
375 oddLi = *it2;
376
377 it1++;
378 it2++;
379
380 if (it1 != m_extensionBits.end() && it2 != m_lengthIndicators.end())
381 {
382 evenE = *it1;
383 evenLi = *it2;
384
385 i.WriteU8(((oddE << 7) & 0x80) | ((oddLi >> 4) & 0x007F));
386 i.WriteU8(((oddLi << 4) & 0x00F0) | ((evenE << 3) & 0x08) |
387 ((evenLi >> 8) & 0x0007));
388 i.WriteU8(evenLi & 0x00FF);
389
390 it1++;
391 it2++;
392 }
393 else
394 {
395 i.WriteU8(((oddE << 7) & 0x80) | ((oddLi >> 4) & 0x007F));
396 i.WriteU8((oddLi << 4) & 0x00F0); // Padding is implicit
397 }
398 }
399 }
400 else // if ( m_dataControlBit == CONTROL_PDU )
401 {
402 i.WriteU8(((CONTROL_PDU << 7) & 0x80) | ((m_controlPduType << 4) & 0x70) |
403 ((m_ackSn.GetValue() >> 6) & 0x0F));
404 // note: second part of ackSn will be written later
405
406 // serialize the NACKs
407 if (it3 == m_nackSnList.end())
408 {
409 NS_LOG_LOGIC(this << " no NACKs");
410 // If there are no NACKs then this line adds the rest of the ACK
411 // along with 0x00, indicating an E1 value of 0 or no NACKs follow.
412 i.WriteU8((m_ackSn.GetValue() << 2) & 0xFC);
413 }
414 else
415 {
416 int oddNack = *it3;
417 int evenNack = -1;
418 // Else write out a series of E1 = 1 and NACK values. Note since we
419 // are not supporting SO start/end the value of E2 will always be 0.
420
421 // First write out the ACK along with the very first NACK
422 // And the remaining NACK with 0x02 or 10 in binary to set
423 // E1 to 1, then Or in the first bit of the NACK
424 i.WriteU8(((m_ackSn.GetValue() << 2) & 0xFC) | (0x02) | ((*it3 >> 9) & 0x01));
425
426 while (it3 != m_nackSnList.end())
427 {
428 // The variable oddNack has the current NACK value to write, also
429 // either the setup to enter this loop or the previous loop would
430 // have written the highest order bit to the previous octet.
431 // Write the next set of bits (2 - 9) into the next octet
432 i.WriteU8((oddNack >> 1) & 0xFF);
433
434 // Next check to see if there is going to be another NACK after
435 // this
436 it3++;
437 if (it3 != m_nackSnList.end())
438 {
439 // Yes there will be another NACK after this, so E1 will be 1
440 evenNack = *it3;
441 i.WriteU8(((oddNack << 7) & 0x80) | (0x40) // E1 = 1 E2 = 0, more NACKs
442 | ((evenNack >> 5) & 0x1F));
443
444 // The final octet of this loop will have the rest of the
445 // NACK and another E1, E2. Check to see if there will be
446 // one more NACK after this.
447 it3++;
448 if (it3 != m_nackSnList.end())
449 {
450 // Yes there is at least one more NACK. Finish writing
451 // this octet and the next iteration will do the rest.
452 oddNack = *it3;
453 i.WriteU8(((evenNack << 3) & 0xF8) | (0x04) | ((oddNack >> 9) & 0x01));
454 }
455 else
456 {
457 // No, there are no more NACKs
458 i.WriteU8((evenNack << 3) & 0xF8);
459 }
460 }
461 else
462 {
463 // No, this is the last NACK so E1 will be 0
464 i.WriteU8((oddNack << 7) & 0x80);
465 }
466 }
467 }
468 }
469}
470
473{
474 Buffer::Iterator i = start;
475 uint8_t byte_1;
476 uint8_t byte_2;
477 uint8_t byte_3;
478 uint8_t byte_4;
479 uint8_t extensionBit;
480
481 byte_1 = i.ReadU8();
482 m_headerLength = 1;
483 m_dataControlBit = (byte_1 & 0x80) >> 7;
484
486 {
487 byte_2 = i.ReadU8();
488 byte_3 = i.ReadU8();
489 byte_4 = i.ReadU8();
490 m_headerLength += 3;
491
492 m_resegmentationFlag = (byte_1 & 0x40) >> 6;
493 m_pollingBit = (byte_1 & 0x20) >> 5;
494 m_framingInfo = (byte_1 & 0x18) >> 3;
495 m_sequenceNumber = ((byte_1 & 0x03) << 8) | byte_2;
496
497 m_lastSegmentFlag = (byte_3 & 0x80) >> 7;
498 m_segmentOffset = (byte_3 & 0x7F) | byte_4;
499
500 extensionBit = (byte_1 & 0x04) >> 2;
501 m_extensionBits.push_back(extensionBit);
502
503 if (extensionBit == DATA_FIELD_FOLLOWS)
504 {
505 return GetSerializedSize();
506 }
507
508 uint16_t oddLi;
509 uint16_t evenLi;
510 uint8_t oddE;
511 uint8_t evenE;
512 bool moreLiFields = (extensionBit == E_LI_FIELDS_FOLLOWS);
513
514 while (moreLiFields)
515 {
516 byte_1 = i.ReadU8();
517 byte_2 = i.ReadU8();
518
519 oddE = (byte_1 & 0x80) >> 7;
520 oddLi = ((byte_1 & 0x7F) << 4) | ((byte_2 & 0xF0) >> 4);
521 moreLiFields = (oddE == E_LI_FIELDS_FOLLOWS);
522
523 m_extensionBits.push_back(oddE);
524 m_lengthIndicators.push_back(oddLi);
525 m_headerLength += 2;
526
527 if (moreLiFields)
528 {
529 byte_3 = i.ReadU8();
530
531 evenE = (byte_2 & 0x08) >> 3;
532 evenLi = ((byte_2 & 0x07) << 8) | (byte_3 & 0xFF);
533 moreLiFields = (evenE == E_LI_FIELDS_FOLLOWS);
534
535 m_extensionBits.push_back(evenE);
536 m_lengthIndicators.push_back(evenLi);
537
538 m_headerLength += 1;
539 }
540 }
541
543 {
544 m_lastOffset = m_segmentOffset + start.GetSize() - m_headerLength;
545 }
546 }
547 else // if ( m_dataControlBit == CONTROL_PDU )
548 {
549 byte_2 = i.ReadU8();
550
551 m_controlPduType = (byte_1 & 0x70) >> 4;
552 m_ackSn = ((byte_1 & 0x0F) << 6) | ((byte_2 & 0xFC) >> 2);
553
554 int moreNacks = (byte_2 & 0x02) >> 1;
555 // Get the first NACK outside the loop as it is not preceded by an E2
556 // field but all following NACKs will.
557 if (moreNacks == 1)
558 {
559 byte_3 = i.ReadU8();
560 byte_4 = i.ReadU8();
561 m_headerLength = 4;
562
563 m_nackSnList.push_back(((byte_2 & 0x01) << 9) | (byte_3 << 1) | ((byte_4 & 0x80) >> 7));
564
565 // Loop until all NACKs are found
566 moreNacks = ((byte_4 & 0x40) >> 6);
567 uint8_t byte = byte_4;
568 uint8_t nextByte;
569 uint8_t finalByte;
570 while (moreNacks == 1)
571 {
572 // Ignore E2, read next NACK
573 nextByte = i.ReadU8();
574 m_nackSnList.push_back(((byte & 0x1F) << 5) | ((nextByte & 0xF8) >> 3));
575
576 // Check for another NACK, after this any following NACKs will
577 // be aligned properly for the next iteration of this loop.
578 moreNacks = (nextByte & 0x04) >> 2;
579 byte = nextByte;
580 if (moreNacks == 1)
581 {
582 nextByte = i.ReadU8();
583 finalByte = i.ReadU8();
584
585 m_nackSnList.push_back(((byte & 0x01) << 9) | (nextByte << 1) |
586 ((finalByte & 0x80) >> 7));
587
588 moreNacks = ((finalByte & 0x40) >> 6);
589 byte = finalByte;
590 m_headerLength += 3;
591 }
592 else
593 {
595 }
596 }
597 }
598 else
599 {
601 }
602 }
603
604 return GetSerializedSize();
605}
606
607}; // namespace ns3
iterator in a Buffer instance
Definition buffer.h:89
void WriteU8(uint8_t data)
Definition buffer.h:870
Protocol header serialization and deserialization.
Definition header.h:33
The packet header for the AM Radio Link Control (RLC) protocol packets.
uint8_t GetPollingBit() const
Get polling bit function.
uint8_t PopExtensionBit()
Pop extension bit function.
void SetSegmentOffset(uint16_t segmentOffset)
Set segment offset function.
void PushExtensionBit(uint8_t extensionBit)
Push extension bit function.
uint32_t Deserialize(Buffer::Iterator start) override
bool IsDataPdu() const
Is data PDU function.
SequenceNumber10 GetAckSn() const
Get ack sn function.
void SetPollingBit(uint8_t pollingBit)
Set polling bit function.
bool OneMoreNackWouldFitIn(uint16_t bytes)
uint32_t GetSerializedSize() const override
uint16_t m_headerLength
header length
void SetLastSegmentFlag(uint8_t lsf)
Set last segment flag function.
void Print(std::ostream &os) const override
uint16_t GetLastOffset() const
Get last offset function.
SequenceNumber10 m_sequenceNumber
sequence number
uint16_t m_lastOffset
last offset
LteRlcAmHeader()
Constructor.
void PushNack(int nack)
Add one more NACK to the CONTROL PDU.
uint8_t m_dataControlBit
data control bit
std::list< uint8_t > m_extensionBits
Includes extensionBit of the fixed part.
void SetFramingInfo(uint8_t framingInfo)
Set sequence number.
static constexpr uint8_t STATUS_PDU
Control PDU type status.
uint8_t GetLastSegmentFlag() const
Get last segment flag function.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
void Serialize(Buffer::Iterator start) const override
SequenceNumber10 m_ackSn
ack sn
uint16_t PopLengthIndicator()
Pop length indicator function.
uint8_t m_controlPduType
control PDU type
uint16_t m_segmentOffset
segment offset
void SetAckSn(SequenceNumber10 ackSn)
Set ack sn function.
bool IsControlPdu() const
Is control PDU function.
void SetDataPdu()
Set data PDU function.
uint8_t m_framingInfo
2 bits
uint8_t m_resegmentationFlag
resegmentation flag
void PushLengthIndicator(uint16_t lengthIndicator)
Push length indicator function.
uint8_t GetResegmentationFlag() const
Get resegmentation flag function.
void SetResegmentationFlag(uint8_t resegFlag)
Pop extension bit function.
uint16_t GetSegmentOffset() const
Get segment offset function.
uint8_t m_pollingBit
polling bit
static TypeId GetTypeId()
Get the type ID.
uint8_t m_lastSegmentFlag
last segment flag
bool IsNackPresent(SequenceNumber10 nack)
std::list< int > m_nackSnList
nack sn list
uint8_t GetFramingInfo() const
Get framing info.
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
int PopNack()
Retrieve one NACK from the CONTROL PDU.
void SetControlPdu(uint8_t controlPduType)
Set control PDU function.
std::list< uint16_t > m_lengthIndicators
length indicators
void SetSequenceNumber(SequenceNumber10 sequenceNumber)
Set sequence number.
SequenceNumber10 class.
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Every class exported by the ns3 library is enclosed in the ns3 namespace.