--- 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 ();