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;
76 }
77 bool
79 {
80  return m_dataControlBit == CONTROL_PDU;
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
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
virtual uint32_t Deserialize(Buffer::Iterator start)=0
Deserialize the object from a buffer iterator.
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.
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