diff --git a/src/lte/helper/lte-helper.cc b/src/lte/helper/lte-helper.cc index 7938e8a85..8bd812c5a 100644 --- a/src/lte/helper/lte-helper.cc +++ b/src/lte/helper/lte-helper.cc @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -150,6 +151,12 @@ TypeId LteHelper::GetTypeId (void) StringValue (""), // fake module -> no fading MakeStringAccessor (&LteHelper::SetFadingModel), MakeStringChecker ()) + .AddAttribute ("UseIdealRrc", + "If true, LteRrcProtocolIdeal will be used for RRC signaling. " + "If false, LteRrcProtocolReal will be used.", + BooleanValue (true), + MakeBooleanAccessor (&LteHelper::m_useIdealRrc), + MakeBooleanChecker ()) ; return tid; } @@ -306,6 +313,10 @@ LteHelper::InstallUeDevice (NodeContainer c) Ptr LteHelper::InstallSingleEnbDevice (Ptr n) { + + NS_ABORT_MSG_IF (m_cellIdCounter == 65535, "max num eNBs exceeded"); + uint16_t cellId = ++m_cellIdCounter; + Ptr dlPhy = CreateObject (); Ptr ulPhy = CreateObject (); @@ -341,8 +352,23 @@ LteHelper::InstallSingleEnbDevice (Ptr n) Ptr mac = CreateObject (); Ptr sched = m_schedulerFactory.Create (); Ptr rrc = CreateObject (); - Ptr rrcProtocol = CreateObject (); - rrc->AggregateObject (rrcProtocol); + + if (m_useIdealRrc) + { + Ptr rrcProtocol = CreateObject (); + rrcProtocol->SetLteEnbRrcSapProvider (rrc->GetLteEnbRrcSapProvider ()); + rrc->SetLteEnbRrcSapUser (rrcProtocol->GetLteEnbRrcSapUser ()); + rrc->AggregateObject (rrcProtocol); + rrcProtocol->SetCellId (cellId); + } + else + { + Ptr rrcProtocol = CreateObject (); + rrcProtocol->SetLteEnbRrcSapProvider (rrc->GetLteEnbRrcSapProvider ()); + rrc->SetLteEnbRrcSapUser (rrcProtocol->GetLteEnbRrcSapUser ()); + rrc->AggregateObject (rrcProtocol); + rrcProtocol->SetCellId (cellId); + } if (m_epcHelper != 0) { @@ -355,10 +381,6 @@ LteHelper::InstallSingleEnbDevice (Ptr n) } } - // connect SAPs - rrcProtocol->SetLteEnbRrcSapProvider (rrc->GetLteEnbRrcSapProvider ()); - rrc->SetLteEnbRrcSapUser (rrcProtocol->GetLteEnbRrcSapUser ()); - rrc->SetLteEnbCmacSapProvider (mac->GetLteEnbCmacSapProvider ()); mac->SetLteEnbCmacSapUser (rrc->GetLteEnbCmacSapUser ()); rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ()); @@ -375,9 +397,6 @@ LteHelper::InstallSingleEnbDevice (Ptr n) phy->SetLteEnbCphySapUser (rrc->GetLteEnbCphySapUser ()); rrc->SetLteEnbCphySapProvider (phy->GetLteEnbCphySapProvider ()); - - NS_ABORT_MSG_IF (m_cellIdCounter == 65535, "max num eNBs exceeded"); - uint16_t cellId = ++m_cellIdCounter; Ptr dev = m_enbNetDeviceFactory.Create (); dev->SetNode (n); @@ -414,10 +433,7 @@ LteHelper::InstallSingleEnbDevice (Ptr n) } - dev->Start (); - - rrcProtocol->SetCellId (dev->GetCellId ()); - + dev->Start (); m_uplinkChannel->AddRx (ulPhy); @@ -476,9 +492,23 @@ LteHelper::InstallSingleUeDevice (Ptr n) Ptr mac = CreateObject (); Ptr rrc = CreateObject (); - Ptr rrcProtocol = CreateObject (); - rrc->AggregateObject (rrcProtocol); - rrcProtocol->SetUeRrc (rrc); + + if (m_useIdealRrc) + { + Ptr rrcProtocol = CreateObject (); + rrcProtocol->SetUeRrc (rrc); + rrc->AggregateObject (rrcProtocol); + rrcProtocol->SetLteUeRrcSapProvider (rrc->GetLteUeRrcSapProvider ()); + rrc->SetLteUeRrcSapUser (rrcProtocol->GetLteUeRrcSapUser ()); + } + else + { + Ptr rrcProtocol = CreateObject (); + rrcProtocol->SetUeRrc (rrc); + rrc->AggregateObject (rrcProtocol); + rrcProtocol->SetLteUeRrcSapProvider (rrc->GetLteUeRrcSapProvider ()); + rrc->SetLteUeRrcSapUser (rrcProtocol->GetLteUeRrcSapUser ()); + } if (m_epcHelper != 0) { @@ -486,13 +516,9 @@ LteHelper::InstallSingleUeDevice (Ptr n) } Ptr nas = CreateObject (); - // connect SAPs nas->SetAsSapProvider (rrc->GetAsSapProvider ()); rrc->SetAsSapUser (nas->GetAsSapUser ()); - rrcProtocol->SetLteUeRrcSapProvider (rrc->GetLteUeRrcSapProvider ()); - rrc->SetLteUeRrcSapUser (rrcProtocol->GetLteUeRrcSapUser ()); - rrc->SetLteUeCmacSapProvider (mac->GetLteUeCmacSapProvider ()); mac->SetLteUeCmacSapUser (rrc->GetLteUeCmacSapUser ()); rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ()); diff --git a/src/lte/helper/lte-helper.h b/src/lte/helper/lte-helper.h index 60c34e6af..4fbca4ba0 100644 --- a/src/lte/helper/lte-helper.h +++ b/src/lte/helper/lte-helper.h @@ -409,7 +409,7 @@ private: uint64_t m_imsiCounter; uint16_t m_cellIdCounter; - + bool m_useIdealRrc; }; diff --git a/src/lte/model/lte-rrc-protocol-real.cc b/src/lte/model/lte-rrc-protocol-real.cc new file mode 100644 index 000000000..fc754ed5c --- /dev/null +++ b/src/lte/model/lte-rrc-protocol-real.cc @@ -0,0 +1,687 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2012 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: Nicola Baldo + */ + +#include +#include +#include +#include +#include +#include + +#include "lte-rrc-protocol-real.h" +#include "lte-ue-rrc.h" +#include "lte-enb-rrc.h" +#include "lte-enb-net-device.h" +#include "lte-ue-net-device.h" + +NS_LOG_COMPONENT_DEFINE ("LteRrcProtocolReal"); + + +namespace ns3 { + + +const Time RRC_REAL_MSG_DELAY = MilliSeconds (0); + +NS_OBJECT_ENSURE_REGISTERED (LteUeRrcProtocolReal); + +LteUeRrcProtocolReal::LteUeRrcProtocolReal () + : m_ueRrcSapProvider (0), + m_enbRrcSapProvider (0) +{ + m_ueRrcSapUser = new MemberLteUeRrcSapUser (this); +} + +LteUeRrcProtocolReal::~LteUeRrcProtocolReal () +{ +} + +void +LteUeRrcProtocolReal::DoDispose () +{ + NS_LOG_FUNCTION (this); + delete m_ueRrcSapUser; + m_rrc = 0; +} + +TypeId +LteUeRrcProtocolReal::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::LteUeRrcProtocolReal") + .SetParent () + .AddConstructor () + ; + return tid; +} + +void +LteUeRrcProtocolReal::SetLteUeRrcSapProvider (LteUeRrcSapProvider* p) +{ + m_ueRrcSapProvider = p; +} + +LteUeRrcSapUser* +LteUeRrcProtocolReal::GetLteUeRrcSapUser () +{ + return m_ueRrcSapUser; +} + +void +LteUeRrcProtocolReal::SetUeRrc (Ptr rrc) +{ + m_rrc = rrc; +} + +void +LteUeRrcProtocolReal::DoSetup (LteUeRrcSapUser::SetupParameters params) +{ + NS_LOG_FUNCTION (this); + // Trick: we use this as a trigger to initialize the RNTI and cellID, + // and to make sure we are talking to the appropriate eNB (e.g., + // after handover). We don't care about SRB0/SRB1 since we use real + // RRC messages. + DoReestablish (); +} + +void +LteUeRrcProtocolReal::DoReestablish () +{ + NS_LOG_FUNCTION (this); + // // initialize the RNTI and get the EnbLteRrcSapProvider for the + // // eNB we are currently attached to + // m_rnti = m_rrc->GetRnti (); + // SetEnbRrcSapProvider (); + + + // if (m_havePendingRrcConnectionRequest == true) + // { + // Simulator::Schedule (RRC_REAL_MSG_DELAY, + // &LteEnbRrcSapProvider::RecvRrcConnectionRequest, + // m_enbRrcSapProvider, + // m_rnti, + // m_pendingRrcConnectionRequest); + // } +} + +void +LteUeRrcProtocolReal::DoSendRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg) +{ + // initialize the RNTI and get the EnbLteRrcSapProvider for the + // eNB we are currently attached to + m_rnti = m_rrc->GetRnti (); + SetEnbRrcSapProvider (); + + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteEnbRrcSapProvider::RecvRrcConnectionRequest, + m_enbRrcSapProvider, + m_rnti, + msg); +} + +void +LteUeRrcProtocolReal::DoSendRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg) +{ + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteEnbRrcSapProvider::RecvRrcConnectionSetupCompleted, + m_enbRrcSapProvider, + m_rnti, + msg); +} + +void +LteUeRrcProtocolReal::DoSendRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg) +{ + // re-initialize the RNTI and get the EnbLteRrcSapProvider for the + // eNB we are currently attached to + m_rnti = m_rrc->GetRnti (); + SetEnbRrcSapProvider (); + + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteEnbRrcSapProvider::RecvRrcConnectionReconfigurationCompleted, + m_enbRrcSapProvider, + m_rnti, + msg); +} + +void +LteUeRrcProtocolReal::DoSendRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg) +{ + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteEnbRrcSapProvider::RecvRrcConnectionReestablishmentRequest, + m_enbRrcSapProvider, + m_rnti, + msg); +} + +void +LteUeRrcProtocolReal::DoSendRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg) +{ + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteEnbRrcSapProvider::RecvRrcConnectionReestablishmentComplete, + m_enbRrcSapProvider, + m_rnti, +msg); +} + + +void +LteUeRrcProtocolReal::SetEnbRrcSapProvider () +{ + uint16_t cellId = m_rrc->GetCellId (); + + // walk list of all nodes to get the peer eNB + Ptr enbDev; + NodeList::Iterator listEnd = NodeList::End (); + bool found = false; + for (NodeList::Iterator i = NodeList::Begin (); + (i != listEnd) && (!found); + ++i) + { + Ptr node = *i; + int nDevs = node->GetNDevices (); + for (int j = 0; + (j < nDevs) && (!found); + j++) + { + enbDev = node->GetDevice (j)->GetObject (); + if (enbDev == 0) + { + continue; + } + else + { + if (enbDev->GetCellId () == cellId) + { + found = true; + break; + } + } + } + } + NS_ASSERT_MSG (found, " Unable to find eNB with CellId =" << cellId); + m_enbRrcSapProvider = enbDev->GetRrc ()->GetLteEnbRrcSapProvider (); + Ptr enbRrcProtocolReal = enbDev->GetRrc ()->GetObject (); + enbRrcProtocolReal->SetUeRrcSapProvider (m_rnti, m_ueRrcSapProvider); +} + + +NS_OBJECT_ENSURE_REGISTERED (LteEnbRrcProtocolReal); + +LteEnbRrcProtocolReal::LteEnbRrcProtocolReal () + : m_enbRrcSapProvider (0) +{ + NS_LOG_FUNCTION (this); + m_enbRrcSapUser = new MemberLteEnbRrcSapUser (this); +} + +LteEnbRrcProtocolReal::~LteEnbRrcProtocolReal () +{ + NS_LOG_FUNCTION (this); +} + +void +LteEnbRrcProtocolReal::DoDispose () +{ + NS_LOG_FUNCTION (this); + delete m_enbRrcSapUser; +} + +TypeId +LteEnbRrcProtocolReal::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::LteEnbRrcProtocolReal") + .SetParent () + .AddConstructor () + ; + return tid; +} + +void +LteEnbRrcProtocolReal::SetLteEnbRrcSapProvider (LteEnbRrcSapProvider* p) +{ + m_enbRrcSapProvider = p; +} + +LteEnbRrcSapUser* +LteEnbRrcProtocolReal::GetLteEnbRrcSapUser () +{ + return m_enbRrcSapUser; +} + +void +LteEnbRrcProtocolReal::SetCellId (uint16_t cellId) +{ + m_cellId = cellId; +} + +LteUeRrcSapProvider* +LteEnbRrcProtocolReal::GetUeRrcSapProvider (uint16_t rnti) +{ + std::map::const_iterator it; + it = m_enbRrcSapProviderMap.find (rnti); + NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "could not find RNTI = " << rnti); + return it->second; +} + +void +LteEnbRrcProtocolReal::SetUeRrcSapProvider (uint16_t rnti, LteUeRrcSapProvider* p) +{ + std::map::iterator it; + it = m_enbRrcSapProviderMap.find (rnti); + NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "could not find RNTI = " << rnti); + it->second = p; +} + +void +LteEnbRrcProtocolReal::DoSetupUe (uint16_t rnti, LteEnbRrcSapUser::SetupUeParameters params) +{ + NS_LOG_FUNCTION (this << rnti); + + // // walk list of all nodes to get the peer UE RRC SAP Provider + // Ptr ueRrc; + // NodeList::Iterator listEnd = NodeList::End (); + // bool found = false; + // for (NodeList::Iterator i = NodeList::Begin (); (i != listEnd) && (found == false); i++) + // { + // Ptr node = *i; + // int nDevs = node->GetNDevices (); + // for (int j = 0; j < nDevs; j++) + // { + // Ptr ueDev = node->GetDevice (j)->GetObject (); + // if (!ueDev) + // { + // continue; + // } + // else + // { + // ueRrc = ueDev->GetRrc (); + // if ((ueRrc->GetRnti () == rnti) && (ueRrc->GetCellId () == m_cellId)) + // { + // found = true; + // break; + // } + // } + // } + // } + // NS_ASSERT_MSG (found , " Unable to find UE with RNTI=" << rnti << " cellId=" << m_cellId); + // m_enbRrcSapProviderMap[rnti] = ueRrc->GetLteUeRrcSapProvider (); + + + // just create empty entry, the UeRrcSapProvider will be set by the + // ue upon connection request or connection reconfiguration + // completed + m_enbRrcSapProviderMap[rnti] = 0; + +} + +void +LteEnbRrcProtocolReal::DoRemoveUe (uint16_t rnti) +{ + NS_LOG_FUNCTION (this << rnti); + m_enbRrcSapProviderMap.erase (rnti); +} + +void +LteEnbRrcProtocolReal::DoSendMasterInformationBlock (LteRrcSap::MasterInformationBlock msg) +{ + NS_LOG_FUNCTION (this); + for (std::map::const_iterator it = m_enbRrcSapProviderMap.begin (); + it != m_enbRrcSapProviderMap.end (); + ++it) + { + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteUeRrcSapProvider::RecvMasterInformationBlock, + it->second, + msg); + } +} + +void +LteEnbRrcProtocolReal::DoSendSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg) +{ + NS_LOG_FUNCTION (this << m_cellId); + // walk list of all nodes to get UEs with this cellId + Ptr ueRrc; + for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i) + { + Ptr node = *i; + int nDevs = node->GetNDevices (); + for (int j = 0; j < nDevs; ++j) + { + Ptr ueDev = node->GetDevice (j)->GetObject (); + if (ueDev != 0) + { + NS_LOG_LOGIC ("considering UE " << ueDev->GetImsi ()); + Ptr ueRrc = ueDev->GetRrc (); + if (ueRrc->GetCellId () == m_cellId) + { + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteUeRrcSapProvider::RecvSystemInformationBlockType1, + ueRrc->GetLteUeRrcSapProvider (), + msg); + } + } + } + } +} + +void +LteEnbRrcProtocolReal::DoSendSystemInformation (LteRrcSap::SystemInformation msg) +{ + NS_LOG_FUNCTION (this << m_cellId); + // walk list of all nodes to get UEs with this cellId + Ptr ueRrc; + for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i) + { + Ptr node = *i; + int nDevs = node->GetNDevices (); + for (int j = 0; j < nDevs; ++j) + { + Ptr ueDev = node->GetDevice (j)->GetObject (); + if (ueDev != 0) + { + Ptr ueRrc = ueDev->GetRrc (); + NS_LOG_LOGIC ("considering UE IMSI " << ueDev->GetImsi () << " that has cellId " << ueRrc->GetCellId ()); + if (ueRrc->GetCellId () == m_cellId) + { + NS_LOG_LOGIC ("sending SI to IMSI " << ueDev->GetImsi ()); + ueRrc->GetLteUeRrcSapProvider ()->RecvSystemInformation (msg); + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteUeRrcSapProvider::RecvSystemInformation, + ueRrc->GetLteUeRrcSapProvider (), + msg); + } + } + } + } +} + +void +LteEnbRrcProtocolReal::DoSendRrcConnectionSetup (uint16_t rnti, LteRrcSap::RrcConnectionSetup msg) +{ + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteUeRrcSapProvider::RecvRrcConnectionSetup, + GetUeRrcSapProvider (rnti), + msg); +} + +void +LteEnbRrcProtocolReal::DoSendRrcConnectionReconfiguration (uint16_t rnti, LteRrcSap::RrcConnectionReconfiguration msg) +{ + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteUeRrcSapProvider::RecvRrcConnectionReconfiguration, + GetUeRrcSapProvider (rnti), + msg); +} + +void +LteEnbRrcProtocolReal::DoSendRrcConnectionReestablishment (uint16_t rnti, LteRrcSap::RrcConnectionReestablishment msg) +{ + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteUeRrcSapProvider::RecvRrcConnectionReestablishment, + GetUeRrcSapProvider (rnti), + msg); +} + +void +LteEnbRrcProtocolReal::DoSendRrcConnectionReestablishmentReject (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentReject msg) +{ + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteUeRrcSapProvider::RecvRrcConnectionReestablishmentReject, + GetUeRrcSapProvider (rnti), + msg); +} + +void +LteEnbRrcProtocolReal::DoSendRrcConnectionRelease (uint16_t rnti, LteRrcSap::RrcConnectionRelease msg) +{ + Simulator::Schedule (RRC_REAL_MSG_DELAY, + &LteUeRrcSapProvider::RecvRrcConnectionRelease, + GetUeRrcSapProvider (rnti), + msg); +} + + +/* + * The purpose of LteEnbRrcProtocolReal is to avoid encoding + * messages. In order to do so, we need to have some form of encoding for + * inter-node RRC messages like HandoverPreparationInfo and HandoverCommand. Doing so + * directly is not practical (these messages includes a lot of + * information elements, so encoding all of them would defeat the + * purpose of LteEnbRrcProtocolReal. The workaround is to store the + * actual message in a global map, so that then we can just encode the + * key in a header and send that between eNBs over X2. + * + */ + +std::map g_handoverPreparationInfoMsgMap2; +uint32_t g_handoverPreparationInfoMsgIdCounter2 = 0; + +/* + * This header encodes the map key discussed above. We keep this + * private since it should not be used outside this file. + * + */ +class RealHandoverPreparationInfoHeader : public Header +{ +public: + uint32_t GetMsgId (); + void SetMsgId (uint32_t id); + 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: + uint32_t m_msgId; +}; + +uint32_t +RealHandoverPreparationInfoHeader::GetMsgId () +{ + return m_msgId; +} + +void +RealHandoverPreparationInfoHeader::SetMsgId (uint32_t id) +{ + m_msgId = id; +} + + +TypeId +RealHandoverPreparationInfoHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RealHandoverPreparationInfoHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} + +TypeId +RealHandoverPreparationInfoHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +void RealHandoverPreparationInfoHeader::Print (std::ostream &os) const +{ + os << " msgId=" << m_msgId; +} + +uint32_t RealHandoverPreparationInfoHeader::GetSerializedSize (void) const +{ + return 4; +} + +void RealHandoverPreparationInfoHeader::Serialize (Buffer::Iterator start) const +{ + start.WriteU32 (m_msgId); +} + +uint32_t RealHandoverPreparationInfoHeader::Deserialize (Buffer::Iterator start) +{ + m_msgId = start.ReadU32 (); + return GetSerializedSize (); +} + + + +Ptr +LteEnbRrcProtocolReal::DoEncodeHandoverPreparationInformation (LteRrcSap::HandoverPreparationInfo msg) +{ + uint32_t msgId = ++g_handoverPreparationInfoMsgIdCounter2; + NS_ASSERT_MSG (g_handoverPreparationInfoMsgMap2.find (msgId) == g_handoverPreparationInfoMsgMap2.end (), "msgId " << msgId << " already in use"); + NS_LOG_INFO (" encoding msgId = " << msgId); + g_handoverPreparationInfoMsgMap2.insert (std::pair (msgId, msg)); + RealHandoverPreparationInfoHeader h; + h.SetMsgId (msgId); + Ptr p = Create (); + p->AddHeader (h); + return p; +} + +LteRrcSap::HandoverPreparationInfo +LteEnbRrcProtocolReal::DoDecodeHandoverPreparationInformation (Ptr p) +{ + RealHandoverPreparationInfoHeader h; + p->RemoveHeader (h); + uint32_t msgId = h.GetMsgId (); + NS_LOG_INFO (" decoding msgId = " << msgId); + std::map::iterator it = g_handoverPreparationInfoMsgMap2.find (msgId); + NS_ASSERT_MSG (it != g_handoverPreparationInfoMsgMap2.end (), "msgId " << msgId << " not found"); + LteRrcSap::HandoverPreparationInfo msg = it->second; + g_handoverPreparationInfoMsgMap2.erase (it); + return msg; +} + + + +std::map g_handoverCommandMsgMap2; +uint32_t g_handoverCommandMsgIdCounter2 = 0; + +/* + * This header encodes the map key discussed above. We keep this + * private since it should not be used outside this file. + * + */ +class RealHandoverCommandHeader : public Header +{ +public: + uint32_t GetMsgId (); + void SetMsgId (uint32_t id); + 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: + uint32_t m_msgId; +}; + +uint32_t +RealHandoverCommandHeader::GetMsgId () +{ + return m_msgId; +} + +void +RealHandoverCommandHeader::SetMsgId (uint32_t id) +{ + m_msgId = id; +} + + +TypeId +RealHandoverCommandHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RealHandoverCommandHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} + +TypeId +RealHandoverCommandHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +void RealHandoverCommandHeader::Print (std::ostream &os) const +{ + os << " msgId=" << m_msgId; +} + +uint32_t RealHandoverCommandHeader::GetSerializedSize (void) const +{ + return 4; +} + +void RealHandoverCommandHeader::Serialize (Buffer::Iterator start) const +{ + start.WriteU32 (m_msgId); +} + +uint32_t RealHandoverCommandHeader::Deserialize (Buffer::Iterator start) +{ + m_msgId = start.ReadU32 (); + return GetSerializedSize (); +} + + + +Ptr +LteEnbRrcProtocolReal::DoEncodeHandoverCommand (LteRrcSap::RrcConnectionReconfiguration msg) +{ + uint32_t msgId = ++g_handoverCommandMsgIdCounter2; + NS_ASSERT_MSG (g_handoverCommandMsgMap2.find (msgId) == g_handoverCommandMsgMap2.end (), "msgId " << msgId << " already in use"); + NS_LOG_INFO (" encoding msgId = " << msgId); + g_handoverCommandMsgMap2.insert (std::pair (msgId, msg)); + RealHandoverCommandHeader h; + h.SetMsgId (msgId); + Ptr p = Create (); + p->AddHeader (h); + return p; +} + +LteRrcSap::RrcConnectionReconfiguration +LteEnbRrcProtocolReal::DoDecodeHandoverCommand (Ptr p) +{ + RealHandoverCommandHeader h; + p->RemoveHeader (h); + uint32_t msgId = h.GetMsgId (); + NS_LOG_INFO (" decoding msgId = " << msgId); + std::map::iterator it = g_handoverCommandMsgMap2.find (msgId); + NS_ASSERT_MSG (it != g_handoverCommandMsgMap2.end (), "msgId " << msgId << " not found"); + LteRrcSap::RrcConnectionReconfiguration msg = it->second; + g_handoverCommandMsgMap2.erase (it); + return msg; +} + + + + + +} // namespace ns3 diff --git a/src/lte/model/lte-rrc-protocol-real.h b/src/lte/model/lte-rrc-protocol-real.h new file mode 100644 index 000000000..32a3297f6 --- /dev/null +++ b/src/lte/model/lte-rrc-protocol-real.h @@ -0,0 +1,149 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2012 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: Nicola Baldo + */ + + +#ifndef LTE_RRC_PROTOCOL_REAL_H +#define LTE_RRC_PROTOCOL_REAL_H + +#include +#include + +#include +#include +#include + +namespace ns3 { + +class LteUeRrcSapProvider; +class LteUeRrcSapUser; +class LteEnbRrcSapProvider; +class LteUeRrc; + + +/** + * Models the transmission of RRC messages from the UE to the eNB in + * a real fashion, by creating real RRC PDUs and transmitting them + * over Signaling Radio Bearers using radio resources allocated by the + * LTE MAC scheduler. + * + */ +class LteUeRrcProtocolReal : public Object +{ + friend class MemberLteUeRrcSapUser; + +public: + + LteUeRrcProtocolReal (); + virtual ~LteUeRrcProtocolReal (); + + // inherited from Object + virtual void DoDispose (void); + static TypeId GetTypeId (void); + + void SetLteUeRrcSapProvider (LteUeRrcSapProvider* p); + LteUeRrcSapUser* GetLteUeRrcSapUser (); + + void SetUeRrc (Ptr rrc); + + +private: + + // methods forwarded from LteUeRrcSapUser + void DoSetup (LteUeRrcSapUser::SetupParameters params); + void DoReestablish (); + void DoSendRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg); + void DoSendRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg); + void DoSendRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg); + void DoSendRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg); + void DoSendRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg); + + void SetEnbRrcSapProvider (); + + Ptr m_rrc; + uint16_t m_rnti; + LteUeRrcSapProvider* m_ueRrcSapProvider; + LteUeRrcSapUser* m_ueRrcSapUser; + LteEnbRrcSapProvider* m_enbRrcSapProvider; + +}; + + +/** + * Models the transmission of RRC messages from the UE to the eNB in + * a real fashion, by creating real RRC PDUs and transmitting them + * over Signaling Radio Bearers using radio resources allocated by the + * LTE MAC scheduler. + * + */ +class LteEnbRrcProtocolReal : public Object +{ + friend class MemberLteEnbRrcSapUser; + +public: + + LteEnbRrcProtocolReal (); + virtual ~LteEnbRrcProtocolReal (); + + // inherited from Object + virtual void DoDispose (void); + static TypeId GetTypeId (void); + + void SetLteEnbRrcSapProvider (LteEnbRrcSapProvider* p); + LteEnbRrcSapUser* GetLteEnbRrcSapUser (); + + void SetCellId (uint16_t cellId); + + LteUeRrcSapProvider* GetUeRrcSapProvider (uint16_t rnti); + void SetUeRrcSapProvider (uint16_t rnti, LteUeRrcSapProvider* p); + +private: + + // methods forwarded from LteEnbRrcSapUser + void DoSetupUe (uint16_t rnti, LteEnbRrcSapUser::SetupUeParameters params); + void DoRemoveUe (uint16_t rnti); + void DoSendMasterInformationBlock (LteRrcSap::MasterInformationBlock msg); + void DoSendSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg); + void DoSendSystemInformation (LteRrcSap::SystemInformation msg); + void SendSystemInformation (LteRrcSap::SystemInformation msg); + void DoSendRrcConnectionSetup (uint16_t rnti, LteRrcSap::RrcConnectionSetup msg); + void DoSendRrcConnectionReconfiguration (uint16_t rnti, LteRrcSap::RrcConnectionReconfiguration msg); + void DoSendRrcConnectionReestablishment (uint16_t rnti, LteRrcSap::RrcConnectionReestablishment msg); + void DoSendRrcConnectionReestablishmentReject (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentReject msg); + void DoSendRrcConnectionRelease (uint16_t rnti, LteRrcSap::RrcConnectionRelease msg); + Ptr DoEncodeHandoverPreparationInformation (LteRrcSap::HandoverPreparationInfo msg); + LteRrcSap::HandoverPreparationInfo DoDecodeHandoverPreparationInformation (Ptr p); + Ptr DoEncodeHandoverCommand (LteRrcSap::RrcConnectionReconfiguration msg); + LteRrcSap::RrcConnectionReconfiguration DoDecodeHandoverCommand (Ptr p); + + + uint16_t m_rnti; + uint16_t m_cellId; + LteEnbRrcSapProvider* m_enbRrcSapProvider; + LteEnbRrcSapUser* m_enbRrcSapUser; + std::map m_enbRrcSapProviderMap; + +}; + + + +} + + +#endif // LTE_RRC_PROTOCOL_REAL_H diff --git a/src/lte/test/test-lte-rrc.cc b/src/lte/test/test-lte-rrc.cc index 55404a308..c7111f4bf 100644 --- a/src/lte/test/test-lte-rrc.cc +++ b/src/lte/test/test-lte-rrc.cc @@ -42,10 +42,10 @@ public: * \param delayDiscStart expected duration to perform connection establishment in ms * */ - LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart); + LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart, bool useIdealRrc); private: - static std::string BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart); + static std::string BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart, bool useIdealRrc); virtual void DoRun (void); void Connect (Ptr ueDevice, Ptr enbDevice); void CheckConnected (Ptr ueDevice, Ptr enbDevice); @@ -58,12 +58,13 @@ private: uint32_t m_delayConnEnd; // expected duration to perform connection establishment in ms uint32_t m_delayDiscStart; // delay between connection completed and disconnection request in ms uint32_t m_delayDiscEnd; // expected duration to complete disconnection in ms + bool m_useIdealRrc; Ptr m_lteHelper; }; -std::string LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart) +std::string LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart, bool useIdealRrc) { std::ostringstream oss; oss << "nUes=" << nUes @@ -71,10 +72,18 @@ std::string LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUe << ", tConnBase=" << tConnBase << ", tConnIncrPerUe=" << tConnIncrPerUe << ", delayDiscStart=" << delayDiscStart; + if (useIdealRrc) + { + oss << ", ideal RRC"; + } + else + { + oss << ", real RRC"; + } return oss.str (); } -LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart) +LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart, bool useIdealRrc) : TestCase ("RRC connection establishment"), m_nUes (nUes), m_nBearers (nBearers), @@ -82,7 +91,8 @@ LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (ui m_tConnIncrPerUe (tConnIncrPerUe), m_delayConnEnd (150), // includes: time to receive system information, time for Random Access (RACH preamble, RAR response), time to send and receive RRC connection request+setup+completed. Value should be slightly higher than T300 in TS 36.331 m_delayDiscStart (delayDiscStart), - m_delayDiscEnd (10) + m_delayDiscEnd (10), + m_useIdealRrc (useIdealRrc) { } @@ -92,6 +102,7 @@ LteRrcConnectionEstablishmentTestCase::DoRun () // normal code m_lteHelper = CreateObject (); + m_lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_useIdealRrc)); NodeContainer enbNodes; enbNodes.Create (1); @@ -241,36 +252,37 @@ LteRrcTestSuite::LteRrcTestSuite () : TestSuite ("lte-rrc", SYSTEM) { NS_LOG_FUNCTION (this); + for (uint32_t useIdealRrc = 0; useIdealRrc <= 1; ++useIdealRrc) + { + // <----- all times in ms -----------------> + // nUes, nBearers, tConnBase, tConnIncrPerUe, delayDiscStart, useIdealRrc + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 0, 0, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 0, 100, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 1, 0, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 1, 100, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 2, 0, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 2, 100, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 0, 20, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 0, 20, 10, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 0, 20, 100, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 1, 20, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 1, 20, 10, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 1, 20, 100, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 2, 20, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 2, 20, 10, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 2, 20, 100, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 3, 0, 20, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 4, 0, 20, 0, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 4, 0, 20, 300, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 20, 0, 10, 1, 1, useIdealRrc)); + AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 50, 0, 10, 0, 1, useIdealRrc)); - // <----- all times in ms -----------------> - // nUes, nBearers, tConnBase, tConnIncrPerUe, delayDiscStart - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 0, 0, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 0, 100, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 1, 0, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 1, 100, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 2, 0, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 2, 100, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 0, 20, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 0, 20, 10, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 0, 20, 100, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 1, 20, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 1, 20, 10, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 1, 20, 100, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 2, 20, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 2, 20, 10, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 2, 20, 100, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 3, 0, 20, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 4, 0, 20, 0, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 4, 0, 20, 300, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 20, 0, 10, 1, 1)); - AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 50, 0, 10, 0, 1)); - - // // time consuming tests with a lot of UEs - // AddTestCase (new LteRrcConnectionEstablishmentTestCase (100, 0, 10, 0, 1)); - // AddTestCase (new LteRrcConnectionEstablishmentTestCase (100, 0, 10, 1, 1)); - // AddTestCase (new LteRrcConnectionEstablishmentTestCase (200, 0, 10, 0, 1)); - // AddTestCase (new LteRrcConnectionEstablishmentTestCase (200, 0, 10, 1, 1)); - + // // time consuming tests with a lot of UEs + // AddTestCase (new LteRrcConnectionEstablishmentTestCase (100, 0, 10, 0, 1)); + // AddTestCase (new LteRrcConnectionEstablishmentTestCase (100, 0, 10, 1, 1)); + // AddTestCase (new LteRrcConnectionEstablishmentTestCase (200, 0, 10, 0, 1)); + // AddTestCase (new LteRrcConnectionEstablishmentTestCase (200, 0, 10, 1, 1)); + } } static LteRrcTestSuite g_lteRrcTestSuiteInstance; diff --git a/src/lte/wscript b/src/lte/wscript index 1d3d6ae74..56b16e15f 100644 --- a/src/lte/wscript +++ b/src/lte/wscript @@ -16,6 +16,7 @@ def build(bld): 'model/lte-ue-rrc.cc', 'model/lte-rrc-sap.cc', 'model/lte-rrc-protocol-ideal.cc', + 'model/lte-rrc-protocol-real.cc', 'model/lte-rlc-sap.cc', 'model/lte-rlc.cc', 'model/lte-rlc-sequence-number.cc', @@ -135,6 +136,7 @@ def build(bld): 'model/lte-ue-rrc.h', 'model/lte-rrc-sap.h', 'model/lte-rrc-protocol-ideal.h', + 'model/lte-rrc-protocol-real.h', 'model/lte-rlc-sap.h', 'model/lte-rlc.h', 'model/lte-rlc-header.h',