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/////////////////////////////
86// ue RRC methods
87/////////////////////////////
88
90
92 : m_cmacSapProvider(0),
93 m_rrcSapUser(nullptr),
94 m_macSapProvider(nullptr),
95 m_asSapUser(nullptr),
96 m_ccmRrcSapProvider(nullptr),
97 m_state(IDLE_START),
98 m_imsi(0),
99 m_rnti(0),
100 m_cellId(0),
101 m_useRlcSm(true),
102 m_connectionPending(false),
103 m_hasReceivedMib(false),
104 m_hasReceivedSib1(false),
105 m_hasReceivedSib2(false),
106 m_csgWhiteList(0),
107 m_noOfSyncIndications(0),
108 m_leaveConnectedMode(false),
109 m_previousCellId(0),
110 m_connEstFailCountLimit(0),
111 m_connEstFailCount(0),
112 m_numberOfComponentCarriers(MIN_NO_CC)
113{
114 NS_LOG_FUNCTION(this);
116 m_cmacSapUser.push_back(new UeMemberLteUeCmacSapUser(this));
117 m_cphySapProvider.push_back(nullptr);
118 m_cmacSapProvider.push_back(nullptr);
123}
124
129
130void
132{
133 NS_LOG_FUNCTION(this);
134 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
135 {
136 delete m_cphySapUser.at(i);
137 delete m_cmacSapUser.at(i);
138 }
139 m_cphySapUser.clear();
140 m_cmacSapUser.clear();
141 delete m_rrcSapProvider;
142 delete m_drbPdcpSapUser;
143 delete m_asSapProvider;
144 delete m_ccmRrcSapUser;
146 m_cphySapProvider.clear();
148 m_cmacSapProvider.clear();
149 m_drbMap.clear();
150}
151
152TypeId
154{
155 static TypeId tid =
156 TypeId("ns3::LteUeRrc")
157 .SetParent<Object>()
158 .SetGroupName("Lte")
159 .AddConstructor<LteUeRrc>()
160 .AddAttribute("DataRadioBearerMap",
161 "List of UE RadioBearerInfo for Data Radio Bearers by LCID.",
165 .AddAttribute("Srb0",
166 "SignalingRadioBearerInfo for SRB0",
167 PointerValue(),
170 .AddAttribute("Srb1",
171 "SignalingRadioBearerInfo for SRB1",
172 PointerValue(),
175 .AddAttribute("CellId",
176 "Serving cell identifier",
177 UintegerValue(0), // unused, read-only attribute
180 .AddAttribute("C-RNTI",
181 "Cell Radio Network Temporary Identifier",
182 UintegerValue(0), // unused, read-only attribute
185 .AddAttribute(
186 "T300",
187 "Timer for the RRC Connection Establishment procedure "
188 "(i.e., the procedure is deemed as failed if it takes longer than this). "
189 "Standard values: 100ms, 200ms, 300ms, 400ms, 600ms, 1000ms, 1500ms, 2000ms",
191 100)), // see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
194 .AddAttribute(
195 "T310",
196 "Timer for detecting the Radio link failure "
197 "(i.e., the radio link is deemed as failed if this timer expires). "
198 "Standard values: 0ms 50ms, 100ms, 200ms, 500ms, 1000ms, 2000ms",
200 1000)), // see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
203 .AddAttribute(
204 "N310",
205 "This specifies the maximum number of out-of-sync indications. "
206 "Standard values: 1, 2, 3, 4, 6, 8, 10, 20",
207 UintegerValue(6), // see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
210 .AddAttribute(
211 "N311",
212 "This specifies the maximum number of in-sync indications. "
213 "Standard values: 1, 2, 3, 4, 5, 6, 8, 10",
214 UintegerValue(2), // see 3GPP 36.331 UE-TimersAndConstants & RLF-TimersAndConstants
217 .AddTraceSource("MibReceived",
218 "trace fired upon reception of Master Information Block",
220 "ns3::LteUeRrc::MibSibHandoverTracedCallback")
221 .AddTraceSource("Sib1Received",
222 "trace fired upon reception of System Information Block Type 1",
224 "ns3::LteUeRrc::MibSibHandoverTracedCallback")
225 .AddTraceSource("Sib2Received",
226 "trace fired upon reception of System Information Block Type 2",
228 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
229 .AddTraceSource("StateTransition",
230 "trace fired upon every UE RRC state transition",
232 "ns3::LteUeRrc::StateTracedCallback")
233 .AddTraceSource("InitialCellSelectionEndOk",
234 "trace fired upon successful initial cell selection procedure",
236 "ns3::LteUeRrc::CellSelectionTracedCallback")
237 .AddTraceSource("InitialCellSelectionEndError",
238 "trace fired upon failed initial cell selection procedure",
240 "ns3::LteUeRrc::CellSelectionTracedCallback")
241 .AddTraceSource("RandomAccessSuccessful",
242 "trace fired upon successful completion of the random access procedure",
244 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
245 .AddTraceSource("RandomAccessError",
246 "trace fired upon failure of the random access procedure",
248 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
249 .AddTraceSource("ConnectionEstablished",
250 "trace fired upon successful RRC connection establishment",
252 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
253 .AddTraceSource("ConnectionTimeout",
254 "trace fired upon timeout RRC connection establishment because of T300",
256 "ns3::LteUeRrc::ImsiCidRntiCountTracedCallback")
257 .AddTraceSource("ConnectionReconfiguration",
258 "trace fired upon RRC connection reconfiguration",
260 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
261 .AddTraceSource("HandoverStart",
262 "trace fired upon start of a handover procedure",
264 "ns3::LteUeRrc::MibSibHandoverTracedCallback")
265 .AddTraceSource("HandoverEndOk",
266 "trace fired upon successful termination of a handover procedure",
268 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
269 .AddTraceSource("HandoverEndError",
270 "trace fired upon failure of a handover procedure",
272 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
273 .AddTraceSource("SCarrierConfigured",
274 "trace fired after configuring secondary carriers",
276 "ns3::LteUeRrc::SCarrierConfiguredTracedCallback")
277 .AddTraceSource("Srb1Created",
278 "trace fired after SRB1 is created",
280 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
281 .AddTraceSource("DrbCreated",
282 "trace fired after DRB is created",
284 "ns3::LteUeRrc::ImsiCidRntiLcIdTracedCallback")
285 .AddTraceSource("RadioLinkFailure",
286 "trace fired upon failure of radio link",
288 "ns3::LteUeRrc::ImsiCidRntiTracedCallback")
289 .AddTraceSource(
290 "PhySyncDetection",
291 "trace fired upon receiving in Sync or out of Sync indications from UE PHY",
293 "ns3::LteUeRrc::PhySyncDetectionTracedCallback");
294 return tid;
295}
296
297void
303
304void
306{
307 NS_LOG_FUNCTION(this << s);
308 m_cphySapProvider.at(index) = s;
309}
310
313{
314 NS_LOG_FUNCTION(this);
315 return m_cphySapUser.at(0);
316}
317
320{
321 NS_LOG_FUNCTION(this);
322 return m_cphySapUser.at(index);
323}
324
325void
331
332void
334{
335 NS_LOG_FUNCTION(this << s);
336 m_cmacSapProvider.at(index) = s;
337}
338
341{
342 NS_LOG_FUNCTION(this);
343 return m_cmacSapUser.at(0);
344}
345
348{
349 NS_LOG_FUNCTION(this);
350 return m_cmacSapUser.at(index);
351}
352
353void
359
366
367void
373
374void
380
387
388void
393
399
400void
401LteUeRrc::SetImsi(uint64_t imsi)
402{
403 NS_LOG_FUNCTION(this << imsi);
404 m_imsi = imsi;
405
406 // Communicate the IMSI to MACs and PHYs for all the component carriers
407 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
408 {
409 m_cmacSapProvider.at(i)->SetImsi(m_imsi);
410 m_cphySapProvider.at(i)->SetImsi(m_imsi);
411 }
412}
413
414void
416{
417 NS_LOG_FUNCTION(this << cellId);
418 m_previousCellId = cellId;
419}
420
421uint64_t
423{
424 return m_imsi;
425}
426
427uint16_t
429{
430 NS_LOG_FUNCTION(this);
431 return m_rnti;
432}
433
434uint16_t
436{
437 NS_LOG_FUNCTION(this);
438 return m_cellId;
439}
440
441bool
442LteUeRrc::IsServingCell(uint16_t cellId) const
443{
444 NS_LOG_FUNCTION(this);
445 for (auto& cphySap : m_cphySapProvider)
446 {
447 if (cellId == cphySap->GetCellId())
448 {
449 return true;
450 }
451 }
452 return false;
453}
454
455uint8_t
457{
458 NS_LOG_FUNCTION(this);
459 return m_ulBandwidth;
460}
461
462uint8_t
464{
465 NS_LOG_FUNCTION(this);
466 return m_dlBandwidth;
467}
468
471{
472 return m_dlEarfcn;
473}
474
477{
478 NS_LOG_FUNCTION(this);
479 return m_ulEarfcn;
480}
481
484{
485 NS_LOG_FUNCTION(this);
486 return m_state;
487}
488
489uint16_t
491{
492 NS_LOG_FUNCTION(this);
493 return m_previousCellId;
494}
495
496void
498{
499 NS_LOG_FUNCTION(this);
500 m_useRlcSm = val;
501}
502
503void
505{
506 NS_LOG_FUNCTION(this);
507
508 // setup the UE side of SRB0
509 uint8_t lcid = 0;
510
511 Ptr<LteRlc> rlc = CreateObject<LteRlcTm>()->GetObject<LteRlc>();
512 rlc->SetLteMacSapProvider(m_macSapProvider);
513 rlc->SetRnti(m_rnti);
514 rlc->SetLcId(lcid);
515
517 m_srb0->m_rlc = rlc;
518 m_srb0->m_srbIdentity = 0;
520 ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider();
521 ueParams.srb1SapProvider = nullptr;
522 m_rrcSapUser->Setup(ueParams);
523
524 // CCCH (LCID 0) is pre-configured, here is the hardcoded configuration:
526 lcConfig.priority = 0; // highest priority
527 lcConfig.prioritizedBitRateKbps = 65535; // maximum
528 lcConfig.bucketSizeDurationMs = 65535; // maximum
529 lcConfig.logicalChannelGroup = 0; // all SRBs mapped to LCG 0
530 LteMacSapUser* msu =
531 m_ccmRrcSapProvider->ConfigureSignalBearer(lcid, lcConfig, rlc->GetLteMacSapUser());
532 m_cmacSapProvider.at(0)->AddLc(lcid, lcConfig, msu);
533}
534
535void
537{
539 {
540 // this check is needed in order to maintain backward compatibility with scripts and tests
541 // if case lte-helper is not used (like in several tests) the m_numberOfComponentCarriers
542 // is not set and then an error is raised
543 // In this case m_numberOfComponentCarriers is set to 1
545 }
547 {
548 for (uint16_t i = 1; i < m_numberOfComponentCarriers; i++)
549 {
551 m_cmacSapUser.push_back(new UeMemberLteUeCmacSapUser(this));
552 m_cphySapProvider.push_back(nullptr);
553 m_cmacSapProvider.push_back(nullptr);
554 }
555 }
556}
557
558void
560{
561 NS_LOG_FUNCTION(this << packet);
562
563 uint8_t drbid = Bid2Drbid(bid);
564
565 if (drbid != 0)
566 {
567 auto it = m_drbMap.find(drbid);
568 NS_ASSERT_MSG(it != m_drbMap.end(), "could not find bearer with drbid == " << drbid);
569
571 params.pdcpSdu = packet;
572 params.rnti = m_rnti;
573 params.lcid = it->second->m_logicalChannelIdentity;
574
575 NS_LOG_LOGIC(this << " RNTI=" << m_rnti << " sending packet " << packet << " on DRBID "
576 << (uint32_t)drbid << " (LCID " << (uint32_t)params.lcid << ")"
577 << " (" << packet->GetSize() << " bytes)");
578 it->second->m_pdcp->GetLtePdcpSapProvider()->TransmitPdcpSdu(params);
579 }
580}
581
582void
584{
585 NS_LOG_FUNCTION(this);
586
587 switch (m_state)
588 {
589 case IDLE_START:
590 case IDLE_CELL_SEARCH:
592 case IDLE_WAIT_MIB:
593 case IDLE_WAIT_SIB1:
595 NS_LOG_INFO("already disconnected");
596 break;
597
598 case IDLE_WAIT_SIB2:
599 case IDLE_CONNECTING:
600 NS_FATAL_ERROR("cannot abort connection setup procedure");
601 break;
602
608 break;
609
610 default: // i.e. IDLE_RANDOM_ACCESS
611 NS_FATAL_ERROR("method unexpected in state " << m_state);
612 break;
613 }
614}
615
616void
622
623void
625{
626 NS_LOG_FUNCTION(this << rnti);
627 m_rnti = rnti;
628 m_srb0->m_rlc->SetRnti(m_rnti);
629 m_cphySapProvider.at(0)->SetRnti(m_rnti);
630}
631
632void
634{
635 NS_LOG_FUNCTION(this << m_imsi << m_state);
637
638 switch (m_state)
639 {
640 case IDLE_RANDOM_ACCESS: {
641 // we just received a RAR with a T-C-RNTI and an UL grant
642 // send RRC connection request as message 3 of the random access procedure
645 msg.ueIdentity = m_imsi;
648 }
649 break;
650
651 case CONNECTED_HANDOVER: {
655
656 // 3GPP TS 36.331 section 5.5.6.1 Measurements related actions upon handover
657 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
658 measIdIt != m_varMeasConfig.measIdList.end();
659 ++measIdIt)
660 {
661 VarMeasReportListClear(measIdIt->second.measId);
662 }
663
665 m_cmacSapProvider.at(0)->NotifyConnectionSuccessful(); // RA successful during handover
667 }
668 break;
669
670 default:
671 NS_FATAL_ERROR("unexpected event in state " << m_state);
672 break;
673 }
674}
675
676void
678{
679 NS_LOG_FUNCTION(this << m_imsi << m_state);
681
682 switch (m_state)
683 {
684 case IDLE_RANDOM_ACCESS: {
687 }
688 break;
689
690 case CONNECTED_HANDOVER: {
692 /**
693 * @todo After a handover failure because of a random access failure,
694 * send an RRC Connection Re-establishment and switch to
695 * CONNECTED_REESTABLISHING state.
696 */
698 {
702 // we should have called NotifyConnectionFailed
703 // but that method would immediately ask you UE to
704 // connect rather than doing cell selection again.
706 }
707 }
708 break;
709
710 default:
711 NS_FATAL_ERROR("unexpected event in state " << m_state);
712 break;
713 }
714}
715
716void
718{
719 NS_LOG_FUNCTION(this << m_imsi << csgId);
720 m_csgWhiteList = csgId;
721}
722
723void
725{
726 NS_LOG_FUNCTION(this << m_imsi << dlEarfcn);
727 NS_ASSERT_MSG(m_state == IDLE_START, "cannot start cell selection from state " << m_state);
728 m_dlEarfcn = dlEarfcn;
729 m_cphySapProvider.at(0)->StartCellSearch(dlEarfcn);
731}
732
733void
734LteUeRrc::DoForceCampedOnEnb(uint16_t cellId, uint32_t dlEarfcn)
735{
736 NS_LOG_FUNCTION(this << m_imsi << cellId << dlEarfcn);
737
738 switch (m_state)
739 {
740 case IDLE_START:
741 m_cellId = cellId;
742 m_dlEarfcn = dlEarfcn;
743 m_cphySapProvider.at(0)->SynchronizeWithEnb(m_cellId, m_dlEarfcn);
745 break;
746
747 case IDLE_CELL_SEARCH:
749 case IDLE_WAIT_SIB1:
750 NS_FATAL_ERROR("cannot abort cell selection " << m_state);
751 break;
752
753 case IDLE_WAIT_MIB:
754 NS_LOG_INFO("already forced to camp to cell " << m_cellId);
755 break;
756
758 case IDLE_WAIT_SIB2:
760 case IDLE_CONNECTING:
761 NS_LOG_INFO("already camped to cell " << m_cellId);
762 break;
763
768 NS_LOG_INFO("already connected to cell " << m_cellId);
769 break;
770
771 default:
772 NS_FATAL_ERROR("unexpected event in state " << m_state);
773 break;
774 }
775}
776
777void
779{
780 NS_LOG_FUNCTION(this << m_imsi);
781
782 switch (m_state)
783 {
784 case IDLE_START:
785 case IDLE_CELL_SEARCH:
787 case IDLE_WAIT_SIB1:
788 case IDLE_WAIT_MIB:
789 m_connectionPending = true;
790 break;
791
793 m_connectionPending = true;
795 break;
796
797 case IDLE_WAIT_SIB2:
799 case IDLE_CONNECTING:
800 NS_LOG_INFO("already connecting");
801 break;
802
806 NS_LOG_INFO("already connected");
807 break;
808
809 default:
810 NS_FATAL_ERROR("unexpected event in state " << m_state);
811 break;
812 }
813}
814
815// CPHY SAP methods
816
817void
819{
821 m_cphySapProvider.at(0)->SetDlBandwidth(msg.dlBandwidth);
822 m_hasReceivedMib = true;
824
825 switch (m_state)
826 {
827 case IDLE_WAIT_MIB:
828 // manual attachment
830 break;
831
833 // automatic attachment from Idle mode cell selection
835 break;
836
837 default:
838 // do nothing extra
839 break;
840 }
841}
842
843void
846{
847 NS_LOG_FUNCTION(this);
848 switch (m_state)
849 {
850 case IDLE_WAIT_SIB1:
852 "Cell identity in SIB1 does not match with the originating cell");
853 m_hasReceivedSib1 = true;
854 m_lastSib1 = msg;
857 break;
858
861 case IDLE_CONNECTING:
867 "Cell identity in SIB1 does not match with the originating cell");
868 m_hasReceivedSib1 = true;
869 m_lastSib1 = msg;
871 break;
872
874 // MIB has not been received, so ignore this SIB1
875
876 default: // e.g. IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_SIB2
877 // do nothing
878 break;
879 }
880}
881
882void
884{
885 NS_LOG_FUNCTION(this);
886
887 // layer 3 filtering does not apply in IDLE mode
888 bool useLayer3Filtering = (m_state == CONNECTED_NORMALLY);
889 bool triggering = true;
890 for (auto newMeasIt = params.m_ueMeasurementsList.begin();
891 newMeasIt != params.m_ueMeasurementsList.end();
892 ++newMeasIt)
893 {
894 if (params.m_componentCarrierId != 0)
895 {
896 triggering = false; // report is triggered only when an event is on the primary carrier
897 // in this case the measurement received is related to secondary carriers
898 }
899 SaveUeMeasurements(newMeasIt->m_cellId,
900 newMeasIt->m_rsrp,
901 newMeasIt->m_rsrq,
902 useLayer3Filtering,
903 params.m_componentCarrierId);
904 }
905
907 {
908 // start decoding BCH
910 }
911 else
912 {
913 if (triggering)
914 {
915 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
916 measIdIt != m_varMeasConfig.measIdList.end();
917 ++measIdIt)
918 {
919 MeasurementReportTriggering(measIdIt->first);
920 }
921 }
922 }
923
924} // end of LteUeRrc::DoReportUeMeasurements
925
926// RRC SAP methods
927
928void
930{
931 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
932 m_srb0->m_rlc->SetLteRlcSapUser(params.srb0SapUser);
933 if (m_srb1)
934 {
935 m_srb1->m_pdcp->SetLtePdcpSapUser(params.srb1SapUser);
936 }
937}
938
939void
941{
942 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
943
944 if (msg.haveSib2)
945 {
946 switch (m_state)
947 {
949 case IDLE_WAIT_SIB2:
951 case IDLE_CONNECTING:
956 m_hasReceivedSib2 = true;
961 rc.numberOfRaPreambles = msg.sib2.radioResourceConfigCommon.rachConfigCommon
963 rc.preambleTransMax = msg.sib2.radioResourceConfigCommon.rachConfigCommon
965 rc.raResponseWindowSize = msg.sib2.radioResourceConfigCommon.rachConfigCommon
967 rc.connEstFailCount =
969 m_connEstFailCountLimit = rc.connEstFailCount;
971 "SIB2 msg contains wrong value " << m_connEstFailCountLimit
972 << "of connEstFailCount");
973 m_cmacSapProvider.at(0)->ConfigureRach(rc);
974 m_cphySapProvider.at(0)->ConfigureUplink(m_ulEarfcn, m_ulBandwidth);
975 m_cphySapProvider.at(0)->ConfigureReferenceSignalPower(
977 if (m_state == IDLE_WAIT_SIB2)
978 {
981 }
982 break;
983
984 default: // IDLE_START, IDLE_CELL_SEARCH, IDLE_WAIT_MIB, IDLE_WAIT_MIB_SIB1, IDLE_WAIT_SIB1
985 // do nothing
986 break;
987 }
988 }
989}
990
991void
993{
994 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
995 switch (m_state)
996 {
997 case IDLE_CONNECTING: {
1002 m_leaveConnectedMode = false;
1007 m_cmacSapProvider.at(0)->NotifyConnectionSuccessful();
1010 "Sync indications should be zero "
1011 "when a new RRC connection is established. Current value = "
1012 << (uint16_t)m_noOfSyncIndications);
1013 }
1014 break;
1015
1016 default:
1017 NS_FATAL_ERROR("method unexpected in state " << m_state);
1018 break;
1019 }
1020}
1021
1022void
1024{
1025 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1026 NS_LOG_INFO("DoRecvRrcConnectionReconfiguration haveNonCriticalExtension:"
1028 switch (m_state)
1029 {
1030 case CONNECTED_NORMALLY:
1032 {
1033 NS_LOG_INFO("haveMobilityControlInfo == true");
1036 {
1038 }
1041 // We should reset the MACs and PHYs for all the component carriers
1042 for (auto cmacSapProvider : m_cmacSapProvider)
1043 {
1044 cmacSapProvider->Reset();
1045 }
1046 for (auto cphySapProvider : m_cphySapProvider)
1047 {
1048 cphySapProvider->Reset();
1049 }
1055 m_cphySapProvider.at(0)->SynchronizeWithEnb(m_cellId, mci.carrierFreq.dlCarrierFreq);
1056 m_cphySapProvider.at(0)->SetDlBandwidth(mci.carrierBandwidth.dlBandwidth);
1057 m_cphySapProvider.at(0)->ConfigureUplink(mci.carrierFreq.ulCarrierFreq,
1060 m_srb0->m_rlc->SetRnti(m_rnti);
1063 "handover is only supported with non-contention-based random access procedure");
1064 m_cmacSapProvider.at(0)->StartNonContentionBasedRandomAccessProcedure(
1065 m_rnti,
1068 m_cphySapProvider.at(0)->SetRnti(m_rnti);
1071
1072 // we re-establish SRB1 by creating a new entity
1073 // note that we can't dispose the old entity now, because
1074 // it's in the current stack, so we would corrupt the stack
1075 // if we did so. Hence we schedule it for later disposal
1076 m_srb1Old = m_srb1;
1078 m_srb1 =
1079 nullptr; // new instance will be be created within ApplyRadioResourceConfigDedicated
1080
1081 m_drbMap.clear(); // dispose all DRBs
1084 {
1085 NS_LOG_DEBUG(this << "RNTI " << m_rnti
1086 << " Handover. Configuring secondary carriers");
1088 }
1089
1090 if (msg.haveMeasConfig)
1091 {
1093 }
1094 // RRC connection reconfiguration completed will be sent
1095 // after handover is complete
1096 }
1097 else
1098 {
1099 NS_LOG_INFO("haveMobilityControlInfo == false");
1101 {
1103 NS_LOG_DEBUG(this << "RNTI " << m_rnti << " Configured for CA");
1104 }
1106 {
1108 }
1109 if (msg.haveMeasConfig)
1110 {
1112 }
1117 }
1118 break;
1119
1120 default:
1121 NS_FATAL_ERROR("method unexpected in state " << m_state);
1122 break;
1123 }
1124}
1125
1126void
1128{
1129 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1130 switch (m_state)
1131 {
1133 /**
1134 * @todo After receiving RRC Connection Re-establishment, stop timer
1135 * T301, fire a new trace source, reply with RRC Connection
1136 * Re-establishment Complete, and finally switch to
1137 * CONNECTED_NORMALLY state. See Section 5.3.7.5 of 3GPP TS
1138 * 36.331.
1139 */
1140 }
1141 break;
1142
1143 default:
1144 NS_FATAL_ERROR("method unexpected in state " << m_state);
1145 break;
1146 }
1147}
1148
1149void
1152{
1153 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1154 switch (m_state)
1155 {
1157 /**
1158 * @todo After receiving RRC Connection Re-establishment Reject, stop
1159 * timer T301. See Section 5.3.7.8 of 3GPP TS 36.331.
1160 */
1161 m_asSapUser->NotifyConnectionReleased(); // Inform upper layers
1162 }
1163 break;
1164
1165 default:
1166 NS_FATAL_ERROR("method unexpected in state " << m_state);
1167 break;
1168 }
1169}
1170
1171void
1173{
1174 NS_LOG_FUNCTION(this << " RNTI " << m_rnti);
1175 /// @todo Currently not implemented, see Section 5.3.8 of 3GPP TS 36.331.
1176
1178 // release resources at UE
1180 {
1181 m_leaveConnectedMode = true;
1185 }
1186}
1187
1188void
1190{
1191 NS_LOG_FUNCTION(this);
1193 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
1194 {
1195 m_cmacSapProvider.at(i)->Reset(); // reset the MAC
1196 }
1197 m_hasReceivedSib2 = false; // invalidate the previously received SIB2
1199 m_asSapUser->NotifyConnectionFailed(); // inform upper layer
1200}
1201
1202void
1203LteUeRrc::DoSetNumberOfComponentCarriers(uint16_t noOfComponentCarriers)
1204{
1205 NS_LOG_FUNCTION(this);
1206 m_numberOfComponentCarriers = noOfComponentCarriers;
1207}
1208
1209void
1211{
1212 NS_LOG_FUNCTION(this);
1214
1215 uint16_t maxRsrpCellId = 0;
1216 double maxRsrp = -std::numeric_limits<double>::infinity();
1217 double minRsrp = -140.0; // Minimum RSRP in dBm a UE can report
1218
1219 for (auto it = m_storedMeasValues.begin(); it != m_storedMeasValues.end(); it++)
1220 {
1221 /*
1222 * This block attempts to find a cell with strongest RSRP and has not
1223 * yet been identified as "acceptable cell".
1224 */
1225 if (maxRsrp < it->second.rsrp && it->second.rsrp > minRsrp)
1226 {
1227 auto itCell = m_acceptableCell.find(it->first);
1228 if (itCell == m_acceptableCell.end())
1229 {
1230 maxRsrpCellId = it->first;
1231 maxRsrp = it->second.rsrp;
1232 }
1233 }
1234 }
1235
1236 if (maxRsrpCellId == 0)
1237 {
1238 NS_LOG_WARN(this << " Cell search is unable to detect surrounding cell to attach to");
1239 }
1240 else
1241 {
1242 NS_LOG_LOGIC(this << " cell " << maxRsrpCellId
1243 << " is the strongest untried surrounding cell");
1244 m_cphySapProvider.at(0)->SynchronizeWithEnb(maxRsrpCellId, m_dlEarfcn);
1246 }
1247
1248} // end of void LteUeRrc::SynchronizeToStrongestCell ()
1249
1250void
1252{
1253 NS_LOG_FUNCTION(this);
1258
1259 // Cell selection criteria evaluation
1260
1261 bool isSuitableCell = false;
1262 bool isAcceptableCell = false;
1263 auto storedMeasIt = m_storedMeasValues.find(cellId);
1264 double qRxLevMeas = storedMeasIt->second.rsrp;
1265 double qRxLevMin =
1267 NS_LOG_LOGIC(this << " cell selection to cellId=" << cellId << " qrxlevmeas=" << qRxLevMeas
1268 << " dBm"
1269 << " qrxlevmin=" << qRxLevMin << " dBm");
1270
1271 if (qRxLevMeas - qRxLevMin > 0)
1272 {
1273 isAcceptableCell = true;
1274
1276 bool cellCsgIndication = m_lastSib1.cellAccessRelatedInfo.csgIndication;
1277
1278 isSuitableCell = (!cellCsgIndication || cellCsgId == m_csgWhiteList);
1279
1280 NS_LOG_LOGIC(this << " csg(ue/cell/indication)=" << m_csgWhiteList << "/" << cellCsgId
1281 << "/" << cellCsgIndication);
1282 }
1283
1284 // Cell selection decision
1285
1286 if (isSuitableCell)
1287 {
1288 m_cellId = cellId;
1289 m_cphySapProvider.at(0)->SynchronizeWithEnb(cellId, m_dlEarfcn);
1290 m_cphySapProvider.at(0)->SetDlBandwidth(m_dlBandwidth);
1292 // Once the UE is connected, m_connectionPending is
1293 // set to false. So, when RLF occurs and UE performs
1294 // cell selection upon leaving RRC_CONNECTED state,
1295 // the following call to DoConnect will make the
1296 // m_connectionPending to be true again. Thus,
1297 // upon calling SwitchToState (IDLE_CAMPED_NORMALLY)
1298 // UE state is instantly change to IDLE_WAIT_SIB2.
1299 // This will make the UE to read the SIB2 message
1300 // and start random access.
1302 {
1303 NS_LOG_DEBUG("Calling DoConnect in state = " << m_state);
1304 DoConnect();
1305 }
1307 }
1308 else
1309 {
1310 // ignore the MIB and SIB1 received from this cell
1311 m_hasReceivedMib = false;
1312 m_hasReceivedSib1 = false;
1313
1315
1316 if (isAcceptableCell)
1317 {
1318 /*
1319 * The cells inserted into this list will not be considered for
1320 * subsequent cell search attempt.
1321 */
1322 m_acceptableCell.insert(cellId);
1323 }
1324
1326 SynchronizeToStrongestCell(); // retry to a different cell
1327 }
1328
1329} // end of void LteUeRrc::EvaluateCellForSelection ()
1330
1331void
1334{
1335 NS_LOG_FUNCTION(this);
1336
1338
1339 for (uint32_t sCellIndex : nonCec.sCellToReleaseList)
1340 {
1341 m_cphySapProvider.at(sCellIndex)->Reset();
1342 m_cmacSapProvider.at(sCellIndex)->Reset();
1343 }
1344
1345 for (auto& scell : nonCec.sCellToAddModList)
1346 {
1347 uint8_t ccId = scell.sCellIndex;
1348
1349 uint16_t physCellId = scell.cellIdentification.physCellId;
1350 uint16_t ulBand =
1351 scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulBandwidth;
1352 uint32_t ulEarfcn =
1353 scell.radioResourceConfigCommonSCell.ulConfiguration.ulFreqInfo.ulCarrierFreq;
1354 uint16_t dlBand = scell.radioResourceConfigCommonSCell.nonUlConfiguration.dlBandwidth;
1355 uint32_t dlEarfcn = scell.cellIdentification.dlCarrierFreq;
1356 uint8_t txMode = scell.radioResourceConfigDedicatedSCell.physicalConfigDedicatedSCell
1357 .antennaInfo.transmissionMode;
1358 uint16_t srsIndex = scell.radioResourceConfigDedicatedSCell.physicalConfigDedicatedSCell
1359 .soundingRsUlConfigDedicated.srsConfigIndex;
1360
1361 m_cphySapProvider.at(ccId)->SynchronizeWithEnb(physCellId, dlEarfcn);
1362 m_cphySapProvider.at(ccId)->SetDlBandwidth(dlBand);
1363 m_cphySapProvider.at(ccId)->ConfigureUplink(ulEarfcn, ulBand);
1364 m_cphySapProvider.at(ccId)->ConfigureReferenceSignalPower(
1365 scell.radioResourceConfigCommonSCell.nonUlConfiguration.pdschConfigCommon
1366 .referenceSignalPower);
1367 m_cphySapProvider.at(ccId)->SetTransmissionMode(txMode);
1368 m_cphySapProvider.at(ccId)->SetRnti(m_rnti);
1369 m_cmacSapProvider.at(ccId)->SetRnti(m_rnti);
1370 // update PdschConfigDedicated (i.e. P_A value)
1371 LteRrcSap::PdschConfigDedicated pdschConfigDedicated =
1372 scell.radioResourceConfigDedicatedSCell.physicalConfigDedicatedSCell
1373 .pdschConfigDedicated;
1374 double paDouble = LteRrcSap::ConvertPdschConfigDedicated2Double(pdschConfigDedicated);
1375 m_cphySapProvider.at(ccId)->SetPa(paDouble);
1376 m_cphySapProvider.at(ccId)->SetSrsConfigurationIndex(srsIndex);
1377 }
1378
1380}
1381
1382void
1384{
1385 NS_LOG_FUNCTION(this);
1387
1389 {
1390 m_cphySapProvider.at(0)->SetTransmissionMode(pcd.antennaInfo.transmissionMode);
1391 }
1393 {
1394 m_cphySapProvider.at(0)->SetSrsConfigurationIndex(
1396 }
1397
1399 {
1400 // update PdschConfigDedicated (i.e. P_A value)
1403 m_cphySapProvider.at(0)->SetPa(paDouble);
1404 }
1405
1406 auto stamIt = rrcd.srbToAddModList.begin();
1407 if (stamIt != rrcd.srbToAddModList.end())
1408 {
1409 if (!m_srb1)
1410 {
1411 // SRB1 not setup yet
1413 "unexpected state " << m_state);
1414 NS_ASSERT_MSG(stamIt->srbIdentity == 1, "only SRB1 supported");
1415
1416 const uint8_t lcid = 1; // fixed LCID for SRB1
1417
1419 rlc->SetLteMacSapProvider(m_macSapProvider);
1420 rlc->SetRnti(m_rnti);
1421 rlc->SetLcId(lcid);
1422
1424 pdcp->SetRnti(m_rnti);
1425 pdcp->SetLcId(lcid);
1426 pdcp->SetLtePdcpSapUser(m_drbPdcpSapUser);
1427 pdcp->SetLteRlcSapProvider(rlc->GetLteRlcSapProvider());
1428 rlc->SetLteRlcSapUser(pdcp->GetLteRlcSapUser());
1429
1431 m_srb1->m_rlc = rlc;
1432 m_srb1->m_pdcp = pdcp;
1433 m_srb1->m_srbIdentity = 1;
1435
1436 m_srb1->m_logicalChannelConfig.priority = stamIt->logicalChannelConfig.priority;
1437 m_srb1->m_logicalChannelConfig.prioritizedBitRateKbps =
1438 stamIt->logicalChannelConfig.prioritizedBitRateKbps;
1439 m_srb1->m_logicalChannelConfig.bucketSizeDurationMs =
1440 stamIt->logicalChannelConfig.bucketSizeDurationMs;
1441 m_srb1->m_logicalChannelConfig.logicalChannelGroup =
1442 stamIt->logicalChannelConfig.logicalChannelGroup;
1443
1445 lcConfig.priority = stamIt->logicalChannelConfig.priority;
1446 lcConfig.prioritizedBitRateKbps = stamIt->logicalChannelConfig.prioritizedBitRateKbps;
1447 lcConfig.bucketSizeDurationMs = stamIt->logicalChannelConfig.bucketSizeDurationMs;
1448 lcConfig.logicalChannelGroup = stamIt->logicalChannelConfig.logicalChannelGroup;
1449 LteMacSapUser* msu =
1450 m_ccmRrcSapProvider->ConfigureSignalBearer(lcid, lcConfig, rlc->GetLteMacSapUser());
1451 m_cmacSapProvider.at(0)->AddLc(lcid, lcConfig, msu);
1452 ++stamIt;
1453 NS_ASSERT_MSG(stamIt == rrcd.srbToAddModList.end(), "at most one SrbToAdd supported");
1454
1456 ueParams.srb0SapProvider = m_srb0->m_rlc->GetLteRlcSapProvider();
1457 ueParams.srb1SapProvider = m_srb1->m_pdcp->GetLtePdcpSapProvider();
1458 m_rrcSapUser->Setup(ueParams);
1459 }
1460 else
1461 {
1462 NS_LOG_INFO("request to modify SRB1 (skipping as currently not implemented)");
1463 // would need to modify m_srb1, and then propagate changes to the MAC
1464 }
1465 }
1466
1467 for (auto dtamIt = rrcd.drbToAddModList.begin(); dtamIt != rrcd.drbToAddModList.end(); ++dtamIt)
1468 {
1469 NS_LOG_INFO(this << " IMSI " << m_imsi << " adding/modifying DRBID "
1470 << (uint32_t)dtamIt->drbIdentity << " LC "
1471 << (uint32_t)dtamIt->logicalChannelIdentity);
1472 NS_ASSERT_MSG(dtamIt->logicalChannelIdentity > 2,
1473 "LCID value " << dtamIt->logicalChannelIdentity << " is reserved for SRBs");
1474
1475 auto drbMapIt = m_drbMap.find(dtamIt->drbIdentity);
1476 if (drbMapIt == m_drbMap.end())
1477 {
1478 NS_LOG_INFO("New Data Radio Bearer");
1479
1480 TypeId rlcTypeId;
1481 if (m_useRlcSm)
1482 {
1483 rlcTypeId = LteRlcSm::GetTypeId();
1484 }
1485 else
1486 {
1487 switch (dtamIt->rlcConfig.choice)
1488 {
1490 rlcTypeId = LteRlcAm::GetTypeId();
1491 break;
1492
1494 rlcTypeId = LteRlcUm::GetTypeId();
1495 break;
1496
1497 default:
1498 NS_FATAL_ERROR("unsupported RLC configuration");
1499 break;
1500 }
1501 }
1502
1503 ObjectFactory rlcObjectFactory;
1504 rlcObjectFactory.SetTypeId(rlcTypeId);
1505 Ptr<LteRlc> rlc = rlcObjectFactory.Create()->GetObject<LteRlc>();
1506 rlc->SetLteMacSapProvider(m_macSapProvider);
1507 rlc->SetRnti(m_rnti);
1508 rlc->SetLcId(dtamIt->logicalChannelIdentity);
1509
1511 drbInfo->m_rlc = rlc;
1512 drbInfo->m_epsBearerIdentity = dtamIt->epsBearerIdentity;
1513 drbInfo->m_logicalChannelIdentity = dtamIt->logicalChannelIdentity;
1514 drbInfo->m_drbIdentity = dtamIt->drbIdentity;
1515
1516 // we need PDCP only for real RLC, i.e., RLC/UM or RLC/AM
1517 // if we are using RLC/SM we don't care of anything above RLC
1518 if (rlcTypeId != LteRlcSm::GetTypeId())
1519 {
1521 pdcp->SetRnti(m_rnti);
1522 pdcp->SetLcId(dtamIt->logicalChannelIdentity);
1523 pdcp->SetLtePdcpSapUser(m_drbPdcpSapUser);
1524 pdcp->SetLteRlcSapProvider(rlc->GetLteRlcSapProvider());
1525 rlc->SetLteRlcSapUser(pdcp->GetLteRlcSapUser());
1526 drbInfo->m_pdcp = pdcp;
1527 }
1528
1529 m_bid2DrbidMap[dtamIt->epsBearerIdentity] = dtamIt->drbIdentity;
1530
1531 m_drbMap.insert(
1532 std::pair<uint8_t, Ptr<LteDataRadioBearerInfo>>(dtamIt->drbIdentity, drbInfo));
1533
1534 m_drbCreatedTrace(m_imsi, m_cellId, m_rnti, dtamIt->drbIdentity);
1535
1537 lcConfig.priority = dtamIt->logicalChannelConfig.priority;
1538 lcConfig.prioritizedBitRateKbps = dtamIt->logicalChannelConfig.prioritizedBitRateKbps;
1539 lcConfig.bucketSizeDurationMs = dtamIt->logicalChannelConfig.bucketSizeDurationMs;
1540 lcConfig.logicalChannelGroup = dtamIt->logicalChannelConfig.logicalChannelGroup;
1541
1542 NS_LOG_DEBUG(this << " UE RRC RNTI " << m_rnti << " Number Of Component Carriers "
1543 << m_numberOfComponentCarriers << " lcID "
1544 << (uint16_t)dtamIt->logicalChannelIdentity);
1545 // Call AddLc of UE component carrier manager
1546 std::vector<LteUeCcmRrcSapProvider::LcsConfig> lcOnCcMapping =
1547 m_ccmRrcSapProvider->AddLc(dtamIt->logicalChannelIdentity,
1548 lcConfig,
1549 rlc->GetLteMacSapUser());
1550
1551 NS_LOG_DEBUG("Size of lcOnCcMapping vector " << lcOnCcMapping.size());
1552 auto itLcOnCcMapping = lcOnCcMapping.begin();
1553 NS_ASSERT_MSG(itLcOnCcMapping != lcOnCcMapping.end(),
1554 "Component carrier manager failed to add LC for data radio bearer");
1555
1556 for (itLcOnCcMapping = lcOnCcMapping.begin(); itLcOnCcMapping != lcOnCcMapping.end();
1557 ++itLcOnCcMapping)
1558 {
1559 NS_LOG_DEBUG("RNTI " << m_rnti << " LCG id "
1560 << (uint16_t)itLcOnCcMapping->lcConfig.logicalChannelGroup
1561 << " ComponentCarrierId "
1562 << (uint16_t)itLcOnCcMapping->componentCarrierId);
1563 uint8_t index = itLcOnCcMapping->componentCarrierId;
1565 itLcOnCcMapping->lcConfig;
1566 LteMacSapUser* msu = itLcOnCcMapping->msu;
1567 m_cmacSapProvider.at(index)->AddLc(dtamIt->logicalChannelIdentity,
1568 lcConfigFromCcm,
1569 msu);
1570 }
1571
1572 rlc->Initialize();
1573 }
1574 else
1575 {
1576 NS_LOG_INFO("request to modify existing DRBID");
1577 Ptr<LteDataRadioBearerInfo> drbInfo = drbMapIt->second;
1578 /// @todo currently not implemented. Would need to modify drbInfo, and then propagate
1579 /// changes to the MAC
1580 }
1581 }
1582
1583 for (auto dtdmIt = rrcd.drbToReleaseList.begin(); dtdmIt != rrcd.drbToReleaseList.end();
1584 ++dtdmIt)
1585 {
1586 uint8_t drbid = *dtdmIt;
1587 NS_LOG_INFO(this << " IMSI " << m_imsi << " releasing DRB " << (uint32_t)drbid);
1588 auto it = m_drbMap.find(drbid);
1589 NS_ASSERT_MSG(it != m_drbMap.end(), "could not find bearer with given lcid");
1590 m_drbMap.erase(it);
1591 m_bid2DrbidMap.erase(drbid);
1592 // Remove LCID
1593 for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
1594 {
1595 m_cmacSapProvider.at(i)->RemoveLc(drbid + 2);
1596 }
1597 }
1598}
1599
1600void
1602{
1603 NS_LOG_FUNCTION(this);
1604
1605 // perform the actions specified in 3GPP TS 36.331 section 5.5.2.1
1606
1607 // 3GPP TS 36.331 section 5.5.2.4 Measurement object removal
1608 for (auto it = mc.measObjectToRemoveList.begin(); it != mc.measObjectToRemoveList.end(); ++it)
1609 {
1610 uint8_t measObjectId = *it;
1611 NS_LOG_LOGIC(this << " deleting measObjectId " << (uint32_t)measObjectId);
1612 m_varMeasConfig.measObjectList.erase(measObjectId);
1613 auto measIdIt = m_varMeasConfig.measIdList.begin();
1614 while (measIdIt != m_varMeasConfig.measIdList.end())
1615 {
1616 if (measIdIt->second.measObjectId == measObjectId)
1617 {
1618 uint8_t measId = measIdIt->second.measId;
1619 NS_ASSERT(measId == measIdIt->first);
1620 NS_LOG_LOGIC(this << " deleting measId " << (uint32_t)measId
1621 << " because referring to measObjectId "
1622 << (uint32_t)measObjectId);
1623 // note: postfix operator preserves iterator validity
1624 m_varMeasConfig.measIdList.erase(measIdIt++);
1625 VarMeasReportListClear(measId);
1626 }
1627 else
1628 {
1629 ++measIdIt;
1630 }
1631 }
1632 }
1633
1634 // 3GPP TS 36.331 section 5.5.2.5 Measurement object addition/ modification
1635 for (auto it = mc.measObjectToAddModList.begin(); it != mc.measObjectToAddModList.end(); ++it)
1636 {
1637 // simplifying assumptions
1638 NS_ASSERT_MSG(it->measObjectEutra.cellsToRemoveList.empty(),
1639 "cellsToRemoveList not supported");
1640 NS_ASSERT_MSG(it->measObjectEutra.cellsToAddModList.empty(),
1641 "cellsToAddModList not supported");
1642 NS_ASSERT_MSG(it->measObjectEutra.cellsToRemoveList.empty(),
1643 "blackCellsToRemoveList not supported");
1644 NS_ASSERT_MSG(it->measObjectEutra.blackCellsToAddModList.empty(),
1645 "blackCellsToAddModList not supported");
1646 NS_ASSERT_MSG(it->measObjectEutra.haveCellForWhichToReportCGI == false,
1647 "cellForWhichToReportCGI is not supported");
1648
1649 uint8_t measObjectId = it->measObjectId;
1650 auto measObjectIt = m_varMeasConfig.measObjectList.find(measObjectId);
1651 if (measObjectIt != m_varMeasConfig.measObjectList.end())
1652 {
1653 NS_LOG_LOGIC("measObjectId " << (uint32_t)measObjectId << " exists, updating entry");
1654 measObjectIt->second = *it;
1655 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
1656 measIdIt != m_varMeasConfig.measIdList.end();
1657 ++measIdIt)
1658 {
1659 if (measIdIt->second.measObjectId == measObjectId)
1660 {
1661 uint8_t measId = measIdIt->second.measId;
1662 NS_LOG_LOGIC(this << " found measId " << (uint32_t)measId
1663 << " referring to measObjectId " << (uint32_t)measObjectId);
1664 VarMeasReportListClear(measId);
1665 }
1666 }
1667 }
1668 else
1669 {
1670 NS_LOG_LOGIC("measObjectId " << (uint32_t)measObjectId << " is new, adding entry");
1671 m_varMeasConfig.measObjectList[measObjectId] = *it;
1672 }
1673 }
1674
1675 // 3GPP TS 36.331 section 5.5.2.6 Reporting configuration removal
1676 for (auto it = mc.reportConfigToRemoveList.begin(); it != mc.reportConfigToRemoveList.end();
1677 ++it)
1678 {
1679 uint8_t reportConfigId = *it;
1680 NS_LOG_LOGIC(this << " deleting reportConfigId " << (uint32_t)reportConfigId);
1681 m_varMeasConfig.reportConfigList.erase(reportConfigId);
1682 auto measIdIt = m_varMeasConfig.measIdList.begin();
1683 while (measIdIt != m_varMeasConfig.measIdList.end())
1684 {
1685 if (measIdIt->second.reportConfigId == reportConfigId)
1686 {
1687 uint8_t measId = measIdIt->second.measId;
1688 NS_ASSERT(measId == measIdIt->first);
1689 NS_LOG_LOGIC(this << " deleting measId " << (uint32_t)measId
1690 << " because referring to reportConfigId "
1691 << (uint32_t)reportConfigId);
1692 // note: postfix operator preserves iterator validity
1693 m_varMeasConfig.measIdList.erase(measIdIt++);
1694 VarMeasReportListClear(measId);
1695 }
1696 else
1697 {
1698 ++measIdIt;
1699 }
1700 }
1701 }
1702
1703 // 3GPP TS 36.331 section 5.5.2.7 Reporting configuration addition/ modification
1704 for (auto it = mc.reportConfigToAddModList.begin(); it != mc.reportConfigToAddModList.end();
1705 ++it)
1706 {
1707 // simplifying assumptions
1708 NS_ASSERT_MSG(it->reportConfigEutra.triggerType == LteRrcSap::ReportConfigEutra::EVENT,
1709 "only trigger type EVENT is supported");
1710
1711 uint8_t reportConfigId = it->reportConfigId;
1712 auto reportConfigIt = m_varMeasConfig.reportConfigList.find(reportConfigId);
1713 if (reportConfigIt != m_varMeasConfig.reportConfigList.end())
1714 {
1715 NS_LOG_LOGIC("reportConfigId " << (uint32_t)reportConfigId
1716 << " exists, updating entry");
1717 m_varMeasConfig.reportConfigList[reportConfigId] = *it;
1718 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
1719 measIdIt != m_varMeasConfig.measIdList.end();
1720 ++measIdIt)
1721 {
1722 if (measIdIt->second.reportConfigId == reportConfigId)
1723 {
1724 uint8_t measId = measIdIt->second.measId;
1725 NS_LOG_LOGIC(this << " found measId " << (uint32_t)measId
1726 << " referring to reportConfigId "
1727 << (uint32_t)reportConfigId);
1728 VarMeasReportListClear(measId);
1729 }
1730 }
1731 }
1732 else
1733 {
1734 NS_LOG_LOGIC("reportConfigId " << (uint32_t)reportConfigId << " is new, adding entry");
1735 m_varMeasConfig.reportConfigList[reportConfigId] = *it;
1736 }
1737 }
1738
1739 // 3GPP TS 36.331 section 5.5.2.8 Quantity configuration
1740 if (mc.haveQuantityConfig)
1741 {
1742 NS_LOG_LOGIC(this << " setting quantityConfig");
1744 // Convey the filter coefficient to PHY layer so it can configure the power control
1745 // parameter
1746 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
1747 {
1748 m_cphySapProvider.at(i)->SetRsrpFilterCoefficient(
1750 }
1751 // we calculate here the coefficient a used for Layer 3 filtering, see 3GPP TS 36.331
1752 // section 5.5.3.2
1755 NS_LOG_LOGIC(this << " new filter coefficients: aRsrp=" << m_varMeasConfig.aRsrp
1756 << ", aRsrq=" << m_varMeasConfig.aRsrq);
1757
1758 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
1759 measIdIt != m_varMeasConfig.measIdList.end();
1760 ++measIdIt)
1761 {
1762 VarMeasReportListClear(measIdIt->second.measId);
1763 }
1764 }
1765
1766 // 3GPP TS 36.331 section 5.5.2.2 Measurement identity removal
1767 for (auto it = mc.measIdToRemoveList.begin(); it != mc.measIdToRemoveList.end(); ++it)
1768 {
1769 uint8_t measId = *it;
1770 NS_LOG_LOGIC(this << " deleting measId " << (uint32_t)measId);
1771 m_varMeasConfig.measIdList.erase(measId);
1772 VarMeasReportListClear(measId);
1773
1774 // removing time-to-trigger queues
1775 m_enteringTriggerQueue.erase(measId);
1776 m_leavingTriggerQueue.erase(measId);
1777 }
1778
1779 // 3GPP TS 36.331 section 5.5.2.3 Measurement identity addition/ modification
1780 for (auto it = mc.measIdToAddModList.begin(); it != mc.measIdToAddModList.end(); ++it)
1781 {
1782 NS_LOG_LOGIC(this << " measId " << (uint32_t)it->measId
1783 << " (measObjectId=" << (uint32_t)it->measObjectId
1784 << ", reportConfigId=" << (uint32_t)it->reportConfigId << ")");
1785 NS_ASSERT(m_varMeasConfig.measObjectList.find(it->measObjectId) !=
1787 NS_ASSERT(m_varMeasConfig.reportConfigList.find(it->reportConfigId) !=
1789 m_varMeasConfig.measIdList[it->measId] = *it; // side effect: create new entry if not exists
1790 auto measReportIt = m_varMeasReportList.find(it->measId);
1791 if (measReportIt != m_varMeasReportList.end())
1792 {
1793 measReportIt->second.periodicReportTimer.Cancel();
1794 m_varMeasReportList.erase(measReportIt);
1795 }
1796 NS_ASSERT(m_varMeasConfig.reportConfigList.find(it->reportConfigId)
1797 ->second.reportConfigEutra.triggerType !=
1799
1800 // new empty queues for time-to-trigger
1801 std::list<PendingTrigger_t> s;
1802 m_enteringTriggerQueue[it->measId] = s;
1803 m_leavingTriggerQueue[it->measId] = s;
1804 }
1805
1806 if (mc.haveMeasGapConfig)
1807 {
1808 NS_FATAL_ERROR("measurement gaps are currently not supported");
1809 }
1810
1811 if (mc.haveSmeasure)
1812 {
1813 NS_FATAL_ERROR("s-measure is currently not supported");
1814 }
1815
1816 if (mc.haveSpeedStatePars)
1817 {
1818 NS_FATAL_ERROR("SpeedStatePars are currently not supported");
1819 }
1820}
1821
1822void
1824 double rsrp,
1825 double rsrq,
1826 bool useLayer3Filtering,
1827 uint8_t componentCarrierId)
1828{
1829 NS_LOG_FUNCTION(this << cellId << +componentCarrierId << rsrp << rsrq << useLayer3Filtering);
1830
1831 auto storedMeasIt = m_storedMeasValues.find(cellId);
1832
1833 if (storedMeasIt != m_storedMeasValues.end())
1834 {
1835 if (useLayer3Filtering)
1836 {
1837 // F_n = (1-a) F_{n-1} + a M_n
1838 storedMeasIt->second.rsrp = (1 - m_varMeasConfig.aRsrp) * storedMeasIt->second.rsrp +
1839 m_varMeasConfig.aRsrp * rsrp;
1840
1841 if (std::isnan(storedMeasIt->second.rsrq))
1842 {
1843 // the previous RSRQ measurements provided UE PHY are invalid
1844 storedMeasIt->second.rsrq = rsrq; // replace it with unfiltered value
1845 }
1846 else
1847 {
1848 storedMeasIt->second.rsrq =
1849 (1 - m_varMeasConfig.aRsrq) * storedMeasIt->second.rsrq +
1850 m_varMeasConfig.aRsrq * rsrq;
1851 }
1852 }
1853 else
1854 {
1855 storedMeasIt->second.rsrp = rsrp;
1856 storedMeasIt->second.rsrq = rsrq;
1857 }
1858 }
1859 else
1860 {
1861 // first value is always unfiltered
1862 MeasValues v;
1863 v.rsrp = rsrp;
1864 v.rsrq = rsrq;
1865 v.carrierFreq = m_cphySapProvider.at(componentCarrierId)->GetDlEarfcn();
1866
1867 std::pair<uint16_t, MeasValues> val(cellId, v);
1868 auto ret = m_storedMeasValues.insert(val);
1869 NS_ASSERT_MSG(ret.second == true, "element already existed");
1870 storedMeasIt = ret.first;
1871 }
1872
1873 NS_LOG_DEBUG(this << " IMSI " << m_imsi << " state " << m_state << ", measured cell " << cellId
1874 << ", carrier component Id " << componentCarrierId << ", new RSRP " << rsrp
1875 << " stored " << storedMeasIt->second.rsrp << ", new RSRQ " << rsrq
1876 << " stored " << storedMeasIt->second.rsrq);
1877
1878} // end of void SaveUeMeasurements
1879
1880void
1882{
1883 NS_LOG_FUNCTION(this << (uint16_t)measId);
1884
1885 auto measIdIt = m_varMeasConfig.measIdList.find(measId);
1886 NS_ASSERT(measIdIt != m_varMeasConfig.measIdList.end());
1887 NS_ASSERT(measIdIt->first == measIdIt->second.measId);
1888
1889 auto reportConfigIt = m_varMeasConfig.reportConfigList.find(measIdIt->second.reportConfigId);
1890 NS_ASSERT(reportConfigIt != m_varMeasConfig.reportConfigList.end());
1891 LteRrcSap::ReportConfigEutra& reportConfigEutra = reportConfigIt->second.reportConfigEutra;
1892
1893 auto measObjectIt = m_varMeasConfig.measObjectList.find(measIdIt->second.measObjectId);
1894 NS_ASSERT(measObjectIt != m_varMeasConfig.measObjectList.end());
1895 LteRrcSap::MeasObjectEutra& measObjectEutra = measObjectIt->second.measObjectEutra;
1896
1897 auto measReportIt = m_varMeasReportList.find(measId);
1898 bool isMeasIdInReportList = (measReportIt != m_varMeasReportList.end());
1899
1900 // we don't check the purpose field, as it is only included for
1901 // triggerType == periodical, which is not supported
1903 "only triggerType == event is supported");
1904 // only EUTRA is supported, no need to check for it
1905
1906 NS_LOG_LOGIC(this << " considering measId " << (uint32_t)measId);
1907 bool eventEntryCondApplicable = false;
1908 bool eventLeavingCondApplicable = false;
1909 ConcernedCells_t concernedCellsEntry;
1910 ConcernedCells_t concernedCellsLeaving;
1911
1912 /*
1913 * Find which serving cell corresponds to measObjectEutra.carrierFreq
1914 * It is used, for example, by A1 event:
1915 * See TS 36.331 5.5.4.2: "for this measurement, consider the primary or
1916 * secondary cell that is configured on the frequency indicated in the
1917 * associated measObjectEUTRA to be the serving cell"
1918 */
1919 uint16_t servingCellId = 0;
1920 for (auto cphySapProvider : m_cphySapProvider)
1921 {
1922 if (cphySapProvider->GetDlEarfcn() == measObjectEutra.carrierFreq)
1923 {
1924 servingCellId = cphySapProvider->GetCellId();
1925 }
1926 }
1927
1928 if (servingCellId == 0)
1929 {
1930 return;
1931 }
1932
1933 switch (reportConfigEutra.eventId)
1934 {
1936 /*
1937 * Event A1 (Serving becomes better than threshold)
1938 * Please refer to 3GPP TS 36.331 Section 5.5.4.2
1939 */
1940
1941 double ms; // Ms, the measurement result of the serving cell
1942 double thresh; // Thresh, the threshold parameter for this event
1943 // Hys, the hysteresis parameter for this event.
1944 double hys =
1946
1947 switch (reportConfigEutra.triggerQuantity)
1948 {
1950 ms = m_storedMeasValues[servingCellId].rsrp;
1951
1952 NS_ASSERT(reportConfigEutra.threshold1.choice ==
1954 thresh = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold1.range);
1955 break;
1957 ms = m_storedMeasValues[servingCellId].rsrq;
1958 NS_ASSERT(reportConfigEutra.threshold1.choice ==
1960 thresh = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold1.range);
1961 break;
1962 default:
1963 NS_FATAL_ERROR("unsupported triggerQuantity");
1964 break;
1965 }
1966
1967 // Inequality A1-1 (Entering condition): Ms - Hys > Thresh
1968 bool entryCond = ms - hys > thresh;
1969
1970 if (entryCond)
1971 {
1972 if (!isMeasIdInReportList)
1973 {
1974 concernedCellsEntry.push_back(servingCellId);
1975 eventEntryCondApplicable = true;
1976 }
1977 else
1978 {
1979 /*
1980 * This is to check that the triggered cell recorded in the
1981 * VarMeasReportList is the serving cell.
1982 */
1983 NS_ASSERT(measReportIt->second.cellsTriggeredList.find(servingCellId) !=
1984 measReportIt->second.cellsTriggeredList.end());
1985 }
1986 }
1987 else if (reportConfigEutra.timeToTrigger > 0)
1988 {
1989 CancelEnteringTrigger(measId);
1990 }
1991
1992 // Inequality A1-2 (Leaving condition): Ms + Hys < Thresh
1993 bool leavingCond = ms + hys < thresh;
1994
1995 if (leavingCond)
1996 {
1997 if (isMeasIdInReportList)
1998 {
1999 /*
2000 * This is to check that the triggered cell recorded in the
2001 * VarMeasReportList is the serving cell.
2002 */
2003 NS_ASSERT(measReportIt->second.cellsTriggeredList.find(m_cellId) !=
2004 measReportIt->second.cellsTriggeredList.end());
2005 concernedCellsLeaving.push_back(m_cellId);
2006 eventLeavingCondApplicable = true;
2007 }
2008 }
2009 else if (reportConfigEutra.timeToTrigger > 0)
2010 {
2011 CancelLeavingTrigger(measId);
2012 }
2013
2014 NS_LOG_LOGIC(this << " event A1: serving cell " << servingCellId << " ms=" << ms
2015 << " thresh=" << thresh << " entryCond=" << entryCond
2016 << " leavingCond=" << leavingCond);
2017
2018 } // end of case LteRrcSap::ReportConfigEutra::EVENT_A1
2019
2020 break;
2021
2023 /*
2024 * Event A2 (Serving becomes worse than threshold)
2025 * Please refer to 3GPP TS 36.331 Section 5.5.4.3
2026 */
2027
2028 double ms; // Ms, the measurement result of the serving cell
2029 double thresh; // Thresh, the threshold parameter for this event
2030 // Hys, the hysteresis parameter for this event.
2031 double hys =
2033
2034 switch (reportConfigEutra.triggerQuantity)
2035 {
2037 ms = m_storedMeasValues[servingCellId].rsrp;
2038 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2040 thresh = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold1.range);
2041 break;
2043 ms = m_storedMeasValues[servingCellId].rsrq;
2044 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2046 thresh = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold1.range);
2047 break;
2048 default:
2049 NS_FATAL_ERROR("unsupported triggerQuantity");
2050 break;
2051 }
2052
2053 // Inequality A2-1 (Entering condition): Ms + Hys < Thresh
2054 bool entryCond = ms + hys < thresh;
2055
2056 if (entryCond)
2057 {
2058 if (!isMeasIdInReportList)
2059 {
2060 concernedCellsEntry.push_back(servingCellId);
2061 eventEntryCondApplicable = true;
2062 }
2063 else
2064 {
2065 /*
2066 * This is to check that the triggered cell recorded in the
2067 * VarMeasReportList is the serving cell.
2068 */
2069 NS_ASSERT(measReportIt->second.cellsTriggeredList.find(servingCellId) !=
2070 measReportIt->second.cellsTriggeredList.end());
2071 }
2072 }
2073 else if (reportConfigEutra.timeToTrigger > 0)
2074 {
2075 CancelEnteringTrigger(measId);
2076 }
2077
2078 // Inequality A2-2 (Leaving condition): Ms - Hys > Thresh
2079 bool leavingCond = ms - hys > thresh;
2080
2081 if (leavingCond)
2082 {
2083 if (isMeasIdInReportList)
2084 {
2085 /*
2086 * This is to check that the triggered cell recorded in the
2087 * VarMeasReportList is the serving cell.
2088 */
2089 NS_ASSERT(measReportIt->second.cellsTriggeredList.find(servingCellId) !=
2090 measReportIt->second.cellsTriggeredList.end());
2091 concernedCellsLeaving.push_back(servingCellId);
2092 eventLeavingCondApplicable = true;
2093 }
2094 }
2095 else if (reportConfigEutra.timeToTrigger > 0)
2096 {
2097 CancelLeavingTrigger(measId);
2098 }
2099
2100 NS_LOG_LOGIC(this << " event A2: serving cell " << servingCellId << " ms=" << ms
2101 << " thresh=" << thresh << " entryCond=" << entryCond
2102 << " leavingCond=" << leavingCond);
2103
2104 } // end of case LteRrcSap::ReportConfigEutra::EVENT_A2
2105
2106 break;
2107
2109 /*
2110 * Event A3 (Neighbour becomes offset better than PCell)
2111 * Please refer to 3GPP TS 36.331 Section 5.5.4.4
2112 */
2113
2114 double mn; // Mn, the measurement result of the neighbouring cell
2115 double ofn = measObjectEutra
2116 .offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2117 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2118 double mp; // Mp, the measurement result of the PCell
2119 double ofp = measObjectEutra
2120 .offsetFreq; // Ofp, the frequency specific offset of the primary frequency
2121 double ocp = 0.0; // Ocp, the cell specific offset of the PCell
2122 // Off, the offset parameter for this event.
2123 double off = EutranMeasurementMapping::IeValue2ActualA3Offset(reportConfigEutra.a3Offset);
2124 // Hys, the hysteresis parameter for this event.
2125 double hys =
2127
2128 switch (reportConfigEutra.triggerQuantity)
2129 {
2131 mp = m_storedMeasValues[m_cellId].rsrp;
2132 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2134 break;
2136 mp = m_storedMeasValues[m_cellId].rsrq;
2137 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2139 break;
2140 default:
2141 NS_FATAL_ERROR("unsupported triggerQuantity");
2142 break;
2143 }
2144
2145 for (auto storedMeasIt = m_storedMeasValues.begin();
2146 storedMeasIt != m_storedMeasValues.end();
2147 ++storedMeasIt)
2148 {
2149 uint16_t cellId = storedMeasIt->first;
2150 if (cellId == m_cellId)
2151 {
2152 continue;
2153 }
2154
2155 // Only cell(s) on the frequency indicated in the associated measObject can trigger
2156 // event.
2157 if (m_storedMeasValues.at(cellId).carrierFreq != measObjectEutra.carrierFreq)
2158 {
2159 continue;
2160 }
2161
2162 switch (reportConfigEutra.triggerQuantity)
2163 {
2165 mn = storedMeasIt->second.rsrp;
2166 break;
2168 mn = storedMeasIt->second.rsrq;
2169 break;
2170 default:
2171 NS_FATAL_ERROR("unsupported triggerQuantity");
2172 break;
2173 }
2174
2175 bool hasTriggered =
2176 isMeasIdInReportList && (measReportIt->second.cellsTriggeredList.find(cellId) !=
2177 measReportIt->second.cellsTriggeredList.end());
2178
2179 // Inequality A3-1 (Entering condition): Mn + Ofn + Ocn - Hys > Mp + Ofp + Ocp + Off
2180 bool entryCond = mn + ofn + ocn - hys > mp + ofp + ocp + off;
2181
2182 if (entryCond)
2183 {
2184 if (!hasTriggered)
2185 {
2186 concernedCellsEntry.push_back(cellId);
2187 eventEntryCondApplicable = true;
2188 }
2189 }
2190 else if (reportConfigEutra.timeToTrigger > 0)
2191 {
2192 CancelEnteringTrigger(measId, cellId);
2193 }
2194
2195 // Inequality A3-2 (Leaving condition): Mn + Ofn + Ocn + Hys < Mp + Ofp + Ocp + Off
2196 bool leavingCond = mn + ofn + ocn + hys < mp + ofp + ocp + off;
2197
2198 if (leavingCond)
2199 {
2200 if (hasTriggered)
2201 {
2202 concernedCellsLeaving.push_back(cellId);
2203 eventLeavingCondApplicable = true;
2204 }
2205 }
2206 else if (reportConfigEutra.timeToTrigger > 0)
2207 {
2208 CancelLeavingTrigger(measId, cellId);
2209 }
2210
2211 NS_LOG_LOGIC(this << " event A3: neighbor cell " << cellId << " mn=" << mn
2212 << " mp=" << mp << " offset=" << off << " entryCond=" << entryCond
2213 << " leavingCond=" << leavingCond);
2214
2215 } // end of for (storedMeasIt)
2216
2217 } // end of case LteRrcSap::ReportConfigEutra::EVENT_A3
2218
2219 break;
2220
2222 /*
2223 * Event A4 (Neighbour becomes better than threshold)
2224 * Please refer to 3GPP TS 36.331 Section 5.5.4.5
2225 */
2226
2227 double mn; // Mn, the measurement result of the neighbouring cell
2228 double ofn = measObjectEutra
2229 .offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2230 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2231 double thresh; // Thresh, the threshold parameter for this event
2232 // Hys, the hysteresis parameter for this event.
2233 double hys =
2235
2236 switch (reportConfigEutra.triggerQuantity)
2237 {
2239 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2241 thresh = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold1.range);
2242 break;
2244 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2246 thresh = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold1.range);
2247 break;
2248 default:
2249 NS_FATAL_ERROR("unsupported triggerQuantity");
2250 break;
2251 }
2252
2253 for (auto storedMeasIt = m_storedMeasValues.begin();
2254 storedMeasIt != m_storedMeasValues.end();
2255 ++storedMeasIt)
2256 {
2257 uint16_t cellId = storedMeasIt->first;
2258 if (cellId == m_cellId)
2259 {
2260 continue;
2261 }
2262
2263 switch (reportConfigEutra.triggerQuantity)
2264 {
2266 mn = storedMeasIt->second.rsrp;
2267 break;
2269 mn = storedMeasIt->second.rsrq;
2270 break;
2271 default:
2272 NS_FATAL_ERROR("unsupported triggerQuantity");
2273 break;
2274 }
2275
2276 bool hasTriggered =
2277 isMeasIdInReportList && (measReportIt->second.cellsTriggeredList.find(cellId) !=
2278 measReportIt->second.cellsTriggeredList.end());
2279
2280 // Inequality A4-1 (Entering condition): Mn + Ofn + Ocn - Hys > Thresh
2281 bool entryCond = mn + ofn + ocn - hys > thresh;
2282
2283 if (entryCond)
2284 {
2285 if (!hasTriggered)
2286 {
2287 concernedCellsEntry.push_back(cellId);
2288 eventEntryCondApplicable = true;
2289 }
2290 }
2291 else if (reportConfigEutra.timeToTrigger > 0)
2292 {
2293 CancelEnteringTrigger(measId, cellId);
2294 }
2295
2296 // Inequality A4-2 (Leaving condition): Mn + Ofn + Ocn + Hys < Thresh
2297 bool leavingCond = mn + ofn + ocn + hys < thresh;
2298
2299 if (leavingCond)
2300 {
2301 if (hasTriggered)
2302 {
2303 concernedCellsLeaving.push_back(cellId);
2304 eventLeavingCondApplicable = true;
2305 }
2306 }
2307 else if (reportConfigEutra.timeToTrigger > 0)
2308 {
2309 CancelLeavingTrigger(measId, cellId);
2310 }
2311
2312 NS_LOG_LOGIC(this << " event A4: neighbor cell " << cellId << " mn=" << mn
2313 << " thresh=" << thresh << " entryCond=" << entryCond
2314 << " leavingCond=" << leavingCond);
2315
2316 } // end of for (storedMeasIt)
2317
2318 } // end of case LteRrcSap::ReportConfigEutra::EVENT_A4
2319
2320 break;
2321
2323 /*
2324 * Event A5 (PCell becomes worse than threshold1 and neighbour
2325 * becomes better than threshold2)
2326 * Please refer to 3GPP TS 36.331 Section 5.5.4.6
2327 */
2328
2329 double mp; // Mp, the measurement result of the PCell
2330 double mn; // Mn, the measurement result of the neighbouring cell
2331 double ofn = measObjectEutra
2332 .offsetFreq; // Ofn, the frequency specific offset of the frequency of the
2333 double ocn = 0.0; // Ocn, the cell specific offset of the neighbour cell
2334 double thresh1; // Thresh1, the threshold parameter for this event
2335 double thresh2; // Thresh2, the threshold parameter for this event
2336 // Hys, the hysteresis parameter for this event.
2337 double hys =
2339
2340 switch (reportConfigEutra.triggerQuantity)
2341 {
2343 mp = m_storedMeasValues[m_cellId].rsrp;
2344 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2346 NS_ASSERT(reportConfigEutra.threshold2.choice ==
2348 thresh1 = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold1.range);
2349 thresh2 = EutranMeasurementMapping::RsrpRange2Dbm(reportConfigEutra.threshold2.range);
2350 break;
2352 mp = m_storedMeasValues[m_cellId].rsrq;
2353 NS_ASSERT(reportConfigEutra.threshold1.choice ==
2355 NS_ASSERT(reportConfigEutra.threshold2.choice ==
2357 thresh1 = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold1.range);
2358 thresh2 = EutranMeasurementMapping::RsrqRange2Db(reportConfigEutra.threshold2.range);
2359 break;
2360 default:
2361 NS_FATAL_ERROR("unsupported triggerQuantity");
2362 break;
2363 }
2364
2365 // Inequality A5-1 (Entering condition 1): Mp + Hys < Thresh1
2366 bool entryCond = mp + hys < thresh1;
2367
2368 if (entryCond)
2369 {
2370 for (auto storedMeasIt = m_storedMeasValues.begin();
2371 storedMeasIt != m_storedMeasValues.end();
2372 ++storedMeasIt)
2373 {
2374 uint16_t cellId = storedMeasIt->first;
2375 if (cellId == m_cellId)
2376 {
2377 continue;
2378 }
2379
2380 switch (reportConfigEutra.triggerQuantity)
2381 {
2383 mn = storedMeasIt->second.rsrp;
2384 break;
2386 mn = storedMeasIt->second.rsrq;
2387 break;
2388 default:
2389 NS_FATAL_ERROR("unsupported triggerQuantity");
2390 break;
2391 }
2392
2393 bool hasTriggered =
2394 isMeasIdInReportList && (measReportIt->second.cellsTriggeredList.find(cellId) !=
2395 measReportIt->second.cellsTriggeredList.end());
2396
2397 // Inequality A5-2 (Entering condition 2): Mn + Ofn + Ocn - Hys > Thresh2
2398
2399 entryCond = mn + ofn + ocn - hys > thresh2;
2400
2401 if (entryCond)
2402 {
2403 if (!hasTriggered)
2404 {
2405 concernedCellsEntry.push_back(cellId);
2406 eventEntryCondApplicable = true;
2407 }
2408 }
2409 else if (reportConfigEutra.timeToTrigger > 0)
2410 {
2411 CancelEnteringTrigger(measId, cellId);
2412 }
2413
2414 NS_LOG_LOGIC(this << " event A5: neighbor cell " << cellId << " mn=" << mn
2415 << " mp=" << mp << " thresh2=" << thresh2
2416 << " thresh1=" << thresh1 << " entryCond=" << entryCond);
2417
2418 } // end of for (storedMeasIt)
2419
2420 } // end of if (entryCond)
2421 else
2422 {
2423 NS_LOG_LOGIC(this << " event A5: serving cell " << m_cellId << " mp=" << mp
2424 << " thresh1=" << thresh1 << " entryCond=" << entryCond);
2425
2426 if (reportConfigEutra.timeToTrigger > 0)
2427 {
2428 CancelEnteringTrigger(measId);
2429 }
2430 }
2431
2432 if (isMeasIdInReportList)
2433 {
2434 // Inequality A5-3 (Leaving condition 1): Mp - Hys > Thresh1
2435 bool leavingCond = mp - hys > thresh1;
2436
2437 if (leavingCond)
2438 {
2439 if (reportConfigEutra.timeToTrigger == 0)
2440 {
2441 // leaving condition #2 does not have to be checked
2442
2443 for (auto storedMeasIt = m_storedMeasValues.begin();
2444 storedMeasIt != m_storedMeasValues.end();
2445 ++storedMeasIt)
2446 {
2447 uint16_t cellId = storedMeasIt->first;
2448 if (cellId == m_cellId)
2449 {
2450 continue;
2451 }
2452
2453 if (measReportIt->second.cellsTriggeredList.find(cellId) !=
2454 measReportIt->second.cellsTriggeredList.end())
2455 {
2456 concernedCellsLeaving.push_back(cellId);
2457 eventLeavingCondApplicable = true;
2458 }
2459 }
2460 } // end of if (reportConfigEutra.timeToTrigger == 0)
2461 else
2462 {
2463 // leaving condition #2 has to be checked to cancel time-to-trigger
2464
2465 for (auto storedMeasIt = m_storedMeasValues.begin();
2466 storedMeasIt != m_storedMeasValues.end();
2467 ++storedMeasIt)
2468 {
2469 uint16_t cellId = storedMeasIt->first;
2470 if (cellId == m_cellId)
2471 {
2472 continue;
2473 }
2474
2475 if (measReportIt->second.cellsTriggeredList.find(cellId) !=
2476 measReportIt->second.cellsTriggeredList.end())
2477 {
2478 switch (reportConfigEutra.triggerQuantity)
2479 {
2481 mn = storedMeasIt->second.rsrp;
2482 break;
2484 mn = storedMeasIt->second.rsrq;
2485 break;
2486 default:
2487 NS_FATAL_ERROR("unsupported triggerQuantity");
2488 break;
2489 }
2490
2491 // Inequality A5-4 (Leaving condition 2): Mn + Ofn + Ocn + Hys < Thresh2
2492
2493 leavingCond = mn + ofn + ocn + hys < thresh2;
2494
2495 if (!leavingCond)
2496 {
2497 CancelLeavingTrigger(measId, cellId);
2498 }
2499
2500 /*
2501 * Whatever the result of leaving condition #2, this
2502 * cell is still "in", because leaving condition #1
2503 * is already true.
2504 */
2505 concernedCellsLeaving.push_back(cellId);
2506 eventLeavingCondApplicable = true;
2507
2508 NS_LOG_LOGIC(this << " event A5: neighbor cell " << cellId
2509 << " mn=" << mn << " mp=" << mp
2510 << " thresh2=" << thresh2 << " thresh1=" << thresh1
2511 << " leavingCond=" << leavingCond);
2512
2513 } // end of if (measReportIt->second.cellsTriggeredList.find (cellId)
2514 // != measReportIt->second.cellsTriggeredList.end ())
2515
2516 } // end of for (storedMeasIt)
2517
2518 } // end of else of if (reportConfigEutra.timeToTrigger == 0)
2519
2520 NS_LOG_LOGIC(this << " event A5: serving cell " << m_cellId << " mp=" << mp
2521 << " thresh1=" << thresh1 << " leavingCond=" << leavingCond);
2522
2523 } // end of if (leavingCond)
2524 else
2525 {
2526 if (reportConfigEutra.timeToTrigger > 0)
2527 {
2528 CancelLeavingTrigger(measId);
2529 }
2530
2531 // check leaving condition #2
2532
2533 for (auto storedMeasIt = m_storedMeasValues.begin();
2534 storedMeasIt != m_storedMeasValues.end();
2535 ++storedMeasIt)
2536 {
2537 uint16_t cellId = storedMeasIt->first;
2538 if (cellId == m_cellId)
2539 {
2540 continue;
2541 }
2542
2543 if (measReportIt->second.cellsTriggeredList.find(cellId) !=
2544 measReportIt->second.cellsTriggeredList.end())
2545 {
2546 switch (reportConfigEutra.triggerQuantity)
2547 {
2549 mn = storedMeasIt->second.rsrp;
2550 break;
2552 mn = storedMeasIt->second.rsrq;
2553 break;
2554 default:
2555 NS_FATAL_ERROR("unsupported triggerQuantity");
2556 break;
2557 }
2558
2559 // Inequality A5-4 (Leaving condition 2): Mn + Ofn + Ocn + Hys < Thresh2
2560 leavingCond = mn + ofn + ocn + hys < thresh2;
2561
2562 if (leavingCond)
2563 {
2564 concernedCellsLeaving.push_back(cellId);
2565 eventLeavingCondApplicable = true;
2566 }
2567
2568 NS_LOG_LOGIC(this << " event A5: neighbor cell " << cellId << " mn=" << mn
2569 << " mp=" << mp << " thresh2=" << thresh2 << " thresh1="
2570 << thresh1 << " leavingCond=" << leavingCond);
2571
2572 } // end of if (measReportIt->second.cellsTriggeredList.find (cellId)
2573 // != measReportIt->second.cellsTriggeredList.end ())
2574
2575 } // end of for (storedMeasIt)
2576
2577 } // end of else of if (leavingCond)
2578
2579 } // end of if (isMeasIdInReportList)
2580
2581 } // end of case LteRrcSap::ReportConfigEutra::EVENT_A5
2582
2583 break;
2584
2585 default:
2586 NS_FATAL_ERROR("unsupported eventId " << reportConfigEutra.eventId);
2587 break;
2588
2589 } // switch (event type)
2590
2591 NS_LOG_LOGIC(this << " eventEntryCondApplicable=" << eventEntryCondApplicable
2592 << " eventLeavingCondApplicable=" << eventLeavingCondApplicable);
2593
2594 if (eventEntryCondApplicable)
2595 {
2596 if (reportConfigEutra.timeToTrigger == 0)
2597 {
2598 VarMeasReportListAdd(measId, concernedCellsEntry);
2599 }
2600 else
2601 {
2603 t.measId = measId;
2604 t.concernedCells = concernedCellsEntry;
2605 t.timer = Simulator::Schedule(MilliSeconds(reportConfigEutra.timeToTrigger),
2607 this,
2608 measId,
2609 concernedCellsEntry);
2610 auto enteringTriggerIt = m_enteringTriggerQueue.find(measId);
2611 NS_ASSERT(enteringTriggerIt != m_enteringTriggerQueue.end());
2612 enteringTriggerIt->second.push_back(t);
2613 }
2614 }
2615
2616 if (eventLeavingCondApplicable)
2617 {
2618 // reportOnLeave will only be set when eventId = eventA3
2619 bool reportOnLeave =
2620 (reportConfigEutra.eventId == LteRrcSap::ReportConfigEutra::EVENT_A3) &&
2621 reportConfigEutra.reportOnLeave;
2622
2623 if (reportConfigEutra.timeToTrigger == 0)
2624 {
2625 VarMeasReportListErase(measId, concernedCellsLeaving, reportOnLeave);
2626 }
2627 else
2628 {
2630 t.measId = measId;
2631 t.concernedCells = concernedCellsLeaving;
2632 t.timer = Simulator::Schedule(MilliSeconds(reportConfigEutra.timeToTrigger),
2634 this,
2635 measId,
2636 concernedCellsLeaving,
2637 reportOnLeave);
2638 auto leavingTriggerIt = m_leavingTriggerQueue.find(measId);
2639 NS_ASSERT(leavingTriggerIt != m_leavingTriggerQueue.end());
2640 leavingTriggerIt->second.push_back(t);
2641 }
2642 }
2643
2644} // end of void LteUeRrc::MeasurementReportTriggering (uint8_t measId)
2645
2646void
2648{
2649 NS_LOG_FUNCTION(this << (uint16_t)measId);
2650
2651 auto it1 = m_enteringTriggerQueue.find(measId);
2652 NS_ASSERT(it1 != m_enteringTriggerQueue.end());
2653
2654 if (!it1->second.empty())
2655 {
2656 for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
2657 {
2658 NS_ASSERT(it2->measId == measId);
2659 NS_LOG_LOGIC(this << " canceling entering time-to-trigger event at "
2660 << Simulator::GetDelayLeft(it2->timer).GetSeconds());
2661 Simulator::Cancel(it2->timer);
2662 }
2663
2664 it1->second.clear();
2665 }
2666}
2667
2668void
2669LteUeRrc::CancelEnteringTrigger(uint8_t measId, uint16_t cellId)
2670{
2671 NS_LOG_FUNCTION(this << (uint16_t)measId << cellId);
2672
2673 auto it1 = m_enteringTriggerQueue.find(measId);
2674 NS_ASSERT(it1 != m_enteringTriggerQueue.end());
2675
2676 auto it2 = it1->second.begin();
2677 while (it2 != it1->second.end())
2678 {
2679 NS_ASSERT(it2->measId == measId);
2680
2681 for (auto it3 = it2->concernedCells.begin(); it3 != it2->concernedCells.end(); ++it3)
2682 {
2683 if (*it3 == cellId)
2684 {
2685 it3 = it2->concernedCells.erase(it3);
2686 }
2687 }
2688
2689 if (it2->concernedCells.empty())
2690 {
2691 NS_LOG_LOGIC(this << " canceling entering time-to-trigger event at "
2692 << Simulator::GetDelayLeft(it2->timer).GetSeconds());
2693 Simulator::Cancel(it2->timer);
2694 it2 = it1->second.erase(it2);
2695 }
2696 else
2697 {
2698 it2++;
2699 }
2700 }
2701}
2702
2703void
2705{
2706 NS_LOG_FUNCTION(this << (uint16_t)measId);
2707
2708 auto it1 = m_leavingTriggerQueue.find(measId);
2709 NS_ASSERT(it1 != m_leavingTriggerQueue.end());
2710
2711 if (!it1->second.empty())
2712 {
2713 for (auto it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
2714 {
2715 NS_ASSERT(it2->measId == measId);
2716 NS_LOG_LOGIC(this << " canceling leaving time-to-trigger event at "
2717 << Simulator::GetDelayLeft(it2->timer).GetSeconds());
2718 Simulator::Cancel(it2->timer);
2719 }
2720
2721 it1->second.clear();
2722 }
2723}
2724
2725void
2726LteUeRrc::CancelLeavingTrigger(uint8_t measId, uint16_t cellId)
2727{
2728 NS_LOG_FUNCTION(this << (uint16_t)measId << cellId);
2729
2730 auto it1 = m_leavingTriggerQueue.find(measId);
2731 NS_ASSERT(it1 != m_leavingTriggerQueue.end());
2732
2733 auto it2 = it1->second.begin();
2734 while (it2 != it1->second.end())
2735 {
2736 NS_ASSERT(it2->measId == measId);
2737
2738 for (auto it3 = it2->concernedCells.begin(); it3 != it2->concernedCells.end(); ++it3)
2739 {
2740 if (*it3 == cellId)
2741 {
2742 it3 = it2->concernedCells.erase(it3);
2743 }
2744 }
2745
2746 if (it2->concernedCells.empty())
2747 {
2748 NS_LOG_LOGIC(this << " canceling leaving time-to-trigger event at "
2749 << Simulator::GetDelayLeft(it2->timer).GetSeconds());
2750 Simulator::Cancel(it2->timer);
2751 it2 = it1->second.erase(it2);
2752 }
2753 else
2754 {
2755 it2++;
2756 }
2757 }
2758}
2759
2760void
2762{
2763 NS_LOG_FUNCTION(this << (uint16_t)measId);
2764 NS_ASSERT(!enteringCells.empty());
2765
2766 auto measReportIt = m_varMeasReportList.find(measId);
2767
2768 if (measReportIt == m_varMeasReportList.end())
2769 {
2770 VarMeasReport r;
2771 r.measId = measId;
2772 std::pair<uint8_t, VarMeasReport> val(measId, r);
2773 auto ret = m_varMeasReportList.insert(val);
2774 NS_ASSERT_MSG(ret.second == true, "element already existed");
2775 measReportIt = ret.first;
2776 }
2777
2778 NS_ASSERT(measReportIt != m_varMeasReportList.end());
2779
2780 for (auto it = enteringCells.begin(); it != enteringCells.end(); ++it)
2781 {
2782 measReportIt->second.cellsTriggeredList.insert(*it);
2783 }
2784
2785 NS_ASSERT(!measReportIt->second.cellsTriggeredList.empty());
2786
2787 // #issue 224, schedule only when there is no periodic event scheduled already
2788 if (!measReportIt->second.periodicReportTimer.IsPending())
2789 {
2790 measReportIt->second.numberOfReportsSent = 0;
2791 measReportIt->second.periodicReportTimer =
2794 this,
2795 measId);
2796 }
2797
2798 auto enteringTriggerIt = m_enteringTriggerQueue.find(measId);
2799 NS_ASSERT(enteringTriggerIt != m_enteringTriggerQueue.end());
2800 if (!enteringTriggerIt->second.empty())
2801 {
2802 /*
2803 * Assumptions at this point:
2804 * - the call to this function was delayed by time-to-trigger;
2805 * - the time-to-trigger delay is fixed (not adaptive/dynamic); and
2806 * - the first element in the list is associated with this function call.
2807 */
2808 enteringTriggerIt->second.pop_front();
2809
2810 if (!enteringTriggerIt->second.empty())
2811 {
2812 /*
2813 * To prevent the same set of cells triggering again in the future,
2814 * we clean up the time-to-trigger queue. This case might occur when
2815 * time-to-trigger > 200 ms.
2816 */
2817 for (auto it = enteringCells.begin(); it != enteringCells.end(); ++it)
2818 {
2819 CancelEnteringTrigger(measId, *it);
2820 }
2821 }
2822
2823 } // end of if (!enteringTriggerIt->second.empty ())
2824
2825} // end of LteUeRrc::VarMeasReportListAdd
2826
2827void
2828LteUeRrc::VarMeasReportListErase(uint8_t measId, ConcernedCells_t leavingCells, bool reportOnLeave)
2829{
2830 NS_LOG_FUNCTION(this << (uint16_t)measId);
2831 NS_ASSERT(!leavingCells.empty());
2832
2833 auto measReportIt = m_varMeasReportList.find(measId);
2834 NS_ASSERT(measReportIt != m_varMeasReportList.end());
2835
2836 for (auto it = leavingCells.begin(); it != leavingCells.end(); ++it)
2837 {
2838 measReportIt->second.cellsTriggeredList.erase(*it);
2839 }
2840
2841 if (reportOnLeave)
2842 {
2843 // runs immediately without UE_MEASUREMENT_REPORT_DELAY
2844 SendMeasurementReport(measId);
2845 }
2846
2847 if (measReportIt->second.cellsTriggeredList.empty())
2848 {
2849 measReportIt->second.periodicReportTimer.Cancel();
2850 m_varMeasReportList.erase(measReportIt);
2851 }
2852
2853 auto leavingTriggerIt = m_leavingTriggerQueue.find(measId);
2854 NS_ASSERT(leavingTriggerIt != m_leavingTriggerQueue.end());
2855 if (!leavingTriggerIt->second.empty())
2856 {
2857 /*
2858 * Assumptions at this point:
2859 * - the call to this function was delayed by time-to-trigger; and
2860 * - the time-to-trigger delay is fixed (not adaptive/dynamic); and
2861 * - the first element in the list is associated with this function call.
2862 */
2863 leavingTriggerIt->second.pop_front();
2864
2865 if (!leavingTriggerIt->second.empty())
2866 {
2867 /*
2868 * To prevent the same set of cells triggering again in the future,
2869 * we clean up the time-to-trigger queue. This case might occur when
2870 * time-to-trigger > 200 ms.
2871 */
2872 for (auto it = leavingCells.begin(); it != leavingCells.end(); ++it)
2873 {
2874 CancelLeavingTrigger(measId, *it);
2875 }
2876 }
2877
2878 } // end of if (!leavingTriggerIt->second.empty ())
2879
2880} // end of LteUeRrc::VarMeasReportListErase
2881
2882void
2884{
2885 NS_LOG_FUNCTION(this << (uint16_t)measId);
2886
2887 // remove the measurement reporting entry for this measId from the VarMeasReportList
2888 auto measReportIt = m_varMeasReportList.find(measId);
2889 if (measReportIt != m_varMeasReportList.end())
2890 {
2891 NS_LOG_LOGIC(this << " deleting existing report for measId " << (uint16_t)measId);
2892 measReportIt->second.periodicReportTimer.Cancel();
2893 m_varMeasReportList.erase(measReportIt);
2894 }
2895
2896 CancelEnteringTrigger(measId);
2897 CancelLeavingTrigger(measId);
2898}
2899
2900void
2902{
2903 NS_LOG_FUNCTION(this << (uint16_t)measId);
2904 // 3GPP TS 36.331 section 5.5.5 Measurement reporting
2905
2906 auto measIdIt = m_varMeasConfig.measIdList.find(measId);
2907 NS_ASSERT(measIdIt != m_varMeasConfig.measIdList.end());
2908
2909 auto reportConfigIt = m_varMeasConfig.reportConfigList.find(measIdIt->second.reportConfigId);
2910 NS_ASSERT(reportConfigIt != m_varMeasConfig.reportConfigList.end());
2911 LteRrcSap::ReportConfigEutra& reportConfigEutra = reportConfigIt->second.reportConfigEutra;
2912
2913 LteRrcSap::MeasurementReport measurementReport;
2914 LteRrcSap::MeasResults& measResults = measurementReport.measResults;
2915 measResults.measId = measId;
2916
2917 auto measReportIt = m_varMeasReportList.find(measId);
2918 if (measReportIt == m_varMeasReportList.end())
2919 {
2920 NS_LOG_ERROR("no entry found in m_varMeasReportList for measId " << (uint32_t)measId);
2921 }
2922 else
2923 {
2924 auto servingMeasIt = m_storedMeasValues.find(m_cellId);
2925 NS_ASSERT(servingMeasIt != m_storedMeasValues.end());
2926 measResults.measResultPCell.rsrpResult =
2927 EutranMeasurementMapping::Dbm2RsrpRange(servingMeasIt->second.rsrp);
2928 measResults.measResultPCell.rsrqResult =
2929 EutranMeasurementMapping::Db2RsrqRange(servingMeasIt->second.rsrq);
2930 NS_LOG_INFO(this << " reporting serving cell "
2931 "RSRP "
2932 << +measResults.measResultPCell.rsrpResult << " ("
2933 << servingMeasIt->second.rsrp
2934 << " dBm) "
2935 "RSRQ "
2936 << +measResults.measResultPCell.rsrqResult << " ("
2937 << servingMeasIt->second.rsrq << " dB)");
2938
2939 measResults.haveMeasResultServFreqList = false;
2940 for (uint16_t componentCarrierId = 1; componentCarrierId < m_numberOfComponentCarriers;
2941 componentCarrierId++)
2942 {
2943 const uint16_t cellId = m_cphySapProvider.at(componentCarrierId)->GetCellId();
2944 auto measValuesIt = m_storedMeasValues.find(cellId);
2945 if (measValuesIt != m_storedMeasValues.end())
2946 {
2947 measResults.haveMeasResultServFreqList = true;
2948 LteRrcSap::MeasResultServFreq measResultServFreq;
2949 measResultServFreq.servFreqId = componentCarrierId;
2950 measResultServFreq.haveMeasResultSCell = true;
2951 measResultServFreq.measResultSCell.rsrpResult =
2952 EutranMeasurementMapping::Dbm2RsrpRange(measValuesIt->second.rsrp);
2953 measResultServFreq.measResultSCell.rsrqResult =
2954 EutranMeasurementMapping::Db2RsrqRange(measValuesIt->second.rsrq);
2955 measResultServFreq.haveMeasResultBestNeighCell = false;
2956 measResults.measResultServFreqList.push_back(measResultServFreq);
2957 }
2958 }
2959
2960 measResults.haveMeasResultNeighCells = false;
2961
2962 if (!(measReportIt->second.cellsTriggeredList.empty()))
2963 {
2964 std::multimap<double, uint16_t> sortedNeighCells;
2965 for (auto cellsTriggeredIt = measReportIt->second.cellsTriggeredList.begin();
2966 cellsTriggeredIt != measReportIt->second.cellsTriggeredList.end();
2967 ++cellsTriggeredIt)
2968 {
2969 uint16_t cellId = *cellsTriggeredIt;
2970 if (cellId != m_cellId)
2971 {
2972 auto neighborMeasIt = m_storedMeasValues.find(cellId);
2973 double triggerValue;
2974 switch (reportConfigEutra.triggerQuantity)
2975 {
2977 triggerValue = neighborMeasIt->second.rsrp;
2978 break;
2980 triggerValue = neighborMeasIt->second.rsrq;
2981 break;
2982 default:
2983 NS_FATAL_ERROR("unsupported triggerQuantity");
2984 break;
2985 }
2986 sortedNeighCells.insert(std::pair<double, uint16_t>(triggerValue, cellId));
2987 }
2988 }
2989
2990 std::multimap<double, uint16_t>::reverse_iterator sortedNeighCellsIt;
2991 uint32_t count;
2992 for (sortedNeighCellsIt = sortedNeighCells.rbegin(), count = 0;
2993 sortedNeighCellsIt != sortedNeighCells.rend() &&
2994 count < reportConfigEutra.maxReportCells;
2995 ++sortedNeighCellsIt, ++count)
2996 {
2997 uint16_t cellId = sortedNeighCellsIt->second;
2998 auto neighborMeasIt = m_storedMeasValues.find(cellId);
2999 NS_ASSERT(neighborMeasIt != m_storedMeasValues.end());
3000 LteRrcSap::MeasResultEutra measResultEutra;
3001 measResultEutra.physCellId = cellId;
3002 measResultEutra.haveCgiInfo = false;
3003 measResultEutra.haveRsrpResult = true;
3004 measResultEutra.rsrpResult =
3005 EutranMeasurementMapping::Dbm2RsrpRange(neighborMeasIt->second.rsrp);
3006 measResultEutra.haveRsrqResult = true;
3007 measResultEutra.rsrqResult =
3008 EutranMeasurementMapping::Db2RsrqRange(neighborMeasIt->second.rsrq);
3009 NS_LOG_INFO(this << " reporting neighbor cell "
3010 << (uint32_t)measResultEutra.physCellId << " RSRP "
3011 << (uint32_t)measResultEutra.rsrpResult << " ("
3012 << neighborMeasIt->second.rsrp << " dBm)"
3013 << " RSRQ " << (uint32_t)measResultEutra.rsrqResult << " ("
3014 << neighborMeasIt->second.rsrq << " dB)");
3015 measResults.measResultListEutra.push_back(measResultEutra);
3016 measResults.haveMeasResultNeighCells = true;
3017 }
3018 }
3019 else
3020 {
3021 NS_LOG_WARN(this << " cellsTriggeredList is empty");
3022 }
3023
3024 /*
3025 * The current LteRrcSap implementation is broken in that it does not
3026 * allow for infinite values of reportAmount, which is probably the most
3027 * reasonable setting. So we just always assume infinite reportAmount.
3028 */
3029 measReportIt->second.numberOfReportsSent++;
3030 measReportIt->second.periodicReportTimer.Cancel();
3031
3032 Time reportInterval;
3033 switch (reportConfigEutra.reportInterval)
3034 {
3036 reportInterval = MilliSeconds(120);
3037 break;
3039 reportInterval = MilliSeconds(240);
3040 break;
3042 reportInterval = MilliSeconds(480);
3043 break;
3045 reportInterval = MilliSeconds(640);
3046 break;
3048 reportInterval = MilliSeconds(1024);
3049 break;
3051 reportInterval = MilliSeconds(2048);
3052 break;
3054 reportInterval = MilliSeconds(5120);
3055 break;
3057 reportInterval = MilliSeconds(10240);
3058 break;
3060 reportInterval = Seconds(60);
3061 break;
3063 reportInterval = Seconds(360);
3064 break;
3066 reportInterval = Seconds(720);
3067 break;
3069 reportInterval = Seconds(1800);
3070 break;
3072 reportInterval = Seconds(3600);
3073 break;
3074 default:
3075 NS_FATAL_ERROR("Unsupported reportInterval "
3076 << (uint16_t)reportConfigEutra.reportInterval);
3077 break;
3078 }
3079
3080 // schedule the next measurement reporting
3081 measReportIt->second.periodicReportTimer =
3082 Simulator::Schedule(reportInterval, &LteUeRrc::SendMeasurementReport, this, measId);
3083
3084 // send the measurement report to eNodeB
3085 m_rrcSapUser->SendMeasurementReport(measurementReport);
3086 }
3087}
3088
3089void
3091{
3092 NS_LOG_FUNCTION(this << m_imsi);
3095 m_connectionPending = false; // reset the flag
3097 m_cmacSapProvider.at(0)->StartContentionBasedRandomAccessProcedure();
3098}
3099
3100void
3102{
3103 NS_LOG_FUNCTION(this << m_imsi);
3104 m_leaveConnectedMode = true;
3105 m_storedMeasValues.clear();
3107
3108 for (auto measIdIt = m_varMeasConfig.measIdList.begin();
3109 measIdIt != m_varMeasConfig.measIdList.end();
3110 ++measIdIt)
3111 {
3112 VarMeasReportListClear(measIdIt->second.measId);
3113 }
3115
3117
3118 for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
3119 {
3120 m_cmacSapProvider.at(i)->Reset(); // reset the MAC
3121 }
3122
3123 m_drbMap.clear();
3124 m_bid2DrbidMap.clear();
3125 m_srb1 = nullptr;
3126 m_hasReceivedMib = false;
3127 m_hasReceivedSib1 = false;
3128 m_hasReceivedSib2 = false;
3129
3130 for (uint32_t i = 0; i < m_numberOfComponentCarriers; i++)
3131 {
3132 m_cphySapProvider.at(i)->ResetPhyAfterRlf(); // reset the PHY
3133 }
3136 // Save the cell id UE was attached to
3138 m_cellId = 0;
3139 m_rnti = 0;
3140 m_srb0->m_rlc->SetRnti(m_rnti);
3141}
3142
3143void
3145{
3146 NS_LOG_FUNCTION(this << m_imsi);
3149 {
3152 // Assumption: The eNB connection request timer would expire
3153 // before the expiration of T300 at UE. Upon which, the eNB deletes
3154 // the UE context. Therefore, here we don't need to send the UE context
3155 // deletion request to the eNB.
3158 }
3159 else
3160 {
3161 for (uint16_t i = 0; i < m_numberOfComponentCarriers; i++)
3162 {
3163 m_cmacSapProvider.at(i)->Reset(); // reset the MAC
3164 }
3165 m_hasReceivedSib2 = false; // invalidate the previously received SIB2
3168 // Following call to UE NAS will force the UE to immediately
3169 // perform the random access to the same cell again.
3170 m_asSapUser->NotifyConnectionFailed(); // inform upper layer
3171 }
3172}
3173
3174void
3176{
3177 NS_LOG_FUNCTION(this);
3178 m_srb1Old = nullptr;
3179}
3180
3181uint8_t
3183{
3184 auto it = m_bid2DrbidMap.find(bid);
3185 // NS_ASSERT_MSG (it != m_bid2DrbidMap.end (), "could not find BID " << bid);
3186 if (it == m_bid2DrbidMap.end())
3187 {
3188 return 0;
3189 }
3190 else
3191 {
3192 return it->second;
3193 }
3194}
3195
3196void
3198{
3199 NS_LOG_FUNCTION(this << newState);
3200 State oldState = m_state;
3201 m_state = newState;
3202 NS_LOG_INFO(this << " IMSI " << m_imsi << " RNTI " << m_rnti << " UeRrc " << oldState << " --> "
3203 << newState);
3204 m_stateTransitionTrace(m_imsi, m_cellId, m_rnti, oldState, newState);
3205
3206 switch (newState)
3207 {
3208 case IDLE_START:
3210 {
3211 NS_LOG_INFO("Starting initial cell selection after RLF");
3212 }
3213 else
3214 {
3215 NS_FATAL_ERROR("cannot switch to an initial state");
3216 }
3217 break;
3218
3219 case IDLE_CELL_SEARCH:
3220 case IDLE_WAIT_MIB_SIB1:
3221 case IDLE_WAIT_MIB:
3222 case IDLE_WAIT_SIB1:
3223 break;
3224
3227 {
3229 }
3230 break;
3231
3232 case IDLE_WAIT_SIB2:
3234 {
3237 }
3238 break;
3239
3240 case IDLE_RANDOM_ACCESS:
3241 case IDLE_CONNECTING:
3242 case CONNECTED_NORMALLY:
3243 case CONNECTED_HANDOVER:
3246 default:
3247 break;
3248 }
3249}
3250
3251void
3260
3261void
3263{
3264 NS_LOG_FUNCTION(this << m_imsi);
3266 NS_LOG_INFO("noOfSyncIndications " << (uint16_t)m_noOfSyncIndications);
3269 {
3271 }
3272}
3273
3274void
3276{
3277 NS_LOG_FUNCTION(this << m_imsi);
3279 NS_LOG_INFO(this << " Total Number of Sync indications from PHY "
3280 << (uint16_t)m_noOfSyncIndications << "N310 value : " << (uint16_t)m_n310);
3283 {
3287 {
3288 NS_LOG_INFO("t310 started");
3289 }
3290 m_cphySapProvider.at(0)->StartInSyncDetection();
3292 }
3293}
3294
3295void
3297{
3298 NS_LOG_FUNCTION(this << m_imsi);
3299
3300 NS_LOG_DEBUG("The number of sync indication received by RRC from PHY: "
3301 << (uint16_t)m_noOfSyncIndications);
3303}
3304
3305void
3307{
3308 NS_LOG_FUNCTION(this << m_imsi);
3311 m_cphySapProvider.at(0)->ResetRlfParams();
3312}
3313
3314const std::string
3316{
3317 std::ostringstream ss;
3318 ss << s;
3319 return ss.str();
3320}
3321
3322std::ostream&
3323operator<<(std::ostream& os, LteUeRrc::State state)
3324{
3325 switch (state)
3326 {
3328 return os << "IDLE_START";
3330 return os << "IDLE_CELL_SEARCH";
3332 return os << "IDLE_WAIT_MIB_SIB1";
3334 return os << "IDLE_WAIT_MIB";
3336 return os << "IDLE_WAIT_SIB1";
3338 return os << "IDLE_CAMPED_NORMALLY";
3340 return os << "IDLE_WAIT_SIB2";
3342 return os << "IDLE_RANDOM_ACCESS";
3344 return os << "IDLE_CONNECTING";
3346 return os << "CONNECTED_NORMALLY";
3348 return os << "CONNECTED_HANDOVER";
3350 return os << "CONNECTED_PHY_PROBLEM";
3352 return os << "CONNECTED_REESTABLISHING";
3354 return os << "NUM_STATES";
3355 };
3356 return os << "UNKNOWN(" << static_cast<uint32_t>(state) << ")";
3357}
3358
3359} // 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:81
void DoRecvRrcConnectionReconfiguration(LteRrcSap::RrcConnectionReconfiguration msg)
Part of the RRC protocol.
uint8_t m_lastRrcTransactionIdentifier
last RRC transaction identifier
Definition lte-ue-rrc.h:810
bool m_connectionPending
True if a connection request by upper layers is pending.
Definition lte-ue-rrc.h:925
bool m_hasReceivedSib1
True if SIB1 was received for the current cell.
Definition lte-ue-rrc.h:929
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:797
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:759
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:825
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:775
uint8_t m_n311
The 'N311' attribute.
Ptr< LteSignalingRadioBearerInfo > m_srb0
The Srb0 attribute.
Definition lte-ue-rrc.h:788
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:893
State
The states of the UE RRC entity.
Definition lte-ue-rrc.h:89
@ CONNECTED_REESTABLISHING
Definition lte-ue-rrc.h:102
TracedCallback< uint64_t, uint16_t, uint16_t, State, State > m_stateTransitionTrace
The StateTransition trace source.
Definition lte-ue-rrc.h:842
VarMeasConfig m_varMeasConfig
Includes the accumulated configuration of the measurements to be performed by the UE.
Definition lte-ue-rrc.h:967
friend class MemberLteUeRrcSapProvider< LteUeRrc >
allow MemberLteUeRrcSapProvider<LteUeRrc> class friend access
Definition lte-ue-rrc.h:79
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:812
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:852
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:757
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:931
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:748
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:754
State GetState() const
uint32_t m_dlEarfcn
Downlink carrier frequency.
Definition lte-ue-rrc.h:817
LteUeCcmRrcSapProvider * m_ccmRrcSapProvider
Interface to the LteUeComponentCarrierManage instance.
Definition lte-ue-rrc.h:768
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:922
uint64_t GetImsi() const
uint32_t m_ulEarfcn
Uplink carrier frequency.
Definition lte-ue-rrc.h:818
TracedCallback< uint64_t, uint16_t, uint16_t > m_connectionEstablishedTrace
The ConnectionEstablished trace source.
Definition lte-ue-rrc.h:868
uint8_t GetDlBandwidth() const
TracedCallback< uint64_t, uint16_t, uint16_t, uint16_t > m_sib1ReceivedTrace
The Sib1Received trace source.
Definition lte-ue-rrc.h:831
TracedCallback< uint64_t, uint16_t, uint16_t > m_randomAccessErrorTrace
The RandomAccessError trace source.
Definition lte-ue-rrc.h:863
uint32_t GetDlEarfcn() const
std::list< LteRrcSap::SCellToAddMod > m_sCellToAddModList
Secondary carriers.
Definition lte-ue-rrc.h:819
LtePdcpSapUser * m_drbPdcpSapUser
DRB PDCP SAP user.
Definition lte-ue-rrc.h:760
TracedCallback< Ptr< LteUeRrc >, std::list< LteRrcSap::SCellToAddMod > > m_sCarrierConfiguredTrace
The SCarrierConfigured trace source.
Definition lte-ue-rrc.h:899
void DoStartCellSelection(uint32_t dlEarfcn)
Start cell selection function.
friend class MemberLteAsSapProvider< LteUeRrc >
allow MemberLteAsSapProvider<LteUeRrc> class friend access
Definition lte-ue-rrc.h:75
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:808
TracedCallback< uint64_t, uint16_t, uint16_t > m_handoverEndOkTrace
The HandoverEndOk trace source.
Definition lte-ue-rrc.h:888
TracedCallback< uint64_t, uint16_t, uint16_t, std::string, uint8_t > m_phySyncDetectionTrace
The 'PhySyncDetection' trace source.
Definition lte-ue-rrc.h:917
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:69
void RadioLinkFailureDetected()
Radio link failure detected function.
State m_state
The current UE RRC state.
Definition lte-ue-rrc.h:772
std::vector< LteUeCphySapProvider * > m_cphySapProvider
UE CPhy SAP provider.
Definition lte-ue-rrc.h:751
LteUeCcmRrcSapUser * m_ccmRrcSapUser
CCM RRC SAP user.
Definition lte-ue-rrc.h:769
TracedCallback< uint64_t, uint16_t, uint16_t, uint8_t > m_drbCreatedTrace
The DrbCreated trace source.
Definition lte-ue-rrc.h:911
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:989
std::vector< LteUeCmacSapUser * > m_cmacSapUser
UE CMac SAP user.
Definition lte-ue-rrc.h:753
TracedCallback< uint64_t, uint16_t, uint16_t > m_srb1CreatedTrace
The Srb1Created trace source.
Definition lte-ue-rrc.h:905
TracedCallback< uint64_t, uint16_t > m_initialCellSelectionEndOkTrace
The InitialCellSelectionEndOk trace source.
Definition lte-ue-rrc.h:847
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:762
uint16_t m_rnti
The C-RNTI attribute.
Definition lte-ue-rrc.h:779
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:756
TracedCallback< uint64_t, uint16_t, uint16_t > m_connectionReconfigurationTrace
The ConnectionReconfiguration trace source.
Definition lte-ue-rrc.h:878
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:836
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:802
uint16_t m_cellId
The CellId attribute.
Definition lte-ue-rrc.h:783
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:873
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:937
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:750
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:927
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:994
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:815
LteUeRrc()
create an RRC instance for use within an ue
Definition lte-ue-rrc.cc:91
uint32_t m_csgWhiteList
List of CSG ID which this UE entity has access to.
Definition lte-ue-rrc.h:940
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:73
TracedCallback< uint64_t, uint16_t, uint16_t > m_randomAccessSuccessfulTrace
The RandomAccessSuccessful trace source.
Definition lte-ue-rrc.h:858
bool IsServingCell(uint16_t cellId) const
LteRrcSap::SystemInformationBlockType1 m_lastSib1
Stored content of the last SIB1 received.
Definition lte-ue-rrc.h:934
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:814
Ptr< LteSignalingRadioBearerInfo > m_srb1
The Srb1 attribute.
Definition lte-ue-rrc.h:792
LteAsSapUser * m_asSapUser
AS SAP user.
Definition lte-ue-rrc.h:763
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:883
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
AttributeValue implementation for Time.
Definition nstime.h:1431
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
ObjectPtrContainerValue ObjectMapValue
ObjectMapValue is an alias for ObjectPtrContainerValue.
Definition object-map.h:29
Ptr< const AttributeAccessor > MakeObjectMapAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition object-map.h:65
Ptr< const AttributeChecker > MakeObjectMapChecker()
Definition object-map.h:110
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1432
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1452
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1368
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1356
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
const Time UE_MEASUREMENT_REPORT_DELAY
Artificial delay of UE measurements procedure.
Definition lte-ue-rrc.cc:35
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
constexpr uint32_t MIN_NO_CC
Minimum number of carrier components allowed by 3GPP up to R13.
Definition lte-common.h:25
constexpr uint32_t MAX_NO_CC
Maximum number of carrier components allowed by 3GPP up to R13.
Definition lte-common.h:28
Parameters for LtePdcpSapProvider::TransmitPdcpSdu.
Parameters for LtePdcpSapUser::ReceivePdcpSdu.
uint8_t transmissionMode
transmission mode
uint32_t dlCarrierFreq
DL carrier frequency.
uint32_t ulCarrierFreq
UL carrier frequency.
int8_t qRxLevMin
INTEGER (-70..-22), actual value = IE value * 2 [dBm].
Definition lte-rrc-sap.h:70
uint32_t ulCarrierFreq
UL carrier frequency.
Definition lte-rrc-sap.h:77
uint16_t ulBandwidth
UL bandwidth.
Definition lte-rrc-sap.h:78
MasterInformationBlock structure.
MeasConfig structure.
std::list< uint8_t > measIdToRemoveList
measure ID to remove list
std::list< MeasObjectToAddMod > measObjectToAddModList
measure object to add mod list
std::list< uint8_t > reportConfigToRemoveList
report config to remove list
std::list< uint8_t > measObjectToRemoveList
measure object to remove list
bool haveMeasGapConfig
have measure gap config?
QuantityConfig quantityConfig
quantity config
bool haveSmeasure
have S measure?
bool haveSpeedStatePars
have speed state parameters?
std::list< ReportConfigToAddMod > reportConfigToAddModList
report config to add mod list
std::list< MeasIdToAddMod > measIdToAddModList
measure ID to add mod list
bool haveQuantityConfig
have quantity config?
MeasObjectEutra structure.
int8_t offsetFreq
offset frequency
uint32_t carrierFreq
carrier frequency
MeasResultEutra structure.
uint8_t rsrqResult
RSRQ result.
uint8_t rsrpResult
RSRP result.
bool haveRsrpResult
have RSRP result
bool haveRsrqResult
have RSRQ result?
uint16_t physCellId
Phy cell ID.
bool haveCgiInfo
have CGI info?
uint8_t rsrqResult
the RSRQ result
uint8_t rsrpResult
the RSRP result
uint8_t rsrpResult
the RSRP result
uint8_t rsrqResult
the RSRQ result
MeasResultServFreq structure.
bool haveMeasResultSCell
have measResultSCell?
bool haveMeasResultBestNeighCell
have measResultBestNeighCell?
uint16_t servFreqId
serving cell index
MeasResultSCell measResultSCell
SCell measurement results.
MeasResults structure.
uint8_t measId
measure ID
bool haveMeasResultNeighCells
have measure result neighbor cells
std::list< MeasResultEutra > measResultListEutra
measure result list eutra
bool haveMeasResultServFreqList
has measResultServFreqList-r10
std::list< MeasResultServFreq > measResultServFreqList
MeasResultServFreqList-r10.
MeasResultPCell measResultPCell
measurement result primary cell
MeasurementReport structure.
MeasResults measResults
measure results
MobilityControlInfo structure.
RachConfigDedicated rachConfigDedicated
RACH config dedicated.
bool haveRachConfigDedicated
Have RACH config dedicated?
uint16_t newUeIdentity
new UE identity
bool haveCarrierBandwidth
have carrier bandwidth?
bool haveCarrierFreq
have carrier frequency?
CarrierBandwidthEutra carrierBandwidth
carrier bandwidth
CarrierFreqEutra carrierFreq
carrier frequency
uint16_t targetPhysCellId
target Phy cell ID
NonCriticalExtensionConfiguration structure.
std::list< uint8_t > sCellToReleaseList
SCell to release list.
std::list< SCellToAddMod > sCellToAddModList
SCell to add mod list.
int8_t referenceSignalPower
INTEGER (-60..50),.
PdschConfigDedicated structure.
PhysicalConfigDedicated structure.
PdschConfigDedicated pdschConfigDedicated
PDSCH config dedicated.
bool haveAntennaInfoDedicated
have antenna info dedicated?
SoundingRsUlConfigDedicated soundingRsUlConfigDedicated
sounding RS UL config dedicated
bool haveSoundingRsUlConfigDedicated
have sounding RS UL config dedicated?
bool havePdschConfigDedicated
have PDSCH config dedicated?
AntennaInfoDedicated antennaInfo
antenna info
uint8_t numberOfRaPreambles
number of RA preambles
uint8_t filterCoefficientRSRQ
filter coefficient RSRQ
uint8_t filterCoefficientRSRP
filter coefficient RSRP
uint8_t raResponseWindowSize
RA response window size.
uint8_t preambleTransMax
preamble transmit maximum
TxFailParam txFailParam
txFailParams
PreambleInfo preambleInfo
preamble info
RaSupervisionInfo raSupervisionInfo
RA supervision info.
uint8_t raPreambleIndex
RA preamble index.
uint8_t raPrachMaskIndex
RA PRACH mask index.
RachConfigCommon rachConfigCommon
RACH config common.
PdschConfigCommon pdschConfigCommon
PDSCH config common.
RadioResourceConfigDedicated structure.
PhysicalConfigDedicated physicalConfigDedicated
physical config dedicated
std::list< uint8_t > drbToReleaseList
DRB to release list.
std::list< DrbToAddMod > drbToAddModList
DRB to add mod list.
std::list< SrbToAddMod > srbToAddModList
SRB to add mod list.
Specifies criteria for triggering of an E-UTRA measurement reporting event.
bool reportOnLeave
Indicates whether or not the UE shall initiate the measurement reporting procedure when the leaving c...
uint8_t maxReportCells
Maximum number of cells, excluding the serving cell, to be included in the measurement report.
enum ns3::LteRrcSap::ReportConfigEutra::@62 eventId
Event enumeration.
enum ns3::LteRrcSap::ReportConfigEutra::@61 triggerType
Trigger enumeration.
uint8_t hysteresis
Parameter used within the entry and leave condition of an event triggered reporting condition.
@ RSRP
Reference Signal Received Power.
@ RSRQ
Reference Signal Received Quality.
@ EVENT_A2
Event A2: Serving becomes worse than absolute threshold.
@ EVENT_A3
Event A3: Neighbour becomes amount of offset better than PCell.
@ EVENT_A4
Event A4: Neighbour becomes better than absolute threshold.
@ EVENT_A1
Event A1: Serving becomes better than absolute threshold.
@ EVENT_A5
Event A5: PCell becomes worse than absolute threshold1 AND Neighbour becomes better than another abso...
enum ns3::LteRrcSap::ReportConfigEutra::@65 reportInterval
Report interval enumeration.
ThresholdEutra threshold2
Threshold for event A5.
enum ns3::LteRrcSap::ReportConfigEutra::@63 triggerQuantity
Trigger type enumeration.
ThresholdEutra threshold1
Threshold for event A1, A2, A4, and A5.
int8_t a3Offset
Offset value for Event A3.
uint16_t timeToTrigger
Time during which specific criteria for the event needs to be met in order to trigger a measurement r...
RrcConnectionReconfigurationCompleted structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
RrcConnectionReconfiguration structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
bool haveMobilityControlInfo
have mobility control info
NonCriticalExtensionConfiguration nonCriticalExtension
3GPP TS 36.331 v.11.10 R11 Sec.
bool haveRadioResourceConfigDedicated
have radio resource config dedicated
RadioResourceConfigDedicated radioResourceConfigDedicated
radio resource config dedicated
bool haveNonCriticalExtension
have critical extension?
MobilityControlInfo mobilityControlInfo
mobility control info
RrcConnectionReestablishment structure.
RrcConnectionReestablishmentReject structure.
RrcConnectionReject structure.
RrcConnectionRelease structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
RrcConnectionRequest structure.
RrcConnectionSetupCompleted structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
RrcConnectionSetup structure.
uint8_t rrcTransactionIdentifier
RRC transaction identifier.
RadioResourceConfigDedicated radioResourceConfigDedicated
radio resource config dedicated
uint16_t srsConfigIndex
SRS config index.
SystemInformationBlockType1 structure.
CellSelectionInfo cellSelectionInfo
cell selection info
CellAccessRelatedInfo cellAccessRelatedInfo
cell access related info
RadioResourceConfigCommonSib radioResourceConfigCommon
radio resource config common
SystemInformation structure.
SystemInformationBlockType2 sib2
SIB2.
@ THRESHOLD_RSRP
RSRP is used for the threshold.
@ THRESHOLD_RSRQ
RSRQ is used for the threshold.
enum ns3::LteRrcSap::ThresholdEutra::@60 choice
Threshold enumeration.
uint8_t range
Value range used in RSRP/RSRQ threshold.
uint8_t connEstFailCount
Number of times that the UE detects T300 expiry on the same cell.
uint16_t prioritizedBitRateKbps
prioritize bit rate Kbps
uint16_t bucketSizeDurationMs
bucket size duration ms
uint8_t logicalChannelGroup
logical channel group
UeMeasurementsParameters structure.
Represents a measurement result from a certain cell.
uint32_t carrierFreq
Measurement object frequency.
double rsrp
Measured RSRP in dBm.
double rsrq
Measured RSRQ in dB.
Represents a single triggered event from a measurement identity which reporting criteria have been fu...
ConcernedCells_t concernedCells
The list of cells responsible for this trigger.
EventId timer
The pending reporting event, scheduled at the end of the time-to-trigger.
uint8_t measId
The measurement identity which raised the trigger.
std::map< uint8_t, LteRrcSap::ReportConfigToAddMod > reportConfigList
report config list
Definition lte-ue-rrc.h:955
LteRrcSap::QuantityConfig quantityConfig
quantity config
Definition lte-ue-rrc.h:956
std::map< uint8_t, LteRrcSap::MeasObjectToAddMod > measObjectList
measure object list
Definition lte-ue-rrc.h:954
std::map< uint8_t, LteRrcSap::MeasIdToAddMod > measIdList
measure ID list
Definition lte-ue-rrc.h:953
Represents a single measurement reporting entry., which includes information about a measurement for ...
Definition lte-ue-rrc.h:977
uint8_t measId
measure ID
Definition lte-ue-rrc.h:978
CompleteSetupParameters structure.
SetupParameters structure.
LteRlcSapProvider * srb0SapProvider
SRB0 SAP provider.
LtePdcpSapProvider * srb1SapProvider
SRB1 SAP provider.