fix Bug 1762 - UE stuck in IDLE_CONNECTING because RRC CONN REQ is not transmitted
authorBudiarto Herman <buherman@gmx.com>
Thu, 31 Jul 2014 14:00:06 +0200
changeset 10850 310b021e4598
parent 10849 10f7ccb63b6a
child 10851 674e0a46b808
fix Bug 1762 - UE stuck in IDLE_CONNECTING because RRC CONN REQ is not transmitted
src/lte/doc/source/figures/lte-enb-rrc-states.dot
src/lte/doc/source/figures/lte-ue-rrc-states.dot
src/lte/doc/source/lte-design.rst
src/lte/doc/source/lte-testing.rst
src/lte/model/epc-ue-nas.cc
src/lte/model/lte-enb-rrc.cc
src/lte/model/lte-enb-rrc.h
src/lte/model/lte-ue-mac.cc
src/lte/model/lte-ue-rrc.cc
src/lte/model/lte-ue-rrc.h
src/lte/test/test-lte-rrc.cc
--- a/src/lte/doc/source/figures/lte-enb-rrc-states.dot	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/doc/source/figures/lte-enb-rrc-states.dot	Thu Jul 31 14:00:06 2014 +0200
@@ -17,8 +17,9 @@
 NO_CONTEXT -> INITIAL_RANDOM_ACCESS [label="rx RA\npreamble"]
 INITIAL_RANDOM_ACCESS -> CONNECTION_REJECTED [label="rx RRC CONN REQ,\nAdmit = false"]
 CONNECTION_REJECTED -> CONTEXT_DESTROYED [label="connection\nrejected\ntimeout"]
-INITIAL_RANDOM_ACCESS -> CONTEXT_DESTROYED [label="connection\ntimeout"]
+INITIAL_RANDOM_ACCESS -> CONTEXT_DESTROYED [label="connection\nrequest\ntimeout"]
 INITIAL_RANDOM_ACCESS -> CONNECTION_SETUP [label="rx RRC CONN REQ,\nAdmit = true"]
+CONNECTION_SETUP -> CONTEXT_DESTROYED [label="connection\nsetup\ntimeout"]
 CONNECTION_SETUP -> CONNECTED_NORMALLY [label="rx RRC CONN SETUP\nCOMPLETED"]
 CONNECTED_NORMALLY -> CONNECTION_RECONFIGURATION [label="reconfiguration\ntrigger"]
 CONNECTION_RECONFIGURATION -> CONNECTED_NORMALLY [label="rx RRC CONN RECONF\nCOMPLETED"]
--- a/src/lte/doc/source/figures/lte-ue-rrc-states.dot	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/doc/source/figures/lte-ue-rrc-states.dot	Thu Jul 31 14:00:06 2014 +0200
@@ -29,7 +29,7 @@
 IDLE_RANDOM_ACCESS -> IDLE_CONNECTING [label="random access\nsuccessful"]
 IDLE_RANDOM_ACCESS -> IDLE_CAMPED_NORMALLY [label="random access\nfailure"]
 IDLE_CONNECTING -> CONNECTED_NORMALLY [label="rx RRC CONN SETUP"]
-IDLE_CONNECTING -> IDLE_CAMPED_NORMALLY [label="rx RRC CONN\nREJECT"]
+IDLE_CONNECTING -> IDLE_CAMPED_NORMALLY [label="T300 expiry or\nrx RRC CONN\nREJECT"]
 
 // Handover
 CONNECTED_NORMALLY -> CONNECTED_HANDOVER [label="rx RRC CONN RECONF\nwith MobilityCtrlInfo"]
--- a/src/lte/doc/source/lte-design.rst	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/doc/source/lte-design.rst	Thu Jul 31 14:00:06 2014 +0200
@@ -2755,6 +2755,39 @@
 
    Sequence diagram of the RRC Connection Establishment procedure
 
+There are several timeouts related to this procedure, which are listed in the
+following Table :ref:`tab-rrc-connection_establishment_timer`. If any of these
+timers expired, the RRC connection establishment procedure is terminated in
+failure. In this case, the upper layer (UE NAS) will immediately attempt to
+retry the procedure until it completes successfully.
+
+.. _tab-rrc-connection_establishment_timer:
+
+.. table:: Timers in RRC connection establishment procedure
+
+   +------------+----------+------------+-------------+----------+------------+
+   | Name       | Location | Timer      | Timer       | Default  | When timer |
+   |            |          | starts     | stops       | duration | expired    |
+   +============+==========+============+=============+==========+============+
+   | Connection | eNodeB   | New UE     | Receive RRC | 15 ms    | Remove UE  |
+   | request    | RRC      | context    | CONNECTION  |          | context    |
+   | timeout    |          | added      | REQUEST     |          |            |
+   +------------+----------+------------+-------------+----------+------------+
+   | Connection | UE RRC   | Send RRC   | Receive RRC | 100 ms   | Reset UE   |
+   | timeout    |          | CONNECTION | CONNECTION  |          | MAC        |
+   | (T300      |          | REQUEST    | SETUP or    |          |            |
+   | timer)     |          |            | REJECT      |          |            |
+   +------------+----------+------------+-------------+----------+------------+
+   | Connection | eNodeB   | Send RRC   | Receive RRC | 100 ms   | Remove UE  |
+   | setup      | RRC      | CONNECTION | CONNECTION  |          | context    |
+   | timeout    |          | SETUP      | SETUP       |          |            |
+   |            |          |            | COMPLETE    |          |            |
+   +------------+----------+------------+-------------+----------+------------+
+   | Connection | eNodeB   | Send RRC   | Never       | 30 ms    | Remove UE  |
+   | rejected   | RRC      | CONNECTION |             |          | context    |
+   | timeout    |          | REJECT     |             |          |            |
+   +------------+----------+------------+-------------+----------+------------+
+
 
 
 .. _sec-rrc-connection-reconfiguration:
--- a/src/lte/doc/source/lte-testing.rst	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/doc/source/lte-testing.rst	Thu Jul 31 14:00:06 2014 +0200
@@ -1007,12 +1007,19 @@
  #. RRC Connection Establishment 
  #. RRC Reconfiguration
 
-The test suite considers a type of scenario with a single eNB and multiple UEs that are instructed to connect to the eNB. Each test case implement an instance of this scenario with specific values of the following parameters:
+The test suite considers a type of scenario with four eNBs aligned in a square
+layout with 100-meter edges. Multiple UEs are located at a specific spot on the
+diagonal of the square and are instructed to connect to the first eNB. Each test
+case implements an instance of this scenario with specific values of the
+following parameters:
 
  - number of UEs
  - number of Data Radio Bearers to be activated for each UE
  - time :math:`t^c_0` at which the first UE is instructed to start connecting to the eNB
  - time interval :math:`d^i` between the start of connection of UE :math:`n` and UE :math:`n+1`; the time at which user :math:`n` connects is thus determined as :math:`t^c_n = t^c_0 + n d^i` sdf
