A Discrete-Event Network Simulator
API
lte-rlc-am-header.cc
Go to the documentation of this file.
1/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Manuel Requena <manuel.requena@cttc.es>
19 */
20
21#include "ns3/log.h"
22
23#include "ns3/lte-rlc-am-header.h"
24
25namespace ns3 {
26
27NS_LOG_COMPONENT_DEFINE ("LteRlcAmHeader");
28
29NS_OBJECT_ENSURE_REGISTERED (LteRlcAmHeader);
30
32 : m_headerLength (0),
33 m_dataControlBit (0xff),
34 m_resegmentationFlag (0xff),
35 m_pollingBit (0xff),
36 m_framingInfo (0xff),
37 m_sequenceNumber (0xfffa),
38 m_segmentOffset (0xffff),
39 m_lastOffset (0xffff),
40 m_controlPduType (0xff),
41 m_ackSn (0xffff)
42{
43}
44
46{
48 m_dataControlBit = 0xff;
50 m_pollingBit = 0xff;
51 m_framingInfo = 0xff;
52 m_sequenceNumber = 0xfffb;
53 m_segmentOffset = 0xffff;
54 m_lastOffset = 0xffff;
55 m_controlPduType = 0xff;
56 m_ackSn = 0xffff;
57}
58
59void
61{
64}
65void
66LteRlcAmHeader::SetControlPdu (uint8_t controlPduType)
67{
70 m_controlPduType = controlPduType;
71}
72bool
74{
75 return m_dataControlBit == DATA_PDU;
76}
77bool
79{
81}
82
83void
84LteRlcAmHeader::SetFramingInfo (uint8_t framingInfo)
85{
86 m_framingInfo = framingInfo & 0x03;
87}
88
89void
91{
92 m_sequenceNumber = sequenceNumber;
93}
94
95uint8_t
97{
98 return m_framingInfo;
99}
100
103{
104 return m_sequenceNumber;
105}
106
107
108void
110{
111 m_extensionBits.push_back (extensionBit);
112 if (m_extensionBits.size() > 1)
113 {
114 if (m_extensionBits.size() % 2)
115 {
116 m_headerLength += 1;
117 }
118 else
119 {
120 m_headerLength += 2;
121 }
122 }
123}
124
125void
126LteRlcAmHeader::PushLengthIndicator (uint16_t lengthIndicator)
127{
128 m_lengthIndicators.push_back (lengthIndicator);
129}
130
131
132uint8_t
134{
135 uint8_t extensionBit = m_extensionBits.front ();
136 m_extensionBits.pop_front ();
137
138 return extensionBit;
139}
140
141uint16_t
143{
144 uint16_t lengthIndicator = m_lengthIndicators.front ();
145 m_lengthIndicators.pop_front ();
146
147 return lengthIndicator;
148}
149
150
151void
153{
154 m_resegmentationFlag = resegFlag & 0x01;
155}
156
157uint8_t
159{
161}
162
163
164void
166{
167 m_pollingBit = pollingBit & 0x01;
168}
169
170uint8_t
172{
173 return m_pollingBit;
174}
175
176
177void
179{
180 m_lastSegmentFlag = lsf & 0x01;
181}
182
183uint8_t
185{
186 return m_lastSegmentFlag;
187}
188
189
190void
191LteRlcAmHeader::SetSegmentOffset (uint16_t segmentOffset)
192{
193 m_segmentOffset = segmentOffset & 0x7FFF;
194}
195
196uint16_t
198{
199 return m_segmentOffset;
200}
201
202uint16_t
204{
205 return m_lastOffset;
206}
207
208
209void
211{
212 m_ackSn = ackSn;
213}
214
215bool
217{
218 NS_LOG_FUNCTION (this << bytes);
220 "method allowed only for STATUS PDUs");
221 if (m_nackSnList.size () % 2 == 0)
222 {
223 return (m_headerLength < bytes);
224 }
225 else
226 {
227 return (m_headerLength < (bytes - 1));
228 }
229}
230
231void
233{
234 NS_LOG_FUNCTION (this << nack);
236 "method allowed only for STATUS PDUs");
237 m_nackSnList.push_back (nack);
238
239 if (m_nackSnList.size () % 2 == 0)
240 {
242 }
243 else
244 {
246 }
247}
248
249bool
251{
252 NS_LOG_FUNCTION (this);
254 "method allowed only for STATUS PDUs");
255 for (std::list<int>::iterator nackIt = m_nackSnList.begin ();
256 nackIt != m_nackSnList.end ();
257 ++nackIt)
258 {
259 if ((*nackIt) == nack.GetValue ())
260 {
261 return true;
262 }
263 }
264 return false;
265}
266
267int
269{
270 NS_LOG_FUNCTION (this);
272 "method allowed only for STATUS PDUs");
273 if ( m_nackSnList.empty () )
274 {
275 return -1;
276 }
277
278 int nack = m_nackSnList.front ();
279 m_nackSnList.pop_front ();
280
281 return nack;
282}
283
284
287{
288 return m_ackSn;
289}
290
291
292TypeId
294{
295 static TypeId tid = TypeId ("ns3::LteRlcAmHeader")
296 .SetParent<Header> ()
297 .SetGroupName("Lte")
298 .AddConstructor<LteRlcAmHeader> ()
299 ;
300 return tid;
301}
302
303TypeId
305{
306 return GetTypeId ();
307}
308
309void
310LteRlcAmHeader::Print (std::ostream &os) const
311{
312 std::list <uint8_t>::const_iterator it1 = m_extensionBits.begin ();
313 std::list <uint16_t>::const_iterator it2 = m_lengthIndicators.begin ();
314 std::list <int>::const_iterator it3 = m_nackSnList.begin ();
315
316 os << "Len=" << m_headerLength;
317 os << " D/C=" << (uint16_t)m_dataControlBit;
318
319 if ( m_dataControlBit == DATA_PDU )
320 {
321 os << " RF=" << (uint16_t)m_resegmentationFlag;
322 os << " P=" << (uint16_t)m_pollingBit;
323 os << " FI=" << (uint16_t)m_framingInfo;
324 os << " E=" << (uint16_t)(*it1);
325 os << " SN=" << m_sequenceNumber;
326 os << " LSF=" << (uint16_t)(m_lastSegmentFlag);
327 os << " SO=" << m_segmentOffset;
328
329 it1++;
330 if (it1 != m_extensionBits.end ())
331 {
332 os << " E=";
333 }
334 while ( it1 != m_extensionBits.end () )
335 {
336 os << (uint16_t)(*it1);
337 it1++;
338 }
339
340 if (it2 != m_lengthIndicators.end ())
341 {
342 os << " LI=";
343 }
344 while ( it2 != m_lengthIndicators.end () )
345 {
346 os << (uint16_t)(*it2) << " ";
347 it2++;
348 }
349 }
350 else // if ( m_dataControlBit == CONTROL_PDU )
351 {
352 os << " ACK_SN=" << m_ackSn;
353
354 while ( it3 != m_nackSnList.end () )
355 {
356 os << " NACK_SN=" << (int)(*it3);
357 it3++;
358 }
359
360
361 }
362}
363
365{
366 return m_headerLength;
367}
368
370{
372
373 std::list <uint8_t>::const_iterator it1 = m_extensionBits.begin ();
374 std::list <uint16_t>::const_iterator it2 = m_lengthIndicators.begin ();
375 std::list <int>::const_iterator it3 = m_nackSnList.begin ();
376
377 if ( m_dataControlBit == DATA_PDU )
378 {
379 i.WriteU8 ( ((DATA_PDU << 7) & 0x80) |
380 ((m_resegmentationFlag << 6) & 0x40) |
381 ((m_pollingBit << 5) & 0x20) |
382 ((m_framingInfo << 3) & 0x18) |
383 (((*it1) << 2) & 0x04) |
384 ((m_sequenceNumber.GetValue () >> 8) & 0x0003) );
385 i.WriteU8 ( m_sequenceNumber.GetValue () & 0x00FF );
386 i.WriteU8 ( ((m_lastSegmentFlag << 7) & 0x80) |
387 ((m_segmentOffset >> 8) & 0x007F) );
388 i.WriteU8 ( m_segmentOffset & 0x00FF );
389 it1++;
390
391 while ( it1 != m_extensionBits.end () &&
392 it2 != m_lengthIndicators.end () )
393 {
394 uint16_t oddLi, evenLi;
395 uint8_t oddE, evenE;
396
397 oddE = *it1;
398 oddLi = *it2;
399
400 it1++;
401 it2++;
402
403 if ( it1 != m_extensionBits.end () &&
404 it2 != m_lengthIndicators.end () )
405 {
406 evenE = *it1;
407 evenLi = *it2;
408
409 i.WriteU8 ( ((oddE << 7) & 0x80) | ((oddLi >> 4) & 0x007F) );
410 i.WriteU8 ( ((oddLi << 4) & 0x00F0) | ((evenE << 3) & 0x08) | ((evenLi >> 8) & 0x0007) );
411 i.WriteU8 ( evenLi & 0x00FF );
412
413 it1++;
414 it2++;
415 }
416 else
417 {
418 i.WriteU8 ( ((oddE << 7) & 0x80) | ((oddLi >> 4) & 0x007F) );
419 i.WriteU8 ( ((oddLi << 4) & 0x00F0) ); // Padding is implicit
420 }
421 }
422 }
423 else // if ( m_dataControlBit == CONTROL_PDU )
424 {
425 i.WriteU8 ( ((CONTROL_PDU << 7) & 0x80) |
426 ((m_controlPduType << 4) & 0x70) |
427 ((m_ackSn.GetValue () >> 6) & 0x0F) );
428 // note: second part of ackSn will be written later
429
430 // serialize the NACKs
431 if ( it3 == m_nackSnList.end () )
432 {
433 NS_LOG_LOGIC (this << " no NACKs");
434 // If there are no NACKs then this line adds the rest of the ACK
435 // along with 0x00, indicating an E1 value of 0 or no NACKs follow.
436 i.WriteU8 ( ((m_ackSn.GetValue () << 2) & 0xFC) );
437 }
438 else
439 {
440 int oddNack = *it3;
441 int evenNack = -1;
442 // Else write out a series of E1 = 1 and NACK values. Note since we
443 // are not supporting SO start/end the value of E2 will always be 0.
444
445
446 // First write out the ACK along with the very first NACK
447 // And the remaining NACK with 0x02 or 10 in binary to set
448 // E1 to 1, then Or in the first bit of the NACK
449 i.WriteU8 ( ((m_ackSn.GetValue () << 2) & 0xFC)
450 | (0x02)
451 | ((*it3 >> 9) & 0x01));
452
453 while ( it3 != m_nackSnList.end () )
454 {
455 // The variable oddNack has the current NACK value to write, also
456 // either the setup to enter this loop or the previous loop would
457 // have written the highest order bit to the previous octet.
458 // Write the next set of bits (2 - 9) into the next octet
459 i.WriteU8( ((oddNack >> 1) & 0xFF) );
460
461 // Next check to see if there is going to be another NACK after
462 // this
463 it3++;
464 if ( it3 != m_nackSnList.end () )
465 {
466 // Yes there will be another NACK after this, so E1 will be 1
467 evenNack = *it3;
468 i.WriteU8( ((oddNack << 7) & 0x80)
469 | (0x40) // E1 = 1 E2 = 0, more NACKs
470 | ( (evenNack >> 5) & 0x1F) );
471
472 // The final octet of this loop will have the rest of the
473 // NACK and another E1, E2. Check to see if there will be
474 // one more NACK after this.
475 it3++;
476 if ( it3 != m_nackSnList.end () )
477 {
478 // Yes there is at least one more NACK. Finish writing
479 // this octet and the next iteration will do the rest.
480 oddNack = *it3;
481 i.WriteU8 ( ((evenNack << 3) & 0xF8)
482 | (0x04)
483 | ((oddNack >> 9) & 0x01));
484 }
485 else
486 {
487 // No, there are no more NACKs
488 i.WriteU8 ( ((evenNack << 3) & 0xF8) );
489 }
490 }
491 else
492 {
493 // No, this is the last NACK so E1 will be 0
494 i.WriteU8 ( ((oddNack << 7) & 0x80) );
495 }
496 }
497 }
498
499 }
500}
501
503{
505 uint8_t byte_1;
506 uint8_t byte_2;
507 uint8_t byte_3;
508 uint8_t byte_4;
509 uint8_t extensionBit;
510
511 byte_1 = i.ReadU8 ();
512 m_headerLength = 1;
513 m_dataControlBit = (byte_1 & 0x80) >> 7;
514
515 if ( m_dataControlBit == DATA_PDU )
516 {
517 byte_2 = i.ReadU8 ();
518 byte_3 = i.ReadU8 ();
519 byte_4 = i.ReadU8 ();
520 m_headerLength += 3;
521
522 m_resegmentationFlag = (byte_1 & 0x40) >> 6;
523 m_pollingBit = (byte_1 & 0x20) >> 5;
524 m_framingInfo = (byte_1 & 0x18) >> 3;
525 m_sequenceNumber = ((byte_1 & 0x03) << 8) | byte_2;
526
527 m_lastSegmentFlag = (byte_3 & 0x80) >> 7;
528 m_segmentOffset = (byte_3 & 0x7F) | byte_4;
529
530 extensionBit = (byte_1 & 0x04) >> 2;
531 m_extensionBits.push_back (extensionBit);
532
533 if (extensionBit == DATA_FIELD_FOLLOWS)
534 {
535 return GetSerializedSize ();
536 }
537
538 uint16_t oddLi, evenLi;
539 uint8_t oddE, evenE;
540 bool moreLiFields = (extensionBit == E_LI_FIELDS_FOLLOWS);
541
542 while (moreLiFields)
543 {
544 byte_1 = i.ReadU8 ();
545 byte_2 = i.ReadU8 ();
546
547 oddE = (byte_1 & 0x80) >> 7;
548 oddLi = ((byte_1 & 0x7F) << 4) | ((byte_2 & 0xF0) >> 4);
549 moreLiFields = (oddE == E_LI_FIELDS_FOLLOWS);
550
551 m_extensionBits.push_back (oddE);
552 m_lengthIndicators.push_back (oddLi);
553 m_headerLength += 2;
554
555 if (moreLiFields)
556 {
557 byte_3 = i.ReadU8 ();
558
559 evenE = (byte_2 & 0x08) >> 3;
560 evenLi = ((byte_2 & 0x07) << 8) | (byte_3 & 0xFF);
561 moreLiFields = (evenE == E_LI_FIELDS_FOLLOWS);
562
563 m_extensionBits.push_back (evenE);
564 m_lengthIndicators.push_back (evenLi);
565
566 m_headerLength += 1;
567 }
568 }
569
571 {
573 }
574 }
575 else // if ( m_dataControlBit == CONTROL_PDU )
576 {
577 byte_2 = i.ReadU8 ();
578
579 m_controlPduType = (byte_1 & 0x70) >> 4;
580 m_ackSn = ((byte_1 & 0x0F) << 6 ) | ((byte_2 & 0xFC) >> 2);
581
582 int moreNacks = (byte_2 & 0x02) >> 1;
583 // Get the first NACK outside the loop as it is not preceded by an E2
584 // field but all following NACKs will.
585 if ( moreNacks == 1 )
586 {
587 byte_3 = i.ReadU8 ();
588 byte_4 = i.ReadU8 ();
589 m_headerLength = 4;
590
591 m_nackSnList.push_back (
592 ((byte_2 & 0x01) << 9)
593 | (byte_3 << 1)
594 | ((byte_4 & 0x80) >> 7)
595 );
596
597 // Loop until all NACKs are found
598 moreNacks = ((byte_4 & 0x40) >> 6);
599 uint8_t byte = byte_4;
600 uint8_t nextByte;
601 uint8_t finalByte;
602 while (moreNacks == 1)
603 {
604 // Ignore E2, read next NACK
605 nextByte = i.ReadU8 ();
606 m_nackSnList.push_back (
607 ((byte & 0x1F) << 5)
608 | ((nextByte & 0xF8) >> 3)
609 );
610
611 // Check for another NACK, after this any following NACKs will
612 // be aligned properly for the next iteration of this loop.
613 moreNacks = (nextByte & 0x04) >> 2;
614 byte = nextByte;
615 if (moreNacks == 1)
616 {
617 nextByte = i.ReadU8 ();
618 finalByte = i.ReadU8 ();
619
620 m_nackSnList.push_back (
621 ((byte & 0x01) << 9)
622 | (nextByte << 1)
623 | ((finalByte & 0x80) >> 7)
624 );
625
626 moreNacks = ((finalByte & 0x40) >> 6);
627 byte = finalByte;
629 }
630 else
631 {
633 }
634
635 }
636 }
637 else
638 {
640 }
641 }
642
643 return GetSerializedSize ();
644}
645
646}; // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:99
void WriteU8(uint8_t data)
Definition: buffer.h:869
uint8_t ReadU8(void)
Definition: buffer.h:1021
Protocol header serialization and deserialization.
Definition: header.h:43
The packet header for the AM Radio Link Control (RLC) protocol packets.
uint8_t GetPollingBit() const
Get polling bit function.
void SetSegmentOffset(uint16_t segmentOffset)
Set segment offset function.
void PushExtensionBit(uint8_t extensionBit)
Push extension bit function.
SequenceNumber10 GetAckSn() const
Get ack sn function.
void SetPollingBit(uint8_t pollingBit)
Set polling bit function.
bool OneMoreNackWouldFitIn(uint16_t bytes)
uint16_t m_headerLength
header length
virtual void Serialize(Buffer::Iterator start) const
void SetLastSegmentFlag(uint8_t lsf)
Set last segment flag function.
uint16_t GetLastOffset() const
Get last offset function.
SequenceNumber10 m_sequenceNumber
sequence number
uint8_t PopExtensionBit(void)
Pop extension bit function.
uint16_t m_lastOffset
last offset
LteRlcAmHeader()
Constructor.
void PushNack(int nack)
Add one more NACK to the CONTROL PDU.
static TypeId GetTypeId(void)
Get the type ID.
bool IsControlPdu(void) const
Is control PDU function.
void SetDataPdu(void)
Set data PDU function.
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.
int PopNack(void)
Retrieve one NACK from the CONTROL PDU.
virtual uint32_t GetSerializedSize(void) const
bool IsDataPdu(void) const
Is data PDU function.
uint8_t GetLastSegmentFlag() const
Get last segment flag function.
SequenceNumber10 m_ackSn
ack sn
uint8_t m_controlPduType
control PDU type
virtual void Print(std::ostream &os) const
uint16_t m_segmentOffset
segment offset
uint16_t PopLengthIndicator(void)
Pop length indicator function.
void SetAckSn(SequenceNumber10 ackSn)
Set ack sn function.
virtual uint32_t Deserialize(Buffer::Iterator start)
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
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.
void SetControlPdu(uint8_t controlPduType)
Set control PDU function.
std::list< uint16_t > m_lengthIndicators
length indicators
void SetSequenceNumber(SequenceNumber10 sequenceNumber)
Set sequence number.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
SequenceNumber10 class.
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#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:88
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#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:45
Every class exported by the ns3 library is enclosed in the ns3 namespace.
def start()
Definition: core.py:1853