From 0cd22f5536ccb9f5c2098778acaefb139012b108 Mon Sep 17 00:00:00 2001 From: Manuel Requena Date: Wed, 1 Aug 2012 13:21:02 +0200 Subject: [PATCH] Add some IEs to the X2 message headers --- src/lte/examples/lena-x2-handover.cc | 3 + src/lte/model/epc-x2-header.cc | 304 +++++++++++++++++++++++---- src/lte/model/epc-x2.cc | 4 +- 3 files changed, 273 insertions(+), 38 deletions(-) diff --git a/src/lte/examples/lena-x2-handover.cc b/src/lte/examples/lena-x2-handover.cc index cf999912a..8324bb19e 100644 --- a/src/lte/examples/lena-x2-handover.cc +++ b/src/lte/examples/lena-x2-handover.cc @@ -146,6 +146,9 @@ main (int argc, char *argv[]) lteHelper->HandoverRequest (Seconds (2.0), ueNodes.Get (0), enbNodes.Get (0), enbNodes.Get (1)); + // Uncomment to enable PCAP tracing + //p2ph.EnablePcapAll("lena-x2-handover"); + Simulator::Stop(Seconds(simTime)); Simulator::Run(); diff --git a/src/lte/model/epc-x2-header.cc b/src/lte/model/epc-x2-header.cc index 3b4e46553..54096d855 100644 --- a/src/lte/model/epc-x2-header.cc +++ b/src/lte/model/epc-x2-header.cc @@ -19,18 +19,21 @@ */ #include "ns3/log.h" -// #include "ns3/packet.h" #include "ns3/epc-x2-header.h" + NS_LOG_COMPONENT_DEFINE ("EpcX2Header"); namespace ns3 { - + + NS_OBJECT_ENSURE_REGISTERED (EpcX2Header); EpcX2Header::EpcX2Header () : m_messageType (0xfa), - m_procedureCode (0xfa) + m_procedureCode (0xfa), + m_lengthOfIes (0xfa), + m_numberOfIes (0xfa) { } @@ -38,6 +41,8 @@ EpcX2Header::~EpcX2Header () { m_messageType = 0xfb; m_procedureCode = 0xfb; + m_lengthOfIes = 0xfb; + m_numberOfIes = 0xfb; } TypeId @@ -59,7 +64,7 @@ EpcX2Header::GetInstanceTypeId (void) const uint32_t EpcX2Header::GetSerializedSize (void) const { - return 2; + return 7; } void @@ -69,6 +74,11 @@ EpcX2Header::Serialize (Buffer::Iterator start) const i.WriteU8 (m_messageType); i.WriteU8 (m_procedureCode); + + i.WriteU8 (0x00); // criticality = REJECT + i.WriteU8 (m_lengthOfIes + 3); + i.WriteHtonU16 (0); + i.WriteU8 (m_numberOfIes); } uint32_t @@ -79,6 +89,11 @@ EpcX2Header::Deserialize (Buffer::Iterator start) m_messageType = i.ReadU8 (); m_procedureCode = i.ReadU8 (); + i.ReadU8 (); + m_lengthOfIes = i.ReadU8 () - 3; + i.ReadNtohU16 (); + m_numberOfIes = i.ReadU8 (); + return GetSerializedSize (); } @@ -87,6 +102,8 @@ EpcX2Header::Print (std::ostream &os) const { os << "MessageType=" << (uint32_t) m_messageType; os << " ProcedureCode=" << (uint32_t) m_procedureCode; + os << " LengthOfIEs=" << (uint32_t) m_lengthOfIes; + os << " NumberOfIEs=" << (uint32_t) m_numberOfIes; } uint8_t @@ -98,7 +115,7 @@ EpcX2Header::GetMessageType () const void EpcX2Header::SetMessageType (uint8_t messageType) { - this->m_messageType = messageType; + m_messageType = messageType; } uint8_t @@ -110,7 +127,20 @@ EpcX2Header::GetProcedureCode () const void EpcX2Header::SetProcedureCode (uint8_t procedureCode) { - this->m_procedureCode = procedureCode; + m_procedureCode = procedureCode; +} + + +void +EpcX2Header::SetLengthOfIes (uint32_t lengthOfIes) +{ + m_lengthOfIes = lengthOfIes; +} + +void +EpcX2Header::SetNumberOfIes (uint32_t numberOfIes) +{ + m_numberOfIes = numberOfIes; } ///////////////////////////////////////////////////////////////////// @@ -118,7 +148,9 @@ EpcX2Header::SetProcedureCode (uint8_t procedureCode) NS_OBJECT_ENSURE_REGISTERED (EpcX2HandoverRequestHeader); EpcX2HandoverRequestHeader::EpcX2HandoverRequestHeader () - : m_oldEnbUeX2apId (0xfffa), + : m_numberOfIes (0), + m_headerLength (0), + m_oldEnbUeX2apId (0xfffa), m_cause (0xfffa), m_targetCellId (0xfffa) { @@ -126,10 +158,12 @@ EpcX2HandoverRequestHeader::EpcX2HandoverRequestHeader () EpcX2HandoverRequestHeader::~EpcX2HandoverRequestHeader () { + m_numberOfIes = 0; + m_headerLength = 0; m_oldEnbUeX2apId = 0xfffb; m_cause = 0xfffb; m_targetCellId = 0xfffb; - m_erabsList.clear (); // TODO Clearing of a list + m_erabsToBeSetupList.clear (); } TypeId @@ -151,7 +185,7 @@ EpcX2HandoverRequestHeader::GetInstanceTypeId (void) const uint32_t EpcX2HandoverRequestHeader::GetSerializedSize (void) const { - return 6; + return m_headerLength; } void @@ -159,9 +193,46 @@ EpcX2HandoverRequestHeader::Serialize (Buffer::Iterator start) const { Buffer::Iterator i = start; + i.WriteHtonU16 (10); // id = OLD_ENB_UE_X2AP_ID + i.WriteU8 (0); // criticality = REJECT + i.WriteU8 (2); // length of OLD_ENB_UE_X2AP_ID i.WriteHtonU16 (m_oldEnbUeX2apId); - i.WriteHtonU16 (m_cause); - i.WriteHtonU16 (m_targetCellId); + + i.WriteHtonU16 (5); // id = CAUSE + i.WriteU8 (1 << 6); // criticality = IGNORE + i.WriteU8 (1); // length of CAUSE + i.WriteU8 (m_cause); + + i.WriteHtonU16 (11); // id = TARGET_CELLID + i.WriteU8 (0); // criticality = REJECT + i.WriteU8 (8); // length of TARGET_CELLID + i.WriteHtonU32 (0x123456); // fake PLMN + i.WriteHtonU32 (m_targetCellId << 4); + + i.WriteHtonU16 (14); // id = UE_CONTEXT_INFORMATION + i.WriteU8 (0); // criticality = REJECT + + i.WriteHtonU64 (m_ueAggregateMaxBitRateDownlink); + i.WriteHtonU64 (m_ueAggregateMaxBitRateUplink); + + std::vector ::size_type sz = m_erabsToBeSetupList.size (); + i.WriteHtonU32 (sz); // number of bearers + for (int j = 0; j < (int) sz; j++) + { + i.WriteHtonU16 (m_erabsToBeSetupList [j].erabId); + i.WriteHtonU16 (m_erabsToBeSetupList [j].erabLevelQosParameters.qci); + i.WriteHtonU64 (m_erabsToBeSetupList [j].erabLevelQosParameters.gbrQosInfo.gbrDl); + i.WriteHtonU64 (m_erabsToBeSetupList [j].erabLevelQosParameters.gbrQosInfo.gbrUl); + i.WriteHtonU64 (m_erabsToBeSetupList [j].erabLevelQosParameters.gbrQosInfo.mbrDl); + i.WriteHtonU64 (m_erabsToBeSetupList [j].erabLevelQosParameters.gbrQosInfo.mbrUl); + i.WriteU8 (m_erabsToBeSetupList [j].erabLevelQosParameters.arp.priorityLevel); + i.WriteU8 (m_erabsToBeSetupList [j].erabLevelQosParameters.arp.preemptionCapability); + i.WriteU8 (m_erabsToBeSetupList [j].erabLevelQosParameters.arp.preemptionVulnerability); + i.WriteU8 (m_erabsToBeSetupList [j].dlForwarding); + i.WriteHtonU32 (m_erabsToBeSetupList [j].transportLayerAddress.Get ()); + i.WriteHtonU32 (m_erabsToBeSetupList [j].gtpTeid); + } + } uint32_t @@ -169,9 +240,64 @@ EpcX2HandoverRequestHeader::Deserialize (Buffer::Iterator start) { Buffer::Iterator i = start; + m_headerLength = 0; + + i.ReadNtohU16 (); + i.ReadU8 (); + i.ReadU8 (); m_oldEnbUeX2apId = i.ReadNtohU16 (); - m_cause = i.ReadNtohU16 (); - m_targetCellId = i.ReadNtohU16 (); + m_headerLength += 6; + + i.ReadNtohU16 (); + i.ReadU8 (); + i.ReadU8 (); + m_cause = i.ReadU8 (); + m_headerLength += 5; + + i.ReadNtohU16 (); + i.ReadU8 (); + i.ReadU8 (); + i.ReadNtohU32 (); + m_targetCellId = i.ReadNtohU32 () >> 4; + m_headerLength += 12; + + i.ReadNtohU16 (); + i.ReadU8 (); + m_ueAggregateMaxBitRateDownlink = i.ReadNtohU64 (); + m_ueAggregateMaxBitRateUplink = i.ReadNtohU64 (); + + int sz = i.ReadNtohU32 (); + for (int j = 0; j < sz; j++) + { + EpcX2Sap::ErabToBeSetupItem erabItem; + + erabItem.erabId = i.ReadNtohU16 (); + erabItem.erabLevelQosParameters = EpsBearer ((EpsBearer::Qci) i.ReadNtohU16 ()); + +#if 0 // TODO missing some parameters in EpsBearer + erabItem.erabLevelQosParameters.gbrQosInfo.gbrDl = i.ReadNtohU64 (); + erabItem.erabLevelQosParameters.gbrQosInfo.gbrUl = i.ReadNtohU64 (); + erabItem.erabLevelQosParameters.gbrQosInfo.mbrDl = i.ReadNtohU64 (); + erabItem.erabLevelQosParameters.gbrQosInfo.mbrUl = i.ReadNtohU64 (); + erabItem.erabLevelQosParameters.arp.priorityLevel = i.ReadU8 (); + erabItem.erabLevelQosParameters.arp.preemptionCapability = i.ReadU8 (); + erabItem.erabLevelQosParameters.arp.preemptionVulnerability = i.ReadU8 (); +#else + i.ReadNtohU64 (); + i.ReadNtohU64 (); + i.ReadNtohU64 (); + i.ReadNtohU64 (); + i.ReadU8 (); + i.ReadU8 (); + i.ReadU8 (); +#endif + + erabItem.dlForwarding = i.ReadU8 (); + erabItem.transportLayerAddress = Ipv4Address (i.ReadNtohU32 ()); + erabItem.gtpTeid = i.ReadNtohU32 (); + + m_erabsToBeSetupList[j] = erabItem; + } return GetSerializedSize (); } @@ -179,8 +305,35 @@ EpcX2HandoverRequestHeader::Deserialize (Buffer::Iterator start) void EpcX2HandoverRequestHeader::Print (std::ostream &os) const { - os << "Cause=" << m_cause; + os << "OldEnbUeX2apId=" << m_oldEnbUeX2apId; + os << " Cause=" << m_cause; os << " TargetCellId=" << m_targetCellId; + os << " UeAggrMaxBitRateDownlink= " << m_ueAggregateMaxBitRateDownlink; + os << " UeAggrMaxBitRateUplink= " << m_ueAggregateMaxBitRateUplink; + os << " NumOfBearers=" << m_erabsToBeSetupList.size (); + + std::vector ::size_type sz = m_erabsToBeSetupList.size (); + os << " ["; + for (int j = 0; j < (int) sz; j++) + { + os << m_erabsToBeSetupList[j].erabId << " "; + } + os << "]"; +} + +uint16_t +EpcX2HandoverRequestHeader::GetOldEnbUeX2apId () const +{ + return m_oldEnbUeX2apId; +} + +void +EpcX2HandoverRequestHeader::SetOldEnbUeX2apId (uint16_t x2apId) +{ + m_oldEnbUeX2apId = x2apId; + + m_headerLength += 6; + m_numberOfIes++; } uint16_t @@ -192,7 +345,10 @@ EpcX2HandoverRequestHeader::GetCause () const void EpcX2HandoverRequestHeader::SetCause (uint16_t cause) { - this->m_cause = cause; + m_cause = cause; + + m_headerLength += 5; + m_numberOfIes++; } uint16_t @@ -204,7 +360,62 @@ EpcX2HandoverRequestHeader::GetTargetCellId () const void EpcX2HandoverRequestHeader::SetTargetCellId (uint16_t targetCellId) { - this->m_targetCellId = targetCellId; + m_targetCellId = targetCellId; + + m_headerLength += 12; + m_numberOfIes++; +} + +std::vector +EpcX2HandoverRequestHeader::GetBearers () const +{ + return m_erabsToBeSetupList; +} + +void +EpcX2HandoverRequestHeader::SetBearers (std::vector bearers) +{ + m_erabsToBeSetupList = bearers; +} + +uint64_t +EpcX2HandoverRequestHeader::GetUeAggregateMaxBitRateDownlink () const +{ + return m_ueAggregateMaxBitRateDownlink; +} + +void +EpcX2HandoverRequestHeader::SetUeAggregateMaxBitRateDownlink (uint64_t bitRate) +{ + m_ueAggregateMaxBitRateDownlink = bitRate; + + m_headerLength += 8; +} + +uint64_t +EpcX2HandoverRequestHeader::GetUeAggregateMaxBitRateUplink () const +{ + return m_ueAggregateMaxBitRateUplink; +} + +void +EpcX2HandoverRequestHeader::SetUeAggregateMaxBitRateUplink (uint64_t bitRate) +{ + m_ueAggregateMaxBitRateUplink = bitRate; + + m_headerLength += 8; +} + +uint32_t +EpcX2HandoverRequestHeader::GetLengthOfIes () const +{ + return m_headerLength; +} + +uint32_t +EpcX2HandoverRequestHeader::GetNumberOfIes () const +{ + return m_numberOfIes + 1; } ///////////////////////////////////////////////////////////////////// @@ -213,17 +424,16 @@ NS_OBJECT_ENSURE_REGISTERED (EpcX2HandoverRequestAckHeader); EpcX2HandoverRequestAckHeader::EpcX2HandoverRequestAckHeader () : m_oldEnbUeX2apId (0xfffa), - m_cause (0xfffa), - m_targetCellId (0xfffa) + m_newEnbUeX2apId (0xfffa) { } EpcX2HandoverRequestAckHeader::~EpcX2HandoverRequestAckHeader () { m_oldEnbUeX2apId = 0xfffb; - m_cause = 0xfffb; - m_targetCellId = 0xfffb; - m_erabsList.clear (); // TODO Clearing of a list + m_newEnbUeX2apId = 0xfffb; + m_erabsAdmittedList.clear (); + m_erabsNotAdmittedList.clear (); } TypeId @@ -245,7 +455,7 @@ EpcX2HandoverRequestAckHeader::GetInstanceTypeId (void) const uint32_t EpcX2HandoverRequestAckHeader::GetSerializedSize (void) const { - return 6; + return 4; } void @@ -254,8 +464,7 @@ EpcX2HandoverRequestAckHeader::Serialize (Buffer::Iterator start) const Buffer::Iterator i = start; i.WriteHtonU16 (m_oldEnbUeX2apId); - i.WriteHtonU16 (m_cause); - i.WriteHtonU16 (m_targetCellId); + i.WriteHtonU16 (m_newEnbUeX2apId); } uint32_t @@ -264,8 +473,7 @@ EpcX2HandoverRequestAckHeader::Deserialize (Buffer::Iterator start) Buffer::Iterator i = start; m_oldEnbUeX2apId = i.ReadNtohU16 (); - m_cause = i.ReadNtohU16 (); - m_targetCellId = i.ReadNtohU16 (); + m_newEnbUeX2apId = i.ReadNtohU16 (); return GetSerializedSize (); } @@ -273,32 +481,56 @@ EpcX2HandoverRequestAckHeader::Deserialize (Buffer::Iterator start) void EpcX2HandoverRequestAckHeader::Print (std::ostream &os) const { - os << "Cause=" << m_cause; - os << " TargetCellId=" << m_targetCellId; + os << "OldEnbUeX2apId=" << m_oldEnbUeX2apId; + os << " NewEnbUeX2apId=" << m_newEnbUeX2apId; } uint16_t -EpcX2HandoverRequestAckHeader::GetCause () const +EpcX2HandoverRequestAckHeader::GetOldEnbUeX2apId () const { - return m_cause; + return m_oldEnbUeX2apId; } void -EpcX2HandoverRequestAckHeader::SetCause (uint16_t cause) +EpcX2HandoverRequestAckHeader::SetOldEnbUeX2apId (uint16_t x2apId) { - this->m_cause = cause; + m_oldEnbUeX2apId = x2apId; } uint16_t -EpcX2HandoverRequestAckHeader::GetTargetCellId () const +EpcX2HandoverRequestAckHeader::GetNewEnbUeX2apId () const { - return m_targetCellId; + return m_newEnbUeX2apId; } void -EpcX2HandoverRequestAckHeader::SetTargetCellId (uint16_t targetCellId) +EpcX2HandoverRequestAckHeader::SetNewEnbUeX2apId (uint16_t x2apId) { - this->m_targetCellId = targetCellId; + m_newEnbUeX2apId = x2apId; +} + +std::vector +EpcX2HandoverRequestAckHeader::GetAdmittedBearers () const +{ + return m_erabsAdmittedList; +} + +void +EpcX2HandoverRequestAckHeader::SetAdmittedBearers (std::vector bearers) +{ + m_erabsAdmittedList = bearers; +} + +std::vector +EpcX2HandoverRequestAckHeader::GetNotAdmittedBearers () const +{ + return m_erabsNotAdmittedList; +} + +void +EpcX2HandoverRequestAckHeader::SetNotAdmittedBearers (std::vector bearers) +{ + m_erabsNotAdmittedList = bearers; } diff --git a/src/lte/model/epc-x2.cc b/src/lte/model/epc-x2.cc index b623b13d3..4138b95c4 100644 --- a/src/lte/model/epc-x2.cc +++ b/src/lte/model/epc-x2.cc @@ -262,8 +262,8 @@ EpcX2::DoSendHandoverRequest (EpcX2SapProvider::HandoverRequestParams params) EpcX2Header x2Header; x2Header.SetMessageType (EpcX2Header::InitiatingMessage); x2Header.SetProcedureCode (EpcX2Header::HandoverPreparation); -// x2Header.SetLengthOfIes (x2HoReqHeader.GetLengthOfIes ()); -// x2Header.SetNumberOfIes (x2HoReqHeader.GetNumberOfIes ()); + x2Header.SetLengthOfIes (x2HoReqHeader.GetLengthOfIes ()); + x2Header.SetNumberOfIes (x2HoReqHeader.GetNumberOfIes ()); NS_LOG_INFO ("X2 header: " << x2Header); NS_LOG_INFO ("X2 HandoverRequest header: " << x2HoReqHeader);