+ - the relative position of the UEs on the diagonal of the square, where higher
+   values indicate larger distance from the serving eNodeB, i.e., higher
+   interference from the other eNodeBs
  - a boolean flag indicating whether the ideal or the real RRC protocol model is used
 
 Each test cases passes if a number of test conditions are positively evaluated for each UE after a delay :math:`d^e` from the time it started connecting to the eNB. The delay :math:`d^e` is determined as 
@@ -1031,9 +1038,9 @@
    to allocate the UL grant because of lack of resources. The number
    of collisions depends on the number of UEs that try to access
    simultaneously; we estimated that for a :math:`0.99` RA success
-   probability, 5 attempts are sufficient for up to 20 UEs, and 10
-   attempts for up to 50 UEs. For the UL
-   grant, considered the system bandwidth and the
+   probability, 5 attempts are sufficient for up to 20 UEs, 10 attempts for up
+   to 50 UEs, 20 attempts for up to 100 UEs, and 40 attempts for up to 200 UEs.
+   For the UL grant, considered the system bandwidth and the
    default MCS used for the UL grant (MCS 0), at most 4 UL grants can
    be assigned in a TTI; so for :math:`n` UEs trying to
    do RA simultaneously the max number of attempts due to the UL grant
@@ -1045,7 +1052,10 @@
    SETUP + RRC CONNECTION SETUP COMPLETED. We consider a round trip
    delay of 10ms plus :math:`\lceil 2n/4 \rceil` considering that 2
    RRC packets have to be transmitted and that at most 4 such packets
-   can be transmitted per TTI.
+   can be transmitted per TTI. In cases where interference is high, we
+   accommodate one retry attempt by the UE, so we double the :math:`d^{ce}`
+   value and then add :math:`d^{si}` on top of it (because the timeout has
+   reset the previously received SIB2).
  - :math:`d^{cr}` is the delay required for eventually needed RRC
    CONNECTION RECONFIGURATION transactions. The number of transactions needed is
    1 for each bearer activation. Similarly to what done for
@@ -1056,9 +1066,6 @@
 The conditions that are evaluated for a test case to pass are, for
 each UE:
 
- - the eNB has the context of the UE (identified by the RNTI value
-   retrieved from the UE RRC)
- - the RRC state of the UE at the eNB is CONNECTED_NORMALLY
  - the RRC state at the UE is CONNECTED_NORMALLY
  - the UE is configured with the CellId, DlBandwidth, UlBandwidth,
    DlEarfcn and UlEarfcn of the eNB
@@ -1068,6 +1075,12 @@
  - for each Data Radio Bearer, the following identifiers match between
    the UE and the eNB: EPS bearer id, DRB id, LCID
 
+Ideally, the UE context at the serving eNodeB would have an RRC state of
+CONNECTED_NORMALLY at the end of the procedure. But in the rare case of error
+while transmitting RRC CONNECTION SETUP COMPLETE message, the eNodeB would have
+removed the context because of *connection setup timeout*. A better way to
+handle this error is to make the UE fall back to Idle mode and retry the
+connection, but this behaviour is not yet implemented at the moment.
  
 
 Initial cell selection
--- a/src/lte/model/epc-ue-nas.cc	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/model/epc-ue-nas.cc	Thu Jul 31 14:00:06 2014 +0200
@@ -236,17 +236,13 @@
   SwitchToState (ACTIVE); // will eventually activate dedicated bearers
 }
 
-void 
+void
 EpcUeNas::DoNotifyConnectionFailed ()
 {
   NS_LOG_FUNCTION (this);
 
-  SwitchToState (OFF);
-  /**
-   * \todo Currently not implemented, action by NAS and upper layers after UE
-   *       fails to switch to CONNNECTED mode. Maybe a retry, or just stop here
-   *       and fire a trace to let user know.
-   */
+  // immediately retry the connection
+  Simulator::ScheduleNow (&LteAsSapProvider::Connect, m_asSapProvider);
 }
 
 void
--- a/src/lte/model/lte-enb-rrc.cc	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/model/lte-enb-rrc.cc	Thu Jul 31 14:00:06 2014 +0200
@@ -240,16 +240,16 @@
   switch (m_state)
     {
     case INITIAL_RANDOM_ACCESS:
-      m_connectionTimeout = Simulator::Schedule (m_rrc->m_connectionTimeoutDuration, 
-                                                 &LteEnbRrc::ConnectionTimeout, 
-                                                 m_rrc, m_rnti);
+      m_connectionRequestTimeout = Simulator::Schedule (m_rrc->m_connectionRequestTimeoutDuration,
+                                                        &LteEnbRrc::ConnectionRequestTimeout,
+                                                        m_rrc, m_rnti);
       break;
 
     case HANDOVER_JOINING:
-      m_handoverJoiningTimeout = Simulator::Schedule (m_rrc->m_handoverJoiningTimeoutDuration, 
+      m_handoverJoiningTimeout = Simulator::Schedule (m_rrc->m_handoverJoiningTimeoutDuration,
                                                       &LteEnbRrc::HandoverJoiningTimeout,
                                                       m_rrc, m_rnti);
-      break;      
+      break;
 
     default:
       NS_FATAL_ERROR ("unexpected state " << ToString (m_state));
@@ -771,41 +771,50 @@
   NS_LOG_FUNCTION (this);
   switch (m_state)
     {
-    case INITIAL_RANDOM_ACCESS:      
-      {      
+    case INITIAL_RANDOM_ACCESS:
+      {
+        m_connectionRequestTimeout.Cancel ();
+
         if (m_rrc->m_admitRrcConnectionRequest == true)
           {
-            m_connectionTimeout.Cancel ();
-            m_imsi = msg.ueIdentity;      
+            m_imsi = msg.ueIdentity;
             if (m_rrc->m_s1SapProvider != 0)
               {
                 m_rrc->m_s1SapProvider->InitialUeMessage (m_imsi, m_rnti);
-              }      
+              }
+
+            // send RRC CONNECTION SETUP to UE
             LteRrcSap::RrcConnectionSetup msg2;
             msg2.rrcTransactionIdentifier = GetNewRrcTransactionIdentifier ();
             msg2.radioResourceConfigDedicated = BuildRadioResourceConfigDedicated ();
             m_rrc->m_rrcSapUser->SendRrcConnectionSetup (m_rnti, msg2);
+
             RecordDataRadioBearersToBeStarted ();
+            m_connectionSetupTimeout = Simulator::Schedule (
+                m_rrc->m_connectionSetupTimeoutDuration,
+                &LteEnbRrc::ConnectionSetupTimeout, m_rrc, m_rnti);
             SwitchToState (CONNECTION_SETUP);
           }
         else
           {
-            m_connectionTimeout.Cancel ();
             NS_LOG_INFO ("rejecting connection request for RNTI " << m_rnti);
+
+            // send RRC CONNECTION REJECT to UE
             LteRrcSap::RrcConnectionReject rejectMsg;
             rejectMsg.waitTime = 3;
             m_rrc->m_rrcSapUser->SendRrcConnectionReject (m_rnti, rejectMsg);
-            m_connectionRejectedTimeout = Simulator::Schedule (m_rrc->m_connectionRejectedTimeoutDuration, 
-                                                       &LteEnbRrc::ConnectionRejectedTimeout, 
-                                                       m_rrc, m_rnti);
+
+            m_connectionRejectedTimeout = Simulator::Schedule (
+                m_rrc->m_connectionRejectedTimeoutDuration,
+                &LteEnbRrc::ConnectionRejectedTimeout, m_rrc, m_rnti);
             SwitchToState (CONNECTION_REJECTED);
-          }        
+          }
       }
       break;
-      
+
     default:
       NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
-      break;      
+      break;
     }
 }
 
