--- a/src/lte/doc/source/lte-design.rst Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/doc/source/lte-design.rst Tue Oct 30 16:02:07 2012 +0100
@@ -1071,6 +1071,16 @@
+ handover
+Radio Bearer Configuration
+--------------------------
+
+Some implementation choices have been made in the RRC regarding the setup of radio bearers:
+
+ - three Logical Channel Groups (out of four available) are used, according to the following policy:
+ + LCG 0 is for signaling radio bearers
+ + LCG 1 is for GBR data radio bearers
+ + LCG 2 is for Non-GBR data radio bearers
+
RRC connection establishment
----------------------------
--- a/src/lte/doc/source/lte-user.rst Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/doc/source/lte-user.rst Tue Oct 30 16:02:07 2012 +0100
@@ -48,10 +48,10 @@
#. Initial boilerplate::
- #include "ns3/core-module.h"
- #include "ns3/network-module.h"
- #include "ns3/mobility-module.h"
- #include "ns3/lte-module.h"
+ #include <ns3/core-module.h>
+ #include <ns3/network-module.h>
+ #include <ns3/mobility-module.h>
+ #include <ns3/lte-module.h>
using namespace ns3;
@@ -106,14 +106,13 @@
lteHelper->Attach (ueDevs, enbDevs.Get (0));
-#. Activate an EPS Bearer including the setup of the Radio Bearer between an eNB and its attached UE::
+#. Activate a data radio bearer between each UE and the eNB it is attached to::
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
EpsBearer bearer (q);
- lteHelper->ActivateEpsBearer (ueDevs, bearer);
+ lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
- In the current version of the ns-3 LTE model, the activation of an
- EPS Bearer will also activate two saturation traffic generators for
+ this method will also activate two saturation traffic generators for
that bearer, one in uplink and one in downlink.
#. Set the stop time::
@@ -707,10 +706,24 @@
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
}
-The activation of bearers is done exactly in the same way as for an
-LTE-only simulation. Here is how to activate a default bearer::
+The activation of bearers is done in a slightly different way with
+respect to what done for an LTE-only simulation. First, the method
+ActivateDataRadioBearer is not to be used when the EPC is
+used. Second, when EPC is used, the default EPS bearer will be
+activated automatically when you call LteHelper::Attach (). Third, if
+you want to setup dedicated EPS bearer, you can do so using the method
+LteHelper::ActivateDedicatedEpsBearer (). This method takes as a
+parameter the Traffic Flow Template (TFT), which is a struct that
+identifies the type of traffic that will be mapped to the dedicated
+EPS bearer. Here is an example for how to setup a dedicated bearer
+for an application at the UE communicating on port 1234::
- lteHelper->ActivateEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
+ Ptr<EpcTft> tft = Create<EpcTft> ();
+ EpcTft::PacketFilter pf;
+ pf.localPortStart = 1234;
+ pf.localPortEnd = 1234;
+ tft->Add (pf);
+ lteHelper->ActivateEpsBearer (ueLteDevs, EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), pf);
you can of course use custom EpsBearer and EpcTft configurations,
please refer to the doxygen documentation for how to do it.
--- a/src/lte/helper/lte-helper.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/helper/lte-helper.cc Tue Oct 30 16:02:07 2012 +0100
@@ -36,7 +36,7 @@
#include <ns3/lte-ue-phy.h>
#include <ns3/lte-spectrum-phy.h>
#include <ns3/lte-sinr-chunk-processor.h>
-#include <ns3/single-model-spectrum-channel.h>
+#include <ns3/multi-model-spectrum-channel.h>
#include <ns3/friis-spectrum-propagation-loss.h>
#include <ns3/isotropic-antenna-model.h>
#include <ns3/lte-enb-net-device.h>
@@ -46,6 +46,7 @@
#include <ns3/lte-rlc-um.h>
#include <ns3/lte-rlc-am.h>
#include <ns3/epc-enb-s1-sap.h>
+#include <ns3/lte-rrc-protocol-ideal.h>
#include <ns3/epc-helper.h>
#include <iostream>
@@ -65,7 +66,7 @@
m_enbNetDeviceFactory.SetTypeId (LteEnbNetDevice::GetTypeId ());
m_enbAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ());
m_ueAntennaModelFactory.SetTypeId (IsotropicAntennaModel::GetTypeId ());
- m_channelFactory.SetTypeId (SingleModelSpectrumChannel::GetTypeId ());
+ m_channelFactory.SetTypeId (MultiModelSpectrumChannel::GetTypeId ());
}
void
@@ -330,6 +331,8 @@
Ptr<LteEnbMac> mac = CreateObject<LteEnbMac> ();
Ptr<FfMacScheduler> sched = m_schedulerFactory.Create<FfMacScheduler> ();
Ptr<LteEnbRrc> rrc = CreateObject<LteEnbRrc> ();
+ Ptr<LteEnbRrcProtocolIdeal> rrcProtocol = CreateObject<LteEnbRrcProtocolIdeal> ();
+ rrc->AggregateObject (rrcProtocol);
if (m_epcHelper != 0)
{
@@ -343,6 +346,9 @@
}
// connect SAPs
+ rrcProtocol->SetLteEnbRrcSapProvider (rrc->GetLteEnbRrcSapProvider ());
+ rrc->SetLteEnbRrcSapUser (rrcProtocol->GetLteEnbRrcSapUser ());
+
rrc->SetLteEnbCmacSapProvider (mac->GetLteEnbCmacSapProvider ());
mac->SetLteEnbCmacSapUser (rrc->GetLteEnbCmacSapUser ());
rrc->SetLteMacSapProvider (mac->GetLteMacSapProvider ());
@@ -395,6 +401,9 @@
dev->Start ();
+ rrcProtocol->SetCellId (dev->GetCellId ());
+
+
m_uplinkChannel->AddRx (ulPhy);
if (m_epcHelper != 0)
@@ -447,6 +456,14 @@
Ptr<LteUeMac> mac = CreateObject<LteUeMac> ();
Ptr<LteUeRrc> rrc = CreateObject<LteUeRrc> ();
+ Ptr<LteUeRrcProtocolIdeal> rrcProtocol = CreateObject<LteUeRrcProtocolIdeal> ();
+ rrc->AggregateObject (rrcProtocol);
+ rrcProtocol->SetUeRrc (rrc);
+
+ if (m_epcHelper != 0)
+ {
+ rrc->SetUseRlcSm (false);
+ }
Ptr<EpcUeNas> nas = CreateObject<EpcUeNas> ();
nas->SetEpcHelper (m_epcHelper);
@@ -455,6 +472,9 @@
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 ());
@@ -476,7 +496,6 @@
dlPhy->SetLtePhyRxCtrlEndOkCallback (MakeCallback (&LteUePhy::ReceiveLteControlMessageList, phy));
nas->SetForwardUpCallback (MakeCallback (&LteUeNetDevice::Receive, dev));
-
dev->Start ();
return dev;
@@ -503,8 +522,6 @@
Ptr<EpcUeNas> ueNas = ueLteDevice->GetNas ();
ueNas->Connect (enbDevice);
- m_downlinkChannel->AddRx (ueLteDevice->GetPhy ()->GetDownlinkSpectrumPhy ());
-
// tricks needed for the simplified LTE-only simulations
if (m_epcHelper == 0)
{
@@ -570,14 +587,39 @@
LteHelper::ActivateDataRadioBearer (Ptr<NetDevice> ueDevice, EpsBearer bearer)
{
NS_LOG_FUNCTION (this << ueDevice);
- NS_ASSERT_MSG (m_epcHelper == 0, "this method must not be used when EPC is being used");
- Ptr<LteEnbNetDevice> enbDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
- Ptr<LteEnbRrc> enbRrc = enbDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
- EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params;
- params.rnti = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ()->GetRnti();
- params.bearer = bearer;
- params.teid = 0; // don't care
- enbRrc->GetS1SapUser ()->DataRadioBearerSetupRequest (params);
+ NS_ASSERT_MSG (m_epcHelper == 0, "this method must not be used when EPC is being used");
+
+ /*
+ * Note: this method is kind of a hack, just because running
+ * simulations without the EPC is kind of a hack.
+ */
+
+ Ptr<LteUeRrc> ueRrc = ueDevice->GetObject<LteUeNetDevice> ()->GetRrc ();
+ bool done = false;
+ if (ueRrc->GetState () == LteUeRrc::CONNECTED_NORMALLY)
+ {
+ uint16_t rnti = ueRrc->GetRnti();
+ Ptr<LteEnbNetDevice> enbLteDevice = ueDevice->GetObject<LteUeNetDevice> ()->GetTargetEnb ();
+ Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetObject<LteEnbNetDevice> ()->GetRrc ();
+ NS_ASSERT (ueRrc->GetCellId () == enbLteDevice->GetCellId ());
+ Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
+ if (ueManager->GetState () == UeManager::CONNECTED_NORMALLY)
+ {
+ EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params;
+ params.rnti = rnti;
+ params.bearer = bearer;
+ params.teid = 0; // don't care
+ enbRrc->GetS1SapUser ()->DataRadioBearerSetupRequest (params);
+ done = true;
+ }
+ }
+
+ if (!done) // UE not connected yet, try again later
+ {
+ // use a function pointer to get around overloading
+ void (LteHelper::*functionPtr) (NetDeviceContainer ueDevices, EpsBearer bearer) = &LteHelper::ActivateDataRadioBearer;
+ Simulator::Schedule (Seconds (0.001), functionPtr, this, ueDevice, bearer);
+ }
}
void
@@ -686,17 +728,17 @@
{
NS_LOG_FUNCTION (path);
// Sample path input:
- // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/RadioBearerMap/#LCID/LteRlc/RxPDU
+ // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/DataRadioBearerMap/#LCID/LteRlc/RxPDU
- // We retrieve the UeInfo associated to the C-RNTI and perform the IMSI lookup
- std::string ueMapPath = path.substr (0, path.find ("/RadioBearerMap"));
+ // We retrieve the UeManager associated to the C-RNTI and perform the IMSI lookup
+ std::string ueMapPath = path.substr (0, path.find ("/DataRadioBearerMap"));
Config::MatchContainer match = Config::LookupMatches (ueMapPath);
if (match.GetN () != 0)
{
Ptr<Object> ueInfo = match.Get (0);
- NS_LOG_LOGIC ("FindImsiFromEnbRlcPath: " << path << ", " << ueInfo->GetObject<UeInfo> ()->GetImsi ());
- return ueInfo->GetObject<UeInfo> ()->GetImsi ();
+ NS_LOG_LOGIC ("FindImsiFromEnbRlcPath: " << path << ", " << ueInfo->GetObject<UeManager> ()->GetImsi ());
+ return ueInfo->GetObject<UeManager> ()->GetImsi ();
}
else
{
@@ -709,7 +751,7 @@
{
NS_LOG_FUNCTION (path);
// Sample path input:
- // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/RadioBearerMap/#LCID/LteRlc/RxPDU
+ // /NodeList/#NodeId/DeviceList/#DeviceId/LteEnbRrc/UeMap/#C-RNTI/DataRadioBearerMap/#LCID/LteRlc/RxPDU
// We retrieve the CellId associated to the Enb
std::string enbNetDevicePath = path.substr (0, path.find ("/LteEnbRrc"));
@@ -830,9 +872,9 @@
LteHelper::EnableDlRlcTraces (void)
{
NS_LOG_FUNCTION_NOARGS ();
- Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LteRlc/TxPDU",
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/DataRadioBearerMap/*/LteRlc/TxPDU",
MakeBoundCallback (&DlTxPduCallback, m_rlcStats));
- Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/RxPDU",
+ Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/DataRadioBearerMap/*/LteRlc/RxPDU",
MakeBoundCallback (&DlRxPduCallback, m_rlcStats));
}
@@ -920,9 +962,10 @@
void
LteHelper::EnableUlRlcTraces (void)
{
- Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/TxPDU",
+ NS_LOG_FUNCTION_NOARGS ();
+ Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/DataRadioBearerMap/*/LteRlc/TxPDU",
MakeBoundCallback (&UlTxPduCallback, m_rlcStats));
- Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LteRlc/RxPDU",
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/DataRadioBearerMap/*/LteRlc/RxPDU",
MakeBoundCallback (&UlRxPduCallback, m_rlcStats));
}
@@ -998,18 +1041,18 @@
LteHelper::EnableDlPdcpTraces (void)
{
NS_LOG_FUNCTION_NOARGS ();
- Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LtePdcp/TxPDU",
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/DataRadioBearerMap/*/LtePdcp/TxPDU",
MakeBoundCallback (&DlTxPduCallback, m_pdcpStats));
- Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LtePdcp/RxPDU",
+ Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/DataRadioBearerMap/*/LtePdcp/RxPDU",
MakeBoundCallback (&DlRxPduCallback, m_pdcpStats));
}
void
LteHelper::EnableUlPdcpTraces (void)
{
- Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LtePdcp/TxPDU",
+ Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/DataRadioBearerMap/*/LtePdcp/TxPDU",
MakeBoundCallback (&UlTxPduCallback, m_pdcpStats));
- Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/RadioBearerMap/*/LtePdcp/RxPDU",
+ Config::Connect ("/NodeList/*/DeviceList/*/LteEnbRrc/UeMap/*/DataRadioBearerMap/*/LtePdcp/RxPDU",
MakeBoundCallback (&UlRxPduCallback, m_pdcpStats));
}
--- a/src/lte/model/epc-enb-application.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-enb-application.cc Tue Oct 30 16:02:07 2012 +0100
@@ -28,7 +28,7 @@
#include "ns3/uinteger.h"
#include "epc-gtpu-header.h"
-#include "lte-radio-bearer-tag.h"
+#include "eps-bearer-tag.h"
namespace ns3 {
@@ -36,6 +36,29 @@
NS_LOG_COMPONENT_DEFINE ("EpcEnbApplication");
+EpcEnbApplication::EpsFlowId_t::EpsFlowId_t ()
+{
+}
+
+EpcEnbApplication::EpsFlowId_t::EpsFlowId_t (const uint16_t a, const uint8_t b)
+ : m_rnti (a),
+ m_bid (b)
+{
+}
+
+bool
+operator == (const EpcEnbApplication::EpsFlowId_t &a, const EpcEnbApplication::EpsFlowId_t &b)
+{
+ return ( (a.m_rnti == b.m_rnti) && (a.m_bid == b.m_bid) );
+}
+
+bool
+operator < (const EpcEnbApplication::EpsFlowId_t& a, const EpcEnbApplication::EpsFlowId_t& b)
+{
+ return ( (a.m_rnti < b.m_rnti) || ( (a.m_rnti == b.m_rnti) && (a.m_bid < b.m_bid) ) );
+}
+
+
TypeId
EpcEnbApplication::GetTypeId (void)
{
@@ -93,8 +116,8 @@
void
EpcEnbApplication::DoS1BearerSetupRequest (EpcEnbS1SapProvider::S1BearerSetupRequestParameters params)
{
- NS_LOG_FUNCTION (this);
- LteFlowId_t rbid (params.rnti, params.lcid);
+ NS_LOG_FUNCTION (this << params.rnti << params.bid);
+ EpsFlowId_t rbid (params.rnti, params.bid);
// side effect: create entries if not exist
m_rbidTeidMap[rbid] = params.teid;
m_teidRbidMap[params.teid] = rbid;
@@ -120,14 +143,14 @@
SocketAddressTag satag;
packet->RemovePacketTag (satag);
- LteRadioBearerTag tag;
+ EpsBearerTag tag;
bool found = packet->RemovePacketTag (tag);
NS_ASSERT (found);
- LteFlowId_t flowId;
+ EpsFlowId_t flowId;
flowId.m_rnti = tag.GetRnti ();
- flowId.m_lcId = tag.GetLcid ();
- NS_LOG_LOGIC ("received packet with RNTI=" << flowId.m_rnti << ", LCID=" << (uint16_t) flowId.m_lcId);
- std::map<LteFlowId_t, uint32_t>::iterator it = m_rbidTeidMap.find (flowId);
+ flowId.m_bid = tag.GetBid ();
+ NS_LOG_LOGIC ("received packet with RNTI=" << flowId.m_rnti << ", BID=" << (uint16_t) flowId.m_bid);
+ std::map<EpsFlowId_t, uint32_t>::iterator it = m_rbidTeidMap.find (flowId);
NS_ASSERT (it != m_rbidTeidMap.end ());
uint32_t teid = it->second;
SendToS1uSocket (packet, teid);
@@ -142,21 +165,21 @@
GtpuHeader gtpu;
packet->RemoveHeader (gtpu);
uint32_t teid = gtpu.GetTeid ();
- std::map<uint32_t, LteFlowId_t>::iterator it = m_teidRbidMap.find (teid);
+ std::map<uint32_t, EpsFlowId_t>::iterator it = m_teidRbidMap.find (teid);
NS_ASSERT (it != m_teidRbidMap.end ());
// workaround for bug 231 https://www.nsnam.org/bugzilla/show_bug.cgi?id=231
SocketAddressTag tag;
packet->RemovePacketTag (tag);
- SendToLteSocket (packet, it->second.m_rnti, it->second.m_lcId);
+ SendToLteSocket (packet, it->second.m_rnti, it->second.m_bid);
}
void
-EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t lcid)
+EpcEnbApplication::SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
{
- NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) lcid);
- LteRadioBearerTag tag (rnti, lcid);
+ NS_LOG_FUNCTION (this << packet << rnti << (uint16_t) bid);
+ EpsBearerTag tag (rnti, bid);
packet->AddPacketTag (tag);
int sentBytes = m_lteSocket->Send (packet);
NS_ASSERT (sentBytes > 0);
--- a/src/lte/model/epc-enb-application.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-enb-application.h Tue Oct 30 16:02:07 2012 +0100
@@ -114,6 +114,20 @@
void RecvFromS1uSocket (Ptr<Socket> socket);
+ struct EpsFlowId_t
+ {
+ uint16_t m_rnti;
+ uint8_t m_bid;
+
+ public:
+ EpsFlowId_t ();
+ EpsFlowId_t (const uint16_t a, const uint8_t b);
+
+ friend bool operator == (const EpsFlowId_t &a, const EpsFlowId_t &b);
+ friend bool operator < (const EpsFlowId_t &a, const EpsFlowId_t &b);
+ };
+
+
private:
// S1 SAP provider methods
@@ -124,9 +138,9 @@
* Send a packet to the UE via the LTE radio interface of the eNB
*
* \param packet t
- * \param rbid the Radio Bearer IDentifier
+ * \param bid the EPS Bearer IDentifier
*/
- void SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t lcid);
+ void SendToLteSocket (Ptr<Packet> packet, uint16_t rnti, uint8_t bid);
/**
@@ -144,9 +158,9 @@
*
* \param teid
* \param rnti
- * \param lcid
+ * \param bid
*/
- void SetupS1Bearer (uint32_t teid, uint16_t rnti, uint8_t lcid);
+ void SetupS1Bearer (uint32_t teid, uint16_t rnti, uint8_t bid);
/**
* raw packet socket to send and receive the packets to and from the LTE radio interface
@@ -164,16 +178,16 @@
Ipv4Address m_sgwAddress;
/**
- * map telling for each RadioBearer (RNTI,LCID) the corresponding S1-U TEID
+ * map telling for each EpsBearer (RNTI,BID) the corresponding S1-U TEID
*
*/
- std::map<LteFlowId_t, uint32_t> m_rbidTeidMap;
+ std::map<EpsFlowId_t, uint32_t> m_rbidTeidMap;
/**
- * map telling for each S1-U TEID the corresponding RadioBearer (RNTI,LCID)
+ * map telling for each S1-U TEID the corresponding EpsBearer (RNTI,BID)
*
*/
- std::map<uint32_t, LteFlowId_t> m_teidRbidMap;
+ std::map<uint32_t, EpsFlowId_t> m_teidRbidMap;
/**
* UDP port to be used for GTP
--- a/src/lte/model/epc-enb-s1-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-enb-s1-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -47,7 +47,7 @@
{
uint16_t rnti; /**< the RNTI corresponding to the IMSI for which
the radio bearer activation was requested */
- uint8_t lcid; /**< the LCID of the newly created radio bearer */
+ uint8_t bid; /**< the EPS Bearer ID of the bearer to be created*/
uint32_t teid; /**< context information that was passed upon the
corresponding call to
--- a/src/lte/model/epc-ue-nas.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-ue-nas.cc Tue Oct 30 16:02:07 2012 +0100
@@ -33,10 +33,30 @@
+
+
+const char* g_ueNasStateName[EpcUeNas::NUM_STATES] =
+ {
+ "OFF",
+ "ATTACHING",
+ "IDLE_REGISTERED",
+ "CONNECTING_TO_EPC",
+ "ACTIVE "
+ };
+
+std::string ToString (EpcUeNas::State s)
+{
+ return std::string (g_ueNasStateName[s]);
+}
+
+
+
+
NS_OBJECT_ENSURE_REGISTERED (EpcUeNas);
EpcUeNas::EpcUeNas ()
- : m_asSapProvider (0),
+ : m_state (OFF),
+ m_asSapProvider (0),
m_bidCounter (0)
{
NS_LOG_FUNCTION (this);
@@ -63,6 +83,9 @@
static TypeId tid = TypeId ("ns3::EpcUeNas")
.SetParent<Object> ()
.AddConstructor<EpcUeNas> ()
+ .AddTraceSource ("StateTransition",
+ "fired upon every UE NAS state transition",
+ MakeTraceSourceAccessor (&EpcUeNas::m_stateTransitionCallback))
;
return tid;
}
@@ -107,6 +130,9 @@
void
EpcUeNas::Connect (Ptr<NetDevice> enbDevice)
{
+ NS_LOG_FUNCTION (this);
+
+ m_enbDevice = enbDevice;
// since RRC Idle Mode cell selection is not supported yet, we
// force the UE RRC to be camped on a specific eNB
@@ -115,22 +141,35 @@
// tell RRC to go into connected mode
m_asSapProvider->Connect ();
+}
- if (m_epcHelper)
- {
- m_epcHelper->AttachUe (m_device, m_imsi, enbDevice);
- // also activate default EPS bearer
- ActivateEpsBearer (EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
- }
+
+void
+EpcUeNas::Disconnect ()
+{
+ NS_LOG_FUNCTION (this);
+ m_asSapProvider->Disconnect ();
+ SwitchToState (OFF);
}
+
void
EpcUeNas::ActivateEpsBearer (EpsBearer bearer, Ptr<EpcTft> tft)
{
- NS_ASSERT_MSG (m_bidCounter < 11, "cannot have more than 11 EPS bearers");
- uint8_t bid = ++m_bidCounter;
- m_epcHelper->ActivateEpsBearer (m_device, m_imsi, tft, bearer);
- m_tftClassifier.Add (tft, bid);
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case ACTIVE:
+ DoActivateEpsBearer (bearer, tft);
+ break;
+
+ default:
+ BearerToBeActivated btba;
+ btba.bearer = bearer;
+ btba.tft = tft;
+ m_bearersToBeActivatedList.push_back (btba);
+ break;
+ }
}
bool
@@ -138,23 +177,43 @@
{
NS_LOG_FUNCTION (this << packet);
- uint32_t id = m_tftClassifier.Classify (packet, EpcTft::UPLINK);
- NS_ASSERT ((id & 0xFFFFFF00) == 0);
- uint8_t bid = (uint8_t) (id & 0x000000FF);
- if (bid == 0)
+ switch (m_state)
{
+ case ACTIVE:
+ {
+ uint32_t id = m_tftClassifier.Classify (packet, EpcTft::UPLINK);
+ NS_ASSERT ((id & 0xFFFFFF00) == 0);
+ uint8_t bid = (uint8_t) (id & 0x000000FF);
+ if (bid == 0)
+ {
+ return false;
+ }
+ else
+ {
+ m_asSapProvider->SendData (packet, bid);
+ return true;
+ }
+ }
+ break;
+
+ default:
+ NS_LOG_WARN (this << " NAS OFF, discarding packet");
return false;
- }
- else
- {
- m_asSapProvider->SendData (packet, bid);
- return true;
- }
+ break;
+ }
}
void
EpcUeNas::DoNotifyConnectionSuccessful ()
{
+ NS_LOG_FUNCTION (this);
+ if (m_epcHelper)
+ {
+ m_epcHelper->AttachUe (m_device, m_imsi, m_enbDevice);
+ // also activate default EPS bearer
+ DoActivateEpsBearer (EpsBearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT), EpcTft::Default ());
+ SwitchToState (ACTIVE);
+ }
}
void
@@ -170,7 +229,48 @@
m_forwardUpCallback (packet);
}
+void
+EpcUeNas::DoNotifyConnectionReleased ()
+{
+ NS_FATAL_ERROR ("connection failed, it should not happen with the current model");
+}
+void
+EpcUeNas::DoActivateEpsBearer (EpsBearer bearer, Ptr<EpcTft> tft)
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT_MSG (m_bidCounter < 11, "cannot have more than 11 EPS bearers");
+ uint8_t bid = ++m_bidCounter;
+ m_epcHelper->ActivateEpsBearer (m_device, m_imsi, tft, bearer);
+ m_tftClassifier.Add (tft, bid);
+}
+
+void
+EpcUeNas::SwitchToState (State newState)
+{
+ NS_LOG_FUNCTION (this << newState);
+ State oldState = m_state;
+ m_state = newState;
+ NS_LOG_INFO ("IMSI " << m_imsi << " NAS " << ToString (oldState) << " --> " << ToString (newState));
+ m_stateTransitionCallback (oldState, newState);
+
+ // actions to be done when entering a new state:
+ switch (m_state)
+ {
+ case ACTIVE:
+ for (std::list<BearerToBeActivated>::iterator it = m_bearersToBeActivatedList.begin ();
+ it != m_bearersToBeActivatedList.end ();
+ m_bearersToBeActivatedList.erase (it++))
+ {
+ DoActivateEpsBearer (it->bearer, it->tft);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+}
} // namespace ns3
--- a/src/lte/model/epc-ue-nas.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/epc-ue-nas.h Tue Oct 30 16:02:07 2012 +0100
@@ -93,12 +93,20 @@
void SetForwardUpCallback (Callback <void, Ptr<Packet> > cb);
/**
- * instruct the NAS to go to EMM Registered + ECM Connected
+ * instruct the NAS to go to ACTIVE state, i.e., EMM Registered + ECM Connected
*
*
- * \param enbDevice the eNB through which to connect
+ * \param enbDevice the eNB through which to connect. This parameter
+ * might be removed in future versions.
*/
void Connect (Ptr<NetDevice> enbDevice);
+
+ /**
+ * instruct the NAS to disconnect
+ *
+ */
+ void Disconnect ();
+
/**
* Activate an EPS bearer
@@ -116,17 +124,45 @@
* \return true if successful, false if an error occurred
*/
bool Send (Ptr<Packet> p);
+
+
+ /**
+ * Definition of NAS states as per "LTE - From theory to practice",
+ * Section 3.2.3.2 "Connection Establishment and Release"
+ *
+ */
+ enum State
+ {
+ OFF = 0,
+ ATTACHING,
+ IDLE_REGISTERED,
+ CONNECTING_TO_EPC,
+ ACTIVE,
+ NUM_STATES
+ };
+
private:
// LTE AS SAP methods
void DoNotifyConnectionSuccessful ();
void DoNotifyConnectionFailed ();
+ void DoNotifyConnectionReleased ();
void DoRecvData (Ptr<Packet> packet);
+ // internal methods
+ void DoActivateEpsBearer (EpsBearer bearer, Ptr<EpcTft> tft);
+ void SwitchToState (State s);
+
+ State m_state;
+
+ TracedCallback<State, State> m_stateTransitionCallback;
+
Ptr<EpcHelper> m_epcHelper;
Ptr<NetDevice> m_device;
+ Ptr<NetDevice> m_enbDevice; // might go away in future versions
+
uint64_t m_imsi;
LteAsSapProvider* m_asSapProvider;
@@ -137,6 +173,14 @@
Callback <void, Ptr<Packet> > m_forwardUpCallback;
+ struct BearerToBeActivated
+ {
+ EpsBearer bearer;
+ Ptr<EpcTft> tft;
+ };
+
+ std::list<BearerToBeActivated> m_bearersToBeActivatedList;
+
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/eps-bearer-tag.cc Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,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: Marco Miozzo <marco.miozzo@cttc.es>
+ * Nicola Baldo <nbaldo@cttc.es>
+ */
+
+
+#include "eps-bearer-tag.h"
+#include "ns3/tag.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (EpsBearerTag);
+
+TypeId
+EpsBearerTag::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::EpsBearerTag")
+ .SetParent<Tag> ()
+ .AddConstructor<EpsBearerTag> ()
+ .AddAttribute ("rnti", "The rnti that indicates the UE which packet belongs",
+ UintegerValue (0),
+ MakeUintegerAccessor (&EpsBearerTag::GetRnti),
+ MakeUintegerChecker<uint16_t> ())
+ .AddAttribute ("bid", "The EPS bearer id within the UE to which the packet belongs",
+ UintegerValue (0),
+ MakeUintegerAccessor (&EpsBearerTag::GetBid),
+ MakeUintegerChecker<uint8_t> ())
+ ;
+ return tid;
+}
+
+TypeId
+EpsBearerTag::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+EpsBearerTag::EpsBearerTag ()
+ : m_rnti (0),
+ m_bid (0)
+{
+}
+EpsBearerTag::EpsBearerTag (uint16_t rnti, uint8_t bid)
+ : m_rnti (rnti),
+ m_bid (bid)
+{
+}
+
+void
+EpsBearerTag::SetRnti (uint16_t rnti)
+{
+ m_rnti = rnti;
+}
+
+void
+EpsBearerTag::SetBid (uint8_t bid)
+{
+ m_bid = bid;
+}
+
+uint32_t
+EpsBearerTag::GetSerializedSize (void) const
+{
+ return 3;
+}
+
+void
+EpsBearerTag::Serialize (TagBuffer i) const
+{
+ i.WriteU16 (m_rnti);
+ i.WriteU8 (m_bid);
+}
+
+void
+EpsBearerTag::Deserialize (TagBuffer i)
+{
+ m_rnti = (uint16_t) i.ReadU16 ();
+ m_bid = (uint8_t) i.ReadU8 ();
+}
+
+uint16_t
+EpsBearerTag::GetRnti () const
+{
+ return m_rnti;
+}
+
+uint8_t
+EpsBearerTag::GetBid () const
+{
+ return m_bid;
+}
+
+void
+EpsBearerTag::Print (std::ostream &os) const
+{
+ os << "rnti=" << m_rnti << ", bid=" << (uint16_t) m_bid;
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/eps-bearer-tag.h Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,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: Marco Miozzo <marco.miozzo@cttc.es>
+ * Nicola Baldo <nbaldo@cttc.es>
+ */
+#ifndef EPS_BEARER_TAG_H
+#define EPS_BEARER_TAG_H
+
+#include "ns3/tag.h"
+
+namespace ns3 {
+
+class Tag;
+
+
+/**
+ * Tag used to define the RNTI and EPS bearer ID for packets
+ * interchanged between the EpcEnbApplication and the LteEnbNetDevice
+ */
+
+class EpsBearerTag : public Tag
+{
+public:
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+
+ /**
+ * Create an empty EpsBearerTag
+ */
+ EpsBearerTag ();
+
+ /**
+ * Create a EpsBearerTag with the given RNTI and bearer id
+ */
+ EpsBearerTag (uint16_t rnti, uint8_t bid);
+
+ /**
+ * Set the RNTI to the given value.
+ *
+ * @param rnti the value of the RNTI to set
+ */
+ void SetRnti (uint16_t tid);
+
+ /**
+ * Set the bearer id to the given value.
+ *
+ * @param bid the value of the RNTI to set
+ */
+ void SetBid (uint8_t bid);
+
+ virtual void Serialize (TagBuffer i) const;
+ virtual void Deserialize (TagBuffer i);
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Print (std::ostream &os) const;
+
+ uint16_t GetRnti (void) const;
+ uint8_t GetBid (void) const;
+ uint8_t GetLayer (void) const;
+
+private:
+ uint16_t m_rnti;
+ uint8_t m_bid;
+
+};
+
+
+
+} // namespace ns3
+
+#endif /* EPS_BEARER_TAG_H */
--- a/src/lte/model/lte-as-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-as-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -55,7 +55,6 @@
/**
* Tell the RRC to go into Connected Mode
*
- * \param params the parameters
*/
virtual void Connect (void) = 0;
@@ -63,11 +62,17 @@
* Send a data packet
*
* \param packet the packet
- * \param drbId the EPS bearer ID
- * \return true if successful, false otherwise
+ * \param bid the EPS bearer ID
*/
virtual void SendData (Ptr<Packet> packet, uint8_t bid) = 0;
+
+ /**
+ * Tell the RRC to release the connection
+ *
+ */
+ virtual void Disconnect () = 0;
+
};
@@ -98,6 +103,12 @@
/**
+ * Notify the NAS that RRC Connection was released
+ *
+ */
+ virtual void NotifyConnectionReleased () = 0;
+
+ /**
* receive a data packet
*
* \param packet the packet
@@ -124,6 +135,7 @@
virtual void Connect (void);
virtual void ForceCampedOnEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
virtual void SendData (Ptr<Packet> packet, uint8_t bid);
+ virtual void Disconnect ();
private:
MemberLteAsSapProvider ();
@@ -163,6 +175,13 @@
m_owner->DoSendData (packet, bid);
}
+template <class C>
+void
+MemberLteAsSapProvider<C>::Disconnect ()
+{
+ m_owner->DoDisconnect ();
+}
+
/**
* Template for the implementation of the LteAsSapUser as a member
@@ -179,6 +198,7 @@
virtual void NotifyConnectionSuccessful ();
virtual void NotifyConnectionFailed ();
virtual void RecvData (Ptr<Packet> packet);
+ virtual void NotifyConnectionReleased ();
private:
MemberLteAsSapUser ();
@@ -217,6 +237,13 @@
m_owner->DoRecvData (packet);
}
+template <class C>
+void
+MemberLteAsSapUser<C>::NotifyConnectionReleased ()
+{
+ m_owner->DoNotifyConnectionReleased ();
+}
+
} // namespace ns3
--- a/src/lte/model/lte-control-messages.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-control-messages.cc Tue Oct 30 16:02:07 2012 +0100
@@ -32,16 +32,12 @@
namespace ns3 {
LteControlMessage::LteControlMessage (void)
- : m_source (0),
- m_destination (0)
{
}
LteControlMessage::~LteControlMessage (void)
{
- m_source = 0;
- m_destination = 0;
}
@@ -176,5 +172,87 @@
}
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+RachPreambleLteControlMessage::RachPreambleLteControlMessage (void)
+{
+ SetMessageType (LteControlMessage::RACH_PREAMBLE);
+}
+
+void
+RachPreambleLteControlMessage::SetPrachId (uint32_t prachId)
+{
+ m_prachId = prachId;
+}
+
+uint32_t
+RachPreambleLteControlMessage::GetPrachId () const
+{
+ return m_prachId;
+}
+
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+RarLteControlMessage::RarLteControlMessage (void)
+{
+ SetMessageType (LteControlMessage::RAR);
+}
+
+
+void
+RarLteControlMessage::SetRar (BuildRarListElement_s rar)
+{
+ m_rar = rar;
+}
+
+BuildRarListElement_s
+RarLteControlMessage::GetRar () const
+{
+ return m_rar;
+}
+
+
+void
+RarLteControlMessage::SetPrachId (uint32_t prachId)
+{
+ m_prachId = prachId;
+}
+
+uint32_t
+RarLteControlMessage::GetPrachId () const
+{
+ return m_prachId;
+}
+
+
+// ----------------------------------------------------------------------------------------------------------
+
+
+
+MibLteControlMessage::MibLteControlMessage (void)
+{
+ SetMessageType (LteControlMessage::MIB);
+}
+
+
+void
+MibLteControlMessage::SetMib (LteRrcSap::MasterInformationBlock mib)
+{
+ m_mib = mib;
+}
+
+LteRrcSap::MasterInformationBlock
+MibLteControlMessage::GetMib () const
+{
+ return m_mib;
+}
+
+
+
} // namespace ns3
--- a/src/lte/model/lte-control-messages.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-control-messages.h Tue Oct 30 16:02:07 2012 +0100
@@ -48,7 +48,10 @@
{
DL_DCI, UL_DCI, // Downlink/Uplink Data Control Indicator
DL_CQI, UL_CQI, // Downlink/Uplink Channel Quality Indicator
- BSR // Buffer Status Report
+ BSR, // Buffer Status Report
+ RACH_PREAMBLE, // Random Access Preamble
+ RAR, // Random Access Response
+ MIB, // Master Information Block
};
LteControlMessage (void);
@@ -66,8 +69,6 @@
MessageType GetMessageType (void);
private:
- Ptr<LteNetDevice> m_source;
- Ptr<LteNetDevice> m_destination;
MessageType m_type;
};
} // namespace ns3
@@ -251,7 +252,124 @@
};
+
+} // namespace ns3
+
+#endif // BSR_LTE_CONTROL_MESSAGES_H
+
+
+
+#ifndef RACH_PREAMBLE_LTE_CONTROL_MESSAGES_H
+#define RACH_PREAMBLE_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+/**
+ * \ingroup lte
+ *
+ * abstract model for the Random Access Preamble
+ */
+class RachPreambleLteControlMessage : public LteControlMessage
+{
+public:
+ RachPreambleLteControlMessage (void);
+
+ void SetPrachId (uint32_t prachId);
+
+ uint32_t GetPrachId () const;
+
+private:
+
+ uint32_t m_prachId;
+
+
+};
+
} // namespace ns3
-#endif /* LTE_CONTROL_MESSAGES_H */
+#endif // RACH_PREAMBLE_LTE_CONTROL_MESSAGES_H
+
+
+#ifndef RAR_LTE_CONTROL_MESSAGES_H
+#define RAR_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+/**
+ * \ingroup lte
+ *
+ * abstract model for the MAC Random Access Response message
+ */
+class RarLteControlMessage : public LteControlMessage
+{
+public:
+ RarLteControlMessage (void);
+
+ void SetRar (BuildRarListElement_s);
+
+ BuildRarListElement_s GetRar () const;
+
+ void SetPrachId (uint32_t prachId);
+
+ uint32_t GetPrachId () const;
+
+
+private:
+
+ BuildRarListElement_s m_rar;
+ uint32_t m_prachId;
+
+};
+
+} // namespace ns3
+#endif // RAR_LTE_CONTROL_MESSAGES_H
+
+
+
+
+#ifndef MIB_LTE_CONTROL_MESSAGES_H
+#define MIB_LTE_CONTROL_MESSAGES_H
+
+#include <ns3/object.h>
+#include <ns3/ff-mac-common.h>
+#include <ns3/lte-rrc-sap.h>
+
+namespace ns3 {
+
+class LteNetDevice;
+
+/**
+ * \ingroup lte
+ *
+ * abstract model for broadcasting the Master Information Block
+ */
+class MibLteControlMessage : public LteControlMessage
+{
+public:
+
+ MibLteControlMessage (void);
+
+ void SetMib (LteRrcSap::MasterInformationBlock mib);
+
+ LteRrcSap::MasterInformationBlock GetMib () const;
+
+private:
+
+ LteRrcSap::MasterInformationBlock m_mib;
+
+};
+
+} // namespace ns3
+
+#endif // MIB_LTE_CONTROL_MESSAGES_H
--- a/src/lte/model/lte-enb-cmac-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-cmac-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -135,6 +135,14 @@
{
public:
virtual ~LteEnbCmacSapUser ();
+
+ /**
+ * request the allocation of a Temporary C-RNTI
+ *
+ * \return the T-C-RNTI
+ */
+ virtual uint16_t AllocateTemporaryCellRnti () = 0;
+
/**
* notify the result of the last LC config operation
*
--- a/src/lte/model/lte-enb-cphy-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-cphy-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -25,6 +25,8 @@
#include <stdint.h>
#include <ns3/ptr.h>
+#include <ns3/lte-rrc-sap.h>
+
namespace ns3 {
class LteEnbNetDevice;
@@ -69,6 +71,13 @@
* \param rnti the UE id relative to this cell
*/
virtual void AddUe (uint16_t rnti) = 0;
+
+ /**
+ * Remove an UE from the the cell
+ *
+ * \param rnti the UE id relative to this cell
+ */
+ virtual void RemoveUe (uint16_t rnti) = 0;
/**
* \param rnti the RNTI of the user
@@ -82,6 +91,11 @@
*/
virtual void SetSrsConfigurationIndex (uint16_t rnti, uint16_t srsCi) = 0;
+ /**
+ *
+ * \param mib the Master Information Block to be sent on the BCH
+ */
+ virtual void SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib) = 0;
};
@@ -119,9 +133,11 @@
virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
virtual void SetEarfcn (uint16_t ulEarfcn, uint16_t dlEarfcn);
virtual void AddUe (uint16_t rnti);
+ virtual void RemoveUe (uint16_t rnti);
virtual void SetTransmissionMode (uint16_t rnti, uint8_t txMode);
virtual void SetSrsConfigurationIndex (uint16_t rnti, uint16_t srsCi);
-
+ virtual void SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
+
private:
MemberLteEnbCphySapProvider ();
C* m_owner;
@@ -167,6 +183,12 @@
m_owner->DoAddUe (rnti);
}
+template <class C>
+void
+MemberLteEnbCphySapProvider<C>::RemoveUe (uint16_t rnti)
+{
+ m_owner->DoRemoveUe (rnti);
+}
template <class C>
void
@@ -182,6 +204,12 @@
m_owner->DoSetSrsConfigurationIndex (rnti, srsCi);
}
+template <class C>
+void
+MemberLteEnbCphySapProvider<C>::SetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib)
+{
+ m_owner->DoSetMasterInformationBlock (mib);
+}
--- a/src/lte/model/lte-enb-mac.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-mac.cc Tue Oct 30 16:02:07 2012 +0100
@@ -233,6 +233,7 @@
virtual void ReceivePhyPdu (Ptr<Packet> p);
virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg);
+ virtual void ReceiveRachPreamble (uint32_t prachId);
virtual void UlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi);
private:
@@ -263,6 +264,12 @@
}
void
+EnbMacMemberLteEnbPhySapUser::ReceiveRachPreamble (uint32_t prachId)
+{
+ m_mac->DoReceiveRachPreamble (prachId);
+}
+
+void
EnbMacMemberLteEnbPhySapUser::UlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
{
m_mac->DoUlCqiReport (ulcqi);
@@ -513,10 +520,32 @@
}
else
{
- NS_LOG_LOGIC (this << " LteControlMessage not recognized");
+ NS_LOG_LOGIC (this << " LteControlMessage type " << msg->GetMessageType () << " not recognized");
}
}
+void
+LteEnbMac::DoReceiveRachPreamble (uint32_t prachId)
+{
+ NS_LOG_FUNCTION (this << prachId);
+ uint16_t rnti = m_cmacSapUser->AllocateTemporaryCellRnti ();
+
+ // todo: should trigger SCHED_DL_RACH_INFO_REQ here
+ // and then wait for DL_SCHEDULE_INDICATION to build the RARs from the RAR_List
+
+ // for now, we take a shortcut and just build the RAR here as an ideal message and without an UL grant
+
+ BuildRarListElement_s rar;
+ rar.m_rnti = rnti;
+
+ Ptr<RarLteControlMessage> msg = Create<RarLteControlMessage> ();
+ msg->SetPrachId (prachId);
+ msg->SetRar (rar);
+ m_enbPhySapProvider->SendLteControlMessage (msg);
+
+}
+
+
void
LteEnbMac::DoUlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
@@ -551,7 +580,6 @@
}
-
void
LteEnbMac::DoReceivePhyPdu (Ptr<Packet> p)
{
@@ -602,7 +630,6 @@
-
// ////////////////////////////////////////////
// CMAC SAP
// ////////////////////////////////////////////
@@ -628,6 +655,7 @@
FfMacCschedSapProvider::CschedUeConfigReqParameters params;
params.m_rnti = rnti;
params.m_transmissionMode = 0; // set to default value (SISO) for avoiding random initialization (valgrind error)
+
m_cschedSapProvider->CschedUeConfigReq (params);
}
@@ -644,10 +672,11 @@
LteEnbMac::DoAddLc (LteEnbCmacSapProvider::LcInfo lcinfo, LteMacSapUser* msu)
{
NS_LOG_FUNCTION (this);
+
std::map <LteFlowId_t, LteMacSapUser* >::iterator it;
-
+
LteFlowId_t flow (lcinfo.rnti, lcinfo.lcId);
-
+
it = m_rlcAttached.find (flow);
if (it == m_rlcAttached.end ())
{
@@ -658,24 +687,30 @@
NS_LOG_ERROR ("LC already exists");
}
-
- struct FfMacCschedSapProvider::CschedLcConfigReqParameters params;
- params.m_rnti = lcinfo.rnti;
- params.m_reconfigureFlag = false;
+ // CCCH (LCID 0) is pre-configured
+ // see FF LTE MAC Scheduler
+ // Interface Specification v1.11,
+ // 4.3.4 logicalChannelConfigListElement
+ if (lcinfo.lcId != 0)
+ {
+ struct FfMacCschedSapProvider::CschedLcConfigReqParameters params;
+ params.m_rnti = lcinfo.rnti;
+ params.m_reconfigureFlag = false;
- struct LogicalChannelConfigListElement_s lccle;
- lccle.m_logicalChannelIdentity = lcinfo.lcId;
- lccle.m_logicalChannelGroup = lcinfo.lcGroup;
- lccle.m_direction = LogicalChannelConfigListElement_s::DIR_BOTH;
- lccle.m_qosBearerType = lcinfo.isGbr ? LogicalChannelConfigListElement_s::QBT_GBR : LogicalChannelConfigListElement_s::QBT_NON_GBR;
- lccle.m_qci = lcinfo.qci;
- lccle.m_eRabMaximulBitrateUl = lcinfo.mbrUl;
- lccle.m_eRabMaximulBitrateDl = lcinfo.mbrDl;
- lccle.m_eRabGuaranteedBitrateUl = lcinfo.gbrUl;
- lccle.m_eRabGuaranteedBitrateDl = lcinfo.gbrDl;
- params.m_logicalChannelConfigList.push_back (lccle);
+ struct LogicalChannelConfigListElement_s lccle;
+ lccle.m_logicalChannelIdentity = lcinfo.lcId;
+ lccle.m_logicalChannelGroup = lcinfo.lcGroup;
+ lccle.m_direction = LogicalChannelConfigListElement_s::DIR_BOTH;
+ lccle.m_qosBearerType = lcinfo.isGbr ? LogicalChannelConfigListElement_s::QBT_GBR : LogicalChannelConfigListElement_s::QBT_NON_GBR;
+ lccle.m_qci = lcinfo.qci;
+ lccle.m_eRabMaximulBitrateUl = lcinfo.mbrUl;
+ lccle.m_eRabMaximulBitrateDl = lcinfo.mbrDl;
+ lccle.m_eRabGuaranteedBitrateUl = lcinfo.gbrUl;
+ lccle.m_eRabGuaranteedBitrateDl = lcinfo.gbrDl;
+ params.m_logicalChannelConfigList.push_back (lccle);
- m_cschedSapProvider->CschedLcConfigReq (params);
+ m_cschedSapProvider->CschedLcConfigReq (params);
+ }
}
void
@@ -875,6 +910,7 @@
FfMacCschedSapProvider::CschedUeConfigReqParameters req;
req.m_rnti = params.m_rnti;
req.m_transmissionMode = params.m_transmissionMode;
+ req.m_reconfigureFlag = true;
m_cschedSapProvider->CschedUeConfigReq (req);
}
--- a/src/lte/model/lte-enb-mac.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-mac.h Tue Oct 30 16:02:07 2012 +0100
@@ -119,6 +119,8 @@
void SetLteEnbPhySapProvider (LteEnbPhySapProvider* s);
+private:
+
/**
* \brief Receive a DL CQI ideal control message
* \param msg the DL CQI message
@@ -133,11 +135,11 @@
*/
void ReceiveBsrMessage (MacCeListElement_s bsr);
+
void DoUlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi);
-private:
// forwarded from LteEnbCmacSapProvider
void DoConfigureMac (uint8_t ulBandwidth, uint8_t dlBandwidth);
void DoAddUe (uint16_t rnti);
@@ -166,25 +168,15 @@
void DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params);
- /**
- * \brief Forwarded from LteEnbPhySapUser: trigger the start from a new frame
- *
- * \param frameNo frame number
- * \param subframeNo subframe number
- */
+ // forwarded from LteEnbPhySapUser
void DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo);
+ void DoReceiveRachPreamble (uint32_t prachId);
- /**
- * \brief Forwarded from LtePhySapUser: receive a PHY-PDU
- *
- * \param p PHY-PDU received
- */
public:
// legacy public for use the Phy callback
void DoReceivePhyPdu (Ptr<Packet> p);
private:
-private:
std::map <LteFlowId_t, LteMacSapUser*> m_rlcAttached;
std::vector <CqiListElement_s> m_dlCqiReceived; // DL-CQI received
--- a/src/lte/model/lte-enb-net-device.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-net-device.cc Tue Oct 30 16:02:07 2012 +0100
@@ -265,7 +265,7 @@
{
NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
NS_ASSERT_MSG (protocolNumber == Ipv4L3Protocol::PROT_NUMBER, "unsupported protocol " << protocolNumber << ", only IPv4 is supported");
- return m_rrc->Send (packet);
+ return m_rrc->SendData (packet);
}
--- a/src/lte/model/lte-enb-phy-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-phy-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -97,6 +97,13 @@
*/
virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg) = 0;
+ /**
+ * notify the reception of a RACH preamble on the PRACH
+ *
+ * \param prachId the ID of the preamble
+ */
+ virtual void ReceiveRachPreamble (uint32_t prachId) = 0;
+
/**
* \brief Returns to MAC level the UL-CQI evaluated
* \param ulcqi the UL-CQI (see FF MAC API 4.3.29)
--- a/src/lte/model/lte-enb-phy.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-phy.cc Tue Oct 30 16:02:07 2012 +0100
@@ -72,8 +72,6 @@
virtual void SetCellId (uint16_t cellId);
virtual void SendLteControlMessage (Ptr<LteControlMessage> msg);
virtual uint8_t GetMacChTtiDelay ();
- virtual void SetTransmissionMode (uint16_t rnti, uint8_t txMode);
- virtual void SetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi);
private:
@@ -85,7 +83,6 @@
}
-
void
EnbMemberLteEnbPhySapProvider::SendMacPdu (Ptr<Packet> p)
{
@@ -116,18 +113,6 @@
return (m_phy->DoGetMacChTtiDelay ());
}
-void
-EnbMemberLteEnbPhySapProvider::SetTransmissionMode (uint16_t rnti, uint8_t txMode)
-{
- m_phy->DoSetTransmissionMode (rnti, txMode);
-}
-
-void
-EnbMemberLteEnbPhySapProvider::SetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi)
-{
- m_phy->DoSetSrsConfigurationIndex (rnti, srcCi);
-}
-
////////////////////////////////////////
// generic LteEnbPhy methods
@@ -419,9 +404,20 @@
std::list<Ptr<LteControlMessage> >::iterator it;
for (it = msgList.begin (); it != msgList.end(); it++)
{
- m_enbPhySapUser->ReceiveLteControlMessage (*it);
+ switch ((*it)->GetMessageType ())
+ {
+ case LteControlMessage::RACH_PREAMBLE:
+ {
+ Ptr<RachPreambleLteControlMessage> rachPreamble = DynamicCast<RachPreambleLteControlMessage> (*it);
+ m_enbPhySapUser->ReceiveRachPreamble (rachPreamble->GetPrachId ());
+ }
+ break;
+
+ default:
+ m_enbPhySapUser->ReceiveLteControlMessage (*it);
+ break;
+ }
}
-
}
@@ -434,6 +430,13 @@
++m_nrFrames;
NS_LOG_INFO ("-----frame " << m_nrFrames << "-----");
m_nrSubFrames = 0;
+
+ // send MIB at beginning of every frame
+ m_mib.systemFrameNumber = m_nrSubFrames;
+ Ptr<MibLteControlMessage> mibMsg = Create<MibLteControlMessage> ();
+ mibMsg->SetMib (m_mib);
+ m_controlMessagesQueue.at (0).push_back (mibMsg);
+
StartSubFrame ();
}
@@ -447,7 +450,9 @@
if (m_srsPeriodicity>0)
{
// might be 0 in case the eNB has no UEs attached
- m_currentSrsOffset = (m_currentSrsOffset + 1) % m_srsPeriodicity;
+ NS_ASSERT_MSG (m_nrFrames > 1, "the SRS index check code assumes that frameNo starts at 1");
+ NS_ASSERT_MSG (m_nrSubFrames > 0 && m_nrSubFrames <= 10, "the SRS index check code assumes that subframeNo starts at 1");
+ m_currentSrsOffset = (((m_nrFrames-1)*10 + (m_nrSubFrames-1)) % m_srsPeriodicity);
}
NS_LOG_INFO ("-----sub frame " << m_nrSubFrames << "-----");
@@ -677,6 +682,15 @@
NS_ASSERT_MSG (success, "AddUePhy() failed");
}
+void
+LteEnbPhy::DoRemoveUe (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << rnti);
+
+ bool success = DeleteUePhy (rnti);
+ NS_ASSERT_MSG (success, "DeleteUePhy() failed");
+}
+
FfMacSchedSapProvider::SchedUlCqiInfoReqParameters
LteEnbPhy::CreateSrsCqiReport (const SpectrumValue& sinr)
@@ -754,7 +768,6 @@
m_srsUeOffset.clear ();
m_srsUeOffset.resize (p, 0);
m_srsPeriodicity = p;
- m_currentSrsOffset = p - 1; // for starting from 0 next subframe
}
NS_LOG_DEBUG (this << " ENB SRS P " << m_srsPeriodicity << " RNTI " << rnti << " offset " << GetSrsSubframeOffset (srcCi) << " CI " << srcCi);
@@ -772,4 +785,12 @@
}
+void
+LteEnbPhy::DoSetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib)
+{
+ NS_LOG_FUNCTION (this);
+ m_mib = mib;
+}
+
+
};
--- a/src/lte/model/lte-enb-phy.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-phy.h Tue Oct 30 16:02:07 2012 +0100
@@ -237,12 +237,13 @@
void DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
void DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
void DoAddUe (uint16_t rnti);
+ void DoRemoveUe (uint16_t rnti);
void DoSetTransmissionMode (uint16_t rnti, uint8_t txMode);
-
+ void DoSetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi);
+ void DoSetMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
// LteEnbPhySapProvider forwarded methods
void DoSendMacPdu (Ptr<Packet> p);
- void DoSetSrsConfigurationIndex (uint16_t rnti, uint16_t srcCi);
void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
uint8_t DoGetMacChTtiDelay ();
@@ -274,6 +275,8 @@
std::map <uint16_t,uint16_t> m_srsCounter;
std::vector <uint16_t> m_srsUeOffset;
uint16_t m_currentSrsOffset;
+
+ LteRrcSap::MasterInformationBlock m_mib;
};
--- a/src/lte/model/lte-enb-rrc.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-rrc.cc Tue Oct 30 16:02:07 2012 +0100
@@ -28,32 +28,29 @@
#include "ns3/object-factory.h"
#include "ns3/simulator.h"
-#include "ns3/lte-enb-rrc.h"
-#include "ns3/lte-enb-net-device.h"
-#include "ns3/lte-rlc.h"
-#include "ns3/lte-pdcp.h"
-#include "ns3/lte-pdcp-sap.h"
-#include "ns3/lte-radio-bearer-info.h"
-#include "lte-radio-bearer-tag.h"
+#include "lte-enb-rrc.h"
+
+#include "lte-enb-net-device.h"
+#include "lte-radio-bearer-info.h"
+#include "eps-bearer-tag.h"
#include "ff-mac-csched-sap.h"
#include "epc-enb-s1-sap.h"
#include "lte-rlc.h"
+#include "lte-rlc-tm.h"
#include "lte-rlc-um.h"
#include "lte-rlc-am.h"
+#include "lte-pdcp.h"
+#include "lte-pdcp-sap.h"
#include <ns3/simulator.h>
-// WILD HACK for UE-RRC direct communications
-#include <ns3/node-list.h>
-#include <ns3/node.h>
-#include <ns3/lte-ue-net-device.h>
-#include <ns3/lte-ue-rrc.h>
NS_LOG_COMPONENT_DEFINE ("LteEnbRrc");
+
namespace ns3 {
@@ -66,6 +63,7 @@
public:
EnbRrcMemberLteEnbCmacSapUser (LteEnbRrc* rrc);
+ virtual uint16_t AllocateTemporaryCellRnti ();
virtual void NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
virtual void RrcConfigurationUpdateInd (UeConfig params);
@@ -78,6 +76,12 @@
{
}
+uint16_t
+EnbRrcMemberLteEnbCmacSapUser::AllocateTemporaryCellRnti ()
+{
+ return m_rrc->DoAllocateTemporaryCellRnti ();
+}
+
void
EnbRrcMemberLteEnbCmacSapUser::NotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
{
@@ -91,115 +95,659 @@
}
+const char* g_ueManagerStateName[UeManager::NUM_STATES] =
+ {
+ "INITIAL_RANDOM_ACCESS",
+ "CONNECTION_SETUP",
+ "CONNECTED_NORMALLY",
+ "CONNECTION_RECONFIGURATION",
+ "CONNECTION_REESTABLISHMENT",
+ "HANDOVER_JOINING",
+ "HANDOVER_LEAVING",
+ };
+
+std::string ToString (UeManager::State s)
+{
+ return std::string (g_ueManagerStateName[s]);
+}
+
+
+
///////////////////////////////////////////
-// UeInfo
+// UeManager
///////////////////////////////////////////
-NS_OBJECT_ENSURE_REGISTERED (UeInfo);
+NS_OBJECT_ENSURE_REGISTERED (UeManager);
+
-UeInfo::UeInfo (void)
- : m_lastAllocatedId (0)
+UeManager::UeManager ()
{
- m_imsi = 0;
- m_srsConfigurationIndex = 0;
- m_transmissionMode = 0;
+ NS_FATAL_ERROR ("this constructor is not espected to be used");
}
-UeInfo::~UeInfo (void)
-{
- // Nothing to do here
+UeManager::UeManager (Ptr<LteEnbRrc> rrc, uint16_t rnti, State s)
+ : m_lastAllocatedDrbid (0),
+ m_rnti (rnti),
+ m_imsi (0),
+ m_lastRrcTransactionIdentifier (0),
+ m_rrc (rrc),
+ m_state (s),
+ m_pendingRrcConnectionReconfiguration (false)
+{
+ NS_LOG_FUNCTION (this);
+
+ m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<UeManager> (this);
+
+ m_physicalConfigDedicated.haveAntennaInfoDedicated = true;
+ m_physicalConfigDedicated.antennaInfo.transmissionMode = m_rrc->m_defaultTransmissionMode;
+ m_physicalConfigDedicated.haveSoundingRsUlConfigDedicated = true;
+ m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex = m_rrc->GetNewSrsConfigurationIndex ();
+
+ m_rrc->m_cmacSapProvider->AddUe (rnti);
+ m_rrc->m_cphySapProvider->AddUe (rnti);
+
+ // setup the eNB side of SRB0
+ {
+ uint8_t lcid = 0;
+
+ Ptr<LteRlc> rlc = CreateObject<LteRlcTm> ()->GetObject<LteRlc> ();
+ rlc->SetLteMacSapProvider (m_rrc->m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+ rlc->SetLcId (lcid);
+
+ m_srb0 = CreateObject<LteSignalingRadioBearerInfo> ();
+ m_srb0->m_rlc = rlc;
+ m_srb0->m_srbIdentity = 1;
+ // no need to store logicalChannelConfig as SRB0 is pre-configured
+
+ LteEnbCmacSapProvider::LcInfo lcinfo;
+ lcinfo.rnti = m_rnti;
+ lcinfo.lcId = lcid;
+ // leave the rest of lcinfo empty as CCCH (LCID 0) is pre-configured
+ m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
+
+ }
+
+ // setup the eNB side of SRB1; the UE side will be set up upon RRC connection establishment
+ {
+ uint8_t lcid = 1;
+
+ Ptr<LteRlc> rlc = CreateObject<LteRlcAm> ()->GetObject<LteRlc> ();
+ rlc->SetLteMacSapProvider (m_rrc->m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+ rlc->SetLcId (lcid);
+
+ Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
+ pdcp->SetRnti (m_rnti);
+ pdcp->SetLcId (lcid);
+ pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
+ pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
+ rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
+
+ m_srb1 = CreateObject<LteSignalingRadioBearerInfo> ();
+ m_srb1->m_rlc = rlc;
+ m_srb1->m_pdcp = pdcp;
+ m_srb1->m_srbIdentity = 1;
+ m_srb1->m_logicalChannelConfig.priority = 0;
+ m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps = 100;
+ m_srb1->m_logicalChannelConfig.bucketSizeDurationMs = 100;
+ m_srb1->m_logicalChannelConfig.logicalChannelGroup = 0;
+
+ LteEnbCmacSapProvider::LcInfo lcinfo;
+ lcinfo.rnti = m_rnti;
+ lcinfo.lcId = lcid;
+ lcinfo.lcGroup = 0; // all SRBs always mapped to LCG 0
+ lcinfo.qci = EpsBearer::GBR_CONV_VOICE; // not sure why the FF API requires a CQI even for SRBs...
+ lcinfo.isGbr = true;
+ lcinfo.mbrUl = 1e6;
+ lcinfo.mbrDl = 1e6;
+ lcinfo.gbrUl = 1e4;
+ lcinfo.gbrDl = 1e4;
+ m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
+ }
+
+ LteEnbRrcSapUser::SetupUeParameters ueParams;
+ ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider ();
+ ueParams.srb1SapProvider = m_srb1->m_pdcp->GetLtePdcpSapProvider ();
+ m_rrc->m_rrcSapUser->SetupUe (m_rnti, ueParams);
+
+ // configure MAC (and scheduler)
+ LteEnbCmacSapProvider::UeConfig req;
+ req.m_rnti = rnti;
+ req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
+ m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
+
+ // configure PHY
+ m_rrc->m_cphySapProvider->SetTransmissionMode (rnti, m_physicalConfigDedicated.antennaInfo.transmissionMode);
+ m_rrc->m_cphySapProvider->SetSrsConfigurationIndex (rnti, m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex);
}
-TypeId UeInfo::GetTypeId (void)
+
+UeManager::~UeManager (void)
+{
+}
+
+void
+UeManager::DoDispose ()
{
- static TypeId tid = TypeId ("ns3::UeInfo")
+ delete m_pdcpSapUser;
+
+ m_rrc->m_cmacSapProvider->RemoveUe (m_rnti);
+ m_rrc->m_cphySapProvider->RemoveUe (m_rnti);
+}
+
+TypeId UeManager::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::UeManager")
.SetParent<Object> ()
- .AddConstructor<UeInfo> ()
- .AddAttribute ("RadioBearerMap", "List of UE RadioBearerInfo by LCID.",
+ .AddConstructor<UeManager> ()
+ .AddAttribute ("DataRadioBearerMap", "List of UE RadioBearerInfo by DRBID.",
ObjectMapValue (),
- MakeObjectMapAccessor (&UeInfo::m_rbMap),
- MakeObjectMapChecker<LteRadioBearerInfo> ())
+ MakeObjectMapAccessor (&UeManager::m_drbMap),
+ MakeObjectMapChecker<LteDataRadioBearerInfo> ())
+ .AddTraceSource ("StateTransition",
+ "fired upon every UE state transition seen by the UeManager at the eNB RRC",
+ MakeTraceSourceAccessor (&UeManager::m_stateTransitionCallback))
;
return tid;
}
+
+uint8_t
+UeManager::SetupDataRadioBearer (EpsBearer bearer)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) m_rnti);
+
+ Ptr<LteDataRadioBearerInfo> drbInfo = CreateObject<LteDataRadioBearerInfo> ();
+ uint8_t drbid = AddDataRadioBearerInfo (drbInfo);
+ uint8_t lcid = Drbid2Lcid (drbid);
+ uint8_t bid = Drbid2Bid (drbid);
+ drbInfo->m_epsBearerIdentity = bid;
+ drbInfo->m_drbIdentity = drbid;
+ drbInfo->m_logicalChannelIdentity = lcid;
+
+ TypeId rlcTypeId = m_rrc->GetRlcType (bearer);
+
+ ObjectFactory rlcObjectFactory;
+ rlcObjectFactory.SetTypeId (rlcTypeId);
+ Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
+ rlc->SetLteMacSapProvider (m_rrc->m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+
+ drbInfo->m_rlc = rlc;
+
+ rlc->SetLcId (lcid);
+
+ // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
+ // if we are using RLC/SM we don't care of anything above RLC
+ if (rlcTypeId != LteRlcSm::GetTypeId ())
+ {
+ Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
+ pdcp->SetRnti (m_rnti);
+ pdcp->SetLcId (lcid);
+ pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
+ pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
+ rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
+ drbInfo->m_pdcp = pdcp;
+ }
+
+ LteEnbCmacSapProvider::LcInfo lcinfo;
+ lcinfo.rnti = m_rnti;
+ lcinfo.lcId = lcid;
+ lcinfo.lcGroup = m_rrc->GetLogicalChannelGroup (bearer);
+ lcinfo.qci = bearer.qci;
+ lcinfo.isGbr = bearer.IsGbr ();
+ lcinfo.mbrUl = bearer.gbrQosInfo.mbrUl;
+ lcinfo.mbrDl = bearer.gbrQosInfo.mbrDl;
+ lcinfo.gbrUl = bearer.gbrQosInfo.gbrUl;
+ lcinfo.gbrDl = bearer.gbrQosInfo.gbrDl;
+ m_rrc->m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
+
+ if (drbInfo->m_rlc->GetTypeId () == LteRlcAm::GetTypeId ())
+ {
+ drbInfo->m_rlcConfig.choice = LteRrcSap::RlcConfig::AM;
+ }
+ else
+ {
+ drbInfo->m_rlcConfig.choice = LteRrcSap::RlcConfig::UM_BI_DIRECTIONAL;
+ }
+
+ drbInfo->m_logicalChannelIdentity = lcid;
+ drbInfo->m_logicalChannelConfig.priority = m_rrc->GetLogicalChannelPriority (bearer);
+ drbInfo->m_logicalChannelConfig.logicalChannelGroup = m_rrc->GetLogicalChannelGroup (bearer);
+ if (bearer.IsGbr ())
+ {
+ drbInfo->m_logicalChannelConfig.prioritizedBitRateKbps = bearer.gbrQosInfo.gbrUl;
+ }
+ else
+ {
+ drbInfo->m_logicalChannelConfig.prioritizedBitRateKbps = 0;
+ }
+ drbInfo->m_logicalChannelConfig.bucketSizeDurationMs = 1000;
+
+ return drbid;
+}
+
+
+void
+UeManager::ReleaseDataRadioBearer (uint8_t drbid)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) m_rnti << (uint32_t) drbid);
+ uint8_t lcid = Drbid2Lcid (drbid);
+ std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ NS_ASSERT_MSG (it != m_drbMap.end (), "request to remove radio bearer with unknown drbid " << drbid);
+ m_drbMap.erase (it);
+ m_rrc->m_cmacSapProvider->ReleaseLc (m_rnti, lcid);
+
+ LteRrcSap::RadioResourceConfigDedicated rrcd;
+ rrcd.havePhysicalConfigDedicated = false;
+ rrcd.drbToReleaseList.push_back (drbid);
+
+ LteRrcSap::RrcConnectionReconfiguration msg;
+ msg.haveMeasConfig = false;
+ msg.haveMobilityControlInfo = false;
+
+ m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, msg);
+}
+
+
+void
+UeManager::ScheduleRrcConnectionReconfiguration ()
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ case CONNECTION_SETUP:
+ case CONNECTION_RECONFIGURATION:
+ case CONNECTION_REESTABLISHMENT:
+ case HANDOVER_JOINING:
+ case HANDOVER_LEAVING:
+ // a previous reconfiguration still ongoing, we need to wait for it to be finished
+ m_pendingRrcConnectionReconfiguration = true;
+ break;
+
+ case CONNECTED_NORMALLY:
+ {
+ m_pendingRrcConnectionReconfiguration = false;
+ LteRrcSap::RrcConnectionReconfiguration msg = BuildRrcConnectionReconfiguration ();
+ m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, msg);
+ SwitchToState (CONNECTION_RECONFIGURATION);
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+UeManager::SendHandoverCommand (LteRrcSap::RrcConnectionReconfiguration rcr)
+{
+ NS_LOG_FUNCTION (this);
+ m_rrc->m_rrcSapUser->SendRrcConnectionReconfiguration (m_rnti, rcr);
+ SwitchToState (HANDOVER_LEAVING);
+}
+
+LteRrcSap::RadioResourceConfigDedicated
+UeManager::GetRadioResourceConfigForHandoverPreparationInfo ()
+{
+ NS_LOG_FUNCTION (this);
+ return BuildRadioResourceConfigDedicated ();
+}
+
+LteRrcSap::RrcConnectionReconfiguration
+UeManager::GetHandoverCommand ()
+{
+ NS_LOG_FUNCTION (this);
+ return BuildRrcConnectionReconfiguration ();
+}
+
+void
+UeManager::SendData (uint8_t bid, Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION (this << p << (uint16_t) bid);
+ LtePdcpSapProvider::TransmitPdcpSduParameters params;
+ params.pdcpSdu = p;
+ params.rnti = m_rnti;
+ params.lcid = Bid2Lcid (bid);
+ uint8_t drbid = Bid2Drbid (bid);
+ LtePdcpSapProvider* pdcpSapProvider = GetDataRadioBearerInfo (drbid)->m_pdcp->GetLtePdcpSapProvider ();
+ pdcpSapProvider->TransmitPdcpSdu (params);
+}
+
+std::vector<EpcX2Sap::ErabToBeSetupItem>
+UeManager::GetErabList ()
+{
+ NS_LOG_FUNCTION (this);
+ std::vector<EpcX2Sap::ErabToBeSetupItem> ret;
+ for (std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.begin ();
+ it != m_drbMap.end ();
+ ++it)
+ {
+ NS_FATAL_ERROR ("filling of each ErabToBeSetupItem is not implemented yet");
+ }
+ return ret;
+}
+
+void
+UeManager::CompleteSetupUe (LteEnbRrcSapProvider::CompleteSetupUeParameters params)
+{
+ NS_LOG_FUNCTION (this);
+ m_srb0->m_rlc->SetLteRlcSapUser (params.srb0SapUser);
+ m_srb1->m_pdcp->SetLtePdcpSapUser (params.srb1SapUser);
+}
+
+void
+UeManager::RecvRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg)
+{
+ NS_LOG_FUNCTION (this);
+ m_imsi = msg.ueIdentity;
+
+ if (m_rrc->m_s1SapProvider != 0)
+ {
+ m_rrc->m_s1SapProvider->InitialUeMessage (m_imsi, m_rnti);
+ }
+
+ LteRrcSap::RrcConnectionSetup msg2;
+ msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+ msg2.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
+ m_rrc->m_rrcSapUser->SendRrcConnectionSetup (m_rnti, msg2);
+ SwitchToState (CONNECTION_SETUP);
+}
+
+void
+UeManager::RecvRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg)
+{
+ NS_LOG_FUNCTION (this);
+ SwitchToState (CONNECTED_NORMALLY);
+}
+
+void
+UeManager::RecvRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg)
+{
+ NS_LOG_FUNCTION (this);
+ SwitchToState (CONNECTED_NORMALLY);
+}
+
+void
+UeManager::RecvRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg)
+{
+ NS_LOG_FUNCTION (this);
+ LteRrcSap::RrcConnectionReestablishment msg2;
+ msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+ msg2.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
+ m_rrc->m_rrcSapUser->SendRrcConnectionReestablishment (m_rnti, msg2);
+ SwitchToState (CONNECTION_REESTABLISHMENT);
+}
+
+void
+UeManager::RecvRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg)
+{
+ NS_LOG_FUNCTION (this);
+ SwitchToState (CONNECTED_NORMALLY);
+}
+
+
+void
+UeManager::CmacUeConfigUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams)
+{
+ NS_LOG_FUNCTION (this << m_rnti);
+ // at this stage used only by the scheduler for updating txMode
+
+ m_physicalConfigDedicated.antennaInfo.transmissionMode = cmacParams.m_transmissionMode;
+
+ // configure MAC (and scheduler)
+ LteEnbCmacSapProvider::UeConfig req;
+ req.m_rnti = m_rnti;
+ req.m_transmissionMode = m_physicalConfigDedicated.antennaInfo.transmissionMode;
+ m_rrc->m_cmacSapProvider->UeUpdateConfigurationReq (req);
+
+ // configure PHY
+ m_rrc->m_cphySapProvider->SetTransmissionMode (req.m_rnti, req.m_transmissionMode);
+
+ // reconfigure the UE RRC
+ ScheduleRrcConnectionReconfiguration ();
+}
+
+
+void
+UeManager::DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params)
+{
+ NS_LOG_FUNCTION (this);
+ if (params.lcid > 2)
+ {
+ // data radio bearer
+ EpsBearerTag tag;
+ tag.SetRnti (params.rnti);
+ tag.SetBid (Lcid2Bid (params.lcid));
+ params.pdcpSdu->AddPacketTag (tag);
+ m_rrc->m_forwardUpCallback (params.pdcpSdu);
+ }
+}
+
+
+uint16_t
+UeManager::GetRnti (void)
+{
+ return m_rnti;
+}
+
uint64_t
-UeInfo::GetImsi (void)
+UeManager::GetImsi (void)
{
return m_imsi;
}
-void
-UeInfo::SetImsi (uint64_t imsi)
-{
- m_imsi = imsi;
-}
-
uint16_t
-UeInfo::GetSrsConfigurationIndex (void)
+UeManager::GetSrsConfigurationIndex (void)
{
- return m_srsConfigurationIndex;
-}
-
-void
-UeInfo::SetSrsConfigurationIndex (uint16_t srsConfIndex)
-{
- m_srsConfigurationIndex = srsConfIndex;
-}
-
-uint8_t
-UeInfo::GetTransmissionMode (void)
-{
- return m_transmissionMode;
+ return m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex;
}
void
-UeInfo::SetTransmissionMode (uint8_t txMode)
+UeManager::SetSrsConfigurationIndex (uint16_t srsConfIndex)
{
- m_transmissionMode = txMode;
+ NS_LOG_FUNCTION (this);
+ m_physicalConfigDedicated.soundingRsUlConfigDedicated.srsConfigIndex = srsConfIndex;
+ m_rrc->m_cphySapProvider->SetSrsConfigurationIndex (m_rnti, srsConfIndex);
+ switch (m_state)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ // do nothing, srs conf index will be correctly enforced upon
+ // RRC connection establishment
+ break;
+
+ default:
+ ScheduleRrcConnectionReconfiguration ();
+ break;
+ }
+}
+
+UeManager::State
+UeManager::GetState (void)
+{
+ return m_state;
}
uint8_t
-UeInfo::AddRadioBearer (Ptr<LteRadioBearerInfo> rbi)
+UeManager::AddDataRadioBearerInfo (Ptr<LteDataRadioBearerInfo> drbInfo)
{
NS_LOG_FUNCTION (this);
- for (uint8_t lcid = m_lastAllocatedId; lcid != m_lastAllocatedId - 1; ++lcid)
+ const uint8_t MAX_DRB_ID = 32;
+ for (uint8_t drbid = (m_lastAllocatedDrbid + 1) % MAX_DRB_ID;
+ drbid != m_lastAllocatedDrbid;
+ drbid = (drbid + 1) % MAX_DRB_ID)
{
- if (lcid != 0)
+ if (drbid != 0) // 0 is not allowed
{
- if (m_rbMap.find (lcid) == m_rbMap.end ())
+ if (m_drbMap.find (drbid) == m_drbMap.end ())
{
- m_rbMap.insert (std::pair<uint8_t, Ptr<LteRadioBearerInfo> > (lcid, rbi));
- m_lastAllocatedId = lcid;
- return lcid;
+ m_drbMap.insert (std::pair<uint8_t, Ptr<LteDataRadioBearerInfo> > (drbid, drbInfo));
+ drbInfo->m_drbIdentity = drbid;
+ m_lastAllocatedDrbid = drbid;
+ return drbid;
}
}
}
- NS_LOG_WARN ("no more logical channel ids available");
+ NS_FATAL_ERROR ("no more data radio bearer ids available");
return 0;
}
-Ptr<LteRadioBearerInfo>
-UeInfo::GetRadioBearer (uint8_t lcid)
+Ptr<LteDataRadioBearerInfo>
+UeManager::GetDataRadioBearerInfo (uint8_t drbid)
{
- NS_LOG_FUNCTION (this << (uint32_t) lcid);
- NS_ASSERT (0 != lcid);
- std::map<uint8_t, Ptr<LteRadioBearerInfo> >::iterator it = m_rbMap.find (lcid);
- NS_ABORT_IF (it == m_rbMap.end ());
+ NS_LOG_FUNCTION (this << (uint32_t) drbid);
+ NS_ASSERT (0 != drbid);
+ std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ NS_ABORT_IF (it == m_drbMap.end ());
return it->second;
}
void
-UeInfo::RemoveRadioBearer (uint8_t lcid)
+UeManager::RemoveDataRadioBearerInfo (uint8_t drbid)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) drbid);
+ std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ NS_ASSERT_MSG (it != m_drbMap.end (), "request to remove radio bearer with unknown drbid " << drbid);
+ m_drbMap.erase (it);
+}
+
+
+LteRrcSap::RrcConnectionReconfiguration
+UeManager::BuildRrcConnectionReconfiguration ()
+{
+ LteRrcSap::RrcConnectionReconfiguration msg;
+ msg.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
+ msg.haveRadioResourceConfigDedicated = true;
+ msg.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
+ msg.haveMobilityControlInfo = false;
+ msg.haveMeasConfig = false;
+ return msg;
+}
+
+LteRrcSap::RadioResourceConfigDedicated
+UeManager::BuildRadioResourceConfigDedicated ()
+{
+ LteRrcSap::RadioResourceConfigDedicated rrcd;
+
+ if (m_srb1 != 0)
+ {
+ LteRrcSap::SrbToAddMod stam;
+ stam.srbIdentity = m_srb1->m_srbIdentity;
+ stam.logicalChannelConfig = m_srb1->m_logicalChannelConfig;
+ rrcd.srbToAddModList.push_back (stam);
+ }
+
+ for (std::map <uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.begin ();
+ it != m_drbMap.end ();
+ ++it)
+ {
+ LteRrcSap::DrbToAddMod dtam;
+ dtam.epsBearerIdentity = it->second->m_epsBearerIdentity;
+ dtam.drbIdentity = it->second->m_drbIdentity;
+ dtam.rlcConfig = it->second->m_rlcConfig;
+ dtam.logicalChannelIdentity = it->second->m_logicalChannelIdentity;
+ dtam.logicalChannelConfig = it->second->m_logicalChannelConfig;
+ rrcd.drbToAddModList.push_back (dtam);
+ }
+
+ rrcd.havePhysicalConfigDedicated = true;
+ rrcd.physicalConfigDedicated = m_physicalConfigDedicated;
+ return rrcd;
+}
+
+uint8_t
+UeManager::GetNewRrcTransactionIdentifier ()
+{
+ return ++m_lastRrcTransactionIdentifier;
+}
+
+uint8_t
+UeManager::Lcid2Drbid (uint8_t lcid)
+{
+ NS_ASSERT (lcid > 2);
+ return lcid - 2;
+}
+
+uint8_t
+UeManager::Drbid2Lcid (uint8_t drbid)
{
- NS_LOG_FUNCTION (this << (uint32_t) lcid);
- std::map <uint8_t, Ptr<LteRadioBearerInfo> >::iterator it = m_rbMap.find (lcid);
- NS_ASSERT_MSG (it != m_rbMap.end (), "request to remove radio bearer with unknown lcid " << lcid);
- m_rbMap.erase (it);
+ return drbid + 2;
+}
+uint8_t
+UeManager::Lcid2Bid (uint8_t lcid)
+{
+ NS_ASSERT (lcid > 2);
+ return lcid - 2;
+}
+
+uint8_t
+UeManager::Bid2Lcid (uint8_t bid)
+{
+ return bid + 2;
+}
+
+uint8_t
+UeManager::Drbid2Bid (uint8_t drbid)
+{
+ return drbid;
+}
+
+uint8_t
+UeManager::Bid2Drbid (uint8_t bid)
+{
+ return bid;
}
+
+
+void
+UeManager::SwitchToState (State newState)
+{
+ NS_LOG_FUNCTION (this << newState);
+ State oldState = m_state;
+ m_state = newState;
+ NS_LOG_INFO ("IMSI " << m_imsi << " RNTI " << m_rnti << " UeManager " << ToString (oldState) << " --> " << ToString (newState));
+ m_stateTransitionCallback (oldState, newState);
+
+ switch (newState)
+ {
+ case INITIAL_RANDOM_ACCESS:
+ case HANDOVER_JOINING:
+ NS_FATAL_ERROR ("cannot switch to an initial state");
+ break;
+
+ case CONNECTION_SETUP:
+ break;
+
+ case CONNECTED_NORMALLY:
+ {
+ if (m_pendingRrcConnectionReconfiguration == true)
+ {
+ ScheduleRrcConnectionReconfiguration ();
+ }
+ }
+ break;
+
+ case CONNECTION_RECONFIGURATION:
+ break;
+
+ case CONNECTION_REESTABLISHMENT:
+ break;
+
+ case HANDOVER_LEAVING:
+ break;
+
+ default:
+ break;
+ }
+}
+
+
// ///////////////////////////
// eNB RRC methods
@@ -210,7 +758,7 @@
LteEnbRrc::LteEnbRrc ()
: m_x2SapProvider (0),
m_cmacSapProvider (0),
- m_ffMacSchedSapProvider (0),
+ m_rrcSapUser (0),
m_macSapProvider (0),
m_s1SapProvider (0),
m_cphySapProvider (0),
@@ -222,10 +770,12 @@
{
NS_LOG_FUNCTION (this);
m_cmacSapUser = new EnbRrcMemberLteEnbCmacSapUser (this);
- m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<LteEnbRrc> (this);
+ m_rrcSapProvider = new MemberLteEnbRrcSapProvider<LteEnbRrc> (this);
m_x2SapUser = new EpcX2SpecificEpcX2SapUser<LteEnbRrc> (this);
m_s1SapUser = new MemberEpcEnbS1SapUser<LteEnbRrc> (this);
m_cphySapUser = new MemberLteEnbCphySapUser<LteEnbRrc> (this);
+
+
}
@@ -240,7 +790,7 @@
{
NS_LOG_FUNCTION (this);
delete m_cmacSapUser;
- delete m_pdcpSapUser;
+ delete m_rrcSapProvider;
delete m_x2SapUser;
delete m_s1SapUser;
delete m_cphySapUser;
@@ -253,10 +803,10 @@
static TypeId tid = TypeId ("ns3::LteEnbRrc")
.SetParent<Object> ()
.AddConstructor<LteEnbRrc> ()
- .AddAttribute ("UeMap", "List of UE Info by C-RNTI.",
+ .AddAttribute ("UeMap", "List of UeManager by C-RNTI.",
ObjectMapValue (),
MakeObjectMapAccessor (&LteEnbRrc::m_ueMap),
- MakeObjectMapChecker<UeInfo> ())
+ MakeObjectMapChecker<UeManager> ())
.AddAttribute ("DefaultTransmissionMode",
"The default UEs' transmission mode (0: SISO)",
UintegerValue (0), // default tx-mode
@@ -269,50 +819,16 @@
MakeEnumChecker (RLC_SM_ALWAYS, "RlcSmAlways",
RLC_UM_ALWAYS, "RlcUmAlways",
RLC_AM_ALWAYS, "RlcAmAlways",
- PER_BASED, "PacketErrorRateBased"))
+ PER_BASED, "PacketErrorRateBased"))
+ .AddAttribute ("SystemInformationPeriodicity",
+ "The interval for sending system information",
+ TimeValue (MilliSeconds (80)),
+ MakeTimeAccessor (&LteEnbRrc::m_systemInformationPeriodicity),
+ MakeTimeChecker ())
;
return tid;
}
-uint16_t
-LteEnbRrc::GetLastAllocatedRnti () const
-{
- NS_LOG_FUNCTION (this);
- return m_lastAllocatedRnti;
-}
-std::map<uint16_t,Ptr<UeInfo> > LteEnbRrc::GetUeMap (void) const
-{
- return m_ueMap;
-}
-
-void LteEnbRrc::SetUeMap (std::map<uint16_t,Ptr<UeInfo> > ueMap)
-{
- this->m_ueMap = ueMap;
-}
-
-
-void
-LteEnbRrc::SetLastAllocatedRnti (uint16_t lastAllocatedRnti)
-{
- NS_LOG_FUNCTION (this << lastAllocatedRnti);
- m_lastAllocatedRnti = lastAllocatedRnti;
-}
-
-
-void
-LteEnbRrc::SetLteEnbCphySapProvider (LteEnbCphySapProvider * s)
-{
- NS_LOG_FUNCTION (this << s);
- m_cphySapProvider = s;
-}
-
-LteEnbCphySapUser*
-LteEnbRrc::GetLteEnbCphySapUser ()
-{
- NS_LOG_FUNCTION (this);
- return m_cphySapUser;
-}
-
void
LteEnbRrc::SetEpcX2SapProvider (EpcX2SapProvider * s)
{
@@ -327,7 +843,6 @@
return m_x2SapUser;
}
-
void
LteEnbRrc::SetLteEnbCmacSapProvider (LteEnbCmacSapProvider * s)
{
@@ -343,13 +858,19 @@
}
void
-LteEnbRrc::SetFfMacSchedSapProvider (FfMacSchedSapProvider * s)
+LteEnbRrc::SetLteEnbRrcSapUser (LteEnbRrcSapUser * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_rrcSapUser = s;
+}
+
+LteEnbRrcSapProvider*
+LteEnbRrc::GetLteEnbRrcSapProvider ()
{
NS_LOG_FUNCTION (this);
- m_ffMacSchedSapProvider = s;
+ return m_rrcSapProvider;
}
-
void
LteEnbRrc::SetLteMacSapProvider (LteMacSapProvider * s)
{
@@ -370,10 +891,28 @@
return m_s1SapUser;
}
-LtePdcpSapProvider*
-LteEnbRrc::GetLtePdcpSapProvider (uint16_t rnti, uint8_t lcid)
+void
+LteEnbRrc::SetLteEnbCphySapProvider (LteEnbCphySapProvider * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_cphySapProvider = s;
+}
+
+LteEnbCphySapUser*
+LteEnbRrc::GetLteEnbCphySapUser ()
{
- return GetUeInfo (rnti)->GetRadioBearer (lcid)->m_pdcp->GetLtePdcpSapProvider ();
+ NS_LOG_FUNCTION (this);
+ return m_cphySapUser;
+}
+
+Ptr<UeManager>
+LteEnbRrc::GetUeManager (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) rnti);
+ NS_ASSERT (0 != rnti);
+ std::map<uint16_t, Ptr<UeManager> >::iterator it = m_ueMap.find (rnti);
+ NS_ASSERT_MSG (it != m_ueMap.end (), "RNTI " << rnti << " not found in eNB with cellId " << m_cellId);
+ return it->second;
}
void
@@ -384,69 +923,254 @@
m_cmacSapProvider->ConfigureMac (ulBandwidth, dlBandwidth);
m_cphySapProvider->SetBandwidth (ulBandwidth, dlBandwidth);
m_cphySapProvider->SetEarfcn (ulEarfcn, dlEarfcn);
+ m_dlEarfcn = dlEarfcn;
+ m_ulEarfcn = ulEarfcn;
+ m_dlBandwidth = dlBandwidth;
+ m_ulBandwidth = ulBandwidth;
m_cellId = cellId;
m_cphySapProvider->SetCellId (cellId);
+ LteRrcSap::MasterInformationBlock mib;
+ mib.dlBandwidth = m_dlBandwidth;
+ m_cphySapProvider->SetMasterInformationBlock (mib);
m_configured = true;
+
+ // the first time System Information is sent
+ Simulator::Schedule (MilliSeconds (16), &LteEnbRrc::SendSystemInformation, this);
+}
+
+
+void
+LteEnbRrc::SetCellId (uint16_t cellId)
+{
+ m_cellId = cellId;
+}
+
+bool
+LteEnbRrc::SendData (Ptr<Packet> packet)
+{
+ NS_LOG_FUNCTION (this << packet);
+
+ EpsBearerTag tag;
+ bool found = packet->RemovePacketTag (tag);
+ NS_ASSERT_MSG (found, "no EpsBearerTag found in packet to be sent");
+ Ptr<UeManager> ueManager = GetUeManager (tag.GetRnti ());
+ ueManager->SendData (tag.GetBid (), packet);
+
+ return true;
+}
+
+void
+LteEnbRrc::SetForwardUpCallback (Callback <void, Ptr<Packet> > cb)
+{
+ m_forwardUpCallback = cb;
}
-uint16_t
-LteEnbRrc::DoRecvConnectionRequest (uint64_t imsi)
+
+void
+LteEnbRrc::SendHandoverRequest (uint16_t rnti, uint16_t cellId)
{
- NS_LOG_FUNCTION (this);
- // no Call Admission Control for now
- uint16_t rnti = AddUe ();
- std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
- NS_ASSERT_MSG (it != m_ueMap.end (), "RNTI " << rnti << " not found in eNB with cellId " << m_cellId);
- it->second->SetImsi (imsi);
+ NS_LOG_FUNCTION (this << rnti << cellId);
+ NS_LOG_LOGIC ("Request to send HANDOVER REQUEST");
+ NS_ASSERT (m_configured);
+
+ Ptr<UeManager> ueManager = GetUeManager (rnti);
- if (m_s1SapProvider != 0)
- {
- m_s1SapProvider->InitialUeMessage (imsi, rnti);
- }
+ EpcX2SapProvider::HandoverRequestParams params;
+ params.oldEnbUeX2apId = rnti;
+ params.cause = EpcX2SapProvider::HandoverDesirableForRadioReason;
+ params.sourceCellId = m_cellId;
+ params.targetCellId = cellId;
+ params.ueAggregateMaxBitRateDownlink = 200 * 1000;
+ params.ueAggregateMaxBitRateUplink = 100 * 1000;
+ params.bearers = ueManager->GetErabList ();
+
+ LteRrcSap::HandoverPreparationInfo hpi;
+ hpi.asConfig.sourceUeIdentity = rnti;
+ hpi.asConfig.sourceDlCarrierFreq = m_dlEarfcn;
+ hpi.asConfig.sourceRadioResourceConfig = ueManager->GetRadioResourceConfigForHandoverPreparationInfo ();
+ params.rrcContext = m_rrcSapUser->EncodeHandoverPreparationInformation (hpi);
- // send RRC connection setup
- LteUeConfig_t ueConfig;
- ueConfig.m_rnti = rnti;
- ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
- ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
- ueConfig.m_reconfigureFlag = false;
- Ptr<LteUeRrc> ueRrc = GetUeRrcByImsi (imsi);
- ueRrc->DoRecvConnectionSetup (ueConfig);
-
- // configure MAC (and scheduler)
- FfMacCschedSapProvider::CschedUeConfigReqParameters req;
- req.m_rnti = rnti;
- req.m_transmissionMode = (*it).second->GetTransmissionMode ();
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+ NS_LOG_LOGIC ("rrcContext = " << params.rrcContext);
+
+ m_x2SapProvider->SendHandoverRequest (params);
+}
- // configure PHY
- m_cphySapProvider->SetTransmissionMode (rnti, (*it).second->GetTransmissionMode ());
- m_cphySapProvider->SetSrsConfigurationIndex (rnti, (*it).second->GetSrsConfigurationIndex ());
+void
+LteEnbRrc::DoCompleteSetupUe (uint16_t rnti, LteEnbRrcSapProvider::CompleteSetupUeParameters params)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetUeManager (rnti)->CompleteSetupUe (params);
+}
- return rnti;
+void
+LteEnbRrc::DoRecvRrcConnectionRequest (uint16_t rnti, LteRrcSap::RrcConnectionRequest msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetUeManager (rnti)->RecvRrcConnectionRequest (msg);
+}
+
+void
+LteEnbRrc::DoRecvRrcConnectionSetupCompleted (uint16_t rnti, LteRrcSap::RrcConnectionSetupCompleted msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetUeManager (rnti)->RecvRrcConnectionSetupCompleted (msg);
}
void
-LteEnbRrc::DoRecvConnectionSetupCompleted (uint16_t rnti)
+LteEnbRrc::DoRecvRrcConnectionReconfigurationCompleted (uint16_t rnti, LteRrcSap::RrcConnectionReconfigurationCompleted msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetUeManager (rnti)->RecvRrcConnectionReconfigurationCompleted (msg);
+}
+
+void
+LteEnbRrc::DoRecvRrcConnectionReestablishmentRequest (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentRequest msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetUeManager (rnti)->RecvRrcConnectionReestablishmentRequest (msg);
+}
+
+void
+LteEnbRrc::DoRecvRrcConnectionReestablishmentComplete (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentComplete msg)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ GetUeManager (rnti)->RecvRrcConnectionReestablishmentComplete (msg);
+}
+
+
+void
+LteEnbRrc::DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters request)
+{
+ EpcEnbS1SapProvider::S1BearerSetupRequestParameters response;
+ Ptr<UeManager> ueManager = GetUeManager (request.rnti);
+ response.rnti = request.rnti;
+ response.bid = ueManager->SetupDataRadioBearer (request.bearer);
+ response.teid = request.teid;
+ if (m_s1SapProvider)
+ {
+ m_s1SapProvider->S1BearerSetupRequest (response);
+ }
+ ueManager->ScheduleRrcConnectionReconfiguration ();
+}
+
+
+void
+LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params)
{
NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST");
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+
+ uint16_t rnti = AddUe (UeManager::HANDOVER_JOINING);
+ Ptr<UeManager> ueManager = GetUeManager (rnti);
+
+ for (std::vector <EpcX2Sap::ErabToBeSetupItem>::iterator it = params.bearers.begin ();
+ it != params.bearers.end ();
+ ++it)
+ {
+ ueManager->SetupDataRadioBearer (it->erabLevelQosParameters);
+ }
+
+ LteRrcSap::RrcConnectionReconfiguration handoverCommand = ueManager->GetHandoverCommand ();
+ Ptr<Packet> encodedHandoverCommand = m_rrcSapUser->EncodeHandoverCommand (handoverCommand);
+
+ NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK");
+
+ EpcX2SapProvider::HandoverRequestAckParams ackParams;
+ ackParams.oldEnbUeX2apId = params.oldEnbUeX2apId;
+ ackParams.newEnbUeX2apId = rnti;
+ ackParams.sourceCellId = params.sourceCellId;
+ ackParams.targetCellId = params.targetCellId;
+ ackParams.rrcContext = encodedHandoverCommand;
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << ackParams.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("newEnbUeX2apId = " << ackParams.newEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << ackParams.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << ackParams.targetCellId);
+
+ m_x2SapProvider->SendHandoverRequestAck (ackParams);
}
void
-LteEnbRrc::DoRecvConnectionReconfigurationCompleted (uint16_t rnti)
+LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params)
{
NS_LOG_FUNCTION (this);
+
+ NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK");
+
+ NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
+ NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
+ NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
+ NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+
+ uint16_t rnti = params.oldEnbUeX2apId;
+ Ptr<UeManager> ueManager = GetUeManager (rnti);
+
+ // note: the Handover command from the target eNB to the source eNB
+ // is expected to be sent transparently tothe UE; however, here we
+ // decode the message and eventually reencode it. This way we can
+ // support both a real RRC protocol implementation and an ideal one
+ // without actual RRC protocol encoding.
+
+ Ptr<Packet> encodedHandoverCommand = params.rrcContext;
+ LteRrcSap::RrcConnectionReconfiguration handoverCommand = m_rrcSapUser->DecodeHandoverCommand (encodedHandoverCommand);
+ ueManager->SendHandoverCommand (handoverCommand);
+
}
+uint16_t
+LteEnbRrc::DoAllocateTemporaryCellRnti ()
+{
+ NS_LOG_FUNCTION (this);
+ return AddUe (UeManager::INITIAL_RANDOM_ACCESS);
+}
+
+void
+LteEnbRrc::DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams)
+{
+ Ptr<UeManager> ueManager = GetUeManager (cmacParams.m_rnti);
+ ueManager->CmacUeConfigUpdateInd (cmacParams);
+}
+
+void
+LteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) rnti);
+ NS_FATAL_ERROR ("not implemented");
+}
+
+
+
uint16_t
-LteEnbRrc::AddUe ()
+LteEnbRrc::AddUe (UeManager::State state)
{
NS_LOG_FUNCTION (this);
+ bool found = false;
+ uint16_t rnti;
+ for (rnti = m_lastAllocatedRnti;
+ (rnti != m_lastAllocatedRnti - 1) && (!found);
+ ++rnti)
+ {
+ if ((rnti != 0) && (m_ueMap.find (rnti) == m_ueMap.end ()))
+ {
+ found = true;
+ break;
+ }
+ }
- uint16_t rnti = CreateUeInfo (); // side effect: create UeInfo for this UE
- NS_ASSERT_MSG (rnti != 0, "CreateUeInfo returned RNTI==0");
- m_cmacSapProvider->AddUe (rnti);
- m_cphySapProvider->AddUe (rnti);
+ NS_ASSERT_MSG (found, "no more RNTIs available (do you have more than 65535 UEs in a cell?)");
+ m_lastAllocatedRnti = rnti;
+ Ptr<UeManager> ueManager = CreateObject<UeManager> (this, rnti, state);
+ m_ueMap.insert (std::pair<uint16_t, Ptr<UeManager> > (rnti, ueManager));
+ NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueManager->GetSrsConfigurationIndex ());
return rnti;
}
@@ -454,9 +1178,14 @@
LteEnbRrc::RemoveUe (uint16_t rnti)
{
NS_LOG_FUNCTION (this << (uint32_t) rnti);
- RemoveUeInfo (rnti);
- NS_FATAL_ERROR ("missing RemoveUe method in CMAC SAP");
-}
+ NS_FATAL_ERROR ("I though this method was unused so far...");
+ std::map <uint16_t, Ptr<UeManager> >::iterator it = m_ueMap.find (rnti);
+ NS_ASSERT_MSG (it != m_ueMap.end (), "request to remove UE info with unknown rnti " << rnti);
+ uint16_t srsCi = (*it).second->GetSrsConfigurationIndex ();
+ m_ueMap.erase (it);
+ // need to do this after UeManager has been deleted
+ RemoveSrsConfigurationIndex (srsCi);
+ }
TypeId
LteEnbRrc::GetRlcType (EpsBearer bearer)
@@ -493,268 +1222,14 @@
}
-void
-LteEnbRrc::DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters request)
-{
- EpcEnbS1SapProvider::S1BearerSetupRequestParameters response;
- std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (request.rnti);
- NS_ASSERT_MSG (it != m_ueMap.end (), "unknown RNTI");
- response.rnti = request.rnti;
- response.lcid = SetupRadioBearer (response.rnti, request.bearer, request.teid);
- NS_ASSERT_MSG (response.lcid > 0, "SetupRadioBearer() returned LCID == 0. Too many LCs?");
- response.teid = request.teid;
- if (m_s1SapProvider)
- {
- m_s1SapProvider->S1BearerSetupRequest (response);
- }
-}
-
-uint8_t
-LteEnbRrc::SetupRadioBearer (uint16_t rnti, EpsBearer bearer, uint32_t teid)
-{
- NS_LOG_FUNCTION (this << (uint32_t) rnti);
-
- TypeId rlcTypeId = GetRlcType (bearer);
- Ptr<UeInfo> ueInfo = GetUeInfo (rnti);
-
- // create RLC instance
-
- ObjectFactory rlcObjectFactory;
- rlcObjectFactory.SetTypeId (rlcTypeId);
- Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
- rlc->SetLteMacSapProvider (m_macSapProvider);
- rlc->SetRnti (rnti);
-
- Ptr<LteRadioBearerInfo> rbInfo = CreateObject<LteRadioBearerInfo> ();
- rbInfo->m_epsBearer = bearer;
- rbInfo->m_teid = teid;
- rbInfo->m_rlc = rlc;
- uint8_t lcid = ueInfo->AddRadioBearer (rbInfo);
- if (lcid == 0)
- {
- NS_LOG_WARN ("cannot setup radio bearer");
- return 0;
- }
- rlc->SetLcId (lcid);
-
- // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
- // if we are using RLC/SM we don't care of anything above RLC
- if (rlcTypeId != LteRlcSm::GetTypeId ())
- {
- Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
- pdcp->SetRnti (rnti);
- pdcp->SetLcId (lcid);
- pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
- pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
- rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
- rbInfo->m_pdcp = pdcp;
- }
-
- LteEnbCmacSapProvider::LcInfo lcinfo;
- lcinfo.rnti = rnti;
- lcinfo.lcId = lcid;
- lcinfo.lcGroup = 0; // TBD
- lcinfo.qci = bearer.qci;
- lcinfo.isGbr = bearer.IsGbr ();
- lcinfo.mbrUl = bearer.gbrQosInfo.mbrUl;
- lcinfo.mbrDl = bearer.gbrQosInfo.mbrDl;
- lcinfo.gbrUl = bearer.gbrQosInfo.gbrUl;
- lcinfo.gbrDl = bearer.gbrQosInfo.gbrDl;
- m_cmacSapProvider->AddLc (lcinfo, rlc->GetLteMacSapUser ());
-
- GetUeRrcByRnti (rnti)->SetupRadioBearer (bearer, rlcTypeId, lcid);
-
- return lcid;
-}
-
-void
-LteEnbRrc::ReleaseRadioBearer (uint16_t rnti, uint8_t lcId)
-{
- NS_LOG_FUNCTION (this << (uint32_t) rnti << (uint32_t) lcId);
- Ptr<UeInfo> ueInfo = GetUeInfo (rnti);
- ueInfo->RemoveRadioBearer (lcId);
-}
-
-
-
-bool
-LteEnbRrc::Send (Ptr<Packet> packet)
-{
- NS_LOG_FUNCTION (this << packet);
-
- LteRadioBearerTag tag;
- bool found = packet->RemovePacketTag (tag);
- NS_ASSERT (found);
-
- LtePdcpSapProvider::TransmitRrcPduParameters params;
- params.rrcPdu = packet;
- params.rnti = tag.GetRnti ();
- params.lcid = tag.GetLcid ();
- LtePdcpSapProvider* pdcpSapProvider = GetLtePdcpSapProvider (tag.GetRnti (), tag.GetLcid ());
- pdcpSapProvider->TransmitRrcPdu (params);
-
- return true;
-}
-
-void
-LteEnbRrc::SetForwardUpCallback (Callback <void, Ptr<Packet> > cb)
-{
- m_forwardUpCallback = cb;
-}
-//
-// User API
-//
-void
-LteEnbRrc::SendHandoverRequest (uint16_t rnti, uint16_t cellId)
-{
- NS_LOG_FUNCTION (this << rnti << cellId);
- NS_LOG_LOGIC ("Request to send HANDOVER REQUEST");
-
- std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
- NS_ASSERT_MSG (it != m_ueMap.end (), "RNTI " << rnti << " not found in eNB with cellId " << m_cellId);
-
- EpcX2SapProvider::HandoverRequestParams params;
- params.oldEnbUeX2apId = rnti;
- params.cause = EpcX2SapProvider::HandoverDesirableForRadioReason;
- params.sourceCellId = m_cellId;
- params.targetCellId = cellId;
- params.ueAggregateMaxBitRateDownlink = 200 * 1000;
- params.ueAggregateMaxBitRateUplink = 100 * 1000;
-
- std::string rrcData ("abcdefghijklmnopqrstuvwxyz");
- params.rrcContext = Create<Packet> ((uint8_t const *) rrcData.data (), rrcData.length ());
-
- NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
- NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
- NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
- NS_LOG_LOGIC ("rrcContext = " << params.rrcContext << " : " << rrcData);
-
- m_x2SapProvider->SendHandoverRequest (params);
-}
-
-
-//
-// X2 User SAP
-//
-void
-LteEnbRrc::DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params)
-{
- NS_LOG_FUNCTION (this);
-
- NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST");
-
- NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
- NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
- NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
-
- // this crashes, apparently EpcX2 is not correctly filling in the params yet
- // uint8_t rrcData [100];
- // params.rrcContext->CopyData (rrcData, params.rrcContext->GetSize ());
- // NS_LOG_LOGIC ("rrcContext = " << rrcData);
-
- uint16_t rnti = AddUe ();
-
- for (std::vector <EpcX2Sap::ErabToBeSetupItem>::iterator it = params.bearers.begin ();
- it != params.bearers.end ();
- ++it)
- {
- SetupRadioBearer (rnti, it->erabLevelQosParameters, it->gtpTeid);
- }
-
- NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK");
-
- EpcX2SapProvider::HandoverRequestAckParams ackParams;
- ackParams.oldEnbUeX2apId = params.oldEnbUeX2apId;
- ackParams.newEnbUeX2apId = params.oldEnbUeX2apId + 100;
- ackParams.sourceCellId = params.sourceCellId;
- ackParams.targetCellId = params.targetCellId;
-
- NS_LOG_LOGIC ("oldEnbUeX2apId = " << ackParams.oldEnbUeX2apId);
- NS_LOG_LOGIC ("newEnbUeX2apId = " << ackParams.newEnbUeX2apId);
- NS_LOG_LOGIC ("sourceCellId = " << ackParams.sourceCellId);
- NS_LOG_LOGIC ("targetCellId = " << ackParams.targetCellId);
-
- m_x2SapProvider->SendHandoverRequestAck (ackParams);
-}
-
-void
-LteEnbRrc::DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params)
-{
- NS_LOG_FUNCTION (this);
-
- NS_LOG_LOGIC ("Recv X2 message: HANDOVER REQUEST ACK");
-
- NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
- NS_LOG_LOGIC ("newEnbUeX2apId = " << params.newEnbUeX2apId);
- NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
- NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
-}
-
-
-void
-LteEnbRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params)
-{
- NS_LOG_FUNCTION (this);
- // this tag is needed by the EpcEnbApplication to determine the S1 bearer that corresponds to this radio bearer
- LteRadioBearerTag tag;
- tag.SetRnti (params.rnti);
- tag.SetLcid (params.lcid);
- params.rrcPdu->AddPacketTag (tag);
- m_forwardUpCallback (params.rrcPdu);
-}
-
-
-
-void
-LteEnbRrc::DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success)
-{
- NS_LOG_FUNCTION (this << (uint32_t) rnti);
- NS_FATAL_ERROR ("not implemented");
-}
-
-
-
-// /////////////////////////////////////////
-// management of multiple UE info instances
-// /////////////////////////////////////////
-
// from 3GPP TS 36.213 table 8.2-1 UE Specific SRS Periodicity
-#define SRS_ENTRIES 9
+const uint8_t SRS_ENTRIES = 9;
uint16_t g_srsPeriodicity[SRS_ENTRIES] = {0, 2, 5, 10, 20, 40, 80, 160, 320};
uint16_t g_srsCiLow[SRS_ENTRIES] = {0, 0, 2, 7, 17, 37, 77, 157, 317};
uint16_t g_srsCiHigh[SRS_ENTRIES] = {0, 1, 6, 16, 36, 76, 156, 316, 636};
-void
-LteEnbRrc::SetCellId (uint16_t cellId)
-{
- m_cellId = cellId;
-}
-
-uint16_t
-LteEnbRrc::CreateUeInfo ()
-{
- NS_LOG_FUNCTION (this);
- for (uint16_t rnti = m_lastAllocatedRnti; rnti != m_lastAllocatedRnti - 1; ++rnti)
- {
- if (rnti != 0)
- {
- if (m_ueMap.find (rnti) == m_ueMap.end ())
- {
- m_lastAllocatedRnti = rnti;
- Ptr<UeInfo> ueInfo = CreateObject<UeInfo> ();
- ueInfo->SetSrsConfigurationIndex (GetNewSrsConfigurationIndex ());
- m_ueMap.insert (std::pair<uint16_t, Ptr<UeInfo> > (rnti, ueInfo));
- NS_LOG_DEBUG (this << " New UE RNTI " << rnti << " cellId " << m_cellId << " srs CI " << ueInfo->GetSrsConfigurationIndex ());
- return rnti;
- }
- }
- }
-
- return 0;
-}
-
uint16_t
LteEnbRrc::GetNewSrsConfigurationIndex ()
{
@@ -773,28 +1248,27 @@
NS_LOG_DEBUG (this << " SRS p " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " set " << m_ueSrsConfigurationIndexSet.size ());
if (m_ueSrsConfigurationIndexSet.size () == g_srsPeriodicity[m_srsCurrentPeriodicityId])
{
-// NS_LOG_DEBUG (this << " SRS reconfigure CIs " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " to " << g_srsPeriodicity[m_srsCurrentPeriodicityId+1] << " at " << Simulator::Now ());
+ NS_LOG_DEBUG (this << " SRS reconfigure CIs " << g_srsPeriodicity[m_srsCurrentPeriodicityId] << " to " << g_srsPeriodicity[m_srsCurrentPeriodicityId+1] << " at " << Simulator::Now ());
// increase the current periocity for having enough CIs
m_ueSrsConfigurationIndexSet.clear ();
m_srsCurrentPeriodicityId++;
NS_ASSERT (m_srsCurrentPeriodicityId < SRS_ENTRIES);
// update all the UE's CI
uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId];
- std::map<uint16_t, Ptr<UeInfo> >::iterator it;
+ std::map<uint16_t, Ptr<UeManager> >::iterator it;
for (it = m_ueMap.begin (); it != m_ueMap.end (); it++)
{
(*it).second->SetSrsConfigurationIndex (srcCi);
m_ueSrsConfigurationIndexSet.insert (srcCi);
m_lastAllocatedConfigurationIndex = srcCi;
+
+ // update UeManager and trigger/update RRC connection reconfiguration
+ (*it).second->SetSrsConfigurationIndex (srcCi);
+
+ // configure PHY
+ m_cphySapProvider->SetSrsConfigurationIndex ((*it).first, srcCi);
+
srcCi++;
- // send update to peer RRC
- LteUeConfig_t ueConfig;
- ueConfig.m_rnti = (*it).first;
- ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
- ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
- ueConfig.m_reconfigureFlag = true;
- NS_LOG_DEBUG (this << "\t rnti "<<ueConfig.m_rnti<< " CI " << ueConfig.m_srsConfigurationIndex);
- PropagateRrcConnectionReconfiguration (ueConfig);
}
m_ueSrsConfigurationIndexSet.insert (m_lastAllocatedConfigurationIndex + 1);
m_lastAllocatedConfigurationIndex++;
@@ -853,162 +1327,57 @@
{
// update all the UE's CI
uint16_t srcCi = g_srsCiLow[m_srsCurrentPeriodicityId];
- std::map<uint16_t, Ptr<UeInfo> >::iterator it;
+ std::map<uint16_t, Ptr<UeManager> >::iterator it;
for (it = m_ueMap.begin (); it != m_ueMap.end (); it++)
{
(*it).second->SetSrsConfigurationIndex (srcCi);
m_ueSrsConfigurationIndexSet.insert (srcCi);
m_lastAllocatedConfigurationIndex = srcCi;
+
+
+ // update UeManager and trigger/update RRC connection reconfiguration
+ (*it).second->SetSrsConfigurationIndex (srcCi);
+
+ // configure PHY
+ m_cphySapProvider->SetSrsConfigurationIndex ((*it).first, (*it).second->GetSrsConfigurationIndex ());
+
srcCi++;
- // send update to peer RRC
- LteUeConfig_t ueConfig;
- ueConfig.m_rnti = (*it).first;
- ueConfig.m_transmissionMode = (*it).second->GetTransmissionMode ();
- ueConfig.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
- ueConfig.m_reconfigureFlag = false;
- NS_LOG_DEBUG (this << "\t rnti "<<ueConfig.m_rnti<< " CI " << ueConfig.m_srsConfigurationIndex);
-
- // avoid multiple reconfiguration during initialization
- if (Simulator::Now ().GetNanoSeconds () != 0)
- {
- PropagateRrcConnectionReconfiguration (ueConfig);
- }
}
}
}
}
-Ptr<UeInfo>
-LteEnbRrc::GetUeInfo (uint16_t rnti)
+uint8_t
+LteEnbRrc::GetLogicalChannelGroup (EpsBearer bearer)
{
- NS_LOG_FUNCTION (this << (uint32_t) rnti);
- NS_ASSERT (0 != rnti);
- std::map<uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
- NS_ABORT_IF (it == m_ueMap.end ());
- return it->second;
+ if (bearer.IsGbr ())
+ {
+ return 1;
+ }
+ else
+ {
+ return 2;
+ }
+}
+
+uint8_t
+LteEnbRrc::GetLogicalChannelPriority (EpsBearer bearer)
+{
+ return bearer.qci;
}
void
-LteEnbRrc::RemoveUeInfo (uint16_t rnti)
-{
- NS_LOG_FUNCTION (this << (uint32_t) rnti);
- NS_FATAL_ERROR ("I though this method was unused so far...");
- std::map <uint16_t, Ptr<UeInfo> >::iterator it = m_ueMap.find (rnti);
- NS_ASSERT_MSG (it != m_ueMap.end (), "request to remove UE info with unknown rnti " << rnti);
- RemoveSrsConfigurationIndex ((*it).second->GetSrsConfigurationIndex ());
- m_ueMap.erase (it);
- // remove SRS configuration index
-}
-
-
-void
-LteEnbRrc::DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams)
-{
- NS_LOG_FUNCTION (this);
- // at this stage used only by the scheduler for updating txMode
-
- LteUeConfig_t rrcParams;
- rrcParams.m_rnti = cmacParams.m_rnti;
- rrcParams.m_reconfigureFlag = true;
- rrcParams.m_transmissionMode = cmacParams.m_transmissionMode;
-
- // for now, the SRS CI is passed every time, so we need to overwrite the value
- std::map<uint16_t, Ptr<UeInfo> >::iterator it;
- it = m_ueMap.find (cmacParams.m_rnti);
- NS_ASSERT_MSG (it!=m_ueMap.end (), "Unable to find UeInfo");
- rrcParams.m_srsConfigurationIndex = (*it).second->GetSrsConfigurationIndex ();
-
- // update Tx Mode info at eNB
- (*it).second->SetTransmissionMode (cmacParams.m_transmissionMode);
-
- rrcParams.m_reconfigureFlag = true;
- PropagateRrcConnectionReconfiguration (rrcParams);
-}
-
-
-void
-LteEnbRrc::PropagateRrcConnectionReconfiguration (LteUeConfig_t params)
-{
-
- Ptr<LteUeRrc> ueRrc = GetUeRrcByRnti (params.m_rnti);
- ueRrc->DoRecvConnectionReconfiguration (params);
-
- // configure MAC (and scheduler)
- LteEnbCmacSapProvider::UeConfig req;
- req.m_rnti = params.m_rnti;
- req.m_transmissionMode = params.m_transmissionMode;
- m_cmacSapProvider->UeUpdateConfigurationReq (req);
-
- // configure PHY
- m_cphySapProvider->SetTransmissionMode (params.m_rnti, params.m_transmissionMode);
- m_cphySapProvider->SetSrsConfigurationIndex (params.m_rnti, params.m_srsConfigurationIndex);
-}
-
-
-Ptr<LteUeRrc>
-LteEnbRrc::GetUeRrcByImsi (uint64_t imsi)
+LteEnbRrc::SendSystemInformation ()
{
NS_LOG_FUNCTION (this);
-
- NodeList::Iterator listEnd = NodeList::End ();
- bool found = false;
- for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
- {
- Ptr<Node> node = *i;
- int nDevs = node->GetNDevices ();
- for (int j = 0; j < nDevs; j++)
- {
- Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
- if (!ueDev)
- {
- continue;
- }
- else
- {
- if (ueDev->GetImsi () == imsi)
- {
- found = true;
- return ueDev->GetRrc ();
- }
- }
- }
- }
- NS_ASSERT_MSG (found , " Unable to find UE with IMSI =" << imsi);
- return 0;
-}
-
-
-
-Ptr<LteUeRrc>
-LteEnbRrc::GetUeRrcByRnti (uint16_t rnti)
-{
- NS_LOG_FUNCTION (this);
-
- NodeList::Iterator listEnd = NodeList::End ();
- bool found = false;
- for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
- {
- Ptr<Node> node = *i;
- int nDevs = node->GetNDevices ();
- for (int j = 0; j < nDevs; j++)
- {
- Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
- if (!ueDev)
- {
- continue;
- }
- else
- {
- Ptr<LteUeRrc> rrc = ueDev->GetRrc ();
- if ((rrc->GetRnti () == rnti) && (rrc->GetCellId () == m_cellId))
- {
- return rrc;
- }
- }
- }
- }
- NS_ASSERT_MSG (found , " Unable to find UE with RNTI=" << rnti << " cellId=" << m_cellId);
- return 0;
+ // for simplicity, we use the same periodicity for all sibs
+ // note that in real systems the periodicy of each sibs could be different
+ LteRrcSap::SystemInformation si;
+ si.haveSib2 = true;
+ si.sib2.freqInfo.ulCarrierFreq = m_ulEarfcn;
+ si.sib2.freqInfo.ulBandwidth = m_ulBandwidth;
+ m_rrcSapUser->SendSystemInformation (si);
+ Simulator::Schedule (m_systemInformationPeriodicity, &LteEnbRrc::SendSystemInformation, this);
}
} // namespace ns3
--- a/src/lte/model/lte-enb-rrc.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-enb-rrc.h Tue Oct 30 16:02:07 2012 +0100
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ * Copyright (c) 2011, 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
@@ -23,15 +23,18 @@
#ifndef LTE_ENB_RRC_H
#define LTE_ENB_RRC_H
-#include "ns3/object.h"
-#include "ns3/packet.h"
-#include "ns3/lte-enb-cmac-sap.h"
-#include "ns3/lte-mac-sap.h"
-#include "ns3/ff-mac-sched-sap.h"
-#include "ns3/lte-pdcp-sap.h"
-#include "ns3/epc-x2-sap.h"
+#include <ns3/nstime.h>
+#include <ns3/object.h>
+#include <ns3/packet.h>
+#include <ns3/lte-enb-cmac-sap.h>
+#include <ns3/lte-mac-sap.h>
+#include <ns3/ff-mac-sched-sap.h>
+#include <ns3/lte-pdcp-sap.h>
+#include <ns3/epc-x2-sap.h>
#include <ns3/epc-enb-s1-sap.h>
#include <ns3/lte-enb-cphy-sap.h>
+#include <ns3/lte-rrc-sap.h>
+#include <ns3/traced-callback.h>
#include <map>
#include <set>
@@ -39,79 +42,285 @@
namespace ns3 {
class LteRadioBearerInfo;
+class LteSignalingRadioBearerInfo;
+class LteDataRadioBearerInfo;
class EpcEnbS1SapUser;
class EpcEnbS1SapProvider;
class LteUeRrc;
+class LteEnbRrc;
/**
* Manages all the radio bearer information possessed by the ENB RRC for a single UE
*
*/
-class UeInfo : public Object
+class UeManager : public Object
{
+ friend class LtePdcpSpecificLtePdcpSapUser<UeManager>;
+
public:
- /**
- *
- *
- * \param radioBearerInfo
- *
- * \return the allocated logical channel id; 0 is returned if it is not possible to allocate a channel id (e.g., id space exausted).
- */
- uint8_t AddRadioBearer (Ptr<LteRadioBearerInfo> radioBearerInfo);
-
- /**
- *
- *
- * \param uint8_t the logical channel id
- *
- * \return the LteRadioBearerInfo of the selected radio bearer
- */
- Ptr<LteRadioBearerInfo> GetRadioBearer (uint8_t lcid);
/**
- * delete the entry of the given radio bearer
+ * The state of the UeManager at the eNB RRC
+ *
+ */
+ enum State
+ {
+ INITIAL_RANDOM_ACCESS = 0,
+ CONNECTION_SETUP,
+ CONNECTED_NORMALLY,
+ CONNECTION_RECONFIGURATION,
+ CONNECTION_REESTABLISHMENT,
+ HANDOVER_JOINING,
+ HANDOVER_LEAVING,
+ NUM_STATES
+ };
+
+ UeManager ();
+
+ /**
+ * UeManager constructor
+ *
+ * \param rrc pointer to the LteEnbRrc holding this UeManager
+ * \param rnti RNTI of the UE
+ * \param s initial state of the UeManager
+ *
+ * \return
+ */
+ UeManager (Ptr<LteEnbRrc> rrc, uint16_t rnti, State s);
+
+ virtual ~UeManager (void);
+
+ // inherited from Object
+protected:
+ virtual void DoDispose ();
+public:
+ static TypeId GetTypeId (void);
+
+
+ /**
+ * Setup a new data radio bearer, including both the configuration
+ * within the eNB and the necessary RRC signaling with the UE
+ *
+ * \param bearer
+ *
+ * \return the EPS Bearer Id
+ */
+ uint8_t SetupDataRadioBearer (EpsBearer bearer);
+
+ /**
*
- * \param lcid the logical channel id of the radio bearer
+ * Release a given radio bearer
+ *
+ * \param drbid the data radio bearer id of the bearer to be released
+ */
+ void ReleaseDataRadioBearer (uint8_t drbid);
+
+ /**
+ * schedule an RRC Connection Reconfiguration procedure with the UE
+ *
*/
- void RemoveRadioBearer (uint8_t lcid);
+ void ScheduleRrcConnectionReconfiguration ();
+
+ /**
+ * In the X2-based handover procedure, at the source eNB, trigger
+ * handover by sending to the UE a RRC Connection
+ * Reconfiguration message including Mobility Control Info
+ *
+ * \param rcr the RrcConnectionReconfiguration message including the
+ * Mobility Control Info. The content of this struct shall be
+ * provided by the target eNB.
+ */
+ void SendHandoverCommand (LteRrcSap::RrcConnectionReconfiguration rcr);
+
+ /**
+ *
+ * \return the HandoverPreparationInfo sent by the source eNB to the
+ * target eNB in the X2-based handover procedure
+ */
+ LteRrcSap::RadioResourceConfigDedicated GetRadioResourceConfigForHandoverPreparationInfo ();
/**
*
- * \return a const iterator pointing to the beginning of the embedded map of radio bearers
+ * \return retrieve the data that the target eNB needs to send to the source
+ * eNB as the Handover Command in the X2-based handover
+ * procedure.
+ */
+ LteRrcSap::RrcConnectionReconfiguration GetHandoverCommand ();
+
+ /**
+ * Send a data packet over the appropriate Data Radio Bearer
+ *
+ * \param bid the corresponding EPS Bearer ID
+ * \param p the packet
+ */
+ void SendData (uint8_t bid, Ptr<Packet> p);
+
+ /**
+ *
+ * \return a list of ERAB-to-be-setup items to be put in a X2 HO REQ message
+ */
+ std::vector<EpcX2Sap::ErabToBeSetupItem> GetErabList ();
+
+
+ // methods forwarded from RRC SAP
+ void CompleteSetupUe (LteEnbRrcSapProvider::CompleteSetupUeParameters params);
+ void RecvRrcConnectionRequest (LteRrcSap::RrcConnectionRequest msg);
+ void RecvRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg);
+ void RecvRrcConnectionReconfigurationCompleted (LteRrcSap::RrcConnectionReconfigurationCompleted msg);
+ void RecvRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg);
+ void RecvRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg);
+
+
+ // methods forwarded from CMAC SAP
+ void CmacUeConfigUpdateInd (LteEnbCmacSapUser::UeConfig cmacParams);
+
+
+ // methods forwarded from PDCP SAP
+ void DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params);
+
+ /**
+ *
+ * \return the RNTI, i.e., an UE identifier that is unique within
+ * the cell
+ */
+ uint16_t GetRnti (void);
+
+ /**
+ *
+ * \return the IMSI, i.e., a globally unique UE identifier
+ */
+ uint64_t GetImsi (void);
+
+ /**
+ *
+ * \return the SRS Configuration Index
*/
- std::map <uint8_t, Ptr<LteRadioBearerInfo> >::const_iterator RadioBearerMapBegin ();
+ uint16_t GetSrsConfigurationIndex (void);
+
+ /**
+ * Set the SRS configuration index and do the necessary reconfiguration
+ *
+ * \param srsConfIndex
+ */
+ void SetSrsConfigurationIndex (uint16_t srsConfIndex);
+
+ /**
+ *
+ * \return the current state
+ */
+ State GetState ();
+
+
+private:
+
+ /**
+ * Add a new LteDataRadioBearerInfo structure to the UeManager
+ *
+ * \param radioBearerInfo
+ *
+ * \return the id of the newly added data radio bearer structure
+ */
+ uint8_t AddDataRadioBearerInfo (Ptr<LteDataRadioBearerInfo> radioBearerInfo);
+
+ /**
+ * \param drbid the Data Radio Bearer id
+ *
+ * \return the corresponding LteDataRadioBearerInfo
+ */
+ Ptr<LteDataRadioBearerInfo> GetDataRadioBearerInfo (uint8_t drbid);
+
+ /**
+ * remove the LteDataRadioBearerInfo corresponding to a bearer being released
+ *
+ * \param drbid the Data Radio Bearer id
+ */
+ void RemoveDataRadioBearerInfo (uint8_t drbid);
+
+ /**
+ *
+ * \return an RrcConnectionReconfiguration struct built based on the
+ * current configuration
+ */
+ LteRrcSap::RrcConnectionReconfiguration BuildRrcConnectionReconfiguration ();
+
+ /**
+ *
+ * \return a RadioResourceConfigDedicated struct built based on the
+ * current configuration
+ */
+ LteRrcSap::RadioResourceConfigDedicated BuildRadioResourceConfigDedicated ();
/**
*
- * \return a const iterator pointing to the end of the embedded map of radio bearers
+ * \return a newly allocated identifier for a new RRC transaction
*/
- std::map <uint8_t, Ptr<LteRadioBearerInfo> >::const_iterator RadioBearerMapEnd ();
+ uint8_t GetNewRrcTransactionIdentifier ();
+
+ /**
+ * \param lcid a Logical Channel Identifier
+ *
+ * \return the corresponding Data Radio Bearer Id
+ */
+ uint8_t Lcid2Drbid (uint8_t lcid);
- UeInfo ();
+ /**
+ * \param drbid a Data Radio Bearer Id
+ *
+ * \return the corresponding Logical Channel Identifier
+ */
+ uint8_t Drbid2Lcid (uint8_t drbid);
- virtual ~UeInfo (void);
+ /**
+ * \param lcid a Logical Channel Identifier
+ *
+ * \return the corresponding EPS Bearer Identifier
+ */
+ uint8_t Lcid2Bid (uint8_t lcid);
- static TypeId GetTypeId (void);
+ /**
+ * \param bid an EPS Bearer Identifier
+ *
+ * \return the corresponding Logical Channel Identifier
+ */
+ uint8_t Bid2Lcid (uint8_t bid);
- uint64_t GetImsi (void);
- void SetImsi (uint64_t imsi);
+ /**
+ * \param drbid Data Radio Bearer Id
+ *
+ * \return the corresponding EPS Bearer Identifier
+ */
+ uint8_t Drbid2Bid (uint8_t drbid);
- uint8_t GetTransmissionMode (void);
- void SetTransmissionMode (uint8_t txMode);
-
- uint16_t GetSrsConfigurationIndex (void);
- void SetSrsConfigurationIndex (uint16_t srsConfIndex);
+ /**
+ * \param bid an EPS Bearer Identifier
+ *
+ * \return the corresponding Data Radio Bearer Id
+ */
+ uint8_t Bid2Drbid (uint8_t bid);
+
+ /**
+ * Switch the UeManager to the given state
+ *
+ * \param s the given state
+ */
+ void SwitchToState (State s);
-
-private:
- std::map <uint8_t, Ptr<LteRadioBearerInfo> > m_rbMap;
- uint8_t m_lastAllocatedId;
+ std::map <uint8_t, Ptr<LteDataRadioBearerInfo> > m_drbMap;
+ Ptr<LteSignalingRadioBearerInfo> m_srb0;
+ Ptr<LteSignalingRadioBearerInfo> m_srb1;
+ uint8_t m_lastAllocatedDrbid;
+ uint16_t m_rnti;
uint64_t m_imsi;
- uint16_t m_srsConfigurationIndex;
- uint8_t m_transmissionMode;
+ uint8_t m_lastRrcTransactionIdentifier;
+ LteRrcSap::PhysicalConfigDedicated m_physicalConfigDedicated;
+ Ptr<LteEnbRrc> m_rrc;
+ State m_state;
+ LtePdcpSapUser* m_pdcpSapUser;
+ bool m_pendingRrcConnectionReconfiguration;
+ TracedCallback<State, State> m_stateTransitionCallback;
};
@@ -124,9 +333,10 @@
{
friend class EnbRrcMemberLteEnbCmacSapUser;
- friend class LtePdcpSpecificLtePdcpSapUser<LteEnbRrc>;
+ friend class MemberLteEnbRrcSapProvider<LteEnbRrc>;
friend class MemberEpcEnbS1SapUser<LteEnbRrc>;
friend class EpcX2SpecificEpcX2SapUser<LteEnbRrc>;
+ friend class UeManager;
public:
/**
@@ -142,7 +352,9 @@
// inherited from Object
+protected:
virtual void DoDispose (void);
+public:
static TypeId GetTypeId (void);
@@ -174,14 +386,18 @@
/**
- * set the FF MAC SCHED SAP provider. The eNB RRC does not use this
- * directly, but it needs to provide it to newly created RLC instances.
+ * set the RRC SAP this RRC should interact with
*
- * \param s the FF MAC SCHED SAP provider that will be used by all
- * newly created RLC instances
+ * \param s the RRC SAP User to be used by this RRC
*/
- void SetFfMacSchedSapProvider (FfMacSchedSapProvider* s);
+ void SetLteEnbRrcSapUser (LteEnbRrcSapUser * s);
+ /**
+ *
+ *
+ * \return s the RRC SAP Provider interface offered to the MAC by this RRC
+ */
+ LteEnbRrcSapProvider* GetLteEnbRrcSapProvider ();
/**
* set the MAC SAP provider. The eNB RRC does not use this
@@ -221,6 +437,14 @@
*/
LteEnbCphySapUser* GetLteEnbCphySapUser ();
+ /**
+ *
+ *
+ * \param rnti the identifier of an UE
+ *
+ * \return the corresponding UeManager instance
+ */
+ Ptr<UeManager> GetUeManager (uint16_t rnti);
/**
* configure cell-specific parameters
@@ -236,73 +460,24 @@
uint16_t ulEarfcn,
uint16_t dlEarfcn,
uint16_t cellId);
-
-
- /**
- * receive RRC Connection Request from an UE
- *
- * \param imsi the id of the UE
- *
- * \return the RNTI identifying the UE in this cell
- */
- uint16_t DoRecvConnectionRequest (uint64_t imsi);
-
- /**
- * receive RRC Connection Setup Completed from an UE
- *
- * \param rnti the RNTI identifying the UE in this cell
- */
- void DoRecvConnectionSetupCompleted (uint16_t rnti);
/**
- * receive RRC Connection Reconfiguration Completed message from UE
- *
- * \param rnti
+ * set the cell id of this eNB
*
+ * \param m_cellId
*/
- void DoRecvConnectionReconfigurationCompleted (uint16_t rnti);
-
void SetCellId (uint16_t m_cellId);
- /**
- * remove a UE from the cell
- *
- * \param rnti the C-RNTI identiftying the user
- */
- void RemoveUe (uint16_t rnti);
-
- uint16_t GetLastAllocatedRnti () const;
- void SetLastAllocatedRnti (uint16_t lastAllocatedRnti);
- void SetUeMap (std::map<uint16_t,Ptr<UeInfo> > ueMap);
- std::map<uint16_t,Ptr<UeInfo> > GetUeMap (void) const;
-
/**
- *
- * \param bearer the specification of an EPS bearer
- *
- * \return the type of RLC that is to be created for the given EPS bearer
- */
- TypeId GetRlcType (EpsBearer bearer);
-
-
- /**
- *
- * Release the given radio bearer
- *
- * \param rnti the C-RNTI of the user owning the bearer
- * \param lcId the logical channel id of the bearer to be released
- */
- void ReleaseRadioBearer (uint16_t rnti, uint8_t lcId);
-
-
- /**
- * Enqueue an IP packet on the proper bearer for downlink transmission
+ * Enqueue an IP data packet on the proper bearer for downlink
+ * transmission. Normally expected to be called by the NetDevice
+ * forwarding a packet coming from the EpcEnbApplication
*
* \param p the packet
*
* \return true if successful, false if an error occurred
*/
- bool Send (Ptr<Packet> p);
+ bool SendData (Ptr<Packet> p);
/**
* set the callback used to forward data packets up the stack
@@ -334,58 +509,108 @@
PER_BASED = 4};
private:
+
+ // methods forwarded from RRC SAP
+
+ void DoCompleteSetupUe (uint16_t rnti, LteEnbRrcSapProvider::CompleteSetupUeParameters params);
+ void DoRecvRrcConnectionRequest (uint16_t rnti, LteRrcSap::RrcConnectionRequest msg);
+ void DoRecvRrcConnectionSetupCompleted (uint16_t rnti, LteRrcSap::RrcConnectionSetupCompleted msg);
+ void DoRecvRrcConnectionReconfigurationCompleted (uint16_t rnti, LteRrcSap::RrcConnectionReconfigurationCompleted msg);
+ void DoRecvRrcConnectionReestablishmentRequest (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentRequest msg);
+ void DoRecvRrcConnectionReestablishmentComplete (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentComplete msg);
+
+
+ // S1 SAP methods
+ void DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params);
+
+
+ // methods forwarded from X2 SAP
+ void DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params);
+ void DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params);
+
+
+ // CMAC SAP methods
+ uint16_t DoAllocateTemporaryCellRnti ();
+ void DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
+ void DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig params);
+
+
+
+
/**
* Allocate a new RNTI for a new UE. This is done in the following cases:
* * T-C-RNTI allocation upon contention-based MAC Random Access procedure
* * target cell RNTI allocation upon handover
*
+ * \param state the initial state of the UeManager
+ *
* \return the newly allocated RNTI
*/
- uint16_t AddUe ();
-
-
+ uint16_t AddUe (UeManager::State state);
/**
- * Setup a new radio bearer for the given user
- *
- * \param rnti the RNTI of the user
- * \param bearer the characteristics of the bearer to be activated
- * \param teid the S1-U Tunnel Endpoint Identifier for this bearer
+ * remove a UE from the cell
*
- * \return the logical channel identifier of the radio bearer for the considered user
+ * \param rnti the C-RNTI identiftying the user
*/
- uint8_t SetupRadioBearer (uint16_t rnti, EpsBearer bearer, uint32_t teid);
-
-
- void DoRecvHandoverRequest (EpcX2SapUser::HandoverRequestParams params);
- void DoRecvHandoverRequestAck (EpcX2SapUser::HandoverRequestAckParams params);
+ void RemoveUe (uint16_t rnti);
- LtePdcpSapProvider* GetLtePdcpSapProvider (uint16_t rnti, uint8_t lcid);
+ /**
+ *
+ * \param bearer the specification of an EPS bearer
+ *
+ * \return the type of RLC that is to be created for the given EPS bearer
+ */
+ TypeId GetRlcType (EpsBearer bearer);
- // PDCP SAP methods
- void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params);
+ /**
+ * Allocate a new SRS configuration index for a new UE.
+ *
+ * \note this method can have the side effect of updating the SRS
+ * configuration index of all UEs
+ *
+ * \return the newly allocated SRS configuration index
+ */
+ uint16_t GetNewSrsConfigurationIndex (void);
- // CMAC SAP methods
- void DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig params);
- void DoNotifyLcConfigResult (uint16_t rnti, uint8_t lcid, bool success);
+ /**
+ * remove a previously allocated SRS configuration index
+ *
+ * \note this method can have the side effect of updating the SRS
+ * configuration index of all UEs
+ *
+ * \param srcCi the indext to be removed
+ */
+ void RemoveSrsConfigurationIndex (uint16_t srcCi);
+
+
- // S1 SAP methods
- void DoDataRadioBearerSetupRequest (EpcEnbS1SapUser::DataRadioBearerSetupRequestParameters params);
+ /**
+ *
+ * \param bearer the characteristics of the bearer
+ *
+ * \return the Logical Channel Group in a bearer with these
+ * characteristics is put. Used for MAC Buffer Status Reporting purposes.
+ */
+ uint8_t GetLogicalChannelGroup (EpsBearer bearer);
- void PropagateRrcConnectionReconfiguration (LteUeConfig_t ueConfig);
+ /**
+ *
+ * \param bearer the characteristics of the bearer
+ *
+ * \return the priority level of a bearer with these
+ * characteristics is put. Used for the part of UL MAC Scheduling
+ * carried out by the UE
+ */
+ uint8_t GetLogicalChannelPriority (EpsBearer bearer);
- // management of multiple UE info instances
- uint16_t CreateUeInfo ();
- Ptr<UeInfo> GetUeInfo (uint16_t rnti);
- void RemoveUeInfo (uint16_t rnti);
- uint16_t GetNewSrsConfigurationIndex (void);
- void RemoveSrsConfigurationIndex (uint16_t srcCi);
-
- // methods used to talk to UE RRC directly in absence of real RRC protocol
- Ptr<LteUeRrc> GetUeRrcByImsi (uint64_t imsi);
- Ptr<LteUeRrc> GetUeRrcByRnti (uint16_t rnti);
+ /**
+ * method used to periodically send System Information
+ *
+ */
+ void SendSystemInformation ();
Callback <void, Ptr<Packet> > m_forwardUpCallback;
@@ -395,9 +620,10 @@
LteEnbCmacSapUser* m_cmacSapUser;
LteEnbCmacSapProvider* m_cmacSapProvider;
- FfMacSchedSapProvider* m_ffMacSchedSapProvider;
+ LteEnbRrcSapUser* m_rrcSapUser;
+ LteEnbRrcSapProvider* m_rrcSapProvider;
+
LteMacSapProvider* m_macSapProvider;
- LtePdcpSapUser* m_pdcpSapUser;
EpcEnbS1SapProvider* m_s1SapProvider;
EpcEnbS1SapUser* m_s1SapUser;
@@ -407,13 +633,19 @@
bool m_configured;
uint16_t m_cellId;
+ uint16_t m_dlEarfcn;
+ uint16_t m_ulEarfcn;
+ uint16_t m_dlBandwidth;
+ uint16_t m_ulBandwidth;
uint16_t m_lastAllocatedRnti;
- std::map<uint16_t, Ptr<UeInfo> > m_ueMap;
+ std::map<uint16_t, Ptr<UeManager> > m_ueMap;
uint8_t m_defaultTransmissionMode;
enum LteEpsBearerToRlcMapping_t m_epsBearerToRlcMapping;
+
+ Time m_systemInformationPeriodicity;
// SRS related attributes
uint16_t m_srsCurrentPeriodicityId;
--- a/src/lte/model/lte-interference.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-interference.cc Tue Oct 30 16:02:07 2012 +0100
@@ -32,7 +32,9 @@
LteInterference::LteInterference ()
- : m_receiving (false)
+ : m_receiving (false),
+ m_lastSignalId (0),
+ m_lastSignalIdBeforeReset (0)
{
NS_LOG_FUNCTION (this);
}
@@ -95,11 +97,18 @@
LteInterference::EndRx ()
{
NS_LOG_FUNCTION (this);
- ConditionallyEvaluateChunk ();
- m_receiving = false;
- for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
+ if (m_receiving != true)
+ {
+ NS_LOG_INFO ("EndRx was already evaluated or RX was aborted");
+ }
+ else
{
- (*it)->End ();
+ ConditionallyEvaluateChunk ();
+ m_receiving = false;
+ for (std::list<Ptr<LteSinrChunkProcessor> >::const_iterator it = m_sinrChunkProcessorList.begin (); it != m_sinrChunkProcessorList.end (); ++it)
+ {
+ (*it)->End ();
+ }
}
}
@@ -108,13 +117,18 @@
LteInterference::AddSignal (Ptr<const SpectrumValue> spd, const Time duration)
{
NS_LOG_FUNCTION (this << *spd << duration);
- // if this is the first signal that we see, we need to initialize the interference calculation
- if (m_allSignals == 0)
+ DoAddSignal (spd);
+ uint32_t signalId = ++m_lastSignalId;
+ if (signalId == m_lastSignalIdBeforeReset)
{
- m_allSignals = Create<SpectrumValue> (spd->GetSpectrumModel ());
+ // This happens when m_lastSignalId eventually wraps around. Given that so
+ // many signals have elapsed since the last reset, we hope that by now there is
+ // no stale pending signal (i.e., a signal that was scheduled
+ // for subtraction before the reset). So we just move the
+ // boundary further.
+ m_lastSignalIdBeforeReset += 0x10000000;
}
- DoAddSignal (spd);
- Simulator::Schedule (duration, &LteInterference::DoSubtractSignal, this, spd);
+ Simulator::Schedule (duration, &LteInterference::DoSubtractSignal, this, spd, signalId);
}
@@ -124,16 +138,22 @@
NS_LOG_FUNCTION (this << *spd);
ConditionallyEvaluateChunk ();
(*m_allSignals) += (*spd);
- m_lastChangeTime = Now ();
}
void
-LteInterference::DoSubtractSignal (Ptr<const SpectrumValue> spd)
+LteInterference::DoSubtractSignal (Ptr<const SpectrumValue> spd, uint32_t signalId)
{
NS_LOG_FUNCTION (this << *spd);
- ConditionallyEvaluateChunk ();
- (*m_allSignals) -= (*spd);
- m_lastChangeTime = Now ();
+ ConditionallyEvaluateChunk ();
+ int32_t deltaSignalId = signalId - m_lastSignalIdBeforeReset;
+ if (deltaSignalId > 0)
+ {
+ (*m_allSignals) -= (*spd);
+ }
+ else
+ {
+ NS_LOG_INFO ("ignoring signal scheduled for subtraction before last reset");
+ }
}
@@ -156,6 +176,7 @@
{
(*it)->EvaluateSinrChunk (sinr, duration);
}
+ m_lastChangeTime = Now ();
}
else
{
@@ -167,12 +188,19 @@
LteInterference::SetNoisePowerSpectralDensity (Ptr<const SpectrumValue> noisePsd)
{
NS_LOG_FUNCTION (this << *noisePsd);
+ ConditionallyEvaluateChunk ();
m_noise = noisePsd;
- // we can initialize m_allSignal only now, because earlier we
- // didn't know what spectrum model was going to be used.
- // we'll now create a zeroed SpectrumValue using the same
- // SpectrumModel which is being specified for the noise.
+ // reset m_allSignals (will reset if already set previously)
+ // this is needed since this method can potentially change the SpectrumModel
m_allSignals = Create<SpectrumValue> (noisePsd->GetSpectrumModel ());
+ if (m_receiving == true)
+ {
+ // abort rx
+ m_receiving = false;
+ }
+ // record the last SignalId so that we can ignore all signals that
+ // were scheduled for subtraction before m_allSignal
+ m_lastSignalIdBeforeReset = m_lastSignalId;
}
void
--- a/src/lte/model/lte-interference.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-interference.h Tue Oct 30 16:02:07 2012 +0100
@@ -99,7 +99,7 @@
private:
void ConditionallyEvaluateChunk ();
void DoAddSignal (Ptr<const SpectrumValue> spd);
- void DoSubtractSignal (Ptr<const SpectrumValue> spd);
+ void DoSubtractSignal (Ptr<const SpectrumValue> spd, uint32_t signalId);
@@ -120,12 +120,14 @@
Time m_lastChangeTime; /**< the time of the last change in
m_TotalPower */
+ uint32_t m_lastSignalId;
+ uint32_t m_lastSignalIdBeforeReset;
+
/** all the processor instances that need to be notified whenever
a new SINR chunk is calculated */
std::list<Ptr<LteSinrChunkProcessor> > m_sinrChunkProcessorList;
-
};
--- a/src/lte/model/lte-pdcp-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-pdcp-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -38,11 +38,11 @@
virtual ~LtePdcpSapProvider ();
/**
- * Parameters for LtePdcpSapProvider::TransmitRrcPdu
+ * Parameters for LtePdcpSapProvider::TransmitPdcpSdu
*/
- struct TransmitRrcPduParameters
+ struct TransmitPdcpSduParameters
{
- Ptr<Packet> rrcPdu; /**< the RRC PDU */
+ Ptr<Packet> pdcpSdu; /**< the RRC PDU */
uint16_t rnti; /**< the C-RNTI identifying the UE */
uint8_t lcid; /**< the logical channel id corresponding to the sending RLC instance */
};
@@ -54,7 +54,7 @@
*
* \param params
*/
- virtual void TransmitRrcPdu (TransmitRrcPduParameters params) = 0;
+ virtual void TransmitPdcpSdu (TransmitPdcpSduParameters params) = 0;
};
@@ -71,11 +71,11 @@
virtual ~LtePdcpSapUser ();
/**
- * Parameters for LtePdcpSapUser::ReceiveRrcPdu
+ * Parameters for LtePdcpSapUser::ReceivePdcpSdu
*/
- struct ReceiveRrcPduParameters
+ struct ReceivePdcpSduParameters
{
- Ptr<Packet> rrcPdu; /**< the RRC PDU */
+ Ptr<Packet> pdcpSdu; /**< the RRC PDU */
uint16_t rnti; /**< the C-RNTI identifying the UE */
uint8_t lcid; /**< the logical channel id corresponding to the sending RLC instance */
};
@@ -85,7 +85,7 @@
*
* \param params
*/
- virtual void ReceiveRrcPdu (ReceiveRrcPduParameters params) = 0;
+ virtual void ReceivePdcpSdu (ReceivePdcpSduParameters params) = 0;
};
///////////////////////////////////////
@@ -97,7 +97,7 @@
LtePdcpSpecificLtePdcpSapProvider (C* pdcp);
// Interface implemented from LtePdcpSapProvider
- virtual void TransmitRrcPdu (TransmitRrcPduParameters params);
+ virtual void TransmitPdcpSdu (TransmitPdcpSduParameters params);
private:
LtePdcpSpecificLtePdcpSapProvider ();
@@ -116,9 +116,9 @@
}
template <class C>
-void LtePdcpSpecificLtePdcpSapProvider<C>::TransmitRrcPdu (TransmitRrcPduParameters params)
+void LtePdcpSpecificLtePdcpSapProvider<C>::TransmitPdcpSdu (TransmitPdcpSduParameters params)
{
- m_pdcp->DoTransmitRrcPdu (params.rrcPdu);
+ m_pdcp->DoTransmitPdcpSdu (params.pdcpSdu);
}
///////////////////////////////////////
@@ -130,7 +130,7 @@
LtePdcpSpecificLtePdcpSapUser (C* rrc);
// Interface implemented from LtePdcpSapUser
- virtual void ReceiveRrcPdu (ReceiveRrcPduParameters params);
+ virtual void ReceivePdcpSdu (ReceivePdcpSduParameters params);
private:
LtePdcpSpecificLtePdcpSapUser ();
@@ -149,9 +149,9 @@
}
template <class C>
-void LtePdcpSpecificLtePdcpSapUser<C>::ReceiveRrcPdu (ReceiveRrcPduParameters params)
+void LtePdcpSpecificLtePdcpSapUser<C>::ReceivePdcpSdu (ReceivePdcpSduParameters params)
{
- m_rrc->DoReceiveRrcPdu (params);
+ m_rrc->DoReceivePdcpSdu (params);
}
--- a/src/lte/model/lte-pdcp.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-pdcp.cc Tue Oct 30 16:02:07 2012 +0100
@@ -145,7 +145,7 @@
////////////////////////////////////////
void
-LtePdcp::DoTransmitRrcPdu (Ptr<Packet> p)
+LtePdcp::DoTransmitPdcpSdu (Ptr<Packet> p)
{
NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
@@ -200,11 +200,11 @@
m_rxSequenceNumber = 0;
}
- LtePdcpSapUser::ReceiveRrcPduParameters params;
- params.rrcPdu = p;
+ LtePdcpSapUser::ReceivePdcpSduParameters params;
+ params.pdcpSdu = p;
params.rnti = m_rnti;
params.lcid = m_lcid;
- m_pdcpSapUser->ReceiveRrcPdu (params);
+ m_pdcpSapUser->ReceivePdcpSdu (params);
}
void
--- a/src/lte/model/lte-pdcp.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-pdcp.h Tue Oct 30 16:02:07 2012 +0100
@@ -90,7 +90,7 @@
protected:
// Interface provided to upper RRC entity
- virtual void DoTransmitRrcPdu (Ptr<Packet> p);
+ virtual void DoTransmitPdcpSdu (Ptr<Packet> p);
LtePdcpSapUser* m_pdcpSapUser;
LtePdcpSapProvider* m_pdcpSapProvider;
--- a/src/lte/model/lte-radio-bearer-info.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-radio-bearer-info.cc Tue Oct 30 16:02:07 2012 +0100
@@ -38,14 +38,43 @@
LteRadioBearerInfo::~LteRadioBearerInfo (void)
{
}
-
-TypeId LteRadioBearerInfo::GetTypeId (void)
+
+TypeId
+LteRadioBearerInfo::GetTypeId (void)
{
static TypeId
- tid =
+ tid =
TypeId ("ns3::LteRadioBearerInfo")
.SetParent<Object> ()
.AddConstructor<LteRadioBearerInfo> ()
+ ;
+ return tid;
+}
+
+
+TypeId
+LteDataRadioBearerInfo::GetTypeId (void)
+{
+ static TypeId
+ tid =
+ TypeId ("ns3::LteDataRadioBearerInfo")
+ .SetParent<LteRadioBearerInfo> ()
+ .AddConstructor<LteDataRadioBearerInfo> ()
+ .AddAttribute ("DrbIdentity", "The id of this Data Radio Bearer",
+ TypeId::ATTR_GET, // allow only getting it.
+ UintegerValue (0), // unused (attribute is read-only
+ MakeUintegerAccessor (&LteDataRadioBearerInfo::m_drbIdentity),
+ MakeUintegerChecker<uint8_t> ())
+ .AddAttribute ("EpsBearerIdentity", "The id of the EPS bearer corresponding to this Data Radio Bearer",
+ TypeId::ATTR_GET, // allow only getting it.
+ UintegerValue (0), // unused (attribute is read-only
+ MakeUintegerAccessor (&LteDataRadioBearerInfo::m_epsBearerIdentity),
+ MakeUintegerChecker<uint8_t> ())
+ .AddAttribute ("logicalChannelIdentity", "The id of the Logical Channel corresponding to this Data Radio Bearer",
+ TypeId::ATTR_GET, // allow only getting it.
+ UintegerValue (0), // unused (attribute is read-only
+ MakeUintegerAccessor (&LteDataRadioBearerInfo::m_logicalChannelIdentity),
+ MakeUintegerChecker<uint8_t> ())
.AddAttribute ("LteRlc", "RLC instance of the radio bearer.",
PointerValue (),
MakePointerAccessor (&LteRadioBearerInfo::m_rlc),
@@ -54,11 +83,36 @@
PointerValue (),
MakePointerAccessor (&LteRadioBearerInfo::m_pdcp),
MakePointerChecker<LtePdcp> ())
- ;
+ ;
+ return tid;
+}
+
+
+TypeId
+LteSignalingRadioBearerInfo::GetTypeId (void)
+{
+ static TypeId
+ tid =
+ TypeId ("ns3::LteSignalingRadioBearerInfo")
+ .SetParent<LteRadioBearerInfo> ()
+ .AddConstructor<LteSignalingRadioBearerInfo> ()
+ .AddAttribute ("SrbIdentity", "The id of this Signaling Radio Bearer",
+ TypeId::ATTR_GET, // allow only getting it.
+ UintegerValue (0), // unused (attribute is read-only
+ MakeUintegerAccessor (&LteSignalingRadioBearerInfo::m_srbIdentity),
+ MakeUintegerChecker<uint8_t> ())
+ .AddAttribute ("LteRlc", "RLC instance of the radio bearer.",
+ PointerValue (),
+ MakePointerAccessor (&LteRadioBearerInfo::m_rlc),
+ MakePointerChecker<LteRlc> ())
+ .AddAttribute ("LtePdcp", "PDCP instance of the radio bearer.",
+ PointerValue (),
+ MakePointerAccessor (&LteRadioBearerInfo::m_pdcp),
+ MakePointerChecker<LtePdcp> ())
+ ;
return tid;
}
-
} // namespace ns3
--- a/src/lte/model/lte-radio-bearer-info.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-radio-bearer-info.h Tue Oct 30 16:02:07 2012 +0100
@@ -24,6 +24,7 @@
#include <ns3/object.h>
#include <ns3/pointer.h>
#include <ns3/eps-bearer.h>
+#include <ns3/lte-rrc-sap.h>
namespace ns3 {
@@ -44,11 +45,46 @@
Ptr<LteRlc> m_rlc;
Ptr<LtePdcp> m_pdcp;
+};
+
+
+/**
+ * store information on active signaling radio bearer instance
+ *
+ */
+class LteSignalingRadioBearerInfo : public LteRadioBearerInfo
+{
+
+public:
+ static TypeId GetTypeId (void);
+
+ uint8_t m_srbIdentity;
+ LteRrcSap::LogicalChannelConfig m_logicalChannelConfig;
+};
+
+
+/**
+ * store information on active data radio bearer instance
+ *
+ */
+class LteDataRadioBearerInfo : public LteRadioBearerInfo
+{
+
+public:
+ static TypeId GetTypeId (void);
+
EpsBearer m_epsBearer;
- uint32_t m_teid;
+ uint8_t m_epsBearerIdentity;
+ uint8_t m_drbIdentity;
+ LteRrcSap::RlcConfig m_rlcConfig;
+ uint8_t m_logicalChannelIdentity;
+ LteRrcSap::LogicalChannelConfig m_logicalChannelConfig;
};
+
+
+
} // namespace ns3
--- a/src/lte/model/lte-radio-bearer-tag.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-radio-bearer-tag.cc Tue Oct 30 16:02:07 2012 +0100
@@ -33,11 +33,11 @@
static TypeId tid = TypeId ("ns3::LteRadioBearerTag")
.SetParent<Tag> ()
.AddConstructor<LteRadioBearerTag> ()
- .AddAttribute ("rnti", "The rnti that indicates the UE which packet belongs",
+ .AddAttribute ("rnti", "The rnti that indicates the UE to which packet belongs",
UintegerValue (0),
MakeUintegerAccessor (&LteRadioBearerTag::GetRnti),
MakeUintegerChecker<uint16_t> ())
- .AddAttribute ("lcid", "The LC id that indicates the UE which packet belongs",
+ .AddAttribute ("lcid", "The id whithin the UE identifying the logical channel to which the packet belongs",
UintegerValue (0),
MakeUintegerAccessor (&LteRadioBearerTag::GetLcid),
MakeUintegerChecker<uint8_t> ())
--- a/src/lte/model/lte-rlc-am.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-rlc-am.h Tue Oct 30 16:02:07 2012 +0100
@@ -21,9 +21,9 @@
#ifndef LTE_RLC_AM_H
#define LTE_RLC_AM_H
-#include "ns3/lte-rlc-sequence-number.h"
-
-#include "ns3/lte-rlc.h"
+#include <ns3/event-id.h>
+#include <ns3/lte-rlc-sequence-number.h>
+#include <ns3/lte-rlc.h>
#include <vector>
#include <map>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rlc-tm.cc Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,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: Manuel Requena <manuel.requena@cttc.es>
+ * Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+
+#include "ns3/lte-rlc-tm.h"
+#include "ns3/lte-rlc-tag.h"
+
+NS_LOG_COMPONENT_DEFINE ("LteRlcTm");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (LteRlcTm);
+
+LteRlcTm::LteRlcTm ()
+ : m_maxTxBufferSize (0),
+ m_txBufferSize (0)
+{
+ NS_LOG_FUNCTION (this);
+
+ Simulator::ScheduleNow (&LteRlcTm::Start, this);
+}
+
+LteRlcTm::~LteRlcTm ()
+{
+}
+
+TypeId
+LteRlcTm::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::LteRlcTm")
+ .SetParent<LteRlc> ()
+ .AddConstructor<LteRlcTm> ()
+ .AddAttribute ("MaxTxBufferSize",
+ "Maximum Size of the Transmission Buffer (in Bytes)",
+ UintegerValue (2 * 1024 * 1024),
+ MakeUintegerAccessor (&LteRlcTm::m_maxTxBufferSize),
+ MakeUintegerChecker<uint32_t> ())
+ ;
+ return tid;
+}
+
+
+/**
+ * RLC SAP
+ */
+
+void
+LteRlcTm::DoTransmitPdcpPdu (Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
+
+ if (m_txBufferSize + p->GetSize () <= m_maxTxBufferSize)
+ {
+ /** Store arrival time */
+ RlcTag timeTag (Simulator::Now ());
+ p->AddPacketTag (timeTag);
+
+ NS_LOG_LOGIC ("Tx Buffer: New packet added");
+ m_txBuffer.push_back (p);
+ m_txBufferSize += p->GetSize ();
+ NS_LOG_LOGIC ("NumOfBuffers = " << m_txBuffer.size() );
+ NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
+ }
+ else
+ {
+ // Discard full RLC SDU
+ NS_LOG_LOGIC ("TxBuffer is full. RLC SDU discarded");
+ NS_LOG_LOGIC ("MaxTxBufferSize = " << m_maxTxBufferSize);
+ NS_LOG_LOGIC ("txBufferSize = " << m_txBufferSize);
+ NS_LOG_LOGIC ("packet size = " << p->GetSize ());
+ }
+
+ /** Report Buffer Status */
+ DoReportBufferStatus ();
+ m_rbsTimer.Cancel ();
+}
+
+
+/**
+ * MAC SAP
+ */
+
+void
+LteRlcTm::DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer)
+{
+ NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << bytes);
+
+ // 5.1.1.1 Transmit operations
+ // 5.1.1.1.1 General
+ // When submitting a new TMD PDU to lower layer, the transmitting TM RLC entity shall:
+ // - submit a RLC SDU without any modification to lower layer.
+
+
+ if ( m_txBuffer.size () == 0 )
+ {
+ NS_LOG_LOGIC ("No data pending");
+ return;
+ }
+
+ Ptr<Packet> packet = (*(m_txBuffer.begin ()))->Copy ();
+
+ if (bytes < packet->GetSize ())
+ {
+ // Stingy MAC: Header fix part is 2 bytes, we need more bytes for the data
+ NS_LOG_WARN ("TX opportunity too small = " << bytes << " (PDU size: " << packet->GetSize () << ")");
+ return;
+ }
+
+ m_txBufferSize -= (*(m_txBuffer.begin()))->GetSize ();
+ m_txBuffer.erase (m_txBuffer.begin ());
+
+ // Sender timestamp
+ RlcTag rlcTag (Simulator::Now ());
+ packet->AddByteTag (rlcTag);
+ m_txPdu (m_rnti, m_lcid, packet->GetSize ());
+
+ // Send RLC PDU to MAC layer
+ LteMacSapProvider::TransmitPduParameters params;
+ params.pdu = packet;
+ params.rnti = m_rnti;
+ params.lcid = m_lcid;
+ params.layer = layer;
+
+ m_macSapProvider->TransmitPdu (params);
+
+ if (! m_txBuffer.empty ())
+ {
+ m_rbsTimer.Cancel ();
+ m_rbsTimer = Simulator::Schedule (MilliSeconds (10), &LteRlcTm::ExpireRbsTimer, this);
+ }
+}
+
+void
+LteRlcTm::DoNotifyHarqDeliveryFailure ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+LteRlcTm::DoReceivePdu (Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION (this << m_rnti << (uint32_t) m_lcid << p->GetSize ());
+
+ // Receiver timestamp
+ RlcTag rlcTag;
+ Time delay;
+ if (p->FindFirstMatchingByteTag (rlcTag))
+ {
+ delay = Simulator::Now() - rlcTag.GetSenderTimestamp ();
+ }
+ m_rxPdu (m_rnti, m_lcid, p->GetSize (), delay.GetNanoSeconds ());
+
+ // 5.1.1.2 Receive operations
+ // 5.1.1.2.1 General
+ // When receiving a new TMD PDU from lower layer, the receiving TM RLC entity shall:
+ // - deliver the TMD PDU without any modification to upper layer.
+
+ m_rlcSapUser->ReceivePdcpPdu (p);
+}
+
+
+void
+LteRlcTm::Start ()
+{
+ NS_LOG_FUNCTION (this);
+
+ DoReportBufferStatus ();
+}
+
+
+void
+LteRlcTm::DoReportBufferStatus (void)
+{
+ Time holDelay (0);
+ uint32_t queueSize = 0;
+
+ if (! m_txBuffer.empty ())
+ {
+ RlcTag holTimeTag;
+ m_txBuffer.front ()->PeekPacketTag (holTimeTag);
+ holDelay = Simulator::Now () - holTimeTag.GetSenderTimestamp ();
+
+ queueSize = m_txBufferSize; // just data in tx queue (no header overhead for RLC TM)
+ }
+
+ LteMacSapProvider::ReportBufferStatusParameters r;
+ r.rnti = m_rnti;
+ r.lcid = m_lcid;
+ r.txQueueSize = queueSize;
+ r.txQueueHolDelay = holDelay.GetMilliSeconds () ;
+ r.retxQueueSize = 0;
+ r.retxQueueHolDelay = 0;
+ r.statusPduSize = 0;
+
+ NS_LOG_LOGIC ("Send ReportBufferStatus = " << r.txQueueSize << ", " << r.txQueueHolDelay );
+ m_macSapProvider->ReportBufferStatus (r);
+}
+
+void
+LteRlcTm::ExpireRbsTimer (void)
+{
+ NS_LOG_LOGIC ("RBS Timer expires");
+
+ if (! m_txBuffer.empty ())
+ {
+ DoReportBufferStatus ();
+ m_rbsTimer = Simulator::Schedule (MilliSeconds (10), &LteRlcTm::ExpireRbsTimer, this);
+ }
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rlc-tm.h Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011,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: Manuel Requena <manuel.requena@cttc.es>
+ * Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#ifndef LTE_RLC_TM_H
+#define LTE_RLC_TM_H
+
+#include "ns3/lte-rlc.h"
+
+#include <ns3/event-id.h>
+#include <map>
+
+namespace ns3 {
+
+/**
+ * LTE RLC Transparent Mode (TM), see 3GPP TS 36.322
+ */
+class LteRlcTm : public LteRlc
+{
+public:
+ LteRlcTm ();
+ virtual ~LteRlcTm ();
+ static TypeId GetTypeId (void);
+
+ /**
+ * RLC SAP
+ */
+ virtual void DoTransmitPdcpPdu (Ptr<Packet> p);
+
+ /**
+ * MAC SAP
+ */
+ virtual void DoNotifyTxOpportunity (uint32_t bytes, uint8_t layer);
+ virtual void DoNotifyHarqDeliveryFailure ();
+ virtual void DoReceivePdu (Ptr<Packet> p);
+
+ void Start ();
+
+private:
+ void ExpireRbsTimer (void);
+ void DoReportBufferStatus ();
+
+private:
+ uint32_t m_maxTxBufferSize;
+ uint32_t m_txBufferSize;
+ std::vector < Ptr<Packet> > m_txBuffer; // Transmission buffer
+
+ EventId m_rbsTimer;
+
+};
+
+
+} // namespace ns3
+
+#endif // LTE_RLC_TM_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rrc-protocol-ideal.cc Tue Oct 30 16:02:07 2012 +0100
@@ -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 <nbaldo@cttc.es>
+ */
+
+#include <ns3/fatal-error.h>
+#include <ns3/log.h>
+#include <ns3/nstime.h>
+#include <ns3/node-list.h>
+#include <ns3/node.h>
+#include <ns3/simulator.h>
+
+#include "lte-rrc-protocol-ideal.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 ("LteRrcProtocolIdeal");
+
+
+namespace ns3 {
+
+
+const Time RRC_IDEAL_MSG_DELAY = MilliSeconds (0);
+
+NS_OBJECT_ENSURE_REGISTERED (LteUeRrcProtocolIdeal);
+
+LteUeRrcProtocolIdeal::LteUeRrcProtocolIdeal ()
+ : m_ueRrcSapProvider (0),
+ m_enbRrcSapProvider (0)
+{
+ m_ueRrcSapUser = new MemberLteUeRrcSapUser<LteUeRrcProtocolIdeal> (this);
+}
+
+LteUeRrcProtocolIdeal::~LteUeRrcProtocolIdeal ()
+{
+}
+
+void
+LteUeRrcProtocolIdeal::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ delete m_ueRrcSapUser;
+ m_rrc = 0;
+}
+
+TypeId
+LteUeRrcProtocolIdeal::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::LteUeRrcProtocolIdeal")
+ .SetParent<Object> ()
+ .AddConstructor<LteUeRrcProtocolIdeal> ()
+ ;
+ return tid;
+}
+
+void
+LteUeRrcProtocolIdeal::SetLteUeRrcSapProvider (LteUeRrcSapProvider* p)
+{
+ m_ueRrcSapProvider = p;
+}
+
+LteUeRrcSapUser*
+LteUeRrcProtocolIdeal::GetLteUeRrcSapUser ()
+{
+ return m_ueRrcSapUser;
+}
+
+void
+LteUeRrcProtocolIdeal::SetUeRrc (Ptr<LteUeRrc> rrc)
+{
+ m_rrc = rrc;
+}
+
+void
+LteUeRrcProtocolIdeal::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 ideal
+ // RRC messages.
+ DoReestablish ();
+}
+
+void
+LteUeRrcProtocolIdeal::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_IDEAL_MSG_DELAY,
+ // &LteEnbRrcSapProvider::RecvRrcConnectionRequest,
+ // m_enbRrcSapProvider,
+ // m_rnti,
+ // m_pendingRrcConnectionRequest);
+ // }
+}
+
+void
+LteUeRrcProtocolIdeal::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_IDEAL_MSG_DELAY,
+ &LteEnbRrcSapProvider::RecvRrcConnectionRequest,
+ m_enbRrcSapProvider,
+ m_rnti,
+ msg);
+}
+
+void
+LteUeRrcProtocolIdeal::DoSendRrcConnectionSetupCompleted (LteRrcSap::RrcConnectionSetupCompleted msg)
+{
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteEnbRrcSapProvider::RecvRrcConnectionSetupCompleted,
+ m_enbRrcSapProvider,
+ m_rnti,
+ msg);
+}
+
+void
+LteUeRrcProtocolIdeal::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_IDEAL_MSG_DELAY,
+ &LteEnbRrcSapProvider::RecvRrcConnectionReconfigurationCompleted,
+ m_enbRrcSapProvider,
+ m_rnti,
+ msg);
+}
+
+void
+LteUeRrcProtocolIdeal::DoSendRrcConnectionReestablishmentRequest (LteRrcSap::RrcConnectionReestablishmentRequest msg)
+{
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteEnbRrcSapProvider::RecvRrcConnectionReestablishmentRequest,
+ m_enbRrcSapProvider,
+ m_rnti,
+ msg);
+}
+
+void
+LteUeRrcProtocolIdeal::DoSendRrcConnectionReestablishmentComplete (LteRrcSap::RrcConnectionReestablishmentComplete msg)
+{
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteEnbRrcSapProvider::RecvRrcConnectionReestablishmentComplete,
+ m_enbRrcSapProvider,
+ m_rnti,
+msg);
+}
+
+
+void
+LteUeRrcProtocolIdeal::SetEnbRrcSapProvider ()
+{
+ uint16_t cellId = m_rrc->GetCellId ();
+
+ // walk list of all nodes to get the peer eNB
+ Ptr<LteEnbNetDevice> enbDev;
+ NodeList::Iterator listEnd = NodeList::End ();
+ bool found = false;
+ for (NodeList::Iterator i = NodeList::Begin ();
+ (i != listEnd) && (!found);
+ ++i)
+ {
+ Ptr<Node> node = *i;
+ int nDevs = node->GetNDevices ();
+ for (int j = 0;
+ (j < nDevs) && (!found);
+ j++)
+ {
+ enbDev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
+ 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<LteEnbRrcProtocolIdeal> enbRrcProtocolIdeal = enbDev->GetRrc ()->GetObject<LteEnbRrcProtocolIdeal> ();
+ enbRrcProtocolIdeal->SetUeRrcSapProvider (m_rnti, m_ueRrcSapProvider);
+}
+
+
+NS_OBJECT_ENSURE_REGISTERED (LteEnbRrcProtocolIdeal);
+
+LteEnbRrcProtocolIdeal::LteEnbRrcProtocolIdeal ()
+ : m_enbRrcSapProvider (0)
+{
+ NS_LOG_FUNCTION (this);
+ m_enbRrcSapUser = new MemberLteEnbRrcSapUser<LteEnbRrcProtocolIdeal> (this);
+}
+
+LteEnbRrcProtocolIdeal::~LteEnbRrcProtocolIdeal ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+LteEnbRrcProtocolIdeal::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ delete m_enbRrcSapUser;
+}
+
+TypeId
+LteEnbRrcProtocolIdeal::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::LteEnbRrcProtocolIdeal")
+ .SetParent<Object> ()
+ .AddConstructor<LteEnbRrcProtocolIdeal> ()
+ ;
+ return tid;
+}
+
+void
+LteEnbRrcProtocolIdeal::SetLteEnbRrcSapProvider (LteEnbRrcSapProvider* p)
+{
+ m_enbRrcSapProvider = p;
+}
+
+LteEnbRrcSapUser*
+LteEnbRrcProtocolIdeal::GetLteEnbRrcSapUser ()
+{
+ return m_enbRrcSapUser;
+}
+
+void
+LteEnbRrcProtocolIdeal::SetCellId (uint16_t cellId)
+{
+ m_cellId = cellId;
+}
+
+LteUeRrcSapProvider*
+LteEnbRrcProtocolIdeal::GetUeRrcSapProvider (uint16_t rnti)
+{
+ std::map<uint16_t, LteUeRrcSapProvider*>::const_iterator it;
+ it = m_enbRrcSapProviderMap.find (rnti);
+ NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "could not find RNTI = " << rnti);
+ return it->second;
+}
+
+void
+LteEnbRrcProtocolIdeal::SetUeRrcSapProvider (uint16_t rnti, LteUeRrcSapProvider* p)
+{
+ std::map<uint16_t, LteUeRrcSapProvider*>::iterator it;
+ it = m_enbRrcSapProviderMap.find (rnti);
+ NS_ASSERT_MSG (it != m_enbRrcSapProviderMap.end (), "could not find RNTI = " << rnti);
+ it->second = p;
+}
+
+void
+LteEnbRrcProtocolIdeal::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<LteUeRrc> ueRrc;
+ // NodeList::Iterator listEnd = NodeList::End ();
+ // bool found = false;
+ // for (NodeList::Iterator i = NodeList::Begin (); (i != listEnd) && (found == false); i++)
+ // {
+ // Ptr<Node> node = *i;
+ // int nDevs = node->GetNDevices ();
+ // for (int j = 0; j < nDevs; j++)
+ // {
+ // Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
+ // 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
+LteEnbRrcProtocolIdeal::DoRemoveUe (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ m_enbRrcSapProviderMap.erase (rnti);
+}
+
+void
+LteEnbRrcProtocolIdeal::DoSendMasterInformationBlock (LteRrcSap::MasterInformationBlock msg)
+{
+ NS_LOG_FUNCTION (this);
+ for (std::map<uint16_t, LteUeRrcSapProvider*>::const_iterator it = m_enbRrcSapProviderMap.begin ();
+ it != m_enbRrcSapProviderMap.end ();
+ ++it)
+ {
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteUeRrcSapProvider::RecvMasterInformationBlock,
+ it->second,
+ msg);
+ }
+}
+
+void
+LteEnbRrcProtocolIdeal::DoSendSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg)
+{
+ NS_LOG_FUNCTION (this << m_cellId);
+ // walk list of all nodes to get UEs with this cellId
+ Ptr<LteUeRrc> ueRrc;
+ for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
+ {
+ Ptr<Node> node = *i;
+ int nDevs = node->GetNDevices ();
+ for (int j = 0; j < nDevs; ++j)
+ {
+ Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
+ if (ueDev != 0)
+ {
+ NS_LOG_LOGIC ("considering UE " << ueDev->GetImsi ());
+ Ptr<LteUeRrc> ueRrc = ueDev->GetRrc ();
+ if (ueRrc->GetCellId () == m_cellId)
+ {
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteUeRrcSapProvider::RecvSystemInformationBlockType1,
+ ueRrc->GetLteUeRrcSapProvider (),
+ msg);
+ }
+ }
+ }
+ }
+}
+
+void
+LteEnbRrcProtocolIdeal::DoSendSystemInformation (LteRrcSap::SystemInformation msg)
+{
+ NS_LOG_FUNCTION (this << m_cellId);
+ // walk list of all nodes to get UEs with this cellId
+ Ptr<LteUeRrc> ueRrc;
+ for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
+ {
+ Ptr<Node> node = *i;
+ int nDevs = node->GetNDevices ();
+ for (int j = 0; j < nDevs; ++j)
+ {
+ Ptr<LteUeNetDevice> ueDev = node->GetDevice (j)->GetObject <LteUeNetDevice> ();
+ if (ueDev != 0)
+ {
+ Ptr<LteUeRrc> 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_IDEAL_MSG_DELAY,
+ &LteUeRrcSapProvider::RecvSystemInformation,
+ ueRrc->GetLteUeRrcSapProvider (),
+ msg);
+ }
+ }
+ }
+ }
+}
+
+void
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionSetup (uint16_t rnti, LteRrcSap::RrcConnectionSetup msg)
+{
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteUeRrcSapProvider::RecvRrcConnectionSetup,
+ GetUeRrcSapProvider (rnti),
+ msg);
+}
+
+void
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionReconfiguration (uint16_t rnti, LteRrcSap::RrcConnectionReconfiguration msg)
+{
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteUeRrcSapProvider::RecvRrcConnectionReconfiguration,
+ GetUeRrcSapProvider (rnti),
+ msg);
+}
+
+void
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionReestablishment (uint16_t rnti, LteRrcSap::RrcConnectionReestablishment msg)
+{
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteUeRrcSapProvider::RecvRrcConnectionReestablishment,
+ GetUeRrcSapProvider (rnti),
+ msg);
+}
+
+void
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionReestablishmentReject (uint16_t rnti, LteRrcSap::RrcConnectionReestablishmentReject msg)
+{
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteUeRrcSapProvider::RecvRrcConnectionReestablishmentReject,
+ GetUeRrcSapProvider (rnti),
+ msg);
+}
+
+void
+LteEnbRrcProtocolIdeal::DoSendRrcConnectionRelease (uint16_t rnti, LteRrcSap::RrcConnectionRelease msg)
+{
+ Simulator::Schedule (RRC_IDEAL_MSG_DELAY,
+ &LteUeRrcSapProvider::RecvRrcConnectionRelease,
+ GetUeRrcSapProvider (rnti),
+ msg);
+}
+
+
+/*
+ * The purpose of LteEnbRrcProtocolIdeal 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 LteEnbRrcProtocolIdeal. 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<uint32_t, LteRrcSap::HandoverPreparationInfo> g_handoverPreparationInfoMsgMap;
+uint32_t g_handoverPreparationInfoMsgIdCounter = 0;
+
+/*
+ * This header encodes the map key discussed above. We keep this
+ * private since it should not be used outside this file.
+ *
+ */
+class IdealHandoverPreparationInfoHeader : 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
+IdealHandoverPreparationInfoHeader::GetMsgId ()
+{
+ return m_msgId;
+}
+
+void
+IdealHandoverPreparationInfoHeader::SetMsgId (uint32_t id)
+{
+ m_msgId = id;
+}
+
+
+TypeId
+IdealHandoverPreparationInfoHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::IdealHandoverPreparationInfoHeader")
+ .SetParent<Header> ()
+ .AddConstructor<IdealHandoverPreparationInfoHeader> ()
+ ;
+ return tid;
+}
+
+TypeId
+IdealHandoverPreparationInfoHeader::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+void IdealHandoverPreparationInfoHeader::Print (std::ostream &os) const
+{
+ os << " msgId=" << m_msgId;
+}
+
+uint32_t IdealHandoverPreparationInfoHeader::GetSerializedSize (void) const
+{
+ return 4;
+}
+
+void IdealHandoverPreparationInfoHeader::Serialize (Buffer::Iterator start) const
+{
+ start.WriteU32 (m_msgId);
+}
+
+uint32_t IdealHandoverPreparationInfoHeader::Deserialize (Buffer::Iterator start)
+{
+ m_msgId = start.ReadU32 ();
+ return GetSerializedSize ();
+}
+
+
+
+Ptr<Packet>
+LteEnbRrcProtocolIdeal::DoEncodeHandoverPreparationInformation (LteRrcSap::HandoverPreparationInfo msg)
+{
+ uint32_t msgId = ++g_handoverPreparationInfoMsgIdCounter;
+ NS_ASSERT_MSG (g_handoverPreparationInfoMsgMap.find (msgId) == g_handoverPreparationInfoMsgMap.end (), "msgId " << msgId << " already in use");
+ NS_LOG_INFO (" encoding msgId = " << msgId);
+ g_handoverPreparationInfoMsgMap.insert (std::pair<uint32_t, LteRrcSap::HandoverPreparationInfo> (msgId, msg));
+ IdealHandoverPreparationInfoHeader h;
+ h.SetMsgId (msgId);
+ Ptr<Packet> p = Create<Packet> ();
+ p->AddHeader (h);
+ return p;
+}
+
+LteRrcSap::HandoverPreparationInfo
+LteEnbRrcProtocolIdeal::DoDecodeHandoverPreparationInformation (Ptr<Packet> p)
+{
+ IdealHandoverPreparationInfoHeader h;
+ p->RemoveHeader (h);
+ uint32_t msgId = h.GetMsgId ();
+ NS_LOG_INFO (" decoding msgId = " << msgId);
+ std::map<uint32_t, LteRrcSap::HandoverPreparationInfo>::iterator it = g_handoverPreparationInfoMsgMap.find (msgId);
+ NS_ASSERT_MSG (it != g_handoverPreparationInfoMsgMap.end (), "msgId " << msgId << " not found");
+ LteRrcSap::HandoverPreparationInfo msg = it->second;
+ g_handoverPreparationInfoMsgMap.erase (it);
+ return msg;
+}
+
+
+
+std::map<uint32_t, LteRrcSap::RrcConnectionReconfiguration> g_handoverCommandMsgMap;
+uint32_t g_handoverCommandMsgIdCounter = 0;
+
+/*
+ * This header encodes the map key discussed above. We keep this
+ * private since it should not be used outside this file.
+ *
+ */
+class IdealHandoverCommandHeader : 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
+IdealHandoverCommandHeader::GetMsgId ()
+{
+ return m_msgId;
+}
+
+void
+IdealHandoverCommandHeader::SetMsgId (uint32_t id)
+{
+ m_msgId = id;
+}
+
+
+TypeId
+IdealHandoverCommandHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::IdealHandoverCommandHeader")
+ .SetParent<Header> ()
+ .AddConstructor<IdealHandoverCommandHeader> ()
+ ;
+ return tid;
+}
+
+TypeId
+IdealHandoverCommandHeader::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+void IdealHandoverCommandHeader::Print (std::ostream &os) const
+{
+ os << " msgId=" << m_msgId;
+}
+
+uint32_t IdealHandoverCommandHeader::GetSerializedSize (void) const
+{
+ return 4;
+}
+
+void IdealHandoverCommandHeader::Serialize (Buffer::Iterator start) const
+{
+ start.WriteU32 (m_msgId);
+}
+
+uint32_t IdealHandoverCommandHeader::Deserialize (Buffer::Iterator start)
+{
+ m_msgId = start.ReadU32 ();
+ return GetSerializedSize ();
+}
+
+
+
+Ptr<Packet>
+LteEnbRrcProtocolIdeal::DoEncodeHandoverCommand (LteRrcSap::RrcConnectionReconfiguration msg)
+{
+ uint32_t msgId = ++g_handoverCommandMsgIdCounter;
+ NS_ASSERT_MSG (g_handoverCommandMsgMap.find (msgId) == g_handoverCommandMsgMap.end (), "msgId " << msgId << " already in use");
+ NS_LOG_INFO (" encoding msgId = " << msgId);
+ g_handoverCommandMsgMap.insert (std::pair<uint32_t, LteRrcSap::RrcConnectionReconfiguration> (msgId, msg));
+ IdealHandoverCommandHeader h;
+ h.SetMsgId (msgId);
+ Ptr<Packet> p = Create<Packet> ();
+ p->AddHeader (h);
+ return p;
+}
+
+LteRrcSap::RrcConnectionReconfiguration
+LteEnbRrcProtocolIdeal::DoDecodeHandoverCommand (Ptr<Packet> p)
+{
+ IdealHandoverCommandHeader h;
+ p->RemoveHeader (h);
+ uint32_t msgId = h.GetMsgId ();
+ NS_LOG_INFO (" decoding msgId = " << msgId);
+ std::map<uint32_t, LteRrcSap::RrcConnectionReconfiguration>::iterator it = g_handoverCommandMsgMap.find (msgId);
+ NS_ASSERT_MSG (it != g_handoverCommandMsgMap.end (), "msgId " << msgId << " not found");
+ LteRrcSap::RrcConnectionReconfiguration msg = it->second;
+ g_handoverCommandMsgMap.erase (it);
+ return msg;
+}
+
+
+
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rrc-protocol-ideal.h Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,147 @@
+/* -*- 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 <nbaldo@cttc.es>
+ */
+
+
+#ifndef LTE_RRC_PROTOCOL_IDEAL_H
+#define LTE_RRC_PROTOCOL_IDEAL_H
+
+#include <stdint.h>
+#include <map>
+
+#include <ns3/ptr.h>
+#include <ns3/object.h>
+#include <ns3/lte-rrc-sap.h>
+
+namespace ns3 {
+
+class LteUeRrcSapProvider;
+class LteUeRrcSapUser;
+class LteEnbRrcSapProvider;
+class LteUeRrc;
+
+
+/**
+ * Models the transmission of RRC messages from the UE to the eNB in
+ * an ideal fashion, without errors and without consuming any radio
+ * resources.
+ *
+ */
+class LteUeRrcProtocolIdeal : public Object
+{
+ friend class MemberLteUeRrcSapUser<LteUeRrcProtocolIdeal>;
+
+public:
+
+ LteUeRrcProtocolIdeal ();
+ virtual ~LteUeRrcProtocolIdeal ();
+
+ // inherited from Object
+ virtual void DoDispose (void);
+ static TypeId GetTypeId (void);
+
+ void SetLteUeRrcSapProvider (LteUeRrcSapProvider* p);
+ LteUeRrcSapUser* GetLteUeRrcSapUser ();
+
+ void SetUeRrc (Ptr<LteUeRrc> 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<LteUeRrc> 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
+ * an ideal fashion, without errors and without consuming any radio
+ * resources.
+ *
+ */
+class LteEnbRrcProtocolIdeal : public Object
+{
+ friend class MemberLteEnbRrcSapUser<LteEnbRrcProtocolIdeal>;
+
+public:
+
+ LteEnbRrcProtocolIdeal ();
+ virtual ~LteEnbRrcProtocolIdeal ();
+
+ // 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<Packet> DoEncodeHandoverPreparationInformation (LteRrcSap::HandoverPreparationInfo msg);
+ LteRrcSap::HandoverPreparationInfo DoDecodeHandoverPreparationInformation (Ptr<Packet> p);
+ Ptr<Packet> DoEncodeHandoverCommand (LteRrcSap::RrcConnectionReconfiguration msg);
+ LteRrcSap::RrcConnectionReconfiguration DoDecodeHandoverCommand (Ptr<Packet> p);
+
+
+ uint16_t m_rnti;
+ uint16_t m_cellId;
+ LteEnbRrcSapProvider* m_enbRrcSapProvider;
+ LteEnbRrcSapUser* m_enbRrcSapUser;
+ std::map<uint16_t, LteUeRrcSapProvider*> m_enbRrcSapProviderMap;
+
+};
+
+
+
+}
+
+
+#endif // LTE_RRC_PROTOCOL_IDEAL_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/model/lte-rrc-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,848 @@
+/* -*- 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 <nbaldo@cttc.es>
+ */
+
+
+#ifndef LTE_RRC_SAP_H
+#define LTE_RRC_SAP_H
+
+#include <stdint.h>
+#include <list>
+
+#include <ns3/ptr.h>
+
+namespace ns3 {
+
+
+class LteRlcSapUser;
+class LtePdcpSapUser;
+class LteRlcSapProvider;
+class LtePdcpSapProvider;
+class Packet;
+
+/**
+ * Class holding definition common to all Ue/Enb SAP
+ * Users/Providers. See 3GPP TS 36.331 for reference.
+ * Note that only those values that are (expected to be) used by the
+ * ns-3 model are mentioned here. The naming of the variables that are
+ * defined here is the same of 36.331, except for removal of "-" and
+ * conversion to CamelCase or ALL_CAPS where needed in order to follow
+ * the ns-3 coding style. Due to the 1-to-1 mapping with TS 36.311,
+ * detailed doxygen documentation is omitted, so please refer to
+ * 36.311 for the meaning of these data structures / fields.
+ *
+ */
+class LteRrcSap
+{
+public:
+
+ // Information Elements
+
+ struct PlmnIdentityInfo
+ {
+ uint32_t plmnIdentity;
+ };
+
+ struct CellAccessRelatedInfo
+ {
+ PlmnIdentityInfo plmnIdentityInfo;
+ uint32_t cellIdentity;
+ bool csgIndication;
+ uint32_t csgIdentity;
+ };
+
+ struct FreqInfo
+ {
+ uint16_t ulCarrierFreq;
+ uint8_t ulBandwidth;
+ };
+
+ struct RlcConfig
+ {
+ enum
+ {
+ AM,
+ UM_BI_DIRECTIONAL,
+ UM_UNI_DIRECTIONAL_UL,
+ UM_UNI_DIRECTIONAL_DL
+ } choice;
+ };
+
+ struct LogicalChannelConfig
+ {
+ uint8_t priority;
+ uint16_t prioritizedBitRateKbps;
+ uint16_t bucketSizeDurationMs;
+ uint8_t logicalChannelGroup;
+ };
+
+ struct SoundingRsUlConfigCommon
+ {
+ enum {SETUP, RESET} type;
+ uint8_t srsBandwidthConfig;
+ uint8_t srsSubframeConfig;
+ };
+
+ struct SoundingRsUlConfigDedicated
+ {
+ enum {SETUP, RESET} type;
+ uint8_t srsBandwidth;
+ uint8_t srsConfigIndex;
+ };
+
+ struct AntennaInfoDedicated
+ {
+ uint8_t transmissionMode;
+ };
+
+
+ struct PhysicalConfigDedicated
+ {
+ bool haveSoundingRsUlConfigDedicated;
+ SoundingRsUlConfigDedicated soundingRsUlConfigDedicated;
+ bool haveAntennaInfoDedicated;
+ AntennaInfoDedicated antennaInfo;
+ };
+
+
+ struct SrbToAddMod
+ {
+ uint8_t srbIdentity;
+ LogicalChannelConfig logicalChannelConfig;
+ };
+
+ struct DrbToAddMod
+ {
+ uint8_t epsBearerIdentity;
+ uint8_t drbIdentity;
+ RlcConfig rlcConfig;
+ uint8_t logicalChannelIdentity;
+ LogicalChannelConfig logicalChannelConfig;
+ };
+
+ struct RadioResourceConfigCommon
+ {
+ };
+
+ struct RadioResourceConfigCommonSib
+ {
+ };
+
+ struct RadioResourceConfigDedicated
+ {
+ std::list<SrbToAddMod> srbToAddModList;
+ std::list<DrbToAddMod> drbToAddModList;
+ std::list<uint8_t> drbToReleaseList;
+ bool havePhysicalConfigDedicated;
+ PhysicalConfigDedicated physicalConfigDedicated;
+ };
+
+ struct MeasConfig
+ {
+
+ };
+
+ struct CarrierFreqEutra
+ {
+ uint16_t dlCarrierFreq;
+ uint16_t ulCarrierFreq;
+ };
+
+ struct CarrierBandwidthEutra
+ {
+ uint8_t dlBandwidth;
+ uint8_t ulBandwidth;
+ };
+
+ struct RachConfigDedicated
+ {
+ uint8_t raPreambleIndex;
+ uint8_t raPrachMaskIndex;
+ };
+
+ struct MobilityControlInfo
+ {
+ uint16_t targetPhysCellId;
+ bool haveCarrierFreq;
+ CarrierFreqEutra carrierFreq;
+ bool haveCarrierBandwidth;
+ CarrierBandwidthEutra carrierBandwidth;
+ uint16_t newUeIdentity;
+ RadioResourceConfigCommon radioResourceConfigCommon;
+ bool haveRachConfigDedicated;
+ RachConfigDedicated rachConfigDedicated;
+ };
+
+ struct ReestabUeIdentity
+ {
+ uint16_t cRnti;
+ uint16_t physCellId;
+ };
+
+ enum ReestablishmentCause
+ {
+ RECONFIGURATION_FAILURE,
+ HANDOVER_FAILURE,
+ OTHER_FAILURE
+ };
+
+ struct MasterInformationBlock
+ {
+ uint8_t dlBandwidth;
+ uint8_t systemFrameNumber;
+ };
+
+ struct SystemInformationBlockType1
+ {
+ CellAccessRelatedInfo cellAccessRelatedInfo;
+ };
+
+ struct SystemInformationBlockType2
+ {
+ RadioResourceConfigCommonSib radioResourceConfigCommon;
+ FreqInfo freqInfo;
+ };
+
+ struct SystemInformation
+ {
+ bool haveSib2;
+ SystemInformationBlockType2 sib2;
+ }
+ ;
+ struct AsConfig
+ {
+ MeasConfig sourceMeasConfig;
+ RadioResourceConfigDedicated sourceRadioResourceConfig;
+ uint16_t sourceUeIdentity;
+ MasterInformationBlock sourceMasterInformationBlock;
+ SystemInformationBlockType1 sourceSystemInformationBlockType1;
+ uint16_t sourceDlCarrierFreq;
+ };
+
+
+ // Messages
+
+ struct RrcConnectionRequest
+ {
+ uint64_t ueIdentity;
+ };
+
+ struct RrcConnectionSetup
+ {
+ uint8_t rrcTransactionIdentifier;
+ RadioResourceConfigDedicated radioResourceConfigDedicated;
+ };
+
+ struct RrcConnectionSetupCompleted
+ {
+ uint8_t rrcTransactionIdentifier;
+ };
+
+ struct RrcConnectionReconfiguration
+ {
+ uint8_t rrcTransactionIdentifier;
+ bool haveMeasConfig;
+ MeasConfig measConfig;
+ bool haveMobilityControlInfo;
+ MobilityControlInfo mobilityControlInfo;
+ bool haveRadioResourceConfigDedicated;
+ RadioResourceConfigDedicated radioResourceConfigDedicated;
+ };
+
+ struct RrcConnectionReconfigurationCompleted
+ {
+ uint8_t rrcTransactionIdentifier;
+ };
+
+
+ struct RrcConnectionReestablishmentRequest
+ {
+ ReestabUeIdentity ueIdentity;
+ ReestablishmentCause reestablishmentCause;
+ };
+
+ struct RrcConnectionReestablishment
+ {
+ uint8_t rrcTransactionIdentifier;
+ RadioResourceConfigDedicated radioResourceConfigDedicated;
+ };
+
+ struct RrcConnectionReestablishmentComplete
+ {
+ uint8_t rrcTransactionIdentifier;
+ };
+
+ struct RrcConnectionReestablishmentReject
+ {
+ };
+
+ struct RrcConnectionRelease
+ {
+ };
+
+ struct HandoverPreparationInfo
+ {
+ AsConfig asConfig;
+ };
+
+};
+
+
+
+/**
+ * Service Access Point (SAP) used by the UE RRC to send messages to
+ * the eNB. Each method defined in this class correspond to the
+ * transmission of a message that is defined in section 6.2.2 of TS
+ * 36.331.
+ */
+class LteUeRrcSapUser : public LteRrcSap
+{
+public:
+
+ struct SetupParameters
+ {
+ LteRlcSapProvider* srb0SapProvider;
+ LtePdcpSapProvider* srb1SapProvider;
+ };
+
+ virtual void Setup (SetupParameters params) = 0;
+ virtual void Reestablish () = 0;
+ virtual void SendRrcConnectionRequest (RrcConnectionRequest msg) = 0;
+ virtual void SendRrcConnectionSetupCompleted (RrcConnectionSetupCompleted msg) = 0;
+ virtual void SendRrcConnectionReconfigurationCompleted (RrcConnectionReconfigurationCompleted msg) = 0;
+ virtual void SendRrcConnectionReestablishmentRequest (RrcConnectionReestablishmentRequest msg) = 0;
+ virtual void SendRrcConnectionReestablishmentComplete (RrcConnectionReestablishmentComplete msg) = 0;
+
+};
+
+
+/**
+ * Service Access Point (SAP) used to let the UE RRC receive a message
+ * from the eNB RRC. Each method defined in this class correspond to
+ * the reception of a message that is defined in section 6.2.2 of TS
+ * 36.331.
+ */
+class LteUeRrcSapProvider : public LteRrcSap
+{
+public:
+
+ virtual void RecvMasterInformationBlock (MasterInformationBlock msg) = 0;
+ virtual void RecvSystemInformationBlockType1 (SystemInformationBlockType1 msg) = 0;
+ virtual void RecvSystemInformation (SystemInformation msg) = 0;
+ virtual void RecvRrcConnectionSetup (RrcConnectionSetup msg) = 0;
+ virtual void RecvRrcConnectionReconfiguration (RrcConnectionReconfiguration msg) = 0;
+ virtual void RecvRrcConnectionReestablishment (RrcConnectionReestablishment msg) = 0;
+ virtual void RecvRrcConnectionReestablishmentReject (RrcConnectionReestablishmentReject msg) = 0;
+ virtual void RecvRrcConnectionRelease (RrcConnectionRelease msg) = 0;
+
+};
+
+
+/**
+ * Service Access Point (SAP) used by the eNB RRC to send messages to
+ * the UE RC. Each method defined in this class correspond to
+ * the transmission of a message that is defined in section 6.2.2 of TS
+ * 36.331.
+ */
+class LteEnbRrcSapUser : public LteRrcSap
+{
+public:
+
+ struct SetupUeParameters
+ {
+ LteRlcSapProvider* srb0SapProvider;
+ LtePdcpSapProvider* srb1SapProvider;
+ };
+
+ virtual void SetupUe (uint16_t rnti, SetupUeParameters params) = 0;
+ virtual void RemoveUe (uint16_t rnti) = 0;
+ virtual void SendSystemInformationBlockType1 (SystemInformationBlockType1 msg) = 0;
+ virtual void SendSystemInformation (SystemInformation msg) = 0;
+ virtual void SendRrcConnectionSetup (uint16_t rnti, RrcConnectionSetup msg) = 0;
+ virtual void SendRrcConnectionReconfiguration (uint16_t rnti, RrcConnectionReconfiguration msg) = 0;
+ virtual void SendRrcConnectionReestablishment (uint16_t rnti, RrcConnectionReestablishment msg) = 0;
+ virtual void SendRrcConnectionReestablishmentReject (uint16_t rnti, RrcConnectionReestablishmentReject msg) = 0;
+ virtual void SendRrcConnectionRelease (uint16_t rnti, RrcConnectionRelease msg) = 0;
+ virtual Ptr<Packet> EncodeHandoverPreparationInformation (HandoverPreparationInfo msg) = 0;
+ virtual HandoverPreparationInfo DecodeHandoverPreparationInformation (Ptr<Packet> p) = 0;
+ virtual Ptr<Packet> EncodeHandoverCommand (RrcConnectionReconfiguration msg) = 0;
+ virtual RrcConnectionReconfiguration DecodeHandoverCommand (Ptr<Packet> p) = 0;
+
+};
+
+
+/**
+ * Service Access Point (SAP) used to let the eNB RRC receive a
+ * message from a UE RRC. Each method defined in this class correspond to
+ * the reception of a message that is defined in section 6.2.2 of TS
+ * 36.331.
+ */
+class LteEnbRrcSapProvider : public LteRrcSap
+{
+public:
+
+
+ struct CompleteSetupUeParameters
+ {
+ LteRlcSapUser* srb0SapUser;
+ LtePdcpSapUser* srb1SapUser;
+ };
+
+ virtual void CompleteSetupUe (uint16_t rnti, CompleteSetupUeParameters params) = 0;
+ virtual void RecvRrcConnectionRequest (uint16_t rnti, RrcConnectionRequest msg) = 0;
+ virtual void RecvRrcConnectionSetupCompleted (uint16_t rnti, RrcConnectionSetupCompleted msg) = 0;
+ virtual void RecvRrcConnectionReconfigurationCompleted (uint16_t rnti, RrcConnectionReconfigurationCompleted msg) = 0;
+ virtual void RecvRrcConnectionReestablishmentRequest (uint16_t rnti, RrcConnectionReestablishmentRequest msg) = 0;
+ virtual void RecvRrcConnectionReestablishmentComplete (uint16_t rnti, RrcConnectionReestablishmentComplete msg) = 0;
+
+};
+
+
+
+
+
+
+////////////////////////////////////
+// templates
+////////////////////////////////////
+
+
+/**
+ * Template for the implementation of the LteUeRrcSapUser as a member
+ * of an owner class of type C to which all methods are forwarded
+ *
+ */
+template <class C>
+class MemberLteUeRrcSapUser : public LteUeRrcSapUser
+{
+public:
+ MemberLteUeRrcSapUser (C* owner);
+
+ // inherited from LteUeRrcSapUser
+ virtual void Setup (SetupParameters params);
+ virtual void Reestablish ();
+ virtual void SendRrcConnectionRequest (RrcConnectionRequest msg);
+ virtual void SendRrcConnectionSetupCompleted (RrcConnectionSetupCompleted msg);
+ virtual void SendRrcConnectionReconfigurationCompleted (RrcConnectionReconfigurationCompleted msg);
+ virtual void SendRrcConnectionReestablishmentRequest (RrcConnectionReestablishmentRequest msg);
+ virtual void SendRrcConnectionReestablishmentComplete (RrcConnectionReestablishmentComplete msg);
+
+private:
+ MemberLteUeRrcSapUser ();
+ C* m_owner;
+};
+
+template <class C>
+MemberLteUeRrcSapUser<C>::MemberLteUeRrcSapUser (C* owner)
+ : m_owner (owner)
+{
+}
+
+template <class C>
+MemberLteUeRrcSapUser<C>::MemberLteUeRrcSapUser ()
+{
+}
+
+template <class C>
+void
+MemberLteUeRrcSapUser<C>::Setup (SetupParameters params)
+{
+ m_owner->DoSetup (params);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapUser<C>::Reestablish ()
+{
+ m_owner->DoReestablish ();
+}
+
+template <class C>
+void
+MemberLteUeRrcSapUser<C>::SendRrcConnectionRequest (RrcConnectionRequest msg)
+{
+ m_owner->DoSendRrcConnectionRequest (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapUser<C>::SendRrcConnectionSetupCompleted (RrcConnectionSetupCompleted msg)
+{
+ m_owner->DoSendRrcConnectionSetupCompleted (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapUser<C>::SendRrcConnectionReconfigurationCompleted (RrcConnectionReconfigurationCompleted msg)
+{
+ m_owner->DoSendRrcConnectionReconfigurationCompleted (msg) ;
+}
+
+template <class C>
+void
+MemberLteUeRrcSapUser<C>::SendRrcConnectionReestablishmentRequest (RrcConnectionReestablishmentRequest msg)
+{
+ m_owner->DoSendRrcConnectionReestablishmentRequest (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapUser<C>::SendRrcConnectionReestablishmentComplete (RrcConnectionReestablishmentComplete msg)
+{
+ m_owner->DoSendRrcConnectionReestablishmentComplete (msg);
+}
+
+/**
+ * Template for the implementation of the LteUeRrcSapProvider as a member
+ * of an owner class of type C to which all methods are forwarded
+ *
+ */
+template <class C>
+class MemberLteUeRrcSapProvider : public LteUeRrcSapProvider
+{
+public:
+ MemberLteUeRrcSapProvider (C* owner);
+
+ // methods inherited from LteUeRrcSapProvider go here
+ virtual void RecvMasterInformationBlock (MasterInformationBlock msg);
+ virtual void RecvSystemInformationBlockType1 (SystemInformationBlockType1 msg);
+ virtual void RecvSystemInformation (SystemInformation msg);
+ virtual void RecvRrcConnectionSetup (RrcConnectionSetup msg);
+ virtual void RecvRrcConnectionReconfiguration (RrcConnectionReconfiguration msg);
+ virtual void RecvRrcConnectionReestablishment (RrcConnectionReestablishment msg);
+ virtual void RecvRrcConnectionReestablishmentReject (RrcConnectionReestablishmentReject msg);
+ virtual void RecvRrcConnectionRelease (RrcConnectionRelease msg);
+
+private:
+ MemberLteUeRrcSapProvider ();
+ C* m_owner;
+};
+
+template <class C>
+MemberLteUeRrcSapProvider<C>::MemberLteUeRrcSapProvider (C* owner)
+ : m_owner (owner)
+{
+}
+
+template <class C>
+MemberLteUeRrcSapProvider<C>::MemberLteUeRrcSapProvider ()
+{
+}
+
+template <class C>
+void
+MemberLteUeRrcSapProvider<C>::RecvMasterInformationBlock (MasterInformationBlock msg)
+{
+ m_owner->DoRecvMasterInformationBlock (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapProvider<C>::RecvSystemInformationBlockType1 (SystemInformationBlockType1 msg)
+{
+ m_owner->DoRecvSystemInformationBlockType1 (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapProvider<C>::RecvSystemInformation (SystemInformation msg)
+{
+ m_owner->DoRecvSystemInformation (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionSetup (RrcConnectionSetup msg)
+{
+ m_owner->DoRecvRrcConnectionSetup (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionReconfiguration (RrcConnectionReconfiguration msg)
+{
+ m_owner->DoRecvRrcConnectionReconfiguration (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionReestablishment (RrcConnectionReestablishment msg)
+{
+ m_owner->DoRecvRrcConnectionReestablishment (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionReestablishmentReject (RrcConnectionReestablishmentReject msg)
+{
+ m_owner->DoRecvRrcConnectionReestablishmentReject (msg);
+}
+
+template <class C>
+void
+MemberLteUeRrcSapProvider<C>::RecvRrcConnectionRelease (RrcConnectionRelease msg)
+{
+ m_owner->DoRecvRrcConnectionRelease (msg);
+}
+
+
+
+/**
+ * Template for the implementation of the LteEnbRrcSapUser as a member
+ * of an owner class of type C to which all methods are forwarded
+ *
+ */
+template <class C>
+class MemberLteEnbRrcSapUser : public LteEnbRrcSapUser
+{
+public:
+ MemberLteEnbRrcSapUser (C* owner);
+
+ // inherited from LteEnbRrcSapUser
+
+ virtual void SetupUe (uint16_t rnti, SetupUeParameters params);
+ virtual void RemoveUe (uint16_t rnti);
+ virtual void SendMasterInformationBlock (MasterInformationBlock msg);
+ virtual void SendSystemInformationBlockType1 (SystemInformationBlockType1 msg);
+ virtual void SendSystemInformation (SystemInformation msg);
+ virtual void SendRrcConnectionSetup (uint16_t rnti, RrcConnectionSetup msg);
+ virtual void SendRrcConnectionReconfiguration (uint16_t rnti, RrcConnectionReconfiguration msg);
+ virtual void SendRrcConnectionReestablishment (uint16_t rnti, RrcConnectionReestablishment msg);
+ virtual void SendRrcConnectionReestablishmentReject (uint16_t rnti, RrcConnectionReestablishmentReject msg);
+ virtual void SendRrcConnectionRelease (uint16_t rnti, RrcConnectionRelease msg);
+ virtual Ptr<Packet> EncodeHandoverPreparationInformation (HandoverPreparationInfo msg);
+ virtual HandoverPreparationInfo DecodeHandoverPreparationInformation (Ptr<Packet> p);
+ virtual Ptr<Packet> EncodeHandoverCommand (RrcConnectionReconfiguration msg);
+ virtual RrcConnectionReconfiguration DecodeHandoverCommand (Ptr<Packet> p);
+
+private:
+ MemberLteEnbRrcSapUser ();
+ C* m_owner;
+};
+
+template <class C>
+MemberLteEnbRrcSapUser<C>::MemberLteEnbRrcSapUser (C* owner)
+ : m_owner (owner)
+{
+}
+
+template <class C>
+MemberLteEnbRrcSapUser<C>::MemberLteEnbRrcSapUser ()
+{
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SetupUe (uint16_t rnti, SetupUeParameters params)
+{
+ m_owner->DoSetupUe (rnti, params);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::RemoveUe (uint16_t rnti)
+{
+ m_owner->DoRemoveUe (rnti);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SendMasterInformationBlock (MasterInformationBlock msg)
+{
+ m_owner->DoSendMasterInformationBlock (msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SendSystemInformationBlockType1 (SystemInformationBlockType1 msg)
+{
+ m_owner->DoSendSystemInformationBlockType1 (msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SendSystemInformation (SystemInformation msg)
+{
+ m_owner->DoSendSystemInformation (msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionSetup (uint16_t rnti, RrcConnectionSetup msg)
+{
+ m_owner->DoSendRrcConnectionSetup (rnti, msg) ;
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionReconfiguration (uint16_t rnti, RrcConnectionReconfiguration msg)
+{
+ m_owner->DoSendRrcConnectionReconfiguration (rnti, msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionReestablishment (uint16_t rnti, RrcConnectionReestablishment msg)
+{
+ m_owner->DoSendRrcConnectionReestablishment (rnti, msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionReestablishmentReject (uint16_t rnti, RrcConnectionReestablishmentReject msg)
+{
+ m_owner->DoSendRrcConnectionReestablishmentReject (rnti, msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapUser<C>::SendRrcConnectionRelease (uint16_t rnti, RrcConnectionRelease msg)
+{
+ m_owner->DoSendRrcConnectionRelease (rnti, msg);
+}
+
+template <class C>
+Ptr<Packet>
+MemberLteEnbRrcSapUser<C>::EncodeHandoverPreparationInformation (HandoverPreparationInfo msg)
+{
+ return m_owner->DoEncodeHandoverPreparationInformation (msg);
+}
+
+template <class C>
+LteRrcSap::HandoverPreparationInfo
+MemberLteEnbRrcSapUser<C>::DecodeHandoverPreparationInformation (Ptr<Packet> p)
+{
+ return m_owner->DoDecodeHandoverPreparationInformation (p);
+}
+
+
+template <class C>
+Ptr<Packet>
+MemberLteEnbRrcSapUser<C>::EncodeHandoverCommand (RrcConnectionReconfiguration msg)
+{
+ return m_owner->DoEncodeHandoverCommand (msg);
+}
+
+template <class C>
+LteRrcSap::RrcConnectionReconfiguration
+MemberLteEnbRrcSapUser<C>::DecodeHandoverCommand (Ptr<Packet> p)
+{
+ return m_owner->DoDecodeHandoverCommand (p);
+}
+
+/**
+ * Template for the implementation of the LteEnbRrcSapProvider as a member
+ * of an owner class of type C to which all methods are forwarded
+ *
+ */
+template <class C>
+class MemberLteEnbRrcSapProvider : public LteEnbRrcSapProvider
+{
+public:
+ MemberLteEnbRrcSapProvider (C* owner);
+
+ // methods inherited from LteEnbRrcSapProvider go here
+
+ virtual void CompleteSetupUe (uint16_t rnti, CompleteSetupUeParameters params);
+ virtual void RecvRrcConnectionRequest (uint16_t rnti, RrcConnectionRequest msg);
+ virtual void RecvRrcConnectionSetupCompleted (uint16_t rnti, RrcConnectionSetupCompleted msg);
+ virtual void RecvRrcConnectionReconfigurationCompleted (uint16_t rnti, RrcConnectionReconfigurationCompleted msg);
+ virtual void RecvRrcConnectionReestablishmentRequest (uint16_t rnti, RrcConnectionReestablishmentRequest msg);
+ virtual void RecvRrcConnectionReestablishmentComplete (uint16_t rnti, RrcConnectionReestablishmentComplete msg);
+
+private:
+ MemberLteEnbRrcSapProvider ();
+ C* m_owner;
+};
+
+template <class C>
+MemberLteEnbRrcSapProvider<C>::MemberLteEnbRrcSapProvider (C* owner)
+ : m_owner (owner)
+{
+}
+
+template <class C>
+MemberLteEnbRrcSapProvider<C>::MemberLteEnbRrcSapProvider ()
+{
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapProvider<C>::CompleteSetupUe (uint16_t rnti, CompleteSetupUeParameters params)
+{
+ m_owner->DoCompleteSetupUe (rnti, params);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionRequest (uint16_t rnti, RrcConnectionRequest msg)
+{
+ m_owner->DoRecvRrcConnectionRequest (rnti, msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionSetupCompleted (uint16_t rnti, RrcConnectionSetupCompleted msg)
+{
+ m_owner->DoRecvRrcConnectionSetupCompleted (rnti, msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionReconfigurationCompleted (uint16_t rnti, RrcConnectionReconfigurationCompleted msg)
+{
+ m_owner->DoRecvRrcConnectionReconfigurationCompleted (rnti, msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionReestablishmentRequest (uint16_t rnti, RrcConnectionReestablishmentRequest msg)
+{
+ m_owner->DoRecvRrcConnectionReestablishmentRequest (rnti, msg);
+}
+
+template <class C>
+void
+MemberLteEnbRrcSapProvider<C>::RecvRrcConnectionReestablishmentComplete (uint16_t rnti, RrcConnectionReestablishmentComplete msg)
+{
+ m_owner->DoRecvRrcConnectionReestablishmentComplete (rnti, msg);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+} // namespace ns3
+
+
+#endif // LTE_RRC_SAP_H
+
+
+
+
--- a/src/lte/model/lte-spectrum-phy.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-spectrum-phy.cc Tue Oct 30 16:02:07 2012 +0100
@@ -217,6 +217,12 @@
m_channel = c;
}
+Ptr<SpectrumChannel>
+LteSpectrumPhy::GetChannel ()
+{
+ return m_channel;
+}
+
Ptr<const SpectrumModel>
LteSpectrumPhy::GetRxSpectrumModel () const
{
@@ -451,6 +457,7 @@
(ii) the power transmission
*/
NS_ASSERT (m_txPsd);
+ NS_LOG_LOGIC (this << " m_txPsd: " << *m_txPsd);
// we need to convey some PHY meta information to the receiver
// to be used for simulation purposes (e.g., the CellId). This
--- a/src/lte/model/lte-spectrum-phy.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-spectrum-phy.h Tue Oct 30 16:02:07 2012 +0100
@@ -307,6 +307,13 @@
*/
void SetTransmissionMode (uint8_t txMode);
+
+ /**
+ *
+ * \return the previously set channel
+ */
+ Ptr<SpectrumChannel> GetChannel ();
+
friend class LteUePhy;
--- a/src/lte/model/lte-ue-cmac-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-cmac-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -41,16 +41,54 @@
{
public:
virtual ~LteUeCmacSapProvider ();
- /**
- * called by the RRC after going to RRC connected
- *
+
+ /**
+ * tell the MAC to start a contention-based random access procedure,
+ * e.g., to perform RRC connection establishment
+ *
+ */
+ virtual void StartContentionBasedRandomAccessProcedure () = 0;
+
+ /**
+ * tell the MAC to start a non-contention-based random access
+ * procedure, e.g., as a consequence of handover
+ *
* \param rnti
+ * \param preambleId
+ * \param prachMask
*/
- virtual void ConfigureUe (uint16_t rnti) = 0;
+ virtual void StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask) = 0;
+
- virtual void AddLc (uint8_t lcId, LteMacSapUser* msu) = 0;
+ struct LogicalChannelConfig
+ {
+ uint8_t priority;
+ uint16_t prioritizedBitRateKbps;
+ uint16_t bucketSizeDurationMs;
+ uint8_t logicalChannelGroup;
+ };
+
+ /**
+ * add a new Logical Channel (LC)
+ *
+ * \param lcId the ID of the LC
+ * \param lcConfig the LC configuration provided by the RRC
+ * \param msu the corresponding LteMacSapUser
+ */
+ virtual void AddLc (uint8_t lcId, LogicalChannelConfig lcConfig, LteMacSapUser* msu) = 0;
+ /**
+ * remove an existing LC
+ *
+ * \param lcId
+ */
virtual void RemoveLc (uint8_t lcId) = 0;
+
+ /**
+ * reset the MAC
+ *
+ */
+ virtual void Reset () = 0;
};
@@ -64,8 +102,27 @@
class LteUeCmacSapUser
{
public:
+
virtual ~LteUeCmacSapUser ();
- virtual void LcConfigCompleted () = 0;
+
+ /**
+ *
+ *
+ * \param rnti the T-C-RNTI, which will eventually become the C-RNTI after contention resolution
+ */
+ virtual void SetTemporaryCellRnti (uint16_t rnti) = 0;
+
+ /**
+ * Notify the RRC that the MAC Random Access procedure completed successfully
+ *
+ */
+ virtual void NotifyRandomAccessSuccessful () = 0;
+
+ /**
+ * Notify the RRC that the MAC Random Access procedure failed
+ *
+ */
+ virtual void NotifyRandomAccessFailed () = 0;
};
--- a/src/lte/model/lte-ue-cphy-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-cphy-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -25,6 +25,8 @@
#include <stdint.h>
#include <ns3/ptr.h>
+#include <ns3/lte-rrc-sap.h>
+
namespace ns3 {
@@ -48,24 +50,24 @@
/**
* tell the PHY to synchronize with a given eNB for communication purposes
*
- * \param enbPhy a pointer to the PHY of the eNB (wild hack, might go away in later versions)
* \param cellId the ID of the eNB
+ * \param dlEarfcn the carrier frequency (EARFCN) in downlink
*/
- virtual void SyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId) = 0;
+ virtual void SyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn) = 0;
/**
- *
- * \param dlEarfcn the carrier frequency (EARFCN) in downlink
- * \param ulEarfcn the carrier frequency (EARFCN) in downlink
- */
- virtual void SetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn) = 0;
-
- /**
- * \param ulBandwidth the UL bandwidth in PRBs
* \param dlBandwidth the DL bandwidth in PRBs
*/
- virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth) = 0;
-
+ virtual void SetDlBandwidth (uint8_t dlBandwidth) = 0;
+
+ /**
+ * Configure uplink (normally done after reception of SIB2)
+ *
+ * \param ulEarfcn the carrier frequency (EARFCN) in uplink
+ * \param ulBandwidth the UL bandwidth in PRBs
+ */
+ virtual void ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth) = 0;
+
/**
*
* \param rnti the cell-specific UE identifier
@@ -99,6 +101,13 @@
* destructor
*/
virtual ~LteUeCphySapUser ();
+
+
+ /**
+ *
+ * \param mib the Master Information Block received on the BCH
+ */
+ virtual void RecvMasterInformationBlock (LteRrcSap::MasterInformationBlock mib) = 0;
};
@@ -116,9 +125,9 @@
MemberLteUeCphySapProvider (C* owner);
// inherited from LteUeCphySapProvider
- virtual void SyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
- virtual void SetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
- virtual void SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
+ virtual void SyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn);
+ virtual void SetDlBandwidth (uint8_t ulBandwidth);
+ virtual void ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth);
virtual void SetRnti (uint16_t rnti);
virtual void SetTransmissionMode (uint8_t txMode);
virtual void SetSrsConfigurationIndex (uint16_t srcCi);
@@ -141,23 +150,23 @@
template <class C>
void
-MemberLteUeCphySapProvider<C>::SyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId)
+MemberLteUeCphySapProvider<C>::SyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn)
{
- m_owner->DoSyncronizeWithEnb (enbDevice, cellId);
+ m_owner->DoSyncronizeWithEnb (cellId, dlEarfcn);
}
template <class C>
void
-MemberLteUeCphySapProvider<C>::SetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn)
+MemberLteUeCphySapProvider<C>::SetDlBandwidth (uint8_t dlBandwidth)
{
- m_owner->DoSetEarfcn (dlEarfcn, ulEarfcn);
+ m_owner->DoSetDlBandwidth (dlBandwidth);
}
template <class C>
void
-MemberLteUeCphySapProvider<C>::SetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth)
+MemberLteUeCphySapProvider<C>::ConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth)
{
- m_owner->DoSetBandwidth (ulBandwidth, dlBandwidth);
+ m_owner->DoConfigureUplink (ulEarfcn, ulBandwidth);
}
template <class C>
@@ -195,6 +204,7 @@
MemberLteUeCphySapUser (C* owner);
// methods inherited from LteUeCphySapUser go here
+ virtual void RecvMasterInformationBlock (LteRrcSap::MasterInformationBlock mib);
private:
MemberLteUeCphySapUser ();
@@ -212,6 +222,13 @@
{
}
+template <class C>
+void
+MemberLteUeCphySapUser<C>::RecvMasterInformationBlock (LteRrcSap::MasterInformationBlock mib)
+{
+ m_owner->DoRecvMasterInformationBlock (mib);
+}
+
--- a/src/lte/model/lte-ue-mac.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-mac.cc Tue Oct 30 16:02:07 2012 +0100
@@ -53,9 +53,11 @@
UeMemberLteUeCmacSapProvider (LteUeMac* mac);
// inherited from LteUeCmacSapProvider
- virtual void ConfigureUe (uint16_t rnti);
- virtual void AddLc (uint8_t lcId, LteMacSapUser* msu);
+ virtual void StartContentionBasedRandomAccessProcedure ();
+ virtual void StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask);
+ virtual void AddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu);
virtual void RemoveLc (uint8_t lcId);
+ virtual void Reset ();
private:
LteUeMac* m_mac;
@@ -67,16 +69,23 @@
{
}
-void
-UeMemberLteUeCmacSapProvider::ConfigureUe (uint16_t rnti)
+ void
+UeMemberLteUeCmacSapProvider::StartContentionBasedRandomAccessProcedure ()
{
- m_mac->DoConfigureUe (rnti);
+ m_mac->DoStartContentionBasedRandomAccessProcedure ();
}
+ void
+UeMemberLteUeCmacSapProvider::StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
+{
+ m_mac->DoStartNonContentionBasedRandomAccessProcedure (rnti, preambleId, prachMask);
+}
+
+
void
-UeMemberLteUeCmacSapProvider::AddLc (uint8_t lcId, LteMacSapUser* msu)
+UeMemberLteUeCmacSapProvider::AddLc (uint8_t lcId, LogicalChannelConfig lcConfig, LteMacSapUser* msu)
{
- m_mac->DoAddLc (lcId, msu);
+ m_mac->DoAddLc (lcId, lcConfig, msu);
}
void
@@ -85,6 +94,12 @@
m_mac->DoRemoveLc (lcid);
}
+void
+UeMemberLteUeCmacSapProvider::Reset ()
+{
+ m_mac->DoReset ();
+}
+
class UeMemberLteMacSapProvider : public LteMacSapProvider
{
public:
@@ -178,8 +193,9 @@
LteUeMac::LteUeMac ()
: m_bsrPeriodicity (MilliSeconds (1)), // ideal behavior
- m_bsrLast (MilliSeconds (0)),
- m_freshUlBsr (false)
+ m_bsrLast (MilliSeconds (0)),
+ m_freshUlBsr (false),
+ m_rnti (0)
{
NS_LOG_FUNCTION (this);
@@ -277,29 +293,40 @@
LteUeMac::SendReportBufferStatus (void)
{
NS_LOG_FUNCTION (this);
+
+ if (m_rnti == 0)
+ {
+ NS_LOG_INFO ("MAC not initialized, BSR deferred");
+ return;
+ }
+
if (m_ulBsrReceived.size () == 0)
{
- return; // No BSR report to transmit
+ NS_LOG_INFO ("No BSR report to transmit");
+ return;
}
MacCeListElement_s bsr;
bsr.m_rnti = m_rnti;
bsr.m_macCeType = MacCeListElement_s::BSR;
- // BSR is reported for each LCG. As a simplification, we consider that all LCs belong to the first LCG.
+ // BSR is reported for each LCG
std::map <uint8_t, uint64_t>::iterator it;
- int queue = 0;
+ std::vector<uint32_t> queue (4, 0); // one value per each of the 4 LCGs, initialized to 0
for (it = m_ulBsrReceived.begin (); it != m_ulBsrReceived.end (); it++)
{
- queue += (*it).second;
-
+ uint8_t lcid = it->first;
+ std::map <uint8_t, LcInfo>::iterator lcInfoMapIt;
+ lcInfoMapIt = m_lcInfoMap.find (lcid);
+ NS_ASSERT (lcInfoMapIt != m_lcInfoMap.end ());
+ uint8_t lcg = lcInfoMapIt->second.lcConfig.logicalChannelGroup;
+ queue.at (lcg) += (*it).second;
}
- int index = BufferSizeLevelBsr::BufferSize2BsrId (queue);
- bsr.m_macCeValue.m_bufferStatus.push_back (index);
+
// FF API says that all 4 LCGs are always present
- // we do so but reporting a 0 size for all other LCGs
- bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (0));
- bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (0));
- bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (0));
+ bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (0)));
+ bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (1)));
+ bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (2)));
+ bsr.m_macCeValue.m_bufferStatus.push_back (BufferSizeLevelBsr::BufferSize2BsrId (queue.at (3)));
// create the feedback to eNB
Ptr<BsrLteControlMessage> msg = Create<BsrLteControlMessage> ();
@@ -308,27 +335,74 @@
}
-void
-LteUeMac::DoConfigureUe (uint16_t rnti)
+void
+LteUeMac::DoStartContentionBasedRandomAccessProcedure ()
+{
+ NS_LOG_FUNCTION (this);
+ static uint32_t prachIdCounter = 256;
+ prachIdCounter += 2;
+ m_prachId = prachIdCounter;
+ NS_LOG_INFO ("sending RACH preamble " << m_prachId);
+
+
+ // Since regular UL LteControlMessages need m_ulConfigured = true in
+ // order to be sent by the UE, the rach preamble needs to be sent
+ // with a dedicated primitive (not
+ // m_uePhySapProvider->SendLteControlMessage (msg)) so that it can
+ // bypass the m_ulConfigured flag. This is reasonable, since In fact
+ // the RACH preamble is sent on 6RB bandwidth so the uplink
+ // bandwidth does not need to be configured.
+
+ Ptr<RachPreambleLteControlMessage> msg = Create<RachPreambleLteControlMessage> ();
+ msg->SetPrachId (m_prachId);
+ m_uePhySapProvider->SendRachPreamble (m_prachId);
+}
+
+void
+LteUeMac::DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
{
NS_LOG_FUNCTION (this << " rnti" << rnti);
m_rnti = rnti;
}
void
-LteUeMac::DoAddLc (uint8_t lcId, LteMacSapUser* msu)
+LteUeMac::DoAddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu)
{
NS_LOG_FUNCTION (this << " lcId" << (uint16_t) lcId);
- NS_ASSERT_MSG (m_macSapUserMap.find (lcId) == m_macSapUserMap.end (), "cannot add channel because LCID " << lcId << " is already present");
- m_macSapUserMap[lcId] = msu;
+ NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (), "cannot add channel because LCID " << lcId << " is already present");
+
+ LcInfo lcInfo;
+ lcInfo.lcConfig = lcConfig;
+ lcInfo.macSapUser = msu;
+ m_lcInfoMap[lcId] = lcInfo;
}
void
LteUeMac::DoRemoveLc (uint8_t lcId)
{
NS_LOG_FUNCTION (this << " lcId" << lcId);
- NS_ASSERT_MSG (m_macSapUserMap.find (lcId) == m_macSapUserMap.end (), "could not find LCID " << lcId);
- m_macSapUserMap.erase (lcId);
+ NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (), "could not find LCID " << lcId);
+ m_lcInfoMap.erase (lcId);
+}
+
+void
+LteUeMac::DoReset ()
+{
+ NS_LOG_FUNCTION (this);
+ std::map <uint8_t, LcInfo>::iterator it = m_lcInfoMap.begin ();
+ while (it != m_lcInfoMap.end ())
+ {
+ // don't delete CCCH)
+ if (it->first == 0)
+ {
+ ++it;
+ }
+ else
+ {
+ // note: use of postfix operator preserves validity of iterator
+ m_lcInfoMap.erase (it++);
+ }
+ }
}
void
@@ -339,9 +413,9 @@
if (tag.GetRnti () == m_rnti)
{
// packet is for the current user
- std::map <uint8_t, LteMacSapUser*>::const_iterator it = m_macSapUserMap.find (tag.GetLcid ());
- NS_ASSERT_MSG (it != m_macSapUserMap.end (), "received packet with unknown lcid");
- it->second->ReceivePdu (p);
+ std::map <uint8_t, LcInfo>::const_iterator it = m_lcInfoMap.find (tag.GetLcid ());
+ NS_ASSERT_MSG (it != m_lcInfoMap.end (), "received packet with unknown lcid");
+ it->second.macSapUser->ReceivePdu (p);
}
}
@@ -355,7 +429,6 @@
Ptr<UlDciLteControlMessage> msg2 = DynamicCast<UlDciLteControlMessage> (msg);
UlDciListElement_s dci = msg2->GetDci ();
std::map <uint8_t, uint64_t>::iterator itBsr;
- NS_ASSERT_MSG (m_ulBsrReceived.size () <=4, " Too many LCs (max is 4)");
uint16_t activeLcs = 0;
for (itBsr = m_ulBsrReceived.begin (); itBsr != m_ulBsrReceived.end (); itBsr++)
{
@@ -369,18 +442,19 @@
NS_LOG_ERROR (this << " No active flows for this UL-DCI");
return;
}
- std::map <uint8_t, LteMacSapUser*>::iterator it;
- NS_LOG_FUNCTION (this << " UE: UL-CQI notified TxOpportunity of " << dci.m_tbSize);
- for (it = m_macSapUserMap.begin (); it!=m_macSapUserMap.end (); it++)
+ std::map <uint8_t, LcInfo>::iterator it;
+ uint32_t bytesPerActiveLc = dci.m_tbSize / activeLcs;
+ NS_LOG_LOGIC (this << " UE: UL-CQI notified TxOpportunity of " << dci.m_tbSize << " => " << bytesPerActiveLc << " bytes per active LC");
+ for (it = m_lcInfoMap.begin (); it!=m_lcInfoMap.end (); it++)
{
itBsr = m_ulBsrReceived.find ((*it).first);
- if (itBsr!=m_ulBsrReceived.end ())
+ if (((itBsr!=m_ulBsrReceived.end ()) && ((*itBsr).second > 0)))
{
- NS_LOG_FUNCTION (this << "\t" << dci.m_tbSize / m_macSapUserMap.size () << " bytes to LC " << (uint16_t)(*it).first << " queue " << (*itBsr).second);
- (*it).second->NotifyTxOpportunity (dci.m_tbSize / activeLcs, 0);
- if ((*itBsr).second >= static_cast<uint64_t> (dci.m_tbSize / activeLcs))
+ NS_LOG_LOGIC (this << "\t" << bytesPerActiveLc << " bytes to LC " << (uint16_t)(*it).first << " queue " << (*itBsr).second);
+ (*it).second.macSapUser->NotifyTxOpportunity (bytesPerActiveLc, 0);
+ if ((*itBsr).second >= static_cast<uint64_t> (bytesPerActiveLc))
{
- (*itBsr).second -= dci.m_tbSize / activeLcs;
+ (*itBsr).second -= bytesPerActiveLc;
}
else
{
@@ -390,9 +464,26 @@
}
}
+ else if (msg->GetMessageType () == LteControlMessage::RAR)
+ {
+ Ptr<RarLteControlMessage> msg2 = DynamicCast<RarLteControlMessage> (msg);
+
+ if (msg2->GetPrachId () == m_prachId)
+ {
+ m_rnti = msg2->GetRar ().m_rnti;
+ NS_LOG_INFO ("got RAR for PRACH ID " << m_prachId << ", setting T-C-RNTI = " << m_rnti);
+ m_cmacSapUser->SetTemporaryCellRnti (m_rnti);
+
+ // in principle we should wait for contention resolution,
+ // but, since we don't model RACH PREAMBLE collisions, we
+ // just stop here
+ m_cmacSapUser->NotifyRandomAccessSuccessful ();
+ }
+ // else the RAR is not for me
+ }
else
{
- NS_LOG_FUNCTION (this << " LteControlMessage not recognized");
+ NS_LOG_WARN (this << " LteControlMessage not recognized");
}
}
--- a/src/lte/model/lte-ue-mac.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-mac.h Tue Oct 30 16:02:07 2012 +0100
@@ -78,10 +78,12 @@
void DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters params);
// forwarded from UE CMAC SAP
- void DoConfigureUe (uint16_t rnti);
- void DoAddLc (uint8_t lcId, LteMacSapUser* msu);
+
+ void DoStartContentionBasedRandomAccessProcedure ();
+ void DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask);
+ void DoAddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu);
void DoRemoveLc (uint8_t lcId);
- void DoRrcUpdateConfigurationReq (LteUeConfig_t params);
+ void DoReset ();
// forwarded from PHY SAP
void DoReceivePhyPdu (Ptr<Packet> p);
@@ -90,8 +92,15 @@
void SendReportBufferStatus (void);
private:
- // end of temporary hack
- std::map <uint8_t, LteMacSapUser*> m_macSapUserMap;
+
+ struct LcInfo
+ {
+ LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
+ LteMacSapUser* macSapUser;
+ };
+
+ std::map <uint8_t, LcInfo> m_lcInfoMap;
+
LteMacSapProvider* m_macSapProvider;
LteUeCmacSapUser* m_cmacSapUser;
@@ -107,8 +116,9 @@
bool m_freshUlBsr; // true when a BSR has been received in the last TTI
+ uint16_t m_rnti;
- uint16_t m_rnti;
+ uint32_t m_prachId;
};
--- a/src/lte/model/lte-ue-phy-sap.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-phy-sap.h Tue Oct 30 16:02:07 2012 +0100
@@ -53,6 +53,12 @@
*/
virtual void SendLteControlMessage (Ptr<LteControlMessage> msg) = 0;
+ /**
+ * send a preamble on the PRACH
+ *
+ * \param prachId the ID of the preamble
+ */
+ virtual void SendRachPreamble (uint32_t prachId) = 0;
};
--- a/src/lte/model/lte-ue-phy.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-phy.cc Tue Oct 30 16:02:07 2012 +0100
@@ -71,7 +71,7 @@
// inherited from LtePhySapProvider
virtual void SendMacPdu (Ptr<Packet> p);
virtual void SendLteControlMessage (Ptr<LteControlMessage> msg);
- virtual void SetSrsConfigurationIndex (uint16_t srcCi);
+ virtual void SendRachPreamble (uint32_t prachId);
private:
LteUePhy* m_phy;
@@ -82,7 +82,6 @@
}
-
void
UeMemberLteUePhySapProvider::SendMacPdu (Ptr<Packet> p)
{
@@ -96,9 +95,9 @@
}
void
-UeMemberLteUePhySapProvider::SetSrsConfigurationIndex (uint16_t srcCi)
+UeMemberLteUePhySapProvider::SendRachPreamble (uint32_t prachId)
{
- m_phy->DoSetSrsConfigurationIndex (srcCi);
+ m_phy->DoSendRachPreamble (prachId);
}
@@ -127,7 +126,12 @@
m_uePhySapUser (0),
m_ueCphySapUser (0),
m_rnti (0),
- m_srsPeriodicity (0)
+ m_transmissionMode (0),
+ m_srsPeriodicity (0),
+ m_srsConfigured (false),
+ m_dlConfigured (false),
+ m_ulConfigured (false),
+ m_addedToDlChannel (false)
{
m_amc = CreateObject <LteAmc> ();
m_uePhySapProvider = new UeMemberLteUePhySapProvider (this);
@@ -364,6 +368,12 @@
LteUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr)
{
NS_LOG_FUNCTION (this);
+
+ if (!(m_dlConfigured && m_ulConfigured))
+ {
+ return;
+ }
+
// check periodic wideband CQI
if (Simulator::Now () > m_p10CqiLast + m_p10CqiPeriocity)
{
@@ -501,6 +511,17 @@
SetControlMessages (msg);
}
+void
+LteUePhy::DoSendRachPreamble (uint32_t prachId)
+{
+ NS_LOG_FUNCTION (this << prachId);
+
+ // unlike other control messages, RACH preamble is sent ASAP
+ Ptr<RachPreambleLteControlMessage> msg = Create<RachPreambleLteControlMessage> ();
+ msg->SetPrachId (prachId);
+ m_controlMessagesQueue.at (0).push_back (msg);
+}
+
void
LteUePhy::ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> > msgList)
@@ -578,6 +599,12 @@
// pass the info to the MAC
m_uePhySapUser->ReceiveLteControlMessage (msg);
}
+ else if (msg->GetMessageType () == LteControlMessage::MIB)
+ {
+ NS_LOG_INFO ("received MIB");
+ Ptr<MibLteControlMessage> msg2 = DynamicCast<MibLteControlMessage> (msg);
+ m_ueCphySapUser->RecvMasterInformationBlock (msg2->GetMib ());
+ }
else
{
// pass the message to UE-MAC
@@ -601,78 +628,76 @@
LteUePhy::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
{
NS_LOG_FUNCTION (this << frameNo << subframeNo);
-
- // update uplink transmission mask according to previous UL-CQIs
- SetSubChannelsForTransmission (m_subChannelsForTransmissionQueue.at (0));
- // shift the queue
- for (uint8_t i = 1; i < m_macChTtiDelay; i++)
- {
- m_subChannelsForTransmissionQueue.at (i-1) = m_subChannelsForTransmissionQueue.at (i);
- }
- m_subChannelsForTransmissionQueue.at (m_macChTtiDelay-1).clear ();
+
+ NS_ASSERT_MSG (frameNo > 0, "the SRS index check code assumes that frameNo starts at 1");
- bool srs = false;
- // check SRS periodicity
- if (m_srsCounter==1)
- {
- srs = true;
- m_srsCounter = m_srsPeriodicity;
- }
- else
- {
- m_srsCounter--;
- }
-
- if (srs)
+ if (m_ulConfigured)
{
- Simulator::Schedule (UL_SRS_DELAY_FROM_SUBFRAME_START,
- &LteUePhy::SendSrs,
- this);
- }
-
+ // update uplink transmission mask according to previous UL-CQIs
+ SetSubChannelsForTransmission (m_subChannelsForTransmissionQueue.at (0));
+
+ // shift the queue
+ for (uint8_t i = 1; i < m_macChTtiDelay; i++)
+ {
+ m_subChannelsForTransmissionQueue.at (i-1) = m_subChannelsForTransmissionQueue.at (i);
+ }
+ m_subChannelsForTransmissionQueue.at (m_macChTtiDelay-1).clear ();
+
+ if (m_srsConfigured)
+ {
- std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
- // send packets in queue
- // send the current burts of packets
- Ptr<PacketBurst> pb = GetPacketBurst ();
- if (pb)
- {
- NS_LOG_LOGIC (this << " UE - start TX PUSCH + PUCCH");
- m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
- }
- else
- {
- // send only PUCCH (ideal: fake full bandwidth signal)
- if (ctrlMsg.size ()>0)
+ NS_ASSERT_MSG (subframeNo > 0 && subframeNo <= 10, "the SRS index check code assumes that subframeNo starts at 1");
+ if ((((frameNo-1)*10 + (subframeNo-1)) % m_srsPeriodicity) == m_srsSubframeOffset)
+ {
+ NS_LOG_INFO ("frame " << frameNo << " subframe " << subframeNo << " sending SRS (offset=" << m_srsSubframeOffset << ", period=" << m_srsPeriodicity << ")");
+ Simulator::Schedule (UL_SRS_DELAY_FROM_SUBFRAME_START,
+ &LteUePhy::SendSrs,
+ this);
+ }
+ }
+
+ std::list<Ptr<LteControlMessage> > ctrlMsg = GetControlMessages ();
+ // send packets in queue
+ // send the current burts of packets
+ Ptr<PacketBurst> pb = GetPacketBurst ();
+ if (pb)
{
- std::vector <int> dlRb;
- for (uint8_t i = 0; i < m_ulBandwidth; i++)
- {
- dlRb.push_back (i);
- }
- SetSubChannelsForTransmission (dlRb);
+ NS_LOG_LOGIC (this << " UE - start TX PUSCH + PUCCH");
m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
}
- }
+ else
+ {
+ // send only PUCCH (ideal: fake full bandwidth signal)
+ if (ctrlMsg.size ()>0)
+ {
+ std::vector <int> dlRb;
+ for (uint8_t i = 0; i < m_ulBandwidth; i++)
+ {
+ dlRb.push_back (i);
+ }
+ SetSubChannelsForTransmission (dlRb);
+ m_uplinkSpectrumPhy->StartTxDataFrame (pb, ctrlMsg, UL_DATA_DURATION);
+ }
+ }
+ } // m_configured
-
// trigger the MAC
m_uePhySapUser->SubframeIndication (frameNo, subframeNo);
-
-
+
+
++subframeNo;
if (subframeNo > 10)
{
++frameNo;
subframeNo = 1;
}
-
+
// schedule next subframe indication
Simulator::Schedule (Seconds (GetTti ()), &LteUePhy::SubframeIndication, this, frameNo, subframeNo);
}
-
+
void
-LteUePhy::SendSrs ()
+ LteUePhy::SendSrs ()
{
NS_LOG_FUNCTION (this << " UE " << m_rnti << " start tx SRS, cell Id " << m_cellId);
// set the current tx power spectral density (full bandwidth)
@@ -688,17 +713,28 @@
void
-LteUePhy::DoSetRnti (uint16_t rnti)
+LteUePhy::DoSyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn)
{
- NS_LOG_FUNCTION (this << rnti);
- m_rnti = rnti;
+ NS_LOG_FUNCTION (this << cellId);
+ m_enbCellId = cellId;
+ m_dlEarfcn = dlEarfcn;
+ m_downlinkSpectrumPhy->SetCellId (cellId);
+ m_uplinkSpectrumPhy->SetCellId (cellId);
+
+ // configure DL for receing the BCH with the minimum bandwith
+ const uint8_t minDlBandwidth = 6;
+ Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, minDlBandwidth, m_noiseFigure);
+ m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
+ m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy);
+
+ m_dlConfigured = false;
+ m_ulConfigured = false;
}
+void
+LteUePhy::DoSetDlBandwidth (uint8_t dlBandwidth)
+{
-void
-LteUePhy::DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth)
-{
- m_ulBandwidth = ulBandwidth;
m_dlBandwidth = dlBandwidth;
int Type0AllocationRbg[4] = {
@@ -715,29 +751,31 @@
break;
}
}
- UpdateNoisePsd ();
-}
+
+ Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_noiseFigure);
+ m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
+ m_downlinkSpectrumPhy->GetChannel ()->AddRx (m_downlinkSpectrumPhy);
-void
-LteUePhy::DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn)
-{
- m_dlEarfcn = dlEarfcn;
- m_ulEarfcn = ulEarfcn;
- UpdateNoisePsd ();
+ m_dlConfigured = true;
}
-void
-LteUePhy::DoSyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId)
+void
+LteUePhy::DoConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth)
{
- NS_LOG_FUNCTION (this << enbDevice << cellId);
- m_enbCellId = cellId;
- m_enbDevice = enbDevice;
-
- m_downlinkSpectrumPhy->SetCellId (cellId);
- m_uplinkSpectrumPhy->SetCellId (cellId);
+ m_ulEarfcn = ulEarfcn;
+ m_ulBandwidth = ulBandwidth;
+ m_ulConfigured = true;
}
+
+void
+LteUePhy::DoSetRnti (uint16_t rnti)
+{
+ NS_LOG_FUNCTION (this << rnti);
+ m_rnti = rnti;
+}
+
void
LteUePhy::DoSetTransmissionMode (uint8_t txMode)
{
@@ -751,8 +789,9 @@
{
NS_LOG_FUNCTION (this << srcCi);
m_srsPeriodicity = GetSrsPeriodicity (srcCi);
- m_srsCounter = GetSrsSubframeOffset (srcCi) + 1;
- NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti << " offset " << GetSrsSubframeOffset (srcCi) << " cellId " << m_cellId << " CI " << srcCi);
+ m_srsSubframeOffset = GetSrsSubframeOffset (srcCi);
+ m_srsConfigured = true;
+ NS_LOG_DEBUG (this << " UE SRS P " << m_srsPeriodicity << " RNTI " << m_rnti << " offset " << m_srsSubframeOffset << " cellId " << m_cellId << " CI " << srcCi);
}
@@ -827,12 +866,5 @@
m_downlinkSpectrumPhy->SetTxModeGain (txMode, gain);
}
-void
-LteUePhy::UpdateNoisePsd ()
-{
- Ptr<SpectrumValue> noisePsd = LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (m_dlEarfcn, m_dlBandwidth, m_noiseFigure);
- m_downlinkSpectrumPhy->SetNoisePowerSpectralDensity (noisePsd);
-}
-
} // namespace ns3
--- a/src/lte/model/lte-ue-phy.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-phy.h Tue Oct 30 16:02:07 2012 +0100
@@ -37,7 +37,6 @@
namespace ns3 {
class PacketBurst;
-class LteNetDevice;
class LteEnbPhy;
/**
@@ -120,11 +119,6 @@
*/
uint8_t GetMacChDelay (void) const;
- /**
- * \brief Queue the MAC PDU to be sent
- * \param p the MAC PDU to sent
- */
- virtual void DoSendMacPdu (Ptr<Packet> p);
/**
* \brief Create the PSD for the TX
@@ -168,11 +162,8 @@
virtual void GenerateCtrlCqiReport (const SpectrumValue& sinr);
virtual void GenerateDataCqiReport (const SpectrumValue& sinr);
- virtual void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
virtual void ReceiveLteControlMessageList (std::list<Ptr<LteControlMessage> >);
- virtual void DoSetSrsConfigurationIndex (uint16_t srcCi);
-
@@ -210,16 +201,20 @@
void SetTxMode7Gain (double gain);
void SetTxModeGain (uint8_t txMode, double gain);
- void UpdateNoisePsd ();
-
void QueueSubChannelsForTransmission (std::vector <int> rbMap);
- // CPHY SAP methods
- void DoSetBandwidth (uint8_t ulBandwidth, uint8_t dlBandwidth);
- void DoSetEarfcn (uint16_t dlEarfcn, uint16_t ulEarfcn);
+ // UE CPHY SAP methods
+ void DoSyncronizeWithEnb (uint16_t cellId, uint16_t dlEarfcn);
+ void DoSetDlBandwidth (uint8_t ulBandwidth);
+ void DoConfigureUplink (uint16_t ulEarfcn, uint8_t ulBandwidth);
+ void DoSetRnti (uint16_t rnti);
void DoSetTransmissionMode (uint8_t txMode);
- void DoSetRnti (uint16_t rnti);
- void DoSyncronizeWithEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
+ void DoSetSrsConfigurationIndex (uint16_t srcCi);
+
+ // UE PHY SAP methods
+ virtual void DoSendMacPdu (Ptr<Packet> p);
+ virtual void DoSendLteControlMessage (Ptr<LteControlMessage> msg);
+ virtual void DoSendRachPreamble (uint32_t prachId);
std::vector <int> m_subChannelsForTransmission;
std::vector <int> m_subChannelsForReception;
@@ -246,13 +241,17 @@
uint16_t m_rnti;
uint16_t m_enbCellId;
- Ptr<LteEnbNetDevice> m_enbDevice; // wild hack, might go away in later versions
-
+
uint8_t m_transmissionMode;
std::vector <double> m_txModeGain;
uint16_t m_srsPeriodicity;
- uint16_t m_srsCounter;
+ uint16_t m_srsSubframeOffset;
+ uint16_t m_srsConfigured;
+
+ bool m_dlConfigured;
+ bool m_ulConfigured;
+ bool m_addedToDlChannel;
};
--- a/src/lte/model/lte-ue-rrc.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-rrc.cc Tue Oct 30 16:02:07 2012 +0100
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ * Copyright (c) 2011, 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
@@ -20,14 +20,17 @@
#include <ns3/fatal-error.h>
#include <ns3/log.h>
-#include "ns3/object-map.h"
-#include "ns3/object-factory.h"
-#include "ns3/node-list.h"
-#include "ns3/node.h"
+#include <ns3/object-map.h>
+#include <ns3/object-factory.h>
+#include <ns3/node-list.h>
+#include <ns3/node.h>
#include "lte-ue-rrc.h"
#include "lte-enb-rrc.h"
#include "lte-rlc.h"
+#include "lte-rlc-tm.h"
+#include "lte-rlc-um.h"
+#include "lte-rlc-am.h"
#include "lte-pdcp.h"
#include "lte-pdcp-sap.h"
#include "lte-radio-bearer-info.h"
@@ -49,8 +52,10 @@
public:
UeMemberLteUeCmacSapUser (LteUeRrc* rrc);
- virtual void LcConfigCompleted ();
-
+ virtual void SetTemporaryCellRnti (uint16_t rnti);
+ virtual void NotifyRandomAccessSuccessful ();
+ virtual void NotifyRandomAccessFailed ();
+
private:
LteUeRrc* m_rrc;
};
@@ -61,31 +66,75 @@
}
void
-UeMemberLteUeCmacSapUser::LcConfigCompleted ()
+UeMemberLteUeCmacSapUser::SetTemporaryCellRnti (uint16_t rnti)
{
- m_rrc->DoLcConfigCompleted ();
+ m_rrc->DoSetTemporaryCellRnti (rnti);
+}
+
+
+void
+UeMemberLteUeCmacSapUser::NotifyRandomAccessSuccessful ()
+{
+ m_rrc->DoNotifyRandomAccessSuccessful ();
+}
+
+void
+UeMemberLteUeCmacSapUser::NotifyRandomAccessFailed ()
+{
+ m_rrc->DoNotifyRandomAccessFailed ();
}
+
+
+const char* g_ueRrcStateName[LteUeRrc::NUM_STATES] =
+ {
+ "IDLE_CELL_SELECTION",
+ "IDLE_WAIT_SYSTEM_INFO",
+ "IDLE_CAMPED_NORMALLY",
+ "IDLE_RANDOM_ACCESS",
+ "IDLE_CONNECTING",
+ "CONNECTED_NORMALLY",
+ "CONNECTED_REESTABLISHING",
+ "CONNECTED_HANDOVER"
+ };
+
+std::string ToString (LteUeRrc::State s)
+{
+ return std::string (g_ueRrcStateName[s]);
+}
+
+
/////////////////////////////
// ue RRC methods
/////////////////////////////
NS_OBJECT_ENSURE_REGISTERED (LteUeRrc);
+
LteUeRrc::LteUeRrc ()
: m_cphySapProvider (0),
m_cmacSapProvider (0),
+ m_rrcSapUser (0),
m_macSapProvider (0),
m_asSapUser (0),
- m_cellId (0)
+ m_state (IDLE_CELL_SELECTION),
+ m_imsi (0),
+ m_rnti (0),
+ m_cellId (0),
+ m_useRlcSm (true),
+ m_connectionPending (0),
+ m_receivedMib (0),
+ m_receivedSib2 (0)
+
{
NS_LOG_FUNCTION (this);
m_cphySapUser = new MemberLteUeCphySapUser<LteUeRrc> (this);
m_cmacSapUser = new UeMemberLteUeCmacSapUser (this);
+ m_rrcSapProvider = new MemberLteUeRrcSapProvider<LteUeRrc> (this);
m_pdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<LteUeRrc> (this);
m_asSapProvider = new MemberLteAsSapProvider<LteUeRrc> (this);
}
@@ -104,7 +153,7 @@
delete m_cmacSapUser;
delete m_pdcpSapUser;
delete m_asSapProvider;
- m_rbMap.clear ();
+ m_drbMap.clear ();
}
TypeId
@@ -113,10 +162,10 @@
static TypeId tid = TypeId ("ns3::LteUeRrc")
.SetParent<Object> ()
.AddConstructor<LteUeRrc> ()
- .AddAttribute ("RadioBearerMap", "List of UE RadioBearerInfo by LCID.",
+ .AddAttribute ("DataRadioBearerMap", "List of UE RadioBearerInfo for Data Radio Bearers by LCID.",
ObjectMapValue (),
- MakeObjectMapAccessor (&LteUeRrc::m_rbMap),
- MakeObjectMapChecker<LteRadioBearerInfo> ())
+ MakeObjectMapAccessor (&LteUeRrc::m_drbMap),
+ MakeObjectMapChecker<LteDataRadioBearerInfo> ())
.AddAttribute ("CellId",
"Serving cell identifier",
UintegerValue (0), // unused, read-only attribute
@@ -127,6 +176,9 @@
UintegerValue (0), // unused, read-only attribute
MakeUintegerAccessor (&LteUeRrc::GetRnti),
MakeUintegerChecker<uint16_t> ())
+ .AddTraceSource ("StateTransition",
+ "fired upon every UE RRC state transition",
+ MakeTraceSourceAccessor (&LteUeRrc::m_stateTransitionCallback))
;
return tid;
}
@@ -161,6 +213,20 @@
}
void
+LteUeRrc::SetLteUeRrcSapUser (LteUeRrcSapUser * s)
+{
+ NS_LOG_FUNCTION (this << s);
+ m_rrcSapUser = s;
+}
+
+LteUeRrcSapProvider*
+LteUeRrc::GetLteUeRrcSapProvider ()
+{
+ NS_LOG_FUNCTION (this);
+ return m_rrcSapProvider;
+}
+
+void
LteUeRrc::SetLteMacSapProvider (LteMacSapProvider * s)
{
NS_LOG_FUNCTION (this << s);
@@ -182,120 +248,10 @@
void
LteUeRrc::SetImsi (uint64_t imsi)
{
+ NS_LOG_FUNCTION (this << imsi);
m_imsi = imsi;
}
-void
-LteUeRrc::SetupRadioBearer (EpsBearer bearer, TypeId rlcTypeId, uint8_t lcid)
-{
- NS_LOG_FUNCTION (this << (uint32_t) lcid);
-
- ObjectFactory rlcObjectFactory;
- rlcObjectFactory.SetTypeId (rlcTypeId);
- Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
- rlc->SetLteMacSapProvider (m_macSapProvider);
- rlc->SetRnti (m_rnti);
- rlc->SetLcId (lcid);
-
- Ptr<LteRadioBearerInfo> rbInfo = CreateObject<LteRadioBearerInfo> ();
- rbInfo->m_rlc = rlc;
-
- // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
- // if we are using RLC/SM we don't care of anything above RLC
- if (rlcTypeId != LteRlcSm::GetTypeId ())
- {
- Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
- pdcp->SetRnti (m_rnti);
- pdcp->SetLcId (lcid);
- pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
- pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
- rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
- rbInfo->m_pdcp = pdcp;
- }
-
- NS_ASSERT_MSG (m_rbMap.find (lcid) == m_rbMap.end (), "bearer with same lcid already existing");
- m_rbMap.insert (std::pair<uint8_t, Ptr<LteRadioBearerInfo> > (lcid, rbInfo));
-
- m_cmacSapProvider->AddLc (lcid, rlc->GetLteMacSapUser ());
-}
-
-void
-LteUeRrc::ReleaseRadioBearer (uint8_t lcid)
-{
- NS_LOG_FUNCTION (this << (uint32_t) lcid);
- std::map<uint8_t, Ptr<LteRadioBearerInfo> >::iterator it = m_rbMap.find (lcid);
- NS_ASSERT_MSG (it != m_rbMap.end (), "could not find bearer with given lcid");
- m_rbMap.erase (it);
- NS_FATAL_ERROR ("need to remove entry from TFT classifier, but this is not implemented yet");
-}
-
-
-void
-LteUeRrc::DoSendData (Ptr<Packet> packet, uint8_t bid)
-{
- NS_LOG_FUNCTION (this << packet);
-
- // this is true until we implement Signaling Radio Bearers
- uint8_t lcid = bid;
- LtePdcpSapProvider::TransmitRrcPduParameters params;
- params.rrcPdu = packet;
- params.rnti = m_rnti;
- params.lcid = lcid;
- std::map<uint8_t, Ptr<LteRadioBearerInfo> >::iterator it = m_rbMap.find (lcid);
- NS_ASSERT_MSG (it != m_rbMap.end (), "could not find bearer with lcid == " << lcid);
-
- NS_LOG_LOGIC (this << " RNTI=" << m_rnti << " sending " << packet << "on LCID " << (uint32_t) lcid << " (" << packet->GetSize () << " bytes)");
- it->second->m_pdcp->GetLtePdcpSapProvider ()->TransmitRrcPdu (params);
-}
-
-void
-LteUeRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params)
-{
- NS_LOG_FUNCTION (this);
- m_asSapUser->RecvData (params.rrcPdu);
-}
-
-
-
-
-void
-LteUeRrc::DoLcConfigCompleted ()
-{
- NS_LOG_FUNCTION (this);
- NS_FATAL_ERROR ("not implemented");
-}
-
-
-void
-LteUeRrc::DoForceCampedOnEnb (Ptr<LteEnbNetDevice> enbLteDevice, uint16_t cellId)
-{
- NS_LOG_FUNCTION (this << cellId);
-
- m_cphySapProvider->SetEarfcn (enbLteDevice->GetDlEarfcn (),
- enbLteDevice->GetUlEarfcn ());
-
- m_cellId = cellId;
- m_cphySapProvider->SyncronizeWithEnb (enbLteDevice, cellId);
-
- // the bandwidth setting should be done upon receiving the MIB, but
- // MIB is not implemented for the time being.
- m_cphySapProvider->SetBandwidth (enbLteDevice->GetUlBandwidth (),
- enbLteDevice->GetDlBandwidth ());
-
- // this is used for RRC interactions until the RRC protocol is implemented
- m_enbRrc = enbLteDevice->GetRrc ();
-}
-
-void
-LteUeRrc::DoConnect ()
-{
- NS_LOG_FUNCTION (this);
-
- m_rnti = m_enbRrc->DoRecvConnectionRequest (m_imsi);
- m_cmacSapProvider->ConfigureUe (m_rnti);
- m_cphySapProvider->SetRnti (m_rnti);
-}
-
uint16_t
LteUeRrc::GetRnti () const
{
@@ -310,74 +266,631 @@
return m_cellId;
}
-std::vector<uint8_t>
-LteUeRrc::GetLcIdVector ()
+
+uint8_t
+LteUeRrc::GetUlBandwidth () const
+{
+ NS_LOG_FUNCTION (this);
+ return m_ulBandwidth;
+}
+
+uint8_t
+LteUeRrc::GetDlBandwidth () const
+{
+ NS_LOG_FUNCTION (this);
+ return m_dlBandwidth;
+}
+
+uint16_t
+LteUeRrc::GetDlEarfcn () const
{
- std::vector<uint8_t> v;
- for (std::map<uint8_t, Ptr<LteRadioBearerInfo> >::iterator it = m_rbMap.begin (); it != m_rbMap.end (); ++it)
- {
- v.push_back (it->first);
- }
- return v;
+ return m_dlEarfcn;
+}
+
+uint16_t
+LteUeRrc::GetUlEarfcn () const
+{
+ NS_LOG_FUNCTION (this);
+ return m_ulEarfcn;
+}
+
+
+LteUeRrc::State
+LteUeRrc::GetState (void)
+{
+ NS_LOG_FUNCTION (this);
+ return m_state;
+}
+
+void
+LteUeRrc::SetUseRlcSm (bool val)
+{
+ NS_LOG_FUNCTION (this);
+ m_useRlcSm = val;
}
-void
-LteUeRrc::DoRecvConnectionSetup (LteUeConfig_t params)
-{
- m_cphySapProvider->SetTransmissionMode (params.m_transmissionMode);
- m_cphySapProvider->SetSrsConfigurationIndex (params.m_srsConfigurationIndex);
+
+void
+LteUeRrc::DoStart (void)
+{
+ NS_LOG_FUNCTION (this);
+
+ // setup the UE side of SRB0
+ uint8_t lcid = 0;
+
+ Ptr<LteRlc> rlc = CreateObject<LteRlcTm> ()->GetObject<LteRlc> ();
+ rlc->SetLteMacSapProvider (m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+ rlc->SetLcId (lcid);
+
+ m_srb0 = CreateObject<LteSignalingRadioBearerInfo> ();
+ m_srb0->m_rlc = rlc;
+ m_srb0->m_srbIdentity = 1;
+
+ // CCCH (LCID 0) is pre-configured, here is the hardcoded configuration:
+ LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
+ lcConfig.priority = 0; // highest priority
+ lcConfig.prioritizedBitRateKbps = 65535; // maximum
+ lcConfig.bucketSizeDurationMs = 65535; // maximum
+ lcConfig.logicalChannelGroup = 0; // all SRBs mapped to LCG 0
+
+ m_cmacSapProvider->AddLc (lcid, lcConfig, rlc->GetLteMacSapUser ());
+
+}
- m_enbRrc->DoRecvConnectionSetupCompleted (m_rnti);
+void
+LteUeRrc::DoSendData (Ptr<Packet> packet, uint8_t bid)
+{
+ NS_LOG_FUNCTION (this << packet);
+
+
+ uint8_t drbid = Bid2Drbid (bid);
+
+ std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with drbid == " << drbid);
+
+ LtePdcpSapProvider::TransmitPdcpSduParameters params;
+ params.pdcpSdu = packet;
+ params.rnti = m_rnti;
+ params.lcid = it->second->m_logicalChannelIdentity;
+
+ NS_LOG_LOGIC (this << " RNTI=" << m_rnti << " sending " << packet << "on DRBID " << (uint32_t) drbid << " (LCID" << params.lcid << ")" << " (" << packet->GetSize () << " bytes)");
+ it->second->m_pdcp->GetLtePdcpSapProvider ()->TransmitPdcpSdu (params);
}
void
-LteUeRrc::DoRecvConnectionReconfiguration (LteUeConfig_t params)
+LteUeRrc::DoDisconnect ()
+{
+ NS_LOG_FUNCTION (this);
+
+ switch (m_state)
+ {
+ case IDLE_CELL_SELECTION:
+ case IDLE_CAMPED_NORMALLY:
+ NS_LOG_INFO ("already disconnected");
+ break;
+
+ case IDLE_CONNECTING:
+ NS_LOG_INFO ("aborting connection setup procedure");
+ SwitchToState (IDLE_CAMPED_NORMALLY);
+ break;
+
+ case CONNECTED_NORMALLY:
+ case CONNECTED_REESTABLISHING:
+ case CONNECTED_HANDOVER:
+ LeaveConnectedMode ();
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+LteUeRrc::DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params)
+{
+ NS_LOG_FUNCTION (this);
+ m_asSapUser->RecvData (params.pdcpSdu);
+}
+
+
+void
+LteUeRrc::DoSetTemporaryCellRnti (uint16_t rnti)
{
- NS_LOG_FUNCTION (this << " RNTI " << params.m_rnti << " txMode " << (uint16_t)params.m_transmissionMode);
-
- m_cphySapProvider->SetTransmissionMode (params.m_transmissionMode);
- m_cphySapProvider->SetSrsConfigurationIndex (params.m_srsConfigurationIndex);
+ NS_LOG_FUNCTION (this << rnti);
+ m_rnti = rnti;
+ m_rrcSapUser->Reestablish ();
+ m_cphySapProvider->SetRnti (m_rnti);
+}
+void
+LteUeRrc::DoNotifyRandomAccessSuccessful ()
+{
+ NS_LOG_FUNCTION (this << m_imsi << ToString (m_state));
+ switch (m_state)
+ {
+ case IDLE_RANDOM_ACCESS:
+ {
+ // we just received a RAR with a T-C-RNTI and an UL grant
+ // send RRC connection request as message 3 of the random access procedure
+ SwitchToState (IDLE_CONNECTING);
+ LteRrcSap::RrcConnectionRequest msg;
+ msg.ueIdentity = m_imsi;
+ m_rrcSapUser->SendRrcConnectionRequest (msg);
+ }
+ break;
+
+ case CONNECTED_HANDOVER:
+ {
+ LteRrcSap::RrcConnectionReconfigurationCompleted msg;
+ msg.rrcTransactionIdentifier = m_lastRrcTransactionIdentifier;
+ m_rrcSapUser->SendRrcConnectionReconfigurationCompleted (msg);
+ SwitchToState (CONNECTED_NORMALLY);
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+LteUeRrc::DoNotifyRandomAccessFailed ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+
+void
+LteUeRrc::DoForceCampedOnEnb (Ptr<LteEnbNetDevice> enbLteDevice, uint16_t cellId)
+{
+ NS_LOG_FUNCTION (this << cellId);
+
+ m_cellId = cellId;
+ m_dlEarfcn = enbLteDevice->GetDlEarfcn ();
+ m_cphySapProvider->SyncronizeWithEnb (m_cellId, m_dlEarfcn);
+ SwitchToState (IDLE_WAIT_SYSTEM_INFO);
}
void
-LteUeRrc::DoRecvConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti)
+LteUeRrc::DoConnect ()
{
- Ptr<LteEnbNetDevice> enbDev;
- // WILD HACK - eventually we'll get rid of all these Ptr<Device> around
- NodeList::Iterator listEnd = NodeList::End ();
- bool found = false;
- for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case IDLE_CELL_SELECTION:
+ case IDLE_WAIT_SYSTEM_INFO:
+ m_connectionPending = true;
+ break;
+
+ case IDLE_CAMPED_NORMALLY:
+ StartConnection ();
+ break;
+
+ case IDLE_RANDOM_ACCESS:
+ case IDLE_CONNECTING:
+ NS_LOG_WARN ("already connecting (state " << ToString (m_state) << ")");
+ break;
+
+ case CONNECTED_NORMALLY:
+ case CONNECTED_REESTABLISHING:
+ case CONNECTED_HANDOVER:
+ NS_LOG_WARN ("already connected (state " << ToString (m_state) << ")");
+ break;
+
+ default:
+ NS_FATAL_ERROR ("cannot connect while in state " << ToString (m_state));
+ break;
+ }
+
+
+}
+
+
+
+// CPHY SAP methods
+
+void
+LteUeRrc::DoRecvMasterInformationBlock (LteRrcSap::MasterInformationBlock msg)
+{
+ NS_LOG_FUNCTION (this);
+ m_dlBandwidth = msg.dlBandwidth;
+ m_cphySapProvider->SetDlBandwidth (msg.dlBandwidth);
+ m_receivedMib = true;
+ if (m_state == IDLE_WAIT_SYSTEM_INFO && m_receivedMib && m_receivedSib2)
+ {
+ SwitchToState (IDLE_CAMPED_NORMALLY);
+ }
+}
+
+
+
+// RRC SAP methods
+
+void
+LteUeRrc::DoRecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg)
+{
+ NS_LOG_FUNCTION (this);
+ // to be implemented
+}
+
+
+void
+LteUeRrc::DoRecvSystemInformation (LteRrcSap::SystemInformation msg)
+{
+ NS_LOG_FUNCTION (this);
+ if (msg.haveSib2)
+ {
+ m_receivedSib2 = true;
+ m_ulBandwidth = msg.sib2.freqInfo.ulBandwidth;
+ m_ulEarfcn = msg.sib2.freqInfo.ulCarrierFreq;
+ m_cphySapProvider->ConfigureUplink (m_ulEarfcn, m_ulBandwidth);
+ }
+ if (m_state == IDLE_WAIT_SYSTEM_INFO && m_receivedMib && m_receivedSib2)
+ {
+ SwitchToState (IDLE_CAMPED_NORMALLY);
+ }
+}
+
+
+void
+LteUeRrc::DoRecvRrcConnectionSetup (LteRrcSap::RrcConnectionSetup msg)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case IDLE_CONNECTING:
+ {
+ ApplyRadioResourceConfigDedicated (msg.radioResourceConfigDedicated);
+ SwitchToState (CONNECTED_NORMALLY);
+ LteRrcSap::RrcConnectionSetupCompleted msg2;
+ msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier;
+ m_rrcSapUser->SendRrcConnectionSetupCompleted (msg2);
+ m_asSapUser->NotifyConnectionSuccessful ();
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+LteUeRrc::DoRecvRrcConnectionReconfiguration (LteRrcSap::RrcConnectionReconfiguration msg)
+{
+ NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
+ switch (m_state)
{
- Ptr<Node> node = *i;
- int nDevs = node->GetNDevices ();
- for (int j = 0; j < nDevs; j++)
+ case CONNECTED_NORMALLY:
+ if (msg.haveRadioResourceConfigDedicated)
+ {
+ ApplyRadioResourceConfigDedicated (msg.radioResourceConfigDedicated);
+ }
+ if (msg.haveMobilityControlInfo)
+ {
+ SwitchToState (CONNECTED_HANDOVER);
+ const LteRrcSap::MobilityControlInfo& mci = msg.mobilityControlInfo;
+ m_cellId = mci.targetPhysCellId;
+ NS_ASSERT (mci.haveCarrierFreq);
+ NS_ASSERT (mci.haveCarrierBandwidth);
+ m_cphySapProvider->SyncronizeWithEnb (m_cellId, mci.carrierFreq.dlCarrierFreq);
+ m_cphySapProvider->SetDlBandwidth ( mci.carrierBandwidth.dlBandwidth);
+ m_cphySapProvider->ConfigureUplink (mci.carrierFreq.ulCarrierFreq, mci.carrierBandwidth.ulBandwidth);
+ m_rnti = msg.mobilityControlInfo.newUeIdentity;
+ NS_ASSERT_MSG (mci.haveRachConfigDedicated, "handover is only supported with non-contention-based random access procedure");
+ m_cmacSapProvider->StartNonContentionBasedRandomAccessProcedure (m_rnti, mci.rachConfigDedicated.raPreambleIndex, mci.rachConfigDedicated.raPrachMaskIndex);
+ m_cphySapProvider->SetRnti (m_rnti);
+ m_lastRrcTransactionIdentifier = msg.rrcTransactionIdentifier;
+ // RRC connection reconfiguration completed will be sent
+ // after handover is completed
+ }
+ else
{
- enbDev = node->GetDevice (j)->GetObject <LteEnbNetDevice> ();
- if (!enbDev)
+ LteRrcSap::RrcConnectionReconfigurationCompleted msg2;
+ msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier;
+ m_rrcSapUser->SendRrcConnectionReconfigurationCompleted (msg2);
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+LteUeRrc::DoRecvRrcConnectionReestablishment (LteRrcSap::RrcConnectionReestablishment msg)
+{
+ switch (m_state)
+ {
+ case CONNECTED_REESTABLISHING:
+ {
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+LteUeRrc::DoRecvRrcConnectionReestablishmentReject (LteRrcSap::RrcConnectionReestablishmentReject msg)
+{
+ NS_LOG_FUNCTION (this);
+ switch (m_state)
+ {
+ case CONNECTED_REESTABLISHING:
+ {
+ LeaveConnectedMode ();
+ }
+ break;
+
+ default:
+ NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
+ break;
+ }
+}
+
+void
+LteUeRrc::DoRecvRrcConnectionRelease (LteRrcSap::RrcConnectionRelease msg)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+
+
+
+void
+LteUeRrc::ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedicated rrcd)
+{
+ NS_LOG_FUNCTION (this);
+ const struct LteRrcSap::PhysicalConfigDedicated& pcd = rrcd.physicalConfigDedicated;
+
+ if (pcd.haveAntennaInfoDedicated)
+ {
+ m_cphySapProvider->SetTransmissionMode (pcd.antennaInfo.transmissionMode);
+ }
+ if (pcd.haveSoundingRsUlConfigDedicated)
+ {
+ m_cphySapProvider->SetSrsConfigurationIndex (pcd.soundingRsUlConfigDedicated.srsConfigIndex);
+ }
+
+ std::list<LteRrcSap::SrbToAddMod>::const_iterator stamIt = rrcd.srbToAddModList.begin ();
+ if (stamIt != rrcd.srbToAddModList.end ())
+ {
+ if (m_srb1 == 0)
+ {
+ // SRB1 not setup yet
+ NS_ASSERT_MSG (m_state == IDLE_CONNECTING, "expected state IDLE_CONNECTING, actual state " << ToString (m_state));
+ NS_ASSERT_MSG (stamIt->srbIdentity == 1, "only SRB1 supported");
+
+ const uint8_t lcid = 1; // fixed LCID for SRB1
+
+ Ptr<LteRlc> rlc = CreateObject<LteRlcAm> ();
+ rlc->SetLteMacSapProvider (m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+ rlc->SetLcId (lcid);
+
+ Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
+ pdcp->SetRnti (m_rnti);
+ pdcp->SetLcId (lcid);
+ pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
+ pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
+ rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
+
+ m_srb1 = CreateObject<LteSignalingRadioBearerInfo> ();
+ m_srb1->m_rlc = rlc;
+ m_srb1->m_pdcp = pdcp;
+ m_srb1->m_srbIdentity = 1;
+
+ m_srb1->m_logicalChannelConfig.priority = stamIt->logicalChannelConfig.priority;
+ m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.prioritizedBitRateKbps;
+ m_srb1->m_logicalChannelConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSizeDurationMs;
+ m_srb1->m_logicalChannelConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalChannelGroup;
+
+ struct LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
+ lcConfig.priority = stamIt->logicalChannelConfig.priority;
+ lcConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.prioritizedBitRateKbps;
+ lcConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSizeDurationMs;
+ lcConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalChannelGroup;
+
+ m_cmacSapProvider->AddLc (lcid, lcConfig, rlc->GetLteMacSapUser ());
+
+ ++stamIt;
+ NS_ASSERT_MSG (stamIt == rrcd.srbToAddModList.end (), "at most one SrbToAdd supported");
+ }
+ else
+ {
+ NS_LOG_INFO ("request to modify SRB1 (skipping as currently not implemented)");
+ // would need to modify m_srb1, and then propagate changes to the MAC
+ }
+ }
+
+
+ std::list<LteRrcSap::DrbToAddMod>::const_iterator dtamIt;
+ for (dtamIt = rrcd.drbToAddModList.begin ();
+ dtamIt != rrcd.drbToAddModList.end ();
+ ++dtamIt)
+ {
+ NS_LOG_INFO (this << " IMSI " << m_imsi << " adding/modifying DRBID " << dtamIt->drbIdentity << " LC " << (uint32_t) dtamIt->logicalChannelIdentity);
+ NS_ASSERT_MSG (dtamIt->logicalChannelIdentity > 2, "LCID value " << dtamIt->logicalChannelIdentity << " is reserved for SRBs");
+
+ std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator drbMapIt = m_drbMap.find (dtamIt->drbIdentity);
+ if (drbMapIt == m_drbMap.end ())
+ {
+ NS_LOG_INFO ("New Data Radio Bearer");
+
+ TypeId rlcTypeId;
+ if (m_useRlcSm)
{
- continue;
+ rlcTypeId = LteRlcSm::GetTypeId ();
}
else
{
- if (enbDev->GetCellId () == targetCellId)
+ switch (dtamIt->rlcConfig.choice)
{
- found = true;
+ case LteRrcSap::RlcConfig::AM:
+ rlcTypeId = LteRlcAm::GetTypeId ();
+ break;
+
+ case LteRrcSap::RlcConfig::UM_BI_DIRECTIONAL:
+ rlcTypeId = LteRlcUm::GetTypeId ();
+ break;
+
+ default:
+ NS_FATAL_ERROR ("unsupported RLC configuration");
+ break;
}
}
+
+ ObjectFactory rlcObjectFactory;
+ rlcObjectFactory.SetTypeId (rlcTypeId);
+ Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
+ rlc->SetLteMacSapProvider (m_macSapProvider);
+ rlc->SetRnti (m_rnti);
+ rlc->SetLcId (dtamIt->logicalChannelIdentity);
+
+ Ptr<LteDataRadioBearerInfo> rbInfo = CreateObject<LteDataRadioBearerInfo> ();
+ rbInfo->m_rlc = rlc;
+
+ // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
+ // if we are using RLC/SM we don't care of anything above RLC
+ if (rlcTypeId != LteRlcSm::GetTypeId ())
+ {
+ Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
+ pdcp->SetRnti (m_rnti);
+ pdcp->SetLcId (dtamIt->logicalChannelIdentity);
+ pdcp->SetLtePdcpSapUser (m_pdcpSapUser);
+ pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
+ rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
+ rbInfo->m_pdcp = pdcp;
+ }
+
+ m_bid2DrbidMap[dtamIt->epsBearerIdentity] = dtamIt->drbIdentity;
+
+ m_drbMap.insert (std::pair<uint8_t, Ptr<LteDataRadioBearerInfo> > (dtamIt->drbIdentity, rbInfo));
+
+
+ struct LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
+ lcConfig.priority = dtamIt->logicalChannelConfig.priority;
+ lcConfig.prioritizedBitRateKbps = dtamIt->logicalChannelConfig.prioritizedBitRateKbps;
+ lcConfig.bucketSizeDurationMs = dtamIt->logicalChannelConfig.bucketSizeDurationMs;
+ lcConfig.logicalChannelGroup = dtamIt->logicalChannelConfig.logicalChannelGroup;
+
+ m_cmacSapProvider->AddLc (dtamIt->logicalChannelIdentity,
+ lcConfig,
+ rlc->GetLteMacSapUser ());
+ }
+ else
+ {
+ NS_LOG_INFO ("request to modify existing DRBID (skipping as currently not implemented)");
+ Ptr<LteDataRadioBearerInfo> rbInfo = drbMapIt->second;
+ // would need to modify rbInfo, and then propagate changes to the MAC
}
}
- NS_ASSERT_MSG (found , " Unable to find eNB with CellId =" << targetCellId);
- m_enbRrc = enbDev->GetObject<LteEnbRrc> ();
+
+ std::list<uint8_t>::iterator dtdmIt;
+ for (dtdmIt = rrcd.drbToReleaseList.begin ();
+ dtdmIt != rrcd.drbToReleaseList.end ();
+ ++dtdmIt)
+ {
+ uint8_t drbid = *dtdmIt;
+ NS_LOG_INFO (this << " IMSI " << m_imsi << " releasing DRB " << (uint32_t) drbid << drbid);
+ std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it = m_drbMap.find (drbid);
+ NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with given lcid");
+ m_drbMap.erase (it);
+ m_bid2DrbidMap.erase (drbid);
+ }
+}
+
+
+void
+LteUeRrc::StartConnection ()
+{
+ NS_LOG_FUNCTION (this);
+ m_connectionPending = false;
+ SwitchToState (IDLE_RANDOM_ACCESS);
+ m_cmacSapProvider->StartContentionBasedRandomAccessProcedure ();
+}
+
+void
+LteUeRrc::LeaveConnectedMode ()
+{
+ NS_LOG_FUNCTION (this << m_imsi);
+ m_asSapUser->NotifyConnectionReleased ();
+ m_cmacSapProvider->RemoveLc (1);
+ std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it;
+ for (it = m_drbMap.begin (); it != m_drbMap.end (); ++it)
+ {
+ m_cmacSapProvider->RemoveLc (it->second->m_logicalChannelIdentity);
+ }
+ m_drbMap.clear ();
+ m_bid2DrbidMap.clear ();
+ m_srb1 = 0;
+ SwitchToState (IDLE_CAMPED_NORMALLY);
+}
+
- DoForceCampedOnEnb (enbDev, targetCellId);
- m_rnti = newRnti;
- m_cmacSapProvider->ConfigureUe (m_rnti);
- m_cphySapProvider->SetRnti (m_rnti);
- m_enbRrc->DoRecvConnectionReconfigurationCompleted (m_rnti);
+uint8_t
+LteUeRrc::Bid2Drbid (uint8_t bid)
+{
+ std::map<uint8_t, uint8_t>::iterator it = m_bid2DrbidMap.find (bid);
+ NS_ASSERT_MSG (it != m_bid2DrbidMap.end (), "could not find BID " << bid);
+ return it->second;
+}
+
+
+void
+LteUeRrc::SwitchToState (State newState)
+{
+ NS_LOG_FUNCTION (this << newState);
+ State oldState = m_state;
+ m_state = newState;
+ NS_LOG_INFO ("IMSI " << m_imsi << " RNTI " << m_rnti << " UeRrc " << ToString (oldState) << " --> " << ToString (newState));
+ m_stateTransitionCallback (oldState, newState);
+
+ switch (newState)
+ {
+ case IDLE_CELL_SELECTION:
+ break;
+
+ case IDLE_WAIT_SYSTEM_INFO:
+ break;
+
+ case IDLE_CAMPED_NORMALLY:
+ if (m_connectionPending)
+ {
+ StartConnection ();
+ }
+ break;
+
+ case IDLE_RANDOM_ACCESS:
+ break;
+
+ case IDLE_CONNECTING:
+ break;
+
+ case CONNECTED_NORMALLY:
+ break;
+
+ case CONNECTED_REESTABLISHING:
+ break;
+
+ case CONNECTED_HANDOVER:
+ break;
+
+ default:
+ break;
+ }
+}
-}
+
+
} // namespace ns3
--- a/src/lte/model/lte-ue-rrc.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/lte-ue-rrc.h Tue Oct 30 16:02:07 2012 +0100
@@ -27,6 +27,8 @@
#include <ns3/lte-pdcp-sap.h>
#include <ns3/lte-as-sap.h>
#include <ns3/lte-ue-cphy-sap.h>
+#include <ns3/lte-rrc-sap.h>
+#include <ns3/traced-callback.h>
#include <map>
@@ -36,7 +38,8 @@
class LteMacSapProvider;
class LteUeCmacSapUser;
class LteUeCmacSapProvider;
-class LteRadioBearerInfo;
+class LteDataRadioBearerInfo;
+class LteSignalingRadioBearerInfo;
class LteEnbRrc;
/**
@@ -51,8 +54,28 @@
friend class LtePdcpSpecificLtePdcpSapUser<LteUeRrc>;
friend class MemberLteAsSapProvider<LteUeRrc>;
friend class MemberLteUeCphySapUser<LteUeRrc>;
+ friend class MemberLteUeRrcSapProvider<LteUeRrc>;
public:
+
+ /**
+ * The states of the UE RRC entity
+ *
+ */
+ enum State
+ {
+ IDLE_CELL_SELECTION = 0,
+ IDLE_WAIT_SYSTEM_INFO,
+ IDLE_CAMPED_NORMALLY,
+ IDLE_RANDOM_ACCESS,
+ IDLE_CONNECTING,
+ CONNECTED_NORMALLY,
+ CONNECTED_REESTABLISHING,
+ CONNECTED_HANDOVER,
+ NUM_STATES
+ };
+
+
/**
* create an RRC instance for use within an ue
*
@@ -67,7 +90,10 @@
// inherited from Object
+private:
+ virtual void DoStart (void);
virtual void DoDispose (void);
+public:
static TypeId GetTypeId (void);
@@ -99,6 +125,21 @@
*/
LteUeCmacSapUser* GetLteUeCmacSapUser ();
+
+ /**
+ * set the RRC SAP this RRC should interact with
+ *
+ * \param s the RRC SAP User to be used by this RRC
+ */
+ void SetLteUeRrcSapUser (LteUeRrcSapUser * s);
+
+ /**
+ *
+ *
+ * \return s the RRC SAP Provider interface offered to the MAC by this RRC
+ */
+ LteUeRrcSapProvider* GetLteUeRrcSapProvider ();
+
/**
* set the MAC SAP provider. The ue RRC does not use this
* directly, but it needs to provide it to newly created RLC instances.
@@ -130,37 +171,6 @@
void SetImsi (uint64_t imsi);
/**
- * Set UE RRC parameters
- *
- * \param rnti C-RNTI of the UE
- * \param cellId Serving cell identifier
- */
- void ConfigureUe (uint16_t rnti, uint16_t cellId);
-
-
-
- /**
- * Setup a new radio bearer for the given user
- *
- * \param bearer the characteristics of the bearer to be activated
- * \param rlcTypeId the TypeId identifying the type of RLC to be used for this bearer.
- * \param lcid the logical channel id allocated for this bearer by the eNB
- * \param tft the Traffic Flow Template identifying this bearer
- *
- */
- void SetupRadioBearer (EpsBearer bearer, TypeId rlcTypeId, uint8_t lcid);
-
-
- /**
- *
- * Release the given radio bearer
- *
- * \param lcId the logical channel id of the bearer to be released
- */
- void ReleaseRadioBearer (uint8_t lcId);
-
-
- /**
*
* \return the C-RNTI of the user
*/
@@ -173,46 +183,79 @@
*/
uint16_t GetCellId () const;
- /**
- *
- * @return a vector with the allocated LCID
+
+ /**
+ * \return the uplink bandwidth in RBs
*/
- std::vector<uint8_t> GetLcIdVector ();
-
+ uint8_t GetUlBandwidth () const;
/**
- * reception of the RRC ConnectionReconfiguration message
- *
+ * \return the downlink bandwidth in RBs
+ */
+ uint8_t GetDlBandwidth () const;
+
+ /**
+ * \return the downlink carrier frequency (EARFCN)
*/
- void DoRecvConnectionSetup (LteUeConfig_t params);
+ uint16_t GetDlEarfcn () const;
+
+ /**
+ * \return the uplink carrier frequency (EARFCN)
+ */
+ uint16_t GetUlEarfcn () const;
/**
- * reception of the RRC ConnectionReconfiguration message
- *
+ *
+ * \return the current state
*/
- void DoRecvConnectionReconfiguration (LteUeConfig_t params);
-
+ State GetState ();
/**
- * Execute a handover
+ *
*
- * \param targetCellId
- * \param newRnti
+ * \param val true if RLC SM is to be used, false if RLC UM/AM are to be used
*/
- void DoRecvConnectionReconfigurationWithMobilityControlInfo (uint16_t targetCellId, uint16_t newRnti);
-
+ void SetUseRlcSm (bool val);
+
+
private:
+
// PDCP SAP methods
- void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params);
+ void DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params);
// CMAC SAP methods
- void DoLcConfigCompleted ();
-
+ void DoSetTemporaryCellRnti (uint16_t rnti);
+ void DoNotifyRandomAccessSuccessful ();
+ void DoNotifyRandomAccessFailed ();
+
// LTE AS SAP methods
void DoForceCampedOnEnb (Ptr<LteEnbNetDevice> enbDevice, uint16_t cellId);
void DoConnect ();
void DoSendData (Ptr<Packet> packet, uint8_t bid);
+ void DoDisconnect ();
+
+ // CPHY SAP methods
+ void DoRecvMasterInformationBlock (LteRrcSap::MasterInformationBlock msg);
+
+ // RRC SAP methods
+ void DoRecvSystemInformationBlockType1 (LteRrcSap::SystemInformationBlockType1 msg);
+ void DoRecvSystemInformation (LteRrcSap::SystemInformation msg);
+ void DoRecvRrcConnectionSetup (LteRrcSap::RrcConnectionSetup msg);
+ void DoRecvRrcConnectionReconfiguration (LteRrcSap::RrcConnectionReconfiguration msg);
+ void DoRecvRrcConnectionReestablishment (LteRrcSap::RrcConnectionReestablishment msg);
+ void DoRecvRrcConnectionReestablishmentReject (LteRrcSap::RrcConnectionReestablishmentReject msg);
+ void DoRecvRrcConnectionRelease (LteRrcSap::RrcConnectionRelease msg);
+
+
+ // internal methods
+ void ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedicated rrcd);
+ void StartConnection ();
+ void LeaveConnectedMode ();
+ uint8_t Bid2Drbid (uint8_t bid);
+ void SwitchToState (State s);
+
+ std::map<uint8_t, uint8_t> m_bid2DrbidMap;
LteUeCphySapUser* m_cphySapUser;
LteUeCphySapProvider* m_cphySapProvider;
@@ -220,20 +263,41 @@
LteUeCmacSapUser* m_cmacSapUser;
LteUeCmacSapProvider* m_cmacSapProvider;
+ LteUeRrcSapUser* m_rrcSapUser;
+ LteUeRrcSapProvider* m_rrcSapProvider;
+
LteMacSapProvider* m_macSapProvider;
LtePdcpSapUser* m_pdcpSapUser;
LteAsSapProvider* m_asSapProvider;
LteAsSapUser* m_asSapUser;
+ State m_state;
+
uint64_t m_imsi;
uint16_t m_rnti;
uint16_t m_cellId;
- std::map <uint8_t, Ptr<LteRadioBearerInfo> > m_rbMap;
+ Ptr<LteSignalingRadioBearerInfo> m_srb0;
+ Ptr<LteSignalingRadioBearerInfo> m_srb1;
+ std::map <uint8_t, Ptr<LteDataRadioBearerInfo> > m_drbMap;
+
+ bool m_useRlcSm;
+
+ uint8_t m_lastRrcTransactionIdentifier;
- Ptr<LteEnbRrc> m_enbRrc; // wild hack, might go away in future versions
-
+ uint8_t m_dlBandwidth; /**< downlink bandwidth in RBs */
+ uint8_t m_ulBandwidth; /**< uplink bandwidth in RBs */
+
+ uint16_t m_dlEarfcn; /**< downlink carrier frequency */
+ uint16_t m_ulEarfcn; /**< uplink carrier frequency */
+
+ TracedCallback<State, State> m_stateTransitionCallback;
+
+ bool m_connectionPending; /**< true if a connection request by upper layers is pending */
+ bool m_receivedMib; /**< true if MIB was received for the current cell */
+ bool m_receivedSib2; /**< true if SIB2 was received for the current cell */
+
};
--- a/src/lte/model/pf-ff-mac-scheduler.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/pf-ff-mac-scheduler.cc Tue Oct 30 16:02:07 2012 +0100
@@ -1021,28 +1021,37 @@
std::map <uint16_t,uint32_t>::iterator it;
for (unsigned int i = 0; i < params.m_macCeList.size (); i++)
- {
- if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
{
- // buffer status report
- // note that we only consider LCG 0, the other three LCGs are neglected
- // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
- uint16_t rnti = params.m_macCeList.at (i).m_rnti;
- it = m_ceBsrRxed.find (rnti);
- if (it == m_ceBsrRxed.end ())
- {
- // create the new entry
- uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
- int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
- m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
- }
- else
- {
- // update the buffer size value
- (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
- }
+ if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
+ {
+ // buffer status report
+ // note that this scheduler does not differentiate the
+ // allocation according to which LCGs have more/less bytes
+ // to send.
+ // Hence the BSR of different LCGs are just summed up to get
+ // a total queue size that is used for allocation purposes.
+
+ uint32_t buffer = 0;
+ for (uint8_t lcg = 0; lcg < 4; ++lcg)
+ {
+ uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
+ buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
+ }
+
+ uint16_t rnti = params.m_macCeList.at (i).m_rnti;
+ it = m_ceBsrRxed.find (rnti);
+ if (it == m_ceBsrRxed.end ())
+ {
+ // create the new entry
+ m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
+ }
+ else
+ {
+ // update the buffer size value
+ (*it).second = buffer;
+ }
+ }
}
- }
return;
}
--- a/src/lte/model/rr-ff-mac-scheduler.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/model/rr-ff-mac-scheduler.cc Tue Oct 30 16:02:07 2012 +0100
@@ -415,11 +415,11 @@
m_rlcBufferReq.sort (SortRlcBufferReq);
int nflows = 0;
int nTbs = 0;
- std::map <uint16_t,uint8_t> lcActivesPerRnti;
+ std::map <uint16_t,uint8_t> lcActivesPerRnti; // tracks how many active LCs per RNTI there are
std::map <uint16_t,uint8_t>::iterator itLcRnti;
for (it = m_rlcBufferReq.begin (); it != m_rlcBufferReq.end (); it++)
{
-// NS_LOG_INFO (this << " User " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
+ NS_LOG_LOGIC (this << " User " << (*it).m_rnti << " LC " << (uint16_t)(*it).m_logicalChannelIdentity);
// remove old entries of this UE-LC
if ( ((*it).m_rlcTransmissionQueueSize > 0)
|| ((*it).m_rlcRetransmissionQueueSize > 0)
@@ -542,16 +542,24 @@
int tbSize = (m_amc->GetTbSizeFromMcs (newDci.m_mcs.at (0), rbgPerTb * rbgSize) / 8);
NS_LOG_DEBUG (this << " DL - Allocate user " << newEl.m_rnti << " LCs " << (uint16_t)(*itLcRnti).second << " bytes " << tbSize << " PRBs " << rbgAllocated * rbgSize << "..." << (rbgAllocated* rbgSize) + (rbgPerTb * rbgSize) - 1 << " mcs " << (uint16_t) newDci.m_mcs.at (0) << " layers " << nLayer);
uint16_t rlcPduSize = tbSize / lcNum;
- for (int i = 0; i < lcNum ; i++)
+ while (lcNum>0)
{
- for (uint8_t j = 0; j < nLayer; j++)
+ if ( ((*it).m_rlcTransmissionQueueSize > 0)
+ || ((*it).m_rlcRetransmissionQueueSize > 0)
+ || ((*it).m_rlcStatusPduSize > 0) )
{
- RlcPduListElement_s newRlcEl;
- newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
-// NS_LOG_DEBUG (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
- newRlcEl.m_size = rlcPduSize;
- UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
- newRlcPduLe.push_back (newRlcEl);
+ std::vector <struct RlcPduListElement_s> newRlcPduLe;
+ for (uint8_t j = 0; j < nLayer; j++)
+ {
+ RlcPduListElement_s newRlcEl;
+ newRlcEl.m_logicalChannelIdentity = (*it).m_logicalChannelIdentity;
+ // NS_LOG_DEBUG (this << "LCID " << (uint32_t) newRlcEl.m_logicalChannelIdentity << " size " << rlcPduSize << " ID " << (*it).m_rnti << " layer " << (uint16_t)j);
+ newRlcEl.m_size = rlcPduSize;
+ UpdateDlRlcBufferInfo ((*it).m_rnti, newRlcEl.m_logicalChannelIdentity, rlcPduSize);
+ newRlcPduLe.push_back (newRlcEl);
+ }
+ newEl.m_rlcPduList.push_back (newRlcPduLe);
+ lcNum--;
}
it++;
if (it == m_rlcBufferReq.end ())
@@ -827,22 +835,31 @@
{
if ( params.m_macCeList.at (i).m_macCeType == MacCeListElement_s::BSR )
{
- // buffer status report
- // note that we only consider LCG 0, the other three LCGs are neglected
- // this is consistent with the assumption in LteUeMac that the first LCG gathers all LCs
+ // buffer status report
+ // note that this scheduler does not differentiate the
+ // allocation according to which LCGs have more/less bytes
+ // to send.
+ // Hence the BSR of different LCGs are just summed up to get
+ // a total queue size that is used for allocation purposes.
+
+ uint32_t buffer = 0;
+ for (uint8_t lcg = 0; lcg < 4; ++lcg)
+ {
+ uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (lcg);
+ buffer += BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
+ }
+
uint16_t rnti = params.m_macCeList.at (i).m_rnti;
it = m_ceBsrRxed.find (rnti);
if (it == m_ceBsrRxed.end ())
{
// create the new entry
- uint8_t bsrId = params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0);
- int buffer = BufferSizeLevelBsr::BsrId2BufferSize (bsrId);
m_ceBsrRxed.insert ( std::pair<uint16_t, uint32_t > (rnti, buffer));
}
else
{
// update the buffer size value
- (*it).second = BufferSizeLevelBsr::BsrId2BufferSize (params.m_macCeList.at (i).m_macCeValue.m_bufferStatus.at (0));
+ (*it).second = buffer;
}
}
}
--- a/src/lte/test/epc-test-s1u-uplink.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/epc-test-s1u-uplink.cc Tue Oct 30 16:02:07 2012 +0100
@@ -19,7 +19,7 @@
* The original version of UdpClient is by Amine Ismail
* <amine.ismail@sophia.inria.fr> <amine.ismail@udcast.com>
* The rest of the code (including modifying UdpClient into
- * LteRadioBearerTagUdpClient) is by Nicola Baldo <nbaldo@cttc.es>
+ * EpsBearerTagUdpClient) is by Nicola Baldo <nbaldo@cttc.es>
*/
@@ -41,7 +41,7 @@
#include <ns3/ipv4-interface.h>
#include <ns3/mac48-address.h>
#include "ns3/seq-ts-header.h"
-#include "ns3/lte-radio-bearer-tag.h"
+#include "ns3/eps-bearer-tag.h"
#include "ns3/arp-cache.h"
#include "ns3/boolean.h"
#include "ns3/uinteger.h"
@@ -56,23 +56,23 @@
/*
* A Udp client. Sends UDP packet carrying sequence number and time
- * stamp but also including the LteRadioBearerTag. This tag is normally
+ * stamp but also including the EpsBearerTag. This tag is normally
* generated by the LteEnbNetDevice when forwarding packet in the
* uplink. But in this test we don't have the LteEnbNetDevice, because
* we test the S1-U interface with simpler devices to make sure it
* just works.
*
*/
-class LteRadioBearerTagUdpClient : public Application
+class EpsBearerTagUdpClient : public Application
{
public:
static TypeId
GetTypeId (void);
- LteRadioBearerTagUdpClient ();
- LteRadioBearerTagUdpClient (uint16_t rnti, uint8_t lcid);
+ EpsBearerTagUdpClient ();
+ EpsBearerTagUdpClient (uint16_t rnti, uint8_t bid);
- virtual ~LteRadioBearerTagUdpClient ();
+ virtual ~EpsBearerTagUdpClient ();
/**
* \brief set the remote address and port
@@ -103,49 +103,49 @@
EventId m_sendEvent;
uint16_t m_rnti;
- uint8_t m_lcid;
+ uint8_t m_bid;
};
TypeId
-LteRadioBearerTagUdpClient::GetTypeId (void)
+EpsBearerTagUdpClient::GetTypeId (void)
{
- static TypeId tid = TypeId ("ns3::LteRadioBearerTagUdpClient")
+ static TypeId tid = TypeId ("ns3::EpsBearerTagUdpClient")
.SetParent<Application> ()
- .AddConstructor<LteRadioBearerTagUdpClient> ()
+ .AddConstructor<EpsBearerTagUdpClient> ()
.AddAttribute ("MaxPackets",
"The maximum number of packets the application will send",
UintegerValue (100),
- MakeUintegerAccessor (&LteRadioBearerTagUdpClient::m_count),
+ MakeUintegerAccessor (&EpsBearerTagUdpClient::m_count),
MakeUintegerChecker<uint32_t> ())
.AddAttribute ("Interval",
"The time to wait between packets", TimeValue (Seconds (1.0)),
- MakeTimeAccessor (&LteRadioBearerTagUdpClient::m_interval),
+ MakeTimeAccessor (&EpsBearerTagUdpClient::m_interval),
MakeTimeChecker ())
.AddAttribute (
"RemoteAddress",
"The destination Ipv4Address of the outbound packets",
Ipv4AddressValue (),
- MakeIpv4AddressAccessor (&LteRadioBearerTagUdpClient::m_peerAddress),
+ MakeIpv4AddressAccessor (&EpsBearerTagUdpClient::m_peerAddress),
MakeIpv4AddressChecker ())
.AddAttribute ("RemotePort", "The destination port of the outbound packets",
UintegerValue (100),
- MakeUintegerAccessor (&LteRadioBearerTagUdpClient::m_peerPort),
+ MakeUintegerAccessor (&EpsBearerTagUdpClient::m_peerPort),
MakeUintegerChecker<uint16_t> ())
.AddAttribute ("PacketSize",
"Size of packets generated. The minimum packet size is 12 bytes which is the size of the header carrying the sequence number and the time stamp.",
UintegerValue (1024),
- MakeUintegerAccessor (&LteRadioBearerTagUdpClient::m_size),
+ MakeUintegerAccessor (&EpsBearerTagUdpClient::m_size),
MakeUintegerChecker<uint32_t> ())
;
return tid;
}
-LteRadioBearerTagUdpClient::LteRadioBearerTagUdpClient ()
+EpsBearerTagUdpClient::EpsBearerTagUdpClient ()
: m_rnti (0),
- m_lcid (0)
+ m_bid (0)
{
NS_LOG_FUNCTION_NOARGS ();
m_sent = 0;
@@ -153,9 +153,9 @@
m_sendEvent = EventId ();
}
-LteRadioBearerTagUdpClient::LteRadioBearerTagUdpClient (uint16_t rnti, uint8_t lcid)
+EpsBearerTagUdpClient::EpsBearerTagUdpClient (uint16_t rnti, uint8_t bid)
: m_rnti (rnti),
- m_lcid (lcid)
+ m_bid (bid)
{
NS_LOG_FUNCTION_NOARGS ();
m_sent = 0;
@@ -163,27 +163,27 @@
m_sendEvent = EventId ();
}
-LteRadioBearerTagUdpClient::~LteRadioBearerTagUdpClient ()
+EpsBearerTagUdpClient::~EpsBearerTagUdpClient ()
{
NS_LOG_FUNCTION_NOARGS ();
}
void
-LteRadioBearerTagUdpClient::SetRemote (Ipv4Address ip, uint16_t port)
+EpsBearerTagUdpClient::SetRemote (Ipv4Address ip, uint16_t port)
{
m_peerAddress = ip;
m_peerPort = port;
}
void
-LteRadioBearerTagUdpClient::DoDispose (void)
+EpsBearerTagUdpClient::DoDispose (void)
{
NS_LOG_FUNCTION_NOARGS ();
Application::DoDispose ();
}
void
-LteRadioBearerTagUdpClient::StartApplication (void)
+EpsBearerTagUdpClient::StartApplication (void)
{
NS_LOG_FUNCTION_NOARGS ();
@@ -196,18 +196,18 @@
}
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
- m_sendEvent = Simulator::Schedule (Seconds (0.0), &LteRadioBearerTagUdpClient::Send, this);
+ m_sendEvent = Simulator::Schedule (Seconds (0.0), &EpsBearerTagUdpClient::Send, this);
}
void
-LteRadioBearerTagUdpClient::StopApplication ()
+EpsBearerTagUdpClient::StopApplication ()
{
NS_LOG_FUNCTION_NOARGS ();
Simulator::Cancel (m_sendEvent);
}
void
-LteRadioBearerTagUdpClient::Send (void)
+EpsBearerTagUdpClient::Send (void)
{
NS_LOG_FUNCTION_NOARGS ();
NS_ASSERT (m_sendEvent.IsExpired ());
@@ -216,7 +216,7 @@
Ptr<Packet> p = Create<Packet> (m_size-(8+4)); // 8+4 : the size of the seqTs header
p->AddHeader (seqTs);
- LteRadioBearerTag tag (m_rnti, m_lcid);
+ EpsBearerTag tag (m_rnti, m_bid);
p->AddPacketTag (tag);
if ((m_socket->Send (p)) >= 0)
@@ -235,7 +235,7 @@
if (m_sent < m_count)
{
- m_sendEvent = Simulator::Schedule (m_interval, &LteRadioBearerTagUdpClient::Send, this);
+ m_sendEvent = Simulator::Schedule (m_interval, &EpsBearerTagUdpClient::Send, this);
}
}
@@ -248,7 +248,7 @@
uint32_t numPkts;
uint32_t pktSize;
uint16_t rnti;
- uint8_t lcid;
+ uint8_t bid;
Ptr<PacketSink> serverApp;
Ptr<Application> clientApp;
@@ -258,7 +258,7 @@
: numPkts (n),
pktSize (s),
rnti (r),
- lcid (l)
+ bid (l)
{
}
@@ -410,7 +410,7 @@
enbit->ues[u].serverApp = sinkApp.Get (0)->GetObject<PacketSink> ();
Time interPacketInterval = Seconds (0.01);
- Ptr<LteRadioBearerTagUdpClient> client = CreateObject<LteRadioBearerTagUdpClient> (enbit->ues[u].rnti, enbit->ues[u].lcid);
+ Ptr<EpsBearerTagUdpClient> client = CreateObject<EpsBearerTagUdpClient> (enbit->ues[u].rnti, enbit->ues[u].bid);
client->SetAttribute ("RemoteAddress", Ipv4AddressValue (internetNodesIpIfaceContainer.GetAddress (1)));
client->SetAttribute ("RemotePort", UintegerValue (udpSinkPort));
client->SetAttribute ("MaxPackets", UintegerValue (enbit->ues[u].numPkts));
--- a/src/lte/test/lte-test-entities.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-entities.cc Tue Oct 30 16:02:07 2012 +0100
@@ -156,10 +156,10 @@
*/
void
-LteTestRrc::DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params)
+LteTestRrc::DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params)
{
- NS_LOG_FUNCTION (this << params.rrcPdu->GetSize ());
- Ptr<Packet> p = params.rrcPdu;
+ NS_LOG_FUNCTION (this << params.pdcpSdu->GetSize ());
+ Ptr<Packet> p = params.pdcpSdu;
// NS_LOG_LOGIC ("PDU received = " << (*p));
uint32_t dataLen = p->GetSize ();
@@ -193,12 +193,12 @@
m_txBytes += m_pduSize;
m_txLastTime = Simulator::Now ();
- LtePdcpSapProvider::TransmitRrcPduParameters p;
+ LtePdcpSapProvider::TransmitPdcpSduParameters p;
p.rnti = 1111;
p.lcid = 222;
- p.rrcPdu = Create<Packet> (m_pduSize);
+ p.pdcpSdu = Create<Packet> (m_pduSize);
- Simulator::ScheduleNow (&LtePdcpSapProvider::TransmitRrcPdu, m_pdcpSapProvider, p);
+ Simulator::ScheduleNow (&LtePdcpSapProvider::TransmitPdcpSdu, m_pdcpSapProvider, p);
m_nextPdu = Simulator::Schedule (m_arrivalTime, &LteTestRrc::Start, this);
// Simulator::Run ();
}
@@ -219,15 +219,15 @@
m_txPdus++;
m_txBytes += dataToSend.length ();
- LtePdcpSapProvider::TransmitRrcPduParameters p;
+ LtePdcpSapProvider::TransmitPdcpSduParameters p;
p.rnti = 1111;
p.lcid = 222;
NS_LOG_LOGIC ("Data(" << dataToSend.length () << ") = " << dataToSend.data ());
- p.rrcPdu = Create<Packet> ((uint8_t *) dataToSend.data (), dataToSend.length ());
+ p.pdcpSdu = Create<Packet> ((uint8_t *) dataToSend.data (), dataToSend.length ());
- NS_LOG_LOGIC ("Packet(" << p.rrcPdu->GetSize () << ")");
- Simulator::Schedule (at, &LtePdcpSapProvider::TransmitRrcPdu, m_pdcpSapProvider, p);
+ NS_LOG_LOGIC ("Packet(" << p.pdcpSdu->GetSize () << ")");
+ Simulator::Schedule (at, &LtePdcpSapProvider::TransmitPdcpSdu, m_pdcpSapProvider, p);
}
/////////////////////////////////////////////////////////////////////
@@ -659,7 +659,7 @@
{
EpcEnbS1SapProvider::S1BearerSetupRequestParameters response;
response.rnti = request.rnti;
- response.lcid = 1;
+ response.bid = 1;
response.teid = request.teid;
m_s1SapProvider->S1BearerSetupRequest (response);
}
--- a/src/lte/test/lte-test-entities.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-entities.h Tue Oct 30 16:02:07 2012 +0100
@@ -84,7 +84,7 @@
private:
// Interface forwarded by LtePdcpSapUser
- virtual void DoReceiveRrcPdu (LtePdcpSapUser::ReceiveRrcPduParameters params);
+ virtual void DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params);
LtePdcpSapUser* m_pdcpSapUser;
LtePdcpSapProvider* m_pdcpSapProvider;
--- a/src/lte/test/lte-test-interference.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-interference.cc Tue Oct 30 16:02:07 2012 +0100
@@ -119,9 +119,6 @@
Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
-// lteHelper->EnableLogComponents ();
- lteHelper->EnableMacTraces ();
- lteHelper->EnableRlcTraces ();
lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
// Create Nodes: eNodeB and UE
@@ -190,7 +187,7 @@
// same as above for eNB2 and UE2
-
+
Ptr<LtePhy> ue2Phy = ueDevs2.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testDlSinr2 = Create<LteTestSinrChunkProcessor> (ue2Phy);
ue2Phy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testDlSinr2);
@@ -205,10 +202,10 @@
Config::Connect ("/NodeList/1/DeviceList/0/LteEnbMac/UlScheduling",
MakeBoundCallback (&LteTestUlSchedulingCallback, this));
+// need to allow for RRC connection establishment + SRS
+ Simulator::Stop (Seconds (0.040));
+ Simulator::Run ();
- Simulator::Stop (Seconds (0.020));
- Simulator::Run ();
-
double dlSinr1Db = 10.0 * log10 (testDlSinr1->GetSinr ()->operator[] (0));
NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr1Db, m_dlSinrDb, 0.01, "Wrong SINR in DL! (eNB1 --> UE1)");
@@ -218,12 +215,12 @@
double dlSinr2Db = 10.0 * log10 (testDlSinr2->GetSinr ()->operator[] (0));
NS_TEST_ASSERT_MSG_EQ_TOL (dlSinr2Db, m_dlSinrDb, 0.01, "Wrong SINR in DL! (eNB2 --> UE2)");
-
+
double ulSinr2Db = 10.0 * log10 (testUlSinr2->GetSinr ()->operator[] (0));
NS_TEST_ASSERT_MSG_EQ_TOL (ulSinr2Db, m_ulSinrDb, 0.01, "Wrong SINR in UL! (UE2 --> eNB2)");
Simulator::Destroy ();
-
+
}
@@ -231,14 +228,10 @@
LteInterferenceTestCase::DlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
uint8_t mcsTb1, uint16_t sizeTb1, uint8_t mcsTb2, uint16_t sizeTb2)
{
- /**
- * Note:
- * For first 4 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
- * because CQI feedback is still not available at the eNB.
- */
- if ( (frameNo > 1) || (subframeNo > 9) )
+ // need to allow for RRC connection establishment + CQI feedback reception
+ if (Simulator::Now () > MilliSeconds (35))
{
- NS_TEST_ASSERT_MSG_EQ ((uint16_t)mcsTb1, m_dlMcs, "Wrong DL MCS ");
+ NS_TEST_ASSERT_MSG_EQ ((uint32_t)mcsTb1, (uint32_t)m_dlMcs, "Wrong DL MCS ");
}
}
@@ -246,14 +239,10 @@
LteInterferenceTestCase::UlScheduling (uint32_t frameNo, uint32_t subframeNo, uint16_t rnti,
uint8_t mcs, uint16_t sizeTb)
{
- /**
- * Note:
- * For first 5 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
- * because CQI feedback is still not available at the eNB.
- */
- if ( (frameNo > 1) && (subframeNo > 6) )
+ // need to allow for RRC connection establishment + SRS transmission
+ if (Simulator::Now () > MilliSeconds (35))
{
- NS_TEST_ASSERT_MSG_EQ ((uint16_t)mcs, m_ulMcs, "Wrong UL MCS");
+ NS_TEST_ASSERT_MSG_EQ ((uint32_t)mcs, (uint32_t)m_ulMcs, "Wrong UL MCS");
}
}
--- a/src/lte/test/lte-test-link-adaptation.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-link-adaptation.cc Tue Oct 30 16:02:07 2012 +0100
@@ -201,12 +201,12 @@
// It will be used to test that the SNR is as intended
Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> (uePhy);
- uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testSinr);
+ uePhy->GetDownlinkSpectrumPhy ()->AddCtrlSinrChunkProcessor (testSinr);
Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
MakeBoundCallback (&LteTestDlSchedulingCallback, this));
- Simulator::Stop (Seconds (0.007));
+ Simulator::Stop (Seconds (0.026));
Simulator::Run ();
double calculatedSinrDb = 10.0 * log10 (testSinr->GetSinr ()->operator[] (0));
@@ -229,10 +229,11 @@
/**
* Note:
- * For first 4 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
- * because CQI feedback is still not available at the eNB.
+ * the MCS can only be properly evaluated after:
+ * RRC connection has been completed and
+ * CQI feedback is available at the eNB.
*/
- if ( (frameNo > 1) || (subframeNo > 8) )
+ if (Simulator::Now ().GetSeconds () > 0.024)
{
NS_LOG_INFO (m_snrDb << "\t" << m_mcsIndex << "\t" << (uint16_t)mcsTb1);
--- a/src/lte/test/lte-test-mimo.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-mimo.cc Tue Oct 30 16:02:07 2012 +0100
@@ -168,13 +168,13 @@
uePhy->SetAttribute ("TxPower", DoubleValue (23.0));
uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
-
- lteHelper->EnableRlcTraces ();
+ // need to allow for RRC connection establishment + SRS before enabling traces
+ Simulator::Schedule (Seconds (0.050), &LteHelper::EnableRlcTraces, lteHelper);
lteHelper->EnableMacTraces ();
double simulationTime = 0.401;
double tolerance = 0.1;
- uint8_t rnti = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetRnti ();
+ uint8_t rnti = 1;
Ptr<LteEnbNetDevice> enbNetDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
PointerValue ptrval;
@@ -212,7 +212,6 @@
Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (0.1)));
-
/**
* Check that the assignation is done in a RR fashion
*/
@@ -223,8 +222,7 @@
NS_LOG_INFO ("\t test with user at distance " << m_dist << " time " << sampleTime);
// get the imsi
uint64_t imsi = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetImsi ();
- // get the lcId
- uint8_t lcId = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 3;
Time t = Seconds (sampleTime);
Simulator::Schedule(t, &LenaMimoTestCase::GetRlcBufferSample, this, rlcStats, imsi, lcId);
sampleTime += 0.1;
--- a/src/lte/test/lte-test-pathloss-model.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-pathloss-model.cc Tue Oct 30 16:02:07 2012 +0100
@@ -158,10 +158,18 @@
// double sinrDb = txPowerDbm- noisePowerDbm - receiverNoiseFigureDb - loss[i];
double sinrDb = 10*log10(sinrLin);
NS_LOG_INFO (" Ptx " << txPowerDbm << " Pn " << noisePowerDbm << " Fn " << receiverNoiseFigureDb << " Pl " << loss[i] << " dist " << dist[i]);
+
+ int mcs = -1;
+ int numSnrEfficiencyMcsEntries = sizeof (snrEfficiencyMcs) / sizeof (SnrEfficiencyMcs);
+ for (int j = 0; j < numSnrEfficiencyMcsEntries && snrEfficiencyMcs[j].snrDb < sinrDb; ++j)
+ {
+ mcs = snrEfficiencyMcs[j].mcsIndex;
+ }
+
std::ostringstream name;
name << " snr= " << sinrDb << " dB, "
- << " mcs= " << snrEfficiencyMcs[i].mcsIndex;
- AddTestCase (new LtePathlossModelSystemTestCase (name.str (), sinrDb, dist[i], snrEfficiencyMcs[i].mcsIndex));
+ << " mcs= " << snrEfficiencyMcs[i].mcsIndex;
+ AddTestCase (new LtePathlossModelSystemTestCase (name.str (), sinrDb, dist[i], mcs));
}
@@ -198,17 +206,7 @@
/**
* Simulation Topology
*/
-// LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL);
-// LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
-// LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("SingleModelSpectrumChannel", LOG_LEVEL_ALL);
- LogComponentEnable ("BuildingsPropagationLossModel", LOG_LEVEL_ALL);
- LogComponentEnable ("HybridBuildingsPropagationLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteHelper", LOG_LEVEL_ALL);
-//
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
// lteHelper->EnableLogComponents ();
lteHelper->EnableMacTraces ();
@@ -272,12 +270,12 @@
// It will be used to test that the SNR is as intended
//Ptr<LtePhy> uePhy = ueDevs.Get (0)->GetObject<LteUeNetDevice> ()->GetPhy ()->GetObject<LtePhy> ();
Ptr<LteTestSinrChunkProcessor> testSinr = Create<LteTestSinrChunkProcessor> (uePhy);
- uePhy->GetDownlinkSpectrumPhy ()->AddDataSinrChunkProcessor (testSinr);
+ uePhy->GetDownlinkSpectrumPhy ()->AddCtrlSinrChunkProcessor (testSinr);
// Config::Connect ("/NodeList/0/DeviceList/0/LteEnbMac/DlScheduling",
// MakeBoundCallback (&LteTestPathlossDlSchedCallback, this));
- Simulator::Stop (Seconds (0.005));
+ Simulator::Stop (Seconds (0.035));
Simulator::Run ();
double calculatedSinrDb = 10.0 * log10 (testSinr->GetSinr ()->operator[] (0));
@@ -299,12 +297,9 @@
NS_LOG_INFO ("SNR\tRef_MCS\tCalc_MCS");
}
- /**
- * Note:
- * For first 4 subframeNo in the first frameNo, the MCS cannot be properly evaluated,
- * because CQI feedback is still not available at the eNB.
- */
- if ( (frameNo > 1) || (subframeNo > 4) )
+
+ // need to allow for RRC connection establishment + SRS transmission
+ if (Simulator::Now () > MilliSeconds (21))
{
NS_LOG_INFO (m_snrDb << "\t" << m_mcsIndex << "\t" << (uint16_t)mcsTb1);
--- a/src/lte/test/lte-test-pf-ff-mac-scheduler.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-pf-ff-mac-scheduler.cc Tue Oct 30 16:02:07 2012 +0100
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ * Copyright (c) 2011, 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
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Author: Marco Miozzo <marco.miozzo@cttc.es>,
+ * Author: Marco Miozzo <marco.miozzo@cttc.es>
* Nicola Baldo <nbaldo@cttc.es>
*/
@@ -207,44 +207,17 @@
void
LenaPfFfMacSchedulerTestCase1::DoRun (void)
{
+ NS_LOG_FUNCTION (this << m_nUser << m_nLc << m_dist);
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
- Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
- Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false)); LogComponentDisableAll (LOG_LEVEL_ALL);
- // LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
-//
-// LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
-
- // LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
- //
- // LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
- //
- // LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
-
-// LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
- LogComponentEnable ("LenaTestPfFfMacCheduler", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
-// LogComponentEnable ("RadioBearerStatsCalculator", LOG_LEVEL_ALL);
/**
* Initialize Simulation Scenario: 1 eNB and m_nUser UEs
*/
+
Ptr<LteHelper> lteHelper = CreateObject<LteHelper> ();
lteHelper->SetAttribute ("PathlossModel", StringValue ("ns3::FriisSpectrumPropagationLossModel"));
@@ -276,7 +249,8 @@
enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE;
EpsBearer bearer (q);
lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
-
+
+
Ptr<LteEnbNetDevice> lteEnbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
Ptr<LteEnbPhy> enbPhy = lteEnbDev->GetPhy ();
enbPhy->SetAttribute ("TxPower", DoubleValue (30.0));
@@ -293,14 +267,18 @@
uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
}
- lteHelper->EnableRlcTraces ();
- double simulationTime = 1.0;
+ double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS
+ double statsDuration = 0.4;
double tolerance = 0.1;
- Simulator::Stop (Seconds (simulationTime));
+ Simulator::Stop (Seconds (statsStartTime + statsDuration + 0.000001));
+ lteHelper->EnableMacTraces ();
+ Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnableRlcTraces, lteHelper);
Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
- rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (simulationTime)));
+ rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime)));
+ rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (statsDuration)));
+
Simulator::Run ();
@@ -313,10 +291,9 @@
{
// get the imsi
uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
- // get the lcId
- uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 3;
dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
- NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << " thr " << (double)dlDataRxed.at (i) / simulationTime << " ref " << m_thrRefDl);
+ NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << " thr " << (double)dlDataRxed.at (i) / statsDuration << " ref " << m_thrRefDl);
}
/**
* Check that the assignation is done in a "proportional fair" manner among users
@@ -326,7 +303,7 @@
*/
for (int i = 0; i < m_nUser; i++)
{
- NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataRxed.at (i) / simulationTime, m_thrRefDl, m_thrRefDl * tolerance, " Unfair Throughput!");
+ NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataRxed.at (i) / statsDuration, m_thrRefDl, m_thrRefDl * tolerance, " Unfair Throughput!");
}
/**
@@ -339,9 +316,9 @@
// get the imsi
uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
// get the lcId
- uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 3;
ulDataRxed.push_back (rlcStats->GetUlRxData (imsi, lcId));
- NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)ulDataRxed.at (i) << " thr " << (double)ulDataRxed.at (i) / simulationTime << " ref " << m_thrRefUl);
+ NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes rxed " << (double)ulDataRxed.at (i) << " thr " << (double)ulDataRxed.at (i) / statsDuration << " ref " << m_thrRefUl);
}
/**
* Check that the assignation is done in a "proportional fair" manner among users
@@ -351,7 +328,7 @@
*/
for (int i = 0; i < m_nUser; i++)
{
- NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / simulationTime, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
+ NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / statsDuration, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
}
Simulator::Destroy ();
@@ -392,35 +369,12 @@
void
LenaPfFfMacSchedulerTestCase2::DoRun (void)
{
- // LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
- //
- // LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
+ NS_LOG_FUNCTION (this);
- // LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
- //
- // LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
- // LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
- //
- // LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
-
-// LogComponentEnable ("PfFfMacScheduler", LOG_LEVEL_ALL);
- LogComponentEnable ("LenaTestPfFfMacCheduler", LOG_LEVEL_ALL);
- // LogComponentEnable ("LteAmc", LOG_LEVEL_ALL);
- // LogComponentEnable ("RadioBearerStatsCalculator", LOG_LEVEL_ALL);
+ Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
+ Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
/**
* Initialize Simulation Scenario: 1 eNB and m_nUser UEs
@@ -474,14 +428,16 @@
uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
}
- lteHelper->EnableRlcTraces ();
-
- double simulationTime = 0.4;
+ double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS
+ double statsDuration = 0.4;
double tolerance = 0.1;
- Simulator::Stop (Seconds (simulationTime));
+ Simulator::Stop (Seconds (statsStartTime + statsDuration + 0.000001));
+ Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnableRlcTraces, lteHelper);
Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
- rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (simulationTime)));
+ rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime)));
+ rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (statsDuration)));
+
Simulator::Run ();
@@ -494,10 +450,10 @@
// get the imsi
uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
// get the lcId
- uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 3;
dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
totalData += (double)dlDataRxed.at (i);
- NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << " thr " << (double)dlDataRxed.at (i) / simulationTime << " ref " << m_nUser);
+ NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " imsi " << imsi << " bytes rxed " << (double)dlDataRxed.at (i) << " thr " << (double)dlDataRxed.at (i) / statsDuration);
totalEstThrPf += m_estThrPfDl.at (i);
}
@@ -525,10 +481,10 @@
// get the imsi
uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
// get the lcId
- uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 3;
ulDataRxed.push_back (rlcStats->GetUlRxData (imsi, lcId));
- NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " bytes rxed " << (double)ulDataRxed.at (i) << " thr " << (double)ulDataRxed.at (i) / simulationTime << " ref " << (double)m_estThrPfUl.at (i));
- NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / simulationTime, (double)m_estThrPfUl.at (i), (double)m_estThrPfUl.at (i) * tolerance, " Unfair Throughput!");
+ NS_LOG_INFO ("\tUser " << i << " dist " << m_dist.at (i) << " bytes rxed " << (double)ulDataRxed.at (i) << " thr " << (double)ulDataRxed.at (i) / statsDuration << " ref " << (double)m_estThrPfUl.at (i));
+ NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / statsDuration, (double)m_estThrPfUl.at (i), (double)m_estThrPfUl.at (i) * tolerance, " Unfair Throughput!");
}
Simulator::Destroy ();
--- a/src/lte/test/lte-test-phy-error-model.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-phy-error-model.cc Tue Oct 30 16:02:07 2012 +0100
@@ -252,7 +252,7 @@
// get the imsi
uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
// get the lcId
- uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 1;
dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
double txed = rlcStats->GetDlTxData (imsi, lcId);
int n = txed / m_tbSize;
@@ -438,7 +438,7 @@
// get the imsi
uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
// get the lcId
- uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 1;
dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
double txed = rlcStats->GetDlTxData (imsi, lcId);
double ber = 1.0 - ((double)dlDataRxed.at (i)/txed);
--- a/src/lte/test/lte-test-rr-ff-mac-scheduler.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/lte-test-rr-ff-mac-scheduler.cc Tue Oct 30 16:02:07 2012 +0100
@@ -1,6 +1,6 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
+ * Copyright (c) 2011, 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
@@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Marco Miozzo <marco.miozzo@cttc.es>
+ * Nicola Baldo <nbaldo@cttc.es>
*/
#include <ns3/object.h>
@@ -43,6 +44,7 @@
#include <ns3/lte-ue-phy.h>
#include <ns3/boolean.h>
#include <ns3/enum.h>
+#include <ns3/config-store-module.h>
#include "lte-test-rr-ff-mac-scheduler.h"
@@ -191,41 +193,11 @@
void
LenaRrFfMacSchedulerTestCase::DoRun (void)
{
+ NS_LOG_FUNCTION (this << m_nUser << m_nLc << m_dist);
Config::SetDefault ("ns3::LteSpectrumPhy::CtrlErrorModelEnabled", BooleanValue (false));
- Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false)); Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
+ Config::SetDefault ("ns3::LteSpectrumPhy::DataErrorModelEnabled", BooleanValue (false));
+ Config::SetDefault ("ns3::LteAmc::AmcModel", EnumValue (LteAmc::PiroEW2010));
Config::SetDefault ("ns3::LteAmc::Ber", DoubleValue (0.00005));
- LogComponentDisableAll (LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbRrc", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUeRrc", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbMac", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUeMac", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteRlc", LOG_LEVEL_ALL);
-//
-// LogComponentEnable ("LtePhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbPhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUePhy", LOG_LEVEL_ALL);
-
-// LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteInterference", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteSinrChunkProcessor", LOG_LEVEL_ALL);
-//
-// LogComponentEnable ("LtePropagationLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("LossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("ShadowingLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("PenetrationLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("MultipathLossModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("PathLossModel", LOG_LEVEL_ALL);
-//
-// LogComponentEnable ("LteNetDevice", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteUeNetDevice", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteEnbNetDevice", LOG_LEVEL_ALL);
-
-// LogComponentEnable ("RrFfMacScheduler", LOG_LEVEL_ALL);
- LogComponentEnable ("LenaTestRrFfMacCheduler", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteMiErrorModel", LOG_LEVEL_ALL);
-// LogComponentEnable ("LenaHelper", LOG_LEVEL_ALL);
-// LogComponentEnable ("LteSpectrumPhy", LOG_LEVEL_ALL);
-
/**
* Initialize Simulation Scenario: 1 eNB and m_nUser UEs
@@ -264,7 +236,7 @@
EpsBearer bearer (q);
lteHelper->ActivateDataRadioBearer (ueDevs, bearer);
-
+
Ptr<LteEnbNetDevice> lteEnbDev = enbDevs.Get (0)->GetObject<LteEnbNetDevice> ();
Ptr<LteEnbPhy> enbPhy = lteEnbDev->GetPhy ();
enbPhy->SetAttribute ("TxPower", DoubleValue (30.0));
@@ -281,13 +253,16 @@
uePhy->SetAttribute ("NoiseFigure", DoubleValue (9.0));
}
- lteHelper->EnableRlcTraces ();
- double simulationTime = 0.4;
+
+ double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS
+ double statsDuration = 0.4;
double tolerance = 0.1;
- Simulator::Stop (Seconds (simulationTime));
+ Simulator::Stop (Seconds (statsStartTime + statsDuration + 0.000001));
+ Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnableRlcTraces, lteHelper);
Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats ();
- rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (simulationTime)));
+ rlcStats->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime)));
+ rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (statsDuration)));
Simulator::Run ();
@@ -301,11 +276,10 @@
{
// get the imsi
uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
- // get the lcId
- uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 3;
dlDataRxed.push_back (rlcStats->GetDlRxData (imsi, lcId));
- NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " lcid " << (uint16_t) lcId << " bytes rxed " << (double)dlDataRxed.at (i) << " thr " << (double)dlDataRxed.at (i) / simulationTime << " ref " << m_thrRefDl);
- NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataRxed.at (i) / simulationTime, m_thrRefDl, m_thrRefDl * tolerance, " Unfair Throughput!");
+ NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " lcid " << (uint16_t) lcId << " bytes rxed " << (double)dlDataRxed.at (i) << " thr " << (double)dlDataRxed.at (i) / statsDuration << " ref " << m_thrRefDl);
+ NS_TEST_ASSERT_MSG_EQ_TOL ((double)dlDataRxed.at (i) / statsDuration, m_thrRefDl, m_thrRefDl * tolerance, " Unfair Throughput!");
}
NS_LOG_INFO ("UL - Test with " << m_nUser << " user(s) at distance " << m_dist);
@@ -315,10 +289,10 @@
// get the imsi
uint64_t imsi = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetImsi ();
// get the lcId
- uint8_t lcId = ueDevs.Get (i)->GetObject<LteUeNetDevice> ()->GetRrc ()->GetLcIdVector ().at (0);
+ uint8_t lcId = 3;
ulDataRxed.push_back (rlcStats->GetUlRxData (imsi, lcId));
- NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " bytes txed " << (double)ulDataRxed.at (i) << " thr " << (double)ulDataRxed.at (i) / simulationTime << " ref " << m_thrRefUl << " txed " << rlcStats->GetUlTxData (imsi, lcId) / simulationTime);
- NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / simulationTime, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
+ NS_LOG_INFO ("\tUser " << i << " imsi " << imsi << " lcid " << (uint16_t) lcId << " bytes rxed " << (double)ulDataRxed.at (i) << " thr " << (double)ulDataRxed.at (i) / statsDuration << " ref " << m_thrRefUl << " txed " << rlcStats->GetUlTxData (imsi, lcId) / statsDuration);
+ NS_TEST_ASSERT_MSG_EQ_TOL ((double)ulDataRxed.at (i) / statsDuration, m_thrRefUl, m_thrRefUl * tolerance, " Unfair Throughput!");
}
Simulator::Destroy ();
--- a/src/lte/test/test-lte-antenna.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/test-lte-antenna.cc Tue Oct 30 16:02:07 2012 +0100
@@ -149,7 +149,7 @@
enbphy->GetUplinkSpectrumPhy ()->AddDataSinrChunkProcessor (testUlSinr);
- Simulator::Stop (Seconds (0.020));
+ Simulator::Stop (Seconds (0.035));
Simulator::Run ();
--- a/src/lte/test/test-lte-epc-e2e-data.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/test/test-lte-epc-e2e-data.cc Tue Oct 30 16:02:07 2012 +0100
@@ -214,7 +214,7 @@
++dlPort;
PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), dlPort));
ApplicationContainer apps = packetSinkHelper.Install (ue);
- apps.Start (Seconds (0.01));
+ apps.Start (Seconds (0.04));
bearerTestData.dlServerApp = apps.Get (0)->GetObject<PacketSink> ();
UdpEchoClientHelper client (ueIpIface.GetAddress (0), dlPort);
@@ -222,7 +222,7 @@
client.SetAttribute ("Interval", TimeValue (bearerTestData.interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (bearerTestData.pktSize));
apps = client.Install (remoteHost);
- apps.Start (Seconds (0.01));
+ apps.Start (Seconds (0.04));
bearerTestData.dlClientApp = apps.Get (0);
}
@@ -230,7 +230,7 @@
++ulPort;
PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), ulPort));
ApplicationContainer apps = packetSinkHelper.Install (remoteHost);
- apps.Start (Seconds (0.5));
+ apps.Start (Seconds (0.8));
bearerTestData.ulServerApp = apps.Get (0)->GetObject<PacketSink> ();
UdpEchoClientHelper client (remoteHostAddr, ulPort);
@@ -238,7 +238,7 @@
client.SetAttribute ("Interval", TimeValue (bearerTestData.interPacketInterval));
client.SetAttribute ("PacketSize", UintegerValue (bearerTestData.pktSize));
apps = client.Install (ue);
- apps.Start (Seconds (0.5));
+ apps.Start (Seconds (0.8));
bearerTestData.ulClientApp = apps.Get (0);
}
@@ -266,9 +266,13 @@
Config::Set ("/NodeList/*/DeviceList/*/LteUeRrc/RadioBearerMap/*/LteRlc/MaxTxBufferSize",
UintegerValue (2 * 1024 * 1024));
- lteHelper->EnableRlcTraces ();
- lteHelper->EnablePdcpTraces ();
+
Time simulationTime = Seconds (2.0);
+
+ double statsStartTime = 0.040; // need to allow for RRC connection establishment + SRS
+ Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnablePdcpTraces, lteHelper);
+
+ lteHelper->GetPdcpStats ()->SetAttribute ("StartTime", TimeValue (Seconds (statsStartTime)));
lteHelper->GetPdcpStats ()->SetAttribute ("EpochDuration", TimeValue (simulationTime));
@@ -288,9 +292,9 @@
uint64_t imsi = ++imsiCounter;
for (uint32_t b = 0; b < ueit->bearers.size (); ++b)
{
- // LCID 0 is unused
- // LCID 1 is (at the moment) the Default EPS bearer, and is unused in this test program
- uint8_t lcid = b+2;
+ // LCID 0, 1, 2 are for SRBs
+ // LCID 3 is (at the moment) the Default EPS bearer, and is unused in this test program
+ uint8_t lcid = b+4;
NS_TEST_ASSERT_MSG_EQ (lteHelper->GetPdcpStats ()->GetDlTxPackets (imsi, lcid),
ueit->bearers.at (b).numPkts,
"wrong TX PDCP packets in downlink for IMSI=" << imsi << " LCID=" << (uint16_t) lcid);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lte/test/test-lte-rrc.cc Tue Oct 30 16:02:07 2012 +0100
@@ -0,0 +1,227 @@
+/* -*- 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 <nbaldo@cttc.es>
+ */
+
+
+#include <ns3/core-module.h>
+#include <ns3/network-module.h>
+#include <ns3/mobility-module.h>
+#include <ns3/lte-module.h>
+
+
+NS_LOG_COMPONENT_DEFINE ("LteRrcTest");
+
+namespace ns3 {
+
+class LteRrcConnectionEstablishmentTestCase : public TestCase
+{
+public:
+
+ /**
+ *
+ *
+ * \param nUes number of UEs in the test
+ * \param tc connection time base value for all UEs in ms
+ * \param tConnIncrPerUe additional connection time increment for each UE index (0...nUes-1) in ms
+ * \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);
+
+private:
+ static std::string BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart);
+ virtual void DoRun (void);
+ void Connect (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
+ void CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
+
+
+ uint32_t m_nUes; // number of UEs in the test
+ uint32_t m_nBearers; // number of UEs in the test
+ uint32_t m_tConnBase; // connection time base value for all UEs in ms
+ uint32_t m_tConnIncrPerUe; // additional connection time increment for each UE index (0...nUes-1) in ms
+ 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
+ Ptr<LteHelper> m_lteHelper;
+
+};
+
+
+std::string LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart)
+{
+ std::ostringstream oss;
+ oss << "nUes=" << nUes
+ << "nBearers=" << nBearers
+ << ", tConnBase=" << tConnBase
+ << ", tConnIncrPerUe=" << tConnIncrPerUe
+ << ", delayDiscStart=" << delayDiscStart;
+ return oss.str ();
+}
+
+LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart)
+ : TestCase ("RRC connection establishment"),
+ m_nUes (nUes),
+ m_nBearers (nBearers),
+ m_tConnBase (tConnBase),
+ 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)
+{
+}
+
+void
+LteRrcConnectionEstablishmentTestCase::DoRun ()
+{
+ // normal code
+
+ m_lteHelper = CreateObject<LteHelper> ();
+
+ NodeContainer enbNodes;
+ enbNodes.Create (1);
+ NodeContainer ueNodes;
+ ueNodes.Create (m_nUes);
+
+ MobilityHelper mobility;
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (enbNodes);
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (ueNodes);
+
+ NetDeviceContainer enbDevs;
+ enbDevs = m_lteHelper->InstallEnbDevice (enbNodes);
+
+ NetDeviceContainer ueDevs;
+ ueDevs = m_lteHelper->InstallUeDevice (ueNodes);
+
+ // custom code used for testing purposes
+ // instead of lteHelper->Attach () and lteHelper->ActivateXxx
+
+ uint32_t i = 0;
+ uint32_t tmax = 0;
+ for (NetDeviceContainer::Iterator it = ueDevs.Begin (); it != ueDevs.End (); ++it)
+ {
+ Ptr<NetDevice> ueDevice = *it;
+ Ptr<NetDevice> enbDevice = enbDevs.Get (0);
+ Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
+ Ptr<EpcUeNas> ueNas = ueLteDevice->GetNas ();
+
+ uint32_t tc = m_tConnBase + m_tConnIncrPerUe * i; // time connection start
+ uint32_t tcc = tc + m_delayConnEnd; // time check connection completed;
+ uint32_t td = tcc + m_delayDiscStart; // time disconnect start
+ uint32_t tcd = td + m_delayDiscEnd; // time check disconnection completed
+ tmax = std::max (tmax, tcd);
+
+ // trick to resolve overloading
+ //void (LteHelper::* overloadedAttachFunctionPointer) (Ptr<NetDevice>, Ptr<NetDevice>) = &LteHelper::Attach;
+ //Simulator::Schedule (MilliSeconds (tc), overloadedAttachFunctionPointer, lteHelper, *it, enbDevice);
+ Simulator::Schedule (MilliSeconds (tc), &LteRrcConnectionEstablishmentTestCase::Connect, this, ueDevice, enbDevice);
+
+ Simulator::Schedule (MilliSeconds (tcc), &LteRrcConnectionEstablishmentTestCase::CheckConnected, this, *it, enbDevice);
+
+ // disconnection not supported yet
+
+ ++i;
+ }
+
+
+ Simulator::Stop (MilliSeconds (tmax+1));
+
+ Simulator::Run ();
+
+ Simulator::Destroy ();
+
+}
+
+void
+LteRrcConnectionEstablishmentTestCase::Connect (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
+{
+ m_lteHelper->Attach (ueDevice, enbDevice);
+}
+void
+LteRrcConnectionEstablishmentTestCase::CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
+{
+ Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
+ Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc ();
+ NS_TEST_ASSERT_MSG_EQ (ueRrc->GetState (), LteUeRrc::CONNECTED_NORMALLY, "Wrong LteUeRrc state!");
+
+
+ Ptr<LteEnbNetDevice> enbLteDevice = enbDevice->GetObject<LteEnbNetDevice> ();
+ Ptr<LteEnbRrc> enbRrc = enbLteDevice->GetRrc ();
+ uint16_t rnti = ueRrc->GetRnti ();
+ Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
+ NS_TEST_ASSERT_MSG_NE (ueManager, 0, "RNTI " << rnti << " not found in eNB");
+
+ NS_TEST_ASSERT_MSG_EQ (ueManager->GetState (), UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
+
+ uint16_t ueCellId = ueRrc->GetCellId ();
+ uint16_t enbCellId = enbLteDevice->GetCellId ();
+ uint16_t ueImsi = ueLteDevice->GetImsi ();
+ uint16_t enbImsi = ueManager->GetImsi ();
+ uint8_t ueDlBandwidth = ueRrc->GetDlBandwidth ();
+ uint8_t enbDlBandwidth = enbLteDevice->GetDlBandwidth ();
+ uint8_t ueUlBandwidth = ueRrc->GetUlBandwidth ();
+ uint8_t enbUlBandwidth = enbLteDevice->GetUlBandwidth ();
+ uint8_t ueDlEarfcn = ueRrc->GetDlEarfcn ();
+ uint8_t enbDlEarfcn = enbLteDevice->GetDlEarfcn ();
+ uint8_t ueUlEarfcn = ueRrc->GetUlEarfcn ();
+ uint8_t enbUlEarfcn = enbLteDevice->GetUlEarfcn ();
+
+
+ NS_TEST_ASSERT_MSG_EQ (ueCellId, enbCellId, "inconsistent CellId");
+ NS_TEST_ASSERT_MSG_EQ (ueImsi, enbImsi, "inconsistent Imsi");
+ NS_TEST_ASSERT_MSG_EQ (ueDlBandwidth, enbDlBandwidth, "inconsistent DlBandwidth");
+ NS_TEST_ASSERT_MSG_EQ (ueUlBandwidth, enbUlBandwidth, "inconsistent UlBandwidth");
+ NS_TEST_ASSERT_MSG_EQ (ueDlEarfcn, enbDlEarfcn, "inconsistent DlEarfcn");
+ NS_TEST_ASSERT_MSG_EQ (ueUlEarfcn, enbUlEarfcn, "inconsistent UlEarfcn");
+
+}
+
+
+
+class LteRrcTestSuite : public TestSuite
+{
+public:
+ LteRrcTestSuite ();
+};
+
+
+LteRrcTestSuite::LteRrcTestSuite ()
+ : TestSuite ("lte-rrc", SYSTEM)
+{
+ NS_LOG_FUNCTION (this);
+
+ // <----- all times in ms ----------------->
+ // nUes, nBearers, tConnBase, tConnIncrPerUe, delayDiscStart
+ AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 0, 0, 0, 1));
+ AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 1, 0, 0, 1));
+ AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 1, 0, 0, 0, 1));
+ AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 2, 0, 20, 0, 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 (100, 0, 10, 1, 1));
+
+}
+
+static LteRrcTestSuite g_lteRrcTestSuiteInstance;
+
+
+
+} // namespace ns3
--- a/src/lte/wscript Tue Aug 28 15:46:47 2012 +0200
+++ b/src/lte/wscript Tue Oct 30 16:02:07 2012 +0100
@@ -14,11 +14,13 @@
'model/lte-amc.cc',
'model/lte-enb-rrc.cc',
'model/lte-ue-rrc.cc',
+ 'model/lte-rrc-protocol-ideal.cc',
'model/lte-rlc-sap.cc',
'model/lte-rlc.cc',
'model/lte-rlc-sequence-number.cc',
'model/lte-rlc-header.cc',
'model/lte-rlc-am-header.cc',
+ 'model/lte-rlc-tm.cc',
'model/lte-rlc-um.cc',
'model/lte-rlc-am.cc',
'model/lte-rlc-tag.cc',
@@ -52,6 +54,7 @@
'model/lte-enb-mac.cc',
'model/lte-ue-mac.cc',
'model/lte-radio-bearer-tag.cc',
+ 'model/eps-bearer-tag.cc',
'model/lte-phy-tag.cc',
'model/lte-enb-phy-sap.cc',
'model/lte-enb-cphy-sap.cc',
@@ -103,7 +106,8 @@
'test/test-lte-epc-e2e-data.cc',
'test/test-lte-antenna.cc',
'test/lte-test-phy-error-model.cc',
- 'test/lte-test-mimo.cc'
+ 'test/lte-test-mimo.cc',
+ 'test/test-lte-rrc.cc'
]
headers = bld.new_task_gen(features=['ns3header'])
@@ -119,11 +123,14 @@
'model/lte-amc.h',
'model/lte-enb-rrc.h',
'model/lte-ue-rrc.h',
+ 'model/lte-rrc-sap.h',
+ 'model/lte-rrc-protocol-ideal.h',
'model/lte-rlc-sap.h',
'model/lte-rlc.h',
'model/lte-rlc-header.h',
'model/lte-rlc-sequence-number.h',
'model/lte-rlc-am-header.h',
+ 'model/lte-rlc-tm.h',
'model/lte-rlc-um.h',
'model/lte-rlc-am.h',
'model/lte-rlc-tag.h',
@@ -157,6 +164,7 @@
'model/lte-enb-mac.h',
'model/lte-ue-mac.h',
'model/lte-radio-bearer-tag.h',
+ 'model/eps-bearer-tag.h',
'model/lte-phy-tag.h',
'model/lte-enb-phy-sap.h',
'model/lte-enb-cphy-sap.h',
--- a/src/spectrum/model/multi-model-spectrum-channel.cc Tue Aug 28 15:46:47 2012 +0200
+++ b/src/spectrum/model/multi-model-spectrum-channel.cc Tue Oct 30 16:02:07 2012 +0100
@@ -91,7 +91,6 @@
m_spectrumPropagationLoss = 0;
m_txSpectrumModelInfoMap.clear ();
m_rxSpectrumModelInfoMap.clear ();
- m_phyVector.clear ();
SpectrumChannel::DoDispose ();
}
@@ -142,12 +141,24 @@
std::vector<Ptr<SpectrumPhy> >::const_iterator it;
- // make sure this phy had not been already added
- for ( it = m_phyVector.begin (); it != m_phyVector.end (); ++it)
+ // remove a previous entry of this phy if it exists
+ // we need to scan for all rxSpectrumModel values since we don't
+ // know which spectrum model the phy had when it was previously added
+ // (it's probably different than the current one)
+ for (RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
+ rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
+ ++rxInfoIterator)
{
- NS_ASSERT (*it != phy);
+ std::set<Ptr<SpectrumPhy> >::iterator phyIt = rxInfoIterator->second.m_rxPhySet.find (phy);
+ if (phyIt != rxInfoIterator->second.m_rxPhySet.end ())
+ {
+ rxInfoIterator->second.m_rxPhySet.erase (phyIt);
+ --m_numDevices;
+ break; // there should be at most one entry
+ }
}
- m_phyVector.push_back (phy);
+
+ ++m_numDevices;
RxSpectrumModelInfoMap_t::iterator rxInfoIterator = m_rxSpectrumModelInfoMap.find (rxSpectrumModelUid);
@@ -157,8 +168,9 @@
std::pair<RxSpectrumModelInfoMap_t::iterator, bool> ret;
ret = m_rxSpectrumModelInfoMap.insert (std::make_pair (rxSpectrumModelUid, RxSpectrumModelInfo (rxSpectrumModel)));
NS_ASSERT (ret.second);
- // also add the phy to the newly created list of SpectrumPhy for this RxSpectrumModel
- ret.first->second.m_rxPhyList.push_back (phy);
+ // also add the phy to the newly created set of SpectrumPhy for this RxSpectrumModel
+ std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = ret.first->second.m_rxPhySet.insert (phy);
+ NS_ASSERT (ret2.second);
// and create the necessary converters for all the TX spectrum models that we know of
for (TxSpectrumModelInfoMap_t::iterator txInfoIterator = m_txSpectrumModelInfoMap.begin ();
@@ -176,7 +188,8 @@
else
{
// spectrum model is already known, just add the device to the corresponding list
- rxInfoIterator->second.m_rxPhyList.push_back (phy);
+ std::pair<std::set<Ptr<SpectrumPhy> >::iterator, bool> ret2 = rxInfoIterator->second.m_rxPhySet.insert (phy);
+ NS_ASSERT (ret2.second);
}
}
@@ -223,7 +236,7 @@
}
return txInfoIterator;
}
-
+
void
MultiModelSpectrumChannel::StartTx (Ptr<SpectrumSignalParameters> txParams)
@@ -268,14 +281,12 @@
}
- for (std::list<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhyList.begin ();
- rxPhyIterator != rxInfoIterator->second.m_rxPhyList.end ();
+ for (std::set<Ptr<SpectrumPhy> >::const_iterator rxPhyIterator = rxInfoIterator->second.m_rxPhySet.begin ();
+ rxPhyIterator != rxInfoIterator->second.m_rxPhySet.end ();
++rxPhyIterator)
{
NS_ASSERT_MSG ((*rxPhyIterator)->GetRxSpectrumModel ()->GetUid () == rxSpectrumModelUid,
- "MultiModelSpectrumChannel only supports devices that use a single RxSpectrumModel that does not change for the whole simulation");
-
-
+ "SpectrumModel change was not notified to MultiModelSpectrumChannel (i.e., AddRx should be called again after model is changed)");
if ((*rxPhyIterator) != txParams->txPhy)
{
@@ -364,7 +375,7 @@
uint32_t
MultiModelSpectrumChannel::GetNDevices (void) const
{
- return m_phyVector.size ();
+ return m_numDevices;
}
@@ -372,7 +383,32 @@
Ptr<NetDevice>
MultiModelSpectrumChannel::GetDevice (uint32_t i) const
{
- return m_phyVector.at (i)->GetDevice ();
+ NS_ASSERT (i < m_numDevices);
+ // this method implementation is computationally intensive. This
+ // method would be faster if we actually used a std::vector for
+ // storing devices, which we don't due to the need to have fast
+ // SpectrumModel conversions and to allow PHY devices to changea
+ // SpectrumModel at run time. Note that having this method slow is
+ // acceptable as it is not used much at run time (often not at all).
+ // On the other hand, having slow SpectrumModel conversion would be
+ // less acceptable.
+ uint32_t j = 0;
+ for (RxSpectrumModelInfoMap_t::const_iterator rxInfoIterator = m_rxSpectrumModelInfoMap.begin ();
+ rxInfoIterator != m_rxSpectrumModelInfoMap.end ();
+ ++rxInfoIterator)
+ {
+ for (std::set<Ptr<SpectrumPhy> >::const_iterator phyIt = rxInfoIterator->second.m_rxPhySet.begin ();
+ phyIt != rxInfoIterator->second.m_rxPhySet.end ();
+ ++phyIt)
+ {
+ if (j == i)
+ {
+ return (*phyIt)->GetDevice ();
+ }
+ }
+ }
+ NS_FATAL_ERROR ("m_numDevice > actual number of devices");
+ return 0;
}
--- a/src/spectrum/model/multi-model-spectrum-channel.h Tue Aug 28 15:46:47 2012 +0200
+++ b/src/spectrum/model/multi-model-spectrum-channel.h Tue Oct 30 16:02:07 2012 +0100
@@ -28,7 +28,7 @@
#include <ns3/spectrum-propagation-loss-model.h>
#include <ns3/propagation-delay-model.h>
#include <map>
-#include <list>
+#include <set>
namespace ns3 {
@@ -62,7 +62,7 @@
RxSpectrumModelInfo (Ptr<const SpectrumModel> rxSpectrumModel);
Ptr<const SpectrumModel> m_rxSpectrumModel;
- std::list<Ptr<SpectrumPhy> > m_rxPhyList;
+ std::set<Ptr<SpectrumPhy> > m_rxPhySet;
};
typedef std::map<SpectrumModelUid_t, RxSpectrumModelInfo> RxSpectrumModelInfoMap_t;
@@ -75,9 +75,13 @@
*
* This SpectrumChannel implementation can handle the presence of
* SpectrumPhy instances which can use
- * different spectrum models, i.e., different SpectrumModel. The only
- * requirement is that every SpectrumPhy instance uses the same
- * SpectrumModel for the whole simulation.
+ * different spectrum models, i.e., different SpectrumModel.
+ *
+ * \note It is allowed for a receiving SpectrumPhy to switch to a
+ * different SpectrumModel during the simulation. The requirement
+ * for this to work is that, after the SpectrumPhy switched its
+ * SpectrumModel, MultiModelSpectrumChannel::AddRx () is
+ * called again passing the pointer to that SpectrumPhy.
*/
class MultiModelSpectrumChannel : public SpectrumChannel
{
@@ -120,18 +124,6 @@
*/
TxSpectrumModelInfoMap_t::const_iterator FindAndEventuallyAddTxSpectrumModel (Ptr<const SpectrumModel> txSpectrumModel);
-
- /**
- * make sure that there are SpectrumConverters from any
- * SpectrumPhy being used for TX to the given SpectrumModel being used for RX
- *
- * @param rxPhy the RXing SpectrumPhy
- * @param rxSpectrumModel the SpectrumModel used for RX by rxPhy
- */
- void CheckAddRxSpectrumModel (Ptr<SpectrumPhy> rxPhy, Ptr<const SpectrumModel> rxSpectrumModel);
-
-
-
/**
* used internally to reschedule transmission after the propagation delay
*
@@ -177,13 +169,7 @@
*/
RxSpectrumModelInfoMap_t m_rxSpectrumModelInfoMap;
- /**
- * this is only used to provide a straighforward implementation of
- * GetNDevices() and GetDevice()
- *
- */
- std::vector<Ptr<SpectrumPhy> > m_phyVector;
-
+ uint32_t m_numDevices;
double m_maxLossDb;