5G-LENA nr-v4.0
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-epc-ue-nas.cc
1// Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4//
5// Author: Nicola Baldo <nbaldo@cttc.es>
6
7#include "nr-epc-ue-nas.h"
8
9#include "nr-as-sap.h"
10
11#include "ns3/fatal-error.h"
12#include "ns3/log.h"
13#include "ns3/nr-epc-helper.h"
14#include "ns3/simulator.h"
15
16namespace ns3
17{
18
19NS_LOG_COMPONENT_DEFINE("NrEpcUeNas");
20
22static const std::string g_ueNasStateName[NrEpcUeNas::NUM_STATES] = {
23 "OFF",
24 "ATTACHING",
25 "IDLE_REGISTERED",
26 "CONNECTING_TO_EPC",
27 "ACTIVE",
28};
29
34static inline const std::string&
35ToString(NrEpcUeNas::State s)
36{
37 return g_ueNasStateName[s];
38}
39
40NS_OBJECT_ENSURE_REGISTERED(NrEpcUeNas);
41
43 : m_state(OFF),
44 m_csgId(0),
45 m_asSapProvider(nullptr),
46 m_bidCounter(0)
47{
48 NS_LOG_FUNCTION(this);
49 m_asSapUser = new MemberNrAsSapUser<NrEpcUeNas>(this);
50}
51
53{
54 NS_LOG_FUNCTION(this);
55}
56
57void
58NrEpcUeNas::DoDispose()
59{
60 NS_LOG_FUNCTION(this);
61 delete m_asSapUser;
62}
63
64TypeId
66{
67 static TypeId tid =
68 TypeId("ns3::NrEpcUeNas")
69 .SetParent<Object>()
70 .SetGroupName("Nr")
71 .AddConstructor<NrEpcUeNas>()
72 .AddTraceSource("StateTransition",
73 "fired upon every UE NAS state transition",
74 MakeTraceSourceAccessor(&NrEpcUeNas::m_stateTransitionCallback),
75 "ns3::NrEpcUeNas::StateTracedCallback");
76 return tid;
77}
78
79void
80NrEpcUeNas::SetDevice(Ptr<NetDevice> dev)
81{
82 NS_LOG_FUNCTION(this << dev);
83 m_device = dev;
84}
85
86void
87NrEpcUeNas::SetImsi(uint64_t imsi)
88{
89 NS_LOG_FUNCTION(this << imsi);
90 m_imsi = imsi;
91}
92
93void
94NrEpcUeNas::SetCsgId(uint32_t csgId)
95{
96 NS_LOG_FUNCTION(this << csgId);
97 m_csgId = csgId;
98 m_asSapProvider->SetCsgWhiteList(csgId);
99}
100
101uint32_t
103{
104 NS_LOG_FUNCTION(this);
105 return m_csgId;
106}
107
108void
110{
111 NS_LOG_FUNCTION(this << s);
112 m_asSapProvider = s;
113}
114
117{
118 NS_LOG_FUNCTION(this);
119 return m_asSapUser;
120}
121
122void
123NrEpcUeNas::SetForwardUpCallback(Callback<void, Ptr<Packet>> cb)
124{
125 NS_LOG_FUNCTION(this);
126 m_forwardUpCallback = cb;
127}
128
129void
131{
132 NS_LOG_FUNCTION(this << dlEarfcn);
133 m_asSapProvider->StartCellSelection(dlEarfcn);
134}
135
136void
138{
139 NS_LOG_FUNCTION(this);
140
141 // tell RRC to go into connected mode
142 m_asSapProvider->Connect();
143}
144
145void
146NrEpcUeNas::Connect(uint16_t cellId, uint32_t dlEarfcn)
147{
148 NS_LOG_FUNCTION(this << cellId << dlEarfcn);
149
150 // force the UE RRC to be camped on a specific eNB
151 m_asSapProvider->ForceCampedOnGnb(cellId, dlEarfcn);
152
153 // tell RRC to go into connected mode
154 m_asSapProvider->Connect();
155}
156
157void
159{
160 NS_LOG_FUNCTION(this);
161 SwitchToState(OFF);
162 m_asSapProvider->Disconnect();
163}
164
165void
167{
168 NS_LOG_FUNCTION(this);
169 switch (m_state)
170 {
171 case ACTIVE:
172 NS_FATAL_ERROR("the necessary NAS signaling to activate a bearer after the initial context "
173 "has already been setup is not implemented");
174 break;
175
176 default:
177 BearerToBeActivated btba;
178 btba.bearer = bearer;
179 btba.tft = tft;
180 m_bearersToBeActivatedList.push_back(btba);
181 m_bearersToBeActivatedListForReconnection.push_back(btba);
182 break;
183 }
184}
185
186bool
187NrEpcUeNas::Send(Ptr<Packet> packet, uint16_t protocolNumber)
188{
189 NS_LOG_FUNCTION(this << packet << protocolNumber);
190
191 switch (m_state)
192 {
193 case ACTIVE: {
194 uint32_t id = m_tftClassifier.Classify(packet, NrEpcTft::UPLINK, protocolNumber);
195 NS_ASSERT((id & 0xFFFFFF00) == 0);
196 auto bid = (uint8_t)(id & 0x000000FF);
197 if (bid == 0)
198 {
199 return false;
200 }
201 else
202 {
203 m_asSapProvider->SendData(packet, bid);
204 return true;
205 }
206 }
207 break;
208
209 default:
210 NS_LOG_WARN(this << " NAS OFF, discarding packet");
211 return false;
212 }
213}
214
215void
216NrEpcUeNas::DoNotifyConnectionSuccessful()
217{
218 NS_LOG_FUNCTION(this);
219
220 SwitchToState(ACTIVE); // will eventually activate dedicated bearers
221}
222
223void
224NrEpcUeNas::DoNotifyConnectionFailed()
225{
226 NS_LOG_FUNCTION(this);
227
228 // immediately retry the connection
229 Simulator::ScheduleNow(&NrAsSapProvider::Connect, m_asSapProvider);
230}
231
232void
233NrEpcUeNas::DoRecvData(Ptr<Packet> packet)
234{
235 NS_LOG_FUNCTION(this << packet);
236 m_forwardUpCallback(packet);
237}
238
239void
240NrEpcUeNas::DoNotifyConnectionReleased()
241{
242 NS_LOG_FUNCTION(this);
243 // remove tfts
244 while (m_bidCounter > 0)
245 {
246 m_tftClassifier.Delete(m_bidCounter);
247 m_bidCounter--;
248 }
249 // restore the bearer list to be activated for the next RRC connection
250 m_bearersToBeActivatedList = m_bearersToBeActivatedListForReconnection;
251
252 Disconnect();
253}
254
255void
256NrEpcUeNas::DoActivateEpsBearer(NrEpsBearer bearer, Ptr<NrEpcTft> tft)
257{
258 NS_LOG_FUNCTION(this);
259 NS_ASSERT_MSG(m_bidCounter < 11, "cannot have more than 11 EPS bearers");
260 uint8_t bid = ++m_bidCounter;
261 m_tftClassifier.Add(tft, bid);
262}
263
266{
267 NS_LOG_FUNCTION(this);
268 return m_state;
269}
270
271void
272NrEpcUeNas::SwitchToState(State newState)
273{
274 NS_LOG_FUNCTION(this << ToString(newState));
275 State oldState = m_state;
276 m_state = newState;
277 NS_LOG_INFO("IMSI " << m_imsi << " NAS " << ToString(oldState) << " --> "
278 << ToString(newState));
279 m_stateTransitionCallback(oldState, newState);
280
281 // actions to be done when entering a new state:
282 switch (m_state)
283 {
284 case ACTIVE:
285 for (auto it = m_bearersToBeActivatedList.begin(); it != m_bearersToBeActivatedList.end();
286 m_bearersToBeActivatedList.erase(it++))
287 {
288 DoActivateEpsBearer(it->bearer, it->tft);
289 }
290 break;
291
292 default:
293 break;
294 }
295}
296
297} // namespace ns3
virtual void StartCellSelection(uint32_t dlEarfcn)=0
Initiate Idle mode cell selection procedure.
virtual void SetCsgWhiteList(uint32_t csgId)=0
Set the selected Closed Subscriber Group subscription list to be used for cell selection.
virtual void ForceCampedOnGnb(uint16_t cellId, uint32_t dlEarfcn)=0
Force the RRC entity to stay camped on a certain eNodeB.
virtual void SendData(Ptr< Packet > packet, uint8_t bid)=0
Send a data packet.
virtual void Disconnect()=0
Tell the RRC entity to release the connection.
virtual void Connect()=0
Tell the RRC entity to enter Connected mode.
uint32_t Classify(Ptr< Packet > p, NrEpcTft::Direction direction, uint16_t protocolNumber)
void Add(Ptr< NrEpcTft > tft, uint32_t id)
void Connect()
Causes NAS to tell AS to go to ACTIVE state.
State GetState() const
static TypeId GetTypeId()
Get the type ID.
void SetImsi(uint64_t imsi)
NrAsSapUser * GetAsSapUser()
void SetAsSapProvider(NrAsSapProvider *s)
friend class MemberNrAsSapUser< NrEpcUeNas >
allow MemberNrAsSapUser<NrEpcUeNas> class friend access
bool Send(Ptr< Packet > p, uint16_t protocolNumber)
void StartCellSelection(uint32_t dlEarfcn)
Causes NAS to tell AS to find a suitable cell and camp to it.
uint32_t GetCsgId() const
~NrEpcUeNas() override
void SetCsgId(uint32_t csgId)
void ActivateEpsBearer(NrEpsBearer bearer, Ptr< NrEpcTft > tft)
void SetDevice(Ptr< NetDevice > dev)
void SetForwardUpCallback(Callback< void, Ptr< Packet > > cb)
This class contains the specification of EPS Bearers.