@@ -816,14 +825,15 @@
   switch (m_state)
     {
     case CONNECTION_SETUP:
+      m_connectionSetupTimeout.Cancel ();
       StartDataRadioBearers ();
       SwitchToState (CONNECTED_NORMALLY);
       m_rrc->m_connectionEstablishedTrace (m_imsi, m_rrc->m_cellId, m_rnti);
       break;
-            
+
     default:
       NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
-      break;      
+      break;
     }
 }
 
@@ -834,9 +844,9 @@
   switch (m_state)
     {
     case CONNECTION_RECONFIGURATION:
-      StartDataRadioBearers ();   
+      StartDataRadioBearers ();
       if (m_needTransmissionModeConfiguration)
-        {          
+        {
           // configure MAC (and scheduler)
           LteEnbCmacSapProvider::UeConfig req;
           req.m_rnti = m_rnti;
@@ -1306,23 +1316,43 @@
                    MakeUintegerChecker<uint32_t> ())
 
     // Timeout related attributes
-    .AddAttribute ("ConnectionTimeoutDuration",
-                   "After a RA attempt, if no RRC Connection Request is received before this time, the UE context is destroyed. Must account for reception of RAR and transmission of RRC CONNECTION REQUEST over UL GRANT.",
+    .AddAttribute ("ConnectionRequestTimeoutDuration",
+                   "After a RA attempt, if no RRC CONNECTION REQUEST is "
+                   "received before this time, the UE context is destroyed. "
+                   "Must account for reception of RAR and transmission of "
+                   "RRC CONNECTION REQUEST over UL GRANT.",
                    TimeValue (MilliSeconds (15)),
-                   MakeTimeAccessor (&LteEnbRrc::m_connectionTimeoutDuration),
+                   MakeTimeAccessor (&LteEnbRrc::m_connectionRequestTimeoutDuration),
+                   MakeTimeChecker ())
+    .AddAttribute ("ConnectionSetupTimeoutDuration",
+                   "After accepting connection request, if no RRC CONNECTION "
+                   "SETUP COMPLETE is received before this time, the UE "
+                   "context is destroyed. Must account for the UE's reception "
+                   "of RRC CONNECTION SETUP and transmission of RRC CONNECTION "
+                   "SETUP COMPLETE.",
+                   TimeValue (MilliSeconds (150)),
+                   MakeTimeAccessor (&LteEnbRrc::m_connectionSetupTimeoutDuration),
                    MakeTimeChecker ())
     .AddAttribute ("ConnectionRejectedTimeoutDuration",
-                   "Time to wait between sending a RRC CONNECTION REJECT and destroying the UE context",
+                   "Time to wait between sending a RRC CONNECTION REJECT and "
+                   "destroying the UE context",
                    TimeValue (MilliSeconds (30)),
                    MakeTimeAccessor (&LteEnbRrc::m_connectionRejectedTimeoutDuration),
                    MakeTimeChecker ())
     .AddAttribute ("HandoverJoiningTimeoutDuration",
-                   "After accepting a handover request, if no RRC Connection Reconfiguration Completed is received before this time, the UE context is destroyed. Must account for reception of X2 HO REQ ACK by source eNB, transmission of the Handover Command, non-contention-based random access and reception of the RRC Connection Reconfiguration Completed message.",
+                   "After accepting a handover request, if no RRC CONNECTION "
+                   "RECONFIGURATION COMPLETE is received before this time, the "
+                   "UE context is destroyed. Must account for reception of "
+                   "X2 HO REQ ACK by source eNB, transmission of the Handover "
+                   "Command, non-contention-based random access and reception "
+                   "of the RRC CONNECTION RECONFIGURATION COMPLETE message.",
                    TimeValue (MilliSeconds (200)),
                    MakeTimeAccessor (&LteEnbRrc::m_handoverJoiningTimeoutDuration),
                    MakeTimeChecker ())
     .AddAttribute ("HandoverLeavingTimeoutDuration",
-                   "After issuing a Handover Command, if neither RRC Connection Reestablishment nor X2 UE Context Release has been previously received, the UE context is destroyed.",
+                   "After issuing a Handover Command, if neither RRC "
+                   "CONNECTION RE-ESTABLISHMENT nor X2 UE Context Release has "
+                   "been previously received, the UE context is destroyed.",
                    TimeValue (MilliSeconds (500)),
                    MakeTimeAccessor (&LteEnbRrc::m_handoverLeavingTimeoutDuration),
                    MakeTimeChecker ())
@@ -1498,6 +1528,14 @@
   return m_cphySapUser;
 }
 
+bool
+LteEnbRrc::HasUeManager (uint16_t rnti) const
+{
+  NS_LOG_FUNCTION (this << (uint32_t) rnti);
+  std::map<uint16_t, Ptr<UeManager> >::const_iterator it = m_ueMap.find (rnti);
+  return (it != m_ueMap.end ());
+}
+
 Ptr<UeManager>
 LteEnbRrc::GetUeManager (uint16_t rnti)
 {
@@ -1694,11 +1732,20 @@
 }
 
 void
-LteEnbRrc::ConnectionTimeout (uint16_t rnti)
+LteEnbRrc::ConnectionRequestTimeout (uint16_t rnti)
 {
   NS_LOG_FUNCTION (this << rnti);
-  NS_ASSERT_MSG (GetUeManager (rnti)->GetState () == UeManager::INITIAL_RANDOM_ACCESS, 
-                 "ConnectionTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
+  NS_ASSERT_MSG (GetUeManager (rnti)->GetState () == UeManager::INITIAL_RANDOM_ACCESS,
+                 "ConnectionRequestTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
+  RemoveUe (rnti);
+}
+
+void
+LteEnbRrc::ConnectionSetupTimeout (uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << rnti);
+  NS_ASSERT_MSG (GetUeManager (rnti)->GetState () == UeManager::CONNECTION_SETUP,
+                 "ConnectionSetupTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
   RemoveUe (rnti);
 }
 
@@ -1707,7 +1754,7 @@
 {
   NS_LOG_FUNCTION (this << rnti);
   NS_ASSERT_MSG (GetUeManager (rnti)->GetState () == UeManager::CONNECTION_REJECTED,
-                 "ConnectionTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
+                 "ConnectionRejectedTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
   RemoveUe (rnti);
 }
 
@@ -1715,7 +1762,7 @@
 LteEnbRrc::HandoverJoiningTimeout (uint16_t rnti)
 {
   NS_LOG_FUNCTION (this << rnti);
-  NS_ASSERT_MSG (GetUeManager (rnti)->GetState () == UeManager::HANDOVER_JOINING, 
+  NS_ASSERT_MSG (GetUeManager (rnti)->GetState () == UeManager::HANDOVER_JOINING,
                  "HandoverJoiningTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
   RemoveUe (rnti);
 }
@@ -1724,7 +1771,7 @@
 LteEnbRrc::HandoverLeavingTimeout (uint16_t rnti)
 {
   NS_LOG_FUNCTION (this << rnti);
-  NS_ASSERT_MSG (GetUeManager (rnti)->GetState () == UeManager::HANDOVER_LEAVING, 
+  NS_ASSERT_MSG (GetUeManager (rnti)->GetState () == UeManager::HANDOVER_LEAVING,
                  "HandoverLeavingTimeout in unexpected state " << ToString (GetUeManager (rnti)->GetState ()));
   RemoveUe (rnti);
 }
--- a/src/lte/model/lte-enb-rrc.h	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/model/lte-enb-rrc.h	Thu Jul 31 14:00:06 2014 +0200
@@ -410,7 +410,8 @@
   std::list<uint8_t> m_drbsToBeStarted;
   bool m_needTransmissionModeConfiguration;
 
-  EventId m_connectionTimeout;
+  EventId m_connectionRequestTimeout;
+  EventId m_connectionSetupTimeout;
   EventId m_connectionRejectedTimeout;
   EventId m_handoverJoiningTimeout;
   EventId m_handoverLeavingTimeout;
@@ -569,6 +570,15 @@
    * 
    * \param rnti the identifier of an UE
    * 
+   * \return true if the corresponding UeManager instance exists
+   */
+  bool HasUeManager (uint16_t rnti) const;
+
+  /**
+   *
+   *
+   * \param rnti the identifier of an UE
+   *
    * \return the corresponding UeManager instance
    */
   Ptr<UeManager> GetUeManager (uint16_t rnti);
@@ -644,14 +654,22 @@
   void SetForwardUpCallback (Callback <void, Ptr<Packet> > cb);
 
   /** 
-   * Method triggered when a UE is expected to get connected but does
+   * Method triggered when a UE is expected to request for connection but does
    * not do so in a reasonable time
    * 
    * \param rnti the T-C-RNTI whose timeout expired
    */
-  void ConnectionTimeout (uint16_t rnti);
+  void ConnectionRequestTimeout (uint16_t rnti);
 
   /** 
+   * Method triggered when a UE is expected to complete a connection setup
+   * procedure but does not do so in a reasonable time
+   *
+   * \param rnti the T-C-RNTI whose timeout expired
+   */
+  void ConnectionSetupTimeout (uint16_t rnti);
+
+  /**
    * Method triggered a while after sending RRC Connection Rejected
    * 
    * \param rnti the T-C-RNTI whose timeout expired
@@ -950,7 +968,8 @@
   uint8_t m_rsrqFilterCoefficient;
 
   // timeouts
-  Time m_connectionTimeoutDuration;
+  Time m_connectionRequestTimeoutDuration;
+  Time m_connectionSetupTimeoutDuration;
   Time m_connectionRejectedTimeoutDuration;
   Time m_handoverJoiningTimeoutDuration;
   Time m_handoverLeavingTimeoutDuration;
--- a/src/lte/model/lte-ue-mac.cc	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/model/lte-ue-mac.cc	Thu Jul 31 14:00:06 2014 +0200
@@ -527,6 +527,8 @@
           m_lcInfoMap.erase (it++);
         }
     }
+
+  m_noRaResponseReceivedEvent.Cancel ();
   m_rachConfigured = false;
   m_freshUlBsr = false;
   m_ulBsrReceived.clear ();
--- a/src/lte/model/lte-ue-rrc.cc	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/model/lte-ue-rrc.cc	Thu Jul 31 14:00:06 2014 +0200
@@ -189,6 +189,12 @@
                    UintegerValue (0), // unused, read-only attribute
                    MakeUintegerAccessor (&LteUeRrc::GetRnti),
                    MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("T300",
+                   "Timer for the RRC Connection Establishment procedure "
+                   "(i.e., the procedure is deemed as failed if it takes longer than this)",
+                   TimeValue (MilliSeconds (100)),
+                   MakeTimeAccessor (&LteUeRrc::m_t300),
+                   MakeTimeChecker ())
     .AddTraceSource ("MibReceived",
                      "trace fired upon reception of Master Information Block",
                      MakeTraceSourceAccessor (&LteUeRrc::m_mibReceivedTrace))
@@ -216,6 +222,9 @@
     .AddTraceSource ("ConnectionEstablished",
                      "trace fired upon successful RRC connection establishment",
                      MakeTraceSourceAccessor (&LteUeRrc::m_connectionEstablishedTrace))
+    .AddTraceSource ("ConnectionTimeout",
+                     "trace fired upon timeout RRC connection establishment because of T300",
+                     MakeTraceSourceAccessor (&LteUeRrc::m_connectionTimeoutTrace))
     .AddTraceSource ("ConnectionReconfiguration",
                      "trace fired upon RRC connection reconfiguration",
                      MakeTraceSourceAccessor (&LteUeRrc::m_connectionReconfigurationTrace))
@@ -487,6 +496,9 @@
         LteRrcSap::RrcConnectionRequest msg;
         msg.ueIdentity = m_imsi;
         m_rrcSapUser->SendRrcConnectionRequest (msg); 
+        m_connectionTimeout = Simulator::Schedule (m_t300,
+                                                   &LteUeRrc::ConnectionTimeout,
+                                                   this);
       }
       break;
 
@@ -821,6 +833,7 @@
     case IDLE_CONNECTING:
       {
         ApplyRadioResourceConfigDedicated (msg.radioResourceConfigDedicated);
+        m_connectionTimeout.Cancel ();
         SwitchToState (CONNECTED_NORMALLY);
         LteRrcSap::RrcConnectionSetupCompleted msg2;
         msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier;
@@ -964,8 +977,12 @@
 LteUeRrc::DoRecvRrcConnectionReject (LteRrcSap::RrcConnectionReject msg)
 {
   NS_LOG_FUNCTION (this);
-  m_cmacSapProvider->Reset ();
+  m_connectionTimeout.Cancel ();
+
+  m_cmacSapProvider->Reset ();       // reset the MAC
+  m_hasReceivedSib2 = false;         // invalidate the previously received SIB2
   SwitchToState (IDLE_CAMPED_NORMALLY);
+  m_asSapUser->NotifyConnectionFailed ();  // inform upper layer
 }
 
 
@@ -2728,6 +2745,17 @@
 }
 
 void
+LteUeRrc::ConnectionTimeout ()
+{
+  NS_LOG_FUNCTION (this << m_imsi);
+  m_cmacSapProvider->Reset ();       // reset the MAC
+  m_hasReceivedSib2 = false;         // invalidate the previously received SIB2
+  SwitchToState (IDLE_CAMPED_NORMALLY);
+  m_connectionTimeoutTrace (m_imsi, m_cellId, m_rnti);
+  m_asSapUser->NotifyConnectionFailed ();  // inform upper layer
+}
+
+void
 LteUeRrc::DisposeOldSrb1 ()
 {
   NS_LOG_FUNCTION (this);
--- a/src/lte/model/lte-ue-rrc.h	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/model/lte-ue-rrc.h	Thu Jul 31 14:00:06 2014 +0200
@@ -526,6 +526,8 @@
   //             imsi      cellId    rnti
   TracedCallback<uint64_t, uint16_t, uint16_t> m_connectionEstablishedTrace;
   //             imsi      cellId    rnti
+  TracedCallback<uint64_t, uint16_t, uint16_t> m_connectionTimeoutTrace;
+  //             imsi      cellId    rnti
   TracedCallback<uint64_t, uint16_t, uint16_t> m_connectionReconfigurationTrace;
   //             imsi      cellId    rnti      targetCellId
   TracedCallback<uint64_t, uint16_t, uint16_t, uint16_t> m_handoverStartTrace;
@@ -796,6 +798,25 @@
    */
   void CancelLeavingTrigger (uint8_t measId, uint16_t cellId);
 
+  /**
+   * \brief Timer for RRC connection establishment procedure.
+   *
+   * Section 7.3 of 3GPP TS 36.331.
+   */
+  Time m_t300;
+
+  /**
+   * \brief Invokes ConnectionEstablishmentTimeout() if RRC connection
+   *        establishment procedure for this UE takes longer than T300.
+   */
+  EventId m_connectionTimeout;
+
+  /**
+   * \brief Invoked after timer T300 expires, notifying upper layers that RRC
+   *        connection establishment procedure has failed.
+   */
+  void ConnectionTimeout ();
+
 }; // end of class LteUeRrc
 
 
--- a/src/lte/test/test-lte-rrc.cc	Sun Jul 27 23:02:38 2014 +0200
+++ b/src/lte/test/test-lte-rrc.cc	Thu Jul 31 14:00:06 2014 +0200
@@ -16,6 +16,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Nicola Baldo <nbaldo@cttc.es>
+ *         Budiarto Herman <budiarto.herman@magister.fi>
  */
 
 
@@ -36,35 +37,70 @@
    *
    * 
    * \param nUes number of UEs in the test
-   * \param tc connection time base value for all UEs in ms
+   * \param nBearers number of bearers to be setup in each connection
+   * \param tConnBase 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
-   *
+   * \param errorExpected if true, test case will wait a bit longer to accomodate for transmission error
+   * \param useIdealRrc If set to false, real RRC protocol model will be used
+   * \param admitRrcConnectionRequest If set to false, eNb will not allow UE connections
+   * \param description additional description of the test case
    */
-  LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart, bool useIdealRrc, bool admitRrcConnectionRequest);
+  LteRrcConnectionEstablishmentTestCase (uint32_t nUes,
+                                         uint32_t nBearers,
+                                         uint32_t tConnBase,
+                                         uint32_t tConnIncrPerUe,
+                                         uint32_t delayDiscStart,
+                                         bool errorExpected,
+                                         bool useIdealRrc,
+                                         bool admitRrcConnectionRequest,
+                                         std::string description = "");
+
+protected:
+  virtual void DoRun (void);
+  virtual void SetupNodes (NodeContainer &enbNodes, NodeContainer &ueNodes);
+  uint32_t m_nUes; // number of UEs in the test
 
 private:
-  static std::string BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tc, uint32_t tConnIncrPerUe, uint32_t delayDiscStart, bool useIdealRrc, bool admitRrcConnectionRequest);
-  virtual void DoRun (void);
+  static std::string BuildNameString (uint32_t nUes,
+                                      uint32_t nBearers,
+                                      uint32_t tConnBase,
+                                      uint32_t tConnIncrPerUe,
+                                      uint32_t delayDiscStart,
+                                      bool useIdealRrc,
+                                      bool admitRrcConnectionRequest,
+                                      std::string description = "");
   void Connect (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
   void CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice);
-
+  void ConnectionEstablishedCallback (std::string context, uint64_t imsi,
+                                      uint16_t cellId, uint16_t rnti);
+  void ConnectionTimeoutCallback (std::string context, uint64_t imsi,
+                                  uint16_t cellId, uint16_t rnti);
 
-  uint32_t m_nUes; // number of UEs in the test
-  uint32_t m_nBearers; // number of UEs in the test
+  uint32_t m_nBearers; // number of bearers to be setup in each connection
   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
-  bool     m_useIdealRrc;
-  bool    m_admitRrcConnectionRequest; // If set to false, eNb will not allow ue connections
+  bool     m_useIdealRrc; // If set to false, real RRC protocol model will be used
+  bool     m_admitRrcConnectionRequest; // If set to false, eNb will not allow UE connections
   Ptr<LteHelper> m_lteHelper;
 
+  // key: IMSI
+  std::map<uint64_t, bool> m_isConnectionEstablished;
 };
 
 
-std::string LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart, bool useIdealRrc, bool admitRrcConnectionRequest)
+std::string
+LteRrcConnectionEstablishmentTestCase::BuildNameString (uint32_t nUes,
+                                                        uint32_t nBearers,
+                                                        uint32_t tConnBase,
+                                                        uint32_t tConnIncrPerUe,
+                                                        uint32_t delayDiscStart,
+                                                        bool useIdealRrc,
+                                                        bool admitRrcConnectionRequest,
+                                                        std::string description)
 {
   std::ostringstream oss;
   oss << "nUes=" << nUes
@@ -72,6 +108,7 @@
       << ", tConnBase=" << tConnBase
       << ", tConnIncrPerUe=" << tConnIncrPerUe
       << ", delayDiscStart=" << delayDiscStart;
+
   if (useIdealRrc)
     {
       oss << ", ideal RRC";
@@ -80,6 +117,7 @@
     {
       oss << ", real RRC";
     }
+
   if (admitRrcConnectionRequest)
     {
       oss << ", admitRrcConnectionRequest = true";
@@ -88,11 +126,24 @@
     {
       oss << ", admitRrcConnectionRequest = false";
     }
+
+  if (!description.empty ())
+    {
+      oss << ", " << description;
+    }
+
   return oss.str ();
 }
 
-LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (uint32_t nUes, uint32_t nBearers, uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart, bool useIdealRrc, bool admitRrcConnectionRequest)
-  : TestCase (BuildNameString (nUes, nBearers, tConnBase, tConnIncrPerUe, delayDiscStart, useIdealRrc, admitRrcConnectionRequest)),
+LteRrcConnectionEstablishmentTestCase::LteRrcConnectionEstablishmentTestCase (
+    uint32_t nUes, uint32_t nBearers,
+    uint32_t tConnBase, uint32_t tConnIncrPerUe, uint32_t delayDiscStart,
+    bool errorExpected, bool useIdealRrc, bool admitRrcConnectionRequest,
+    std::string description)
+  : TestCase (BuildNameString (nUes, nBearers,
+                               tConnBase, tConnIncrPerUe, delayDiscStart,
+                               useIdealRrc, admitRrcConnectionRequest,
+                               description)),
     m_nUes (nUes),
     m_nBearers (nBearers),
     m_tConnBase (tConnBase),
@@ -103,6 +154,8 @@
     m_useIdealRrc (useIdealRrc),
     m_admitRrcConnectionRequest (admitRrcConnectionRequest)
 {
+  NS_LOG_FUNCTION (this << GetName ());
+
   // see the description of d^e in the LTE testing docs
   double dsi = 90;
   double nRaAttempts = 0;
@@ -115,9 +168,18 @@
       NS_ASSERT (nUes <= 50);
       nRaAttempts += 10;
     }
+
   nRaAttempts += std::ceil (nUes / 4.0);
   double dra = nRaAttempts * 7;
   double dce = 10.0 + (2.0 * nUes) / 4.0;
+  if (errorExpected)
+    {
+      /*
+       * If transmission error happens, the UE has to repeat again from
+       * acquiring system information.
+       */
+      dce += dsi + dce;
+    }
   double nCrs;
   if (nUes <= 2)
     {
@@ -142,7 +204,7 @@
   double dcr =  (10.0 + (2.0 * nUes) / 4.0) * (m_nBearers + nCrs);
 
   m_delayConnEnd = round (dsi + dra + dce + dcr);
-  NS_LOG_LOGIC (this << GetName () << " dsi=" << dsi << " dra=" << dra << " dce=" << dce << " dcr=" << dcr << " m_delayConnEnd=" << m_delayConnEnd);
+  NS_LOG_LOGIC (this << " " << GetName () << " dsi=" << dsi << " dra=" << dra << " dce=" << dce << " dcr=" << dcr << " m_delayConnEnd=" << m_delayConnEnd);
 }
 
 void
@@ -173,21 +235,18 @@
   m_lteHelper->SetAttribute ("UseIdealRrc", BooleanValue (m_useIdealRrc));
 
   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);
+  SetupNodes (enbNodes, ueNodes);
 
+  int64_t stream = 1;
   NetDeviceContainer enbDevs;
   enbDevs = m_lteHelper->InstallEnbDevice (enbNodes);
+  stream += m_lteHelper->AssignStreams (enbDevs, stream);
 
   NetDeviceContainer ueDevs;
   ueDevs = m_lteHelper->InstallUeDevice (ueNodes);
+  stream += m_lteHelper->AssignStreams (ueDevs, stream);
 
   // custom code used for testing purposes
   // instead of lteHelper->Attach () and lteHelper->ActivateXxx
@@ -198,7 +257,8 @@
        ++it)
     {
       Ptr<LteEnbRrc> enbRrc = (*it)->GetObject<LteEnbNetDevice> ()->GetRrc ();
-      enbRrc->SetAttribute ("AdmitRrcConnectionRequest", BooleanValue (m_admitRrcConnectionRequest));
+      enbRrc->SetAttribute ("AdmitRrcConnectionRequest",
+                            BooleanValue (m_admitRrcConnectionRequest));
     }
 
 
@@ -225,9 +285,19 @@
 
       // disconnection not supported yet
 
+      uint64_t imsi = ueLteDevice->GetImsi ();
+      m_isConnectionEstablished[imsi] = false;
+
       ++i;
     }
 
+  // Connect to trace sources in UEs
+  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionEstablished",
+                   MakeCallback (&LteRrcConnectionEstablishmentTestCase::ConnectionEstablishedCallback,
+                                 this));
+  Config::Connect ("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionTimeout",
+                   MakeCallback (&LteRrcConnectionEstablishmentTestCase::ConnectionTimeoutCallback,
+                                 this));
 
   Simulator::Stop (MilliSeconds (tmax + 1));
 
@@ -238,8 +308,25 @@
 }
 
 void
