diff --git a/src/lte/model/lte-rlc-header.cc b/src/lte/model/lte-rlc-header.cc new file mode 100644 index 000000000..130714c72 --- /dev/null +++ b/src/lte/model/lte-rlc-header.cc @@ -0,0 +1,256 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Manuel Requena + */ + +#include "ns3/log.h" + +#include "ns3/lte-rlc-header.h" + +NS_LOG_COMPONENT_DEFINE ("LteRlcHeader"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (LteRlcHeader); + +LteRlcHeader::LteRlcHeader () + : m_headerLength (0), + m_framingInfo (0xff), + m_sequenceNumber (0xfffa) +{ +} + +LteRlcHeader::~LteRlcHeader () +{ + m_headerLength = 0; + m_framingInfo = 0xff; + m_sequenceNumber = 0xfffb; +} + +void +LteRlcHeader::SetFramingInfo (uint8_t framingInfo) +{ + m_framingInfo = framingInfo & 0x03; +} + +void +LteRlcHeader::SetSequenceNumber (uint16_t sequenceNumber) +{ + m_sequenceNumber = sequenceNumber & 0x03FF; +} + +uint8_t +LteRlcHeader::GetFramingInfo () const +{ + return m_framingInfo; +} + +uint16_t +LteRlcHeader::GetSequenceNumber () const +{ + return m_sequenceNumber; +} + + +void +LteRlcHeader::PushExtensionBit (uint8_t extensionBit) +{ + m_extensionBits.push_back (extensionBit); + if (m_extensionBits.size() == 1) + { + m_headerLength = 2; // Only fixed part + } + else if (m_extensionBits.size() % 2) + { + m_headerLength += 1; + } + else + { + m_headerLength += 2; + } +} + +void +LteRlcHeader::PushLengthIndicator (uint16_t lengthIndicator) +{ + m_lengthIndicators.push_back (lengthIndicator); +} + + +uint8_t +LteRlcHeader::PopExtensionBit (void) +{ + uint8_t extensionBit = m_extensionBits.front (); + m_extensionBits.pop_front (); + + return extensionBit; +} + +uint16_t +LteRlcHeader::PopLengthIndicator (void) +{ + uint16_t lengthIndicator = m_lengthIndicators.front (); + m_lengthIndicators.pop_front (); + + return lengthIndicator; +} + + +TypeId +LteRlcHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::LteRlcHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} + +TypeId +LteRlcHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +void LteRlcHeader::Print (std::ostream &os) const +{ + std::list ::const_iterator it1 = m_extensionBits.begin (); + std::list ::const_iterator it2 = m_lengthIndicators.begin (); + uint16_t i = 1; + + os << "Len=" << m_headerLength; + os << " FI=" << (uint16_t)m_framingInfo; + os << " E=" << (uint16_t)(*it1); + os << " SN=" << m_sequenceNumber; + + for (it1++; *it1 && *it2; i++, it1++, it2++) + { + os << " E(" << i << ")=" << (uint16_t)(*it1); + os << " LI(" << i << ")=" << (uint16_t)(*it2); + } +} + +uint32_t LteRlcHeader::GetSerializedSize (void) const +{ + return m_headerLength; +} + +void LteRlcHeader::Serialize (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + + std::list ::const_iterator it1 = m_extensionBits.begin (); + std::list ::const_iterator it2 = m_lengthIndicators.begin (); + + i.WriteU8 ( ((m_framingInfo << 3) & 0x18) | + (((*it1) << 2) & 0x04) | + ((m_sequenceNumber >> 8) & 0x0003) ); + i.WriteU8 ( m_sequenceNumber & 0x00FF ); + it1++; + + while ( it1 != m_extensionBits.end () && + it2 != m_lengthIndicators.end () ) + { + uint16_t oddLi, evenLi; + uint8_t oddE, evenE; + + oddE = *it1; + oddLi = *it2; + + it1++; + it2++; + + if ( it1 != m_extensionBits.end () && + it2 != m_lengthIndicators.end () ) + { + evenE = *it1; + evenLi = *it2; + + i.WriteU8 ( ((oddE << 7) & 0x80) | ((oddLi >> 4) & 0x007F) ); + i.WriteU8 ( ((oddLi << 4) & 0x00F0) | ((evenE << 3) & 0x08) | ((evenLi >> 8) & 0x0007) ); + i.WriteU8 ( evenLi & 0x00FF ); + + it1++; + it2++; + } + else + { + i.WriteU8 ( ((oddE << 7) & 0x80) | ((oddLi >> 4) & 0x007F) ); + i.WriteU8 ( ((oddLi << 4) & 0x00F0) ); // Padding is implicit + } + } +} + +uint32_t LteRlcHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + uint8_t byte_1; + uint8_t byte_2; + uint8_t byte_3; + uint8_t extensionBit; + + byte_1 = i.ReadU8 (); + byte_2 = i.ReadU8 (); + m_headerLength = 2; + m_framingInfo = (byte_1 & 0x18) >> 3; + m_sequenceNumber = ((byte_1 & 0x03) << 8) | byte_2; + + extensionBit = (byte_1 & 0x04) >> 2; + m_extensionBits.push_back (extensionBit); + + if (extensionBit == DATA_FIELD_FOLLOWS) + { + return GetSerializedSize (); + } + + uint16_t oddLi, evenLi; + uint8_t oddE, evenE; + bool moreLiFields = (extensionBit == E_LI_FIELDS_FOLLOWS); + + while (moreLiFields) + { + byte_1 = i.ReadU8 (); + byte_2 = i.ReadU8 (); + + oddE = (byte_1 & 0x80) >> 7; + oddLi = ((byte_1 & 0x7F) << 4) | ((byte_2 & 0xF0) >> 4); + moreLiFields = (oddE == E_LI_FIELDS_FOLLOWS); + + m_extensionBits.push_back (oddE); + m_lengthIndicators.push_back (oddLi); + m_headerLength += 2; + + if (moreLiFields) + { + byte_3 = i.ReadU8 (); + + evenE = (byte_2 & 0x08) >> 3; + evenLi = ((byte_2 & 0x07) << 8) | (byte_3 & 0xFF); + moreLiFields = (evenE == E_LI_FIELDS_FOLLOWS); + + m_extensionBits.push_back (evenE); + m_lengthIndicators.push_back (evenLi); + + m_headerLength += 1; + } + } + + return GetSerializedSize (); +} + +}; // namespace ns3 diff --git a/src/lte/model/lte-rlc-header.h b/src/lte/model/lte-rlc-header.h new file mode 100644 index 000000000..e10285035 --- /dev/null +++ b/src/lte/model/lte-rlc-header.h @@ -0,0 +1,97 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Manuel Requena + */ + +#ifndef LTE_RLC_HEADER_H +#define LTE_RLC_HEADER_H + +#include "ns3/header.h" + +#include + +namespace ns3 { + +/** + * \ingroup lte + * \brief The packet header for the Radio Link Control (RLC) protocol packets + * + * This class has fields corresponding to those in an RLC header as well as + * methods for serialization to and deserialization from a byte buffer. + * It follows 3GPP TS 36.322 Radio Link Control (RLC) protocol specification. + */ +class LteRlcHeader : public Header +{ +public: + + /** + * \brief Constructor + * + * Creates a null header + */ + LteRlcHeader (); + ~LteRlcHeader (); + + void SetFramingInfo (uint8_t framingInfo); + void SetSequenceNumber (uint16_t sequenceNumber); + + uint8_t GetFramingInfo () const; + uint16_t GetSequenceNumber () const; + + void PushExtensionBit (uint8_t extensionBit); + void PushLengthIndicator (uint16_t lengthIndicator); + + uint8_t PopExtensionBit (void); + uint16_t PopLengthIndicator (void); + + typedef enum { + DATA_FIELD_FOLLOWS = 0, + E_LI_FIELDS_FOLLOWS = 1 + } ExtensionBit_t; + + typedef enum { + FIRST_BYTE = 0x00, + NO_FIRST_BYTE = 0x02 + } FramingInfoFirstByte_t; + + typedef enum { + LAST_BYTE = 0x00, + NO_LAST_BYTE = 0x01 + } FramingInfoLastByte_t; + + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual void Print (std::ostream &os) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + +private: + uint16_t m_headerLength; + uint8_t m_framingInfo; // 2 bits + uint16_t m_sequenceNumber; // 10 bits TODO Maybe should be SequenceNumber10 or similar + + std::list m_extensionBits; // Includes extensionBit of the fixed part + std::list m_lengthIndicators; + +}; + +}; // namespace ns3 + +#endif // LTE_RLC_HEADER_H