A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
epc-mme-application.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017-2018 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Manuel Requena <manuel.requena@cttc.es>
7 */
8
10
11#include "epc-gtpc-header.h"
12
13#include "ns3/log.h"
14
15#include <map>
16
17namespace ns3
18{
19
20NS_LOG_COMPONENT_DEFINE("EpcMmeApplication");
21
22NS_OBJECT_ENSURE_REGISTERED(EpcMmeApplication);
23
25 : m_gtpcUdpPort(2123) // fixed by the standard
26{
27 NS_LOG_FUNCTION(this);
29}
30
35
36void
42
45{
46 static TypeId tid = TypeId("ns3::EpcMmeApplication")
48 .SetGroupName("Lte")
49 .AddConstructor<EpcMmeApplication>();
50 return tid;
51}
52
58
59void
60EpcMmeApplication::AddSgw(Ipv4Address sgwS11Addr, Ipv4Address mmeS11Addr, Ptr<Socket> mmeS11Socket)
61{
62 NS_LOG_FUNCTION(this << sgwS11Addr << mmeS11Addr << mmeS11Socket);
63 m_sgwS11Addr = sgwS11Addr;
64 m_mmeS11Addr = mmeS11Addr;
65 m_s11Socket = mmeS11Socket;
67}
68
69void
70EpcMmeApplication::AddEnb(uint16_t gci, Ipv4Address enbS1uAddr, EpcS1apSapEnb* enbS1apSap)
71{
72 NS_LOG_FUNCTION(this << gci << enbS1uAddr << enbS1apSap);
73 Ptr<EnbInfo> enbInfo = Create<EnbInfo>();
74 enbInfo->gci = gci;
75 enbInfo->s1uAddr = enbS1uAddr;
76 enbInfo->s1apSapEnb = enbS1apSap;
77 m_enbInfoMap[gci] = enbInfo;
78}
79
80void
82{
83 NS_LOG_FUNCTION(this << imsi);
84 Ptr<UeInfo> ueInfo = Create<UeInfo>();
85 ueInfo->imsi = imsi;
86 ueInfo->mmeUeS1Id = imsi;
87 ueInfo->bearerCounter = 0;
88 m_ueInfoMap[imsi] = ueInfo;
89}
90
91uint8_t
93{
94 NS_LOG_FUNCTION(this << imsi);
95 auto it = m_ueInfoMap.find(imsi);
96 NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
97 NS_ASSERT_MSG(it->second->bearerCounter < 11,
98 "too many bearers already! " << it->second->bearerCounter);
99 BearerInfo bearerInfo;
100 bearerInfo.bearerId = ++(it->second->bearerCounter);
101 bearerInfo.tft = tft;
102 bearerInfo.bearer = bearer;
103 it->second->bearersToBeActivated.push_back(bearerInfo);
104 return bearerInfo.bearerId;
105}
106
107// S1-AP SAP MME forwarded methods
108
109void
111 uint16_t enbUeS1Id,
112 uint64_t imsi,
113 uint16_t gci)
114{
115 NS_LOG_FUNCTION(this << mmeUeS1Id << enbUeS1Id << imsi << gci);
116 auto it = m_ueInfoMap.find(imsi);
117 NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
118 it->second->cellId = gci;
119
121 msg.SetImsi(imsi);
122 msg.SetUliEcgi(gci);
123
124 GtpcHeader::Fteid_t mmeS11Fteid;
126 mmeS11Fteid.teid = imsi;
127 mmeS11Fteid.addr = m_mmeS11Addr;
128 msg.SetSenderCpFteid(mmeS11Fteid); // S11 MME GTP-C F-TEID
129
130 std::list<GtpcCreateSessionRequestMessage::BearerContextToBeCreated> bearerContexts;
131 for (auto bit = it->second->bearersToBeActivated.begin();
132 bit != it->second->bearersToBeActivated.end();
133 ++bit)
134 {
136 bearerContext.epsBearerId = bit->bearerId;
137 bearerContext.tft = bit->tft;
138 bearerContext.bearerLevelQos = bit->bearer;
139 bearerContexts.push_back(bearerContext);
140 }
141 NS_LOG_DEBUG("BearerContextToBeCreated size = " << bearerContexts.size());
142 msg.SetBearerContextsToBeCreated(bearerContexts);
143
144 msg.SetTeid(0);
146
147 Ptr<Packet> packet = Create<Packet>();
148 packet->AddHeader(msg);
149 NS_LOG_DEBUG("Send CreateSessionRequest to SGW " << m_sgwS11Addr);
151}
152
153void
155 uint64_t mmeUeS1Id,
156 uint16_t enbUeS1Id,
157 std::list<EpcS1apSapMme::ErabSetupItem> erabSetupList)
158{
159 NS_LOG_FUNCTION(this << mmeUeS1Id << enbUeS1Id);
160 NS_FATAL_ERROR("unimplemented");
161}
162
163void
165 uint64_t enbUeS1Id,
166 uint64_t mmeUeS1Id,
167 uint16_t gci,
168 std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList)
169{
170 NS_LOG_FUNCTION(this << mmeUeS1Id << enbUeS1Id << gci);
171 uint64_t imsi = mmeUeS1Id;
172 auto it = m_ueInfoMap.find(imsi);
173 NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
174 NS_LOG_INFO("IMSI " << imsi << " old eNB: " << it->second->cellId << ", new eNB: " << gci);
175 it->second->cellId = gci;
176 it->second->enbUeS1Id = enbUeS1Id;
177
179 msg.SetImsi(imsi);
180 msg.SetUliEcgi(gci);
181
182 std::list<GtpcModifyBearerRequestMessage::BearerContextToBeModified> bearerContexts;
183 for (auto& erab : erabToBeSwitchedInDownlinkList)
184 {
185 NS_LOG_DEBUG("erabId " << erab.erabId << " eNB " << erab.enbTransportLayerAddress
186 << " TEID " << erab.enbTeid);
187
189 bearerContext.epsBearerId = erab.erabId;
191 bearerContext.fteid.addr = erab.enbTransportLayerAddress;
192 bearerContext.fteid.teid = erab.enbTeid;
193 bearerContexts.push_back(bearerContext);
194 }
195 msg.SetBearerContextsToBeModified(bearerContexts);
196 msg.SetTeid(imsi);
198
199 Ptr<Packet> packet = Create<Packet>();
200 packet->AddHeader(msg);
201 NS_LOG_DEBUG("Send ModifyBearerRequest to SGW " << m_sgwS11Addr);
203}
204
205void
207 uint64_t mmeUeS1Id,
208 uint16_t enbUeS1Id,
209 std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication)
210{
211 NS_LOG_FUNCTION(this << mmeUeS1Id << enbUeS1Id);
212 uint64_t imsi = mmeUeS1Id;
213 auto it = m_ueInfoMap.find(imsi);
214 NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
215
217 std::list<GtpcDeleteBearerCommandMessage::BearerContext> bearerContexts;
218 for (auto& erab : erabToBeReleaseIndication)
219 {
220 NS_LOG_DEBUG("erabId " << (uint16_t)erab.erabId);
222 bearerContext.m_epsBearerId = erab.erabId;
223 bearerContexts.push_back(bearerContext);
224 }
225 msg.SetBearerContexts(bearerContexts);
226 msg.SetTeid(imsi);
228
229 Ptr<Packet> packet = Create<Packet>();
230 packet->AddHeader(msg);
231 NS_LOG_DEBUG("Send DeleteBearerCommand to SGW " << m_sgwS11Addr);
233}
234
235void
237{
238 NS_LOG_FUNCTION(this << epsBearerId);
239 auto bit = ueInfo->bearersToBeActivated.begin();
240 while (bit != ueInfo->bearersToBeActivated.end())
241 {
242 if (bit->bearerId == epsBearerId)
243 {
244 ueInfo->bearersToBeActivated.erase(bit);
245 ueInfo->bearerCounter = ueInfo->bearerCounter - 1;
246 break;
247 }
248 ++bit;
249 }
250}
251
252void
254{
255 NS_LOG_FUNCTION(this << socket);
256 NS_ASSERT(socket == m_s11Socket);
257 Ptr<Packet> packet = socket->Recv();
258 GtpcHeader header;
259 packet->PeekHeader(header);
260 uint16_t msgType = header.GetMessageType();
261
262 switch (msgType)
263 {
265 DoRecvCreateSessionResponse(header, packet);
266 break;
267
269 DoRecvModifyBearerResponse(header, packet);
270 break;
271
273 DoRecvDeleteBearerRequest(header, packet);
274 break;
275
276 default:
277 NS_FATAL_ERROR("GTP-C message not supported");
278 break;
279 }
280}
281
282void
284{
285 NS_LOG_FUNCTION(this << header);
286 uint64_t imsi = header.GetTeid();
287 NS_LOG_DEBUG("TEID/IMSI " << imsi);
288 auto it = m_ueInfoMap.find(imsi);
289 NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
290 uint16_t cellId = it->second->cellId;
291 uint16_t enbUeS1Id = it->second->enbUeS1Id;
292 uint64_t mmeUeS1Id = it->second->mmeUeS1Id;
293 NS_LOG_DEBUG("cellId " << cellId << " mmeUeS1Id " << mmeUeS1Id << " enbUeS1Id " << enbUeS1Id);
294 auto jt = m_enbInfoMap.find(cellId);
295 NS_ASSERT_MSG(jt != m_enbInfoMap.end(), "could not find any eNB with CellId " << cellId);
296
298 packet->RemoveHeader(msg);
299
300 std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList;
301 std::list<GtpcCreateSessionResponseMessage::BearerContextCreated> bearerContexts =
303 NS_LOG_DEBUG("BearerContextsCreated size = " << bearerContexts.size());
304 for (auto& bearerContext : bearerContexts)
305 {
307 erab.erabId = bearerContext.epsBearerId;
308 erab.erabLevelQosParameters = bearerContext.bearerLevelQos;
309 erab.transportLayerAddress = bearerContext.fteid.addr; // SGW S1U address
310 erab.sgwTeid = bearerContext.fteid.teid;
311 NS_LOG_DEBUG("SGW " << erab.transportLayerAddress << " TEID " << erab.sgwTeid);
312 erabToBeSetupList.push_back(erab);
313 }
314
315 NS_LOG_DEBUG("Send InitialContextSetupRequest to eNB " << jt->second->s1apSapEnb);
316 jt->second->s1apSapEnb->InitialContextSetupRequest(mmeUeS1Id, enbUeS1Id, erabToBeSetupList);
317}
318
319void
321{
322 NS_LOG_FUNCTION(this << header);
324 packet->RemoveHeader(msg);
326
327 uint64_t imsi = header.GetTeid();
328 NS_LOG_DEBUG("TEID/IMSI " << imsi);
329 auto it = m_ueInfoMap.find(imsi);
330 NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
331 uint16_t cellId = it->second->cellId;
332 uint16_t enbUeS1Id = it->second->enbUeS1Id;
333 uint64_t mmeUeS1Id = it->second->mmeUeS1Id;
334 NS_LOG_DEBUG("cellId " << cellId << " mmeUeS1Id " << mmeUeS1Id << " enbUeS1Id " << enbUeS1Id);
335 std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem>
336 erabToBeSwitchedInUplinkList; // unused for now
337 auto jt = m_enbInfoMap.find(cellId);
338 NS_ASSERT_MSG(jt != m_enbInfoMap.end(), "could not find any eNB with CellId " << cellId);
339
340 NS_LOG_DEBUG("Send PathSwitchRequestAcknowledge to eNB " << jt->second->s1apSapEnb);
341 jt->second->s1apSapEnb->PathSwitchRequestAcknowledge(enbUeS1Id,
342 mmeUeS1Id,
343 cellId,
344 erabToBeSwitchedInUplinkList);
345}
346
347void
349{
350 NS_LOG_FUNCTION(this << header);
351 uint64_t imsi = header.GetTeid();
352 NS_LOG_DEBUG("TEID/IMSI " << imsi);
353 auto it = m_ueInfoMap.find(imsi);
354 NS_ASSERT_MSG(it != m_ueInfoMap.end(), "could not find any UE with IMSI " << imsi);
355
357 packet->RemoveHeader(msg);
358
360
361 std::list<uint8_t> epsBearerIds;
362 for (auto& ebid : msg.GetEpsBearerIds())
363 {
364 epsBearerIds.push_back(ebid);
365 /*
366 * This condition is added to not remove bearer info at MME
367 * when UE gets disconnected since the bearers are only added
368 * at beginning of simulation at MME and if it is removed the
369 * bearers cannot be activated again unless scheduled for
370 * addition of the bearer during simulation
371 *
372 */
373 if (it->second->cellId == 0)
374 {
375 RemoveBearer(it->second,
376 ebid); // schedules function to erase, context of de-activated bearer
377 }
378 }
379 msgOut.SetEpsBearerIds(epsBearerIds);
380 msgOut.SetTeid(imsi);
381 msgOut.ComputeMessageLength();
382
383 Ptr<Packet> packetOut = Create<Packet>();
384 packetOut->AddHeader(msgOut);
385 NS_LOG_DEBUG("Send DeleteBearerResponse to SGW " << m_sgwS11Addr);
387}
388
389} // namespace ns3
This application implements the Mobility Management Entity (MME) according to the 3GPP TS 23....
void AddUe(uint64_t imsi)
Add a new UE to the MME.
void DoPathSwitchRequest(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list< EpcS1apSapMme::ErabSwitchedInDownlinkItem > erabToBeSwitchedInDownlinkList)
Process the S1 Path Switch Request received from an eNB.
void AddEnb(uint16_t ecgi, Ipv4Address enbS1UAddr, EpcS1apSapEnb *enbS1apSap)
Add a new eNB to the MME.
std::map< uint64_t, Ptr< UeInfo > > m_ueInfoMap
UeInfo stored by IMSI.
void AddSgw(Ipv4Address sgwS11Addr, Ipv4Address mmeS11Addr, Ptr< Socket > mmeS11Socket)
Add a new SGW to the MME.
Ptr< Socket > m_s11Socket
Socket to send/receive messages in the S11 interface.
friend class MemberEpcS1apSapMme< EpcMmeApplication >
allow MemberEpcS1apSapMme<EpcMme> class friend access
EpcS1apSapMme * m_s1apSapMme
EpcS1apSapMme.
Ipv4Address m_mmeS11Addr
IPv4 address of the MME S11 interface.
Ipv4Address m_sgwS11Addr
IPv4 address of the SGW S11 interface.
~EpcMmeApplication() override
Destructor.
void DoInitialContextSetupResponse(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< EpcS1apSapMme::ErabSetupItem > erabSetupList)
Process the S1 Initial Context Setup Response received from an eNB.
void DoInitialUeMessage(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t ecgi)
Process the S1 Initial UE Message received from an eNB.
static TypeId GetTypeId()
Get the type ID.
void DoErabReleaseIndication(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< EpcS1apSapMme::ErabToBeReleasedIndication > erabToBeReleaseIndication)
Process ERAB Release Indication received from an eNB.
void DoRecvCreateSessionResponse(GtpcHeader &header, Ptr< Packet > packet)
Process GTP-C Create Session Response message.
void DoRecvDeleteBearerRequest(GtpcHeader &header, Ptr< Packet > packet)
Process GTP-C Delete Bearer Request message.
void DoRecvModifyBearerResponse(GtpcHeader &header, Ptr< Packet > packet)
Process GTP-C Modify Bearer Response message.
std::map< uint16_t, Ptr< EnbInfo > > m_enbInfoMap
EnbInfo stored by EGCI.
void RemoveBearer(Ptr< UeInfo > ueInfo, uint8_t epsBearerId)
This Function erases all contexts of bearer from MME side.
uint8_t AddBearer(uint64_t imsi, Ptr< EpcTft > tft, EpsBearer bearer)
Add an EPS bearer to the list of bearers to be activated for this UE.
uint16_t m_gtpcUdpPort
UDP port for GTP-C protocol. Fixed by the standard to port 2123.
void DoDispose() override
Destructor implementation.
EpcS1apSapMme * GetS1apSapMme()
void RecvFromS11Socket(Ptr< Socket > socket)
Reads the S11 messages from a socket.
eNB side of the S1-AP Service Access Point (SAP), provides the eNB methods to be called when an S1-AP...
MME side of the S1-AP Service Access Point (SAP), provides the MME methods to be called when an S1-AP...
This class contains the specification of EPS Bearers.
Definition eps-bearer.h:80
GTP-C Create Session Request Message.
void SetUliEcgi(uint32_t uliEcgi)
Set the UliEcgi.
void SetBearerContextsToBeCreated(std::list< BearerContextToBeCreated > bearerContexts)
Set the Bearer Contexts.
void SetImsi(uint64_t imsi)
Set the IMSI.
void SetSenderCpFteid(GtpcHeader::Fteid_t fteid)
Set the Sender CpFteid.
GTP-C Create Session Response Message.
std::list< BearerContextCreated > GetBearerContextsCreated() const
Get the Container of Bearer Contexts.
GTP-C Delete Bearer Command Message.
void SetBearerContexts(std::list< BearerContext > bearerContexts)
Set the Bearer contexts.
GTP-C Delete Bearer Request Message.
std::list< uint8_t > GetEpsBearerIds() const
Get the Bearers IDs.
GTP-C Delete Bearer Response Message.
void SetEpsBearerIds(std::list< uint8_t > epsBearerIds)
Set the Bearers IDs.
Header of the GTPv2-C protocol.
uint8_t GetMessageType() const
Get message type.
void ComputeMessageLength()
Compute the message length according to the message type.
void SetTeid(uint32_t teid)
Set TEID.
uint32_t GetTeid() const
Get TEID.
GTP-C Modify Bearer Request Message.
void SetBearerContextsToBeModified(std::list< BearerContextToBeModified > bearerContexts)
Set the Bearer Contexts.
void SetUliEcgi(uint32_t uliEcgi)
Set the UliEcgi.
void SetImsi(uint64_t imsi)
Set the IMSI.
GTP-C Modify Bearer Response Message.
Cause_t GetCause() const
Get the Cause.
an Inet address class
Ipv4 addresses are stored in host order in this class.
A base class which provides memory management and object aggregation.
Definition object.h:78
Smart pointer class similar to boost::intrusive_ptr.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition socket.cc:117
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#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
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#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_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Hold info on an EPS bearer to be activated.
EpsBearer bearer
bearer QOS characteristics
Ptr< EpcTft > tft
traffic flow template
ErabToBeSetupItem structure.
EpsBearer erabLevelQosParameters
Level QOS parameters.
Ipv4Address transportLayerAddress
transport layer address
Ipv4Address addr
IPv4 address.
InterfaceType_t interfaceType
Interface type.