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