A Discrete-Event Network Simulator
API
epc-mme-application.cc
Go to the documentation of this file.
1/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2017-2018 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Manuel Requena <manuel.requena@cttc.es>
19 */
20
21#include "ns3/log.h"
22#include "ns3/epc-gtpc-header.h"
23#include "ns3/epc-mme-application.h"
24
25namespace ns3 {
26
27NS_LOG_COMPONENT_DEFINE ("EpcMmeApplication");
28
29NS_OBJECT_ENSURE_REGISTERED (EpcMmeApplication);
30
32 : m_gtpcUdpPort (2123) //fixed by the standard
33{
34 NS_LOG_FUNCTION (this);
36}
38{
39 NS_LOG_FUNCTION (this);
40}
41
42void
44{
45 NS_LOG_FUNCTION (this);
46 delete m_s1apSapMme;
47}
48
51{
52 static TypeId tid = TypeId ("ns3::EpcMmeApplication")
53 .SetParent<Object> ()
54 .SetGroupName ("Lte")
55 .AddConstructor<EpcMmeApplication> ();
56 return tid;
57}
58
61{
62 return m_s1apSapMme;
63}
64
65void
66EpcMmeApplication::AddSgw (Ipv4Address sgwS11Addr, Ipv4Address mmeS11Addr, Ptr<Socket> mmeS11Socket)
67{
68 NS_LOG_FUNCTION (this << sgwS11Addr << mmeS11Addr << mmeS11Socket);
69 m_sgwS11Addr = sgwS11Addr;
70 m_mmeS11Addr = mmeS11Addr;
71 m_s11Socket = mmeS11Socket;
73}
74
75void
76EpcMmeApplication::AddEnb (uint16_t gci, Ipv4Address enbS1uAddr, EpcS1apSapEnb* enbS1apSap)
77{
78 NS_LOG_FUNCTION (this << gci << enbS1uAddr << enbS1apSap);
79 Ptr<EnbInfo> enbInfo = Create<EnbInfo> ();
80 enbInfo->gci = gci;
81 enbInfo->s1uAddr = enbS1uAddr;
82 enbInfo->s1apSapEnb = enbS1apSap;
83 m_enbInfoMap[gci] = enbInfo;
84}
85
86void
88{
89 NS_LOG_FUNCTION (this << imsi);
90 Ptr<UeInfo> ueInfo = Create<UeInfo> ();
91 ueInfo->imsi = imsi;
92 ueInfo->mmeUeS1Id = imsi;
93 ueInfo->bearerCounter = 0;
94 m_ueInfoMap[imsi] = ueInfo;
95}
96
97uint8_t
99{
100 NS_LOG_FUNCTION (this << imsi);
101 std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
102 NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
103 NS_ASSERT_MSG (it->second->bearerCounter < 11, "too many bearers already! " << it->second->bearerCounter);
104 BearerInfo bearerInfo;
105 bearerInfo.bearerId = ++(it->second->bearerCounter);
106 bearerInfo.tft = tft;
107 bearerInfo.bearer = bearer;
108 it->second->bearersToBeActivated.push_back (bearerInfo);
109 return bearerInfo.bearerId;
110}
111
112
113// S1-AP SAP MME forwarded methods
114
115void
116EpcMmeApplication::DoInitialUeMessage (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t imsi, uint16_t gci)
117{
118 NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id << imsi << gci);
119 std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
120 NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
121 it->second->cellId = gci;
122
124 msg.SetImsi (imsi);
125 msg.SetUliEcgi (gci);
126
127 GtpcHeader::Fteid_t mmeS11Fteid;
129 mmeS11Fteid.teid = imsi;
130 mmeS11Fteid.addr = m_mmeS11Addr;
131 msg.SetSenderCpFteid (mmeS11Fteid); // S11 MME GTP-C F-TEID
132
133 std::list<GtpcCreateSessionRequestMessage::BearerContextToBeCreated> bearerContexts;
134 for (std::list<BearerInfo>::iterator bit = it->second->bearersToBeActivated.begin ();
135 bit != it->second->bearersToBeActivated.end ();
136 ++bit)
137 {
139 bearerContext.epsBearerId = bit->bearerId;
140 bearerContext.tft = bit->tft;
141 bearerContext.bearerLevelQos = bit->bearer;
142 bearerContexts.push_back (bearerContext);
143 }
144 NS_LOG_DEBUG ("BearerContextToBeCreated size = " << bearerContexts.size ());
145 msg.SetBearerContextsToBeCreated (bearerContexts);
146
147 msg.SetTeid (0);
149
150 Ptr<Packet> packet = Create <Packet> ();
151 packet->AddHeader (msg);
152 NS_LOG_DEBUG ("Send CreateSessionRequest to SGW " << m_sgwS11Addr);
154}
155
156void
157EpcMmeApplication::DoInitialContextSetupResponse (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapMme::ErabSetupItem> erabSetupList)
158{
159 NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id);
160 NS_FATAL_ERROR ("unimplemented");
161}
162
163void
164EpcMmeApplication::DoPathSwitchRequest (uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList)
165{
166 NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id << gci);
167 uint64_t imsi = mmeUeS1Id;
168 std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
169 NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
170 NS_LOG_INFO ("IMSI " << imsi << " old eNB: " << it->second->cellId << ", new eNB: " << gci);
171 it->second->cellId = gci;
172 it->second->enbUeS1Id = enbUeS1Id;
173
175 msg.SetImsi (imsi);
176 msg.SetUliEcgi (gci);
177
178 std::list<GtpcModifyBearerRequestMessage::BearerContextToBeModified> bearerContexts;
179 for (auto &erab : erabToBeSwitchedInDownlinkList)
180 {
181 NS_LOG_DEBUG ("erabId " << erab.erabId <<
182 " eNB " << erab.enbTransportLayerAddress <<
183 " TEID " << erab.enbTeid);
184
186 bearerContext.epsBearerId = erab.erabId;
188 bearerContext.fteid.addr = erab.enbTransportLayerAddress;
189 bearerContext.fteid.teid = erab.enbTeid;
190 bearerContexts.push_back (bearerContext);
191 }
192 msg.SetBearerContextsToBeModified (bearerContexts);
193 msg.SetTeid (imsi);
195
196 Ptr<Packet> packet = Create <Packet> ();
197 packet->AddHeader (msg);
198 NS_LOG_DEBUG ("Send ModifyBearerRequest to SGW " << m_sgwS11Addr);
200}
201
202void
203EpcMmeApplication::DoErabReleaseIndication (uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication)
204{
205 NS_LOG_FUNCTION (this << mmeUeS1Id << enbUeS1Id);
206 uint64_t imsi = mmeUeS1Id;
207 std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
208 NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
209
211 std::list<GtpcDeleteBearerCommandMessage::BearerContext> bearerContexts;
212 for (auto &erab : erabToBeReleaseIndication)
213 {
214 NS_LOG_DEBUG ("erabId " << (uint16_t)erab.erabId);
216 bearerContext.m_epsBearerId = erab.erabId;
217 bearerContexts.push_back (bearerContext);
218 }
219 msg.SetBearerContexts (bearerContexts);
220 msg.SetTeid (imsi);
222
223 Ptr<Packet> packet = Create <Packet> ();
224 packet->AddHeader (msg);
225 NS_LOG_DEBUG ("Send DeleteBearerCommand to SGW " << m_sgwS11Addr);
227}
228
229void
230EpcMmeApplication::RemoveBearer (Ptr<UeInfo> ueInfo, uint8_t epsBearerId)
231{
232 NS_LOG_FUNCTION (this << epsBearerId);
233 std::list<BearerInfo>::iterator bit = ueInfo->bearersToBeActivated.begin ();
234 while (bit != ueInfo->bearersToBeActivated.end ())
235 {
236 if (bit->bearerId == epsBearerId)
237 {
238 ueInfo->bearersToBeActivated.erase (bit);
239 ueInfo->bearerCounter = ueInfo->bearerCounter - 1;
240 break;
241 }
242 ++bit;
243 }
244}
245
246
247void
249{
250 NS_LOG_FUNCTION (this << socket);
251 NS_ASSERT (socket == m_s11Socket);
252 Ptr<Packet> packet = socket->Recv ();
253 GtpcHeader header;
254 packet->PeekHeader (header);
255 uint16_t msgType = header.GetMessageType ();
256
257 switch (msgType)
258 {
260 DoRecvCreateSessionResponse (header, packet);
261 break;
262
264 DoRecvModifyBearerResponse (header, packet);
265 break;
266
268 DoRecvDeleteBearerRequest (header, packet);
269 break;
270
271 default:
272 NS_FATAL_ERROR ("GTP-C message not supported");
273 break;
274 }
275}
276
277void
279{
280 NS_LOG_FUNCTION (this << header);
281 uint64_t imsi = header.GetTeid ();
282 NS_LOG_DEBUG ("TEID/IMSI " << imsi);
283 std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
284 NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
285 uint16_t cellId = it->second->cellId;
286 uint16_t enbUeS1Id = it->second->enbUeS1Id;
287 uint64_t mmeUeS1Id = it->second->mmeUeS1Id;
288 NS_LOG_DEBUG ("cellId " << cellId << " mmeUeS1Id " << mmeUeS1Id << " enbUeS1Id " << enbUeS1Id);
289 std::map<uint16_t, Ptr<EnbInfo> >::iterator jt = m_enbInfoMap.find (cellId);
290 NS_ASSERT_MSG (jt != m_enbInfoMap.end (), "could not find any eNB with CellId " << cellId);
291
293 packet->RemoveHeader (msg);
294
295 std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList;
296 std::list<GtpcCreateSessionResponseMessage::BearerContextCreated> bearerContexts =
298 NS_LOG_DEBUG ("BearerContextsCreated size = " << bearerContexts.size ());
299 for (auto &bearerContext : bearerContexts)
300 {
302 erab.erabId = bearerContext.epsBearerId;
303 erab.erabLevelQosParameters = bearerContext.bearerLevelQos;
304 erab.transportLayerAddress = bearerContext.fteid.addr; // SGW S1U address
305 erab.sgwTeid = bearerContext.fteid.teid;
306 NS_LOG_DEBUG ("SGW " << erab.transportLayerAddress << " TEID " << erab.sgwTeid);
307 erabToBeSetupList.push_back (erab);
308 }
309
310 NS_LOG_DEBUG ("Send InitialContextSetupRequest to eNB " << jt->second->s1apSapEnb);
311 jt->second->s1apSapEnb->InitialContextSetupRequest (mmeUeS1Id, enbUeS1Id, erabToBeSetupList);
312}
313
314void
316{
317 NS_LOG_FUNCTION (this << header);
319 packet->RemoveHeader (msg);
321
322 uint64_t imsi = header.GetTeid ();
323 NS_LOG_DEBUG ("TEID/IMSI " << imsi);
324 std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
325 NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
326 uint16_t cellId = it->second->cellId;
327 uint16_t enbUeS1Id = it->second->enbUeS1Id;
328 uint64_t mmeUeS1Id = it->second->mmeUeS1Id;
329 NS_LOG_DEBUG ("cellId " << cellId << " mmeUeS1Id " << mmeUeS1Id << " enbUeS1Id " << enbUeS1Id);
330 std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList; // unused for now
331 std::map<uint16_t, Ptr<EnbInfo> >::iterator jt = m_enbInfoMap.find (cellId);
332 NS_ASSERT_MSG (jt != m_enbInfoMap.end (), "could not find any eNB with CellId " << cellId);
333
334 NS_LOG_DEBUG ("Send PathSwitchRequestAcknowledge to eNB " << jt->second->s1apSapEnb);
335 jt->second->s1apSapEnb->PathSwitchRequestAcknowledge (enbUeS1Id, mmeUeS1Id, cellId, erabToBeSwitchedInUplinkList);
336}
337
338void
340{
341 NS_LOG_FUNCTION (this << header);
342 uint64_t imsi = header.GetTeid ();
343 NS_LOG_DEBUG ("TEID/IMSI " << imsi);
344 std::map<uint64_t, Ptr<UeInfo> >::iterator it = m_ueInfoMap.find (imsi);
345 NS_ASSERT_MSG (it != m_ueInfoMap.end (), "could not find any UE with IMSI " << imsi);
346
348 packet->RemoveHeader (msg);
349
351
352 std::list<uint8_t> epsBearerIds;
353 for (auto &ebid : msg.GetEpsBearerIds ())
354 {
355 epsBearerIds.push_back (ebid);
356 /*
357 * This condition is added to not remove bearer info at MME
358 * when UE gets disconnected since the bearers are only added
359 * at beginning of simulation at MME and if it is removed the
360 * bearers cannot be activated again unless scheduled for
361 * addition of the bearer during simulation
362 *
363 */
364 if (it->second->cellId == 0)
365 {
366 RemoveBearer (it->second, ebid); //schedules function to erase, context of de-activated bearer
367 }
368 }
369 msgOut.SetEpsBearerIds (epsBearerIds);
370 msgOut.SetTeid (imsi);
371 msgOut.ComputeMessageLength ();
372
373 Ptr<Packet> packetOut = Create <Packet> ();
374 packetOut->AddHeader (msgOut);
375 NS_LOG_DEBUG ("Send DeleteBearerResponse to SGW " << m_sgwS11Addr);
377}
378
379} // 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.
virtual ~EpcMmeApplication()
Destructor.
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.
static TypeId GetTypeId(void)
Get the type ID.
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.
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.
virtual void DoDispose()
Destructor implementation.
uint16_t m_gtpcUdpPort
UDP port for GTP-C protocol. Fixed by the standard to port 2123.
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...
Definition: epc-s1ap-sap.h:144
MME side of the S1-AP Service Access Point (SAP), provides the MME methods to be called when an S1-AP...
Definition: epc-s1ap-sap.h:54
This class contains the specification of EPS Bearers.
Definition: eps-bearer.h:92
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.
void ComputeMessageLength(void)
Compute the message length according to the message type.
uint8_t GetMessageType() const
Get 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.
Definition: ipv4-address.h:41
A base class which provides memory management and object aggregation.
Definition: object.h:88
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
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:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#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:88
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
Hold info on an EPS bearer to be activated.
EpsBearer bearer
bearer QOS characteristics
Ptr< EpcTft > tft
traffic flow template
ErabToBeSetupItem structure.
Definition: epc-s1ap-sap.h:150
EpsBearer erabLevelQosParameters
Level QOS parameters.
Definition: epc-s1ap-sap.h:152
Ipv4Address transportLayerAddress
transport layer address
Definition: epc-s1ap-sap.h:153
Ipv4Address addr
IPv4 address.
InterfaceType_t interfaceType
Interface type.