A Discrete-Event Network Simulator
API
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  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Manuel Requena <manuel.requena@cttc.es>
18  */
19 
20 #include "lte-rlc-am-header.h"
21 
22 #include "ns3/log.h"
23 
24 namespace ns3
25 {
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 
66 void
67 LteRlcAmHeader::SetControlPdu(uint8_t controlPduType)
68 {
69  m_headerLength = 2;
71  m_controlPduType = controlPduType;
72 }
73 
74 bool
76 {
77  return m_dataControlBit == DATA_PDU;
78 }
79 
80 bool
82 {
83  return m_dataControlBit == CONTROL_PDU;
84 }
85 
86 void
87 LteRlcAmHeader::SetFramingInfo(uint8_t framingInfo)
88 {
89  m_framingInfo = framingInfo & 0x03;
90 }
91 
92 void
94 {
95  m_sequenceNumber = sequenceNumber;
96 }
97 
98 uint8_t
100 {
101  return m_framingInfo;
102 }
103 
106 {
107  return m_sequenceNumber;
108 }
109 
110 void
111 LteRlcAmHeader::PushExtensionBit(uint8_t extensionBit)
112 {
113  m_extensionBits.push_back(extensionBit);
114  if (m_extensionBits.size() > 1)
115  {
116  if (m_extensionBits.size() % 2)
117  {
118  m_headerLength += 1;
119  }
120  else
121  {
122  m_headerLength += 2;
123  }
124  }
125 }
126 
127 void
128 LteRlcAmHeader::PushLengthIndicator(uint16_t lengthIndicator)
129 {
130  m_lengthIndicators.push_back(lengthIndicator);
131 }
132 
133 uint8_t
135 {
136  uint8_t extensionBit = m_extensionBits.front();
137  m_extensionBits.pop_front();
138 
139  return extensionBit;
140 }
141 
142 uint16_t
144 {
145  uint16_t lengthIndicator = m_lengthIndicators.front();
146  m_lengthIndicators.pop_front();
147 
148  return lengthIndicator;
149 }
150 
151 void
153 {
154  m_resegmentationFlag = resegFlag & 0x01;
155 }
156 
157 uint8_t
159 {
160  return m_resegmentationFlag;
161 }
162 
163 void
164 LteRlcAmHeader::SetPollingBit(uint8_t pollingBit)
165 {
166  m_pollingBit = pollingBit & 0x01;
167 }
168 
169 uint8_t
171 {
172  return m_pollingBit;
173 }
174 
175 void
177 {
178  m_lastSegmentFlag = lsf & 0x01;
179 }
180 
181 uint8_t
183 {
184  return m_lastSegmentFlag;
185 }
186 
187 void
188 LteRlcAmHeader::SetSegmentOffset(uint16_t segmentOffset)
189 {
190  m_segmentOffset = segmentOffset & 0x7FFF;
191 }
192 
193 uint16_t
195 {
196  return m_segmentOffset;
197 }
198 
199 uint16_t
201 {
202  return m_lastOffset;
203 }
204 
205 void
207 {
208  m_ackSn = ackSn;
209 }
210 
211 bool
213 {
214  NS_LOG_FUNCTION(this << bytes);
216  "method allowed only for STATUS PDUs");
217  if (m_nackSnList.size() % 2 == 0)
218  {
219  return (m_headerLength < bytes);
220  }
221  else
222  {
223  return (m_headerLength < (bytes - 1));
224  }
225 }
226 
227 void
229 {
230  NS_LOG_FUNCTION(this << nack);
232  "method allowed only for STATUS PDUs");
233  m_nackSnList.push_back(nack);
234 
235  if (m_nackSnList.size() % 2 == 0)
236  {
237  m_headerLength++;
238  }
239  else
240  {
241  m_headerLength += 2;
242  }
243 }
244 
245 bool
247 {
248  NS_LOG_FUNCTION(this);
250  "method allowed only for STATUS PDUs");
251  for (auto nackIt = m_nackSnList.begin(); nackIt != m_nackSnList.end(); ++nackIt)
252  {
253  if ((*nackIt) == nack.GetValue())
254  {
255  return true;
256  }
257  }
258  return false;
259 }
260 
261 int
263 {
264  NS_LOG_FUNCTION(this);
266  "method allowed only for STATUS PDUs");
267  if (m_nackSnList.empty())
268  {
269  return -1;
270  }
271 
272  int nack = m_nackSnList.front();
273  m_nackSnList.pop_front();
274 
275  return nack;
276 }
277 
280 {
281  return m_ackSn;
282 }
283 
284 TypeId
286 {
287  static TypeId tid = TypeId("ns3::LteRlcAmHeader")
288  .SetParent<Header>()
289  .SetGroupName("Lte")
290  .AddConstructor<LteRlcAmHeader>();
291  return tid;
292 }
293 
294 TypeId
296 {
297  return GetTypeId();
298 }
299 
300 void
301 LteRlcAmHeader::Print(std::ostream& os) const
302 {
303  auto it1 = m_extensionBits.begin();
304  auto it2 = m_lengthIndicators.begin();
305  auto it3 = m_nackSnList.begin();
306 
307  os << "Len=" << m_headerLength;
308  os << " D/C=" << (uint16_t)m_dataControlBit;
309 
310  if (m_dataControlBit == DATA_PDU)
311  {
312  os << " RF=" << (uint16_t)m_resegmentationFlag;
313  os << " P=" << (uint16_t)m_pollingBit;
314  os << " FI=" << (uint16_t)m_framingInfo;
315  os << " E=" << (uint16_t)(*it1);
316  os << " SN=" << m_sequenceNumber;
317  os << " LSF=" << (uint16_t)(m_lastSegmentFlag);
318  os << " SO=" << m_segmentOffset;
319 
320  it1++;
321  if (it1 != m_extensionBits.end())
322  {
323  os << " E=";
324  }
325  while (it1 != m_extensionBits.end())
326  {
327  os << (uint16_t)(*it1);
328  it1++;
329  }
330 
331  if (it2 != m_lengthIndicators.end())
332  {
333  os << " LI=";
334  }
335  while (it2 != m_lengthIndicators.end())
336  {
337  os << (uint16_t)(*it2) << " ";
338  it2++;
339  }
340  }
341  else // if ( m_dataControlBit == CONTROL_PDU )
342  {
343  os << " ACK_SN=" << m_ackSn;
344 
345  while (it3 != m_nackSnList.end())
346  {
347  os << " NACK_SN=" << (int)(*it3);
348  it3++;
349  }
350  }
351 }
352 
353 uint32_t
355 {
356  return m_headerLength;
357 }
358 
359 void
361 {
363 
364  auto it1 = m_extensionBits.begin();
365  auto it2 = m_lengthIndicators.begin();
366  auto it3 = m_nackSnList.begin();
367 
368  if (m_dataControlBit == DATA_PDU)
369  {
370  i.WriteU8(((DATA_PDU << 7) & 0x80) | ((m_resegmentationFlag << 6) & 0x40) |
371  ((m_pollingBit << 5) & 0x20) | ((m_framingInfo << 3) & 0x18) |
372  (((*it1) << 2) & 0x04) | ((m_sequenceNumber.GetValue() >> 8) & 0x0003));
373  i.WriteU8(m_sequenceNumber.GetValue() & 0x00FF);
374  i.WriteU8(((m_lastSegmentFlag << 7) & 0x80) | ((m_segmentOffset >> 8) & 0x007F));
375  i.WriteU8(m_segmentOffset & 0x00FF);
376  it1++;
377 
378  while (it1 != m_extensionBits.end() && it2 != m_lengthIndicators.end())
379  {
380  uint16_t oddLi;
381  uint16_t evenLi;
382  uint8_t oddE;
383  uint8_t evenE;
384 
385  oddE = *it1;
386  oddLi = *it2;
387 
388  it1++;
389  it2++;
390 
391  if (it1 != m_extensionBits.end() && it2 != m_lengthIndicators.end())
392  {
393  evenE = *it1;
394  evenLi = *it2;
395 
396  i.WriteU8(((oddE << 7) & 0x80) | ((oddLi >> 4) & 0x007F));
397  i.WriteU8(((oddLi << 4) & 0x00F0) | ((evenE << 3) & 0x08) |
398  ((evenLi >> 8) & 0x0007));
399  i.WriteU8(evenLi & 0x00FF);
400 
401  it1++;
402  it2++;
403  }
404  else
405  {
406  i.WriteU8(((oddE << 7) & 0x80) | ((oddLi >> 4) & 0x007F));
407  i.WriteU8((oddLi << 4) & 0x00F0); // Padding is implicit
408  }
409  }
410  }
411  else // if ( m_dataControlBit == CONTROL_PDU )
412  {
413  i.WriteU8(((CONTROL_PDU << 7) & 0x80) | ((m_controlPduType << 4) & 0x70) |
414  ((m_ackSn.GetValue() >> 6) & 0x0F));
415  // note: second part of ackSn will be written later
416 
417  // serialize the NACKs
418  if (it3 == m_nackSnList.end())
419  {
420  NS_LOG_LOGIC(this << " no NACKs");
421  // If there are no NACKs then this line adds the rest of the ACK
422  // along with 0x00, indicating an E1 value of 0 or no NACKs follow.
423  i.WriteU8((m_ackSn.GetValue() << 2) & 0xFC);
424  }
425  else
426  {
427  int oddNack = *it3;
428  int evenNack = -1;
429  // Else write out a series of E1 = 1 and NACK values. Note since we
430  // are not supporting SO start/end the value of E2 will always be 0.
431 
432  // First write out the ACK along with the very first NACK
433  // And the remaining NACK with 0x02 or 10 in binary to set
434  // E1 to 1, then Or in the first bit of the NACK
435  i.WriteU8(((m_ackSn.GetValue() << 2) & 0xFC) | (0x02) | ((*it3 >> 9) & 0x01));
436 
437  while (it3 != m_nackSnList.end())
438  {
439  // The variable oddNack has the current NACK value to write, also
440  // either the setup to enter this loop or the previous loop would
441  // have written the highest order bit to the previous octet.
442  // Write the next set of bits (2 - 9) into the next octet
443  i.WriteU8((oddNack >> 1) & 0xFF);
444 
445  // Next check to see if there is going to be another NACK after
446  // this
447  it3++;
448  if (it3 != m_nackSnList.end())
449  {
450  // Yes there will be another NACK after this, so E1 will be 1
451  evenNack = *it3;
452  i.WriteU8(((oddNack << 7) & 0x80) | (0x40) // E1 = 1 E2 = 0, more NACKs
453  | ((evenNack >> 5) & 0x1F));
454 
455  // The final octet of this loop will have the rest of the
456  // NACK and another E1, E2. Check to see if there will be
457  // one more NACK after this.
458  it3++;
459  if (it3 != m_nackSnList.end())
460  {
461  // Yes there is at least one more NACK. Finish writing
462  // this octet and the next iteration will do the rest.
463  oddNack = *it3;
464  i.WriteU8(((evenNack << 3) & 0xF8) | (0x04) | ((oddNack >> 9) & 0x01));
465  }
466  else
467  {
468  // No, there are no more NACKs
469  i.WriteU8((evenNack << 3) & 0xF8);
470  }
471  }
472  else
473  {
474  // No, this is the last NACK so E1 will be 0
475  i.WriteU8((oddNack << 7) & 0x80);
476  }
477  }
478  }
479  }
480 }
481 
482 uint32_t
484 {
486  uint8_t byte_1;
487  uint8_t byte_2;
488  uint8_t byte_3;
489  uint8_t byte_4;
490  uint8_t extensionBit;
491 
492  byte_1 = i.ReadU8();
493  m_headerLength = 1;
494  m_dataControlBit = (byte_1 & 0x80) >> 7;
495 
496  if (m_dataControlBit == DATA_PDU)
497  {
498  byte_2 = i.ReadU8();
499  byte_3 = i.ReadU8();
500  byte_4 = i.ReadU8();
501  m_headerLength += 3;
502 
503  m_resegmentationFlag = (byte_1 & 0x40) >> 6;
504  m_pollingBit = (byte_1 & 0x20) >> 5;
505  m_framingInfo = (byte_1 & 0x18) >> 3;
506  m_sequenceNumber = ((byte_1 & 0x03) << 8) | byte_2;
507 
508  m_lastSegmentFlag = (byte_3 & 0x80) >> 7;
509  m_segmentOffset = (byte_3 & 0x7F) | byte_4;
510 
511  extensionBit = (byte_1 & 0x04) >> 2;
512  m_extensionBits.push_back(extensionBit);
513 
514  if (extensionBit == DATA_FIELD_FOLLOWS)
515  {
516  return GetSerializedSize();
517  }
518 
519  uint16_t oddLi;
520  uint16_t evenLi;
521  uint8_t oddE;
522  uint8_t evenE;
523  bool moreLiFields = (extensionBit == E_LI_FIELDS_FOLLOWS);
524 
525  while (moreLiFields)
526  {
527  byte_1 = i.ReadU8();
528  byte_2 = i.ReadU8();
529 
530  oddE = (byte_1 & 0x80) >> 7;
531  oddLi = ((byte_1 & 0x7F) << 4) | ((byte_2 & 0xF0) >> 4);
532  moreLiFields = (oddE == E_LI_FIELDS_FOLLOWS);
533 
534  m_extensionBits.push_back(oddE);
535  m_lengthIndicators.push_back(oddLi);
536  m_headerLength += 2;
537 
538  if (moreLiFields)
539  {
540  byte_3 = i.ReadU8();
541 
542  evenE = (byte_2 & 0x08) >> 3;
543  evenLi = ((byte_2 & 0x07) << 8) | (byte_3 & 0xFF);
544  moreLiFields = (evenE == E_LI_FIELDS_FOLLOWS);
545 
546  m_extensionBits.push_back(evenE);
547  m_lengthIndicators.push_back(evenLi);
548 
549  m_headerLength += 1;
550  }
551  }
552 
554  {
556  }
557  }
558  else // if ( m_dataControlBit == CONTROL_PDU )
559  {
560  byte_2 = i.ReadU8();
561 
562  m_controlPduType = (byte_1 & 0x70) >> 4;
563  m_ackSn = ((byte_1 & 0x0F) << 6) | ((byte_2 & 0xFC) >> 2);
564 
565  int moreNacks = (byte_2 & 0x02) >> 1;
566  // Get the first NACK outside the loop as it is not preceded by an E2
567  // field but all following NACKs will.
568  if (moreNacks == 1)
569  {
570  byte_3 = i.ReadU8();
571  byte_4 = i.ReadU8();
572  m_headerLength = 4;
573 
574  m_nackSnList.push_back(((byte_2 & 0x01) << 9) | (byte_3 << 1) | ((byte_4 & 0x80) >> 7));
575 
576  // Loop until all NACKs are found
577  moreNacks = ((byte_4 & 0x40) >> 6);
578  uint8_t byte = byte_4;
579  uint8_t nextByte;
580  uint8_t finalByte;
581  while (moreNacks == 1)
582  {
583  // Ignore E2, read next NACK
584  nextByte = i.ReadU8();
585  m_nackSnList.push_back(((byte & 0x1F) << 5) | ((nextByte & 0xF8) >> 3));
586 
587  // Check for another NACK, after this any following NACKs will
588  // be aligned properly for the next iteration of this loop.
589  moreNacks = (nextByte & 0x04) >> 2;
590  byte = nextByte;
591  if (moreNacks == 1)
592  {
593  nextByte = i.ReadU8();
594  finalByte = i.ReadU8();
595 
596  m_nackSnList.push_back(((byte & 0x01) << 9) | (nextByte << 1) |
597  ((finalByte & 0x80) >> 7));
598 
599  moreNacks = ((finalByte & 0x40) >> 6);
600  byte = finalByte;
601  m_headerLength += 3;
602  }
603  else
604  {
605  m_headerLength++;
606  }
607  }
608  }
609  else
610  {
611  m_headerLength++;
612  }
613  }
614 
615  return GetSerializedSize();
616 }
617 
618 }; // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
Protocol header serialization and deserialization.
Definition: header.h:44
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.
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.
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:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
#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:86
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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:46
Every class exported by the ns3 library is enclosed in the ns3 namespace.