A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
lte-ue-rrc.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011, 2012 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3 * Copyright (c) 2018 Fraunhofer ESK : RLF extensions
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Author: Nicola Baldo <nbaldo@cttc.es>
8 * Budiarto Herman <budiarto.herman@magister.fi>
9 * Modified by:
10 * Danilo Abrignani <danilo.abrignani@unibo.it> (Carrier Aggregation - GSoC 2015)
11 * Biljana Bojovic <biljana.bojovic@cttc.es> (Carrier Aggregation)
12 * Vignesh Babu <ns3-dev@esk.fraunhofer.de> (RLF extensions)
13 */
14
15#include "lte-ue-rrc.h"
16
17#include "lte-common.h"
18#include "lte-pdcp.h"
20#include "lte-rlc-am.h"
21#include "lte-rlc-tm.h"
22#include "lte-rlc-um.h"
23#include "lte-rlc.h"
24
25#include "ns3/fatal-error.h"
26#include "ns3/log.h"
27#include "ns3/object-factory.h"
28#include "ns3/object-map.h"
29#include "ns3/simulator.h"
30
31#include <cmath>
32
33namespace ns3
34{
35/**
36 * @brief Artificial delay of UE measurements procedure.
37 *
38 * i.e. the period between the time layer-1-filtered measurements from PHY
39 * layer is received and the earliest time the actual measurement report
40 * submission to the serving cell is invoked.
41 *
42 * This delay exists because of racing condition between several UE measurements
43 * functions which happen to be scheduled at the same time. The delay ensures
44 * that:
45 * - measurements (e.g., layer-3 filtering) are always performed before
46 * reporting, thus the latter always use the latest measured RSRP and RSRQ;
47 * and
48 * - time-to-trigger check is always performed before the reporting, so there
49 * would still be chance for it to cancel the reporting if necessary.
50 */
52
53NS_LOG_COMPONENT_DEFINE("LteUeRrc");
54
55/////////////////////////////
56// CMAC SAP forwarder
57/////////////////////////////
58
59/// UeMemberLteUeCmacSapUser class
61{
62 public:
63 /**
64 * Constructor
65 *
66 * @param rrc the RRC class
67 */
69
70 void SetTemporaryCellRnti(uint16_t rnti) override;
71 void NotifyRandomAccessSuccessful() override;
72 void NotifyRandomAccessFailed() override;
73
74 private:
75 LteUeRrc* m_rrc; ///< the RRC class
76};
77
82
83void
88
89void
94
95void
100
101/////////////////////////////
102// ue RRC methods
103/////////////////////////////
104
106
108 : m_cmacSapProvider(0),
109 m_rrcSapUser(nullptr),
110 m_macSapProvider(nullptr),
111 m_asSapUser(nullptr),
112 m_ccmRrcSapProvider(nullptr),
113 m_state(IDLE_START),
114 m_imsi(0),
115 m_rnti(0),
116 m_cellId(0),
117 m_useRlcSm(true),
118 m_connectionPending(false),
119 m_hasReceivedMib(false),
120 m_hasReceivedSib1(false),
121 m_hasReceivedSib2(false),
122 m_csgWhiteList(0),
123 m_noOfSyncIndications(0),
124 m_leaveConnectedMode(false),
125 m_previousCellId(0),
126 m_connEstFailCountLimit(0),
127 m_connEstFailCount(0),
128 m_numberOfComponentCarriers(MIN_NO_CC)
129{
130 NS_LOG_FUNCTION(this);
132 m_cmacSapUser.push_back(new UeMemberLteUeCmacSapUser(this));
133 m_cphySapProvider.push_back(nullptr);
134 m_cmacSapProvider.push_back(nullptr);
139}
140
145
146void
148{
149 NS_LOG_FUNCTION(this);
150 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
151 {
152 delete m_cphySapUser.at(i);
153 delete m_cmacSapUser.at(i);
154 }
155 m_cphySapUser.clear();
156 m_cmacSapUser.clear();
157 delete m_rrcSapProvider;
158 delete m_drbPdcpSapUser;
159 delete m_asSapProvider;
160 delete m_ccmRrcSapUser;
162 m_cphySapProvider.clear();
164 m_cmacSapProvider.clear();
165 m_drbMap.clear();
166}
167
168TypeId
170{
171 static TypeId tid =
172 TypeId("ns3::LteUeRrc")
173 .SetParent<Object>()
174 .SetGroupName("Lte")
175 .AddConstructor<LteUeRrc>()
176 .AddAttribute("DataRadioBearerMap",
177 "List of UE RadioBearerInfo for Data Radio Bearers by LCID.",
181 .AddAttribute("Srb0",
182 "SignalingRadioBearerInfo for SRB0",
183 PointerValue(),
186 .AddAttribute("Srb1",
187 "SignalingRadioBearerInfo for SRB1",
188 PointerValue(),
191 .AddAttribute("CellId",
192 "Serving cell identifier",
193 UintegerValue(0), // unused, read-only attribute
196 .AddAttribute("C-RNTI",
197 "Cell Radio Network Temporary Identifier",
198 UintegerValue(0), // unused, read-only attribute
201 .AddAttribute(
202 "T300",
203 "Timer for the RRC Connection Establishment procedure "
204 "(i.e., the procedure is deemed as failed if it takes longer than this). "
205 "Standard values: 100ms, 200ms, 300ms, 400ms, 600ms, 1000ms, 1500ms, 2000ms",
207 100)), // see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
210 .AddAttribute(
211 "T310",
212 "Timer for detecting the Radio link failure "
213 "(i.e., the radio link is deemed as failed if this timer expires). "
214 "Standard values: 0ms 50ms, 100ms, 200ms, 500ms, 1000ms, 2000ms",
216 1000)), // see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
219 .AddAttribute(
220 "N310",
221 "This specifies the maximum number of out-of-sync indications. "
222 "Standard values: 1, 2, 3, 4, 6, 8, 10, 20",
223 UintegerValue(6), // see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
226 .AddAttribute(
227 "N311",
228 "This specifies the maximum number of in-sync indications. "
229 "Standard values: 1, 2, 3, 4, 5, 6, 8, 10",
230 UintegerValue(2), // see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
233 .AddTraceSource("MibReceived",
234 "trace fired upon reception of Master Information Block",
236 "ns3::LteUeRrc::MibSibHandoverTracedCallback")
237 .AddTraceSource("Sib1Received",
238 "trace fired upon reception of System Information Block Type 1",
240 "ns3::LteUeRrc::MibSibHandoverTracedCallback")
241 .AddTraceSource("Sib2Received",
242 "trace fired upon reception of System Information Block Type 2",
244 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
245 .AddTraceSource("StateTransition",
246 "trace fired upon every UE RRC state transition",
248 "ns3::LteUeRrc::StateTracedCallback")
249 .AddTraceSource("InitialCellSelectionEndOk",
250 "trace fired upon successful initial cell selection procedure",
252 "ns3::LteUeRrc::CellSelectionTracedCallback")
253 .AddTraceSource("InitialCellSelectionEndError",
254 "trace fired upon failed initial cell selection procedure",
256 "ns3::LteUeRrc::CellSelectionTracedCallback")
257 .AddTraceSource("RandomAccessSuccessful",
258 "trace fired upon successful completion of the random access procedure",
260 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
261 .AddTraceSource("RandomAccessError",
262 "trace fired upon failure of the random access procedure",
264 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
265 .AddTraceSource("ConnectionEstablished",
266 "trace fired upon successful RRC connection establishment",
268 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
269 .AddTraceSource("ConnectionTimeout",
270 "trace fired upon timeout RRC connection establishment because of T300",
272 "ns3::LteUeRrc::ImsiCidRntiCountTracedCallback")
273 .AddTraceSource("ConnectionReconfiguration",
274 "trace fired upon RRC connection reconfiguration",
276 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
277 .AddTraceSource("HandoverStart",
278 "trace fired upon start of a handover procedure",
280 "ns3::LteUeRrc::MibSibHandoverTracedCallback")
281 .AddTraceSource("HandoverEndOk",
282 "trace fired upon successful termination of a handover procedure",
284 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
285 .AddTraceSource("HandoverEndError",
286 "trace fired upon failure of a handover procedure",
288 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
289 .AddTraceSource("SCarrierConfigured",
290 "trace fired after configuring secondary carriers",
292 "ns3::LteUeRrc::SCarrierConfiguredTracedCallback")
293 .AddTraceSource("Srb1Created",
294 "trace fired after SRB1 is created",
296 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
297 .AddTraceSource("DrbCreated",
298 "trace fired after DRB is created",
300 "ns3::LteUeRrc::ImsiCidRntiLcIdTracedCallback")
301 .AddTraceSource("RadioLinkFailure",
302 "trace fired upon failure of radio link",
304 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
305 .AddTraceSource(
306 "PhySyncDetection",
307 "trace fired upon receiving in Sync or out of Sync indications from UE PHY",
309 "ns3::LteUeRrc::PhySyncDetectionTracedCallback");
310 return tid;
311}
312
313void
319
320void
322{
323 NS_LOG_FUNCTION(this << s);
324 m_cphySapProvider.at(index) = s;
325}
326
329{
330 NS_LOG_FUNCTION(this);
331 return m_cphySapUser.at(0);
332}
333
336{
337 NS_LOG_FUNCTION(this);
338 return m_cphySapUser.at(index);
339}
340
341void
347
348void
350{
351 NS_LOG_FUNCTION(this << s);
352 m_cmacSapProvider.at(index) = s;
353}
354
357{
358 NS_LOG_FUNCTION(this);
359 return m_cmacSapUser.at(0);
360}
361
364{
365 NS_LOG_FUNCTION(this);
366 return m_cmacSapUser.at(index);
367}
368
369void
375
382
383void
389
390void
396
403
404void
409
415
416void
417LteUeRrc::SetImsi(uint64_t imsi)
418{
419 NS_LOG_FUNCTION(this << imsi);
420 m_imsi = imsi;
421
422 // Communicate the IMSI to MACs and PHYs for all the component carriers
423 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
424 {
425 m_cmacSapProvider.at(i)->SetImsi(m_imsi);
426 m_cphySapProvider.at(i)->SetImsi(m_imsi);
427 }
428}
429
430void
432{
433 NS_LOG_FUNCTION(this << cellId);
434 m_previousCellId = cellId;
435}
436
437uint64_t
439{
440 return m_imsi;
441}
442
443uint16_t
445{
446 NS_LOG_FUNCTION(this);
447 return m_rnti;
448}
449
450uint16_t
452{
453 NS_LOG_FUNCTION(this);
454 return m_cellId;
455}
456
457bool
458LteUeRrc::IsServingCell(uint16_t cellId) const
459{
460 NS_LOG_FUNCTION(this);
461 for (auto& cphySap : m_cphySapProvider)
462 {
463 if (cellId == cphySap->GetCellId())
464 {
465 return true;
466 }
467 }
468 return false;
469}
470
471uint8_t
473{
474 NS_LOG_FUNCTION(this);
475 return m_ulBandwidth;
476}
477
478uint8_t
480{
481 NS_LOG_FUNCTION(this);
482 return m_dlBandwidth;
483}
484
487{
488 return m_dlEarfcn;
489}
490
493{
494 NS_LOG_FUNCTION(this);
495 return m_ulEarfcn;
496}
497
500{
501 NS_LOG_FUNCTION(this);
502 return m_state;
503}
504
505uint16_t
507{
508 NS_LOG_FUNCTION(this);
509 return m_previousCellId;
510}
511
512void
514{
515 NS_LOG_FUNCTION(this);
516 m_useRlcSm = val;
517}
518
519void
521{
522 NS_LOG_FUNCTION(this);
523
524 // setup the UE side of SRB0
525 uint8_t lcid = 0;
526
527 Ptr<LteRlc> rlc = CreateObject<LteRlcTm>()->GetObject<LteRlc>();
528 rlc->SetLteMacSapProvider(m_macSapProvider);
529 rlc->SetRnti(m_rnti);
530 rlc->SetLcId(lcid);
531
533 m_srb0->m_rlc = rlc;
534 m_srb0->m_srbIdentity = 0;
536 ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider();
537 ueParams.srb1SapProvider = nullptr;
538 m_rrcSapUser->Setup(ueParams);
539
540 // CCCH (LCID 0) is pre-configured, here is the hardcoded configuration:
542 lcConfig.priority = 0; // highest priority
543 lcConfig.prioritizedBitRateKbps = 65535; // maximum
544 lcConfig.bucketSizeDurationMs = 65535; // maximum
545 lcConfig.logicalChannelGroup = 0; // all SRBs mapped to LCG 0
546 LteMacSapUser* msu =
547 m_ccmRrcSapProvider->ConfigureSignalBearer(lcid, lcConfig, rlc->GetLteMacSapUser());
548 m_cmacSapProvider.at(0)->AddLc(lcid, lcConfig, msu);
549}
550
551void
553{
555 {
556 // this check is needed in order to maintain backward compatibility with scripts and tests
557 // if case lte-helper is not used (like in several tests) the m_numberOfComponentCarriers
558 // is not set and then an error is raised
559 // In this case m_numberOfComponentCarriers is set to 1
561 }
563 {
564 for (uint16_t i = 1; i < m_numberOfComponentCarriers; i++)
565 {
567 m_cmacSapUser.push_back(new UeMemberLteUeCmacSapUser(this));
568 m_cphySapProvider.push_back(nullptr);
569 m_cmacSapProvider.push_back(nullptr);
570 }
571 }
572}
573
574void
576{
577 NS_LOG_FUNCTION(this << packet);
578
579 uint8_t drbid = Bid2Drbid(bid);
580
581 if (drbid != 0)
582 {
583 auto it = m_drbMap.find(drbid);
584 NS_ASSERT_MSG(it != m_drbMap.end(), "could not find bearer with drbid == " << drbid);
585
587 params.pdcpSdu = packet;
588 params.rnti = m_rnti;
589 params.lcid = it->second->m_logicalChannelIdentity;
590
591 NS_LOG_LOGIC(this << " RNTI=" << m_rnti << " sending packet " << packet << " on DRBID "
592 << (uint32_t)drbid << " (LCID " << (uint32_t)params.lcid << ")"
593 << " (" << packet->GetSize() << " bytes)");
594 it->second->m_pdcp->GetLtePdcpSapProvider()->TransmitPdcpSdu(params);
595 }
596}
597
598void
600{
601 NS_LOG_FUNCTION(this);
602
603 switch (m_state)
604 {
605 case IDLE_START:
606 case IDLE_CELL_SEARCH:
608 case IDLE_WAIT_MIB:
609 case IDLE_WAIT_SIB1:
611 NS_LOG_INFO("already disconnected");
612 break;
613
614 case IDLE_WAIT_SIB2:
615 case IDLE_CONNECTING:
616 NS_FATAL_ERROR("cannot abort connection setup procedure");
617 break;
618
624 break;
625
626 default: // i.e. IDLE_RANDOM_ACCESS
627 NS_FATAL_ERROR("method unexpected in state " << m_state);
628 break;
629 }
630}
631
632void
638
639void
641{
642 NS_LOG_FUNCTION(this << rnti);
643 m_rnti = rnti;
644 m_srb0->m_rlc->SetRnti(m_rnti);
645 m_cphySapProvider.at(0)->SetRnti(m_rnti);
646}
647
648void
650{
651 NS_LOG_FUNCTION(this << m_imsi << m_state);
653
654 switch (m_state)
655 {
656 case IDLE_RANDOM_ACCESS: {
657 // we just received a RAR with a T-C-RNTI and an UL grant
658 // send RRC connection request as message 3 of the random access procedure
661 msg.ueIdentity = m_imsi;
664 }
665 break;
666
667 case CONNECTED_HANDOVER: {
671
672 // 3GPP TS 36.331 section 5.5.6.1 Measurements related actions upon handover
673 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
674 measIdIt != m_varMeasConfig.measIdList.end();
675 ++measIdIt)
676 {
677 VarMeasReportListClear(measIdIt->second.measId);
678 }
679
681 m_cmacSapProvider.at(0)->NotifyConnectionSuccessful(); // RA successful during handover
683 }
684 break;
685
686 default:
687 NS_FATAL_ERROR("unexpected event in state " << m_state);
688 break;
689 }
690}
691
692void
694{
695 NS_LOG_FUNCTION(this << m_imsi << m_state);
697
698 switch (m_state)
699 {
700 case IDLE_RANDOM_ACCESS: {
703 }
704 break;
705
706 case CONNECTED_HANDOVER: {
708 /**
709 * @todo After a handover failure because of a random access failure,
710 * send an RRC Connection Re-establishment and switch to
711 * CONNECTED_REESTABLISHING state.
712 */
714 {
718 // we should have called NotifyConnectionFailed
719 // but that method would immediately ask you UE to
720 // connect rather than doing cell selection again.
722 }
723 }
724 break;
725
726 default:
727 NS_FATAL_ERROR("unexpected event in state " << m_state);
728 break;
729 }
730}
731
732void
734{
735 NS_LOG_FUNCTION(this << m_imsi << csgId);
736 m_csgWhiteList = csgId;
737}
738
739void
741{
742 NS_LOG_FUNCTION(this << m_imsi << dlEarfcn);
743 NS_ASSERT_MSG(m_state == IDLE_START, "cannot start cell selection from state " << m_state);
744 m_dlEarfcn = dlEarfcn;
745 m_cphySapProvider.at(0)->StartCellSearch(dlEarfcn);
747}
748
749void
750LteUeRrc::DoForceCampedOnEnb(uint16_t cellId, uint32_t dlEarfcn)
751{
752 NS_LOG_FUNCTION(this << m_imsi << cellId << dlEarfcn);
753
754 switch (m_state)
755 {
756 case IDLE_START:
757 m_cellId = cellId;
758 m_dlEarfcn = dlEarfcn;
759 m_cphySapProvider.at(0)->SynchronizeWithEnb(m_cellId, m_dlEarfcn);
761 break;
762
763 case IDLE_CELL_SEARCH:
765 case IDLE_WAIT_SIB1:
766 NS_FATAL_ERROR("cannot abort cell selection " << m_state);
767 break;
768
769 case IDLE_WAIT_MIB:
770 NS_LOG_INFO("already forced to camp to cell " << m_cellId);
771 break;
772
774 case IDLE_WAIT_SIB2:
776 case IDLE_CONNECTING:
777 NS_LOG_INFO("already camped to cell " << m_cellId);
778 break;
779
784 NS_LOG_INFO("already connected to cell " << m_cellId);
785 break;
786
787 default:
788 NS_FATAL_ERROR("unexpected event in state " << m_state);
789 break;
790 }
791}
792
793void
795{
796 NS_LOG_FUNCTION(this << m_imsi);
797
798 switch (m_state)
799 {
800 case IDLE_START:
801 case IDLE_CELL_SEARCH:
803 case IDLE_WAIT_SIB1:
804 case IDLE_WAIT_MIB:
805 m_connectionPending = true;
806 break;
807
809 m_connectionPending = true;
811 break;
812
813 case IDLE_WAIT_SIB2:
815 case IDLE_CONNECTING:
816 NS_LOG_INFO("already connecting");
817 break;
818
822 NS_LOG_INFO("already connected");
823 break;
824
825 default:
826 NS_FATAL_ERROR("unexpected event in state " << m_state);
827 break;
828 }
829}
830
831// CPHY SAP methods
832
833void
835{
837 m_cphySapProvider.at(0)->SetDlBandwidth(msg.dlBandwidth);
838 m_hasReceivedMib = true;
840
841 switch (m_state)
842 {
843 case IDLE_WAIT_MIB:
844 // manual attachment
846 break;
847
849 // automatic attachment from Idle mode cell selection
851 break;
852
853 default:
854 // do nothing extra
855 break;
856 }
857}
858
859void
862{
863 NS_LOG_FUNCTION(this);
864 switch (m_state)
865 {
866 case IDLE_WAIT_SIB1:
868 "Cell identity in SIB1 does not match with the originating cell");
869 m_hasReceivedSib1 = true;
870 m_lastSib1 = msg;
873 break;
874
877 case IDLE_CONNECTING:
883 "Cell identity in SIB1 does not match with the originating cell");
884 m_hasReceivedSib1 = true;
885 m_lastSib1 = msg;
887 break;
888
890 // MIB has not been received, so ignore this SIB1
891
892 default: // e.g. IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_SIB2
893 // do nothing
894 break;
895 }
896}
897
898void
900{
901 NS_LOG_FUNCTION(this);
902
903 // layer 3 filtering does not apply in IDLE mode
904 bool useLayer3Filtering = (m_state == CONNECTED_NORMALLY);
905 bool triggering = true;
906 for (auto newMeasIt = params.m_ueMeasurementsList.begin();
907 newMeasIt != params.m_ueMeasurementsList.end();
908 ++newMeasIt)
909 {
910 if (params.m_componentCarrierId != 0)
911 {
912 triggering = false; // report is triggered only when an event is on the primary carrier
913 // in this case the measurement received is related to secondary carriers
914 }
915 SaveUeMeasurements(newMeasIt->m_cellId,
916 newMeasIt->m_rsrp,
917 newMeasIt->m_rsrq,
918 useLayer3Filtering,
919 params.m_componentCarrierId);
920 }
921
923 {
924 // start decoding BCH
926 }
927 else
928 {
929 if (triggering)
930 {
931 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
932 measIdIt != m_varMeasConfig.measIdList.end();
933 ++measIdIt)
934 {
935 MeasurementReportTriggering(measIdIt->first);
936 }
937 }
938 }
939}
940
941// RRC SAP methods
942
943void
945{
946 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
947 m_srb0->m_rlc->SetLteRlcSapUser(params.srb0SapUser);
948 if (m_srb1)
949 {
950 m_srb1->m_pdcp->SetLtePdcpSapUser(params.srb1SapUser);
951 }
952}
953
954void
956{
957 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
958
959 if (msg.haveSib2)
960 {
961 switch (m_state)
962 {
964 case IDLE_WAIT_SIB2:
966 case IDLE_CONNECTING:
971 m_hasReceivedSib2 = true;
976 rc.numberOfRaPreambles = msg.sib2.radioResourceConfigCommon.rachConfigCommon
978 rc.preambleTransMax = msg.sib2.radioResourceConfigCommon.rachConfigCommon
980 rc.raResponseWindowSize = msg.sib2.radioResourceConfigCommon.rachConfigCommon
982 rc.connEstFailCount =
984 m_connEstFailCountLimit = rc.connEstFailCount;
986 "SIB2 msg contains wrong value " << m_connEstFailCountLimit
987 << "of connEstFailCount");
988 m_cmacSapProvider.at(0)->ConfigureRach(rc);
989 m_cphySapProvider.at(0)->ConfigureUplink(m_ulEarfcn, m_ulBandwidth);
990 m_cphySapProvider.at(0)->ConfigureReferenceSignalPower(
992 if (m_state == IDLE_WAIT_SIB2)
993 {
996 }
997 break;
998
999 default: // IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_MIB_SIB1, IDLE_WAIT_SIB1
1000 // do nothing
1001 break;
1002 }
1003 }
1004}
1005
1006void
1008{
1009 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1010 switch (m_state)
1011 {
1012 case IDLE_CONNECTING: {
1017 m_leaveConnectedMode = false;
1022 m_cmacSapProvider.at(0)->NotifyConnectionSuccessful();
1025 "Sync indications should be zero "
1026 "when a new RRC connection is established. Current value = "
1027 << (uint16_t)m_noOfSyncIndications);
1028 }
1029 break;
1030
1031 default:
1032 NS_FATAL_ERROR("method unexpected in state " << m_state);
1033 break;
1034 }
1035}
1036
1037void
1039{
1040 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1041 NS_LOG_INFO("DoRecvRrcConnectionReconfiguration haveNonCriticalExtension:"
1043 switch (m_state)
1044 {
1045 case CONNECTED_NORMALLY:
1047 {
1048 NS_LOG_INFO("haveMobilityControlInfo == true");
1051 {
1053 }
1056 // We should reset the MACs and PHYs for all the component carriers
1057 for (auto cmacSapProvider : m_cmacSapProvider)
1058 {
1059 cmacSapProvider->Reset();
1060 }
1061 for (auto cphySapProvider : m_cphySapProvider)
1062 {
1063 cphySapProvider->Reset();
1064 }
1070 m_cphySapProvider.at(0)->SynchronizeWithEnb(m_cellId, mci.carrierFreq.dlCarrierFreq);
1071 m_cphySapProvider.at(0)->SetDlBandwidth(mci.carrierBandwidth.dlBandwidth);
1072 m_cphySapProvider.at(0)->ConfigureUplink(mci.carrierFreq.ulCarrierFreq,
1075 m_srb0->m_rlc->SetRnti(m_rnti);
1078 "handover is only supported with non-contention-based random access procedure");
1079 m_cmacSapProvider.at(0)->StartNonContentionBasedRandomAccessProcedure(
1080 m_rnti,
1083 m_cphySapProvider.at(0)->SetRnti(m_rnti);
1086
1087 // we re-establish SRB1 by creating a new entity
1088 // note that we can't dispose the old entity now, because
1089 // it's in the current stack, so we would corrupt the stack
1090 // if we did so. Hence we schedule it for later disposal
1091 m_srb1Old = m_srb1;
1093 m_srb1 =
1094 nullptr; // new instance will be be created within ApplyRadioResourceConfigDedicated
1095
1096 m_drbMap.clear(); // dispose all DRBs
1099 {
1100 NS_LOG_DEBUG(this << "RNTI " << m_rnti
1101 << " Handover. Configuring secondary carriers");
1103 }
1104
1105 if (msg.haveMeasConfig)
1106 {
1108 }
1109 // RRC connection reconfiguration completed will be sent
1110 // after handover is complete
1111 }
1112 else
1113 {
1114 NS_LOG_INFO("haveMobilityControlInfo == false");
1116 {
1118 NS_LOG_DEBUG(this << "RNTI " << m_rnti << " Configured for CA");
1119 }
1121 {
1123 }
1124 if (msg.haveMeasConfig)
1125 {
1127 }
1132 }
1133 break;
1134
1135 default:
1136 NS_FATAL_ERROR("method unexpected in state " << m_state);
1137 break;
1138 }
1139}
1140
1141void
1143{
1144 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1145 switch (m_state)
1146 {
1148 /**
1149 * @todo After receiving RRC Connection Re-establishment, stop timer
1150 * T301, fire a new trace source, reply with RRC Connection
1151 * Re-establishment Complete, and finally switch to
1152 * CONNECTED_NORMALLY state. See Section 5.3.7.5 of 3GPP TS
1153 * 36.331.
1154 */
1155 }
1156 break;
1157
1158 default:
1159 NS_FATAL_ERROR("method unexpected in state " << m_state);
1160 break;
1161 }
1162}
1163
1164void
1167{
1168 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1169 switch (m_state)
1170 {
1172 /**
1173 * @todo After receiving RRC Connection Re-establishment Reject, stop
1174 * timer T301. See Section 5.3.7.8 of 3GPP TS 36.331.
1175 */
1176 m_asSapUser->NotifyConnectionReleased(); // Inform upper layers
1177 }
1178 break;
1179
1180 default:
1181 NS_FATAL_ERROR("method unexpected in state " << m_state);
1182 break;
1183 }
1184}
1185
1186void
1188{
1189 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1190 /// @todo Currently not implemented, see Section 5.3.8 of 3GPP TS 36.331.
1191
1193 // release resources at UE
1195 {
1196 m_leaveConnectedMode = true;
1200 }
1201}
1202
1203void
1205{
1206 NS_LOG_FUNCTION(this);
1208 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
1209 {
1210 m_cmacSapProvider.at(i)->Reset(); // reset the MAC
1211 }
1212 m_hasReceivedSib2 = false; // invalidate the previously received SIB2
1214 m_asSapUser->NotifyConnectionFailed(); // inform upper layer
1215}
1216
1217void
1218LteUeRrc::DoSetNumberOfComponentCarriers(uint16_t noOfComponentCarriers)
1219{
1220 NS_LOG_FUNCTION(this);
1221 m_numberOfComponentCarriers = noOfComponentCarriers;
1222}
1223
1224void
1226{
1227 NS_LOG_FUNCTION(this);
1229
1230 uint16_t maxRsrpCellId = 0;
1231 double maxRsrp = -std::numeric_limits<double>::infinity();
1232 double minRsrp = -140.0; // Minimum RSRP in dBm a UE can report
1233
1234 for (auto it = m_storedMeasValues.begin(); it != m_storedMeasValues.end(); it++)
1235 {
1236 /*
1237 * This block attempts to find a cell with strongest RSRP and has not
1238 * yet been identified as "acceptable cell".
1239 */
1240 if (maxRsrp < it->second.rsrp && it->second.rsrp > minRsrp)
1241 {
1242 auto itCell = m_acceptableCell.find(it->first);
1243 if (itCell == m_acceptableCell.end())
1244 {
1245 maxRsrpCellId = it->first;
1246 maxRsrp = it->second.rsrp;
1247 }
1248 }
1249 }
1250
1251 if (maxRsrpCellId == 0)
1252 {
1253 NS_LOG_WARN(this << " Cell search is unable to detect surrounding cell to attach to");
1254 }
1255 else
1256 {
1257 NS_LOG_LOGIC(this << " cell " << maxRsrpCellId
1258 << " is the strongest untried surrounding cell");
1259 m_cphySapProvider.at(0)->SynchronizeWithEnb(maxRsrpCellId, m_dlEarfcn);
1261 }
1262}
1263
1264void
1266{
1267 NS_LOG_FUNCTION(this);
1272
1273 // Cell selection criteria evaluation
1274
1275 bool isSuitableCell = false;
1276 bool isAcceptableCell = false;
1277 auto storedMeasIt = m_storedMeasValues.find(cellId);
1278 double qRxLevMeas = storedMeasIt->second.rsrp;
1279 double qRxLevMin =
1281 NS_LOG_LOGIC(this << " cell selection to cellId=" << cellId << " qrxlevmeas=" << qRxLevMeas
1282 << " dBm"
1283 << " qrxlevmin=" << qRxLevMin << " dBm");
1284
1285 if (qRxLevMeas - qRxLevMin > 0)
1286 {
1287 isAcceptableCell = true;
1288
1290 bool cellCsgIndication = m_lastSib1.cellAccessRelatedInfo.csgIndication;
1291
1292 isSuitableCell = (!cellCsgIndication || cellCsgId == m_csgWhiteList);
1293
1294 NS_LOG_LOGIC(this << " csg(ue/cell/indication)=" << m_csgWhiteList << "/" << cellCsgId
1295 << "/" << cellCsgIndication);
1296 }
1297
1298 // Cell selection decision
1299
1300 if (isSuitableCell)
1301 {
1302 m_cellId = cellId;
1303 m_cphySapProvider.at(0)->SynchronizeWithEnb(cellId, m_dlEarfcn);
1304 m_cphySapProvider.at(0)->SetDlBandwidth(m_dlBandwidth);
1306 // Once the UE is connected, m_connectionPending is
1307 // set to false. So, when RLF occurs and UE performs
1308 // cell selection upon leaving RRC_CONNECTED state,
1309 // the following call to DoConnect will make the
1310 // m_connectionPending to be true again. Thus,
1311 // upon calling SwitchToState (IDLE_CAMPED_NORMALLY)
1312 // UE state is instantly change to IDLE_WAIT_SIB2.
1313 // This will make the UE to read the SIB2 message
1314 // and start random access.
1316 {
1317 NS_LOG_DEBUG("Calling DoConnect in state = " << m_state);
1318 DoConnect();
1319 }
1321 }
1322 else
1323 {
1324 // ignore the MIB and SIB1 received from this cell
1325 m_hasReceivedMib = false;
1326 m_hasReceivedSib1 = false;
1327
1329
1330 if (isAcceptableCell)
1331 {
1332 /*
1333 * The cells inserted into this list will not be considered for
1334 * subsequent cell search attempt.
1335 */
1336 m_acceptableCell.insert(cellId);
1337 }
1338
1340 SynchronizeToStrongestCell(); // retry to a different cell
1341 }
1342}
1343
1344void
1347{
1348 NS_LOG_FUNCTION(this);
1349
1351
1352 for (uint32_t sCellIndex : nonCec.sCellToReleaseList)
1353 {
1354 m_cphySapProvider.at(sCellIndex)->Reset();
1355 m_cmacSapProvider.at(sCellIndex)->Reset();
1356 }
1357
1358 for (auto& scell : nonCec.sCellToAddModList)
1359 {
1360 uint8_t ccId = scell.sCellIndex;
1361
1362 uint16_t physCellId = scell.cellIdentification.physCellId;
1363 uint16_t ulBand =
1364 scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth;
1365 uint32_t ulEarfcn =
1366 scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq;
1367 uint16_t dlBand = scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth;
1368 uint32_t dlEarfcn = scell.cellIdentification.dlCarrierFreq;
1369 uint8_t txMode = scell.radioResourceConfigDedicatedSCell.physicalConfigDedicatedSCell
1370 .antennaInfo.transmissionMode;
1371 uint16_t srsIndex = scell.radioResourceConfigDedicatedSCell.physicalConfigDedicatedSCell
1372 .soundingRsUlConfigDedicated.srsConfigIndex;
1373
1374 m_cphySapProvider.at(ccId)->SynchronizeWithEnb(physCellId, dlEarfcn);
1375 m_cphySapProvider.at(ccId)->SetDlBandwidth(dlBand);
1376 m_cphySapProvider.at(ccId)->ConfigureUplink(ulEarfcn, ulBand);
1377 m_cphySapProvider.at(ccId)->ConfigureReferenceSignalPower(
1378 scell.radioResourceConfigCommonSCell.nonUlConfiguration.pdschConfigCommon
1379 .referenceSignalPower);
1380 m_cphySapProvider.at(ccId)->SetTransmissionMode(txMode);
1381 m_cphySapProvider.at(ccId)->SetRnti(m_rnti);
1382 m_cmacSapProvider.at(ccId)->SetRnti(m_rnti);
1383 // update PdschConfigDedicated (i.e. P_A value)
1384 LteRrcSap::PdschConfigDedicated pdschConfigDedicated =
1385 scell.radioResourceConfigDedicatedSCell.physicalConfigDedicatedSCell
1386 .pdschConfigDedicated;
1387 double paDouble = LteRrcSap::ConvertPdschConfigDedicated2Double(pdschConfigDedicated);
1388 m_cphySapProvider.at(ccId)->SetPa(paDouble);
1389 m_cphySapProvider.at(ccId)->SetSrsConfigurationIndex(srsIndex);
1390 }
1391
1393}
1394
1395void
1397{
1398 NS_LOG_FUNCTION(this);
1400
1402 {
1403 m_cphySapProvider.at(0)->SetTransmissionMode(pcd.antennaInfo.transmissionMode);
1404 }
1406 {
1407 m_cphySapProvider.at(0)->SetSrsConfigurationIndex(
1409 }
1410
1412 {
1413 // update PdschConfigDedicated (i.e. P_A value)
1416 m_cphySapProvider.at(0)->SetPa(paDouble);
1417 }
1418
1419 auto stamIt = rrcd.srbToAddModList.begin();
1420 if (stamIt != rrcd.srbToAddModList.end())
1421 {
1422 if (!m_srb1)
1423 {
1424 // SRB1 not setup yet
1426 "unexpected state " << m_state);
1427 NS_ASSERT_MSG(stamIt->srbIdentity == 1, "only SRB1 supported");
1428
1429 const uint8_t lcid = 1; // fixed LCID for SRB1
1430
1432 rlc->SetLteMacSapProvider(m_macSapProvider);
1433 rlc->SetRnti(m_rnti);
1434 rlc->SetLcId(lcid);
1435
1437 pdcp->SetRnti(m_rnti);
1438 pdcp->SetLcId(lcid);
1439 pdcp->SetLtePdcpSapUser(m_drbPdcpSapUser);
1440 pdcp->SetLteRlcSapProvider(rlc->GetLteRlcSapProvider());
1441 rlc->SetLteRlcSapUser(pdcp->GetLteRlcSapUser());
1442
1444 m_srb1->m_rlc = rlc;
1445 m_srb1->m_pdcp = pdcp;
1446 m_srb1->m_srbIdentity = 1;
1448
1449 m_srb1->m_logicalChannelConfig.priority = stamIt->logicalChannelConfig.priority;
1450 m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps =
1451 stamIt->logicalChannelConfig.prioritizedBitRateKbps;
1452 m_srb1->m_logicalChannelConfig.bucketSizeDurationMs =
1453 stamIt->logicalChannelConfig.bucketSizeDurationMs;
1454 m_srb1->m_logicalChannelConfig.logicalChannelGroup =
1455 stamIt->logicalChannelConfig.logicalChannelGroup;
1456
1458 lcConfig.priority = stamIt->logicalChannelConfig.priority;
1459 lcConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.prioritizedBitRateKbps;
1460 lcConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSizeDurationMs;
1461 lcConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalChannelGroup;
1462 LteMacSapUser* msu =
1463 m_ccmRrcSapProvider->ConfigureSignalBearer(lcid, lcConfig, rlc->GetLteMacSapUser());
1464 m_cmacSapProvider.at(0)->AddLc(lcid, lcConfig, msu);
1465 ++stamIt;
1466 NS_ASSERT_MSG(stamIt == rrcd.srbToAddModList.end(), "at most one SrbToAdd supported");
1467
1469 ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider();
1470 ueParams.srb1SapProvider = m_srb1->m_pdcp->GetLtePdcpSapProvider();
1471 m_rrcSapUser->Setup(ueParams);
1472 }
1473 else
1474 {
1475 NS_LOG_INFO("request to modify SRB1 (skipping as currently not implemented)");
1476 // would need to modify m_srb1, and then propagate changes to the MAC
1477 }
1478 }
1479
1480 for (auto dtamIt = rrcd.drbToAddModList.begin(); dtamIt != rrcd.drbToAddModList.end(); ++dtamIt)
1481 {
1482 NS_LOG_INFO(this << " IMSI " << m_imsi << " adding/modifying DRBID "
1483 << (uint32_t)dtamIt->drbIdentity << " LC "
1484 << (uint32_t)dtamIt->logicalChannelIdentity);
1485 NS_ASSERT_MSG(dtamIt->logicalChannelIdentity > 2,
1486 "LCID value " << dtamIt->logicalChannelIdentity << " is reserved for SRBs");
1487
1488 auto drbMapIt = m_drbMap.find(dtamIt->drbIdentity);
1489 if (drbMapIt == m_drbMap.end())
1490 {
1491 NS_LOG_INFO("New Data Radio Bearer");
1492
1493 TypeId rlcTypeId;
1494 if (m_useRlcSm)
1495 {
1496 rlcTypeId = LteRlcSm::GetTypeId();
1497 }
1498 else
1499 {
1500 switch (dtamIt->rlcConfig.choice)
1501 {
1503 rlcTypeId = LteRlcAm::GetTypeId();
1504 break;
1505
1507 rlcTypeId = LteRlcUm::GetTypeId();
1508 break;
1509
1510 default:
1511 NS_FATAL_ERROR("unsupported RLC configuration");
1512 break;
1513 }
1514 }
1515
1516 ObjectFactory rlcObjectFactory;
1517 rlcObjectFactory.SetTypeId(rlcTypeId);
1518 Ptr<LteRlc> rlc = rlcObjectFactory.Create()->GetObject<LteRlc>();
1519 rlc->SetLteMacSapProvider(m_macSapProvider);
1520 rlc->SetRnti(m_rnti);
1521 rlc->SetLcId(dtamIt->logicalChannelIdentity);
1522
1524 drbInfo->m_rlc = rlc;
1525 drbInfo->m_epsBearerIdentity = dtamIt->epsBearerIdentity;
1526 drbInfo->m_logicalChannelIdentity = dtamIt->logicalChannelIdentity;
1527 drbInfo->m_drbIdentity = dtamIt->drbIdentity;
1528
1529 // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
1530 // if we are using RLC/SM we don't care of anything above RLC
1531 if (rlcTypeId != LteRlcSm::GetTypeId())
1532 {
1534 pdcp->SetRnti(m_rnti);
1535 pdcp->SetLcId(dtamIt->logicalChannelIdentity);
1536 pdcp->SetLtePdcpSapUser(m_drbPdcpSapUser);
1537 pdcp->SetLteRlcSapProvider(rlc->GetLteRlcSapProvider());
1538 rlc->SetLteRlcSapUser(pdcp->GetLteRlcSapUser());
1539 drbInfo->m_pdcp = pdcp;
1540 }
1541
1542 m_bid2DrbidMap[dtamIt->epsBearerIdentity] = dtamIt->drbIdentity;
1543
1544 m_drbMap.insert(
1545 std::pair<uint8_t, Ptr<LteDataRadioBearerInfo>>(dtamIt->drbIdentity, drbInfo));
1546
1547 m_drbCreatedTrace(m_imsi, m_cellId, m_rnti, dtamIt->drbIdentity);
1548
1550 lcConfig.priority = dtamIt->logicalChannelConfig.priority;
1551 lcConfig.prioritizedBitRateKbps = dtamIt->logicalChannelConfig.prioritizedBitRateKbps;
1552 lcConfig.bucketSizeDurationMs = dtamIt->logicalChannelConfig.bucketSizeDurationMs;
1553 lcConfig.logicalChannelGroup = dtamIt->logicalChannelConfig.logicalChannelGroup;
1554
1555 NS_LOG_DEBUG(this << " UE RRC RNTI " << m_rnti << " Number Of Component Carriers "
1556 << m_numberOfComponentCarriers << " lcID "
1557 << (uint16_t)dtamIt->logicalChannelIdentity);
1558 // Call AddLc of UE component carrier manager
1559 std::vector<LteUeCcmRrcSapProvider::LcsConfig> lcOnCcMapping =
1560 m_ccmRrcSapProvider->AddLc(dtamIt->logicalChannelIdentity,
1561 lcConfig,
1562 rlc->GetLteMacSapUser());
1563
1564 NS_LOG_DEBUG("Size of lcOnCcMapping vector " << lcOnCcMapping.size());
1565 auto itLcOnCcMapping = lcOnCcMapping.begin();
1566 NS_ASSERT_MSG(itLcOnCcMapping != lcOnCcMapping.end(),
1567 "Component carrier manager failed to add LC for data radio bearer");
1568
1569 for (itLcOnCcMapping = lcOnCcMapping.begin(); itLcOnCcMapping != lcOnCcMapping.end();
1570 ++itLcOnCcMapping)
1571 {
1572 NS_LOG_DEBUG("RNTI " << m_rnti << " LCG id "
1573 << (uint16_t)itLcOnCcMapping->lcConfig.logicalChannelGroup
1574 << " ComponentCarrierId "
1575 << (uint16_t)itLcOnCcMapping->componentCarrierId);
1576 uint8_t index = itLcOnCcMapping->componentCarrierId;
1578 itLcOnCcMapping->lcConfig;
1579 LteMacSapUser* msu = itLcOnCcMapping->msu;
1580 m_cmacSapProvider.at(index)->AddLc(dtamIt->logicalChannelIdentity,
1581 lcConfigFromCcm,
1582 msu);
1583 }
1584
1585 rlc->Initialize();
1586 }
1587 else
1588 {
1589 NS_LOG_INFO("request to modify existing DRBID");
1590 Ptr<LteDataRadioBearerInfo> drbInfo = drbMapIt->second;
1591 /// @todo currently not implemented. Would need to modify drbInfo, and then propagate
1592 /// changes to the MAC
1593 }
1594 }
1595
1596 for (auto dtdmIt = rrcd.drbToReleaseList.begin(); dtdmIt != rrcd.drbToReleaseList.end();
1597 ++dtdmIt)
1598 {
1599 uint8_t drbid = *dtdmIt;
1600 NS_LOG_INFO(this << " IMSI " << m_imsi << " releasing DRB " << (uint32_t)drbid);
1601 auto it = m_drbMap.find(drbid);
1602 NS_ASSERT_MSG(it != m_drbMap.end(), "could not find bearer with given lcid");
1603 m_drbMap.erase(it);
1604 m_bid2DrbidMap.erase(drbid);
1605 // Remove LCID
1606 for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
1607 {
1608 m_cmacSapProvider.at(i)->RemoveLc(drbid + 2);
1609 }
1610 }
1611}
1612
1613void
1615{
1616 NS_LOG_FUNCTION(this);
1617
1618 // perform the actions specified in 3GPP TS 36.331 section 5.5.2.1
1619
1620 // 3GPP TS 36.331 section 5.5.2.4 Measurement object removal
1621 for (auto it = mc.measObjectToRemoveList.begin(); it != mc.measObjectToRemoveList.end(); ++it)
1622 {
1623 uint8_t measObjectId = *it;
1624 NS_LOG_LOGIC(this << " deleting measObjectId " << (uint32_t)measObjectId);
1625 m_varMeasConfig.measObjectList.erase(measObjectId);
1626 auto measIdIt = m_varMeasConfig.measIdList.begin();
1627 while (measIdIt != m_varMeasConfig.measIdList.end())
1628 {
1629 if (measIdIt->second.measObjectId == measObjectId)
1630 {
1631 uint8_t measId = measIdIt->second.measId;
1632 NS_ASSERT(measId == measIdIt->first);
1633 NS_LOG_LOGIC(this << " deleting measId " << (uint32_t)measId
1634 << " because referring to measObjectId "
1635 << (uint32_t)measObjectId);
1636 // note: postfix operator preserves iterator validity
1637 m_varMeasConfig.measIdList.erase(measIdIt++);
1638 VarMeasReportListClear(measId);
1639 }
1640 else
1641 {
1642 ++measIdIt;
1643 }
1644 }
1645 }
1646
1647 // 3GPP TS 36.331 section 5.5.2.5 Measurement object addition/ modification
1648 for (auto it = mc.measObjectToAddModList.begin(); it != mc.measObjectToAddModList.end(); ++it)
1649 {
1650 // simplifying assumptions
1651 NS_ASSERT_MSG(it->measObjectEutra.cellsToRemoveList.empty(),
1652 "cellsToRemoveList not supported");
1653 NS_ASSERT_MSG(it->measObjectEutra.cellsToAddModList.empty(),
1654 "cellsToAddModList not supported");
1655 NS_ASSERT_MSG(it->measObjectEutra.cellsToRemoveList.empty(),
1656 "blackCellsToRemoveList not supported");
1657 NS_ASSERT_MSG(it->measObjectEutra.blackCellsToAddModList.empty(),
1658 "blackCellsToAddModList not supported");
1659 NS_ASSERT_MSG(it->measObjectEutra.haveCellForWhichToReportCGI == false,
1660 "cellForWhichToReportCGI is not supported");
1661
1662 uint8_t measObjectId = it->measObjectId;
1663 auto measObjectIt = m_varMeasConfig.measObjectList.find(measObjectId);
1664 if (measObjectIt != m_varMeasConfig.measObjectList.end())
1665 {
1666 NS_LOG_LOGIC("measObjectId " << (uint32_t)measObjectId << " exists, updating entry");
1667 measObjectIt->second = *it;
1668 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
1669 measIdIt != m_varMeasConfig.measIdList.end();
1670 ++measIdIt)
1671 {
1672 if (measIdIt->second.measObjectId == measObjectId)
1673 {
1674 uint8_t measId = measIdIt->second.measId;
1675 NS_LOG_LOGIC(this << " found measId " << (uint32_t)measId
1676 << " referring to measObjectId " << (uint32_t)measObjectId);
1677 VarMeasReportListClear(measId);
1678 }
1679 }
1680 }
1681 else
1682 {
1683 NS_LOG_LOGIC("measObjectId " << (uint32_t)measObjectId << " is new, adding entry");
1684 m_varMeasConfig.measObjectList[measObjectId] = *it;
1685 }
1686 }
1687
1688 // 3GPP TS 36.331 section 5.5.2.6 Reporting configuration removal
1689 for (auto it = mc.reportConfigToRemoveList.begin(); it != mc.reportConfigToRemoveList.end();
1690 ++it)
1691 {
1692 uint8_t reportConfigId = *it;
1693 NS_LOG_LOGIC(this << " deleting reportConfigId " << (uint32_t)reportConfigId);
1694 m_varMeasConfig.reportConfigList.erase(reportConfigId);
1695 auto measIdIt = m_varMeasConfig.measIdList.begin();
1696 while (measIdIt != m_varMeasConfig.measIdList.end())
1697 {
1698 if (measIdIt->second.reportConfigId == reportConfigId)
1699 {
1700 uint8_t measId = measIdIt->second.measId;
1701 NS_ASSERT(measId == measIdIt->first);
1702 NS_LOG_LOGIC(this << " deleting measId " << (uint32_t)measId
1703 << " because referring to reportConfigId "
1704 << (uint32_t)reportConfigId);
1705 // note: postfix operator preserves iterator validity
1706 m_varMeasConfig.measIdList.erase(measIdIt++);
1707 VarMeasReportListClear(measId);
1708 }
1709 else
1710 {
1711 ++measIdIt;
1712 }
1713 }
1714 }
1715
1716 // 3GPP TS 36.331 section 5.5.2.7 Reporting configuration addition/ modification
1717 for (auto it = mc.reportConfigToAddModList.begin(); it != mc.reportConfigToAddModList.end();
1718 ++it)
1719 {
1720 // simplifying assumptions
1721 NS_ASSERT_MSG(it->reportConfigEutra.triggerType == LteRrcSap::ReportConfigEutra::EVENT,
1722 "only trigger type EVENT is supported");
1723
1724 uint8_t reportConfigId = it->reportConfigId;
1725 auto reportConfigIt = m_varMeasConfig.reportConfigList.find(reportConfigId);
1726 if (reportConfigIt != m_varMeasConfig.reportConfigList.end())
1727 {
1728 NS_LOG_LOGIC("reportConfigId " << (uint32_t)reportConfigId
1729 << " exists, updating entry");
1730 m_varMeasConfig.reportConfigList[reportConfigId] = *it;
1731 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
1732 measIdIt != m_varMeasConfig.measIdList.end();
1733 ++measIdIt)
1734 {
1735 if (measIdIt->second.reportConfigId == reportConfigId)
1736 {
1737 uint8_t measId = measIdIt->second.measId;
1738 NS_LOG_LOGIC(this << " found measId " << (uint32_t)measId
1739 << " referring to reportConfigId "
1740 << (uint32_t)reportConfigId);
1741 VarMeasReportListClear(measId);
1742 }
1743 }
1744 }
1745 else
1746 {
1747 NS_LOG_LOGIC("reportConfigId " << (uint32_t)reportConfigId << " is new, adding entry");
1748 m_varMeasConfig.reportConfigList[reportConfigId] = *it;
1749 }
1750 }
1751
1752 // 3GPP TS 36.331 section 5.5.2.8 Quantity configuration
1753 if (mc.haveQuantityConfig)
1754 {
1755 NS_LOG_LOGIC(this << " setting quantityConfig");
1757 // Convey the filter coefficient to PHY layer so it can configure the power control
1758 // parameter
1759 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
1760 {
1761 m_cphySapProvider.at(i)->SetRsrpFilterCoefficient(
1763 }
1764 // we calculate here the coefficient a used for Layer 3 filtering, see 3GPP TS 36.331
1765 // section 5.5.3.2
1768 NS_LOG_LOGIC(this << " new filter coefficients: aRsrp=" << m_varMeasConfig.aRsrp
1769 << ", aRsrq=" << m_varMeasConfig.aRsrq);
1770
1771 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
1772 measIdIt != m_varMeasConfig.measIdList.end();
1773 ++measIdIt)
1774 {
1775 VarMeasReportListClear(measIdIt->second.measId);
1776 }
1777 }
1778
1779 // 3GPP TS 36.331 section 5.5.2.2 Measurement identity removal
1780 for (auto it = mc.measIdToRemoveList.begin(); it != mc.measIdToRemoveList.end(); ++it)
1781 {
1782 uint8_t measId = *it;
1783 NS_LOG_LOGIC(this << " deleting measId " << (uint32_t)measId);
1784 m_varMeasConfig.measIdList.erase(measId);
1785 VarMeasReportListClear(measId);
1786
1787 // removing time-to-trigger queues
1788 m_enteringTriggerQueue.erase(measId);
1789 m_leavingTriggerQueue.erase(measId);
1790 }
1791
1792 // 3GPP TS 36.331 section 5.5.2.3 Measurement identity addition/ modification
1793 for (auto it = mc.measIdToAddModList.begin(); it != mc.measIdToAddModList.end(); ++it)
1794 {
1795 NS_LOG_LOGIC(this << " measId " << (uint32_t)it->measId
1796 << " (measObjectId=" << (uint32_t)it->measObjectId
1797 << ", reportConfigId=" << (uint32_t)it->reportConfigId << ")");
1798 NS_ASSERT(m_varMeasConfig.measObjectList.find(it->measObjectId) !=
1800 NS_ASSERT(m_varMeasConfig.reportConfigList.find(it->reportConfigId) !=
1802 m_varMeasConfig.measIdList[it->measId] = *it; // side effect: create new entry if not exists
1803 auto measReportIt = m_varMeasReportList.find(it->measId);
1804 if (measReportIt != m_varMeasReportList.end())
1805 {
1806 measReportIt->second.periodicReportTimer.Cancel();
1807 m_varMeasReportList.erase(measReportIt);
1808 }
1809 NS_ASSERT(m_varMeasConfig.reportConfigList.find(it->reportConfigId)
1810 ->second.reportConfigEutra.triggerType !=
1812
1813 // new empty queues for time-to-trigger
1814 std::list<PendingTrigger_t> s;
1815 m_enteringTriggerQueue[it->measId] = s;
1816 m_leavingTriggerQueue[it->measId] = s;
1817 }
1818
1819 if (mc.haveMeasGapConfig)
1820 {
1821 NS_FATAL_ERROR("measurement gaps are currently not supported");
1822 }
1823
1824 if (mc.haveSmeasure)
1825 {
1826 NS_FATAL_ERROR("s-measure is currently not supported");
1827 }
1828
1829 if (mc.haveSpeedStatePars)
1830 {
1831 NS_FATAL_ERROR("SpeedStatePars are currently not supported");
1832 }
1833}
1834
1835void
1837 double rsrp,
1838 double rsrq,
1839 bool useLayer3Filtering,
1840 uint8_t componentCarrierId)
1841{
1842 NS_LOG_FUNCTION(this << cellId << +componentCarrierId << rsrp << rsrq << useLayer3Filtering);
1843
1844 auto storedMeasIt = m_storedMeasValues.find(cellId);
1845
1846 if (storedMeasIt != m_storedMeasValues.end())
1847 {
1848 if (useLayer3Filtering)
1849 {
1850 // F_n = (1-a) F_{n-1} + a M_n
1851 storedMeasIt->second.rsrp = (1 - m_varMeasConfig.aRsrp) * storedMeasIt->second.rsrp +
1852 m_varMeasConfig.aRsrp * rsrp;
1853
1854 if (std::isnan(storedMeasIt->second.rsrq))
1855 {
1856 // the previous RSRQ measurements provided UE PHY are invalid
1857 storedMeasIt->second.rsrq = rsrq; // replace it with unfiltered value
1858 }
1859 else
1860 {
1861 storedMeasIt->second.rsrq =
1862 (1 - m_varMeasConfig.aRsrq) * storedMeasIt->second.rsrq +
1863 m_varMeasConfig.aRsrq * rsrq;
1864 }
1865 }
1866 else
1867 {
1868 storedMeasIt->second.rsrp = rsrp;
1869 storedMeasIt->second.rsrq = rsrq;
1870 }
1871 }
1872 else
1873 {
1874 // first value is always unfiltered
1875 MeasValues v;
1876 v.rsrp = rsrp;
1877 v.rsrq = rsrq;
1878 v.carrierFreq = m_cphySapProvider.at(componentCarrierId)->GetDlEarfcn();
1879
1880 std::pair<uint16_t, MeasValues> val(cellId, v);
1881 auto ret = m_storedMeasValues.insert(val);
1882 NS_ASSERT_MSG(ret.second == true, "element already existed");
1883 storedMeasIt = ret.first;
1884 }
1885
1886 NS_LOG_DEBUG(this << " IMSI " << m_imsi << " state " << m_state << ", measured cell " << cellId
1887 << ", carrier component Id " << componentCarrierId << ", new RSRP " << rsrp
1888 << " stored " << storedMeasIt->second.rsrp << ", new RSRQ " << rsrq
1889 << " stored " << storedMeasIt->second.rsrq);
1890}
1891
1892void
1894{
1895 NS_LOG_FUNCTION(this << (uint16_t)measId);
1896
1897 auto measIdIt = m_varMeasConfig.measIdList.find(measId);
1898 NS_ASSERT(measIdIt != m_varMeasConfig.measIdList.end());
1899 NS_ASSERT(measIdIt->first == measIdIt->second.measId);
1900
1901 auto reportConfigIt = m_varMeasConfig.reportConfigList.find(measIdIt->second.reportConfigId);
1902 NS_ASSERT(reportConfigIt != m_varMeasConfig.reportConfigList.end());
1903 LteRrcSap::ReportConfigEutra& reportConfigEutra = reportConfigIt->second.reportConfigEutra;
1904
1905 auto measObjectIt = m_varMeasConfig.measObjectList.find(measIdIt->second.measObjectId);
1906 NS_ASSERT(measObjectIt != m_varMeasConfig.measObjectList.end());
1907 LteRrcSap::MeasObjectEutra& measObjectEutra = measObjectIt->second.measObjectEutra;
1908
1909 auto measReportIt = m_varMeasReportList.find(measId);
1910 bool isMeasIdInReportList = (measReportIt != m_varMeasReportList.end());
1911
1912 // we don't check the purpose field, as it is only included for
1913 // triggerType == periodical, which is not supported
1915 "only triggerType == event is supported");
1916 // only EUTRA is supported, no need to check for it
1917
1918 NS_LOG_LOGIC(this << " considering measId " << (uint32_t)measId);
1919 bool eventEntryCondApplicable = false;
1920 bool eventLeavingCondApplicable = false;
1921 ConcernedCells_t concernedCellsEntry;
1922 ConcernedCells_t concernedCellsLeaving;
1923
1924 /*
1925 * Find which serving cell corresponds to measObjectEutra.carrierFreq
1926 * It is used, for example, by A1 event:
1927 * See TS 36.331 5.5.4.2: "for this measurement, consider the primary or
1928 * secondary cell that is configured on the frequency indicated in the
1929 * associated measObjectEUTRA to be the serving cell"
1930 */
1931 uint16_t servingCellId = 0;
1932 for (auto cphySapProvider : m_cphySapProvider)
1933 {
1934 if (cphySapProvider->GetDlEarfcn() == measObjectEutra.carrierFreq)
1935 {
1936 servingCellId = cphySapProvider->GetCellId();
1937 }
1938 }
1939
1940 if (servingCellId == 0)
1941 {
1942 return;
1943 }
1944
1945 switch (reportConfigEutra.eventId)
1946 {
1948 /*
1949 * Event A1 (Serving becomes better than threshold)
1950 * Please refer to 3GPP TS 36.331 Section 5.5.4.2
1951 */
1952
1953 double ms; // Ms, the measurement result of the serving cell
1954 double thresh; // Thresh, the threshold parameter for this event
1955 // Hys, the hysteresis parameter for this event.
1956 double hys =
1958
1959 switch (reportConfigEutra.triggerQuantity)
1960 {
1962 ms = m_storedMeasValues[servingCellId].rsrp;
1963
1964 NS_ASSERT(reportConfigEutra.threshold1.choice ==
1966 thresh = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold1.range);
1967 break;
1969 ms = m_storedMeasValues[servingCellId].rsrq;
1970 NS_ASSERT(reportConfigEutra.threshold1.choice ==
1972 thresh = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold1.range);
1973 break;
1974 default:
1975 NS_FATAL_ERROR("unsupported triggerQuantity");
1976 break;
1977 }
1978
1979 // Inequality A1-1 (Entering condition): Ms - Hys > Thresh
1980 bool entryCond = ms - hys > thresh;
1981
1982 if (entryCond)
1983 {
1984 if (!isMeasIdInReportList)
1985 {
1986 concernedCellsEntry.push_back(servingCellId);
1987 eventEntryCondApplicable = true;
1988 }
1989 else
1990 {
1991 /*
1992 * This is to check that the triggered cell recorded in the
1993 * VarMeasReportList is the serving cell.
1994 */
1995 NS_ASSERT(measReportIt->second.cellsTriggeredList.find(servingCellId) !=
1996 measReportIt->second.cellsTriggeredList.end());
1997 }
1998 }
1999 else if (reportConfigEutra.timeToTrigger > 0)
2000 {
2001 CancelEnteringTrigger(measId);
2002 }
2003
2004 // Inequality A1-2 (Leaving condition): Ms + Hys < Thresh
2005 bool leavingCond = ms + hys < thresh;
2006
2007 if (leavingCond)
2008 {
2009 if (isMeasIdInReportList)
2010 {
2011 /*
2012 * This is to check that the triggered cell recorded in the
2013 * VarMeasReportList is the serving cell.
2014 */
2015 NS_ASSERT(measReportIt->second.cellsTriggeredList.find(m_cellId) !=
2016 measReportIt->second.cellsTriggeredList.end());
2017 concernedCellsLeaving.push_back(m_cellId);
2018 eventLeavingCondApplicable = true;
2019 }
2020 }
2021 else if (reportConfigEutra.timeToTrigger > 0)
2022 {
2023 CancelLeavingTrigger(measId);
2024 }
2025
2026 NS_LOG_LOGIC(this << " event A1: serving cell " << servingCellId << " ms=" << ms
2027 << " thresh=" << thresh << " entryCond=" << entryCond
2028 << " leavingCond=" << leavingCond);
2029 }
2030
2031 break;
2032
2034 /*
2035 * Event A2 (Serving becomes worse than threshold)
2036 * Please refer to 3GPP TS 36.331 Section 5.5.4.3
2037 */
2038
2039 double ms; // Ms, the measurement result of the serving cell
2040 double thresh; // Thresh, the threshold parameter for this event
2041 // Hys, the hysteresis parameter for this event.
2042 double hys =
2044
2045 switch (reportConfigEutra.triggerQuantity)
2046 {
2048 ms = m_storedMeasValues[servingCellId].rsrp;
2049 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2051 thresh = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold1.range);
2052 break;
2054 ms = m_storedMeasValues[servingCellId].rsrq;
2055 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2057 thresh = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold1.range);
2058 break;
2059 default:
2060 NS_FATAL_ERROR("unsupported triggerQuantity");
2061 break;
2062 }
2063
2064 // Inequality A2-1 (Entering condition): Ms + Hys < Thresh
2065 bool entryCond = ms + hys < thresh;
2066
2067 if (entryCond)
2068 {
2069 if (!isMeasIdInReportList)
2070 {
2071 concernedCellsEntry.push_back(servingCellId);
2072 eventEntryCondApplicable = true;
2073 }
2074 else
2075 {
2076 /*
2077 * This is to check that the triggered cell recorded in the
2078 * VarMeasReportList is the serving cell.
2079 */
2080 NS_ASSERT(measReportIt->second.cellsTriggeredList.find(servingCellId) !=
2081 measReportIt->second.cellsTriggeredList.end());
2082 }
2083 }
2084 else if (reportConfigEutra.timeToTrigger > 0)
2085 {
2086 CancelEnteringTrigger(measId);
2087 }
2088
2089 // Inequality A2-2 (Leaving condition): Ms - Hys > Thresh
2090 bool leavingCond = ms - hys > thresh;
2091
2092 if (leavingCond)
2093 {
2094 if (isMeasIdInReportList)
2095 {
2096 /*
2097 * This is to check that the triggered cell recorded in the
2098 * VarMeasReportList is the serving cell.
2099 */
2100 NS_ASSERT(measReportIt->second.cellsTriggeredList.find(servingCellId) !=
2101 measReportIt->second.cellsTriggeredList.end());
2102 concernedCellsLeaving.push_back(servingCellId);
2103 eventLeavingCondApplicable = true;
2104 }
2105 }
2106 else if (reportConfigEutra.timeToTrigger > 0)
2107 {
2108 CancelLeavingTrigger(measId);
2109 }
2110
2111 NS_LOG_LOGIC(this << " event A2: serving cell " << servingCellId << " ms=" << ms
2112 << " thresh=" << thresh << " entryCond=" << entryCond
2113 << " leavingCond=" << leavingCond);
2114 }
2115
2116 break;
2117
2119 /*
2120 * Event A3 (Neighbour becomes offset better than PCell)
2121 * Please refer to 3GPP TS 36.331 Section 5.5.4.4
2122 */
2123
2124 double mn; // Mn, the measurement result of the neighbouring cell
2125 double ofn = measObjectEutra
2126 .offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2127 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2128 double mp; // Mp, the measurement result of the PCell
2129 double ofp = measObjectEutra
2130 .offsetFreq; // Ofp, the frequency specific offset of the primary frequency
2131 double ocp = 0.0; // Ocp, the cell specific offset of the PCell
2132 // Off, the offset parameter for this event.
2133 double off = EutranMeasurementMapping::IeValue2ActualA3Offset(reportConfigEutra.a3Offset);
2134 // Hys, the hysteresis parameter for this event.
2135 double hys =
2137
2138 switch (reportConfigEutra.triggerQuantity)
2139 {
2141 mp = m_storedMeasValues[m_cellId].rsrp;
2142 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2144 break;
2146 mp = m_storedMeasValues[m_cellId].rsrq;
2147 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2149 break;
2150 default:
2151 NS_FATAL_ERROR("unsupported triggerQuantity");
2152 break;
2153 }
2154
2155 for (auto storedMeasIt = m_storedMeasValues.begin();
2156 storedMeasIt != m_storedMeasValues.end();
2157 ++storedMeasIt)
2158 {
2159 uint16_t cellId = storedMeasIt->first;
2160 if (cellId == m_cellId)
2161 {
2162 continue;
2163 }
2164
2165 // Only cell(s) on the frequency indicated in the associated measObject can trigger
2166 // event.
2167 if (m_storedMeasValues.at(cellId).carrierFreq != measObjectEutra.carrierFreq)
2168 {
2169 continue;
2170 }
2171
2172 switch (reportConfigEutra.triggerQuantity)
2173 {
2175 mn = storedMeasIt->second.rsrp;
2176 break;
2178 mn = storedMeasIt->second.rsrq;
2179 break;
2180 default:
2181 NS_FATAL_ERROR("unsupported triggerQuantity");
2182 break;
2183 }
2184
2185 bool hasTriggered =
2186 isMeasIdInReportList && (measReportIt->second.cellsTriggeredList.find(cellId) !=
2187 measReportIt->second.cellsTriggeredList.end());
2188
2189 // Inequality A3-1 (Entering condition): Mn + Ofn + Ocn - Hys > Mp + Ofp + Ocp + Off
2190 bool entryCond = mn + ofn + ocn - hys > mp + ofp + ocp + off;
2191
2192 if (entryCond)
2193 {
2194 if (!hasTriggered)
2195 {
2196 concernedCellsEntry.push_back(cellId);
2197 eventEntryCondApplicable = true;
2198 }
2199 }
2200 else if (reportConfigEutra.timeToTrigger > 0)
2201 {
2202 CancelEnteringTrigger(measId, cellId);
2203 }
2204
2205 // Inequality A3-2 (Leaving condition): Mn + Ofn + Ocn + Hys < Mp + Ofp + Ocp + Off
2206 bool leavingCond = mn + ofn + ocn + hys < mp + ofp + ocp + off;
2207
2208 if (leavingCond)
2209 {
2210 if (hasTriggered)
2211 {
2212 concernedCellsLeaving.push_back(cellId);
2213 eventLeavingCondApplicable = true;
2214 }
2215 }
2216 else if (reportConfigEutra.timeToTrigger > 0)
2217 {
2218 CancelLeavingTrigger(measId, cellId);
2219 }
2220
2221 NS_LOG_LOGIC(this << " event A3: neighbor cell " << cellId << " mn=" << mn
2222 << " mp=" << mp << " offset=" << off << " entryCond=" << entryCond
2223 << " leavingCond=" << leavingCond);
2224 }
2225 }
2226
2227 break;
2228
2230 /*
2231 * Event A4 (Neighbour becomes better than threshold)
2232 * Please refer to 3GPP TS 36.331 Section 5.5.4.5
2233 */
2234
2235 double mn; // Mn, the measurement result of the neighbouring cell
2236 double ofn = measObjectEutra
2237 .offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2238 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2239 double thresh; // Thresh, the threshold parameter for this event
2240 // Hys, the hysteresis parameter for this event.
2241 double hys =
2243
2244 switch (reportConfigEutra.triggerQuantity)
2245 {
2247 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2249 thresh = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold1.range);
2250 break;
2252 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2254 thresh = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold1.range);
2255 break;
2256 default:
2257 NS_FATAL_ERROR("unsupported triggerQuantity");
2258 break;
2259 }
2260
2261 for (auto storedMeasIt = m_storedMeasValues.begin();
2262 storedMeasIt != m_storedMeasValues.end();
2263 ++storedMeasIt)
2264 {
2265 uint16_t cellId = storedMeasIt->first;
2266 if (cellId == m_cellId)
2267 {
2268 continue;
2269 }
2270
2271 switch (reportConfigEutra.triggerQuantity)
2272 {
2274 mn = storedMeasIt->second.rsrp;
2275 break;
2277 mn = storedMeasIt->second.rsrq;
2278 break;
2279 default:
2280 NS_FATAL_ERROR("unsupported triggerQuantity");
2281 break;
2282 }
2283
2284 bool hasTriggered =
2285 isMeasIdInReportList && (measReportIt->second.cellsTriggeredList.find(cellId) !=
2286 measReportIt->second.cellsTriggeredList.end());
2287
2288 // Inequality A4-1 (Entering condition): Mn + Ofn + Ocn - Hys > Thresh
2289 bool entryCond = mn + ofn + ocn - hys > thresh;
2290
2291 if (entryCond)
2292 {
2293 if (!hasTriggered)
2294 {
2295 concernedCellsEntry.push_back(cellId);
2296 eventEntryCondApplicable = true;
2297 }
2298 }
2299 else if (reportConfigEutra.timeToTrigger > 0)
2300 {
2301 CancelEnteringTrigger(measId, cellId);
2302 }
2303
2304 // Inequality A4-2 (Leaving condition): Mn + Ofn + Ocn + Hys < Thresh
2305 bool leavingCond = mn + ofn + ocn + hys < thresh;
2306
2307 if (leavingCond)
2308 {
2309 if (hasTriggered)
2310 {
2311 concernedCellsLeaving.push_back(cellId);
2312 eventLeavingCondApplicable = true;
2313 }
2314 }
2315 else if (reportConfigEutra.timeToTrigger > 0)
2316 {
2317 CancelLeavingTrigger(measId, cellId);
2318 }
2319
2320 NS_LOG_LOGIC(this << " event A4: neighbor cell " << cellId << " mn=" << mn
2321 << " thresh=" << thresh << " entryCond=" << entryCond
2322 << " leavingCond=" << leavingCond);
2323 }
2324 }
2325
2326 break;
2327
2329 /*
2330 * Event A5 (PCell becomes worse than threshold1 and neighbour
2331 * becomes better than threshold2)
2332 * Please refer to 3GPP TS 36.331 Section 5.5.4.6
2333 */
2334
2335 double mp; // Mp, the measurement result of the PCell
2336 double mn; // Mn, the measurement result of the neighbouring cell
2337 double ofn = measObjectEutra
2338 .offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2339 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2340 double thresh1; // Thresh1, the threshold parameter for this event
2341 double thresh2; // Thresh2, the threshold parameter for this event
2342 // Hys, the hysteresis parameter for this event.
2343 double hys =
2345
2346 switch (reportConfigEutra.triggerQuantity)
2347 {
2349 mp = m_storedMeasValues[m_cellId].rsrp;
2350 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2352 NS_ASSERT(reportConfigEutra.threshold2.choice ==
2354 thresh1 = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold1.range);
2355 thresh2 = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold2.range);
2356 break;
2358 mp = m_storedMeasValues[m_cellId].rsrq;
2359 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2361 NS_ASSERT(reportConfigEutra.threshold2.choice ==
2363 thresh1 = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold1.range);
2364 thresh2 = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold2.range);
2365 break;
2366 default:
2367 NS_FATAL_ERROR("unsupported triggerQuantity");
2368 break;
2369 }
2370
2371 // Inequality A5-1 (Entering condition 1): Mp + Hys < Thresh1
2372 bool entryCond = mp + hys < thresh1;
2373
2374 if (entryCond)
2375 {
2376 for (auto storedMeasIt = m_storedMeasValues.begin();
2377 storedMeasIt != m_storedMeasValues.end();
2378 ++storedMeasIt)
2379 {
2380 uint16_t cellId = storedMeasIt->first;
2381 if (cellId == m_cellId)
2382 {
2383 continue;
2384 }
2385
2386 switch (reportConfigEutra.triggerQuantity)
2387 {
2389 mn = storedMeasIt->second.rsrp;
2390 break;
2392 mn = storedMeasIt->second.rsrq;
2393 break;
2394 default:
2395 NS_FATAL_ERROR("unsupported triggerQuantity");
2396 break;
2397 }
2398
2399 bool hasTriggered =
2400 isMeasIdInReportList && (measReportIt->second.cellsTriggeredList.find(cellId) !=
2401 measReportIt->second.cellsTriggeredList.end());
2402
2403 // Inequality A5-2 (Entering condition 2): Mn + Ofn + Ocn - Hys > Thresh2
2404
2405 entryCond = mn + ofn + ocn - hys > thresh2;
2406
2407 if (entryCond)
2408 {
2409 if (!hasTriggered)
2410 {
2411 concernedCellsEntry.push_back(cellId);
2412 eventEntryCondApplicable = true;
2413 }
2414 }
2415 else if (reportConfigEutra.timeToTrigger > 0)
2416 {
2417 CancelEnteringTrigger(measId, cellId);
2418 }
2419
2420 NS_LOG_LOGIC(this << " event A5: neighbor cell " << cellId << " mn=" << mn
2421 << " mp=" << mp << " thresh2=" << thresh2
2422 << " thresh1=" << thresh1 << " entryCond=" << entryCond);
2423 }
2424 }
2425 else
2426 {
2427 NS_LOG_LOGIC(this << " event A5: serving cell " << m_cellId << " mp=" << mp
2428 << " thresh1=" << thresh1 << " entryCond=" << entryCond);
2429
2430 if (reportConfigEutra.timeToTrigger > 0)
2431 {
2432 CancelEnteringTrigger(measId);
2433 }
2434 }
2435
2436 if (isMeasIdInReportList)
2437 {
2438 // Inequality A5-3 (Leaving condition 1): Mp - Hys > Thresh1
2439 bool leavingCond = mp - hys > thresh1;
2440
2441 if (leavingCond)
2442 {
2443 if (reportConfigEutra.timeToTrigger == 0)
2444 {
2445 // leaving condition #2 does not have to be checked
2446
2447 for (auto storedMeasIt = m_storedMeasValues.begin();
2448 storedMeasIt != m_storedMeasValues.end();
2449 ++storedMeasIt)
2450 {
2451 uint16_t cellId = storedMeasIt->first;
2452 if (cellId == m_cellId)
2453 {
2454 continue;
2455 }
2456
2457 if (measReportIt->second.cellsTriggeredList.find(cellId) !=
2458 measReportIt->second.cellsTriggeredList.end())
2459 {
2460 concernedCellsLeaving.push_back(cellId);
2461 eventLeavingCondApplicable = true;
2462 }
2463 }
2464 }
2465 else
2466 {
2467 // leaving condition #2 has to be checked to cancel time-to-trigger
2468
2469 for (auto storedMeasIt = m_storedMeasValues.begin();
2470 storedMeasIt != m_storedMeasValues.end();
2471 ++storedMeasIt)
2472 {
2473 uint16_t cellId = storedMeasIt->first;
2474 if (cellId == m_cellId)
2475 {
2476 continue;
2477 }
2478
2479 if (measReportIt->second.cellsTriggeredList.find(cellId) !=
2480 measReportIt->second.cellsTriggeredList.end())
2481 {
2482 switch (reportConfigEutra.triggerQuantity)
2483 {
2485 mn = storedMeasIt->second.rsrp;
2486 break;
2488 mn = storedMeasIt->second.rsrq;
2489 break;
2490 default:
2491 NS_FATAL_ERROR("unsupported triggerQuantity");
2492 break;
2493 }
2494
2495 // Inequality A5-4 (Leaving condition 2): Mn + Ofn + Ocn + Hys < Thresh2
2496
2497 leavingCond = mn + ofn + ocn + hys < thresh2;
2498
2499 if (!leavingCond)
2500 {
2501 CancelLeavingTrigger(measId, cellId);
2502 }
2503
2504 /*
2505 * Whatever the result of leaving condition #2, this
2506 * cell is still "in", because leaving condition #1
2507 * is already true.
2508 */
2509 concernedCellsLeaving.push_back(cellId);
2510 eventLeavingCondApplicable = true;
2511
2512 NS_LOG_LOGIC(this << " event A5: neighbor cell " << cellId
2513 << " mn=" << mn << " mp=" << mp
2514 << " thresh2=" << thresh2 << " thresh1=" << thresh1
2515 << " leavingCond=" << leavingCond);
2516 }
2517 }
2518 }
2519
2520 NS_LOG_LOGIC(this << " event A5: serving cell " << m_cellId << " mp=" << mp
2521 << " thresh1=" << thresh1 << " leavingCond=" << leavingCond);
2522 }
2523 else
2524 {
2525 if (reportConfigEutra.timeToTrigger > 0)
2526 {
2527 CancelLeavingTrigger(measId);
2528 }
2529
2530 // check leaving condition #2
2531
2532 for (auto storedMeasIt = m_storedMeasValues.begin();
2533 storedMeasIt != m_storedMeasValues.end();
2534 ++storedMeasIt)
2535 {
2536 uint16_t cellId = storedMeasIt->first;
2537 if (cellId == m_cellId)
2538 {
2539 continue;
2540 }
2541
2542 if (measReportIt->second.cellsTriggeredList.find(cellId) !=
2543 measReportIt->second.cellsTriggeredList.end())
2544 {
2545 switch (reportConfigEutra.triggerQuantity)
2546 {
2548 mn = storedMeasIt->second.rsrp;
2549 break;
2551 mn = storedMeasIt->second.rsrq;
2552 break;
2553 default:
2554 NS_FATAL_ERROR("unsupported triggerQuantity");
2555 break;
2556 }
2557
2558 // Inequality A5-4 (Leaving condition 2): Mn + Ofn + Ocn + Hys < Thresh2
2559 leavingCond = mn + ofn + ocn + hys < thresh2;
2560
2561 if (leavingCond)
2562 {
2563 concernedCellsLeaving.push_back(cellId);
2564 eventLeavingCondApplicable = true;
2565 }
2566
2567 NS_LOG_LOGIC(this << " event A5: neighbor cell " << cellId << " mn=" << mn
2568 << " mp=" << mp << " thresh2=" << thresh2 << " thresh1="
2569 << thresh1 << " leavingCond=" << leavingCond);
2570 }
2571 }
2572 }
2573 }
2574 }
2575
2576 break;
2577
2578 default:
2579 NS_FATAL_ERROR("unsupported eventId " << reportConfigEutra.eventId);
2580 break;
2581 }
2582
2583 NS_LOG_LOGIC(this << " eventEntryCondApplicable=" << eventEntryCondApplicable
2584 << " eventLeavingCondApplicable=" << eventLeavingCondApplicable);
2585
2586 if (eventEntryCondApplicable)
2587 {
2588 if (reportConfigEutra.timeToTrigger == 0)
2589 {
2590 VarMeasReportListAdd(measId, concernedCellsEntry);
2591 }
2592 else
2593 {
2595 t.measId = measId;
2596 t.concernedCells = concernedCellsEntry;
2597 t.timer = Simulator::Schedule(MilliSeconds(reportConfigEutra.timeToTrigger),
2599 this,
2600 measId,
2601 concernedCellsEntry);
2602 auto enteringTriggerIt = m_enteringTriggerQueue.find(measId);
2603 NS_ASSERT(enteringTriggerIt != m_enteringTriggerQueue.end());
2604 enteringTriggerIt->second.push_back(t);
2605 }
2606 }
2607
2608 if (eventLeavingCondApplicable)
2609 {
2610 // reportOnLeave will only be set when eventId = eventA3
2611 bool reportOnLeave =
2612 (reportConfigEutra.eventId == LteRrcSap::ReportConfigEutra::EVENT_A3) &&
2613 reportConfigEutra.reportOnLeave;
2614
2615 if (reportConfigEutra.timeToTrigger == 0)
2616 {
2617 VarMeasReportListErase(measId, concernedCellsLeaving, reportOnLeave);
2618 }
2619 else
2620 {
2622 t.measId = measId;
2623 t.concernedCells = concernedCellsLeaving;
2624 t.timer = Simulator::Schedule(MilliSeconds(reportConfigEutra.timeToTrigger),
2626 this,
2627 measId,
2628 concernedCellsLeaving,
2629 reportOnLeave);
2630 auto leavingTriggerIt = m_leavingTriggerQueue.find(measId);
2631 NS_ASSERT(leavingTriggerIt != m_leavingTriggerQueue.end());
2632 leavingTriggerIt->second.push_back(t);
2633 }
2634 }
2635}
2636
2637void
2639{
2640 NS_LOG_FUNCTION(this << (uint16_t)measId);
2641
2642 auto it1 = m_enteringTriggerQueue.find(measId);
2643 NS_ASSERT(it1 != m_enteringTriggerQueue.end());
2644
2645 if (!it1->second.empty())
2646 {
2647 for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
2648 {
2649 NS_ASSERT(it2->measId == measId);
2650 NS_LOG_LOGIC(this << " canceling entering time-to-trigger event at "
2651 << Simulator::GetDelayLeft(it2->timer).GetSeconds());
2652 Simulator::Cancel(it2->timer);
2653 }
2654
2655 it1->second.clear();
2656 }
2657}
2658
2659void
2660LteUeRrc::CancelEnteringTrigger(uint8_t measId, uint16_t cellId)
2661{
2662 NS_LOG_FUNCTION(this << (uint16_t)measId << cellId);
2663
2664 auto it1 = m_enteringTriggerQueue.find(measId);
2665 NS_ASSERT(it1 != m_enteringTriggerQueue.end());
2666
2667 auto it2 = it1->second.begin();
2668 while (it2 != it1->second.end())
2669 {
2670 NS_ASSERT(it2->measId == measId);
2671
2672 it2->concernedCells.remove_if([cellId](auto cell) { return cellId == cell; });
2673
2674 if (it2->concernedCells.empty())
2675 {
2676 NS_LOG_LOGIC(this << " canceling entering time-to-trigger event at "
2677 << Simulator::GetDelayLeft(it2->timer).GetSeconds());
2678 Simulator::Cancel(it2->timer);
2679 it2 = it1->second.erase(it2);
2680 }
2681 else
2682 {
2683 it2++;
2684 }
2685 }
2686}
2687
2688void
2690{
2691 NS_LOG_FUNCTION(this << (uint16_t)measId);
2692
2693 auto it1 = m_leavingTriggerQueue.find(measId);
2694 NS_ASSERT(it1 != m_leavingTriggerQueue.end());
2695
2696 if (!it1->second.empty())
2697 {
2698 for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
2699 {
2700 NS_ASSERT(it2->measId == measId);
2701 NS_LOG_LOGIC(this << " canceling leaving time-to-trigger event at "
2702 << Simulator::GetDelayLeft(it2->timer).GetSeconds());
2703 Simulator::Cancel(it2->timer);
2704 }
2705
2706 it1->second.clear();
2707 }
2708}
2709
2710void
2711LteUeRrc::CancelLeavingTrigger(uint8_t measId, uint16_t cellId)
2712{
2713 NS_LOG_FUNCTION(this << (uint16_t)measId << cellId);
2714
2715 auto it1 = m_leavingTriggerQueue.find(measId);
2716 NS_ASSERT(it1 != m_leavingTriggerQueue.end());
2717
2718 auto it2 = it1->second.begin();
2719 while (it2 != it1->second.end())
2720 {
2721 NS_ASSERT(it2->measId == measId);
2722
2723 it2->concernedCells.remove_if([cellId](auto cell) { return cellId == cell; });
2724
2725 if (it2->concernedCells.empty())
2726 {
2727 NS_LOG_LOGIC(this << " canceling leaving time-to-trigger event at "
2728 << Simulator::GetDelayLeft(it2->timer).GetSeconds());
2729 Simulator::Cancel(it2->timer);
2730 it2 = it1->second.erase(it2);
2731 }
2732 else
2733 {
2734 it2++;
2735 }
2736 }
2737}
2738
2739void
2741{
2742 NS_LOG_FUNCTION(this << (uint16_t)measId);
2743 NS_ASSERT(!enteringCells.empty());
2744
2745 auto measReportIt = m_varMeasReportList.find(measId);
2746
2747 if (measReportIt == m_varMeasReportList.end())
2748 {
2749 VarMeasReport r;
2750 r.measId = measId;
2751 std::pair<uint8_t, VarMeasReport> val(measId, r);
2752 auto ret = m_varMeasReportList.insert(val);
2753 NS_ASSERT_MSG(ret.second == true, "element already existed");
2754 measReportIt = ret.first;
2755 }
2756
2757 NS_ASSERT(measReportIt != m_varMeasReportList.end());
2758
2759 for (auto it = enteringCells.begin(); it != enteringCells.end(); ++it)
2760 {
2761 measReportIt->second.cellsTriggeredList.insert(*it);
2762 }
2763
2764 NS_ASSERT(!measReportIt->second.cellsTriggeredList.empty());
2765
2766 // #issue 224, schedule only when there is no periodic event scheduled already
2767 if (!measReportIt->second.periodicReportTimer.IsPending())
2768 {
2769 measReportIt->second.numberOfReportsSent = 0;
2770 measReportIt->second.periodicReportTimer =
2773 this,
2774 measId);
2775 }
2776
2777 auto enteringTriggerIt = m_enteringTriggerQueue.find(measId);
2778 NS_ASSERT(enteringTriggerIt != m_enteringTriggerQueue.end());
2779 if (!enteringTriggerIt->second.empty())
2780 {
2781 /*
2782 * Assumptions at this point:
2783 * - the call to this function was delayed by time-to-trigger;
2784 * - the time-to-trigger delay is fixed (not adaptive/dynamic); and
2785 * - the first element in the list is associated with this function call.
2786 */
2787 enteringTriggerIt->second.pop_front();
2788
2789 if (!enteringTriggerIt->second.empty())
2790 {
2791 /*
2792 * To prevent the same set of cells triggering again in the future,
2793 * we clean up the time-to-trigger queue. This case might occur when
2794 * time-to-trigger > 200 ms.
2795 */
2796 for (auto it = enteringCells.begin(); it != enteringCells.end(); ++it)
2797 {
2798 CancelEnteringTrigger(measId, *it);
2799 }
2800 }
2801 }
2802}
2803
2804void
2805LteUeRrc::VarMeasReportListErase(uint8_t measId, ConcernedCells_t leavingCells, bool reportOnLeave)
2806{
2807 NS_LOG_FUNCTION(this << (uint16_t)measId);
2808 NS_ASSERT(!leavingCells.empty());
2809
2810 auto measReportIt = m_varMeasReportList.find(measId);
2811 NS_ASSERT(measReportIt != m_varMeasReportList.end());
2812
2813 for (auto it = leavingCells.begin(); it != leavingCells.end(); ++it)
2814 {
2815 measReportIt->second.cellsTriggeredList.erase(*it);
2816 }
2817
2818 if (reportOnLeave)
2819 {
2820 // runs immediately without UE_MEASUREMENT_REPORT_DELAY
2821 SendMeasurementReport(measId);
2822 }
2823
2824 if (measReportIt->second.cellsTriggeredList.empty())
2825 {
2826 measReportIt->second.periodicReportTimer.Cancel();
2827 m_varMeasReportList.erase(measReportIt);
2828 }
2829
2830 auto leavingTriggerIt = m_leavingTriggerQueue.find(measId);
2831 NS_ASSERT(leavingTriggerIt != m_leavingTriggerQueue.end());
2832 if (!leavingTriggerIt->second.empty())
2833 {
2834 /*
2835 * Assumptions at this point:
2836 * - the call to this function was delayed by time-to-trigger; and
2837 * - the time-to-trigger delay is fixed (not adaptive/dynamic); and
2838 * - the first element in the list is associated with this function call.
2839 */
2840 leavingTriggerIt->second.pop_front();
2841
2842 if (!leavingTriggerIt->second.empty())
2843 {
2844 /*
2845 * To prevent the same set of cells triggering again in the future,
2846 * we clean up the time-to-trigger queue. This case might occur when
2847 * time-to-trigger > 200 ms.
2848 */
2849 for (auto it = leavingCells.begin(); it != leavingCells.end(); ++it)
2850 {
2851 CancelLeavingTrigger(measId, *it);
2852 }
2853 }
2854 }
2855}
2856
2857void
2859{
2860 NS_LOG_FUNCTION(this << (uint16_t)measId);
2861
2862 // remove the measurement reporting entry for this measId from the VarMeasReportList
2863 auto measReportIt = m_varMeasReportList.find(measId);
2864 if (measReportIt != m_varMeasReportList.end())
2865 {
2866 NS_LOG_LOGIC(this << " deleting existing report for measId " << (uint16_t)measId);
2867 measReportIt->second.periodicReportTimer.Cancel();
2868 m_varMeasReportList.erase(measReportIt);
2869 }
2870
2871 CancelEnteringTrigger(measId);
2872 CancelLeavingTrigger(measId);
2873}
2874
2875void
2877{
2878 NS_LOG_FUNCTION(this << (uint16_t)measId);
2879 // 3GPP TS 36.331 section 5.5.5 Measurement reporting
2880
2881 auto measIdIt = m_varMeasConfig.measIdList.find(measId);
2882 NS_ASSERT(measIdIt != m_varMeasConfig.measIdList.end());
2883
2884 auto reportConfigIt = m_varMeasConfig.reportConfigList.find(measIdIt->second.reportConfigId);
2885 NS_ASSERT(reportConfigIt != m_varMeasConfig.reportConfigList.end());
2886 LteRrcSap::ReportConfigEutra& reportConfigEutra = reportConfigIt->second.reportConfigEutra;
2887
2888 LteRrcSap::MeasurementReport measurementReport;
2889 LteRrcSap::MeasResults& measResults = measurementReport.measResults;
2890 measResults.measId = measId;
2891
2892 auto measReportIt = m_varMeasReportList.find(measId);
2893 if (measReportIt == m_varMeasReportList.end())
2894 {
2895 NS_LOG_ERROR("no entry found in m_varMeasReportList for measId " << (uint32_t)measId);
2896 }
2897 else
2898 {
2899 auto servingMeasIt = m_storedMeasValues.find(m_cellId);
2900 NS_ASSERT(servingMeasIt != m_storedMeasValues.end());
2901 measResults.measResultPCell.rsrpResult =
2902 EutranMeasurementMapping::Dbm2RsrpRange(servingMeasIt->second.rsrp);
2903 measResults.measResultPCell.rsrqResult =
2904 EutranMeasurementMapping::Db2RsrqRange(servingMeasIt->second.rsrq);
2905 NS_LOG_INFO(this << " reporting serving cell "
2906 "RSRP "
2907 << +measResults.measResultPCell.rsrpResult << " ("
2908 << servingMeasIt->second.rsrp
2909 << " dBm) "
2910 "RSRQ "
2911 << +measResults.measResultPCell.rsrqResult << " ("
2912 << servingMeasIt->second.rsrq << " dB)");
2913
2914 measResults.haveMeasResultServFreqList = false;
2915 for (uint16_t componentCarrierId = 1; componentCarrierId < m_numberOfComponentCarriers;
2916 componentCarrierId++)
2917 {
2918 const uint16_t cellId = m_cphySapProvider.at(componentCarrierId)->GetCellId();
2919 auto measValuesIt = m_storedMeasValues.find(cellId);
2920 if (measValuesIt != m_storedMeasValues.end())
2921 {
2922 measResults.haveMeasResultServFreqList = true;
2923 LteRrcSap::MeasResultServFreq measResultServFreq;
2924 measResultServFreq.servFreqId = componentCarrierId;
2925 measResultServFreq.haveMeasResultSCell = true;
2926 measResultServFreq.measResultSCell.rsrpResult =
2927 EutranMeasurementMapping::Dbm2RsrpRange(measValuesIt->second.rsrp);
2928 measResultServFreq.measResultSCell.rsrqResult =
2929 EutranMeasurementMapping::Db2RsrqRange(measValuesIt->second.rsrq);
2930 measResultServFreq.haveMeasResultBestNeighCell = false;
2931 measResults.measResultServFreqList.push_back(measResultServFreq);
2932 }
2933 }
2934
2935 measResults.haveMeasResultNeighCells = false;
2936
2937 if (!(measReportIt->second.cellsTriggeredList.empty()))
2938 {
2939 std::multimap<double, uint16_t> sortedNeighCells;
2940 for (auto cellsTriggeredIt = measReportIt->second.cellsTriggeredList.begin();
2941 cellsTriggeredIt != measReportIt->second.cellsTriggeredList.end();
2942 ++cellsTriggeredIt)
2943 {
2944 uint16_t cellId = *cellsTriggeredIt;
2945 if (cellId != m_cellId)
2946 {
2947 auto neighborMeasIt = m_storedMeasValues.find(cellId);
2948 double triggerValue;
2949 switch (reportConfigEutra.triggerQuantity)
2950 {
2952 triggerValue = neighborMeasIt->second.rsrp;
2953 break;
2955 triggerValue = neighborMeasIt->second.rsrq;
2956 break;
2957 default:
2958 NS_FATAL_ERROR("unsupported triggerQuantity");
2959 break;
2960 }
2961 sortedNeighCells.insert(std::pair<double, uint16_t>(triggerValue, cellId));
2962 }
2963 }
2964
2965 std::multimap<double, uint16_t>::reverse_iterator sortedNeighCellsIt;
2966 uint32_t count;
2967 for (sortedNeighCellsIt = sortedNeighCells.rbegin(), count = 0;
2968 sortedNeighCellsIt != sortedNeighCells.rend() &&
2969 count < reportConfigEutra.maxReportCells;
2970 ++sortedNeighCellsIt, ++count)
2971 {
2972 uint16_t cellId = sortedNeighCellsIt->second;
2973 auto neighborMeasIt = m_storedMeasValues.find(cellId);
2974 NS_ASSERT(neighborMeasIt != m_storedMeasValues.end());
2975 LteRrcSap::MeasResultEutra measResultEutra;
2976 measResultEutra.physCellId = cellId;
2977 measResultEutra.haveCgiInfo = false;
2978 measResultEutra.haveRsrpResult = true;
2979 measResultEutra.rsrpResult =
2980 EutranMeasurementMapping::Dbm2RsrpRange(neighborMeasIt->second.rsrp);
2981 measResultEutra.haveRsrqResult = true;
2982 measResultEutra.rsrqResult =
2983 EutranMeasurementMapping::Db2RsrqRange(neighborMeasIt->second.rsrq);
2984 NS_LOG_INFO(this << " reporting neighbor cell "
2985 << (uint32_t)measResultEutra.physCellId << " RSRP "
2986 << (uint32_t)measResultEutra.rsrpResult << " ("
2987 << neighborMeasIt->second.rsrp << " dBm)"
2988 << " RSRQ " << (uint32_t)measResultEutra.rsrqResult << " ("
2989 << neighborMeasIt->second.rsrq << " dB)");
2990 measResults.measResultListEutra.push_back(measResultEutra);
2991 measResults.haveMeasResultNeighCells = true;
2992 }
2993 }
2994 else
2995 {
2996 NS_LOG_WARN(this << " cellsTriggeredList is empty");
2997 }
2998
2999 /*
3000 * The current LteRrcSap implementation is broken in that it does not
3001 * allow for infinite values of reportAmount, which is probably the most
3002 * reasonable setting. So we just always assume infinite reportAmount.
3003 */
3004 measReportIt->second.numberOfReportsSent++;
3005 measReportIt->second.periodicReportTimer.Cancel();
3006
3007 Time reportInterval;
3008 switch (reportConfigEutra.reportInterval)
3009 {
3011 reportInterval = MilliSeconds(120);
3012 break;
3014 reportInterval = MilliSeconds(240);
3015 break;
3017 reportInterval = MilliSeconds(480);
3018 break;
3020 reportInterval = MilliSeconds(640);
3021 break;
3023 reportInterval = MilliSeconds(1024);
3024 break;
3026 reportInterval = MilliSeconds(2048);
3027 break;
3029 reportInterval = MilliSeconds(5120);
3030 break;
3032 reportInterval = MilliSeconds(10240);
3033 break;
3035 reportInterval = Seconds(60);
3036 break;
3038 reportInterval = Seconds(360);
3039 break;
3041 reportInterval = Seconds(720);
3042 break;
3044 reportInterval = Seconds(1800);
3045 break;
3047 reportInterval = Seconds(3600);
3048 break;
3049 default:
3050 NS_FATAL_ERROR("Unsupported reportInterval "
3051 << (uint16_t)reportConfigEutra.reportInterval);
3052 break;
3053 }
3054
3055 // schedule the next measurement reporting
3056 measReportIt->second.periodicReportTimer =
3057 Simulator::Schedule(reportInterval, &LteUeRrc::SendMeasurementReport, this, measId);
3058
3059 // send the measurement report to eNodeB
3060 m_rrcSapUser->SendMeasurementReport(measurementReport);
3061 }
3062}
3063
3064void
3066{
3067 NS_LOG_FUNCTION(this << m_imsi);
3070 m_connectionPending = false; // reset the flag
3072 m_cmacSapProvider.at(0)->StartContentionBasedRandomAccessProcedure();
3073}
3074
3075void
3077{
3078 NS_LOG_FUNCTION(this << m_imsi);
3079 m_leaveConnectedMode = true;
3080 m_storedMeasValues.clear();
3082
3083 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
3084 measIdIt != m_varMeasConfig.measIdList.end();
3085 ++measIdIt)
3086 {
3087 VarMeasReportListClear(measIdIt->second.measId);
3088 }
3090
3092
3093 for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
3094 {
3095 m_cmacSapProvider.at(i)->Reset(); // reset the MAC
3096 }
3097
3098 m_drbMap.clear();
3099 m_bid2DrbidMap.clear();
3100 m_srb1 = nullptr;
3101 m_hasReceivedMib = false;
3102 m_hasReceivedSib1 = false;
3103 m_hasReceivedSib2 = false;
3104
3105 for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
3106 {
3107 m_cphySapProvider.at(i)->ResetPhyAfterRlf(); // reset the PHY
3108 }
3111 // Save the cell id UE was attached to
3113 m_cellId = 0;
3114 m_rnti = 0;
3115 m_srb0->m_rlc->SetRnti(m_rnti);
3116}
3117
3118void
3120{
3121 NS_LOG_FUNCTION(this << m_imsi);
3124 {
3127 // Assumption: The eNB connection request timer would expire
3128 // before the expiration of T300 at UE. Upon which, the eNB deletes
3129 // the UE context. Therefore, here we don't need to send the UE context
3130 // deletion request to the eNB.
3133 }
3134 else
3135 {
3136 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
3137 {
3138 m_cmacSapProvider.at(i)->Reset(); // reset the MAC
3139 }
3140 m_hasReceivedSib2 = false; // invalidate the previously received SIB2
3143 // Following call to UE NAS will force the UE to immediately
3144 // perform the random access to the same cell again.
3145 m_asSapUser->NotifyConnectionFailed(); // inform upper layer
3146 }
3147}
3148
3149void
3151{
3152 NS_LOG_FUNCTION(this);
3153 m_srb1Old = nullptr;
3154}
3155
3156uint8_t
3158{
3159 auto it = m_bid2DrbidMap.find(bid);
3160 // NS_ASSERT_MSG (it != m_bid2DrbidMap.end (), "could not find BID " << bid);
3161 if (it == m_bid2DrbidMap.end())
3162 {
3163 return 0;
3164 }
3165 else
3166 {
3167 return it->second;
3168 }
3169}
3170
3171void
3173{
3174 NS_LOG_FUNCTION(this << newState);
3175 State oldState = m_state;
3176 m_state = newState;
3177 NS_LOG_INFO(this << " IMSI " << m_imsi << " RNTI " << m_rnti << " UeRrc " << oldState << " --> "
3178 << newState);
3179 m_stateTransitionTrace(m_imsi, m_cellId, m_rnti, oldState, newState);
3180
3181 switch (newState)
3182 {
3183 case IDLE_START:
3185 {
3186 NS_LOG_INFO("Starting initial cell selection after RLF");
3187 }
3188 else
3189 {
3190 NS_FATAL_ERROR("cannot switch to an initial state");
3191 }
3192 break;
3193
3194 case IDLE_CELL_SEARCH:
3195 case IDLE_WAIT_MIB_SIB1:
3196 case IDLE_WAIT_MIB:
3197 case IDLE_WAIT_SIB1:
3198 break;
3199
3202 {
3204 }
3205 break;
3206
3207 case IDLE_WAIT_SIB2:
3209 {
3212 }
3213 break;
3214
3215 case IDLE_RANDOM_ACCESS:
3216 case IDLE_CONNECTING:
3217 case CONNECTED_NORMALLY:
3218 case CONNECTED_HANDOVER:
3221 default:
3222 break;
3223 }
3224}
3225
3226void
3235
3236void
3238{
3239 NS_LOG_FUNCTION(this << m_imsi);
3241 NS_LOG_INFO("noOfSyncIndications " << (uint16_t)m_noOfSyncIndications);
3244 {
3246 }
3247}
3248
3249void
3251{
3252 NS_LOG_FUNCTION(this << m_imsi);
3254 NS_LOG_INFO(this << " Total Number of Sync indications from PHY "
3255 << (uint16_t)m_noOfSyncIndications << "N310 value : " << (uint16_t)m_n310);
3258 {
3262 {
3263 NS_LOG_INFO("t310 started");
3264 }
3265 m_cphySapProvider.at(0)->StartInSyncDetection();
3267 }
3268}
3269
3270void
3272{
3273 NS_LOG_FUNCTION(this << m_imsi);
3274
3275 NS_LOG_DEBUG("The number of sync indication received by RRC from PHY: "
3276 << (uint16_t)m_noOfSyncIndications);
3278}
3279
3280void
3282{
3283 NS_LOG_FUNCTION(this << m_imsi);
3286 m_cphySapProvider.at(0)->ResetRlfParams();
3287}
3288
3289const std::string
3291{
3292 std::ostringstream ss;
3293 ss << s;
3294 return ss.str();
3295}
3296
3297std::ostream&
3298operator<<(std::ostream& os, LteUeRrc::State state)
3299{
3300 switch (state)
3301 {
3303 return os << "IDLE_START";
3305 return os << "IDLE_CELL_SEARCH";
3307 return os << "IDLE_WAIT_MIB_SIB1";
3309 return os << "IDLE_WAIT_MIB";
3311 return os << "IDLE_WAIT_SIB1";
3313 return os << "IDLE_CAMPED_NORMALLY";
3315 return os << "IDLE_WAIT_SIB2";
3317 return os << "IDLE_RANDOM_ACCESS";
3319 return os << "IDLE_CONNECTING";
3321 return os << "CONNECTED_NORMALLY";
3323 return os << "CONNECTED_HANDOVER";
3325 return os << "CONNECTED_PHY_PROBLEM";
3327 return os << "CONNECTED_REESTABLISHING";
3329 return os << "NUM_STATES";
3330 };
3331 return os << "UNKNOWN(" << static_cast<uint32_t>(state) << ")";
3332}
3333
3334} // namespace ns3
static uint8_t Dbm2RsrpRange(double dbm)
convert an RSRP value in dBm to the corresponding range as per 3GPP TS 36.133 section 9....
static double RsrpRange2Dbm(uint8_t range)
converts an RSRP range to dBm as per 3GPP TS 36.133 section 9.1.4 RSRP Measurement Report Mapping
static double RsrqRange2Db(uint8_t range)
converts an RSRQ range to dB as per 3GPP TS 36.133 section 9.1.7 RSRQ Measurement Report Mapping
static double IeValue2ActualQRxLevMin(int8_t qRxLevMinIeValue)
Returns the actual value of an Q-RxLevMin parameter.
static double IeValue2ActualHysteresis(uint8_t hysteresisIeValue)
Returns the actual value of a hysteresis parameter.
static uint8_t Db2RsrqRange(double db)
convert an RSRQ value in dB to the corresponding range as per 3GPP TS 36.133 section 9....
static double IeValue2ActualA3Offset(int8_t a3OffsetIeValue)
Returns the actual value of an a3-Offset parameter.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
This class implements the Access Stratum (AS) Service Access Point (SAP), i.e., the interface between...
Definition lte-as-sap.h:28
This class implements the Access Stratum (AS) Service Access Point (SAP), i.e., the interface between...
Definition lte-as-sap.h:87
virtual void NotifyConnectionFailed()=0
Notify the NAS that RRC Connection Establishment failed.
virtual void NotifyConnectionSuccessful()=0
Notify the NAS that RRC Connection Establishment was successful.
virtual void NotifyConnectionReleased()=0
Notify the NAS that RRC Connection was released.
virtual void RecvData(Ptr< Packet > packet)=0
receive a data packet
Service Access Point (SAP) offered by the MAC to the RLC See Femto Forum MAC Scheduler Interface Spec...
Definition lte-mac-sap.h:25
Service Access Point (SAP) offered by the MAC to the RLC See Femto Forum MAC Scheduler Interface Spec...
Definition lte-mac-sap.h:85
static TypeId GetTypeId()
Get the type ID.
Definition lte-rlc-am.cc:76
This abstract base class defines the API to interact with the Radio Link Control (LTE_RLC) in LTE,...
Definition lte-rlc.h:38
static TypeId GetTypeId()
Get the type ID.
Definition lte-rlc.cc:186
static TypeId GetTypeId()
Get the type ID.
Definition lte-rlc-um.cc:45
static double ConvertPdschConfigDedicated2Double(PdschConfigDedicated pdschConfigDedicated)
Convert PDSCH config dedicated function.
Service Access Point (SAP) offered by the UE component carrier manager to the UE RRC.
virtual void Reset()=0
Reset LC maps.
virtual LteMacSapUser * ConfigureSignalBearer(uint8_t lcid, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser *msu)=0
Add the Signal Bearer for a specific Ue in LteUeComponenCarrierManager.
virtual std::vector< LteUeCcmRrcSapProvider::LcsConfig > AddLc(uint8_t lcId, LteUeCmacSapProvider::LogicalChannelConfig lcConfig, LteMacSapUser *msu)=0
add a new Logical Channel (LC)
Service Access Point (SAP) offered by the UE RRC to the UE CCM.
Service Access Point (SAP) offered by the UE MAC to the UE RRC.
Service Access Point (SAP) offered by the UE MAC to the UE RRC.
Service Access Point (SAP) offered by the UE PHY to the UE RRC for control purposes.
Service Access Point (SAP) offered by the UE PHY to the UE RRC for control purposes.
friend class MemberLteUeCcmRrcSapUser< LteUeRrc >
allow MemberLteUeCcmRrcSapUser<LteUeRrc> class friend access
Definition lte-ue-rrc.h:63
void DoRecvRrcConnectionReconfiguration(LteRrcSap::RrcConnectionReconfiguration msg)
Part of the RRC protocol.
uint8_t m_lastRrcTransactionIdentifier
last RRC transaction identifier
Definition lte-ue-rrc.h:792
bool m_connectionPending
True if a connection request by upper layers is pending.
Definition lte-ue-rrc.h:907
bool m_hasReceivedSib1
True if SIB1 was received for the current cell.
Definition lte-ue-rrc.h:911
void SendMeasurementReport(uint8_t measId)
Produce a proper measurement report from the given measurement identity's reporting entry in m_varMea...
std::map< uint8_t, std::list< PendingTrigger_t > > m_enteringTriggerQueue
List of triggers that were raised because entering condition have been true, but are still delayed fr...
void DoCompleteSetup(LteUeRrcSapProvider::CompleteSetupParameters params)
Part of the RRC protocol.
void DoNotifyOutOfSync()
Do notify out of sync function.
LteUeCcmRrcSapUser * GetLteCcmRrcSapUser()
Get the Component Carrier Management SAP offered by this RRC.
void DoRecvRrcConnectionReject(LteRrcSap::RrcConnectionReject msg)
Part of the RRC protocol.
uint16_t m_previousCellId
the cell id of the previous cell UE was attached to
Ptr< LteSignalingRadioBearerInfo > m_srb1Old
SRB1 configuration before RRC connection reconfiguration.
Definition lte-ue-rrc.h:779
static TypeId GetTypeId()
Get the type ID.
void SwitchToState(State s)
Switch the UE RRC to the given state.
uint16_t GetRnti() const
void DoDisconnect()
Disconnect function.
LteMacSapProvider * m_macSapProvider
MAC SAP provider.
Definition lte-ue-rrc.h:741
void DoNotifyRandomAccessFailed()
Notify random access failed function.
TracedCallback< uint64_t, uint16_t, uint16_t, uint16_t > m_mibReceivedTrace
The MibReceived trace source.
Definition lte-ue-rrc.h:807
LteUeCmacSapUser * GetLteUeCmacSapUser()
This function is overloaded to maintain backward compatibility.
void SetLteUeCmacSapProvider(LteUeCmacSapProvider *s)
set the CMAC SAP this RRC should interact with
uint64_t m_imsi
The unique UE identifier.
Definition lte-ue-rrc.h:757
uint8_t m_n311
The 'N311' attribute.
Ptr< LteSignalingRadioBearerInfo > m_srb0
The Srb0 attribute.
Definition lte-ue-rrc.h:770
uint8_t m_connEstFailCountLimit
the counter value for T300 timer expiration received from the eNB
LteUeCphySapUser * GetLteUeCphySapUser()
void DoConnect()
Connect function.
TracedCallback< uint64_t, uint16_t, uint16_t > m_handoverEndErrorTrace
The HandoverEndError trace source.
Definition lte-ue-rrc.h:875
State
The states of the UE RRC entity.
Definition lte-ue-rrc.h:71
@ CONNECTED_REESTABLISHING
Definition lte-ue-rrc.h:84
@ CONNECTED_PHY_PROBLEM
Definition lte-ue-rrc.h:83
TracedCallback< uint64_t, uint16_t, uint16_t, State, State > m_stateTransitionTrace
The StateTransition trace source.
Definition lte-ue-rrc.h:824
VarMeasConfig m_varMeasConfig
Includes the accumulated configuration of the measurements to be performed by the UE.
Definition lte-ue-rrc.h:949
friend class MemberLteUeRrcSapProvider< LteUeRrc >
allow MemberLteUeRrcSapProvider<LteUeRrc> class friend access
Definition lte-ue-rrc.h:61
void ApplyMeasConfig(LteRrcSap::MeasConfig mc)
Update the current measurement configuration m_varMeasConfig.
LteRrcSap::PdschConfigDedicated m_pdschConfigDedicated
the PDSCH config dedicated
Definition lte-ue-rrc.h:794
uint8_t m_n310
The 'N310' attribute.
void SetUseRlcSm(bool val)
TracedCallback< uint64_t, uint16_t > m_initialCellSelectionEndErrorTrace
The InitialCellSelectionEndError trace source.
Definition lte-ue-rrc.h:834
EventId m_radioLinkFailureDetected
Time limit (given by m_t310) before the radio link is considered to have failed.
void DoRecvRrcConnectionReestablishmentReject(LteRrcSap::RrcConnectionReestablishmentReject msg)
Part of the RRC protocol.
void DoNotifyRandomAccessSuccessful()
Notify random access successful function.
LteUeRrcSapProvider * m_rrcSapProvider
RRC SAP provider.
Definition lte-ue-rrc.h:739
void VarMeasReportListErase(uint8_t measId, ConcernedCells_t leavingCells, bool reportOnLeave)
Remove some cells from an existing reporting entry in m_varMeasReportList.
void DoRecvRrcConnectionSetup(LteRrcSap::RrcConnectionSetup msg)
Part of the RRC protocol.
void CancelLeavingTrigger(uint8_t measId)
Clear all the waiting triggers in m_leavingTriggerQueue which are associated with the given measureme...
bool m_leaveConnectedMode
true if UE NAS ask UE RRC to leave connected mode, e.g., after RLF, i.e.
void DoRecvRrcConnectionReestablishment(LteRrcSap::RrcConnectionReestablishment msg)
Part of the RRC protocol.
bool m_hasReceivedSib2
True if SIB2 was received for the current cell.
Definition lte-ue-rrc.h:913
void SynchronizeToStrongestCell()
Go through the list of measurement results, choose the one with the strongest RSRP,...
std::map< uint8_t, uint8_t > m_bid2DrbidMap
bid to DR bid map
Definition lte-ue-rrc.h:730
void SetLteUeCphySapProvider(LteUeCphySapProvider *s)
set the CPHY SAP this RRC should use to interact with the PHY
std::vector< LteUeCmacSapProvider * > m_cmacSapProvider
UE CMac SAP provider.
Definition lte-ue-rrc.h:736
State GetState() const
uint32_t m_dlEarfcn
Downlink carrier frequency.
Definition lte-ue-rrc.h:799
LteUeCcmRrcSapProvider * m_ccmRrcSapProvider
Interface to the LteUeComponentCarrierManage instance.
Definition lte-ue-rrc.h:750
void DoSetCsgWhiteList(uint32_t csgId)
Set CSG white list function.
void ApplyRadioResourceConfigDedicatedSecondaryCarrier(LteRrcSap::NonCriticalExtensionConfiguration nonCec)
Apply radio resource config dedicated secondary carrier.
LteAsSapProvider * GetAsSapProvider()
void DoSetTemporaryCellRnti(uint16_t rnti)
Set temporary cell rnti function.
void SetLteMacSapProvider(LteMacSapProvider *s)
set the MAC SAP provider.
TracedCallback< uint64_t, uint16_t, uint16_t > m_radioLinkFailureTrace
The 'RadioLinkFailure' trace source.
Definition lte-ue-rrc.h:904
uint64_t GetImsi() const
uint32_t m_ulEarfcn
Uplink carrier frequency.
Definition lte-ue-rrc.h:800
TracedCallback< uint64_t, uint16_t, uint16_t > m_connectionEstablishedTrace
The ConnectionEstablished trace source.
Definition lte-ue-rrc.h:850
uint8_t GetDlBandwidth() const
TracedCallback< uint64_t, uint16_t, uint16_t, uint16_t > m_sib1ReceivedTrace
The Sib1Received trace source.
Definition lte-ue-rrc.h:813
TracedCallback< uint64_t, uint16_t, uint16_t > m_randomAccessErrorTrace
The RandomAccessError trace source.
Definition lte-ue-rrc.h:845
uint32_t GetDlEarfcn() const
std::list< LteRrcSap::SCellToAddMod > m_sCellToAddModList
Secondary carriers.
Definition lte-ue-rrc.h:801
LtePdcpSapUser * m_drbPdcpSapUser
DRB PDCP SAP user.
Definition lte-ue-rrc.h:742
TracedCallback< Ptr< LteUeRrc >, std::list< LteRrcSap::SCellToAddMod > > m_sCarrierConfiguredTrace
The SCarrierConfigured trace source.
Definition lte-ue-rrc.h:881
void DoStartCellSelection(uint32_t dlEarfcn)
Start cell selection function.
friend class MemberLteAsSapProvider< LteUeRrc >
allow MemberLteAsSapProvider<LteUeRrc> class friend access
Definition lte-ue-rrc.h:57
bool m_useRlcSm
True if RLC SM is to be used, false if RLC UM/AM are to be used.
Definition lte-ue-rrc.h:790
TracedCallback< uint64_t, uint16_t, uint16_t > m_handoverEndOkTrace
The HandoverEndOk trace source.
Definition lte-ue-rrc.h:870
TracedCallback< uint64_t, uint16_t, uint16_t, std::string, uint8_t > m_phySyncDetectionTrace
The 'PhySyncDetection' trace source.
Definition lte-ue-rrc.h:899
std::map< uint8_t, std::list< PendingTrigger_t > > m_leavingTriggerQueue
List of triggers that were raised because leaving condition have been true, but are still delayed fro...
Time m_t310
The 'T310' attribute.
friend class UeMemberLteUeCmacSapUser
allow UeMemberLteUeCmacSapUser class friend access
Definition lte-ue-rrc.h:51
void RadioLinkFailureDetected()
Radio link failure detected function.
State m_state
The current UE RRC state.
Definition lte-ue-rrc.h:754
std::vector< LteUeCphySapProvider * > m_cphySapProvider
UE CPhy SAP provider.
Definition lte-ue-rrc.h:733
LteUeCcmRrcSapUser * m_ccmRrcSapUser
CCM RRC SAP user.
Definition lte-ue-rrc.h:751
TracedCallback< uint64_t, uint16_t, uint16_t, uint8_t > m_drbCreatedTrace
The DrbCreated trace source.
Definition lte-ue-rrc.h:893
uint16_t m_numberOfComponentCarriers
The number of component carriers.
std::map< uint8_t, VarMeasReport > m_varMeasReportList
The list of active reporting entries, indexed by the measurement identity which triggered the reporti...
Definition lte-ue-rrc.h:971
std::vector< LteUeCmacSapUser * > m_cmacSapUser
UE CMac SAP user.
Definition lte-ue-rrc.h:735
TracedCallback< uint64_t, uint16_t, uint16_t > m_srb1CreatedTrace
The Srb1Created trace source.
Definition lte-ue-rrc.h:887
TracedCallback< uint64_t, uint16_t > m_initialCellSelectionEndOkTrace
The InitialCellSelectionEndOk trace source.
Definition lte-ue-rrc.h:829
uint8_t GetUlBandwidth() const
void DoSendData(Ptr< Packet > packet, uint8_t bid)
Send data function.
LteAsSapProvider * m_asSapProvider
AS SAP provider.
Definition lte-ue-rrc.h:744
uint16_t m_rnti
The C-RNTI attribute.
Definition lte-ue-rrc.h:761
uint8_t m_noOfSyncIndications
number of in-sync or out-of-sync indications coming from PHY layer
uint16_t GetCellId() const
void DoSetNumberOfComponentCarriers(uint16_t noOfComponentCarriers)
RRC CCM SAP USER Method.
~LteUeRrc() override
Destructor.
void CancelEnteringTrigger(uint8_t measId)
Clear all the waiting triggers in m_enteringTriggerQueue which are associated with the given measurem...
std::map< uint16_t, MeasValues > m_storedMeasValues
Internal storage of the latest measurement results from all detected detected cells,...
void DoReportUeMeasurements(LteUeCphySapUser::UeMeasurementsParameters params)
Report UE measurements function.
LteUeRrcSapUser * m_rrcSapUser
RRC SAP user.
Definition lte-ue-rrc.h:738
TracedCallback< uint64_t, uint16_t, uint16_t > m_connectionReconfigurationTrace
The ConnectionReconfiguration trace source.
Definition lte-ue-rrc.h:860
void MeasurementReportTriggering(uint8_t measId)
Evaluate the reporting criteria of a measurement identity and invoke some reporting actions based on ...
void SaveUeMeasurements(uint16_t cellId, double rsrp, double rsrq, bool useLayer3Filtering, uint8_t componentCarrierId)
Keep the given measurement result as the latest measurement figures, to be utilised by UE RRC functio...
void SetLteCcmRrcSapProvider(LteUeCcmRrcSapProvider *s)
set the Component Carrier Management SAP this RRC should interact with
TracedCallback< uint64_t, uint16_t, uint16_t > m_sib2ReceivedTrace
The Sib2Received trace source.
Definition lte-ue-rrc.h:818
void LeaveConnectedMode()
Leave connected mode method Resets the UE back to an appropriate state depending on the nature of cau...
uint32_t GetUlEarfcn() const
void VarMeasReportListClear(uint8_t measId)
Remove the reporting entry of the given measurement identity from m_varMeasReportList.
LteUeRrcSapProvider * GetLteUeRrcSapProvider()
std::map< uint8_t, Ptr< LteDataRadioBearerInfo > > m_drbMap
The DataRadioBearerMap attribute.
Definition lte-ue-rrc.h:784
uint16_t m_cellId
The CellId attribute.
Definition lte-ue-rrc.h:765
uint8_t m_connEstFailCount
the counter to count T300 timer expiration
void DoRecvMasterInformationBlock(uint16_t cellId, LteRrcSap::MasterInformationBlock msg)
Receive master information block function.
void DoReceivePdcpSdu(LtePdcpSapUser::ReceivePdcpSduParameters params)
Receive PDCP SDU function.
TracedCallback< uint64_t, uint16_t, uint16_t, uint8_t > m_connectionTimeoutTrace
The ConnectionTimeout trace source.
Definition lte-ue-rrc.h:855
std::set< uint16_t > m_acceptableCell
List of cell ID of acceptable cells for cell selection that have been detected.
Definition lte-ue-rrc.h:919
Time m_t300
The T300 attribute.
EventId m_connectionTimeout
Invokes ConnectionEstablishmentTimeout() if RRC connection establishment procedure for this UE takes ...
void VarMeasReportListAdd(uint8_t measId, ConcernedCells_t enteringCells)
Compose a new reporting entry of the given measurement identity, insert it into m_varMeasReportList,...
std::vector< LteUeCphySapUser * > m_cphySapUser
UE CPhy SAP user.
Definition lte-ue-rrc.h:732
void ConnectionTimeout()
Invoked after timer T300 expires, notifying upper layers that RRC connection establishment procedure ...
bool m_hasReceivedMib
True if MIB was received for the current cell.
Definition lte-ue-rrc.h:909
void DoRecvRrcConnectionRelease(LteRrcSap::RrcConnectionRelease msg)
Part of the RRC protocol.
std::list< uint16_t > ConcernedCells_t
List of cell IDs which are responsible for a certain trigger.
Definition lte-ue-rrc.h:976
void EvaluateCellForSelection()
Performs cell selection evaluation to the current serving cell.
void DoRecvSystemInformationBlockType1(uint16_t cellId, LteRrcSap::SystemInformationBlockType1 msg)
Receive system information block type 1 function.
void StartConnection()
Start connection function.
void DoRecvSystemInformation(LteRrcSap::SystemInformation msg)
Part of the RRC protocol.
void DoNotifyInSync()
Do notify in sync function.
uint16_t m_ulBandwidth
Uplink bandwidth in RBs.
Definition lte-ue-rrc.h:797
LteUeRrc()
create an RRC instance for use within an ue
uint32_t m_csgWhiteList
List of CSG ID which this UE entity has access to.
Definition lte-ue-rrc.h:922
uint16_t GetPreviousCellId() const
Get the previous cell id.
void InitializeSap()
Initialize SAP.
void DisposeOldSrb1()
Dispose old SRB1.
void DoInitialize() override
Initialize() implementation.
friend class LtePdcpSpecificLtePdcpSapUser< LteUeRrc >
allow LtePdcpSpecificLtePdcpSapUser<LteUeRrc> class friend access
Definition lte-ue-rrc.h:55
TracedCallback< uint64_t, uint16_t, uint16_t > m_randomAccessSuccessfulTrace
The RandomAccessSuccessful trace source.
Definition lte-ue-rrc.h:840
bool IsServingCell(uint16_t cellId) const
LteRrcSap::SystemInformationBlockType1 m_lastSib1
Stored content of the last SIB1 received.
Definition lte-ue-rrc.h:916
static const std::string ToString(LteUeRrc::State s)
void SetAsSapUser(LteAsSapUser *s)
Set the AS SAP user to interact with the NAS entity.
void SetLteUeRrcSapUser(LteUeRrcSapUser *s)
set the RRC SAP this RRC should interact with
uint16_t m_dlBandwidth
Downlink bandwidth in RBs.
Definition lte-ue-rrc.h:796
Ptr< LteSignalingRadioBearerInfo > m_srb1
The Srb1 attribute.
Definition lte-ue-rrc.h:774
LteAsSapUser * m_asSapUser
AS SAP user.
Definition lte-ue-rrc.h:745
void SetImsi(uint64_t imsi)
void DoForceCampedOnEnb(uint16_t cellId, uint32_t dlEarfcn)
Force camped on ENB function.
void DoDispose() override
Destructor implementation.
void StorePreviousCellId(uint16_t cellId)
Store the previous cell id.
void ResetRlfParams()
Reset radio link failure parameters.
void DoResetSyncIndicationCounter()
Do reset sync indication counter function.
void ApplyRadioResourceConfigDedicated(LteRrcSap::RadioResourceConfigDedicated rrcd)
Apply radio resource config dedicated.
uint8_t Bid2Drbid(uint8_t bid)
Bid 2 DR bid.
TracedCallback< uint64_t, uint16_t, uint16_t, uint16_t > m_handoverStartTrace
The HandoverStart trace source.
Definition lte-ue-rrc.h:865
Part of the RRC protocol.
Part of the RRC protocol.
virtual void Setup(SetupParameters params)=0
Setup function.
virtual void SendRrcConnectionReconfigurationCompleted(RrcConnectionReconfigurationCompleted msg)=0
Send an RRCConnectionReconfigurationComplete message to the serving eNodeB during an RRC connection r...
virtual void SendMeasurementReport(MeasurementReport msg)=0
Send a MeasurementReport message to the serving eNodeB during a measurement reporting procedure (Sect...
virtual void SendIdealUeContextRemoveRequest(uint16_t rnti)=0
Send UE context remove request function.
virtual void SendRrcConnectionRequest(RrcConnectionRequest msg)=0
Send an _RRCConnectionRequest message to the serving eNodeB during an RRC connection establishment pr...
virtual void SendRrcConnectionSetupCompleted(RrcConnectionSetupCompleted msg)=0
Send an RRCConnectionSetupComplete message to the serving eNodeB during an RRC connection establishme...
Template for the implementation of the LteUeCphySapUser as a member of an owner class of type C to wh...
Instantiate subclasses of ns3::Object.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
A base class which provides memory management and object aggregation.
Definition object.h:78
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition simulator.cc:274
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:595
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition simulator.cc:206
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:394
AttributeValue implementation for Time.
Definition nstime.h:1456
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
UeMemberLteUeCmacSapUser class.
Definition lte-ue-rrc.cc:61
UeMemberLteUeCmacSapUser(LteUeRrc *rrc)
Constructor.
Definition lte-ue-rrc.cc:78
LteUeRrc * m_rrc
the RRC class
Definition lte-ue-rrc.cc:75
void SetTemporaryCellRnti(uint16_t rnti) override
Definition lte-ue-rrc.cc:84
void NotifyRandomAccessSuccessful() override
Notify the RRC that the MAC Random Access procedure completed successfully.
Definition lte-ue-rrc.cc:90
void NotifyRandomAccessFailed() override
Notify the RRC that the MAC Random Access procedure failed.
Definition lte-ue-rrc.cc:96
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
ObjectPtrContainerValue ObjectMapValue
ObjectMapValue is an alias for ObjectPtrContainerValue.
Definition object-map.h:29
Ptr< const AttributeAccessor > MakeObjectMapAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition object-map.h:70
Ptr< const AttributeChecker > MakeObjectMapChecker()
Definition object-map.h:119
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1457
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1477
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1393
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
const Time UE_MEASUREMENT_REPORT_DELAY
Artificial delay of UE measurements procedure.
Definition lte-ue-rrc.cc:51
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
constexpr uint32_t MIN_NO_CC
Minimum number of carrier components allowed by 3GPP up to R13.
Definition lte-common.h:25
constexpr uint32_t MAX_NO_CC
Maximum number of carrier components allowed by 3GPP up to R13.
Definition lte-common.h:28
Parameters for LtePdcpSapProvider::TransmitPdcpSdu.
Parameters for LtePdcpSapUser::ReceivePdcpSdu.
uint8_t transmissionMode
transmission mode
uint32_t dlCarrierFreq
DL carrier frequency.
uint32_t ulCarrierFreq
UL carrier frequency.
int8_t qRxLevMin
INTEGER (-70..-22), actual value = IE value * 2 [dBm].
Definition lte-rrc-sap.h:70
uint32_t ulCarrierFreq
UL carrier frequency.
Definition lte-rrc-sap.h:77
uint16_t ulBandwidth
UL bandwidth.
Definition lte-rrc-sap.h:78
MasterInformationBlock structure.
MeasConfig structure.
std::list< uint8_t > measIdToRemoveList
measure ID to remove list
std::list< MeasObjectToAddMod > measObjectToAddModList
measure object to add mod list
std::list< uint8_t > reportConfigToRemoveList
report config to remove list
std::list< uint8_t > measObjectToRemoveList
measure object to remove list
bool haveMeasGapConfig
have measure gap config?
QuantityConfig quantityConfig
quantity config
bool haveSmeasure
have S measure?
bool haveSpeedStatePars
have speed state parameters?
std::list< ReportConfigToAddMod > reportConfigToAddModList
report config to add mod list
std::list< MeasIdToAddMod > measIdToAddModList
measure ID to add mod list
bool haveQuantityConfig
have quantity config?
MeasObjectEutra structure.
int8_t offsetFreq
offset frequency
uint32_t carrierFreq
carrier frequency
MeasResultEutra structure.
uint8_t rsrqResult
RSRQ result.
uint8_t rsrpResult
RSRP result.
bool haveRsrpResult
have RSRP result
bool haveRsrqResult
have RSRQ result?
uint16_t physCellId
Phy cell ID.
bool haveCgiInfo
have CGI info?
uint8_t rsrqResult
the RSRQ result
uint8_t rsrpResult
the RSRP result
uint8_t rsrpResult
the RSRP result
uint8_t rsrqResult
the RSRQ result
MeasResultServFreq structure.
bool haveMeasResultSCell
have measResultSCell?
bool haveMeasResultBestNeighCell
have measResultBestNeighCell?
uint16_t servFreqId
serving cell index
MeasResultSCell measResultSCell
SCell measurement results.
MeasResults structure.
uint8_t measId
measure ID
bool haveMeasResultNeighCells
have measure result neighbor cells
std::list< MeasResultEutra > measResultListEutra
measure result list eutra
bool haveMeasResultServFreqList
has measResultServFreqList-r10
std::list< MeasResultServFreq > measResultServFreqList
MeasResultServFreqList-r10.
MeasResultPCell measResultPCell
measurement result primary cell
MeasurementReport structure.
MeasResults measResults
measure results
MobilityControlInfo structure.
RachConfigDedicated rachConfigDedicated
RACH config dedicated.
bool haveRachConfigDedicated
Have RACH config dedicated?
uint16_t newUeIdentity
new UE identity
bool haveCarrierBandwidth
have carrier bandwidth?
bool haveCarrierFreq
have carrier frequency?
CarrierBandwidthEutra carrierBandwidth
carrier bandwidth
CarrierFreqEutra carrierFreq
carrier frequency
uint16_t targetPhysCellId
target Phy cell ID
NonCriticalExtensionConfiguration structure.
std::list< uint8_t > sCellToReleaseList
SCell to release list.
std::list< SCellToAddMod > sCellToAddModList
SCell to add mod list.
int8_t referenceSignalPower
INTEGER (-60..50),.
PdschConfigDedicated structure.
PhysicalConfigDedicated structure.
PdschConfigDedicated pdschConfigDedicated
PDSCH config dedicated.
bool haveAntennaInfoDedicated
have antenna info dedicated?
SoundingRsUlConfigDedicated soundingRsUlConfigDedicated
sounding RS UL config dedicated
bool haveSoundingRsUlConfigDedicated
have sounding RS UL config dedicated?
bool havePdschConfigDedicated
have PDSCH config dedicated?
AntennaInfoDedicated antennaInfo
antenna info
uint8_t numberOfRaPreambles
number of RA preambles
uint8_t filterCoefficientRSRQ
filter coefficient RSRQ
uint8_t filterCoefficientRSRP
filter coefficient RSRP
uint8_t raResponseWindowSize
RA response window size.
uint8_t preambleTransMax
preamble transmit maximum
TxFailParam txFailParam
txFailParams
PreambleInfo preambleInfo
preamble info
RaSupervisionInfo raSupervisionInfo
RA supervision info.
uint8_t raPreambleIndex
RA preamble index.
uint8_t raPrachMaskIndex
RA PRACH mask index.
RachConfigCommon rachConfigCommon
RACH config common.
PdschConfigCommon pdschConfigCommon
PDSCH config common.
RadioResourceConfigDedicated structure.
PhysicalConfigDedicated physicalConfigDedicated
physical config dedicated
std::list< uint8_t > drbToReleaseList
DRB to release list.
std::list< DrbToAddMod > drbToAddModList
DRB to add mod list.
std::list< SrbToAddMod > srbToAddModList
SRB to add mod list.
Specifies criteria for triggering of an E-UTRA measurement reporting event.
bool reportOnLeave
Indicates whether or not the UE shall initiate the measurement reporting procedure when the leaving c...
uint8_t maxReportCells
Maximum number of cells, excluding the serving cell, to be included in the measurement report.
enum ns3::LteRrcSap::ReportConfigEutra::@62 eventId
Event enumeration.
enum ns3::LteRrcSap::ReportConfigEutra::@61 triggerType
Trigger enumeration.
uint8_t hysteresis
Parameter used within the entry and leave condition of an event triggered reporting condition.
@ RSRP
Reference Signal Received Power.
@ RSRQ
Reference Signal Received Quality.
@ EVENT_A2
Event A2: Serving becomes worse than absolute threshold.
@ EVENT_A3
Event A3: Neighbour becomes amount of offset better than PCell.
@ EVENT_A4
Event A4: Neighbour becomes better than absolute threshold.
@ EVENT_A1
Event A1: Serving becomes better than absolute threshold.
@ EVENT_A5
Event A5: PCell becomes worse than absolute threshold1 AND Neighbour becomes better than another abso...
enum ns3::LteRrcSap::ReportConfigEutra::@65 reportInterval
Report interval enumeration.
ThresholdEutra threshold2
Threshold for event A5.
enum ns3::LteRrcSap::ReportConfigEutra::@63 triggerQuantity
Trigger type enumeration.
ThresholdEutra threshold1
Threshold for event A1, A2, A4, and A5.
int8_t a3Offset
Offset value for Event A3.
uint16_t timeToTrigger
Time during which specific criteria for the event needs to be met in order to trigger a measurement r...
RrcConnectionReconfigurationCompleted structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
RrcConnectionReconfiguration structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
bool haveMobilityControlInfo
have mobility control info
NonCriticalExtensionConfiguration nonCriticalExtension
3GPP TS 36.331 v.11.10 R11 Sec.
bool haveRadioResourceConfigDedicated
have radio resource config dedicated
RadioResourceConfigDedicated radioResourceConfigDedicated
radio resource config dedicated
bool haveNonCriticalExtension
have critical extension?
MobilityControlInfo mobilityControlInfo
mobility control info
RrcConnectionReestablishment structure.
RrcConnectionReestablishmentReject structure.
RrcConnectionReject structure.
RrcConnectionRelease structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
RrcConnectionRequest structure.
RrcConnectionSetupCompleted structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
RrcConnectionSetup structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
RadioResourceConfigDedicated radioResourceConfigDedicated
radio resource config dedicated
uint16_t srsConfigIndex
SRS config index.
SystemInformationBlockType1 structure.
CellSelectionInfo cellSelectionInfo
cell selection info
CellAccessRelatedInfo cellAccessRelatedInfo
cell access related info
RadioResourceConfigCommonSib radioResourceConfigCommon
radio resource config common
SystemInformation structure.
SystemInformationBlockType2 sib2
SIB2.
@ THRESHOLD_RSRP
RSRP is used for the threshold.
@ THRESHOLD_RSRQ
RSRQ is used for the threshold.
enum ns3::LteRrcSap::ThresholdEutra::@60 choice
Threshold enumeration.
uint8_t range
Value range used in RSRP/RSRQ threshold.
uint8_t connEstFailCount
Number of times that the UE detects T300 expiry on the same cell.
uint16_t prioritizedBitRateKbps
prioritize bit rate Kbps
uint16_t bucketSizeDurationMs
bucket size duration ms
uint8_t logicalChannelGroup
logical channel group
UeMeasurementsParameters structure.
Represents a measurement result from a certain cell.
uint32_t carrierFreq
Measurement object frequency.
double rsrp
Measured RSRP in dBm.
double rsrq
Measured RSRQ in dB.
Represents a single triggered event from a measurement identity which reporting criteria have been fu...
ConcernedCells_t concernedCells
The list of cells responsible for this trigger.
EventId timer
The pending reporting event, scheduled at the end of the time-to-trigger.
uint8_t measId
The measurement identity which raised the trigger.
std::map< uint8_t, LteRrcSap::ReportConfigToAddMod > reportConfigList
report config list
Definition lte-ue-rrc.h:937
LteRrcSap::QuantityConfig quantityConfig
quantity config
Definition lte-ue-rrc.h:938
std::map< uint8_t, LteRrcSap::MeasObjectToAddMod > measObjectList
measure object list
Definition lte-ue-rrc.h:936
std::map< uint8_t, LteRrcSap::MeasIdToAddMod > measIdList
measure ID list
Definition lte-ue-rrc.h:935
Represents a single measurement reporting entry., which includes information about a measurement for ...
Definition lte-ue-rrc.h:959
uint8_t measId
measure ID
Definition lte-ue-rrc.h:960
CompleteSetupParameters structure.
SetupParameters structure.
LteRlcSapProvider * srb0SapProvider
SRB0 SAP provider.
LtePdcpSapProvider * srb1SapProvider
SRB1 SAP provider.