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