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 
25 namespace ns3 {
26 
27 NS_LOG_COMPONENT_DEFINE ("LteRlcAmHeader");
28 
29 NS_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 {
47  m_headerLength = 0;
48  m_dataControlBit = 0xff;
49  m_resegmentationFlag = 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 
59 void
61 {
62  m_headerLength = 4;
64 }
65 void
66 LteRlcAmHeader::SetControlPdu (uint8_t controlPduType)
67 {
68  m_headerLength = 2;
70  m_controlPduType = controlPduType;
71 }
72 bool
74 {
75  return (m_dataControlBit == DATA_PDU) ? true : false;
76 }
77 bool
79 {
80  return (m_dataControlBit == CONTROL_PDU) ? true : false;
81 }
82 
83 void
84 LteRlcAmHeader::SetFramingInfo (uint8_t framingInfo)
85 {
86  m_framingInfo = framingInfo & 0x03;
87 }
88 
89 void
91 {
92  m_sequenceNumber = sequenceNumber;
93 }
94 
95 uint8_t
97 {
98  return m_framingInfo;
99 }
100 
103 {
104  return m_sequenceNumber;
105 }
106 
107 
108 void
109 LteRlcAmHeader::PushExtensionBit (uint8_t extensionBit)
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 
125 void
126 LteRlcAmHeader::PushLengthIndicator (uint16_t lengthIndicator)
127 {
128  m_lengthIndicators.push_back (lengthIndicator);
129 }
130 
131 
132 uint8_t
134 {
135  uint8_t extensionBit = m_extensionBits.front ();
136  m_extensionBits.pop_front ();
137 
138  return extensionBit;
139 }
140 
141 uint16_t
143 {
144  uint16_t lengthIndicator = m_lengthIndicators.front ();
145  m_lengthIndicators.pop_front ();
146 
147  return lengthIndicator;
148 }
149 
150 
151 void
153 {
154  m_resegmentationFlag = resegFlag & 0x01;
155 }
156 
157 uint8_t
159 {
160  return m_resegmentationFlag;
161 }
162 
163 
164 void
165 LteRlcAmHeader::SetPollingBit (uint8_t pollingBit)
166 {
167  m_pollingBit = pollingBit & 0x01;
168 }
169 
170 uint8_t
172 {
173  return m_pollingBit;
174 }
175 
176 
177 void
179 {
180  m_lastSegmentFlag = lsf & 0x01;
181 }
182 
183 uint8_t
185 {
186  return m_lastSegmentFlag;
187 }
188 
189 
190 void
191 LteRlcAmHeader::SetSegmentOffset (uint16_t segmentOffset)
192 {
193  m_segmentOffset = segmentOffset & 0x7FFF;
194 }
195 
196 uint16_t
198 {
199  return m_segmentOffset;
200 }
201 
202 uint16_t
204 {
205  return m_lastOffset;
206 }
207 
208 
209 void
211 {
212  m_ackSn = ackSn;
213 }
214 
215 bool
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 
231 void
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  {
241  m_headerLength++;
242  }
243  else
244  {
245  m_headerLength+=2;
246  }
247 }
248 
249 bool
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 
267 int
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 
292 TypeId
294 {
295  static TypeId tid = TypeId ("ns3::LteRlcAmHeader")
296  .SetParent<Header> ()
297  .SetGroupName("Lte")
298  .AddConstructor<LteRlcAmHeader> ()
299  ;
300  return tid;
301 }
302 
303 TypeId
305 {
306  return GetTypeId ();
307 }
308 
309 void
310 LteRlcAmHeader::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;
628  m_headerLength+=3;
629  }
630  else
631  {
632  m_headerLength++;
633  }
634 
635  }
636  }
637  else
638  {
639  m_headerLength++;
640  }
641  }
642 
643  return GetSerializedSize ();
644 }
645 
646 }; // namespace ns3
uint8_t PopExtensionBit(void)
Pop extension bit function.
uint8_t GetLastSegmentFlag() const
Get last segment flag function.
Protocol header serialization and deserialization.
Definition: header.h:42
uint8_t m_controlPduType
control PDU type
uint16_t m_headerLength
header length
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint16_t GetValue() const
Extracts the numeric value of the sequence number.
void SetResegmentationFlag(uint8_t resegFlag)
Pop extension bit function.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
std::list< uint8_t > m_extensionBits
Includes extensionBit of the fixed part.
uint8_t m_dataControlBit
data control bit
def start()
Definition: core.py:1855
void SetSequenceNumber(SequenceNumber10 sequenceNumber)
Set sequence number.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
void SetDataPdu(void)
Set data PDU function.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
void SetPollingBit(uint8_t pollingBit)
Set polling bit function.
uint8_t m_lastSegmentFlag
last segment flag
std::list< uint16_t > m_lengthIndicators
length indicators
virtual uint32_t GetSerializedSize(void) const
iterator in a Buffer instance
Definition: buffer.h:98
SequenceNumber10 GetSequenceNumber() const
Get sequence number.
uint8_t m_pollingBit
polling bit
bool IsNackPresent(SequenceNumber10 nack)
void PushNack(int nack)
Add one more NACK to the CONTROL PDU.
uint8_t m_framingInfo
2 bits
void SetFramingInfo(uint8_t framingInfo)
Set sequence number.
bool IsControlPdu(void) const
Is control PDU function.
std::list< int > m_nackSnList
nack sn list
void SetSegmentOffset(uint16_t segmentOffset)
Set segment offset function.
uint8_t m_resegmentationFlag
resegmentation flag
virtual void Print(std::ostream &os) const
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
SequenceNumber10 m_sequenceNumber
sequence number
void PushLengthIndicator(uint16_t lengthIndicator)
Push length indicator function.
void SetControlPdu(uint8_t controlPduType)
Set control PDU function.
The packet header for the AM Radio Link Control (RLC) protocol packets.
SequenceNumber10 m_ackSn
ack sn
Every class exported by the ns3 library is enclosed in the ns3 namespace.
virtual uint32_t Deserialize(Buffer::Iterator start)
uint8_t GetResegmentationFlag() const
Get resegmentation flag function.
bool IsDataPdu(void) const
Is data PDU function.
uint8_t GetFramingInfo() const
Get framing info.
uint8_t GetPollingBit() const
Get polling bit function.
#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
static TypeId GetTypeId(void)
Get the type ID.
void WriteU8(uint8_t data)
Definition: buffer.h:869
SequenceNumber10 GetAckSn() const
Get ack sn function.
uint16_t GetLastOffset() const
Get last offset function.
uint16_t m_lastOffset
last offset
uint16_t PopLengthIndicator(void)
Pop length indicator function.
bool OneMoreNackWouldFitIn(uint16_t bytes)
uint8_t ReadU8(void)
Definition: buffer.h:1021
int PopNack(void)
Retrieve one NACK from the CONTROL PDU.
SequenceNumber10 class.
void SetAckSn(SequenceNumber10 ackSn)
Set ack sn function.
uint16_t GetSegmentOffset() const
Get segment offset function.
void SetLastSegmentFlag(uint8_t lsf)
Set last segment flag function.
void PushExtensionBit(uint8_t extensionBit)
Push extension bit function.
uint16_t m_segmentOffset
segment offset
virtual void Serialize(Buffer::Iterator start) const
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
LteRlcAmHeader()
Constructor.