--- a/src/lte/examples/lena-x2-handover.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/examples/lena-x2-handover.cc Tue Nov 20 18:18:01 2012 +0100
@@ -39,22 +39,22 @@
int
main (int argc, char *argv[])
{
- LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL);
+ // LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL);
- LogComponentEnable ("LteHelper", logLevel);
- LogComponentEnable ("EpcHelper", logLevel);
- LogComponentEnable ("EpcEnbApplication", logLevel);
- LogComponentEnable ("EpcX2", logLevel);
- LogComponentEnable ("EpcSgwPgwApplication", logLevel);
+ // LogComponentEnable ("LteHelper", logLevel);
+ // LogComponentEnable ("EpcHelper", logLevel);
+ // LogComponentEnable ("EpcEnbApplication", logLevel);
+ // LogComponentEnable ("EpcX2", logLevel);
+ // LogComponentEnable ("EpcSgwPgwApplication", logLevel);
- LogComponentEnable ("LteEnbRrc", logLevel);
- LogComponentEnable ("LteEnbNetDevice", logLevel);
- LogComponentEnable ("LteUeRrc", logLevel);
- LogComponentEnable ("LteUeNetDevice", logLevel);
+ // LogComponentEnable ("LteEnbRrc", logLevel);
+ // LogComponentEnable ("LteEnbNetDevice", logLevel);
+ // LogComponentEnable ("LteUeRrc", logLevel);
+ // LogComponentEnable ("LteUeNetDevice", logLevel);
uint16_t numberOfUes = 1;
uint16_t numberOfEnbs = 2;
- double simTime = 6.0;
+ double simTime = 2.0;
double distance = 60.0;
// Command line arguments
@@ -145,7 +145,7 @@
lteHelper->AddX2Interface (enbNodes);
// X2-based Handover
- lteHelper->HandoverRequest (Seconds (2.0), ueLteDevs.Get (0), enbLteDevs.Get (0), enbLteDevs.Get (1));
+ lteHelper->HandoverRequest (Seconds (1.0), ueLteDevs.Get (0), enbLteDevs.Get (0), enbLteDevs.Get (1));
// Uncomment to enable PCAP tracing
--- a/src/lte/model/lte-control-messages.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-control-messages.cc Tue Nov 20 18:18:01 2012 +0100
@@ -182,19 +182,18 @@
}
void
-RachPreambleLteControlMessage::SetPrachId (uint32_t prachId)
+RachPreambleLteControlMessage::SetRapId (uint32_t rapId)
{
- m_prachId = prachId;
+ m_rapId = rapId;
}
uint32_t
-RachPreambleLteControlMessage::GetPrachId () const
+RachPreambleLteControlMessage::GetRapId () const
{
- return m_prachId;
+ return m_rapId;
}
-
// ----------------------------------------------------------------------------------------------------------
@@ -205,28 +204,34 @@
void
-RarLteControlMessage::SetRar (BuildRarListElement_s rar)
+RarLteControlMessage::SetRaRnti (uint16_t raRnti)
{
- m_rar = rar;
+ m_raRnti = raRnti;
}
-BuildRarListElement_s
-RarLteControlMessage::GetRar () const
+uint16_t
+RarLteControlMessage::GetRaRnti () const
{
- return m_rar;
+ return m_raRnti;
}
void
-RarLteControlMessage::SetPrachId (uint32_t prachId)
+RarLteControlMessage::AddRar (Rar rar)
{
- m_prachId = prachId;
+ m_rarList.push_back (rar);
}
-uint32_t
-RarLteControlMessage::GetPrachId () const
+std::list<RarLteControlMessage::Rar>::const_iterator
+RarLteControlMessage::RarListBegin () const
{
- return m_prachId;
+ return m_rarList.begin ();
+}
+
+std::list<RarLteControlMessage::Rar>::const_iterator
+RarLteControlMessage::RarListEnd () const
+{
+ return m_rarList.end ();
}
--- a/src/lte/model/lte-control-messages.h Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-control-messages.h Tue Nov 20 18:18:01 2012 +0100
@@ -279,13 +279,23 @@
public:
RachPreambleLteControlMessage (void);
- void SetPrachId (uint32_t prachId);
-
- uint32_t GetPrachId () const;
+
+ /**
+ * Set the Random Access Preamble Identifier (RAPID), see 3GPP TS 36.321 6.2.2
+ *
+ * \param rapid
+ */
+ void SetRapId (uint32_t rapid);
+
+ /**
+ *
+ * \return the RAPID
+ */
+ uint32_t GetRapId () const;
private:
- uint32_t m_prachId;
+ uint32_t m_rapId;
};
@@ -315,19 +325,52 @@
public:
RarLteControlMessage (void);
- void SetRar (BuildRarListElement_s);
+ /**
+ *
+ * \param raRnti the RA-RNTI, see 3GPP TS 36.321 5.1.4
+ */
+ void SetRaRnti (uint16_t raRnti);
+
+ /**
+ *
+ * \return the RA-RNTI, see 3GPP TS 36.321 5.1.4
+ */
+ uint16_t GetRaRnti () const;
- BuildRarListElement_s GetRar () const;
+ /**
+ * a MAC RAR and the corresponding RAPID subheader
+ *
+ */
+ struct Rar
+ {
+ uint8_t rapId;
+ BuildRarListElement_s rarPayload;
+ };
+
+ /**
+ * add a RAR to the MAC PDU, see 3GPP TS 36.321 6.2.3
+ *
+ * \param rar the rar
+ */
+ void AddRar (Rar rar);
+
+ /**
+ *
+ * \return a const iterator to the beginning of the RAR list
+ */
+ std::list<Rar>::const_iterator RarListBegin () const;
- void SetPrachId (uint32_t prachId);
+ /**
+ *
+ * \return a const iterator to the end of the RAR list
+ */
+ std::list<Rar>::const_iterator RarListEnd () const;
- uint32_t GetPrachId () const;
-
-
+
private:
- BuildRarListElement_s m_rar;
- uint32_t m_prachId;
+ std::list<Rar> m_rarList;
+ uint16_t m_raRnti;
};
--- a/src/lte/model/lte-enb-cmac-sap.h Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-enb-cmac-sap.h Tue Nov 20 18:18:01 2012 +0100
@@ -118,9 +118,49 @@
uint8_t m_transmissionMode;
};
+ /**
+ * update the configuration of the UE
+ *
+ * \param params
+ */
virtual void UeUpdateConfigurationReq (UeConfig params) = 0;
+ /**
+ * struct defining the RACH configuration of the MAC
+ *
+ */
+ struct RachConfig
+ {
+ uint8_t numberOfRaPreambles;
+ uint8_t preambleTransMax;
+ uint8_t raResponseWindowSize;
+ };
+
+ /**
+ *
+ * \return the current RACH configuration of the MAC
+ */
+ virtual RachConfig GetRachConfig () = 0;
+
+ /**
+ *
+ *
+ */
+ struct AllocateNcRaPreambleReturnValue
+ {
+ bool valid; ///< true if a valid RA config was allocated, false otherwise
+ uint8_t raPreambleId; ///< random access preamble id
+ uint8_t raPrachMaskIndex; /// PRACH mask index
+ };
+
+ /**
+ * Allocate a random access preamble for non-contention based random access (e.g., for handover).
+ *
+ * \return the newly allocated random access preamble (0 <
+ */
+ virtual AllocateNcRaPreambleReturnValue AllocateNcRaPreamble () = 0;
+
};
--- a/src/lte/model/lte-enb-mac.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-enb-mac.cc Tue Nov 20 18:18:01 2012 +0100
@@ -23,6 +23,7 @@
#include <ns3/log.h>
#include <ns3/pointer.h>
#include <ns3/packet.h>
+#include <ns3/simulator.h>
#include "lte-amc.h"
#include "lte-control-messages.h"
@@ -64,6 +65,9 @@
virtual void ReconfigureLc (LcInfo lcinfo);
virtual void ReleaseLc (uint16_t rnti, uint8_t lcid);
virtual void UeUpdateConfigurationReq (UeConfig params);
+ virtual RachConfig GetRachConfig ();
+ virtual AllocateNcRaPreambleReturnValue AllocateNcRaPreamble ();
+
private:
LteEnbMac* m_mac;
@@ -117,6 +121,17 @@
m_mac->DoUeUpdateConfigurationReq (params);
}
+LteEnbCmacSapProvider::RachConfig
+EnbMacMemberLteEnbCmacSapProvider::GetRachConfig ()
+{
+ return m_mac->DoGetRachConfig ();
+}
+
+LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue
+EnbMacMemberLteEnbCmacSapProvider::AllocateNcRaPreamble ()
+{
+ return m_mac->DoAllocateNcRaPreamble ();
+}
class EnbMacMemberFfMacSchedSapUser : public FfMacSchedSapUser
@@ -287,6 +302,21 @@
static TypeId tid = TypeId ("ns3::LteEnbMac")
.SetParent<Object> ()
.AddConstructor<LteEnbMac> ()
+ .AddAttribute ("NumberOfRaPreambles",
+ "how many random access preambles are available for the contention based RACH process",
+ UintegerValue (50),
+ MakeUintegerAccessor (&LteEnbMac::m_numberOfRaPreambles),
+ MakeUintegerChecker<uint8_t> (4, 64))
+ .AddAttribute ("PreambleTransMax",
+ "Maximum number of random access preamble transmissions",
+ UintegerValue (10),
+ MakeUintegerAccessor (&LteEnbMac::m_preambleTransMax),
+ MakeUintegerChecker<uint8_t> (3, 200))
+ .AddAttribute ("RaResponseWindowSize",
+ "length of the window (in TTIs) for the reception of the random access response (RAR); the resulting RAR timeout is this value + 3 ms",
+ UintegerValue (3),
+ MakeUintegerAccessor (&LteEnbMac::m_raResponseWindowSize),
+ MakeUintegerChecker<uint8_t> (2, 10))
.AddTraceSource ("DlScheduling",
"Information regarding DL scheduling.",
MakeTraceSourceAccessor (&LteEnbMac::m_dlScheduling))
@@ -419,6 +449,50 @@
m_schedSapProvider->SchedDlCqiInfoReq (dlcqiInfoReq);
}
+ if (!m_receivedRachPreambleCount.empty ())
+ {
+ // process received RACH preambles and notify the scheduler
+ FfMacSchedSapProvider::SchedDlRachInfoReqParameters rachInfoReqParams;
+ // TODO: we should wait for DL_SCHEDULE_INDICATION to build the RARs
+ // from the RAR_List; this requires proper support from the scheduler.
+ // For now, we take a shortcut and just build the RAR here
+ // as an ideal message and without an UL grant.
+ Ptr<RarLteControlMessage> rarMsg = Create<RarLteControlMessage> ();
+ NS_ASSERT (subframeNo > 0 && subframeNo <= 10); // subframe in 1..10
+ // see TS 36.321 5.1.4; preambles were sent two frames ago
+ // (plus 3GPP counts subframes from 0, not 1)
+ uint16_t raRnti = subframeNo - 3;
+ rarMsg->SetRaRnti (raRnti);
+ for (std::map<uint8_t, uint32_t>::const_iterator it = m_receivedRachPreambleCount.begin ();
+ it != m_receivedRachPreambleCount.end ();
+ ++it)
+ {
+ NS_LOG_LOGIC ("preambleId " << (uint32_t) it->first << ": " << it->second << " received");
+ NS_ASSERT (it->second != 0);
+ if (it->second > 1)
+ {
+ NS_LOG_INFO ("preambleId " << (uint32_t) it->first << ": collision");
+ // we assume that no preamble is successfully received, hence no RAR is sent
+ }
+ else
+ {
+ uint16_t rnti = m_cmacSapUser->AllocateTemporaryCellRnti ();
+ NS_LOG_INFO ("preambleId " << (uint32_t) it->first << ": allocated T-C-RNTI " << (uint32_t) rnti << ", sending RAR");
+ RachListElement_s rachLe;
+ rachLe.m_rnti = rnti;
+ rachLe.m_estimatedSize = 144; // to be confirmed
+ rachInfoReqParams.m_rachList.push_back (rachLe);
+ RarLteControlMessage::Rar rar;
+ rar.rapId = it->first;
+ rar.rarPayload.m_rnti = rnti;
+ // no UL grant for now
+ rarMsg->AddRar (rar);
+ }
+ }
+ m_schedSapProvider->SchedDlRachInfoReq (rachInfoReqParams);
+ m_enbPhySapProvider->SendLteControlMessage (rarMsg);
+ m_receivedRachPreambleCount.clear ();
+ }
// Get downlink transmission opportunities
uint32_t dlSchedFrameNo = m_frameNo;
@@ -525,28 +599,13 @@
}
void
-LteEnbMac::DoReceiveRachPreamble (uint32_t prachId)
+LteEnbMac::DoReceiveRachPreamble (uint8_t rapId)
{
- 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);
-
+ NS_LOG_FUNCTION (this << rapId);
+ // just record that the preamble has been received; it will be processed later
+ ++m_receivedRachPreambleCount[rapId]; // will create entry if not exists
}
-
-
void
LteEnbMac::DoUlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi)
{
@@ -725,6 +784,63 @@
NS_FATAL_ERROR ("not implemented");
}
+void
+LteEnbMac::DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params)
+{
+ NS_LOG_FUNCTION (this);
+
+ // propagates to scheduler
+ FfMacCschedSapProvider::CschedUeConfigReqParameters req;
+ req.m_rnti = params.m_rnti;
+ req.m_transmissionMode = params.m_transmissionMode;
+ req.m_reconfigureFlag = true;
+ m_cschedSapProvider->CschedUeConfigReq (req);
+}
+
+LteEnbCmacSapProvider::RachConfig
+LteEnbMac::DoGetRachConfig ()
+{
+ struct LteEnbCmacSapProvider::RachConfig rc;
+ rc.numberOfRaPreambles = m_numberOfRaPreambles;
+ rc.preambleTransMax = m_preambleTransMax;
+ rc.raResponseWindowSize = m_raResponseWindowSize;
+ return rc;
+}
+
+LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue
+LteEnbMac::DoAllocateNcRaPreamble ()
+{
+ bool found = false;
+ uint8_t preambleId;
+ for (preambleId = m_numberOfRaPreambles; preambleId < 64; ++preambleId)
+ {
+ std::map<uint8_t, Time>::iterator it = m_allocatedNcRaPreambleMap.find (preambleId);
+ if ((it == m_allocatedNcRaPreambleMap.end ())
+ || (it->second < Simulator::Now ()))
+ {
+ found = true;
+ uint32_t expiryIntervalMs = (uint32_t) m_preambleTransMax * ((uint32_t) m_raResponseWindowSize + 5);
+ Time expiryTime = Simulator::Now () + MilliSeconds (expiryIntervalMs);
+ m_allocatedNcRaPreambleMap[preambleId] = expiryTime; // create if not exist, update otherwise
+ break;
+ }
+ }
+ LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue ret;
+ if (found)
+ {
+ ret.valid = true;
+ ret.raPreambleId = preambleId;
+ ret.raPrachMaskIndex = 0;
+ }
+ else
+ {
+ ret.valid = false;
+ ret.raPreambleId = 0;
+ ret.raPrachMaskIndex = 0;
+ }
+ return ret;
+}
+
// ////////////////////////////////////////////
@@ -902,19 +1018,6 @@
}
void
-LteEnbMac::DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params)
-{
- NS_LOG_FUNCTION (this);
-
- // propagates to scheduler
- FfMacCschedSapProvider::CschedUeConfigReqParameters req;
- req.m_rnti = params.m_rnti;
- req.m_transmissionMode = params.m_transmissionMode;
- req.m_reconfigureFlag = true;
- m_cschedSapProvider->CschedUeConfigReq (req);
-}
-
-void
LteEnbMac::DoCschedCellConfigUpdateInd (FfMacCschedSapUser::CschedCellConfigUpdateIndParameters params)
{
NS_LOG_FUNCTION (this);
--- a/src/lte/model/lte-enb-mac.h Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-enb-mac.h Tue Nov 20 18:18:01 2012 +0100
@@ -147,6 +147,9 @@
void DoAddLc (LteEnbCmacSapProvider::LcInfo lcinfo, LteMacSapUser* msu);
void DoReconfigureLc (LteEnbCmacSapProvider::LcInfo lcinfo);
void DoReleaseLc (uint16_t rnti, uint8_t lcid);
+ void DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params);
+ LteEnbCmacSapProvider::RachConfig DoGetRachConfig ();
+ LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue DoAllocateNcRaPreamble ();
// forwarded from LteMacSapProvider
void DoTransmitPdu (LteMacSapProvider::TransmitPduParameters);
@@ -165,12 +168,10 @@
// forwarded from FfMacSchedSapUser
void DoSchedDlConfigInd (FfMacSchedSapUser::SchedDlConfigIndParameters ind);
void DoSchedUlConfigInd (FfMacSchedSapUser::SchedUlConfigIndParameters params);
-
- void DoUeUpdateConfigurationReq (LteEnbCmacSapProvider::UeConfig params);
// forwarded from LteEnbPhySapUser
void DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo);
- void DoReceiveRachPreamble (uint32_t prachId);
+ void DoReceiveRachPreamble (uint8_t prachId);
public:
// legacy public for use the Phy callback
@@ -222,7 +223,19 @@
uint8_t m_macChTtiDelay; // delay of MAC, PHY and channel in terms of TTIs
+ uint8_t m_numberOfRaPreambles;
+ uint8_t m_preambleTransMax;
+ uint8_t m_raResponseWindowSize;
+ /**
+ * map storing as key the random acccess preamble IDs allocated for
+ * non-contention based access, and as value the expiration time of
+ * this allocation (so that stale preambles can be reused).
+ *
+ */
+ std::map<uint8_t, Time> m_allocatedNcRaPreambleMap;
+
+ std::map<uint8_t, uint32_t> m_receivedRachPreambleCount;
};
} // end namespace ns3
--- a/src/lte/model/lte-enb-phy.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-enb-phy.cc Tue Nov 20 18:18:01 2012 +0100
@@ -410,7 +410,7 @@
case LteControlMessage::RACH_PREAMBLE:
{
Ptr<RachPreambleLteControlMessage> rachPreamble = DynamicCast<RachPreambleLteControlMessage> (*it);
- m_enbPhySapUser->ReceiveRachPreamble (rachPreamble->GetPrachId ());
+ m_enbPhySapUser->ReceiveRachPreamble (rachPreamble->GetRapId ());
}
break;
--- a/src/lte/model/lte-enb-rrc.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-enb-rrc.cc Tue Nov 20 18:18:01 2012 +0100
@@ -410,7 +410,7 @@
}
LteRrcSap::RrcConnectionReconfiguration
-UeManager::GetHandoverCommand ()
+UeManager::GetRrcConnectionReconfigurationForHandover ()
{
NS_LOG_FUNCTION (this);
return BuildRrcConnectionReconfiguration ();
@@ -509,6 +509,10 @@
case CONNECTION_RECONFIGURATION:
SwitchToState (CONNECTED_NORMALLY);
break;
+
+ case HANDOVER_LEAVING:
+ NS_LOG_INFO ("ignoring RecvRrcConnectionReconfigurationCompleted in state " << ToString (m_state));
+ break;
case HANDOVER_JOINING:
NS_LOG_INFO ("Send UE CONTEXT RELEASE from target eNB to source eNB");
@@ -1118,6 +1122,8 @@
NS_LOG_LOGIC ("oldEnbUeX2apId = " << params.oldEnbUeX2apId);
NS_LOG_LOGIC ("sourceCellId = " << params.sourceCellId);
NS_LOG_LOGIC ("targetCellId = " << params.targetCellId);
+
+ NS_ASSERT (params.targetCellId == m_cellId);
uint16_t rnti = AddUe (UeManager::HANDOVER_JOINING);
Ptr<UeManager> ueManager = GetUeManager (rnti);
@@ -1130,7 +1136,26 @@
ueManager->SetupDataRadioBearer (it->erabLevelQosParameters, it->gtpTeid, it->transportLayerAddress);
}
- LteRrcSap::RrcConnectionReconfiguration handoverCommand = ueManager->GetHandoverCommand ();
+ LteRrcSap::RrcConnectionReconfiguration handoverCommand = ueManager->GetRrcConnectionReconfigurationForHandover ();
+ handoverCommand.haveMobilityControlInfo = true;
+ handoverCommand.mobilityControlInfo.targetPhysCellId = m_cellId;
+ handoverCommand.mobilityControlInfo.carrierFreq.dlCarrierFreq = m_dlEarfcn;
+ handoverCommand.mobilityControlInfo.carrierFreq.ulCarrierFreq = m_ulEarfcn;
+ handoverCommand.mobilityControlInfo.haveCarrierBandwidth = true;
+ handoverCommand.mobilityControlInfo.carrierBandwidth.dlBandwidth = m_dlBandwidth;
+ handoverCommand.mobilityControlInfo.carrierBandwidth.ulBandwidth = m_ulBandwidth;
+ handoverCommand.mobilityControlInfo.newUeIdentity = rnti;
+ LteEnbCmacSapProvider::AllocateNcRaPreambleReturnValue anrcrv = m_cmacSapProvider->AllocateNcRaPreamble ();
+ if (anrcrv.valid == true)
+ {
+ handoverCommand.mobilityControlInfo.haveRachConfigDedicated = true;
+ handoverCommand.mobilityControlInfo.rachConfigDedicated.raPreambleIndex = anrcrv.raPreambleId;
+ handoverCommand.mobilityControlInfo.rachConfigDedicated.raPrachMaskIndex = anrcrv.raPrachMaskIndex;
+ }
+ else
+ {
+ handoverCommand.mobilityControlInfo.haveRachConfigDedicated = false;
+ }
Ptr<Packet> encodedHandoverCommand = m_rrcSapUser->EncodeHandoverCommand (handoverCommand);
NS_LOG_LOGIC ("Send X2 message: HANDOVER REQUEST ACK");
@@ -1440,6 +1465,14 @@
si.haveSib2 = true;
si.sib2.freqInfo.ulCarrierFreq = m_ulEarfcn;
si.sib2.freqInfo.ulBandwidth = m_ulBandwidth;
+
+ LteEnbCmacSapProvider::RachConfig rc = m_cmacSapProvider->GetRachConfig ();
+ LteRrcSap::RachConfigCommon rachConfigCommon;
+ rachConfigCommon.preambleInfo.numberOfRaPreambles = rc.numberOfRaPreambles;
+ rachConfigCommon.raSupervisionInfo.preambleTransMax = rc.preambleTransMax;
+ rachConfigCommon.raSupervisionInfo.raResponseWindowSize = rc.raResponseWindowSize;
+ si.sib2.radioResourceConfigCommon.rachConfigCommon = rachConfigCommon;
+
m_rrcSapUser->SendSystemInformation (si);
Simulator::Schedule (m_systemInformationPeriodicity, &LteEnbRrc::SendSystemInformation, this);
}
--- a/src/lte/model/lte-enb-rrc.h Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-enb-rrc.h Tue Nov 20 18:18:01 2012 +0100
@@ -155,8 +155,11 @@
* \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.
+ *
+ * \note mobility control info is not expected to be filled in
+ * (shall be filled in by the caller).
*/
- LteRrcSap::RrcConnectionReconfiguration GetHandoverCommand ();
+ LteRrcSap::RrcConnectionReconfiguration GetRrcConnectionReconfigurationForHandover ();
/**
* Send a data packet over the appropriate Data Radio Bearer
@@ -548,7 +551,7 @@
void DoRrcConfigurationUpdateInd (LteEnbCmacSapUser::UeConfig params);
-
+ // Internal methods
/**
* Allocate a new RNTI for a new UE. This is done in the following cases:
--- a/src/lte/model/lte-rrc-sap.h Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-rrc-sap.h Tue Nov 20 18:18:01 2012 +0100
@@ -136,12 +136,31 @@
LogicalChannelConfig logicalChannelConfig;
};
+ struct PreambleInfo
+ {
+ uint8_t numberOfRaPreambles;
+ };
+
+ struct RaSupervisionInfo
+ {
+ uint8_t preambleTransMax;
+ uint8_t raResponseWindowSize;
+ };
+
+ struct RachConfigCommon
+ {
+ PreambleInfo preambleInfo;
+ RaSupervisionInfo raSupervisionInfo;
+ };
+
struct RadioResourceConfigCommon
{
+ RachConfigCommon rachConfigCommon;
};
struct RadioResourceConfigCommonSib
{
+ RachConfigCommon rachConfigCommon;
};
struct RadioResourceConfigDedicated
--- a/src/lte/model/lte-ue-cmac-sap.h Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-ue-cmac-sap.h Tue Nov 20 18:18:01 2012 +0100
@@ -42,6 +42,15 @@
public:
virtual ~LteUeCmacSapProvider ();
+ struct RachConfig
+ {
+ uint8_t numberOfRaPreambles;
+ uint8_t preambleTransMax;
+ uint8_t raResponseWindowSize;
+ };
+
+ virtual void ConfigureRach (RachConfig rc) = 0;
+
/**
* tell the MAC to start a contention-based random access procedure,
* e.g., to perform RRC connection establishment
@@ -54,10 +63,10 @@
* procedure, e.g., as a consequence of handover
*
* \param rnti
- * \param preambleId
+ * \param rapId Random Access Preamble Identifier
* \param prachMask
*/
- virtual void StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask) = 0;
+ virtual void StartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t rapId, uint8_t prachMask) = 0;
struct LogicalChannelConfig
--- a/src/lte/model/lte-ue-mac.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-ue-mac.cc Tue Nov 20 18:18:01 2012 +0100
@@ -53,6 +53,7 @@
UeMemberLteUeCmacSapProvider (LteUeMac* mac);
// inherited from LteUeCmacSapProvider
+ virtual void ConfigureRach (RachConfig rc);
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);
@@ -69,6 +70,12 @@
{
}
+void
+UeMemberLteUeCmacSapProvider::ConfigureRach (RachConfig rc)
+{
+ m_mac->DoConfigureRach (rc);
+}
+
void
UeMemberLteUeCmacSapProvider::StartContentionBasedRandomAccessProcedure ()
{
@@ -195,7 +202,9 @@
: m_bsrPeriodicity (MilliSeconds (1)), // ideal behavior
m_bsrLast (MilliSeconds (0)),
m_freshUlBsr (false),
- m_rnti (0)
+ m_rnti (0),
+ m_rachConfigured (false),
+ m_waitingForRaResponse (false)
{
NS_LOG_FUNCTION (this);
@@ -336,15 +345,22 @@
}
void
-LteUeMac::DoStartContentionBasedRandomAccessProcedure ()
+LteUeMac::RandomlySelectAndSendRaPreamble ()
{
NS_LOG_FUNCTION (this);
- static uint32_t prachIdCounter = 256;
- prachIdCounter += 2;
- m_prachId = prachIdCounter;
- NS_LOG_INFO ("sending RACH preamble " << m_prachId);
-
-
+ // 3GPP 36.321 5.1.1
+ NS_ASSERT_MSG (m_rachConfigured, "RACH not configured");
+ UniformVariable uv;
+ // assume that there is no Random Access Preambles group B
+ m_raPreambleId = uv.GetInteger (0, m_rachConfig.numberOfRaPreambles - 1);
+ bool contention = true;
+ SendRaPreamble (contention);
+}
+
+void
+LteUeMac::SendRaPreamble (bool contention)
+{
+ NS_LOG_FUNCTION (this << (uint32_t) m_raPreambleId << contention);
// 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
@@ -352,23 +368,101 @@
// 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.
+ m_uePhySapProvider->SendRachPreamble (m_raPreambleId);
+ NS_ASSERT (m_subframeNo > 0); // sanity check for subframe starting at 1
+ m_raRnti = m_subframeNo - 1;
+ NS_LOG_INFO (this << " sent preamble id " << (uint32_t) m_raPreambleId << ", RA-RNTI " << (uint32_t) m_raRnti);
+ // 3GPP 36.321 5.1.4
+ Time raWindowBegin = MilliSeconds (3);
+ Time raWindowEnd = MilliSeconds (3 + m_rachConfig.raResponseWindowSize);
+ Simulator::Schedule (raWindowBegin, &LteUeMac::StartWaitingForRaResponse, this);
+ m_noRaResponseReceivedEvent = Simulator::Schedule (raWindowEnd, &LteUeMac::RaResponseTimeout, this, contention);
+}
- Ptr<RachPreambleLteControlMessage> msg = Create<RachPreambleLteControlMessage> ();
- msg->SetPrachId (m_prachId);
- m_uePhySapProvider->SendRachPreamble (m_prachId);
+void
+LteUeMac::StartWaitingForRaResponse ()
+{
+ NS_LOG_FUNCTION (this);
+ m_waitingForRaResponse = true;
+}
+
+void
+LteUeMac::RecvRaResponse (BuildRarListElement_s raResponse)
+{
+ NS_LOG_FUNCTION (this);
+ m_waitingForRaResponse = false;
+ m_noRaResponseReceivedEvent.Cancel ();
+ NS_LOG_INFO ("got RAR for RAPID " << (uint32_t) m_raPreambleId << ", setting T-C-RNTI = " << raResponse.m_rnti);
+ m_rnti = raResponse.m_rnti;
+ m_cmacSapUser->SetTemporaryCellRnti (m_rnti);
+ // in principle we should wait for contention resolution,
+ // but in the current LTE model when two or more identical
+ // preambles are sent no one is received, so there is no need
+ // for contention resolution
+ m_cmacSapUser->NotifyRandomAccessSuccessful ();
+}
+
+void
+LteUeMac::RaResponseTimeout (bool contention)
+{
+ NS_LOG_FUNCTION (this << contention);
+ m_waitingForRaResponse = false;
+ // 3GPP 36.321 5.1.4
+ ++m_preambleTransmissionCounter;
+ if (m_preambleTransmissionCounter == m_rachConfig.preambleTransMax + 1)
+ {
+ NS_LOG_INFO ("RAR timeout, preambleTransMax reached => giving up");
+ m_cmacSapUser->NotifyRandomAccessFailed ();
+ }
+ else
+ {
+ NS_LOG_INFO ("RAR timeout, re-send preamble");
+ if (contention)
+ {
+ RandomlySelectAndSendRaPreamble ();
+ }
+ else
+ {
+ SendRaPreamble (contention);
+ }
+ }
+}
+
+void
+LteUeMac::DoConfigureRach (LteUeCmacSapProvider::RachConfig rc)
+{
+ NS_LOG_FUNCTION (this);
+ m_rachConfig = rc;
+ m_rachConfigured = true;
+}
+
+void
+LteUeMac::DoStartContentionBasedRandomAccessProcedure ()
+{
+ NS_LOG_FUNCTION (this);
+
+ // 3GPP 36.321 5.1.1
+ NS_ASSERT_MSG (m_rachConfigured, "RACH not configured");
+ m_preambleTransmissionCounter = 0;
+ m_backoffParameter = 0;
+ RandomlySelectAndSendRaPreamble ();
}
void
LteUeMac::DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask)
{
NS_LOG_FUNCTION (this << " rnti" << rnti);
+ NS_ASSERT_MSG (prachMask == 0, "requested PRACH MASK = " << (uint32_t) prachMask << ", but only PRACH MASK = 0 is supported");
m_rnti = rnti;
+ m_raPreambleId = preambleId;
+ bool contention = false;
+ SendRaPreamble (contention);
}
void
LteUeMac::DoAddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu)
{
- NS_LOG_FUNCTION (this << " lcId" << (uint16_t) lcId);
+ NS_LOG_FUNCTION (this << " lcId" << (uint32_t) lcId);
NS_ASSERT_MSG (m_lcInfoMap.find (lcId) == m_lcInfoMap.end (), "cannot add channel because LCID " << lcId << " is already present");
LcInfo lcInfo;
@@ -403,6 +497,7 @@
m_lcInfoMap.erase (it++);
}
}
+ m_rachConfigured = false;
}
void
@@ -450,7 +545,7 @@
itBsr = m_ulBsrReceived.find ((*it).first);
if (((itBsr!=m_ulBsrReceived.end ()) && ((*itBsr).second > 0)))
{
- NS_LOG_LOGIC (this << "\t" << bytesPerActiveLc << " bytes to LC " << (uint16_t)(*it).first << " queue " << (*itBsr).second);
+ NS_LOG_LOGIC (this << "\t" << bytesPerActiveLc << " bytes to LC " << (uint32_t)(*it).first << " queue " << (*itBsr).second);
(*it).second.macSapUser->NotifyTxOpportunity (bytesPerActiveLc, 0);
if ((*itBsr).second >= static_cast<uint64_t> (bytesPerActiveLc))
{
@@ -466,20 +561,24 @@
}
else if (msg->GetMessageType () == LteControlMessage::RAR)
{
- Ptr<RarLteControlMessage> msg2 = DynamicCast<RarLteControlMessage> (msg);
-
- if (msg2->GetPrachId () == m_prachId)
+ if (m_waitingForRaResponse)
{
- 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 ();
+ Ptr<RarLteControlMessage> rarMsg = DynamicCast<RarLteControlMessage> (msg);
+ uint16_t raRnti = rarMsg->GetRaRnti ();
+ NS_LOG_LOGIC (this << "got RAR with RA-RNTI " << (uint32_t) raRnti << ", expecting " << (uint32_t) m_raRnti);
+ if (raRnti == m_raRnti) // RAR corresponds to TX subframe of preamble
+ {
+ for (std::list<RarLteControlMessage::Rar>::const_iterator it = rarMsg->RarListBegin ();
+ it != rarMsg->RarListEnd ();
+ ++it)
+ {
+ if (it->rapId == m_raPreambleId) // RAR is for me
+ {
+ RecvRaResponse (it->rarPayload);
+ }
+ }
+ }
}
- // else the RAR is not for me
}
else
{
@@ -492,6 +591,8 @@
LteUeMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo)
{
NS_LOG_FUNCTION (this);
+ m_frameNo = frameNo;
+ m_subframeNo = subframeNo;
if ((Simulator::Now () >= m_bsrLast + m_bsrPeriodicity) && (m_freshUlBsr==true))
{
SendReportBufferStatus ();
--- a/src/lte/model/lte-ue-mac.h Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-ue-mac.h Tue Nov 20 18:18:01 2012 +0100
@@ -30,7 +30,7 @@
#include <ns3/lte-ue-cmac-sap.h>
#include <ns3/lte-ue-phy-sap.h>
#include <ns3/nstime.h>
-
+#include <ns3/event-id.h>
namespace ns3 {
@@ -78,9 +78,9 @@
void DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters params);
// forwarded from UE CMAC SAP
-
+ void DoConfigureRach (LteUeCmacSapProvider::RachConfig rc);
void DoStartContentionBasedRandomAccessProcedure ();
- void DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t preambleId, uint8_t prachMask);
+ void DoStartNonContentionBasedRandomAccessProcedure (uint16_t rnti, uint8_t rapId, uint8_t prachMask);
void DoAddLc (uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser* msu);
void DoRemoveLc (uint8_t lcId);
void DoReset ();
@@ -89,6 +89,12 @@
void DoReceivePhyPdu (Ptr<Packet> p);
void DoReceiveLteControlMessage (Ptr<LteControlMessage> msg);
+ // internal methods
+ void RandomlySelectAndSendRaPreamble ();
+ void SendRaPreamble (bool contention);
+ void StartWaitingForRaResponse ();
+ void RecvRaResponse (BuildRarListElement_s raResponse);
+ void RaResponseTimeout (bool contention);
void SendReportBufferStatus (void);
private:
@@ -118,8 +124,17 @@
uint16_t m_rnti;
- uint32_t m_prachId;
+ bool m_rachConfigured;
+ LteUeCmacSapProvider::RachConfig m_rachConfig;
+ uint8_t m_raPreambleId;
+ uint8_t m_preambleTransmissionCounter;
+ uint16_t m_backoffParameter;
+ EventId m_noRaResponseReceivedEvent;
+ uint32_t m_frameNo;
+ uint32_t m_subframeNo;
+ uint8_t m_raRnti;
+ bool m_waitingForRaResponse;
};
} // namespace ns3
--- a/src/lte/model/lte-ue-phy.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-ue-phy.cc Tue Nov 20 18:18:01 2012 +0100
@@ -512,13 +512,13 @@
}
void
-LteUePhy::DoSendRachPreamble (uint32_t prachId)
+LteUePhy::DoSendRachPreamble (uint32_t raPreambleId)
{
- NS_LOG_FUNCTION (this << prachId);
+ NS_LOG_FUNCTION (this << raPreambleId);
// unlike other control messages, RACH preamble is sent ASAP
Ptr<RachPreambleLteControlMessage> msg = Create<RachPreambleLteControlMessage> ();
- msg->SetPrachId (prachId);
+ msg->SetRapId (raPreambleId);
m_controlMessagesQueue.at (0).push_back (msg);
}
--- a/src/lte/model/lte-ue-rrc.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/model/lte-ue-rrc.cc Tue Nov 20 18:18:01 2012 +0100
@@ -527,6 +527,11 @@
m_receivedSib2 = true;
m_ulBandwidth = msg.sib2.freqInfo.ulBandwidth;
m_ulEarfcn = msg.sib2.freqInfo.ulCarrierFreq;
+ LteUeCmacSapProvider::RachConfig rc;
+ rc.numberOfRaPreambles = msg.sib2.radioResourceConfigCommon.rachConfigCommon.preambleInfo.numberOfRaPreambles;
+ rc.preambleTransMax = msg.sib2.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.preambleTransMax;
+ rc.raResponseWindowSize = msg.sib2.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.raResponseWindowSize;
+ m_cmacSapProvider->ConfigureRach (rc);
m_cphySapProvider->ConfigureUplink (m_ulEarfcn, m_ulBandwidth);
}
if (m_state == IDLE_WAIT_SYSTEM_INFO && m_receivedMib && m_receivedSib2)
@@ -572,6 +577,7 @@
}
if (msg.haveMobilityControlInfo)
{
+ NS_LOG_INFO ("haveMobilityControlInfo == true");
SwitchToState (CONNECTED_HANDOVER);
const LteRrcSap::MobilityControlInfo& mci = msg.mobilityControlInfo;
m_cellId = mci.targetPhysCellId;
@@ -590,6 +596,7 @@
}
else
{
+ NS_LOG_INFO ("haveMobilityControlInfo == false");
LteRrcSap::RrcConnectionReconfigurationCompleted msg2;
msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier;
m_rrcSapUser->SendRrcConnectionReconfigurationCompleted (msg2);
@@ -717,7 +724,7 @@
dtamIt != rrcd.drbToAddModList.end ();
++dtamIt)
{
- NS_LOG_INFO (this << " IMSI " << m_imsi << " adding/modifying DRBID " << dtamIt->drbIdentity << " LC " << (uint32_t) dtamIt->logicalChannelIdentity);
+ NS_LOG_INFO (this << " IMSI " << m_imsi << " adding/modifying DRBID " << (uint32_t) 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);
--- a/src/lte/test/lte-test-pf-ff-mac-scheduler.cc Wed Nov 14 16:05:54 2012 +0100
+++ b/src/lte/test/lte-test-pf-ff-mac-scheduler.cc Tue Nov 20 18:18:01 2012 +0100
@@ -268,10 +268,10 @@
}
- double statsStartTime = 0.050; // need to allow for RRC connection establishment + SRS
- double statsDuration = 0.4;
+ double statsStartTime = 0.060; // need to allow for RRC connection establishment + SRS
+ double statsDuration = 0.6;
double tolerance = 0.1;
- Simulator::Stop (Seconds (statsStartTime + statsDuration + 0.000001));
+ Simulator::Stop (Seconds (statsStartTime + statsDuration - 0.000001));
lteHelper->EnableMacTraces ();
Simulator::Schedule (Seconds (statsStartTime), &LteHelper::EnableRlcTraces, lteHelper);