+LteRrcConnectionEstablishmentTestCase::SetupNodes (NodeContainer &enbNodes,
+                                                   NodeContainer &ueNodes)
+{
+  NS_LOG_FUNCTION (this);
+
+  enbNodes.Create (1);
+  ueNodes.Create (m_nUes);
+
+  // the following positions all nodes at (0, 0, 0)
+  MobilityHelper mobility;
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (enbNodes);
+  mobility.Install (ueNodes);
+}
+
+void
 LteRrcConnectionEstablishmentTestCase::Connect (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
 {
+  NS_LOG_FUNCTION (this);
   m_lteHelper->Attach (ueDevice, enbDevice);
 
   for (uint32_t b = 0; b < m_nBearers; ++b)
@@ -249,32 +336,66 @@
       m_lteHelper->ActivateDataRadioBearer (ueDevice, bearer);
     }
 }
+
 void
 LteRrcConnectionEstablishmentTestCase::CheckConnected (Ptr<NetDevice> ueDevice, Ptr<NetDevice> enbDevice)
 {
   Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice> ();
   Ptr<LteUeRrc> ueRrc = ueLteDevice->GetRrc ();
+  const uint64_t imsi = ueLteDevice->GetImsi ();
+  const uint16_t rnti = ueRrc->GetRnti ();
+  NS_LOG_FUNCTION (this << imsi << rnti);
+  NS_ASSERT_MSG (m_isConnectionEstablished.find (imsi) != m_isConnectionEstablished.end (),
+                 "Invalid IMSI " << imsi);
 
   if (!m_admitRrcConnectionRequest)
     {
-      NS_TEST_ASSERT_MSG_EQ (ueRrc->GetState (), LteUeRrc::IDLE_CAMPED_NORMALLY, "Wrong LteUeRrc state!");
+      NS_TEST_ASSERT_MSG_EQ (m_isConnectionEstablished[imsi], false,
+                             "Connection with RNTI " << rnti << " should have been rejected");
       return;
     }
 
-  NS_TEST_ASSERT_MSG_EQ (ueRrc->GetState (), LteUeRrc::CONNECTED_NORMALLY, "Wrong LteUeRrc state!");
+  /*
+   * Verifying UE state in UE RRC. Try to increase the test case duration if
+   * the following checks.
+   */
+  NS_TEST_ASSERT_MSG_EQ (m_isConnectionEstablished[imsi], true,
+                         "RNTI " << rnti << " fails to establish connection");
+  NS_TEST_ASSERT_MSG_EQ (ueRrc->GetState (), LteUeRrc::CONNECTED_NORMALLY,
+                         "RNTI " << rnti << " is not at CONNECTED_NORMALLY state");
+
+  // Verifying UE context state in eNodeB RRC.
 
   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");
+  const bool hasContext = enbRrc->HasUeManager (rnti);
 
-  NS_TEST_ASSERT_MSG_EQ (ueManager->GetState (), UeManager::CONNECTED_NORMALLY, "Wrong UeManager state!");
+  if (hasContext)
+    {
+      Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
+      NS_ASSERT (ueManager != 0);
+      NS_TEST_ASSERT_MSG_EQ (ueManager->GetState (),
+                             UeManager::CONNECTED_NORMALLY,
+                             "The context of RNTI " << rnti << " is in invalid state");
+    }
+  else
+    {
+       NS_LOG_WARN (this << " RNTI " << rnti << " thinks that it has"
+                         << " established connection but the eNodeB thinks"
+                         << " that the UE has failed on connection setup.");
+       /*
+        * The standard specifies that this case would exceed the maximum
+        * retransmission limit at UE RLC (SRB1), which will then trigger an RLF.
+        * However, this behaviour is not implemented yet.
+        */
+    }
+
+  // Verifying other attributes on both sides.
 
   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 ();
@@ -284,46 +405,155 @@
   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");
 
-  ObjectMapValue enbDataRadioBearerMapValue;
-  ueManager->GetAttribute ("DataRadioBearerMap", enbDataRadioBearerMapValue);
-  NS_TEST_ASSERT_MSG_EQ (enbDataRadioBearerMapValue.GetN (), m_nBearers, "wrong num bearers at eNB");
-
-  ObjectMapValue ueDataRadioBearerMapValue;
-  ueRrc->GetAttribute ("DataRadioBearerMap", ueDataRadioBearerMapValue);
-  NS_TEST_ASSERT_MSG_EQ (ueDataRadioBearerMapValue.GetN (), m_nBearers, "wrong num bearers at UE");
-
-  ObjectMapValue::Iterator enbBearerIt = enbDataRadioBearerMapValue.Begin ();
-  ObjectMapValue::Iterator ueBearerIt = ueDataRadioBearerMapValue.Begin ();
-  while (enbBearerIt != enbDataRadioBearerMapValue.End ()
-         && ueBearerIt != ueDataRadioBearerMapValue.End ())
+  if (hasContext)
     {
-      Ptr<LteDataRadioBearerInfo> enbDrbInfo = enbBearerIt->second->GetObject<LteDataRadioBearerInfo> ();
-      Ptr<LteDataRadioBearerInfo> ueDrbInfo = ueBearerIt->second->GetObject<LteDataRadioBearerInfo> ();
-      //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_epsBearer, ueDrbInfo->m_epsBearer, "epsBearer differs");
-      NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_epsBearerIdentity, (uint32_t) ueDrbInfo->m_epsBearerIdentity, "epsBearerIdentity differs");
-      NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_drbIdentity, (uint32_t) ueDrbInfo->m_drbIdentity, "drbIdentity differs");
-      //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_rlcConfig, ueDrbInfo->m_rlcConfig, "rlcConfig differs");
-      NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_logicalChannelIdentity, (uint32_t) ueDrbInfo->m_logicalChannelIdentity, "logicalChannelIdentity differs");
-      //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_logicalChannelConfig, ueDrbInfo->m_logicalChannelConfig, "logicalChannelConfig differs");
+      Ptr<UeManager> ueManager = enbRrc->GetUeManager (rnti);
+      NS_ASSERT (ueManager != 0);
+      UeManager::State state = ueManager->GetState ();
+      uint16_t enbImsi = ueManager->GetImsi ();
+      NS_TEST_ASSERT_MSG_EQ (ueImsi, enbImsi, "inconsistent Imsi");
+
+      if (state == UeManager::CONNECTED_NORMALLY)
+        {
+          ObjectMapValue enbDataRadioBearerMapValue;
+          ueManager->GetAttribute ("DataRadioBearerMap", enbDataRadioBearerMapValue);
+          NS_TEST_ASSERT_MSG_EQ (enbDataRadioBearerMapValue.GetN (), m_nBearers, "wrong num bearers at eNB");
+          ObjectMapValue ueDataRadioBearerMapValue;
+          ueRrc->GetAttribute ("DataRadioBearerMap", ueDataRadioBearerMapValue);
+          NS_TEST_ASSERT_MSG_EQ (ueDataRadioBearerMapValue.GetN (), m_nBearers, "wrong num bearers at UE");
 
-      ++enbBearerIt;
-      ++ueBearerIt;
+          ObjectMapValue::Iterator enbBearerIt = enbDataRadioBearerMapValue.Begin ();
+          ObjectMapValue::Iterator ueBearerIt = ueDataRadioBearerMapValue.Begin ();
+          while (enbBearerIt != enbDataRadioBearerMapValue.End ()
+                 && ueBearerIt != ueDataRadioBearerMapValue.End ())
+            {
+              Ptr<LteDataRadioBearerInfo> enbDrbInfo = enbBearerIt->second->GetObject<LteDataRadioBearerInfo> ();
+              Ptr<LteDataRadioBearerInfo> ueDrbInfo = ueBearerIt->second->GetObject<LteDataRadioBearerInfo> ();
+              //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_epsBearer, ueDrbInfo->m_epsBearer, "epsBearer differs");
+              NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_epsBearerIdentity, (uint32_t) ueDrbInfo->m_epsBearerIdentity, "epsBearerIdentity differs");
+              NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_drbIdentity, (uint32_t) ueDrbInfo->m_drbIdentity, "drbIdentity differs");
+              //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_rlcConfig, ueDrbInfo->m_rlcConfig, "rlcConfig differs");
+              NS_TEST_ASSERT_MSG_EQ ((uint32_t) enbDrbInfo->m_logicalChannelIdentity, (uint32_t) ueDrbInfo->m_logicalChannelIdentity, "logicalChannelIdentity differs");
+              //NS_TEST_ASSERT_MSG_EQ (enbDrbInfo->m_logicalChannelConfig, ueDrbInfo->m_logicalChannelConfig, "logicalChannelConfig differs");
+
+              ++enbBearerIt;
+              ++ueBearerIt;
+            }
+
+          NS_ASSERT_MSG (enbBearerIt == enbDataRadioBearerMapValue.End (), "too many bearers at eNB");
+          NS_ASSERT_MSG (ueBearerIt == ueDataRadioBearerMapValue.End (), "too many bearers at UE");
+        }
     }
