--- a/src/lte/model/epc-x2-header.cc Sat Sep 29 20:23:43 2012 +0200
+++ b/src/lte/model/epc-x2-header.cc Mon Oct 08 23:22:57 2012 +0200
@@ -533,5 +533,94 @@
m_erabsNotAdmittedList = bearers;
}
+/////////////////////////////////////////////////////////////////////
+
+NS_OBJECT_ENSURE_REGISTERED (EpcX2UeContextReleaseHeader);
+
+EpcX2UeContextReleaseHeader::EpcX2UeContextReleaseHeader ()
+ : m_oldEnbUeX2apId (0xfffa),
+ m_newEnbUeX2apId (0xfffa)
+{
+}
+
+EpcX2UeContextReleaseHeader::~EpcX2UeContextReleaseHeader ()
+{
+ m_oldEnbUeX2apId = 0xfffb;
+ m_newEnbUeX2apId = 0xfffb;
+}
+
+TypeId
+EpcX2UeContextReleaseHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::EpcX2UeContextReleaseHeader")
+ .SetParent<Header> ()
+ .AddConstructor<EpcX2UeContextReleaseHeader> ()
+ ;
+ return tid;
+}
+
+TypeId
+EpcX2UeContextReleaseHeader::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+uint32_t
+EpcX2UeContextReleaseHeader::GetSerializedSize (void) const
+{
+ return 4;
+}
+
+void
+EpcX2UeContextReleaseHeader::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+
+ i.WriteHtonU16 (m_oldEnbUeX2apId);
+ i.WriteHtonU16 (m_newEnbUeX2apId);
+}
+
+uint32_t
+EpcX2UeContextReleaseHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+
+ m_oldEnbUeX2apId = i.ReadNtohU16 ();
+ m_newEnbUeX2apId = i.ReadNtohU16 ();
+
+ return GetSerializedSize ();
+}
+
+void
+EpcX2UeContextReleaseHeader::Print (std::ostream &os) const
+{
+ os << "OldEnbUeX2apId=" << m_oldEnbUeX2apId;
+ os << " NewEnbUeX2apId=" << m_newEnbUeX2apId;
+}
+
+uint16_t
+EpcX2UeContextReleaseHeader::GetOldEnbUeX2apId () const
+{
+ return m_oldEnbUeX2apId;
+}
+
+void
+EpcX2UeContextReleaseHeader::SetOldEnbUeX2apId (uint16_t x2apId)
+{
+ m_oldEnbUeX2apId = x2apId;
+}
+
+uint16_t
+EpcX2UeContextReleaseHeader::GetNewEnbUeX2apId () const
+{
+ return m_newEnbUeX2apId;
+}
+
+void
+EpcX2UeContextReleaseHeader::SetNewEnbUeX2apId (uint16_t x2apId)
+{
+ m_newEnbUeX2apId = x2apId;
+}
+
} // namespace ns3
--- a/src/lte/model/epc-x2-header.h Sat Sep 29 20:23:43 2012 +0200
+++ b/src/lte/model/epc-x2-header.h Mon Oct 08 23:22:57 2012 +0200
@@ -55,7 +55,8 @@
enum ProcedureCode_t {
- HandoverPreparation = 0
+ HandoverPreparation = 0,
+ UeContextRelease = 5
};
enum TypeOfMessage_t {
@@ -157,6 +158,31 @@
};
+class EpcX2UeContextReleaseHeader : public Header
+{
+public:
+ EpcX2UeContextReleaseHeader ();
+ virtual ~EpcX2UeContextReleaseHeader ();
+
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ virtual uint32_t GetSerializedSize (void) const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ virtual void Print (std::ostream &os) const;
+
+
+ uint16_t GetOldEnbUeX2apId () const;
+ void SetOldEnbUeX2apId (uint16_t x2apId);
+
+ uint16_t GetNewEnbUeX2apId () const;
+ void SetNewEnbUeX2apId (uint16_t x2apId);
+
+private:
+ uint16_t m_oldEnbUeX2apId;
+ uint16_t m_newEnbUeX2apId;
+};
+
} // namespace ns3
#endif // EPC_X2_HEADER_H
--- a/src/lte/model/epc-x2.cc Sat Sep 29 20:23:43 2012 +0200
+++ b/src/lte/model/epc-x2.cc Mon Oct 08 23:22:57 2012 +0200
@@ -189,11 +189,17 @@
params.rrcContext = packet;
NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
NS_LOG_LOGIC ("cellsInfo->m_localCellId = " << cellsInfo->m_localCellId);
NS_ASSERT_MSG (params.targetCellId == cellsInfo->m_localCellId,
"TargetCellId mismatches with localCellId");
+ // Map oldEnbUeX2apId to sourceCellId
+ NS_ASSERT_MSG (m_x2Ues.find (params.oldEnbUeX2apId) == m_x2Ues.end (),
+ "UE already in CellId. enbUeX2apId = " << params.oldEnbUeX2apId << ". CellId = " << params.sourceCellId);
+ m_x2Ues [params.oldEnbUeX2apId] = params.sourceCellId;
+
m_x2SapUser->RecvHandoverRequest (params);
}
else // messageType == SuccessfulOutcome
@@ -224,6 +230,27 @@
m_x2SapUser->RecvHandoverRequestAck (params);
}
}
+ else // procedureCode == EpcX2Header::HandoverPreparation
+ {
+ if (messageType == EpcX2Header::InitiatingMessage)
+ {
+ NS_LOG_LOGIC ("Recv X2 message: UE CONTEXT RELEASE");
+
+ EpcX2UeContextReleaseHeader x2UeCtxReleaseHeader;
+ packet->RemoveHeader (x2UeCtxReleaseHeader);
+
+ NS_LOG_INFO ("X2 UeContextRelease header: " << x2UeCtxReleaseHeader);
+
+ EpcX2SapUser::UeContextReleaseParams params;
+ params.oldEnbUeX2apId = x2UeCtxReleaseHeader.GetOldEnbUeX2apId ();
+ params.newEnbUeX2apId = x2UeCtxReleaseHeader.GetNewEnbUeX2apId ();
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
+
+ m_x2SapUser->RecvUeContextRelease (params);
+ }
+ }
}
@@ -247,7 +274,12 @@
NS_LOG_LOGIC ("sourceSocket = " << sourceSocket);
NS_LOG_LOGIC ("targetIpAddr = " << targetIpAddr);
-
+
+ // Map oldEnbUeX2apId to sourceCellId
+ NS_ASSERT_MSG (m_x2Ues.find (params.oldEnbUeX2apId) == m_x2Ues.end (),
+ "UE already in CellId. enbUeX2apId = " << params.oldEnbUeX2apId << ". CellId = " << params.sourceCellId);
+ m_x2Ues [params.oldEnbUeX2apId] = params.sourceCellId;
+
NS_LOG_INFO ("Send X2 message: HANDOVER REQUEST");
// Build the X2 message
@@ -326,4 +358,52 @@
}
+void
+EpcX2::DoSendUeContextRelease (EpcX2SapProvider::UeContextReleaseParams params)
+{
+ NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
+
+ NS_ASSERT_MSG (m_x2Ues.find (params.oldEnbUeX2apId) != m_x2Ues.end (),
+ "Missing CellId for enbUeX2apId = " << params.oldEnbUeX2apId);
+ uint16_t sourceCellId = m_x2Ues [params.oldEnbUeX2apId];
+
+ NS_LOG_LOGIC ("sourceCellId = " << sourceCellId);
+
+ NS_ASSERT_MSG (m_x2InterfaceSockets.find (sourceCellId) != m_x2InterfaceSockets.end (),
+ "Socket infos not defined for sourceCellId = " << sourceCellId);
+
+ Ptr<Socket> localSocket = m_x2InterfaceSockets [sourceCellId]->m_localSocket;
+ Ipv4Address remoteIpAddr = m_x2InterfaceSockets [sourceCellId]->m_remoteIpAddr;
+
+ NS_LOG_LOGIC ("localSocket = " << localSocket);
+ NS_LOG_LOGIC ("remoteIpAddr = " << remoteIpAddr);
+
+ NS_LOG_INFO ("Send X2 message: UE CONTEXT RELEASE");
+
+ // Build the X2 message
+ EpcX2Header x2Header;
+ x2Header.SetMessageType (EpcX2Header::InitiatingMessage);
+ x2Header.SetProcedureCode (EpcX2Header::UeContextRelease);
+
+ EpcX2UeContextReleaseHeader x2UeCtxReleaseHeader;
+ x2UeCtxReleaseHeader.SetOldEnbUeX2apId (params.oldEnbUeX2apId);
+ x2UeCtxReleaseHeader.SetNewEnbUeX2apId (params.newEnbUeX2apId);
+
+ NS_LOG_INFO ("X2 header: " << x2Header);
+ NS_LOG_INFO ("X2 UeContextRelease header: " << x2UeCtxReleaseHeader);
+
+ // Build the X2 packet
+ Ptr<Packet> packet = Create <Packet> ();
+ packet->AddHeader (x2UeCtxReleaseHeader);
+ packet->AddHeader (x2Header);
+ NS_LOG_INFO ("packetLen = " << packet->GetSize ());
+
+ // Send the X2 message through the socket
+ localSocket->SendTo (packet, 0, InetSocketAddress (remoteIpAddr, m_x2cUdpPort));
+}
+
+
} // namespace ns3
--- a/src/lte/model/epc-x2.h Sat Sep 29 20:23:43 2012 +0200
+++ b/src/lte/model/epc-x2.h Mon Oct 08 23:22:57 2012 +0200
@@ -112,6 +112,7 @@
// Interface provided by LteRlcSapProvider
virtual void DoSendHandoverRequest (EpcX2SapProvider::HandoverRequestParams params);
virtual void DoSendHandoverRequestAck (EpcX2SapProvider::HandoverRequestAckParams params);
+ virtual void DoSendUeContextRelease (EpcX2SapProvider::UeContextReleaseParams params);
EpcX2SapUser* m_x2SapUser;
EpcX2SapProvider* m_x2SapProvider;
@@ -120,6 +121,11 @@
private:
/**
+ * Map the enbUeX2apId to the corresponding cellId where the UE is camping on
+ */
+ std::map < uint16_t, uint16_t > m_x2Ues;
+
+ /**
* Map the targetCellId to the corresponding (sourceSocket, remoteIpAddr) to be used
* to send the X2 message
*/