1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011, 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4  * Copyright (c) 2018 Fraunhofer ESK : RLF extensions
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Author: Nicola Baldo <nbaldo@cttc.es>
20  *         Budiarto Herman <budiarto.herman@magister.fi>
21  * Modified by:
22  *          Danilo Abrignani <danilo.abrignani@unibo.it> (Carrier Aggregation - GSoC 2015)
23  *          Biljana Bojovic <biljana.bojovic@cttc.es> (Carrier Aggregation)
24  *          Vignesh Babu <ns3-dev@esk.fraunhofer.de> (RLF extensions)
25  */
26 
27 #include "lte-ue-rrc.h"
28 
29 #include <ns3/fatal-error.h>
30 #include <ns3/log.h>
31 #include <ns3/object-map.h>
32 #include <ns3/object-factory.h>
33 #include <ns3/simulator.h>
34 
35 #include <ns3/lte-rlc.h>
36 #include <ns3/lte-rlc-tm.h>
37 #include <ns3/lte-rlc-um.h>
38 #include <ns3/lte-rlc-am.h>
39 #include <ns3/lte-pdcp.h>
40 #include <ns3/lte-radio-bearer-info.h>
41 
42 #include <cmath>
43 
44 namespace ns3 {
45 
46 NS_LOG_COMPONENT_DEFINE ("LteUeRrc");
47 
48 /////////////////////////////
49 // CMAC SAP forwarder
50 /////////////////////////////
51 
52 /// UeMemberLteUeCmacSapUser class
53 class UeMemberLteUeCmacSapUser : public LteUeCmacSapUser
54 {
55 public:
56   /**
57    * Constructor
58    *
59    * \param rrc the RRC class
60    */
61   UeMemberLteUeCmacSapUser (LteUeRrc* rrc);
62 
63   virtual void SetTemporaryCellRnti (uint16_t rnti);
64   virtual void NotifyRandomAccessSuccessful ();
65   virtual void NotifyRandomAccessFailed ();
66 
67 private:
68   LteUeRrc* m_rrc; ///< the RRC class
69 };
70 
UeMemberLteUeCmacSapUser(LteUeRrc * rrc)71 UeMemberLteUeCmacSapUser::UeMemberLteUeCmacSapUser (LteUeRrc* rrc)
72   : m_rrc (rrc)
73 {}
74 
75 void
SetTemporaryCellRnti(uint16_t rnti)76 UeMemberLteUeCmacSapUser::SetTemporaryCellRnti (uint16_t rnti)
77 {
78   m_rrc->DoSetTemporaryCellRnti (rnti);
79 }
80 
81 
82 void
NotifyRandomAccessSuccessful()83 UeMemberLteUeCmacSapUser::NotifyRandomAccessSuccessful ()
84 {
85   m_rrc->DoNotifyRandomAccessSuccessful ();
86 }
87 
88 void
NotifyRandomAccessFailed()89 UeMemberLteUeCmacSapUser::NotifyRandomAccessFailed ()
90 {
91   m_rrc->DoNotifyRandomAccessFailed ();
92 }
93 
94 
95 
96 
97 
98 
99 /// Map each of UE RRC states to its string representation.
100 static const std::string g_ueRrcStateName[LteUeRrc::NUM_STATES] =
101 {
102   "IDLE_START",
103   "IDLE_CELL_SEARCH",
104   "IDLE_WAIT_MIB_SIB1",
105   "IDLE_WAIT_MIB",
106   "IDLE_WAIT_SIB1",
107   "IDLE_CAMPED_NORMALLY",
108   "IDLE_WAIT_SIB2",
109   "IDLE_RANDOM_ACCESS",
110   "IDLE_CONNECTING",
111   "CONNECTED_NORMALLY",
112   "CONNECTED_HANDOVER",
113   "CONNECTED_PHY_PROBLEM",
114   "CONNECTED_REESTABLISHING"
115 };
116 
117 /**
118  * \param s The UE RRC state.
119  * \return The string representation of the given state.
120  */
ToString(LteUeRrc::State s)121 static const std::string & ToString (LteUeRrc::State s)
122 {
123   return g_ueRrcStateName[s];
124 }
125 
126 
127 /////////////////////////////
128 // ue RRC methods
129 /////////////////////////////
130 
131 NS_OBJECT_ENSURE_REGISTERED (LteUeRrc);
132 
133 
LteUeRrc()134 LteUeRrc::LteUeRrc ()
135   : m_cmacSapProvider (0),
136     m_rrcSapUser (0),
137     m_macSapProvider (0),
138     m_asSapUser (0),
139     m_ccmRrcSapProvider (0),
140     m_state (IDLE_START),
141     m_imsi (0),
142     m_rnti (0),
143     m_cellId (0),
144     m_useRlcSm (true),
145     m_connectionPending (false),
146     m_hasReceivedMib (false),
147     m_hasReceivedSib1 (false),
148     m_hasReceivedSib2 (false),
149     m_csgWhiteList (0),
150     m_noOfSyncIndications (0),
151     m_leaveConnectedMode (false),
152     m_previousCellId (0),
153     m_connEstFailCountLimit (0),
154     m_connEstFailCount (0),
155     m_numberOfComponentCarriers (MIN_NO_CC)
156 {
157   NS_LOG_FUNCTION (this);
158   m_cphySapUser.push_back (new MemberLteUeCphySapUser<LteUeRrc> (this));
159   m_cmacSapUser.push_back (new UeMemberLteUeCmacSapUser (this));
160   m_cphySapProvider.push_back (0);
161   m_cmacSapProvider.push_back (0);
162   m_rrcSapProvider = new MemberLteUeRrcSapProvider<LteUeRrc> (this);
163   m_drbPdcpSapUser = new LtePdcpSpecificLtePdcpSapUser<LteUeRrc> (this);
164   m_asSapProvider = new MemberLteAsSapProvider<LteUeRrc> (this);
165   m_ccmRrcSapUser = new MemberLteUeCcmRrcSapUser<LteUeRrc> (this);
166 }
167 
~LteUeRrc()168 LteUeRrc::~LteUeRrc ()
169 {
170   NS_LOG_FUNCTION (this);
171 }
172 
173 void
DoDispose()174 LteUeRrc::DoDispose ()
175 {
176   NS_LOG_FUNCTION (this);
177   for ( uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
178     {
179       delete m_cphySapUser.at (i);
180       delete m_cmacSapUser.at (i);
181     }
182   m_cphySapUser.clear ();
183   m_cmacSapUser.clear ();
184   delete m_rrcSapProvider;
185   delete m_drbPdcpSapUser;
186   delete m_asSapProvider;
187   delete m_ccmRrcSapUser;
188   m_cphySapProvider.erase (m_cphySapProvider.begin (), m_cphySapProvider.end ());
189   m_cphySapProvider.clear ();
190   m_cmacSapProvider.erase (m_cmacSapProvider.begin (), m_cmacSapProvider.end ());
191   m_cmacSapProvider.clear ();
192   m_drbMap.clear ();
193 }
194 
195 TypeId
GetTypeId(void)196 LteUeRrc::GetTypeId (void)
197 {
198   static TypeId tid = TypeId ("ns3::LteUeRrc")
199     .SetParent<Object> ()
200     .SetGroupName ("Lte")
201     .AddConstructor<LteUeRrc> ()
202     .AddAttribute ("DataRadioBearerMap", "List of UE RadioBearerInfo for Data Radio Bearers by LCID.",
203                    ObjectMapValue (),
204                    MakeObjectMapAccessor (&LteUeRrc::m_drbMap),
205                    MakeObjectMapChecker<LteDataRadioBearerInfo> ())
206     .AddAttribute ("Srb0", "SignalingRadioBearerInfo for SRB0",
207                    PointerValue (),
208                    MakePointerAccessor (&LteUeRrc::m_srb0),
209                    MakePointerChecker<LteSignalingRadioBearerInfo> ())
210     .AddAttribute ("Srb1", "SignalingRadioBearerInfo for SRB1",
211                    PointerValue (),
212                    MakePointerAccessor (&LteUeRrc::m_srb1),
213                    MakePointerChecker<LteSignalingRadioBearerInfo> ())
214     .AddAttribute ("CellId",
215                    "Serving cell identifier",
216                    UintegerValue (0), // unused, read-only attribute
217                    MakeUintegerAccessor (&LteUeRrc::GetCellId),
218                    MakeUintegerChecker<uint16_t> ())
219     .AddAttribute ("C-RNTI",
220                    "Cell Radio Network Temporary Identifier",
221                    UintegerValue (0), // unused, read-only attribute
222                    MakeUintegerAccessor (&LteUeRrc::GetRnti),
223                    MakeUintegerChecker<uint16_t> ())
224     .AddAttribute ("T300",
225                    "Timer for the RRC Connection Establishment procedure "
226                    "(i.e., the procedure is deemed as failed if it takes longer than this). "
227                    "Standard values: 100ms, 200ms, 300ms, 400ms, 600ms, 1000ms, 1500ms, 2000ms",
228                    TimeValue (MilliSeconds (100)), //see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
229                    MakeTimeAccessor (&LteUeRrc::m_t300),
230                    MakeTimeChecker (MilliSeconds (100), MilliSeconds (2000)))
231     .AddAttribute ("T310",
232                    "Timer for detecting the Radio link failure "
233                    "(i.e., the radio link is deemed as failed if this timer expires). "
234                    "Standard values: 0ms 50ms, 100ms, 200ms, 500ms, 1000ms, 2000ms",
235                    TimeValue (MilliSeconds (1000)), //see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
236                    MakeTimeAccessor (&LteUeRrc::m_t310),
237                    MakeTimeChecker (MilliSeconds (0), MilliSeconds (2000)))
238     .AddAttribute ("N310",
239                    "This specifies the maximum number of out-of-sync indications. "
240                    "Standard values: 1, 2, 3, 4, 6, 8, 10, 20",
241                    UintegerValue (6), //see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
242                    MakeUintegerAccessor (&LteUeRrc::m_n310),
243                    MakeUintegerChecker<uint8_t> (1, 20))
244     .AddAttribute ("N311",
245                    "This specifies the maximum number of in-sync indications. "
246                    "Standard values: 1, 2, 3, 4, 5, 6, 8, 10",
247                    UintegerValue (2), //see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
248                    MakeUintegerAccessor (&LteUeRrc::m_n311),
249                    MakeUintegerChecker<uint8_t> (1, 10))
250     .AddTraceSource ("MibReceived",
251                      "trace fired upon reception of Master Information Block",
252                      MakeTraceSourceAccessor (&LteUeRrc::m_mibReceivedTrace),
253                      "ns3::LteUeRrc::MibSibHandoverTracedCallback")
254     .AddTraceSource ("Sib1Received",
255                      "trace fired upon reception of System Information Block Type 1",
256                      MakeTraceSourceAccessor (&LteUeRrc::m_sib1ReceivedTrace),
257                      "ns3::LteUeRrc::MibSibHandoverTracedCallback")
258     .AddTraceSource ("Sib2Received",
259                      "trace fired upon reception of System Information Block Type 2",
260                      MakeTraceSourceAccessor (&LteUeRrc::m_sib2ReceivedTrace),
261                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
262     .AddTraceSource ("StateTransition",
263                      "trace fired upon every UE RRC state transition",
264                      MakeTraceSourceAccessor (&LteUeRrc::m_stateTransitionTrace),
265                      "ns3::LteUeRrc::StateTracedCallback")
266     .AddTraceSource ("InitialCellSelectionEndOk",
267                      "trace fired upon successful initial cell selection procedure",
268                      MakeTraceSourceAccessor (&LteUeRrc::m_initialCellSelectionEndOkTrace),
269                      "ns3::LteUeRrc::CellSelectionTracedCallback")
270     .AddTraceSource ("InitialCellSelectionEndError",
271                      "trace fired upon failed initial cell selection procedure",
272                      MakeTraceSourceAccessor (&LteUeRrc::m_initialCellSelectionEndErrorTrace),
273                      "ns3::LteUeRrc::CellSelectionTracedCallback")
274     .AddTraceSource ("RandomAccessSuccessful",
275                      "trace fired upon successful completion of the random access procedure",
276                      MakeTraceSourceAccessor (&LteUeRrc::m_randomAccessSuccessfulTrace),
277                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
278     .AddTraceSource ("RandomAccessError",
279                      "trace fired upon failure of the random access procedure",
280                      MakeTraceSourceAccessor (&LteUeRrc::m_randomAccessErrorTrace),
281                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
282     .AddTraceSource ("ConnectionEstablished",
283                      "trace fired upon successful RRC connection establishment",
284                      MakeTraceSourceAccessor (&LteUeRrc::m_connectionEstablishedTrace),
285                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
286     .AddTraceSource ("ConnectionTimeout",
287                      "trace fired upon timeout RRC connection establishment because of T300",
288                      MakeTraceSourceAccessor (&LteUeRrc::m_connectionTimeoutTrace),
289                      "ns3::LteUeRrc::ImsiCidRntiCountTracedCallback")
290     .AddTraceSource ("ConnectionReconfiguration",
291                      "trace fired upon RRC connection reconfiguration",
292                      MakeTraceSourceAccessor (&LteUeRrc::m_connectionReconfigurationTrace),
293                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
294     .AddTraceSource ("HandoverStart",
295                      "trace fired upon start of a handover procedure",
296                      MakeTraceSourceAccessor (&LteUeRrc::m_handoverStartTrace),
297                      "ns3::LteUeRrc::MibSibHandoverTracedCallback")
298     .AddTraceSource ("HandoverEndOk",
299                      "trace fired upon successful termination of a handover procedure",
300                      MakeTraceSourceAccessor (&LteUeRrc::m_handoverEndOkTrace),
301                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
302     .AddTraceSource ("HandoverEndError",
303                      "trace fired upon failure of a handover procedure",
304                      MakeTraceSourceAccessor (&LteUeRrc::m_handoverEndErrorTrace),
305                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
306     .AddTraceSource ("SCarrierConfigured",
307                      "trace fired after configuring secondary carriers",
308                      MakeTraceSourceAccessor (&LteUeRrc::m_sCarrierConfiguredTrace),
309                      "ns3::LteUeRrc::SCarrierConfiguredTracedCallback")
310     .AddTraceSource ("Srb1Created",
311                      "trace fired after SRB1 is created",
312                      MakeTraceSourceAccessor (&LteUeRrc::m_srb1CreatedTrace),
313                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
314     .AddTraceSource ("DrbCreated",
315                      "trace fired after DRB is created",
316                      MakeTraceSourceAccessor (&LteUeRrc::m_drbCreatedTrace),
317                      "ns3::LteUeRrc::ImsiCidRntiLcIdTracedCallback")
318     .AddTraceSource ("RadioLinkFailure",
319                      "trace fired upon failure of radio link",
320                      MakeTraceSourceAccessor (&LteUeRrc::m_radioLinkFailureTrace),
321                      "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
322     .AddTraceSource ("PhySyncDetection",
323                      "trace fired upon receiving in Sync or out of Sync indications from UE PHY",
324                      MakeTraceSourceAccessor (&LteUeRrc::m_phySyncDetectionTrace),
325                      "ns3::LteUeRrc::PhySyncDetectionTracedCallback")
326   ;
327   return tid;
328 }
329 
330 
331 void
SetLteUeCphySapProvider(LteUeCphySapProvider * s)332 LteUeRrc::SetLteUeCphySapProvider (LteUeCphySapProvider * s)
333 {
334   NS_LOG_FUNCTION (this << s);
335   m_cphySapProvider.at (0) = s;
336 }
337 
338 void
SetLteUeCphySapProvider(LteUeCphySapProvider * s,uint8_t index)339 LteUeRrc::SetLteUeCphySapProvider (LteUeCphySapProvider * s, uint8_t index)
340 {
341   NS_LOG_FUNCTION (this << s);
342   m_cphySapProvider.at (index) = s;
343 }
344 
345 LteUeCphySapUser*
GetLteUeCphySapUser()346 LteUeRrc::GetLteUeCphySapUser ()
347 {
348   NS_LOG_FUNCTION (this);
349   return m_cphySapUser.at (0);
350 }
351 
352 LteUeCphySapUser*
GetLteUeCphySapUser(uint8_t index)353 LteUeRrc::GetLteUeCphySapUser (uint8_t index)
354 {
355   NS_LOG_FUNCTION (this);
356   return m_cphySapUser.at (index);
357 }
358 
359 void
SetLteUeCmacSapProvider(LteUeCmacSapProvider * s)360 LteUeRrc::SetLteUeCmacSapProvider (LteUeCmacSapProvider * s)
361 {
362   NS_LOG_FUNCTION (this << s);
363   m_cmacSapProvider.at (0) = s;
364 }
365 
366 void
SetLteUeCmacSapProvider(LteUeCmacSapProvider * s,uint8_t index)367 LteUeRrc::SetLteUeCmacSapProvider (LteUeCmacSapProvider * s, uint8_t index)
368 {
369   NS_LOG_FUNCTION (this << s);
370   m_cmacSapProvider.at (index) = s;
371 }
372 
373 LteUeCmacSapUser*
GetLteUeCmacSapUser()374 LteUeRrc::GetLteUeCmacSapUser ()
375 {
376   NS_LOG_FUNCTION (this);
377   return m_cmacSapUser.at (0);
378 }
379 
380 LteUeCmacSapUser*
GetLteUeCmacSapUser(uint8_t index)381 LteUeRrc::GetLteUeCmacSapUser (uint8_t index)
382 {
383   NS_LOG_FUNCTION (this);
384   return m_cmacSapUser.at (index);
385 }
386 
387 void
SetLteUeRrcSapUser(LteUeRrcSapUser * s)388 LteUeRrc::SetLteUeRrcSapUser (LteUeRrcSapUser * s)
389 {
390   NS_LOG_FUNCTION (this << s);
391   m_rrcSapUser = s;
392 }
393 
394 LteUeRrcSapProvider*
GetLteUeRrcSapProvider()395 LteUeRrc::GetLteUeRrcSapProvider ()
396 {
397   NS_LOG_FUNCTION (this);
398   return m_rrcSapProvider;
399 }
400 
401 void
SetLteMacSapProvider(LteMacSapProvider * s)402 LteUeRrc::SetLteMacSapProvider (LteMacSapProvider * s)
403 {
404   NS_LOG_FUNCTION (this << s);
405   m_macSapProvider = s;
406 }
407 
408 void
SetLteCcmRrcSapProvider(LteUeCcmRrcSapProvider * s)409 LteUeRrc::SetLteCcmRrcSapProvider (LteUeCcmRrcSapProvider * s)
410 {
411   NS_LOG_FUNCTION (this << s);
412   m_ccmRrcSapProvider = s;
413 }
414 
415 LteUeCcmRrcSapUser*
GetLteCcmRrcSapUser()416 LteUeRrc::GetLteCcmRrcSapUser ()
417 {
418   NS_LOG_FUNCTION (this);
419   return m_ccmRrcSapUser;
420 }
421 
422 void
SetAsSapUser(LteAsSapUser * s)423 LteUeRrc::SetAsSapUser (LteAsSapUser* s)
424 {
425   m_asSapUser = s;
426 }
427 
428 LteAsSapProvider*
GetAsSapProvider()429 LteUeRrc::GetAsSapProvider ()
430 {
431   return m_asSapProvider;
432 }
433 
434 void
SetImsi(uint64_t imsi)435 LteUeRrc::SetImsi (uint64_t imsi)
436 {
437   NS_LOG_FUNCTION (this << imsi);
438   m_imsi = imsi;
439 
440   //Communicate the IMSI to MACs and PHYs for all the component carriers
441   for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
442     {
443       m_cmacSapProvider.at (i)->SetImsi (m_imsi);
444       m_cphySapProvider.at (i)->SetImsi (m_imsi);
445     }
446 }
447 
448 void
StorePreviousCellId(uint16_t cellId)449 LteUeRrc::StorePreviousCellId (uint16_t cellId)
450 {
451   NS_LOG_FUNCTION (this << cellId);
452   m_previousCellId = cellId;
453 }
454 
455 uint64_t
GetImsi(void) const456 LteUeRrc::GetImsi (void) const
457 {
458   return m_imsi;
459 }
460 
461 uint16_t
GetRnti() const462 LteUeRrc::GetRnti () const
463 {
464   NS_LOG_FUNCTION (this);
465   return m_rnti;
466 }
467 
468 uint16_t
GetCellId() const469 LteUeRrc::GetCellId () const
470 {
471   NS_LOG_FUNCTION (this);
472   return m_cellId;
473 }
474 
475 
476 uint8_t
GetUlBandwidth() const477 LteUeRrc::GetUlBandwidth () const
478 {
479   NS_LOG_FUNCTION (this);
480   return m_ulBandwidth;
481 }
482 
483 uint8_t
GetDlBandwidth() const484 LteUeRrc::GetDlBandwidth () const
485 {
486   NS_LOG_FUNCTION (this);
487   return m_dlBandwidth;
488 }
489 
490 uint32_t
GetDlEarfcn() const491 LteUeRrc::GetDlEarfcn () const
492 {
493   return m_dlEarfcn;
494 }
495 
496 uint32_t
GetUlEarfcn() const497 LteUeRrc::GetUlEarfcn () const
498 {
499   NS_LOG_FUNCTION (this);
500   return m_ulEarfcn;
501 }
502 
503 LteUeRrc::State
GetState(void) const504 LteUeRrc::GetState (void) const
505 {
506   NS_LOG_FUNCTION (this);
507   return m_state;
508 }
509 
510 uint16_t
GetPreviousCellId() const511 LteUeRrc::GetPreviousCellId () const
512 {
513   NS_LOG_FUNCTION (this);
514   return m_previousCellId;
515 }
516 
517 void
SetUseRlcSm(bool val)518 LteUeRrc::SetUseRlcSm (bool val)
519 {
520   NS_LOG_FUNCTION (this);
521   m_useRlcSm = val;
522 }
523 
524 
525 void
DoInitialize(void)526 LteUeRrc::DoInitialize (void)
527 {
528   NS_LOG_FUNCTION (this);
529 
530   // setup the UE side of SRB0
531   uint8_t lcid = 0;
532 
533   Ptr<LteRlc> rlc = CreateObject<LteRlcTm> ()->GetObject<LteRlc> ();
534   rlc->SetLteMacSapProvider (m_macSapProvider);
535   rlc->SetRnti (m_rnti);
536   rlc->SetLcId (lcid);
537 
538   m_srb0 = CreateObject<LteSignalingRadioBearerInfo> ();
539   m_srb0->m_rlc = rlc;
540   m_srb0->m_srbIdentity = 0;
541   LteUeRrcSapUser::SetupParameters ueParams;
542   ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider ();
543   ueParams.srb1SapProvider = 0;
544   m_rrcSapUser->Setup (ueParams);
545 
546   // CCCH (LCID 0) is pre-configured, here is the hardcoded configuration:
547   LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
548   lcConfig.priority = 0; // highest priority
549   lcConfig.prioritizedBitRateKbps = 65535; // maximum
550   lcConfig.bucketSizeDurationMs = 65535; // maximum
551   lcConfig.logicalChannelGroup = 0; // all SRBs mapped to LCG 0
552   LteMacSapUser* msu = m_ccmRrcSapProvider->ConfigureSignalBearer (lcid, lcConfig, rlc->GetLteMacSapUser ());
553   m_cmacSapProvider.at (0)->AddLc (lcid, lcConfig, msu);
554 }
555 
556 void
InitializeSap(void)557 LteUeRrc::InitializeSap (void)
558 {
559   if (m_numberOfComponentCarriers < MIN_NO_CC || m_numberOfComponentCarriers > MAX_NO_CC)
560     {
561       // this check is needed in order to maintain backward compatibility with scripts and tests
562       // if case lte-helper is not used (like in several tests) the m_numberOfComponentCarriers
563       // is not set and then an error is raised
564       // In this case m_numberOfComponentCarriers is set to 1
565       m_numberOfComponentCarriers = MIN_NO_CC;
566     }
567   if (m_numberOfComponentCarriers > MIN_NO_CC )
568     {
569       for ( uint16_t i = 1; i < m_numberOfComponentCarriers; i++)
570         {
571           m_cphySapUser.push_back (new MemberLteUeCphySapUser<LteUeRrc> (this));
572           m_cmacSapUser.push_back (new UeMemberLteUeCmacSapUser (this));
573           m_cphySapProvider.push_back (0);
574           m_cmacSapProvider.push_back (0);
575         }
576     }
577 }
578 
579 
580 void
DoSendData(Ptr<Packet> packet,uint8_t bid)581 LteUeRrc::DoSendData (Ptr<Packet> packet, uint8_t bid)
582 {
583   NS_LOG_FUNCTION (this << packet);
584 
585   uint8_t drbid = Bid2Drbid (bid);
586 
587   if (drbid != 0)
588     {
589       std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it =   m_drbMap.find (drbid);
590       NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with drbid == " << drbid);
591 
592       LtePdcpSapProvider::TransmitPdcpSduParameters params;
593       params.pdcpSdu = packet;
594       params.rnti = m_rnti;
595       params.lcid = it->second->m_logicalChannelIdentity;
596 
597       NS_LOG_LOGIC (this << " RNTI=" << m_rnti << " sending packet " << packet
598                          << " on DRBID " << (uint32_t) drbid
599                          << " (LCID " << (uint32_t) params.lcid << ")"
600                          << " (" << packet->GetSize () << " bytes)");
601       it->second->m_pdcp->GetLtePdcpSapProvider ()->TransmitPdcpSdu (params);
602     }
603 }
604 
605 
606 void
DoDisconnect()607 LteUeRrc::DoDisconnect ()
608 {
609   NS_LOG_FUNCTION (this);
610 
611   switch (m_state)
612     {
613       case IDLE_START:
614       case IDLE_CELL_SEARCH:
615       case IDLE_WAIT_MIB_SIB1:
616       case IDLE_WAIT_MIB:
617       case IDLE_WAIT_SIB1:
618       case IDLE_CAMPED_NORMALLY:
619         NS_LOG_INFO ("already disconnected");
620         break;
621 
622       case IDLE_WAIT_SIB2:
623       case IDLE_CONNECTING:
624         NS_FATAL_ERROR ("cannot abort connection setup procedure");
625         break;
626 
627       case CONNECTED_NORMALLY:
628       case CONNECTED_HANDOVER:
629       case CONNECTED_PHY_PROBLEM:
630       case CONNECTED_REESTABLISHING:
631         LeaveConnectedMode ();
632         break;
633 
634       default: // i.e. IDLE_RANDOM_ACCESS
635         NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
636         break;
637     }
638 }
639 
640 void
DoReceivePdcpSdu(LtePdcpSapUser::ReceivePdcpSduParameters params)641 LteUeRrc::DoReceivePdcpSdu (LtePdcpSapUser::ReceivePdcpSduParameters params)
642 {
643   NS_LOG_FUNCTION (this);
644   m_asSapUser->RecvData (params.pdcpSdu);
645 }
646 
647 
648 void
DoSetTemporaryCellRnti(uint16_t rnti)649 LteUeRrc::DoSetTemporaryCellRnti (uint16_t rnti)
650 {
651   NS_LOG_FUNCTION (this << rnti);
652   m_rnti = rnti;
653   m_srb0->m_rlc->SetRnti (m_rnti);
654   m_cphySapProvider.at (0)->SetRnti (m_rnti);
655 }
656 
657 void
DoNotifyRandomAccessSuccessful()658 LteUeRrc::DoNotifyRandomAccessSuccessful ()
659 {
660   NS_LOG_FUNCTION (this << m_imsi << ToString (m_state));
661   m_randomAccessSuccessfulTrace (m_imsi, m_cellId, m_rnti);
662 
663   switch (m_state)
664     {
665       case IDLE_RANDOM_ACCESS:
666         {
667           // we just received a RAR with a T-C-RNTI and an UL grant
668           // send RRC connection request as message 3 of the random access procedure
669           SwitchToState (IDLE_CONNECTING);
670           LteRrcSap::RrcConnectionRequest msg;
671           msg.ueIdentity = m_imsi;
672           m_rrcSapUser->SendRrcConnectionRequest (msg);
673           m_connectionTimeout = Simulator::Schedule (m_t300,
674                                                      &LteUeRrc::ConnectionTimeout,
675                                                      this);
676         }
677         break;
678 
679       case CONNECTED_HANDOVER:
680         {
681           LteRrcSap::RrcConnectionReconfigurationCompleted msg;
682           msg.rrcTransactionIdentifier = m_lastRrcTransactionIdentifier;
683           m_rrcSapUser->SendRrcConnectionReconfigurationCompleted (msg);
684 
685           // 3GPP TS 36.331 section 5.5.6.1 Measurements related actions upon handover
686           std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt;
687           for (measIdIt = m_varMeasConfig.measIdList.begin ();
688                measIdIt != m_varMeasConfig.measIdList.end ();
689                ++measIdIt)
690             {
691               VarMeasReportListClear (measIdIt->second.measId);
692             }
693 
694           SwitchToState (CONNECTED_NORMALLY);
695           m_cmacSapProvider.at (0)->NotifyConnectionSuccessful (); //RA successful during handover
696           m_handoverEndOkTrace (m_imsi, m_cellId, m_rnti);
697         }
698         break;
699 
700       default:
701         NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state));
702         break;
703     }
704 }
705 
706 void
DoNotifyRandomAccessFailed()707 LteUeRrc::DoNotifyRandomAccessFailed ()
708 {
709   NS_LOG_FUNCTION (this << m_imsi << ToString (m_state));
710   m_randomAccessErrorTrace (m_imsi, m_cellId, m_rnti);
711 
712   switch (m_state)
713     {
714       case IDLE_RANDOM_ACCESS:
715         {
716           SwitchToState (IDLE_CAMPED_NORMALLY);
717           m_asSapUser->NotifyConnectionFailed ();
718         }
719         break;
720 
721       case CONNECTED_HANDOVER:
722         {
723           m_handoverEndErrorTrace (m_imsi, m_cellId, m_rnti);
724           /**
725            * \todo After a handover failure because of a random access failure,
726            *       send an RRC Connection Re-establishment and switch to
727            *       CONNECTED_REESTABLISHING state.
728            */
729         }
730         break;
731 
732       default:
733         NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state));
734         break;
735     }
736 }
737 
738 
739 void
DoSetCsgWhiteList(uint32_t csgId)740 LteUeRrc::DoSetCsgWhiteList (uint32_t csgId)
741 {
742   NS_LOG_FUNCTION (this << m_imsi << csgId);
743   m_csgWhiteList = csgId;
744 }
745 
746 void
DoStartCellSelection(uint32_t dlEarfcn)747 LteUeRrc::DoStartCellSelection (uint32_t dlEarfcn)
748 {
749   NS_LOG_FUNCTION (this << m_imsi << dlEarfcn);
750   NS_ASSERT_MSG (m_state == IDLE_START,
751                  "cannot start cell selection from state " << ToString (m_state));
752   m_dlEarfcn = dlEarfcn;
753   m_cphySapProvider.at (0)->StartCellSearch (dlEarfcn);
754   SwitchToState (IDLE_CELL_SEARCH);
755 }
756 
757 void
DoForceCampedOnEnb(uint16_t cellId,uint32_t dlEarfcn)758 LteUeRrc::DoForceCampedOnEnb (uint16_t cellId, uint32_t dlEarfcn)
759 {
760   NS_LOG_FUNCTION (this << m_imsi << cellId << dlEarfcn);
761 
762   switch (m_state)
763     {
764       case IDLE_START:
765         m_cellId = cellId;
766         m_dlEarfcn = dlEarfcn;
767         m_cphySapProvider.at (0)->SynchronizeWithEnb (m_cellId, m_dlEarfcn);
768         SwitchToState (IDLE_WAIT_MIB);
769         break;
770 
771       case IDLE_CELL_SEARCH:
772       case IDLE_WAIT_MIB_SIB1:
773       case IDLE_WAIT_SIB1:
774         NS_FATAL_ERROR ("cannot abort cell selection " << ToString (m_state));
775         break;
776 
777       case IDLE_WAIT_MIB:
778         NS_LOG_INFO ("already forced to camp to cell " << m_cellId);
779         break;
780 
781       case IDLE_CAMPED_NORMALLY:
782       case IDLE_WAIT_SIB2:
783       case IDLE_RANDOM_ACCESS:
784       case IDLE_CONNECTING:
785         NS_LOG_INFO ("already camped to cell " << m_cellId);
786         break;
787 
788       case CONNECTED_NORMALLY:
789       case CONNECTED_HANDOVER:
790       case CONNECTED_PHY_PROBLEM:
791       case CONNECTED_REESTABLISHING:
792         NS_LOG_INFO ("already connected to cell " << m_cellId);
793         break;
794 
795       default:
796         NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state));
797         break;
798     }
799 
800 }
801 
802 void
DoConnect()803 LteUeRrc::DoConnect ()
804 {
805   NS_LOG_FUNCTION (this << m_imsi);
806 
807   switch (m_state)
808     {
809       case IDLE_START:
810       case IDLE_CELL_SEARCH:
811       case IDLE_WAIT_MIB_SIB1:
812       case IDLE_WAIT_SIB1:
813       case IDLE_WAIT_MIB:
814         m_connectionPending = true;
815         break;
816 
817       case IDLE_CAMPED_NORMALLY:
818         m_connectionPending = true;
819         SwitchToState (IDLE_WAIT_SIB2);
820         break;
821 
822       case IDLE_WAIT_SIB2:
823       case IDLE_RANDOM_ACCESS:
824       case IDLE_CONNECTING:
825         NS_LOG_INFO ("already connecting");
826         break;
827 
828       case CONNECTED_NORMALLY:
829       case CONNECTED_REESTABLISHING:
830       case CONNECTED_HANDOVER:
831         NS_LOG_INFO ("already connected");
832         break;
833 
834       default:
835         NS_FATAL_ERROR ("unexpected event in state " << ToString (m_state));
836         break;
837     }
838 }
839 
840 
841 
842 // CPHY SAP methods
843 
844 void
DoRecvMasterInformationBlock(uint16_t cellId,LteRrcSap::MasterInformationBlock msg)845 LteUeRrc::DoRecvMasterInformationBlock (uint16_t cellId,
846                                         LteRrcSap::MasterInformationBlock msg)
847 {
848   m_dlBandwidth = msg.dlBandwidth;
849   m_cphySapProvider.at (0)->SetDlBandwidth (msg.dlBandwidth);
850   m_hasReceivedMib = true;
851   m_mibReceivedTrace (m_imsi, m_cellId, m_rnti, cellId);
852 
853   switch (m_state)
854     {
855       case IDLE_WAIT_MIB:
856         // manual attachment
857         SwitchToState (IDLE_CAMPED_NORMALLY);
858         break;
859 
860       case IDLE_WAIT_MIB_SIB1:
861         // automatic attachment from Idle mode cell selection
862         SwitchToState (IDLE_WAIT_SIB1);
863         break;
864 
865       default:
866         // do nothing extra
867         break;
868     }
869 }
870 
871 void
DoRecvSystemInformationBlockType1(uint16_t cellId,LteRrcSap::SystemInformationBlockType1 msg)872 LteUeRrc::DoRecvSystemInformationBlockType1 (uint16_t cellId,
873                                              LteRrcSap::SystemInformationBlockType1 msg)
874 {
875   NS_LOG_FUNCTION (this);
876   switch (m_state)
877     {
878       case IDLE_WAIT_SIB1:
879         NS_ASSERT_MSG (cellId == msg.cellAccessRelatedInfo.cellIdentity,
880                        "Cell identity in SIB1 does not match with the originating cell");
881         m_hasReceivedSib1 = true;
882         m_lastSib1 = msg;
883         m_sib1ReceivedTrace (m_imsi, m_cellId, m_rnti, cellId);
884         EvaluateCellForSelection ();
885         break;
886 
887       case IDLE_CAMPED_NORMALLY:
888       case IDLE_RANDOM_ACCESS:
889       case IDLE_CONNECTING:
890       case CONNECTED_NORMALLY:
891       case CONNECTED_HANDOVER:
892       case CONNECTED_PHY_PROBLEM:
893       case CONNECTED_REESTABLISHING:
894         NS_ASSERT_MSG (cellId == msg.cellAccessRelatedInfo.cellIdentity,
895                        "Cell identity in SIB1 does not match with the originating cell");
896         m_hasReceivedSib1 = true;
897         m_lastSib1 = msg;
898         m_sib1ReceivedTrace (m_imsi, m_cellId, m_rnti, cellId);
899         break;
900 
901       case IDLE_WAIT_MIB_SIB1:
902         // MIB has not been received, so ignore this SIB1
903         break;
904 
905       default: // e.g. IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_SIB2
906         // do nothing
907         break;
908     }
909 }
910 
911 void
DoReportUeMeasurements(LteUeCphySapUser::UeMeasurementsParameters params)912 LteUeRrc::DoReportUeMeasurements (LteUeCphySapUser::UeMeasurementsParameters params)
913 {
914   NS_LOG_FUNCTION (this);
915 
916   // layer 3 filtering does not apply in IDLE mode
917   bool useLayer3Filtering = (m_state == CONNECTED_NORMALLY);
918   bool triggering = true;
919   std::vector <LteUeCphySapUser::UeMeasurementsElement>::iterator newMeasIt;
920   for (newMeasIt = params.m_ueMeasurementsList.begin ();
921        newMeasIt != params.m_ueMeasurementsList.end (); ++newMeasIt)
922     {
923       if (params.m_componentCarrierId != 0)
924         {
925           triggering = false; // report is triggered only when an event is on the primary carrier
926           // in this case the measurement received is related to secondary carriers
927           // measurements related to secondary carriers are saved on a different portion of memory
928           SaveScellUeMeasurements (newMeasIt->m_cellId, newMeasIt->m_rsrp,
929                                    newMeasIt->m_rsrq, useLayer3Filtering,
930                                    params.m_componentCarrierId );
931         }
932       else
933         {
934           SaveUeMeasurements (newMeasIt->m_cellId, newMeasIt->m_rsrp,
935                               newMeasIt->m_rsrq, useLayer3Filtering);
936         }
937     }
938 
939   if (m_state == IDLE_CELL_SEARCH)
940     {
941       // start decoding BCH
942       SynchronizeToStrongestCell ();
943     }
944   else
945     {
946       if (triggering)
947         {
948           std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt;
949           for (measIdIt = m_varMeasConfig.measIdList.begin ();
950                measIdIt != m_varMeasConfig.measIdList.end (); ++measIdIt)
951             {
952               MeasurementReportTriggering (measIdIt->first);
953             }
954         }
955     }
956 
957 } // end of LteUeRrc::DoReportUeMeasurements
958 
959 
960 
961 // RRC SAP methods
962 
963 void
DoCompleteSetup(LteUeRrcSapProvider::CompleteSetupParameters params)964 LteUeRrc::DoCompleteSetup (LteUeRrcSapProvider::CompleteSetupParameters params)
965 {
966   NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
967   m_srb0->m_rlc->SetLteRlcSapUser (params.srb0SapUser);
968   if (m_srb1)
969     {
970       m_srb1->m_pdcp->SetLtePdcpSapUser (params.srb1SapUser);
971     }
972 }
973 
974 
975 void
DoRecvSystemInformation(LteRrcSap::SystemInformation msg)976 LteUeRrc::DoRecvSystemInformation (LteRrcSap::SystemInformation msg)
977 {
978   NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
979 
980   if (msg.haveSib2)
981     {
982       switch (m_state)
983         {
984           case IDLE_CAMPED_NORMALLY:
985           case IDLE_WAIT_SIB2:
986           case IDLE_RANDOM_ACCESS:
987           case IDLE_CONNECTING:
988           case CONNECTED_NORMALLY:
989           case CONNECTED_HANDOVER:
990           case CONNECTED_PHY_PROBLEM:
991           case CONNECTED_REESTABLISHING:
992             m_hasReceivedSib2 = true;
993             m_ulBandwidth = msg.sib2.freqInfo.ulBandwidth;
994             m_ulEarfcn = msg.sib2.freqInfo.ulCarrierFreq;
995             m_sib2ReceivedTrace (m_imsi, m_cellId, m_rnti);
996             LteUeCmacSapProvider::RachConfig rc;
997             rc.numberOfRaPreambles = msg.sib2.radioResourceConfigCommon.rachConfigCommon.preambleInfo.numberOfRaPreambles;
998             rc.preambleTransMax = msg.sib2.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.preambleTransMax;
999             rc.raResponseWindowSize = msg.sib2.radioResourceConfigCommon.rachConfigCommon.raSupervisionInfo.raResponseWindowSize;
1000             rc.connEstFailCount = msg.sib2.radioResourceConfigCommon.rachConfigCommon.txFailParam.connEstFailCount;
1001             m_connEstFailCountLimit = rc.connEstFailCount;
1002             NS_ASSERT_MSG (m_connEstFailCountLimit > 0 && m_connEstFailCountLimit < 5,
1003                            "SIB2 msg contains wrong value "
1004                            << m_connEstFailCountLimit << "of connEstFailCount");
1005             m_cmacSapProvider.at (0)->ConfigureRach (rc);
1006             m_cphySapProvider.at (0)->ConfigureUplink (m_ulEarfcn, m_ulBandwidth);
1007             m_cphySapProvider.at (0)->ConfigureReferenceSignalPower (msg.sib2.radioResourceConfigCommon.pdschConfigCommon.referenceSignalPower);
1008             if (m_state == IDLE_WAIT_SIB2)
1009               {
1010                 NS_ASSERT (m_connectionPending);
1011                 StartConnection ();
1012               }
1013             break;
1014 
1015           default: // IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_MIB_SIB1, IDLE_WAIT_SIB1
1016             // do nothing
1017             break;
1018         }
1019     }
1020 
1021 }
1022 
1023 
1024 void
DoRecvRrcConnectionSetup(LteRrcSap::RrcConnectionSetup msg)1025 LteUeRrc::DoRecvRrcConnectionSetup (LteRrcSap::RrcConnectionSetup msg)
1026 {
1027   NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
1028   switch (m_state)
1029     {
1030       case IDLE_CONNECTING:
1031         {
1032           ApplyRadioResourceConfigDedicated (msg.radioResourceConfigDedicated);
1033           m_connEstFailCount = 0;
1034           m_connectionTimeout.Cancel ();
1035           SwitchToState (CONNECTED_NORMALLY);
1036           m_leaveConnectedMode = false;
1037           LteRrcSap::RrcConnectionSetupCompleted msg2;
1038           msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier;
1039           m_rrcSapUser->SendRrcConnectionSetupCompleted (msg2);
1040           m_asSapUser->NotifyConnectionSuccessful ();
1041           m_cmacSapProvider.at (0)->NotifyConnectionSuccessful ();
1042           m_connectionEstablishedTrace (m_imsi, m_cellId, m_rnti);
1043           NS_ABORT_MSG_IF (m_noOfSyncIndications > 0, "Sync indications should be zero "
1044                            "when a new RRC connection is established. Current value = " << (uint16_t) m_noOfSyncIndications);
1045         }
1046         break;
1047 
1048       default:
1049         NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
1050         break;
1051     }
1052 }
1053 
1054 void
DoRecvRrcConnectionReconfiguration(LteRrcSap::RrcConnectionReconfiguration msg)1055 LteUeRrc::DoRecvRrcConnectionReconfiguration (LteRrcSap::RrcConnectionReconfiguration msg)
1056 {
1057   NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
1058   NS_LOG_INFO ("DoRecvRrcConnectionReconfiguration haveNonCriticalExtension:" << msg.haveNonCriticalExtension);
1059   switch (m_state)
1060     {
1061       case CONNECTED_NORMALLY:
1062         if (msg.haveMobilityControlInfo)
1063           {
1064             NS_LOG_INFO ("haveMobilityControlInfo == true");
1065             SwitchToState (CONNECTED_HANDOVER);
1066             const LteRrcSap::MobilityControlInfo& mci = msg.mobilityControlInfo;
1067             m_handoverStartTrace (m_imsi, m_cellId, m_rnti, mci.targetPhysCellId);
1068             //We should reset the MACs and PHYs for all the component carriers
1069             for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
1070               {
1071                 m_cmacSapProvider.at (i)->Reset ();
1072                 m_cphySapProvider.at (i)->Reset ();
1073               }
1074             m_ccmRrcSapProvider->Reset ();
1075             StorePreviousCellId (m_cellId);
1076             m_cellId = mci.targetPhysCellId;
1077             NS_ASSERT (mci.haveCarrierFreq);
1078             NS_ASSERT (mci.haveCarrierBandwidth);
1079             m_cphySapProvider.at (0)->SynchronizeWithEnb (m_cellId, mci.carrierFreq.dlCarrierFreq);
1080             m_cphySapProvider.at (0)->SetDlBandwidth ( mci.carrierBandwidth.dlBandwidth);
1081             m_cphySapProvider.at (0)->ConfigureUplink (mci.carrierFreq.ulCarrierFreq, mci.carrierBandwidth.ulBandwidth);
1082             m_rnti = msg.mobilityControlInfo.newUeIdentity;
1083             m_srb0->m_rlc->SetRnti (m_rnti);
1084             NS_ASSERT_MSG (mci.haveRachConfigDedicated, "handover is only supported with non-contention-based random access procedure");
1085             m_cmacSapProvider.at (0)->StartNonContentionBasedRandomAccessProcedure (m_rnti, mci.rachConfigDedicated.raPreambleIndex, mci.rachConfigDedicated.raPrachMaskIndex);
1086             m_cphySapProvider.at (0)->SetRnti (m_rnti);
1087             m_lastRrcTransactionIdentifier = msg.rrcTransactionIdentifier;
1088             NS_ASSERT (msg.haveRadioResourceConfigDedicated);
1089 
1090             // we re-establish SRB1 by creating a new entity
1091             // note that we can't dispose the old entity now, because
1092             // it's in the current stack, so we would corrupt the stack
1093             // if we did so. Hence we schedule it for later disposal
1094             m_srb1Old = m_srb1;
1095             Simulator::ScheduleNow (&LteUeRrc::DisposeOldSrb1, this);
1096             m_srb1 = 0; // new instance will be be created within ApplyRadioResourceConfigDedicated
1097 
1098             m_drbMap.clear (); // dispose all DRBs
1099             ApplyRadioResourceConfigDedicated (msg.radioResourceConfigDedicated);
1100             if (msg.haveNonCriticalExtension)
1101               {
1102                 NS_LOG_DEBUG (this << "RNTI " << m_rnti << " Handover. Configuring secondary carriers");
1103                 ApplyRadioResourceConfigDedicatedSecondaryCarrier (msg.nonCriticalExtension);
1104               }
1105 
1106             if (msg.haveMeasConfig)
1107               {
1108                 ApplyMeasConfig (msg.measConfig);
1109               }
1110             // RRC connection reconfiguration completed will be sent
1111             // after handover is complete
1112           }
1113         else
1114           {
1115             NS_LOG_INFO ("haveMobilityControlInfo == false");
1116             if (msg.haveNonCriticalExtension)
1117               {
1118                 ApplyRadioResourceConfigDedicatedSecondaryCarrier (msg.nonCriticalExtension);
1119                 NS_LOG_DEBUG (this << "RNTI " << m_rnti << " Configured for CA" );
1120               }
1121             if (msg.haveRadioResourceConfigDedicated)
1122               {
1123                 ApplyRadioResourceConfigDedicated (msg.radioResourceConfigDedicated);
1124               }
1125             if (msg.haveMeasConfig)
1126               {
1127                 ApplyMeasConfig (msg.measConfig);
1128               }
1129             LteRrcSap::RrcConnectionReconfigurationCompleted msg2;
1130             msg2.rrcTransactionIdentifier = msg.rrcTransactionIdentifier;
1131             m_rrcSapUser->SendRrcConnectionReconfigurationCompleted (msg2);
1132             m_connectionReconfigurationTrace (m_imsi, m_cellId, m_rnti);
1133           }
1134         break;
1135 
1136       default:
1137         NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
1138         break;
1139     }
1140 }
1141 
1142 void
DoRecvRrcConnectionReestablishment(LteRrcSap::RrcConnectionReestablishment msg)1143 LteUeRrc::DoRecvRrcConnectionReestablishment (LteRrcSap::RrcConnectionReestablishment msg)
1144 {
1145   NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
1146   switch (m_state)
1147     {
1148       case CONNECTED_REESTABLISHING:
1149         {
1150           /**
1151            * \todo After receiving RRC Connection Re-establishment, stop timer
1152            *       T301, fire a new trace source, reply with RRC Connection
1153            *       Re-establishment Complete, and finally switch to
1154            *       CONNECTED_NORMALLY state. See Section 5.3.7.5 of 3GPP TS
1155            *       36.331.
1156            */
1157         }
1158         break;
1159 
1160       default:
1161         NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
1162         break;
1163     }
1164 }
1165 
1166 void
DoRecvRrcConnectionReestablishmentReject(LteRrcSap::RrcConnectionReestablishmentReject msg)1167 LteUeRrc::DoRecvRrcConnectionReestablishmentReject (LteRrcSap::RrcConnectionReestablishmentReject msg)
1168 {
1169   NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
1170   switch (m_state)
1171     {
1172       case CONNECTED_REESTABLISHING:
1173         {
1174           /**
1175            * \todo After receiving RRC Connection Re-establishment Reject, stop
1176            *       timer T301. See Section 5.3.7.8 of 3GPP TS 36.331.
1177            */
1178           m_asSapUser->NotifyConnectionReleased (); // Inform upper layers
1179         }
1180         break;
1181 
1182       default:
1183         NS_FATAL_ERROR ("method unexpected in state " << ToString (m_state));
1184         break;
1185     }
1186 }
1187 
1188 void
DoRecvRrcConnectionRelease(LteRrcSap::RrcConnectionRelease msg)1189 LteUeRrc::DoRecvRrcConnectionRelease (LteRrcSap::RrcConnectionRelease msg)
1190 {
1191   NS_LOG_FUNCTION (this << " RNTI " << m_rnti);
1192   /// \todo Currently not implemented, see Section 5.3.8 of 3GPP TS 36.331.
1193 }
1194 
1195 void
DoRecvRrcConnectionReject(LteRrcSap::RrcConnectionReject msg)1196 LteUeRrc::DoRecvRrcConnectionReject (LteRrcSap::RrcConnectionReject msg)
1197 {
1198   NS_LOG_FUNCTION (this);
1199   m_connectionTimeout.Cancel ();
1200   for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
1201     {
1202       m_cmacSapProvider.at (i)->Reset (); // reset the MAC
1203     }
1204   m_hasReceivedSib2 = false;         // invalidate the previously received SIB2
1205   SwitchToState (IDLE_CAMPED_NORMALLY);
1206   m_asSapUser->NotifyConnectionFailed ();  // inform upper layer
1207 }
1208 
1209 void
DoSetNumberOfComponentCarriers(uint16_t noOfComponentCarriers)1210 LteUeRrc::DoSetNumberOfComponentCarriers (uint16_t noOfComponentCarriers)
1211 {
1212   NS_LOG_FUNCTION (this);
1213   m_numberOfComponentCarriers = noOfComponentCarriers;
1214 }
1215 
1216 
1217 
1218 void
SynchronizeToStrongestCell()1219 LteUeRrc::SynchronizeToStrongestCell ()
1220 {
1221   NS_LOG_FUNCTION (this);
1222   NS_ASSERT (m_state == IDLE_CELL_SEARCH);
1223 
1224   uint16_t maxRsrpCellId = 0;
1225   double maxRsrp = -std::numeric_limits<double>::infinity ();
1226   double minRsrp = -140.0; // Minimum RSRP in dBm a UE can report
1227 
1228   std::map<uint16_t, MeasValues>::iterator it;
1229   for (it = m_storedMeasValues.begin (); it != m_storedMeasValues.end (); it++)
1230     {
1231       /*
1232        * This block attempts to find a cell with strongest RSRP and has not
1233        * yet been identified as "acceptable cell".
1234        */
1235       if (maxRsrp < it->second.rsrp && it->second.rsrp > minRsrp)
1236         {
1237           std::set<uint16_t>::const_iterator itCell;
1238           itCell = m_acceptableCell.find (it->first);
1239           if (itCell == m_acceptableCell.end ())
1240             {
1241               maxRsrpCellId = it->first;
1242               maxRsrp = it->second.rsrp;
1243             }
1244         }
1245     }
1246 
1247   if (maxRsrpCellId == 0)
1248     {
1249       NS_LOG_WARN (this << " Cell search is unable to detect surrounding cell to attach to");
1250     }
1251   else
1252     {
1253       NS_LOG_LOGIC (this << " cell " << maxRsrpCellId
1254                          << " is the strongest untried surrounding cell");
1255       m_cphySapProvider.at (0)->SynchronizeWithEnb (maxRsrpCellId, m_dlEarfcn);
1256       SwitchToState (IDLE_WAIT_MIB_SIB1);
1257     }
1258 
1259 } // end of void LteUeRrc::SynchronizeToStrongestCell ()
1260 
1261 
1262 void
EvaluateCellForSelection()1263 LteUeRrc::EvaluateCellForSelection ()
1264 {
1265   NS_LOG_FUNCTION (this);
1266   NS_ASSERT (m_state == IDLE_WAIT_SIB1);
1267   NS_ASSERT (m_hasReceivedMib);
1268   NS_ASSERT (m_hasReceivedSib1);
1269   uint16_t cellId = m_lastSib1.cellAccessRelatedInfo.cellIdentity;
1270 
1271   // Cell selection criteria evaluation
1272 
1273   bool isSuitableCell = false;
1274   bool isAcceptableCell = false;
1275   std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.find (cellId);
1276   double qRxLevMeas = storedMeasIt->second.rsrp;
1277   double qRxLevMin = EutranMeasurementMapping::IeValue2ActualQRxLevMin (m_lastSib1.cellSelectionInfo.qRxLevMin);
1278   NS_LOG_LOGIC (this << " cell selection to cellId=" << cellId
1279                      << " qrxlevmeas=" << qRxLevMeas << " dBm"
1280                      << " qrxlevmin=" << qRxLevMin << " dBm");
1281 
1282   if (qRxLevMeas - qRxLevMin > 0)
1283     {
1284       isAcceptableCell = true;
1285 
1286       uint32_t cellCsgId = m_lastSib1.cellAccessRelatedInfo.csgIdentity;
1287       bool cellCsgIndication = m_lastSib1.cellAccessRelatedInfo.csgIndication;
1288 
1289       isSuitableCell = (cellCsgIndication == false) || (cellCsgId == m_csgWhiteList);
1290 
1291       NS_LOG_LOGIC (this << " csg(ue/cell/indication)=" << m_csgWhiteList << "/"
1292                          << cellCsgId << "/" << cellCsgIndication);
1293     }
1294 
1295   // Cell selection decision
1296 
1297   if (isSuitableCell)
1298     {
1299       m_cellId = cellId;
1300       m_cphySapProvider.at (0)->SynchronizeWithEnb (cellId, m_dlEarfcn);
1301       m_cphySapProvider.at (0)->SetDlBandwidth (m_dlBandwidth);
1302       m_initialCellSelectionEndOkTrace (m_imsi, cellId);
1303       // Once the UE is connected, m_connectionPending is
1304       // set to false. So, when RLF occurs and UE performs
1305       // cell selection upon leaving RRC_CONNECTED state,
1306       // the following call to DoConnect will make the
1307       // m_connectionPending to be true again. Thus,
1308       // upon calling SwitchToState (IDLE_CAMPED_NORMALLY)
1309       // UE state is instantly change to IDLE_WAIT_SIB2.
1310       // This will make the UE to read the SIB2 message
1311       // and start random access.
1312       if (!m_connectionPending)
1313         {
1314           NS_LOG_DEBUG ("Calling DoConnect in state = " << ToString (m_state));
1315           DoConnect ();
1316         }
1317       SwitchToState (IDLE_CAMPED_NORMALLY);
1318     }
1319   else
1320     {
1321       // ignore the MIB and SIB1 received from this cell
1322       m_hasReceivedMib = false;
1323       m_hasReceivedSib1 = false;
1324 
1325       m_initialCellSelectionEndErrorTrace (m_imsi, cellId);
1326 
1327       if (isAcceptableCell)
1328         {
1329           /*
1330            * The cells inserted into this list will not be considered for
1331            * subsequent cell search attempt.
1332            */
1333           m_acceptableCell.insert (cellId);
1334         }
1335 
1336       SwitchToState (IDLE_CELL_SEARCH);
1337       SynchronizeToStrongestCell (); // retry to a different cell
1338     }
1339 
1340 } // end of void LteUeRrc::EvaluateCellForSelection ()
1341 
1342 
1343 void
ApplyRadioResourceConfigDedicatedSecondaryCarrier(LteRrcSap::NonCriticalExtensionConfiguration nonCec)1344 LteUeRrc::ApplyRadioResourceConfigDedicatedSecondaryCarrier (LteRrcSap::NonCriticalExtensionConfiguration nonCec)
1345 {
1346   NS_LOG_FUNCTION (this);
1347 
1348   m_sCellToAddModList = nonCec.sCellsToAddModList;
1349 
1350   for (std::list<LteRrcSap::SCellToAddMod>::iterator it = nonCec.sCellsToAddModList.begin (); it != nonCec.sCellsToAddModList.end (); it++)
1351     {
1352       LteRrcSap::SCellToAddMod scell = *it;
1353       uint8_t ccId = scell.sCellIndex;
1354 
1355 
1356       uint16_t physCellId = scell.cellIdentification.physCellId;
1357       uint16_t ulBand = scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth;
1358       uint32_t ulEarfcn = scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq;
1359       uint16_t dlBand = scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth;
1360       uint32_t dlEarfcn = scell.cellIdentification.dlCarrierFreq;
1361       uint8_t txMode = scell.radioResourceConfigDedicateSCell.physicalConfigDedicatedSCell.antennaInfo.transmissionMode;
1362       uint16_t srsIndex = scell.radioResourceConfigDedicateSCell.physicalConfigDedicatedSCell.soundingRsUlConfigDedicated.srsConfigIndex;
1363 
1364       m_cphySapProvider.at (ccId)->SynchronizeWithEnb (physCellId, dlEarfcn);
1365       m_cphySapProvider.at (ccId)->SetDlBandwidth (dlBand);
1366       m_cphySapProvider.at (ccId)->ConfigureUplink (ulEarfcn, ulBand);
1367       m_cphySapProvider.at (ccId)->ConfigureReferenceSignalPower (scell.radioResourceConfigCommonSCell.nonUlConfiguration.pdschConfigCommon.referenceSignalPower);
1368       m_cphySapProvider.at (ccId)->SetTransmissionMode (txMode);
1369       m_cphySapProvider.at (ccId)->SetRnti (m_rnti);
1370       m_cmacSapProvider.at (ccId)->SetRnti (m_rnti);
1371       // update PdschConfigDedicated (i.e. P_A value)
1372       LteRrcSap::PdschConfigDedicated pdschConfigDedicated = scell.radioResourceConfigDedicateSCell.physicalConfigDedicatedSCell.pdschConfigDedicated;
1373       double paDouble = LteRrcSap::ConvertPdschConfigDedicated2Double (pdschConfigDedicated);
1374       m_cphySapProvider.at (ccId)->SetPa (paDouble);
1375       m_cphySapProvider.at (ccId)->SetSrsConfigurationIndex (srsIndex);
1376     }
1377 
1378   m_sCarrierConfiguredTrace (this, m_sCellToAddModList);
1379 }
1380 
1381 void
ApplyRadioResourceConfigDedicated(LteRrcSap::RadioResourceConfigDedicated rrcd)1382 LteUeRrc::ApplyRadioResourceConfigDedicated (LteRrcSap::RadioResourceConfigDedicated rrcd)
1383 {
1384   NS_LOG_FUNCTION (this);
1385   const struct LteRrcSap::PhysicalConfigDedicated& pcd = rrcd.physicalConfigDedicated;
1386 
1387   if (pcd.haveAntennaInfoDedicated)
1388     {
1389       m_cphySapProvider.at (0)->SetTransmissionMode (pcd.antennaInfo.transmissionMode);
1390     }
1391   if (pcd.haveSoundingRsUlConfigDedicated)
1392     {
1393       m_cphySapProvider.at (0)->SetSrsConfigurationIndex (pcd.soundingRsUlConfigDedicated.srsConfigIndex);
1394     }
1395 
1396   if (pcd.havePdschConfigDedicated)
1397     {
1398       // update PdschConfigDedicated (i.e. P_A value)
1399       m_pdschConfigDedicated = pcd.pdschConfigDedicated;
1400       double paDouble = LteRrcSap::ConvertPdschConfigDedicated2Double (m_pdschConfigDedicated);
1401       m_cphySapProvider.at (0)->SetPa (paDouble);
1402     }
1403 
1404   std::list<LteRrcSap::SrbToAddMod>::const_iterator stamIt = rrcd.srbToAddModList.begin ();
1405   if (stamIt != rrcd.srbToAddModList.end ())
1406     {
1407       if (m_srb1 == 0)
1408         {
1409           // SRB1 not setup yet
1410           NS_ASSERT_MSG ((m_state == IDLE_CONNECTING) || (m_state == CONNECTED_HANDOVER),
1411                          "unexpected state " << ToString (m_state));
1412           NS_ASSERT_MSG (stamIt->srbIdentity == 1, "only SRB1 supported");
1413 
1414           const uint8_t lcid = 1; // fixed LCID for SRB1
1415 
1416           Ptr<LteRlc> rlc = CreateObject<LteRlcAm> ();
1417           rlc->SetLteMacSapProvider (m_macSapProvider);
1418           rlc->SetRnti (m_rnti);
1419           rlc->SetLcId (lcid);
1420 
1421           Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
1422           pdcp->SetRnti (m_rnti);
1423           pdcp->SetLcId (lcid);
1424           pdcp->SetLtePdcpSapUser (m_drbPdcpSapUser);
1425           pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
1426           rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
1427 
1428           m_srb1 = CreateObject<LteSignalingRadioBearerInfo> ();
1429           m_srb1->m_rlc = rlc;
1430           m_srb1->m_pdcp = pdcp;
1431           m_srb1->m_srbIdentity = 1;
1432           m_srb1CreatedTrace (m_imsi, m_cellId, m_rnti);
1433 
1434           m_srb1->m_logicalChannelConfig.priority = stamIt->logicalChannelConfig.priority;
1435           m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.prioritizedBitRateKbps;
1436           m_srb1->m_logicalChannelConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSizeDurationMs;
1437           m_srb1->m_logicalChannelConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalChannelGroup;
1438 
1439           struct LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
1440           lcConfig.priority = stamIt->logicalChannelConfig.priority;
1441           lcConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.prioritizedBitRateKbps;
1442           lcConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSizeDurationMs;
1443           lcConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalChannelGroup;
1444           LteMacSapUser* msu = m_ccmRrcSapProvider->ConfigureSignalBearer (lcid, lcConfig, rlc->GetLteMacSapUser ());
1445           m_cmacSapProvider.at (0)->AddLc (lcid, lcConfig, msu);
1446           ++stamIt;
1447           NS_ASSERT_MSG (stamIt == rrcd.srbToAddModList.end (), "at most one SrbToAdd supported");
1448 
1449           LteUeRrcSapUser::SetupParameters ueParams;
1450           ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider ();
1451           ueParams.srb1SapProvider = m_srb1->m_pdcp->GetLtePdcpSapProvider ();
1452           m_rrcSapUser->Setup (ueParams);
1453         }
1454       else
1455         {
1456           NS_LOG_INFO ("request to modify SRB1 (skipping as currently not implemented)");
1457           // would need to modify m_srb1, and then propagate changes to the MAC
1458         }
1459     }
1460 
1461 
1462   std::list<LteRrcSap::DrbToAddMod>::const_iterator dtamIt;
1463   for (dtamIt = rrcd.drbToAddModList.begin ();
1464        dtamIt != rrcd.drbToAddModList.end ();
1465        ++dtamIt)
1466     {
1467       NS_LOG_INFO (this << " IMSI " << m_imsi << " adding/modifying DRBID " << (uint32_t) dtamIt->drbIdentity << " LC " << (uint32_t) dtamIt->logicalChannelIdentity);
1468       NS_ASSERT_MSG (dtamIt->logicalChannelIdentity > 2, "LCID value " << dtamIt->logicalChannelIdentity << " is reserved for SRBs");
1469 
1470       std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator drbMapIt = m_drbMap.find (dtamIt->drbIdentity);
1471       if (drbMapIt == m_drbMap.end ())
1472         {
1473           NS_LOG_INFO ("New Data Radio Bearer");
1474 
1475           TypeId rlcTypeId;
1476           if (m_useRlcSm)
1477             {
1478               rlcTypeId = LteRlcSm::GetTypeId ();
1479             }
1480           else
1481             {
1482               switch (dtamIt->rlcConfig.choice)
1483                 {
1484                   case LteRrcSap::RlcConfig::AM:
1485                     rlcTypeId = LteRlcAm::GetTypeId ();
1486                     break;
1487 
1488                   case LteRrcSap::RlcConfig::UM_BI_DIRECTIONAL:
1489                     rlcTypeId = LteRlcUm::GetTypeId ();
1490                     break;
1491 
1492                   default:
1493                     NS_FATAL_ERROR ("unsupported RLC configuration");
1494                     break;
1495                 }
1496             }
1497 
1498           ObjectFactory rlcObjectFactory;
1499           rlcObjectFactory.SetTypeId (rlcTypeId);
1500           Ptr<LteRlc> rlc = rlcObjectFactory.Create ()->GetObject<LteRlc> ();
1501           rlc->SetLteMacSapProvider (m_macSapProvider);
1502           rlc->SetRnti (m_rnti);
1503           rlc->SetLcId (dtamIt->logicalChannelIdentity);
1504 
1505           Ptr<LteDataRadioBearerInfo> drbInfo = CreateObject<LteDataRadioBearerInfo> ();
1506           drbInfo->m_rlc = rlc;
1507           drbInfo->m_epsBearerIdentity = dtamIt->epsBearerIdentity;
1508           drbInfo->m_logicalChannelIdentity = dtamIt->logicalChannelIdentity;
1509           drbInfo->m_drbIdentity = dtamIt->drbIdentity;
1510 
1511           // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
1512           // if we are using RLC/SM we don't care of anything above RLC
1513           if (rlcTypeId != LteRlcSm::GetTypeId ())
1514             {
1515               Ptr<LtePdcp> pdcp = CreateObject<LtePdcp> ();
1516               pdcp->SetRnti (m_rnti);
1517               pdcp->SetLcId (dtamIt->logicalChannelIdentity);
1518               pdcp->SetLtePdcpSapUser (m_drbPdcpSapUser);
1519               pdcp->SetLteRlcSapProvider (rlc->GetLteRlcSapProvider ());
1520               rlc->SetLteRlcSapUser (pdcp->GetLteRlcSapUser ());
1521               drbInfo->m_pdcp = pdcp;
1522             }
1523 
1524           m_bid2DrbidMap[dtamIt->epsBearerIdentity] = dtamIt->drbIdentity;
1525 
1526           m_drbMap.insert (std::pair<uint8_t, Ptr<LteDataRadioBearerInfo> > (dtamIt->drbIdentity, drbInfo));
1527 
1528           m_drbCreatedTrace (m_imsi, m_cellId, m_rnti, dtamIt->drbIdentity);
1529 
1530 
1531           struct LteUeCmacSapProvider::LogicalChannelConfig lcConfig;
1532           lcConfig.priority = dtamIt->logicalChannelConfig.priority;
1533           lcConfig.prioritizedBitRateKbps = dtamIt->logicalChannelConfig.prioritizedBitRateKbps;
1534           lcConfig.bucketSizeDurationMs = dtamIt->logicalChannelConfig.bucketSizeDurationMs;
1535           lcConfig.logicalChannelGroup = dtamIt->logicalChannelConfig.logicalChannelGroup;
1536 
1537           NS_LOG_DEBUG (this << " UE RRC RNTI " << m_rnti << " Number Of Component Carriers " << m_numberOfComponentCarriers << " lcID " << (uint16_t) dtamIt->logicalChannelIdentity);
1538           //Call AddLc of UE component carrier manager
1539           std::vector <LteUeCcmRrcSapProvider::LcsConfig> lcOnCcMapping = m_ccmRrcSapProvider->AddLc (dtamIt->logicalChannelIdentity, lcConfig, rlc->GetLteMacSapUser ());
1540 
1541           NS_LOG_DEBUG ("Size of lcOnCcMapping vector " << lcOnCcMapping.size ());
1542           std::vector<LteUeCcmRrcSapProvider::LcsConfig>::iterator itLcOnCcMapping = lcOnCcMapping.begin ();
1543           NS_ASSERT_MSG (itLcOnCcMapping != lcOnCcMapping.end (), "Component carrier manager failed to add LC for data radio bearer");
1544 
1545           for (itLcOnCcMapping = lcOnCcMapping.begin (); itLcOnCcMapping != lcOnCcMapping.end (); ++itLcOnCcMapping)
1546             {
1547               NS_LOG_DEBUG ("RNTI " << m_rnti
1548                                     << " LCG id " << (uint16_t) itLcOnCcMapping->lcConfig.logicalChannelGroup
1549                                     << " ComponentCarrierId " << (uint16_t) itLcOnCcMapping->componentCarrierId);
1550               uint8_t index = itLcOnCcMapping->componentCarrierId;
1551               LteUeCmacSapProvider::LogicalChannelConfig lcConfigFromCcm = itLcOnCcMapping->lcConfig;
1552               LteMacSapUser *msu = itLcOnCcMapping->msu;
1553               m_cmacSapProvider.at (index)->AddLc (dtamIt->logicalChannelIdentity, lcConfigFromCcm, msu);
1554             }
1555 
1556           rlc->Initialize ();
1557         }
1558       else
1559         {
1560           NS_LOG_INFO ("request to modify existing DRBID");
1561           Ptr<LteDataRadioBearerInfo> drbInfo = drbMapIt->second;
1562           /// \todo currently not implemented. Would need to modify drbInfo, and then propagate changes to the MAC
1563         }
1564     }
1565 
1566   std::list<uint8_t>::iterator dtdmIt;
1567   for (dtdmIt = rrcd.drbToReleaseList.begin ();
1568        dtdmIt != rrcd.drbToReleaseList.end ();
1569        ++dtdmIt)
1570     {
1571       uint8_t drbid = *dtdmIt;
1572       NS_LOG_INFO (this << " IMSI " << m_imsi << " releasing DRB " << (uint32_t) drbid);
1573       std::map<uint8_t, Ptr<LteDataRadioBearerInfo> >::iterator it =   m_drbMap.find (drbid);
1574       NS_ASSERT_MSG (it != m_drbMap.end (), "could not find bearer with given lcid");
1575       m_drbMap.erase (it);
1576       m_bid2DrbidMap.erase (drbid);
1577       //Remove LCID
1578       for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
1579         {
1580           m_cmacSapProvider.at (i)->RemoveLc (drbid + 2);
1581         }
1582     }
1583 }
1584 
1585 
1586 void
ApplyMeasConfig(LteRrcSap::MeasConfig mc)1587 LteUeRrc::ApplyMeasConfig (LteRrcSap::MeasConfig mc)
1588 {
1589   NS_LOG_FUNCTION (this);
1590 
1591   // perform the actions specified in 3GPP TS 36.331 section 5.5.2.1
1592 
1593   // 3GPP TS 36.331 section 5.5.2.4 Measurement object removal
1594   for (std::list<uint8_t>::iterator it = mc.measObjectToRemoveList.begin ();
1595        it !=  mc.measObjectToRemoveList.end ();
1596        ++it)
1597     {
1598       uint8_t measObjectId = *it;
1599       NS_LOG_LOGIC (this << " deleting measObjectId " << (uint32_t)  measObjectId);
1600       m_varMeasConfig.measObjectList.erase (measObjectId);
1601       std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt = m_varMeasConfig.measIdList.begin ();
1602       while (measIdIt != m_varMeasConfig.measIdList.end ())
1603         {
1604           if (measIdIt->second.measObjectId == measObjectId)
1605             {
1606               uint8_t measId = measIdIt->second.measId;
1607               NS_ASSERT (measId == measIdIt->first);
1608               NS_LOG_LOGIC (this << " deleting measId " << (uint32_t) measId << " because referring to measObjectId " << (uint32_t)  measObjectId);
1609               // note: postfix operator preserves iterator validity
1610               m_varMeasConfig.measIdList.erase (measIdIt++);
1611               VarMeasReportListClear (measId);
1612             }
1613           else
1614             {
1615               ++measIdIt;
1616             }
1617         }
1618 
1619     }
1620 
1621   // 3GPP TS 36.331 section 5.5.2.5  Measurement object addition/ modification
1622   for (std::list<LteRrcSap::MeasObjectToAddMod>::iterator it = mc.measObjectToAddModList.begin ();
1623        it !=  mc.measObjectToAddModList.end ();
1624        ++it)
1625     {
1626       // simplifying assumptions
1627       NS_ASSERT_MSG (it->measObjectEutra.cellsToRemoveList.empty (), "cellsToRemoveList not supported");
1628       NS_ASSERT_MSG (it->measObjectEutra.cellsToAddModList.empty (), "cellsToAddModList not supported");
1629       NS_ASSERT_MSG (it->measObjectEutra.cellsToRemoveList.empty (), "blackCellsToRemoveList not supported");
1630       NS_ASSERT_MSG (it->measObjectEutra.blackCellsToAddModList.empty (), "blackCellsToAddModList not supported");
1631       NS_ASSERT_MSG (it->measObjectEutra.haveCellForWhichToReportCGI == false, "cellForWhichToReportCGI is not supported");
1632 
1633       uint8_t measObjectId = it->measObjectId;
1634       std::map<uint8_t, LteRrcSap::MeasObjectToAddMod>::iterator measObjectIt = m_varMeasConfig.measObjectList.find (measObjectId);
1635       if (measObjectIt != m_varMeasConfig.measObjectList.end ())
1636         {
1637           NS_LOG_LOGIC ("measObjectId " << (uint32_t) measObjectId << " exists, updating entry");
1638           measObjectIt->second = *it;
1639           for (std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt
1640                  = m_varMeasConfig.measIdList.begin ();
1641                measIdIt != m_varMeasConfig.measIdList.end ();
1642                ++measIdIt)
1643             {
1644               if (measIdIt->second.measObjectId == measObjectId)
1645                 {
1646                   uint8_t measId = measIdIt->second.measId;
1647                   NS_LOG_LOGIC (this << " found measId " << (uint32_t) measId << " referring to measObjectId " << (uint32_t)  measObjectId);
1648                   VarMeasReportListClear (measId);
1649                 }
1650             }
1651         }
1652       else
1653         {
1654           NS_LOG_LOGIC ("measObjectId " << (uint32_t) measObjectId << " is new, adding entry");
1655           m_varMeasConfig.measObjectList[measObjectId] = *it;
1656         }
1657 
1658     }
1659 
1660   // 3GPP TS 36.331 section 5.5.2.6 Reporting configuration removal
1661   for (std::list<uint8_t>::iterator it = mc.reportConfigToRemoveList.begin ();
1662        it !=  mc.reportConfigToRemoveList.end ();
1663        ++it)
1664     {
1665       uint8_t reportConfigId = *it;
1666       NS_LOG_LOGIC (this << " deleting reportConfigId " << (uint32_t)  reportConfigId);
1667       m_varMeasConfig.reportConfigList.erase (reportConfigId);
1668       std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt = m_varMeasConfig.measIdList.begin ();
1669       while (measIdIt != m_varMeasConfig.measIdList.end ())
1670         {
1671           if (measIdIt->second.reportConfigId == reportConfigId)
1672             {
1673               uint8_t measId = measIdIt->second.measId;
1674               NS_ASSERT (measId == measIdIt->first);
1675               NS_LOG_LOGIC (this << " deleting measId " << (uint32_t) measId << " because referring to reportConfigId " << (uint32_t)  reportConfigId);
1676               // note: postfix operator preserves iterator validity
1677               m_varMeasConfig.measIdList.erase (measIdIt++);
1678               VarMeasReportListClear (measId);
1679             }
1680           else
1681             {
1682               ++measIdIt;
1683             }
1684         }
1685 
1686     }
1687 
1688   // 3GPP TS 36.331 section 5.5.2.7 Reporting configuration addition/ modification
1689   for (std::list<LteRrcSap::ReportConfigToAddMod>::iterator it = mc.reportConfigToAddModList.begin ();
1690        it !=  mc.reportConfigToAddModList.end ();
1691        ++it)
1692     {
1693       // simplifying assumptions
1694       NS_ASSERT_MSG (it->reportConfigEutra.triggerType == LteRrcSap::ReportConfigEutra::EVENT,
1695                      "only trigger type EVENT is supported");
1696 
1697       uint8_t reportConfigId = it->reportConfigId;
1698       std::map<uint8_t, LteRrcSap::ReportConfigToAddMod>::iterator reportConfigIt = m_varMeasConfig.reportConfigList.find (reportConfigId);
1699       if (reportConfigIt != m_varMeasConfig.reportConfigList.end ())
1700         {
1701           NS_LOG_LOGIC ("reportConfigId " << (uint32_t) reportConfigId << " exists, updating entry");
1702           m_varMeasConfig.reportConfigList[reportConfigId] = *it;
1703           for (std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt
1704                  = m_varMeasConfig.measIdList.begin ();
1705                measIdIt != m_varMeasConfig.measIdList.end ();
1706                ++measIdIt)
1707             {
1708               if (measIdIt->second.reportConfigId == reportConfigId)
1709                 {
1710                   uint8_t measId = measIdIt->second.measId;
1711                   NS_LOG_LOGIC (this << " found measId " << (uint32_t) measId << " referring to reportConfigId " << (uint32_t)  reportConfigId);
1712                   VarMeasReportListClear (measId);
1713                 }
1714             }
1715         }
1716       else
1717         {
1718           NS_LOG_LOGIC ("reportConfigId " << (uint32_t) reportConfigId << " is new, adding entry");
1719           m_varMeasConfig.reportConfigList[reportConfigId] = *it;
1720         }
1721 
1722     }
1723 
1724   // 3GPP TS 36.331 section 5.5.2.8 Quantity configuration
1725   if (mc.haveQuantityConfig)
1726     {
1727       NS_LOG_LOGIC (this << " setting quantityConfig");
1728       m_varMeasConfig.quantityConfig = mc.quantityConfig;
1729       //Convey the filter coefficient to PHY layer so it can configure the power control parameter
1730       for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
1731         {
1732           m_cphySapProvider.at (i)->SetRsrpFilterCoefficient (mc.quantityConfig.filterCoefficientRSRP);
1733         }
1734       // we calculate here the coefficient a used for Layer 3 filtering, see 3GPP TS 36.331 section 5.5.3.2
1735       m_varMeasConfig.aRsrp = std::pow (0.5, mc.quantityConfig.filterCoefficientRSRP / 4.0);
1736       m_varMeasConfig.aRsrq = std::pow (0.5, mc.quantityConfig.filterCoefficientRSRQ / 4.0);
1737       NS_LOG_LOGIC (this << " new filter coefficients: aRsrp=" << m_varMeasConfig.aRsrp << ", aRsrq=" << m_varMeasConfig.aRsrq);
1738 
1739       for (std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt
1740              = m_varMeasConfig.measIdList.begin ();
1741            measIdIt != m_varMeasConfig.measIdList.end ();
1742            ++measIdIt)
1743         {
1744           VarMeasReportListClear (measIdIt->second.measId);
1745         }
1746     }
1747 
1748   // 3GPP TS 36.331 section 5.5.2.2 Measurement identity removal
1749   for (std::list<uint8_t>::iterator it = mc.measIdToRemoveList.begin ();
1750        it !=  mc.measIdToRemoveList.end ();
1751        ++it)
1752     {
1753       uint8_t measId = *it;
1754       NS_LOG_LOGIC (this << " deleting measId " << (uint32_t) measId);
1755       m_varMeasConfig.measIdList.erase (measId);
1756       VarMeasReportListClear (measId);
1757 
1758       // removing time-to-trigger queues
1759       m_enteringTriggerQueue.erase (measId);
1760       m_leavingTriggerQueue.erase (measId);
1761     }
1762 
1763   // 3GPP TS 36.331 section 5.5.2.3 Measurement identity addition/ modification
1764   for (std::list<LteRrcSap::MeasIdToAddMod>::iterator it = mc.measIdToAddModList.begin ();
1765        it !=  mc.measIdToAddModList.end ();
1766        ++it)
1767     {
1768       NS_LOG_LOGIC (this << " measId " << (uint32_t) it->measId
1769                          << " (measObjectId=" << (uint32_t) it->measObjectId
1770                          << ", reportConfigId=" << (uint32_t) it->reportConfigId
1771                          << ")");
1772       NS_ASSERT (m_varMeasConfig.measObjectList.find (it->measObjectId)
1773                  != m_varMeasConfig.measObjectList.end ());
1774       NS_ASSERT (m_varMeasConfig.reportConfigList.find (it->reportConfigId)
1775                  != m_varMeasConfig.reportConfigList.end ());
1776       m_varMeasConfig.measIdList[it->measId] = *it; // side effect: create new entry if not exists
1777       std::map<uint8_t, VarMeasReport>::iterator measReportIt = m_varMeasReportList.find (it->measId);
1778       if (measReportIt != m_varMeasReportList.end ())
1779         {
1780           measReportIt->second.periodicReportTimer.Cancel ();
1781           m_varMeasReportList.erase (measReportIt);
1782         }
1783       NS_ASSERT (m_varMeasConfig.reportConfigList.find (it->reportConfigId)
1784                  ->second.reportConfigEutra.triggerType != LteRrcSap::ReportConfigEutra::PERIODICAL);
1785 
1786       // new empty queues for time-to-trigger
1787       std::list<PendingTrigger_t> s;
1788       m_enteringTriggerQueue[it->measId] = s;
1789       m_leavingTriggerQueue[it->measId] = s;
1790     }
1791 
1792   if (mc.haveMeasGapConfig)
1793     {
1794       NS_FATAL_ERROR ("measurement gaps are currently not supported");
1795     }
1796 
1797   if (mc.haveSmeasure)
1798     {
1799       NS_FATAL_ERROR ("s-measure is currently not supported");
1800     }
1801 
1802   if (mc.haveSpeedStatePars)
1803     {
1804       NS_FATAL_ERROR ("SpeedStatePars are currently not supported");
1805     }
1806 }
1807 
1808 void
SaveUeMeasurements(uint16_t cellId,double rsrp,double rsrq,bool useLayer3Filtering)1809 LteUeRrc::SaveUeMeasurements (uint16_t cellId, double rsrp, double rsrq,
1810                               bool useLayer3Filtering)
1811 {
1812   NS_LOG_FUNCTION (this << cellId << rsrp << rsrq << useLayer3Filtering);
1813 
1814   std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.find (cellId);
1815 
1816   if (storedMeasIt != m_storedMeasValues.end ())
1817     {
1818       if (useLayer3Filtering)
1819         {
1820           // F_n = (1-a) F_{n-1} + a M_n
1821           storedMeasIt->second.rsrp = (1 - m_varMeasConfig.aRsrp) * storedMeasIt->second.rsrp
1822             + m_varMeasConfig.aRsrp * rsrp;
1823 
1824           if (std::isnan (storedMeasIt->second.rsrq))
1825             {
1826               // the previous RSRQ measurements provided UE PHY are invalid
1827               storedMeasIt->second.rsrq = rsrq; // replace it with unfiltered value
1828             }
1829           else
1830             {
1831               storedMeasIt->second.rsrq = (1 - m_varMeasConfig.aRsrq) * storedMeasIt->second.rsrq
1832                 + m_varMeasConfig.aRsrq * rsrq;
1833             }
1834         }
1835       else
1836         {
1837           storedMeasIt->second.rsrp = rsrp;
1838           storedMeasIt->second.rsrq = rsrq;
1839         }
1840     }
1841   else
1842     {
1843       // first value is always unfiltered
1844       MeasValues v;
1845       v.rsrp = rsrp;
1846       v.rsrq = rsrq;
1847       std::pair<uint16_t, MeasValues> val (cellId, v);
1848       std::pair<std::map<uint16_t, MeasValues>::iterator, bool>
1849       ret = m_storedMeasValues.insert (val);
1850       NS_ASSERT_MSG (ret.second == true, "element already existed");
1851       storedMeasIt = ret.first;
1852     }
1853 
1854   NS_LOG_DEBUG (this << " IMSI " << m_imsi << " state " << ToString (m_state)
1855                      << ", measured cell " << m_cellId
1856                      << ", new RSRP " << rsrp << " stored " << storedMeasIt->second.rsrp
1857                      << ", new RSRQ " << rsrq << " stored " << storedMeasIt->second.rsrq);
1858   storedMeasIt->second.timestamp = Simulator::Now ();
1859 
1860 } // end of void SaveUeMeasurements
1861 
1862 void
MeasurementReportTriggering(uint8_t measId)1863 LteUeRrc::MeasurementReportTriggering (uint8_t measId)
1864 {
1865   NS_LOG_FUNCTION (this << (uint16_t) measId);
1866 
1867   std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt =
1868     m_varMeasConfig.measIdList.find (measId);
1869   NS_ASSERT (measIdIt != m_varMeasConfig.measIdList.end ());
1870   NS_ASSERT (measIdIt->first == measIdIt->second.measId);
1871 
1872   std::map<uint8_t, LteRrcSap::ReportConfigToAddMod>::iterator
1873     reportConfigIt = m_varMeasConfig.reportConfigList.find (measIdIt->second.reportConfigId);
1874   NS_ASSERT (reportConfigIt != m_varMeasConfig.reportConfigList.end ());
1875   LteRrcSap::ReportConfigEutra& reportConfigEutra = reportConfigIt->second.reportConfigEutra;
1876 
1877   std::map<uint8_t, LteRrcSap::MeasObjectToAddMod>::iterator
1878     measObjectIt = m_varMeasConfig.measObjectList.find (measIdIt->second.measObjectId);
1879   NS_ASSERT (measObjectIt != m_varMeasConfig.measObjectList.end ());
1880   LteRrcSap::MeasObjectEutra& measObjectEutra = measObjectIt->second.measObjectEutra;
1881 
1882   std::map<uint8_t, VarMeasReport>::iterator
1883     measReportIt = m_varMeasReportList.find (measId);
1884   bool isMeasIdInReportList = (measReportIt != m_varMeasReportList.end ());
1885 
1886   // we don't check the purpose field, as it is only included for
1887   // triggerType == periodical, which is not supported
1888   NS_ASSERT_MSG (reportConfigEutra.triggerType
1889                  == LteRrcSap::ReportConfigEutra::EVENT,
1890                  "only triggerType == event is supported");
1891   // only EUTRA is supported, no need to check for it
1892 
1893   NS_LOG_LOGIC (this << " considering measId " << (uint32_t) measId);
1894   bool eventEntryCondApplicable = false;
1895   bool eventLeavingCondApplicable = false;
1896   ConcernedCells_t concernedCellsEntry;
1897   ConcernedCells_t concernedCellsLeaving;
1898 
1899   switch (reportConfigEutra.eventId)
1900     {
1901       case LteRrcSap::ReportConfigEutra::EVENT_A1:
1902         {
1903           /*
1904            * Event A1 (Serving becomes better than threshold)
1905            * Please refer to 3GPP TS 36.331 Section 5.5.4.2
1906            */
1907 
1908           double ms; // Ms, the measurement result of the serving cell
1909           double thresh; // Thresh, the threshold parameter for this event
1910           // Hys, the hysteresis parameter for this event.
1911           double hys = EutranMeasurementMapping::IeValue2ActualHysteresis (reportConfigEutra.hysteresis);
1912 
1913           switch (reportConfigEutra.triggerQuantity)
1914             {
1915               case LteRrcSap::ReportConfigEutra::RSRP:
1916                 ms = m_storedMeasValues[m_cellId].rsrp;
1917                 NS_ASSERT (reportConfigEutra.threshold1.choice
1918                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRP);
1919                 thresh = EutranMeasurementMapping::RsrpRange2Dbm (reportConfigEutra.threshold1.range);
1920                 break;
1921               case LteRrcSap::ReportConfigEutra::RSRQ:
1922                 ms = m_storedMeasValues[m_cellId].rsrq;
1923                 NS_ASSERT (reportConfigEutra.threshold1.choice
1924                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ);
1925                 thresh = EutranMeasurementMapping::RsrqRange2Db (reportConfigEutra.threshold1.range);
1926                 break;
1927               default:
1928                 NS_FATAL_ERROR ("unsupported triggerQuantity");
1929                 break;
1930             }
1931 
1932           // Inequality A1-1 (Entering condition): Ms - Hys > Thresh
1933           bool entryCond = ms - hys > thresh;
1934 
1935           if (entryCond)
1936             {
1937               if (!isMeasIdInReportList)
1938                 {
1939                   concernedCellsEntry.push_back (m_cellId);
1940                   eventEntryCondApplicable = true;
1941                 }
1942               else
1943                 {
1944                   /*
1945                    * This is to check that the triggered cell recorded in the
1946                    * VarMeasReportList is the serving cell.
1947                    */
1948                   NS_ASSERT (measReportIt->second.cellsTriggeredList.find (m_cellId)
1949                              != measReportIt->second.cellsTriggeredList.end ());
1950                 }
1951             }
1952           else if (reportConfigEutra.timeToTrigger > 0)
1953             {
1954               CancelEnteringTrigger (measId);
1955             }
1956 
1957           // Inequality A1-2 (Leaving condition): Ms + Hys < Thresh
1958           bool leavingCond = ms + hys < thresh;
1959 
1960           if (leavingCond)
1961             {
1962               if (isMeasIdInReportList)
1963                 {
1964                   /*
1965                    * This is to check that the triggered cell recorded in the
1966                    * VarMeasReportList is the serving cell.
1967                    */
1968                   NS_ASSERT (measReportIt->second.cellsTriggeredList.find (m_cellId)
1969                              != measReportIt->second.cellsTriggeredList.end ());
1970                   concernedCellsLeaving.push_back (m_cellId);
1971                   eventLeavingCondApplicable = true;
1972                 }
1973             }
1974           else if (reportConfigEutra.timeToTrigger > 0)
1975             {
1976               CancelLeavingTrigger (measId);
1977             }
1978 
1979           NS_LOG_LOGIC (this << " event A1: serving cell " << m_cellId
1980                              << " ms=" << ms << " thresh=" << thresh
1981                              << " entryCond=" << entryCond
1982                              << " leavingCond=" << leavingCond);
1983 
1984         } // end of case LteRrcSap::ReportConfigEutra::EVENT_A1
1985 
1986         break;
1987 
1988       case LteRrcSap::ReportConfigEutra::EVENT_A2:
1989         {
1990           /*
1991            * Event A2 (Serving becomes worse than threshold)
1992            * Please refer to 3GPP TS 36.331 Section 5.5.4.3
1993            */
1994 
1995           double ms; // Ms, the measurement result of the serving cell
1996           double thresh; // Thresh, the threshold parameter for this event
1997           // Hys, the hysteresis parameter for this event.
1998           double hys = EutranMeasurementMapping::IeValue2ActualHysteresis (reportConfigEutra.hysteresis);
1999 
2000           switch (reportConfigEutra.triggerQuantity)
2001             {
2002               case LteRrcSap::ReportConfigEutra::RSRP:
2003                 ms = m_storedMeasValues[m_cellId].rsrp;
2004                 NS_ASSERT (reportConfigEutra.threshold1.choice
2005                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRP);
2006                 thresh = EutranMeasurementMapping::RsrpRange2Dbm (reportConfigEutra.threshold1.range);
2007                 break;
2008               case LteRrcSap::ReportConfigEutra::RSRQ:
2009                 ms = m_storedMeasValues[m_cellId].rsrq;
2010                 NS_ASSERT (reportConfigEutra.threshold1.choice
2011                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ);
2012                 thresh = EutranMeasurementMapping::RsrqRange2Db (reportConfigEutra.threshold1.range);
2013                 break;
2014               default:
2015                 NS_FATAL_ERROR ("unsupported triggerQuantity");
2016                 break;
2017             }
2018 
2019           // Inequality A2-1 (Entering condition): Ms + Hys < Thresh
2020           bool entryCond = ms + hys < thresh;
2021 
2022           if (entryCond)
2023             {
2024               if (!isMeasIdInReportList)
2025                 {
2026                   concernedCellsEntry.push_back (m_cellId);
2027                   eventEntryCondApplicable = true;
2028                 }
2029               else
2030                 {
2031                   /*
2032                    * This is to check that the triggered cell recorded in the
2033                    * VarMeasReportList is the serving cell.
2034                    */
2035                   NS_ASSERT (measReportIt->second.cellsTriggeredList.find (m_cellId)
2036                              != measReportIt->second.cellsTriggeredList.end ());
2037                 }
2038             }
2039           else if (reportConfigEutra.timeToTrigger > 0)
2040             {
2041               CancelEnteringTrigger (measId);
2042             }
2043 
2044           // Inequality A2-2 (Leaving condition): Ms - Hys > Thresh
2045           bool leavingCond = ms - hys > thresh;
2046 
2047           if (leavingCond)
2048             {
2049               if (isMeasIdInReportList)
2050                 {
2051                   /*
2052                    * This is to check that the triggered cell recorded in the
2053                    * VarMeasReportList is the serving cell.
2054                    */
2055                   NS_ASSERT (measReportIt->second.cellsTriggeredList.find (m_cellId)
2056                              != measReportIt->second.cellsTriggeredList.end ());
2057                   concernedCellsLeaving.push_back (m_cellId);
2058                   eventLeavingCondApplicable = true;
2059                 }
2060             }
2061           else if (reportConfigEutra.timeToTrigger > 0)
2062             {
2063               CancelLeavingTrigger (measId);
2064             }
2065 
2066           NS_LOG_LOGIC (this << " event A2: serving cell " << m_cellId
2067                              << " ms=" << ms << " thresh=" << thresh
2068                              << " entryCond=" << entryCond
2069                              << " leavingCond=" << leavingCond);
2070 
2071         } // end of case LteRrcSap::ReportConfigEutra::EVENT_A2
2072 
2073         break;
2074 
2075       case LteRrcSap::ReportConfigEutra::EVENT_A3:
2076         {
2077           /*
2078            * Event A3 (Neighbour becomes offset better than PCell)
2079            * Please refer to 3GPP TS 36.331 Section 5.5.4.4
2080            */
2081 
2082           double mn; // Mn, the measurement result of the neighbouring cell
2083           double ofn = measObjectEutra.offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2084           double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2085           double mp; // Mp, the measurement result of the PCell
2086           double ofp = measObjectEutra.offsetFreq; // Ofp, the frequency specific offset of the primary frequency
2087           double ocp = 0.0; // Ocp, the cell specific offset of the PCell
2088           // Off, the offset parameter for this event.
2089           double off = EutranMeasurementMapping::IeValue2ActualA3Offset (reportConfigEutra.a3Offset);
2090           // Hys, the hysteresis parameter for this event.
2091           double hys = EutranMeasurementMapping::IeValue2ActualHysteresis (reportConfigEutra.hysteresis);
2092 
2093           switch (reportConfigEutra.triggerQuantity)
2094             {
2095               case LteRrcSap::ReportConfigEutra::RSRP:
2096                 mp = m_storedMeasValues[m_cellId].rsrp;
2097                 NS_ASSERT (reportConfigEutra.threshold1.choice
2098                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRP);
2099                 break;
2100               case LteRrcSap::ReportConfigEutra::RSRQ:
2101                 mp = m_storedMeasValues[m_cellId].rsrq;
2102                 NS_ASSERT (reportConfigEutra.threshold1.choice
2103                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ);
2104                 break;
2105               default:
2106                 NS_FATAL_ERROR ("unsupported triggerQuantity");
2107                 break;
2108             }
2109 
2110           for (std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.begin ();
2111                storedMeasIt != m_storedMeasValues.end ();
2112                ++storedMeasIt)
2113             {
2114               uint16_t cellId = storedMeasIt->first;
2115               if (cellId == m_cellId)
2116                 {
2117                   continue;
2118                 }
2119 
2120               switch (reportConfigEutra.triggerQuantity)
2121                 {
2122                   case LteRrcSap::ReportConfigEutra::RSRP:
2123                     mn = storedMeasIt->second.rsrp;
2124                     break;
2125                   case LteRrcSap::ReportConfigEutra::RSRQ:
2126                     mn = storedMeasIt->second.rsrq;
2127                     break;
2128                   default:
2129                     NS_FATAL_ERROR ("unsupported triggerQuantity");
2130                     break;
2131                 }
2132 
2133               bool hasTriggered = isMeasIdInReportList
2134                 && (measReportIt->second.cellsTriggeredList.find (cellId)
2135                     != measReportIt->second.cellsTriggeredList.end ());
2136 
2137               // Inequality A3-1 (Entering condition): Mn + Ofn + Ocn - Hys > Mp + Ofp + Ocp + Off
2138               bool entryCond = mn + ofn + ocn - hys > mp + ofp + ocp + off;
2139 
2140               if (entryCond)
2141                 {
2142                   if (!hasTriggered)
2143                     {
2144                       concernedCellsEntry.push_back (cellId);
2145                       eventEntryCondApplicable = true;
2146                     }
2147                 }
2148               else if (reportConfigEutra.timeToTrigger > 0)
2149                 {
2150                   CancelEnteringTrigger (measId, cellId);
2151                 }
2152 
2153               // Inequality A3-2 (Leaving condition): Mn + Ofn + Ocn + Hys < Mp + Ofp + Ocp + Off
2154               bool leavingCond = mn + ofn + ocn + hys < mp + ofp + ocp + off;
2155 
2156               if (leavingCond)
2157                 {
2158                   if (hasTriggered)
2159                     {
2160                       concernedCellsLeaving.push_back (cellId);
2161                       eventLeavingCondApplicable = true;
2162                     }
2163                 }
2164               else if (reportConfigEutra.timeToTrigger > 0)
2165                 {
2166                   CancelLeavingTrigger (measId, cellId);
2167                 }
2168 
2169               NS_LOG_LOGIC (this << " event A3: neighbor cell " << cellId
2170                                  << " mn=" << mn << " mp=" << mp << " offset=" << off
2171                                  << " entryCond=" << entryCond
2172                                  << " leavingCond=" << leavingCond);
2173 
2174             } // end of for (storedMeasIt)
2175 
2176         } // end of case LteRrcSap::ReportConfigEutra::EVENT_A3
2177 
2178         break;
2179 
2180       case LteRrcSap::ReportConfigEutra::EVENT_A4:
2181         {
2182           /*
2183            * Event A4 (Neighbour becomes better than threshold)
2184            * Please refer to 3GPP TS 36.331 Section 5.5.4.5
2185            */
2186 
2187           double mn; // Mn, the measurement result of the neighbouring cell
2188           double ofn = measObjectEutra.offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2189           double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2190           double thresh; // Thresh, the threshold parameter for this event
2191           // Hys, the hysteresis parameter for this event.
2192           double hys = EutranMeasurementMapping::IeValue2ActualHysteresis (reportConfigEutra.hysteresis);
2193 
2194           switch (reportConfigEutra.triggerQuantity)
2195             {
2196               case LteRrcSap::ReportConfigEutra::RSRP:
2197                 NS_ASSERT (reportConfigEutra.threshold1.choice
2198                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRP);
2199                 thresh = EutranMeasurementMapping::RsrpRange2Dbm (reportConfigEutra.threshold1.range);
2200                 break;
2201               case LteRrcSap::ReportConfigEutra::RSRQ:
2202                 NS_ASSERT (reportConfigEutra.threshold1.choice
2203                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ);
2204                 thresh = EutranMeasurementMapping::RsrqRange2Db (reportConfigEutra.threshold1.range);
2205                 break;
2206               default:
2207                 NS_FATAL_ERROR ("unsupported triggerQuantity");
2208                 break;
2209             }
2210 
2211           for (std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.begin ();
2212                storedMeasIt != m_storedMeasValues.end ();
2213                ++storedMeasIt)
2214             {
2215               uint16_t cellId = storedMeasIt->first;
2216               if (cellId == m_cellId)
2217                 {
2218                   continue;
2219                 }
2220 
2221               switch (reportConfigEutra.triggerQuantity)
2222                 {
2223                   case LteRrcSap::ReportConfigEutra::RSRP:
2224                     mn = storedMeasIt->second.rsrp;
2225                     break;
2226                   case LteRrcSap::ReportConfigEutra::RSRQ:
2227                     mn = storedMeasIt->second.rsrq;
2228                     break;
2229                   default:
2230                     NS_FATAL_ERROR ("unsupported triggerQuantity");
2231                     break;
2232                 }
2233 
2234               bool hasTriggered = isMeasIdInReportList
2235                 && (measReportIt->second.cellsTriggeredList.find (cellId)
2236                     != measReportIt->second.cellsTriggeredList.end ());
2237 
2238               // Inequality A4-1 (Entering condition): Mn + Ofn + Ocn - Hys > Thresh
2239               bool entryCond = mn + ofn + ocn - hys > thresh;
2240 
2241               if (entryCond)
2242                 {
2243                   if (!hasTriggered)
2244                     {
2245                       concernedCellsEntry.push_back (cellId);
2246                       eventEntryCondApplicable = true;
2247                     }
2248                 }
2249               else if (reportConfigEutra.timeToTrigger > 0)
2250                 {
2251                   CancelEnteringTrigger (measId, cellId);
2252                 }
2253 
2254               // Inequality A4-2 (Leaving condition): Mn + Ofn + Ocn + Hys < Thresh
2255               bool leavingCond = mn + ofn + ocn + hys < thresh;
2256 
2257               if (leavingCond)
2258                 {
2259                   if (hasTriggered)
2260                     {
2261                       concernedCellsLeaving.push_back (cellId);
2262                       eventLeavingCondApplicable = true;
2263                     }
2264                 }
2265               else if (reportConfigEutra.timeToTrigger > 0)
2266                 {
2267                   CancelLeavingTrigger (measId, cellId);
2268                 }
2269 
2270               NS_LOG_LOGIC (this << " event A4: neighbor cell " << cellId
2271                                  << " mn=" << mn << " thresh=" << thresh
2272                                  << " entryCond=" << entryCond
2273                                  << " leavingCond=" << leavingCond);
2274 
2275             } // end of for (storedMeasIt)
2276 
2277         } // end of case LteRrcSap::ReportConfigEutra::EVENT_A4
2278 
2279         break;
2280 
2281       case LteRrcSap::ReportConfigEutra::EVENT_A5:
2282         {
2283           /*
2284            * Event A5 (PCell becomes worse than threshold1 and neighbour
2285            * becomes better than threshold2)
2286            * Please refer to 3GPP TS 36.331 Section 5.5.4.6
2287            */
2288 
2289           double mp; // Mp, the measurement result of the PCell
2290           double mn; // Mn, the measurement result of the neighbouring cell
2291           double ofn = measObjectEutra.offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2292           double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2293           double thresh1; // Thresh1, the threshold parameter for this event
2294           double thresh2; // Thresh2, the threshold parameter for this event
2295           // Hys, the hysteresis parameter for this event.
2296           double hys = EutranMeasurementMapping::IeValue2ActualHysteresis (reportConfigEutra.hysteresis);
2297 
2298           switch (reportConfigEutra.triggerQuantity)
2299             {
2300               case LteRrcSap::ReportConfigEutra::RSRP:
2301                 mp = m_storedMeasValues[m_cellId].rsrp;
2302                 NS_ASSERT (reportConfigEutra.threshold1.choice
2303                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRP);
2304                 NS_ASSERT (reportConfigEutra.threshold2.choice
2305                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRP);
2306                 thresh1 = EutranMeasurementMapping::RsrpRange2Dbm (reportConfigEutra.threshold1.range);
2307                 thresh2 = EutranMeasurementMapping::RsrpRange2Dbm (reportConfigEutra.threshold2.range);
2308                 break;
2309               case LteRrcSap::ReportConfigEutra::RSRQ:
2310                 mp = m_storedMeasValues[m_cellId].rsrq;
2311                 NS_ASSERT (reportConfigEutra.threshold1.choice
2312                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ);
2313                 NS_ASSERT (reportConfigEutra.threshold2.choice
2314                            == LteRrcSap::ThresholdEutra::THRESHOLD_RSRQ);
2315                 thresh1 = EutranMeasurementMapping::RsrqRange2Db (reportConfigEutra.threshold1.range);
2316                 thresh2 = EutranMeasurementMapping::RsrqRange2Db (reportConfigEutra.threshold2.range);
2317                 break;
2318               default:
2319                 NS_FATAL_ERROR ("unsupported triggerQuantity");
2320                 break;
2321             }
2322 
2323           // Inequality A5-1 (Entering condition 1): Mp + Hys < Thresh1
2324           bool entryCond = mp + hys < thresh1;
2325 
2326           if (entryCond)
2327             {
2328               for (std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.begin ();
2329                    storedMeasIt != m_storedMeasValues.end ();
2330                    ++storedMeasIt)
2331                 {
2332                   uint16_t cellId = storedMeasIt->first;
2333                   if (cellId == m_cellId)
2334                     {
2335                       continue;
2336                     }
2337 
2338                   switch (reportConfigEutra.triggerQuantity)
2339                     {
2340                       case LteRrcSap::ReportConfigEutra::RSRP:
2341                         mn = storedMeasIt->second.rsrp;
2342                         break;
2343                       case LteRrcSap::ReportConfigEutra::RSRQ:
2344                         mn = storedMeasIt->second.rsrq;
2345                         break;
2346                       default:
2347                         NS_FATAL_ERROR ("unsupported triggerQuantity");
2348                         break;
2349                     }
2350 
2351                   bool hasTriggered = isMeasIdInReportList
2352                     && (measReportIt->second.cellsTriggeredList.find (cellId)
2353                         != measReportIt->second.cellsTriggeredList.end ());
2354 
2355                   // Inequality A5-2 (Entering condition 2): Mn + Ofn + Ocn - Hys > Thresh2
2356 
2357                   entryCond = mn + ofn + ocn - hys > thresh2;
2358 
2359                   if (entryCond)
2360                     {
2361                       if (!hasTriggered)
2362                         {
2363                           concernedCellsEntry.push_back (cellId);
2364                           eventEntryCondApplicable = true;
2365                         }
2366                     }
2367                   else if (reportConfigEutra.timeToTrigger > 0)
2368                     {
2369                       CancelEnteringTrigger (measId, cellId);
2370                     }
2371 
2372                   NS_LOG_LOGIC (this << " event A5: neighbor cell " << cellId
2373                                      << " mn=" << mn << " mp=" << mp
2374                                      << " thresh2=" << thresh2
2375                                      << " thresh1=" << thresh1
2376                                      << " entryCond=" << entryCond);
2377 
2378                 } // end of for (storedMeasIt)
2379 
2380             } // end of if (entryCond)
2381           else
2382             {
2383               NS_LOG_LOGIC (this << " event A5: serving cell " << m_cellId
2384                                  << " mp=" << mp << " thresh1=" << thresh1
2385                                  << " entryCond=" << entryCond);
2386 
2387               if (reportConfigEutra.timeToTrigger > 0)
2388                 {
2389                   CancelEnteringTrigger (measId);
2390                 }
2391             }
2392 
2393           if (isMeasIdInReportList)
2394             {
2395               // Inequality A5-3 (Leaving condition 1): Mp - Hys > Thresh1
2396               bool leavingCond = mp - hys > thresh1;
2397 
2398               if (leavingCond)
2399                 {
2400                   if (reportConfigEutra.timeToTrigger == 0)
2401                     {
2402                       // leaving condition #2 does not have to be checked
2403 
2404                       for (std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.begin ();
2405                            storedMeasIt != m_storedMeasValues.end ();
2406                            ++storedMeasIt)
2407                         {
2408                           uint16_t cellId = storedMeasIt->first;
2409                           if (cellId == m_cellId)
2410                             {
2411                               continue;
2412                             }
2413 
2414                           if (measReportIt->second.cellsTriggeredList.find (cellId)
2415                               != measReportIt->second.cellsTriggeredList.end ())
2416                             {
2417                               concernedCellsLeaving.push_back (cellId);
2418                               eventLeavingCondApplicable = true;
2419                             }
2420                         }
2421                     } // end of if (reportConfigEutra.timeToTrigger == 0)
2422                   else
2423                     {
2424                       // leaving condition #2 has to be checked to cancel time-to-trigger
2425 
2426                       for (std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.begin ();
2427                            storedMeasIt != m_storedMeasValues.end ();
2428                            ++storedMeasIt)
2429                         {
2430                           uint16_t cellId = storedMeasIt->first;
2431                           if (cellId == m_cellId)
2432                             {
2433                               continue;
2434                             }
2435 
2436                           if (measReportIt->second.cellsTriggeredList.find (cellId)
2437                               != measReportIt->second.cellsTriggeredList.end ())
2438                             {
2439                               switch (reportConfigEutra.triggerQuantity)
2440                                 {
2441                                   case LteRrcSap::ReportConfigEutra::RSRP:
2442                                     mn = storedMeasIt->second.rsrp;
2443                                     break;
2444                                   case LteRrcSap::ReportConfigEutra::RSRQ:
2445                                     mn = storedMeasIt->second.rsrq;
2446                                     break;
2447                                   default:
2448                                     NS_FATAL_ERROR ("unsupported triggerQuantity");
2449                                     break;
2450                                 }
2451 
2452                               // Inequality A5-4 (Leaving condition 2): Mn + Ofn + Ocn + Hys < Thresh2
2453 
2454                               leavingCond = mn + ofn + ocn + hys < thresh2;
2455 
2456                               if (!leavingCond)
2457                                 {
2458                                   CancelLeavingTrigger (measId, cellId);
2459                                 }
2460 
2461                               /*
2462                                * Whatever the result of leaving condition #2, this
2463                                * cell is still "in", because leaving condition #1
2464                                * is already true.
2465                                */
2466                               concernedCellsLeaving.push_back (cellId);
2467                               eventLeavingCondApplicable = true;
2468 
2469                               NS_LOG_LOGIC (this << " event A5: neighbor cell " << cellId
2470                                                  << " mn=" << mn << " mp=" << mp
2471                                                  << " thresh2=" << thresh2
2472                                                  << " thresh1=" << thresh1
2473                                                  << " leavingCond=" << leavingCond);
2474 
2475                             } // end of if (measReportIt->second.cellsTriggeredList.find (cellId)
2476                               //            != measReportIt->second.cellsTriggeredList.end ())
2477 
2478                         } // end of for (storedMeasIt)
2479 
2480                     } // end of else of if (reportConfigEutra.timeToTrigger == 0)
2481 
2482                   NS_LOG_LOGIC (this << " event A5: serving cell " << m_cellId
2483                                      << " mp=" << mp << " thresh1=" << thresh1
2484                                      << " leavingCond=" << leavingCond);
2485 
2486                 } // end of if (leavingCond)
2487               else
2488                 {
2489                   if (reportConfigEutra.timeToTrigger > 0)
2490                     {
2491                       CancelLeavingTrigger (measId);
2492                     }
2493 
2494                   // check leaving condition #2
2495 
2496                   for (std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedMeasValues.begin ();
2497                        storedMeasIt != m_storedMeasValues.end ();
2498                        ++storedMeasIt)
2499                     {
2500                       uint16_t cellId = storedMeasIt->first;
2501                       if (cellId == m_cellId)
2502                         {
2503                           continue;
2504                         }
2505 
2506                       if (measReportIt->second.cellsTriggeredList.find (cellId)
2507                           != measReportIt->second.cellsTriggeredList.end ())
2508                         {
2509                           switch (reportConfigEutra.triggerQuantity)
2510                             {
2511                               case LteRrcSap::ReportConfigEutra::RSRP:
2512                                 mn = storedMeasIt->second.rsrp;
2513                                 break;
2514                               case LteRrcSap::ReportConfigEutra::RSRQ:
2515                                 mn = storedMeasIt->second.rsrq;
2516                                 break;
2517                               default:
2518                                 NS_FATAL_ERROR ("unsupported triggerQuantity");
2519                                 break;
2520                             }
2521 
2522                           // Inequality A5-4 (Leaving condition 2): Mn + Ofn + Ocn + Hys < Thresh2
2523                           leavingCond = mn + ofn + ocn + hys < thresh2;
2524 
2525                           if (leavingCond)
2526                             {
2527                               concernedCellsLeaving.push_back (cellId);
2528                               eventLeavingCondApplicable = true;
2529                             }
2530 
2531                           NS_LOG_LOGIC (this << " event A5: neighbor cell " << cellId
2532                                              << " mn=" << mn << " mp=" << mp
2533                                              << " thresh2=" << thresh2
2534                                              << " thresh1=" << thresh1
2535                                              << " leavingCond=" << leavingCond);
2536 
2537                         } // end of if (measReportIt->second.cellsTriggeredList.find (cellId)
2538                           //            != measReportIt->second.cellsTriggeredList.end ())
2539 
2540                     } // end of for (storedMeasIt)
2541 
2542                 } // end of else of if (leavingCond)
2543 
2544             } // end of if (isMeasIdInReportList)
2545 
2546         } // end of case LteRrcSap::ReportConfigEutra::EVENT_A5
2547 
2548         break;
2549 
2550       default:
2551         NS_FATAL_ERROR ("unsupported eventId " << reportConfigEutra.eventId);
2552         break;
2553 
2554     } // switch (event type)
2555 
2556   NS_LOG_LOGIC (this << " eventEntryCondApplicable=" << eventEntryCondApplicable
2557                      << " eventLeavingCondApplicable=" << eventLeavingCondApplicable);
2558 
2559   if (eventEntryCondApplicable)
2560     {
2561       if (reportConfigEutra.timeToTrigger == 0)
2562         {
2563           VarMeasReportListAdd (measId, concernedCellsEntry);
2564         }
2565       else
2566         {
2567           PendingTrigger_t t;
2568           t.measId = measId;
2569           t.concernedCells = concernedCellsEntry;
2570           t.timer = Simulator::Schedule (MilliSeconds (reportConfigEutra.timeToTrigger),
2571                                          &LteUeRrc::VarMeasReportListAdd, this,
2572                                          measId, concernedCellsEntry);
2573           std::map<uint8_t, std::list<PendingTrigger_t> >::iterator
2574             enteringTriggerIt = m_enteringTriggerQueue.find (measId);
2575           NS_ASSERT (enteringTriggerIt != m_enteringTriggerQueue.end ());
2576           enteringTriggerIt->second.push_back (t);
2577         }
2578     }
2579 
2580   if (eventLeavingCondApplicable)
2581     {
2582       // reportOnLeave will only be set when eventId = eventA3
2583       bool reportOnLeave = (reportConfigEutra.eventId == LteRrcSap::ReportConfigEutra::EVENT_A3)
2584         && reportConfigEutra.reportOnLeave;
2585 
2586       if (reportConfigEutra.timeToTrigger == 0)
2587         {
2588           VarMeasReportListErase (measId, concernedCellsLeaving, reportOnLeave);
2589         }
2590       else
2591         {
2592           PendingTrigger_t t;
2593           t.measId = measId;
2594           t.concernedCells = concernedCellsLeaving;
2595           t.timer = Simulator::Schedule (MilliSeconds (reportConfigEutra.timeToTrigger),
2596                                          &LteUeRrc::VarMeasReportListErase, this,
2597                                          measId, concernedCellsLeaving, reportOnLeave);
2598           std::map<uint8_t, std::list<PendingTrigger_t> >::iterator
2599             leavingTriggerIt = m_leavingTriggerQueue.find (measId);
2600           NS_ASSERT (leavingTriggerIt != m_leavingTriggerQueue.end ());
2601           leavingTriggerIt->second.push_back (t);
2602         }
2603     }
2604 
2605 } // end of void LteUeRrc::MeasurementReportTriggering (uint8_t measId)
2606 
2607 void
CancelEnteringTrigger(uint8_t measId)2608 LteUeRrc::CancelEnteringTrigger (uint8_t measId)
2609 {
2610   NS_LOG_FUNCTION (this << (uint16_t) measId);
2611 
2612   std::map<uint8_t, std::list<PendingTrigger_t> >::iterator
2613     it1 = m_enteringTriggerQueue.find (measId);
2614   NS_ASSERT (it1 != m_enteringTriggerQueue.end ());
2615 
2616   if (!it1->second.empty ())
2617     {
2618       std::list<PendingTrigger_t>::iterator it2;
2619       for (it2 = it1->second.begin (); it2 != it1->second.end (); ++it2)
2620         {
2621           NS_ASSERT (it2->measId == measId);
2622           NS_LOG_LOGIC (this << " canceling entering time-to-trigger event at "
2623                              << Simulator::GetDelayLeft (it2->timer).GetSeconds ());
2624           Simulator::Cancel (it2->timer);
2625         }
2626 
2627       it1->second.clear ();
2628     }
2629 }
2630 
2631 void
CancelEnteringTrigger(uint8_t measId,uint16_t cellId)2632 LteUeRrc::CancelEnteringTrigger (uint8_t measId, uint16_t cellId)
2633 {
2634   NS_LOG_FUNCTION (this << (uint16_t) measId << cellId);
2635 
2636   std::map<uint8_t, std::list<PendingTrigger_t> >::iterator
2637     it1 = m_enteringTriggerQueue.find (measId);
2638   NS_ASSERT (it1 != m_enteringTriggerQueue.end ());
2639 
2640   std::list<PendingTrigger_t>::iterator it2 = it1->second.begin ();
2641   while (it2 != it1->second.end ())
2642     {
2643       NS_ASSERT (it2->measId == measId);
2644 
2645       ConcernedCells_t::iterator it3;
2646       for (it3 = it2->concernedCells.begin ();
2647            it3 != it2->concernedCells.end (); ++it3)
2648         {
2649           if (*it3 == cellId)
2650             {
2651               it3 = it2->concernedCells.erase (it3);
2652             }
2653         }
2654 
2655       if (it2->concernedCells.empty ())
2656         {
2657           NS_LOG_LOGIC (this << " canceling entering time-to-trigger event at "
2658                              << Simulator::GetDelayLeft (it2->timer).GetSeconds ());
2659           Simulator::Cancel (it2->timer);
2660           it2 = it1->second.erase (it2);
2661         }
2662       else
2663         {
2664           it2++;
2665         }
2666     }
2667 }
2668 
2669 void
CancelLeavingTrigger(uint8_t measId)2670 LteUeRrc::CancelLeavingTrigger (uint8_t measId)
2671 {
2672   NS_LOG_FUNCTION (this << (uint16_t) measId);
2673 
2674   std::map<uint8_t, std::list<PendingTrigger_t> >::iterator
2675     it1 = m_leavingTriggerQueue.find (measId);
2676   NS_ASSERT (it1 != m_leavingTriggerQueue.end ());
2677 
2678   if (!it1->second.empty ())
2679     {
2680       std::list<PendingTrigger_t>::iterator it2;
2681       for (it2 = it1->second.begin (); it2 != it1->second.end (); ++it2)
2682         {
2683           NS_ASSERT (it2->measId == measId);
2684           NS_LOG_LOGIC (this << " canceling leaving time-to-trigger event at "
2685                              << Simulator::GetDelayLeft (it2->timer).GetSeconds ());
2686           Simulator::Cancel (it2->timer);
2687         }
2688 
2689       it1->second.clear ();
2690     }
2691 }
2692 
2693 void
CancelLeavingTrigger(uint8_t measId,uint16_t cellId)2694 LteUeRrc::CancelLeavingTrigger (uint8_t measId, uint16_t cellId)
2695 {
2696   NS_LOG_FUNCTION (this << (uint16_t) measId << cellId);
2697 
2698   std::map<uint8_t, std::list<PendingTrigger_t> >::iterator
2699     it1 = m_leavingTriggerQueue.find (measId);
2700   NS_ASSERT (it1 != m_leavingTriggerQueue.end ());
2701 
2702   std::list<PendingTrigger_t>::iterator it2 = it1->second.begin ();
2703   while (it2 != it1->second.end ())
2704     {
2705       NS_ASSERT (it2->measId == measId);
2706 
2707       ConcernedCells_t::iterator it3;
2708       for (it3 = it2->concernedCells.begin ();
2709            it3 != it2->concernedCells.end (); ++it3)
2710         {
2711           if (*it3 == cellId)
2712             {
2713               it3 = it2->concernedCells.erase (it3);
2714             }
2715         }
2716 
2717       if (it2->concernedCells.empty ())
2718         {
2719           NS_LOG_LOGIC (this << " canceling leaving time-to-trigger event at "
2720                              << Simulator::GetDelayLeft (it2->timer).GetSeconds ());
2721           Simulator::Cancel (it2->timer);
2722           it2 = it1->second.erase (it2);
2723         }
2724       else
2725         {
2726           it2++;
2727         }
2728     }
2729 }
2730 
2731 void
VarMeasReportListAdd(uint8_t measId,ConcernedCells_t enteringCells)2732 LteUeRrc::VarMeasReportListAdd (uint8_t measId, ConcernedCells_t enteringCells)
2733 {
2734   NS_LOG_FUNCTION (this << (uint16_t) measId);
2735   NS_ASSERT (!enteringCells.empty ());
2736 
2737   std::map<uint8_t, VarMeasReport>::iterator
2738     measReportIt = m_varMeasReportList.find (measId);
2739 
2740   if (measReportIt == m_varMeasReportList.end ())
2741     {
2742       VarMeasReport r;
2743       r.measId = measId;
2744       std::pair<uint8_t, VarMeasReport> val (measId, r);
2745       std::pair<std::map<uint8_t, VarMeasReport>::iterator, bool>
2746       ret = m_varMeasReportList.insert (val);
2747       NS_ASSERT_MSG (ret.second == true, "element already existed");
2748       measReportIt = ret.first;
2749     }
2750 
2751   NS_ASSERT (measReportIt != m_varMeasReportList.end ());
2752 
2753   for (ConcernedCells_t::const_iterator it = enteringCells.begin ();
2754        it != enteringCells.end ();
2755        ++it)
2756     {
2757       measReportIt->second.cellsTriggeredList.insert (*it);
2758     }
2759 
2760   NS_ASSERT (!measReportIt->second.cellsTriggeredList.empty ());
2761 
2762   // #issue 224, schedule only when there is no periodic event scheduled already
2763   if (!measReportIt->second.periodicReportTimer.IsRunning ())
2764     {
2765       measReportIt->second.numberOfReportsSent = 0;
2766       measReportIt->second.periodicReportTimer
2767         = Simulator::Schedule (UE_MEASUREMENT_REPORT_DELAY,
2768                                &LteUeRrc::SendMeasurementReport,
2769                                this, measId);
2770     }
2771 
2772   std::map<uint8_t, std::list<PendingTrigger_t> >::iterator
2773     enteringTriggerIt = m_enteringTriggerQueue.find (measId);
2774   NS_ASSERT (enteringTriggerIt != m_enteringTriggerQueue.end ());
2775   if (!enteringTriggerIt->second.empty ())
2776     {
2777       /*
2778        * Assumptions at this point:
2779        *  - the call to this function was delayed by time-to-trigger;
2780        *  - the time-to-trigger delay is fixed (not adaptive/dynamic); and
2781        *  - the first element in the list is associated with this function call.
2782        */
2783       enteringTriggerIt->second.pop_front ();
2784 
2785       if (!enteringTriggerIt->second.empty ())
2786         {
2787           /*
2788            * To prevent the same set of cells triggering again in the future,
2789            * we clean up the time-to-trigger queue. This case might occur when
2790            * time-to-trigger > 200 ms.
2791            */
2792           for (ConcernedCells_t::const_iterator it = enteringCells.begin ();
2793                it != enteringCells.end (); ++it)
2794             {
2795               CancelEnteringTrigger (measId, *it);
2796             }
2797         }
2798 
2799     } // end of if (!enteringTriggerIt->second.empty ())
2800 
2801 } // end of LteUeRrc::VarMeasReportListAdd
2802 
2803 void
VarMeasReportListErase(uint8_t measId,ConcernedCells_t leavingCells,bool reportOnLeave)2804 LteUeRrc::VarMeasReportListErase (uint8_t measId, ConcernedCells_t leavingCells,
2805                                   bool reportOnLeave)
2806 {
2807   NS_LOG_FUNCTION (this << (uint16_t) measId);
2808   NS_ASSERT (!leavingCells.empty ());
2809 
2810   std::map<uint8_t, VarMeasReport>::iterator
2811     measReportIt = m_varMeasReportList.find (measId);
2812   NS_ASSERT (measReportIt != m_varMeasReportList.end ());
2813 
2814   for (ConcernedCells_t::const_iterator it = leavingCells.begin ();
2815        it != leavingCells.end ();
2816        ++it)
2817     {
2818       measReportIt->second.cellsTriggeredList.erase (*it);
2819     }
2820 
2821   if (reportOnLeave)
2822     {
2823       // runs immediately without UE_MEASUREMENT_REPORT_DELAY
2824       SendMeasurementReport (measId);
2825     }
2826 
2827   if (measReportIt->second.cellsTriggeredList.empty ())
2828     {
2829       measReportIt->second.periodicReportTimer.Cancel ();
2830       m_varMeasReportList.erase (measReportIt);
2831     }
2832 
2833   std::map<uint8_t, std::list<PendingTrigger_t> >::iterator
2834     leavingTriggerIt = m_leavingTriggerQueue.find (measId);
2835   NS_ASSERT (leavingTriggerIt != m_leavingTriggerQueue.end ());
2836   if (!leavingTriggerIt->second.empty ())
2837     {
2838       /*
2839        * Assumptions at this point:
2840        *  - the call to this function was delayed by time-to-trigger; and
2841        *  - the time-to-trigger delay is fixed (not adaptive/dynamic); and
2842        *  - the first element in the list is associated with this function call.
2843        */
2844       leavingTriggerIt->second.pop_front ();
2845 
2846       if (!leavingTriggerIt->second.empty ())
2847         {
2848           /*
2849            * To prevent the same set of cells triggering again in the future,
2850            * we clean up the time-to-trigger queue. This case might occur when
2851            * time-to-trigger > 200 ms.
2852            */
2853           for (ConcernedCells_t::const_iterator it = leavingCells.begin ();
2854                it != leavingCells.end (); ++it)
2855             {
2856               CancelLeavingTrigger (measId, *it);
2857             }
2858         }
2859 
2860     } // end of if (!leavingTriggerIt->second.empty ())
2861 
2862 } // end of LteUeRrc::VarMeasReportListErase
2863 
2864 void
VarMeasReportListClear(uint8_t measId)2865 LteUeRrc::VarMeasReportListClear (uint8_t measId)
2866 {
2867   NS_LOG_FUNCTION (this << (uint16_t) measId);
2868 
2869   // remove the measurement reporting entry for this measId from the VarMeasReportList
2870   std::map<uint8_t, VarMeasReport>::iterator
2871     measReportIt = m_varMeasReportList.find (measId);
2872   if (measReportIt != m_varMeasReportList.end ())
2873     {
2874       NS_LOG_LOGIC (this << " deleting existing report for measId " << (uint16_t) measId);
2875       measReportIt->second.periodicReportTimer.Cancel ();
2876       m_varMeasReportList.erase (measReportIt);
2877     }
2878 
2879   CancelEnteringTrigger (measId);
2880   CancelLeavingTrigger (measId);
2881 }
2882 
2883 void
SendMeasurementReport(uint8_t measId)2884 LteUeRrc::SendMeasurementReport (uint8_t measId)
2885 {
2886   NS_LOG_FUNCTION (this << (uint16_t) measId);
2887   //  3GPP TS 36.331 section 5.5.5 Measurement reporting
2888 
2889   std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator
2890     measIdIt = m_varMeasConfig.measIdList.find (measId);
2891   NS_ASSERT (measIdIt != m_varMeasConfig.measIdList.end ());
2892 
2893   std::map<uint8_t, LteRrcSap::ReportConfigToAddMod>::iterator
2894     reportConfigIt = m_varMeasConfig.reportConfigList.find (measIdIt->second.reportConfigId);
2895   NS_ASSERT (reportConfigIt != m_varMeasConfig.reportConfigList.end ());
2896   LteRrcSap::ReportConfigEutra& reportConfigEutra = reportConfigIt->second.reportConfigEutra;
2897 
2898   LteRrcSap::MeasurementReport measurementReport;
2899   LteRrcSap::MeasResults& measResults = measurementReport.measResults;
2900   measResults.measId = measId;
2901 
2902   std::map<uint16_t, MeasValues>::iterator servingMeasIt = m_storedMeasValues.find (m_cellId);
2903   NS_ASSERT (servingMeasIt != m_storedMeasValues.end ());
2904   measResults.rsrpResult = EutranMeasurementMapping::Dbm2RsrpRange (servingMeasIt->second.rsrp);
2905   measResults.rsrqResult = EutranMeasurementMapping::Db2RsrqRange (servingMeasIt->second.rsrq);
2906   NS_LOG_INFO (this << " reporting serving cell "
2907                "RSRP " << (uint32_t) measResults.rsrpResult << " (" << servingMeasIt->second.rsrp << " dBm) "
2908                "RSRQ " << (uint32_t) measResults.rsrqResult << " (" << servingMeasIt->second.rsrq << " dB)");
2909   measResults.haveMeasResultNeighCells = false;
2910   std::map<uint8_t, VarMeasReport>::iterator measReportIt = m_varMeasReportList.find (measId);
2911   if (measReportIt == m_varMeasReportList.end ())
2912     {
2913       NS_LOG_ERROR ("no entry found in m_varMeasReportList for measId " << (uint32_t) measId);
2914     }
2915   else
2916     {
2917       if (!(measReportIt->second.cellsTriggeredList.empty ()))
2918         {
2919           std::multimap<double, uint16_t> sortedNeighCells;
2920           for (std::set<uint16_t>::iterator cellsTriggeredIt = measReportIt->second.cellsTriggeredList.begin ();
2921                cellsTriggeredIt != measReportIt->second.cellsTriggeredList.end ();
2922                ++cellsTriggeredIt)
2923             {
2924               uint16_t cellId = *cellsTriggeredIt;
2925               if (cellId != m_cellId)
2926                 {
2927                   std::map<uint16_t, MeasValues>::iterator neighborMeasIt = m_storedMeasValues.find (cellId);
2928                   double triggerValue;
2929                   switch (reportConfigEutra.triggerQuantity)
2930                     {
2931                       case LteRrcSap::ReportConfigEutra::RSRP:
2932                         triggerValue = neighborMeasIt->second.rsrp;
2933                         break;
2934                       case LteRrcSap::ReportConfigEutra::RSRQ:
2935                         triggerValue = neighborMeasIt->second.rsrq;
2936                         break;
2937                       default:
2938                         NS_FATAL_ERROR ("unsupported triggerQuantity");
2939                         break;
2940                     }
2941                   sortedNeighCells.insert (std::pair<double, uint16_t> (triggerValue, cellId));
2942                 }
2943             }
2944 
2945           std::multimap<double, uint16_t>::reverse_iterator sortedNeighCellsIt;
2946           uint32_t count;
2947           for (sortedNeighCellsIt = sortedNeighCells.rbegin (), count = 0;
2948                sortedNeighCellsIt != sortedNeighCells.rend () && count < reportConfigEutra.maxReportCells;
2949                ++sortedNeighCellsIt, ++count)
2950             {
2951               uint16_t cellId = sortedNeighCellsIt->second;
2952               std::map<uint16_t, MeasValues>::iterator neighborMeasIt = m_storedMeasValues.find (cellId);
2953               NS_ASSERT (neighborMeasIt != m_storedMeasValues.end ());
2954               LteRrcSap::MeasResultEutra measResultEutra;
2955               measResultEutra.physCellId = cellId;
2956               measResultEutra.haveCgiInfo = false;
2957               measResultEutra.haveRsrpResult = true;
2958               measResultEutra.rsrpResult = EutranMeasurementMapping::Dbm2RsrpRange (neighborMeasIt->second.rsrp);
2959               measResultEutra.haveRsrqResult = true;
2960               measResultEutra.rsrqResult = EutranMeasurementMapping::Db2RsrqRange (neighborMeasIt->second.rsrq);
2961               NS_LOG_INFO (this << " reporting neighbor cell " << (uint32_t) measResultEutra.physCellId
2962                                 << " RSRP " << (uint32_t) measResultEutra.rsrpResult
2963                                 << " (" << neighborMeasIt->second.rsrp << " dBm)"
2964                                 << " RSRQ " << (uint32_t) measResultEutra.rsrqResult
2965                                 << " (" << neighborMeasIt->second.rsrq << " dB)");
2966               measResults.measResultListEutra.push_back (measResultEutra);
2967               measResults.haveMeasResultNeighCells = true;
2968             }
2969         }
2970       else
2971         {
2972           NS_LOG_WARN (this << " cellsTriggeredList is empty");
2973         }
2974 
2975       measResults.haveScellsMeas = false;
2976       std::map<uint16_t, MeasValues>::iterator sCellsMeasIt =  m_storedScellMeasValues.begin ();
2977       if (sCellsMeasIt != m_storedScellMeasValues.end ())
2978         {
2979           measResults.haveScellsMeas = true;
2980           measResults.measScellResultList.haveMeasurementResultsServingSCells = true;
2981           measResults.measScellResultList.haveMeasurementResultsNeighCell = false;
2982 
2983 
2984           for ( sCellsMeasIt = m_storedScellMeasValues.begin ();
2985                 sCellsMeasIt != m_storedScellMeasValues.end (); ++sCellsMeasIt)
2986             {
2987               LteRrcSap::MeasResultScell measResultScell;
2988               measResultScell.servFreqId = sCellsMeasIt->first;
2989               measResultScell.haveRsrpResult =  true;
2990               measResultScell.haveRsrqResult =  true;
2991               measResultScell.rsrpResult = EutranMeasurementMapping::Dbm2RsrpRange (sCellsMeasIt->second.rsrp);
2992               measResultScell.rsrqResult = EutranMeasurementMapping::Db2RsrqRange (sCellsMeasIt->second.rsrq);
2993               measResults.measScellResultList.measResultScell.push_back (measResultScell);
2994             }
2995         }
2996 
2997       /*
2998        * The current LteRrcSap implementation is broken in that it does not
2999        * allow for infinite values of reportAmount, which is probably the most
3000        * reasonable setting. So we just always assume infinite reportAmount.
3001        */
3002       measReportIt->second.numberOfReportsSent++;
3003       measReportIt->second.periodicReportTimer.Cancel ();
3004 
3005       Time reportInterval;
3006       switch (reportConfigEutra.reportInterval)
3007         {
3008           case LteRrcSap::ReportConfigEutra::MS120:
3009             reportInterval = MilliSeconds (120);
3010             break;
3011           case LteRrcSap::ReportConfigEutra::MS240:
3012             reportInterval = MilliSeconds (240);
3013             break;
3014           case LteRrcSap::ReportConfigEutra::MS480:
3015             reportInterval = MilliSeconds (480);
3016             break;
3017           case LteRrcSap::ReportConfigEutra::MS640:
3018             reportInterval = MilliSeconds (640);
3019             break;
3020           case LteRrcSap::ReportConfigEutra::MS1024:
3021             reportInterval = MilliSeconds (1024);
3022             break;
3023           case LteRrcSap::ReportConfigEutra::MS2048:
3024             reportInterval = MilliSeconds (2048);
3025             break;
3026           case LteRrcSap::ReportConfigEutra::MS5120:
3027             reportInterval = MilliSeconds (5120);
3028             break;
3029           case LteRrcSap::ReportConfigEutra::MS10240:
3030             reportInterval = MilliSeconds (10240);
3031             break;
3032           case LteRrcSap::ReportConfigEutra::MIN1:
3033             reportInterval = Seconds (60);
3034             break;
3035           case LteRrcSap::ReportConfigEutra::MIN6:
3036             reportInterval = Seconds (360);
3037             break;
3038           case LteRrcSap::ReportConfigEutra::MIN12:
3039             reportInterval = Seconds (720);
3040             break;
3041           case LteRrcSap::ReportConfigEutra::MIN30:
3042             reportInterval = Seconds (1800);
3043             break;
3044           case LteRrcSap::ReportConfigEutra::MIN60:
3045             reportInterval = Seconds (3600);
3046             break;
3047           default:
3048             NS_FATAL_ERROR ("Unsupported reportInterval " << (uint16_t) reportConfigEutra.reportInterval);
3049             break;
3050         }
3051 
3052       // schedule the next measurement reporting
3053       measReportIt->second.periodicReportTimer
3054         = Simulator::Schedule (reportInterval,
3055                                &LteUeRrc::SendMeasurementReport,
3056                                this, measId);
3057 
3058       // send the measurement report to eNodeB
3059       m_rrcSapUser->SendMeasurementReport (measurementReport);
3060     }
3061 }
3062 
3063 void
StartConnection()3064 LteUeRrc::StartConnection ()
3065 {
3066   NS_LOG_FUNCTION (this << m_imsi);
3067   NS_ASSERT (m_hasReceivedMib);
3068   NS_ASSERT (m_hasReceivedSib2);
3069   m_connectionPending = false; // reset the flag
3070   SwitchToState (IDLE_RANDOM_ACCESS);
3071   m_cmacSapProvider.at (0)->StartContentionBasedRandomAccessProcedure ();
3072 }
3073 
3074 void
LeaveConnectedMode()3075 LteUeRrc::LeaveConnectedMode ()
3076 {
3077   NS_LOG_FUNCTION (this << m_imsi);
3078   m_leaveConnectedMode = true;
3079   m_storedMeasValues.clear ();
3080   ResetRlfParams ();
3081 
3082   std::map<uint8_t, LteRrcSap::MeasIdToAddMod>::iterator measIdIt;
3083   for (measIdIt = m_varMeasConfig.measIdList.begin ();
3084        measIdIt != m_varMeasConfig.measIdList.end (); ++measIdIt)
3085     {
3086       VarMeasReportListClear (measIdIt->second.measId);
3087     }
3088   m_varMeasConfig.measIdList.clear ();
3089 
3090   m_ccmRrcSapProvider->Reset ();
3091 
3092   for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
3093     {
3094       m_cmacSapProvider.at (i)->Reset ();  // reset the MAC
3095     }
3096 
3097   m_drbMap.clear ();
3098   m_bid2DrbidMap.clear ();
3099   m_srb1 = nullptr;
3100   m_hasReceivedMib = false;
3101   m_hasReceivedSib1 = false;
3102   m_hasReceivedSib2 = false;
3103 
3104   for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
3105     {
3106       m_cphySapProvider.at (i)->ResetPhyAfterRlf ();  //reset the PHY
3107     }
3108   SwitchToState (IDLE_START);
3109   DoStartCellSelection (m_dlEarfcn);
3110   //Save the cell id UE was attached to
3111   StorePreviousCellId (m_cellId);
3112   m_cellId = 0;
3113   m_rnti = 0;
3114   m_srb0->m_rlc->SetRnti (m_rnti);
3115 }
3116 
3117 void
ConnectionTimeout()3118 LteUeRrc::ConnectionTimeout ()
3119 {
3120   NS_LOG_FUNCTION (this << m_imsi);
3121   ++m_connEstFailCount;
3122   if (m_connEstFailCount >= m_connEstFailCountLimit)
3123     {
3124       m_connectionTimeoutTrace (m_imsi, m_cellId, m_rnti, m_connEstFailCount);
3125       SwitchToState (CONNECTED_PHY_PROBLEM);
3126       //Assumption: The eNB connection request timer would expire
3127       //before the expiration of T300 at UE. Upon which, the eNB deletes
3128       //the UE context. Therefore, here we don't need to send the UE context
3129       //deletion request to the eNB.
3130       m_asSapUser->NotifyConnectionReleased ();
3131       m_connEstFailCount = 0;
3132     }
3133   else
3134     {
3135       for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
3136         {
3137           m_cmacSapProvider.at (i)->Reset ();  // reset the MAC
3138         }
3139       m_hasReceivedSib2 = false;           // invalidate the previously received SIB2
3140       SwitchToState (IDLE_CAMPED_NORMALLY);
3141       m_connectionTimeoutTrace (m_imsi, m_cellId, m_rnti, m_connEstFailCount);
3142       //Following call to UE NAS will force the UE to immediately
3143       //perform the random access to the same cell again.
3144       m_asSapUser->NotifyConnectionFailed ();    // inform upper layer
3145     }
3146 }
3147 
3148 void
DisposeOldSrb1()3149 LteUeRrc::DisposeOldSrb1 ()
3150 {
3151   NS_LOG_FUNCTION (this);
3152   m_srb1Old = 0;
3153 }
3154 
3155 uint8_t
Bid2Drbid(uint8_t bid)3156 LteUeRrc::Bid2Drbid (uint8_t bid)
3157 {
3158   std::map<uint8_t, uint8_t>::iterator it = m_bid2DrbidMap.find (bid);
3159   //NS_ASSERT_MSG (it != m_bid2DrbidMap.end (), "could not find BID " << bid);
3160   if (it == m_bid2DrbidMap.end ())
3161     {
3162       return 0;
3163     }
3164   else
3165     {
3166       return it->second;
3167     }
3168 }
3169 
3170 void
SwitchToState(State newState)3171 LteUeRrc::SwitchToState (State newState)
3172 {
3173   NS_LOG_FUNCTION (this << ToString (newState));
3174   State oldState = m_state;
3175   m_state = newState;
3176   NS_LOG_INFO (this << " IMSI " << m_imsi << " RNTI " << m_rnti << " UeRrc "
3177                     << ToString (oldState) << " --> " << ToString (newState));
3178   m_stateTransitionTrace (m_imsi, m_cellId, m_rnti, oldState, newState);
3179 
3180   switch (newState)
3181     {
3182       case IDLE_START:
3183         if (m_leaveConnectedMode)
3184           {
3185             NS_LOG_INFO ("Starting initial cell selection after RLF");
3186           }
3187         else
3188           {
3189             NS_FATAL_ERROR ("cannot switch to an initial state");
3190           }
3191         break;
3192 
3193       case IDLE_CELL_SEARCH:
3194       case IDLE_WAIT_MIB_SIB1:
3195       case IDLE_WAIT_MIB:
3196       case IDLE_WAIT_SIB1:
3197         break;
3198 
3199       case IDLE_CAMPED_NORMALLY:
3200         if (m_connectionPending)
3201           {
3202             SwitchToState (IDLE_WAIT_SIB2);
3203           }
3204         break;
3205 
3206       case IDLE_WAIT_SIB2:
3207         if (m_hasReceivedSib2)
3208           {
3209             NS_ASSERT (m_connectionPending);
3210             StartConnection ();
3211           }
3212         break;
3213 
3214       case IDLE_RANDOM_ACCESS:
3215       case IDLE_CONNECTING:
3216       case CONNECTED_NORMALLY:
3217       case CONNECTED_HANDOVER:
3218       case CONNECTED_PHY_PROBLEM:
3219       case CONNECTED_REESTABLISHING:
3220         break;
3221 
3222       default:
3223         break;
3224     }
3225 }
3226 
3227 
3228 void
SaveScellUeMeasurements(uint16_t sCellId,double rsrp,double rsrq,bool useLayer3Filtering,uint16_t componentCarrierId)3229 LteUeRrc::SaveScellUeMeasurements (uint16_t sCellId, double rsrp, double rsrq,
3230                                    bool useLayer3Filtering, uint16_t componentCarrierId)
3231 {
3232   NS_LOG_FUNCTION (this << sCellId << componentCarrierId << rsrp << rsrq << useLayer3Filtering);
3233   if (sCellId == m_cellId)
3234     {
3235 
3236       std::map<uint16_t, MeasValues>::iterator storedMeasIt = m_storedScellMeasValues.find (componentCarrierId);
3237 
3238       if (storedMeasIt != m_storedScellMeasValues.end ())
3239         {
3240           if (useLayer3Filtering)
3241             {
3242               // F_n = (1-a) F_{n-1} + a M_n
3243               storedMeasIt->second.rsrp = (1 - m_varMeasConfig.aRsrp) * storedMeasIt->second.rsrp
3244                 + m_varMeasConfig.aRsrp * rsrp;
3245 
3246               if (std::isnan (storedMeasIt->second.rsrq))
3247                 {
3248                   // the previous RSRQ measurements provided UE PHY are invalid
3249                   storedMeasIt->second.rsrq = rsrq;   // replace it with unfiltered value
3250                 }
3251               else
3252                 {
3253                   storedMeasIt->second.rsrq = (1 - m_varMeasConfig.aRsrq) * storedMeasIt->second.rsrq
3254                     + m_varMeasConfig.aRsrq * rsrq;
3255                 }
3256             }
3257           else
3258             {
3259               storedMeasIt->second.rsrp = rsrp;
3260               storedMeasIt->second.rsrq = rsrq;
3261             }
3262         }
3263       else
3264         {
3265           // first value is always unfiltered
3266           MeasValues v;
3267           v.rsrp = rsrp;
3268           v.rsrq = rsrq;
3269           std::pair<uint16_t, MeasValues> val (componentCarrierId, v);
3270           std::pair<std::map<uint16_t, MeasValues>::iterator, bool>
3271           ret = m_storedScellMeasValues.insert (val);
3272           NS_ASSERT_MSG (ret.second == true, "element already existed");
3273           storedMeasIt = ret.first;
3274         }
3275 
3276       NS_LOG_DEBUG (this << " IMSI " << m_imsi << " state " << ToString (m_state)
3277                          << ", measured cell " << sCellId
3278                          << ", carrier component Id " << componentCarrierId
3279                          << ", new RSRP " << rsrp << " stored " << storedMeasIt->second.rsrp
3280                          << ", new RSRQ " << rsrq << " stored " << storedMeasIt->second.rsrq);
3281       storedMeasIt->second.timestamp = Simulator::Now ();
3282     }
3283   else
3284     {
3285       NS_LOG_DEBUG (this << " IMSI " << m_imsi << "measurement on SCC from not serving cell ");
3286     }
3287 
3288 }   // end of void SaveUeMeasurements
3289 
3290 void
RadioLinkFailureDetected()3291 LteUeRrc::RadioLinkFailureDetected ()
3292 {
3293   NS_LOG_FUNCTION (this << m_imsi << m_rnti);
3294   m_radioLinkFailureTrace (m_imsi, m_cellId, m_rnti);
3295   SwitchToState (CONNECTED_PHY_PROBLEM);
3296   m_rrcSapUser->SendIdealUeContextRemoveRequest (m_rnti);
3297   m_asSapUser->NotifyConnectionReleased ();
3298 }
3299 
3300 void
DoNotifyInSync()3301 LteUeRrc::DoNotifyInSync ()
3302 {
3303   NS_LOG_FUNCTION (this << m_imsi);
3304   m_noOfSyncIndications++;
3305   NS_LOG_INFO ("noOfSyncIndications " << (uint16_t) m_noOfSyncIndications);
3306   m_phySyncDetectionTrace (m_imsi, m_rnti, m_cellId, "Notify in sync", m_noOfSyncIndications);
3307   if (m_noOfSyncIndications == m_n311)
3308     {
3309       ResetRlfParams ();
3310     }
3311 }
3312 
3313 void
DoNotifyOutOfSync()3314 LteUeRrc::DoNotifyOutOfSync ()
3315 {
3316   NS_LOG_FUNCTION (this << m_imsi);
3317   m_noOfSyncIndications++;
3318   NS_LOG_INFO (this << " Total Number of Sync indications from PHY "
3319                     << (uint16_t) m_noOfSyncIndications << "N310 value : " << (uint16_t) m_n310);
3320   m_phySyncDetectionTrace (m_imsi, m_rnti, m_cellId, "Notify out of sync", m_noOfSyncIndications);
3321   if (m_noOfSyncIndications == m_n310)
3322     {
3323       m_radioLinkFailureDetected = Simulator::Schedule (m_t310, &LteUeRrc::RadioLinkFailureDetected, this);
3324       if (m_radioLinkFailureDetected.IsRunning ())
3325         {
3326           NS_LOG_INFO ("t310 started");
3327         }
3328       m_cphySapProvider.at (0)->StartInSnycDetection ();
3329       m_noOfSyncIndications = 0;
3330     }
3331 }
3332 
3333 void
DoResetSyncIndicationCounter()3334 LteUeRrc::DoResetSyncIndicationCounter ()
3335 {
3336   NS_LOG_FUNCTION (this << m_imsi);
3337 
3338   NS_LOG_DEBUG ("The number of sync indication received by RRC from PHY: " << (uint16_t) m_noOfSyncIndications);
3339   m_noOfSyncIndications = 0;
3340 }
3341 
3342 void
ResetRlfParams()3343 LteUeRrc::ResetRlfParams ()
3344 {
3345   NS_LOG_FUNCTION (this << m_imsi);
3346   m_radioLinkFailureDetected.Cancel ();
3347   m_noOfSyncIndications = 0;
3348   m_cphySapProvider.at (0)->ResetRlfParams ();
3349 }
3350 
3351 
3352 
3353 } // namespace ns3
3354 
3355