-  NS_ASSERT_MSG (enbBearerIt == enbDataRadioBearerMapValue.End (), "too many bearers at eNB");
-  NS_ASSERT_MSG (ueBearerIt == ueDataRadioBearerMapValue.End (), "too many bearers at UE");
+}
 
+void
+LteRrcConnectionEstablishmentTestCase::ConnectionEstablishedCallback (
+    std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << imsi << cellId);
+  m_isConnectionEstablished[imsi] = true;
+}
+
+
+void
+LteRrcConnectionEstablishmentTestCase::ConnectionTimeoutCallback (
+    std::string context, uint64_t imsi, uint16_t cellId, uint16_t rnti)
+{
+  NS_LOG_FUNCTION (this << imsi << cellId);
 }
 
 
 
+class LteRrcConnectionEstablishmentInterferenceTestCase
+  : public LteRrcConnectionEstablishmentTestCase
+{
+public:
+  /**
+   *
+   *
+   * \param jumpAwayTime the time when all the UEs 'teleport' to a pre-defined
+   *                     high-interference position and stay there for 100 ms
+   * \param description additional description of the test case
+   */
+  LteRrcConnectionEstablishmentInterferenceTestCase (Time jumpAwayTime,
+                                                     std::string description = "");
+protected:
+  virtual void SetupNodes (NodeContainer &enbNodes, NodeContainer &ueNodes);
+
+private:
+  void JumpAway ();
+  void JumpBack ();
+
+  Time m_jumpAwayTime;
+  Ptr<MobilityModel> m_ueMobility;
+};
+
+
+LteRrcConnectionEstablishmentInterferenceTestCase::LteRrcConnectionEstablishmentInterferenceTestCase (
+  Time jumpAwayTime, std::string description)
+  : LteRrcConnectionEstablishmentTestCase (1, 1, 0, 0, 1, true, false, true,
+                                           description),
+    m_jumpAwayTime (jumpAwayTime)
+{
+  NS_LOG_FUNCTION (this << GetName ());
+}
+
+
+void
+LteRrcConnectionEstablishmentInterferenceTestCase::SetupNodes (NodeContainer &enbNodes,
+                                                               NodeContainer &ueNodes)
+{
+  NS_LOG_FUNCTION (this);
+
+  enbNodes.Create (4);
+  ueNodes.Create (1);
+
+  MobilityHelper mobility;
+  mobility.Install (ueNodes); // UE position at (0, 0, 0)
+  m_ueMobility = ueNodes.Get (0)->GetObject<MobilityModel> ();
+
+  Ptr<ListPositionAllocator> enbPosition = CreateObject<ListPositionAllocator> ();
+  enbPosition->Add (Vector (0, 0, 0));
+  enbPosition->Add (Vector (100.0, 0, 0));
+  enbPosition->Add (Vector (0, 100.0, 0));
+  enbPosition->Add (Vector (100.0, 100.0, 0));
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.SetPositionAllocator (enbPosition);
+  mobility.Install (enbNodes);
+
+  Simulator::Schedule (m_jumpAwayTime,
+                       &LteRrcConnectionEstablishmentInterferenceTestCase::JumpAway,
+                       this);
+  Simulator::Schedule (m_jumpAwayTime + MilliSeconds (100),
+                       &LteRrcConnectionEstablishmentInterferenceTestCase::JumpBack,
+                       this);
+}
+
+
+void
+LteRrcConnectionEstablishmentInterferenceTestCase::JumpAway ()
+{
+  NS_LOG_FUNCTION (this);
+  // Position with high interference from other eNodeBs.
+  m_ueMobility->SetPosition (Vector (100.0, 100.0, 0.0));
+}
+
+
+void
+LteRrcConnectionEstablishmentInterferenceTestCase::JumpBack ()
+{
+  NS_LOG_FUNCTION (this);
+  // Position with low interference.
+  m_ueMobility->SetPosition (Vector (0.0, 0.0, 0.0));
+}
+
+
 class LteRrcTestSuite : public TestSuite
 {
 public:
@@ -334,47 +564,64 @@
 LteRrcTestSuite::LteRrcTestSuite ()
   : TestSuite ("lte-rrc", SYSTEM)
 {
+//  LogComponentEnableAll (LOG_PREFIX_ALL);
+//  LogComponentEnable ("LteRrcTest", LOG_LEVEL_ALL);
+//  LogComponentEnable ("LteEnbRrc", LOG_INFO);
+//  LogComponentEnable ("LteUeRrc", LOG_INFO);
+
   NS_LOG_FUNCTION (this);
 
   for (uint32_t useIdealRrc = 0; useIdealRrc <= 1; ++useIdealRrc)
     {
       //         <----- all times in ms ----------------->
-      //                                                     nUes, nBearers, tConnBase, tConnIncrPerUe, delayDiscStart, useIdealRrc, admitRrcConnectionRequest
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        0,         0,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        0,       100,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        1,         0,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        1,       100,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        2,         0,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        2,       100,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        0,        20,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        0,        20,             10,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        0,        20,            100,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        1,        20,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        1,        20,             10,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        1,        20,            100,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        2,        20,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        2,        20,             10,             1, useIdealRrc, true), TestCase::QUICK);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        2,        20,            100,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  3,        0,        20,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  4,        0,        20,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  4,        0,        20,            300,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 20,        0,        10,              1,             1, useIdealRrc, true), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 50,        0,         0,              0,             1, useIdealRrc, true), TestCase::EXTENSIVE);
+
+      //                                                     nUes      tConnBase            delayDiscStart         useIdealRrc
+      //                                                        nBearers       tConnIncrPerUe       errorExpected               admitRrcConnectionRequest
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     0,      0,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     0,    100,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     1,      0,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     1,    100,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     2,      0,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     2,    100,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     0,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     0,     20,          10,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     0,     20,         100,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     1,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     1,     20,          10,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     1,     20,         100,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     2,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     2,     20,          10,           1, false, useIdealRrc, true), TestCase::QUICK);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     2,     20,         100,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  3,     0,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  4,     0,     20,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  4,     0,     20,         300,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 20,     0,     10,           1,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase ( 50,     0,      0,           0,           1, false, useIdealRrc, true), TestCase::EXTENSIVE);
 
-      //Test cases to check admitRrcConnectionRequest=false
-      //                                                     nUes, nBearers, tConnBase, tConnIncrPerUe, delayDiscStart, useIdealRrc, admitRrcConnectionRequest
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        0,         0,              0,             1, useIdealRrc, false), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,        2,       100,              0,             1, useIdealRrc, false), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        0,        20,              0,             1, useIdealRrc, false), TestCase::EXTENSIVE);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,        1,        20,              0,             1, useIdealRrc, false), TestCase::QUICK);
-      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  3,        0,        20,              0,             1, useIdealRrc, false), TestCase::EXTENSIVE);
+      // Test cases to check admitRrcConnectionRequest=false
+      //                                                     nUes      tConnBase            delayDiscStart         useIdealRrc
+      //                                                        nBearers       tConnIncrPerUe       errorExpected               admitRrcConnectionRequest
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     0,      0,           0,           1, false, useIdealRrc, false), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  1,     2,    100,           0,           1, false, useIdealRrc, false), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     0,     20,           0,           1, false, useIdealRrc, false), TestCase::EXTENSIVE);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  2,     1,     20,           0,           1, false, useIdealRrc, false), TestCase::QUICK);
+      AddTestCase (new LteRrcConnectionEstablishmentTestCase (  3,     0,     20,           0,           1, false, useIdealRrc, false), TestCase::EXTENSIVE);
+    }
 
-      //time consuming tests with a lot of UEs
-      // AddTestCase (new LteRrcConnectionEstablishmentTestCase (100,        0,        10,              0,             1, useIdealRrc, true), TestCase::TAKES_FOREVER);
-      // AddTestCase (new LteRrcConnectionEstablishmentTestCase (100,        0,        10,              1,             1, useIdealRrc, true), TestCase::TAKES_FOREVER);
-      // AddTestCase (new LteRrcConnectionEstablishmentTestCase (200,        0,        10,              0,             1, useIdealRrc, true), TestCase::TAKES_FOREVER);
-      // AddTestCase (new LteRrcConnectionEstablishmentTestCase (200,        0,        10,              1,             1, useIdealRrc, true), TestCase::TAKES_FOREVER);
-    }
+  // Test cases with transmission error
+  AddTestCase (new LteRrcConnectionEstablishmentInterferenceTestCase (
+                   Seconds (0.020214),
+                   "failure at RRC Connection Request"),
+               TestCase::QUICK);
+  AddTestCase (new LteRrcConnectionEstablishmentInterferenceTestCase (
+                   Seconds (0.025),
+                   "failure at RRC Connection Setup"),
+               TestCase::QUICK);
+  AddTestCase (new LteRrcConnectionEstablishmentInterferenceTestCase (
+                   Seconds (0.030),
+                   "failure at RRC Connection Setup Complete"),
+               TestCase::QUICK);
+
 }
 
 static LteRrcTestSuite g_lteRrcTestSuiteInstance;