A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
epc-enb-application.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Jaume Nin <jnin@cttc.cat>
18 * Nicola Baldo <nbaldo@cttc.cat>
19 */
20
21#include "epc-enb-application.h"
22
23#include "epc-gtpu-header.h"
24#include "eps-bearer-tag.h"
25
26#include "ns3/inet-socket-address.h"
27#include "ns3/ipv4.h"
28#include "ns3/log.h"
29#include "ns3/mac48-address.h"
30#include "ns3/uinteger.h"
31
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("EpcEnbApplication");
36
38{
39}
40
41EpcEnbApplication::EpsFlowId_t::EpsFlowId_t(const uint16_t a, const uint8_t b)
42 : m_rnti(a),
43 m_bid(b)
44{
45}
46
47bool
49{
50 return ((a.m_rnti == b.m_rnti) && (a.m_bid == b.m_bid));
51}
52
53bool
55{
56 return ((a.m_rnti < b.m_rnti) || ((a.m_rnti == b.m_rnti) && (a.m_bid < b.m_bid)));
57}
58
61{
62 static TypeId tid =
63 TypeId("ns3::EpcEnbApplication")
65 .SetGroupName("Lte")
66 .AddTraceSource("RxFromEnb",
67 "Receive data packets from LTE Enb Net Device",
69 "ns3::EpcEnbApplication::RxTracedCallback")
70 .AddTraceSource("RxFromS1u",
71 "Receive data packets from S1-U Net Device",
73 "ns3::EpcEnbApplication::RxTracedCallback");
74 return tid;
75}
76
77void
79{
80 NS_LOG_FUNCTION(this);
81 m_lteSocket = nullptr;
82 m_lteSocket6 = nullptr;
83 m_s1uSocket = nullptr;
84 delete m_s1SapProvider;
85 delete m_s1apSapEnb;
86}
87
88EpcEnbApplication::EpcEnbApplication(Ptr<Socket> lteSocket, Ptr<Socket> lteSocket6, uint16_t cellId)
89 : m_lteSocket(lteSocket),
90 m_lteSocket6(lteSocket6),
91 m_gtpuUdpPort(2152), // fixed by the standard
92 m_s1SapUser(nullptr),
93 m_s1apSapMme(nullptr),
94 m_cellId(cellId)
95{
96 NS_LOG_FUNCTION(this << lteSocket << lteSocket6 << cellId);
97
102}
103
104void
106 Ipv4Address enbAddress,
107 Ipv4Address sgwAddress)
108{
109 NS_LOG_FUNCTION(this << s1uSocket << enbAddress << sgwAddress);
110
111 m_s1uSocket = s1uSocket;
113 m_enbS1uAddress = enbAddress;
114 m_sgwS1uAddress = sgwAddress;
115}
116
118{
119 NS_LOG_FUNCTION(this);
120}
121
122void
124{
125 m_s1SapUser = s;
126}
127
130{
131 return m_s1SapProvider;
132}
133
134void
136{
137 m_s1apSapMme = s;
138}
139
142{
143 return m_s1apSapEnb;
144}
145
146void
147EpcEnbApplication::DoInitialUeMessage(uint64_t imsi, uint16_t rnti)
148{
149 NS_LOG_FUNCTION(this);
150 // side effect: create entry if not exist
151 m_imsiRntiMap[imsi] = rnti;
152 m_s1apSapMme->InitialUeMessage(imsi, rnti, imsi, m_cellId);
153}
154
155void
157{
158 NS_LOG_FUNCTION(this);
159 uint16_t enbUeS1Id = params.rnti;
160 uint64_t mmeUeS1Id = params.mmeUeS1Id;
161 uint64_t imsi = mmeUeS1Id;
162 // side effect: create entry if not exist
163 m_imsiRntiMap[imsi] = params.rnti;
164
165 uint16_t gci = params.cellId;
166 std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList;
167 for (auto bit = params.bearersToBeSwitched.begin(); bit != params.bearersToBeSwitched.end();
168 ++bit)
169 {
170 EpsFlowId_t flowId;
171 flowId.m_rnti = params.rnti;
172 flowId.m_bid = bit->epsBearerId;
173 uint32_t teid = bit->teid;
174
175 EpsFlowId_t rbid(params.rnti, bit->epsBearerId);
176 // side effect: create entries if not exist
177 m_rbidTeidMap[params.rnti][bit->epsBearerId] = teid;
178 m_teidRbidMap[teid] = rbid;
179
181 erab.erabId = bit->epsBearerId;
183 erab.enbTeid = bit->teid;
184
185 erabToBeSwitchedInDownlinkList.push_back(erab);
186 }
187 m_s1apSapMme->PathSwitchRequest(enbUeS1Id, mmeUeS1Id, gci, erabToBeSwitchedInDownlinkList);
188}
189
190void
192{
193 NS_LOG_FUNCTION(this << rnti);
194 auto rntiIt = m_rbidTeidMap.find(rnti);
195 if (rntiIt != m_rbidTeidMap.end())
196 {
197 for (auto bidIt = rntiIt->second.begin(); bidIt != rntiIt->second.end(); ++bidIt)
198 {
199 uint32_t teid = bidIt->second;
200 m_teidRbidMap.erase(teid);
201 NS_LOG_INFO("TEID: " << teid << " erased");
202 }
203 m_rbidTeidMap.erase(rntiIt);
204 NS_LOG_INFO("RNTI: " << rntiIt->first << " erased");
205 }
206}
207
208void
210 uint64_t mmeUeS1Id,
211 uint16_t enbUeS1Id,
212 std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList)
213{
214 NS_LOG_FUNCTION(this);
215
216 uint64_t imsi = mmeUeS1Id;
217 auto imsiIt = m_imsiRntiMap.find(imsi);
218 NS_ASSERT_MSG(imsiIt != m_imsiRntiMap.end(), "unknown IMSI");
219 uint16_t rnti = imsiIt->second;
220
221 for (auto erabIt = erabToBeSetupList.begin(); erabIt != erabToBeSetupList.end(); ++erabIt)
222 {
223 // request the RRC to setup a radio bearer
225 params.rnti = rnti;
226 params.bearer = erabIt->erabLevelQosParameters;
227 params.bearerId = erabIt->erabId;
228 params.gtpTeid = erabIt->sgwTeid;
230
231 EpsFlowId_t rbid(rnti, erabIt->erabId);
232 // side effect: create entries if not exist
233 m_rbidTeidMap[rnti][erabIt->erabId] = params.gtpTeid;
234 m_teidRbidMap[params.gtpTeid] = rbid;
235 }
236
237 // Send Initial Context Setup Request to RRC
239 params.rnti = rnti;
241}
242
243void
245 uint64_t enbUeS1Id,
246 uint64_t mmeUeS1Id,
247 uint16_t gci,
248 std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
249{
250 NS_LOG_FUNCTION(this);
251
252 uint64_t imsi = mmeUeS1Id;
253 auto imsiIt = m_imsiRntiMap.find(imsi);
254 NS_ASSERT_MSG(imsiIt != m_imsiRntiMap.end(), "unknown IMSI");
255 uint16_t rnti = imsiIt->second;
257 params.rnti = rnti;
259}
260
261void
263{
264 NS_LOG_FUNCTION(this);
265 if (m_lteSocket6)
266 {
267 NS_ASSERT(socket == m_lteSocket || socket == m_lteSocket6);
268 }
269 else
270 {
271 NS_ASSERT(socket == m_lteSocket);
272 }
273 Ptr<Packet> packet = socket->Recv();
274
275 EpsBearerTag tag;
276 bool found = packet->RemovePacketTag(tag);
277 NS_ASSERT(found);
278 uint16_t rnti = tag.GetRnti();
279 uint8_t bid = tag.GetBid();
280 NS_LOG_INFO("Received packet with RNTI: " << rnti << ", BID: " << +bid);
281 auto rntiIt = m_rbidTeidMap.find(rnti);
282 if (rntiIt == m_rbidTeidMap.end())
283 {
284 NS_LOG_WARN("UE context not found, discarding packet");
285 }
286 else
287 {
288 auto bidIt = rntiIt->second.find(bid);
289 NS_ASSERT(bidIt != rntiIt->second.end());
290 uint32_t teid = bidIt->second;
291 m_rxLteSocketPktTrace(packet->Copy());
292 SendToS1uSocket(packet, teid);
293 }
294}
295
296void
298{
299 NS_LOG_FUNCTION(this << socket);
300 NS_ASSERT(socket == m_s1uSocket);
301 Ptr<Packet> packet = socket->Recv();
302 GtpuHeader gtpu;
303 packet->RemoveHeader(gtpu);
304 uint32_t teid = gtpu.GetTeid();
305 NS_LOG_INFO("Received packet from S1-U interface with GTP TEID: " << teid);
306 auto it = m_teidRbidMap.find(teid);
307 if (it == m_teidRbidMap.end())
308 {
309 NS_LOG_WARN("UE context at cell id " << m_cellId << " not found, discarding packet");
310 }
311 else
312 {
313 m_rxS1uSocketPktTrace(packet->Copy());
314 SendToLteSocket(packet, it->second.m_rnti, it->second.m_bid);
315 }
316}
317
318void
319EpcEnbApplication::SendToLteSocket(Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
320{
321 NS_LOG_FUNCTION(this << packet << rnti << bid << packet->GetSize());
322 EpsBearerTag tag(rnti, bid);
323 packet->AddPacketTag(tag);
324 NS_LOG_INFO("Add EpsBearerTag with RNTI " << rnti << " and bearer ID " << +bid);
325 uint8_t ipType;
326
327 packet->CopyData(&ipType, 1);
328 ipType = (ipType >> 4) & 0x0f;
329
330 int sentBytes;
331 if (ipType == 0x04)
332 {
333 NS_LOG_INFO("Forward packet from eNB's S1-U to LTE stack via IPv4 socket.");
334 sentBytes = m_lteSocket->Send(packet);
335 }
336 else if (ipType == 0x06)
337 {
338 NS_LOG_INFO("Forward packet from eNB's S1-U to LTE stack via IPv6 socket.");
339 sentBytes = m_lteSocket6->Send(packet);
340 }
341 else
342 {
343 NS_ABORT_MSG("EpcEnbApplication::SendToLteSocket - Unknown IP type...");
344 }
345
346 NS_ASSERT(sentBytes > 0);
347}
348
349void
351{
352 NS_LOG_FUNCTION(this << packet << teid << packet->GetSize());
353 GtpuHeader gtpu;
354 gtpu.SetTeid(teid);
355 // From 3GPP TS 29.281 v10.0.0 Section 5.1
356 // Length of the payload + the non obligatory GTP-U header
357 gtpu.SetLength(packet->GetSize() + gtpu.GetSerializedSize() - 8);
358 packet->AddHeader(gtpu);
359 uint32_t flags = 0;
360 NS_LOG_INFO("Forward packet from eNB's LTE to S1-U stack with TEID: " << teid);
362}
363
364void
365EpcEnbApplication::DoReleaseIndication(uint64_t imsi, uint16_t rnti, uint8_t bearerId)
366{
367 NS_LOG_FUNCTION(this << bearerId);
368 std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication;
370 erab.erabId = bearerId;
371 erabToBeReleaseIndication.push_back(erab);
372 // From 3GPP TS 23401-950 Section 5.4.4.2, enB sends EPS bearer Identity in Bearer Release
373 // Indication message to MME
374 m_s1apSapMme->ErabReleaseIndication(imsi, rnti, erabToBeReleaseIndication);
375}
376
377} // namespace ns3
std::map< uint16_t, std::map< uint8_t, uint32_t > > m_rbidTeidMap
map of maps telling for each RNTI and BID the corresponding S1-U TEID
EpcS1apSapEnb * m_s1apSapEnb
ENB side of the S1-AP SAP.
Ipv4Address m_enbS1uAddress
address of the eNB for S1-U communications
Ptr< Socket > m_s1uSocket
UDP socket to send and receive GTP-U the packets to and from the S1-U interface.
void DoReleaseIndication(uint64_t imsi, uint16_t rnti, uint8_t bearerId)
This function accepts bearer id corresponding to a particular UE and schedules indication of bearer r...
void DoPathSwitchRequestAcknowledge(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t cgi, std::list< EpcS1apSapEnb::ErabSwitchedInUplinkItem > erabToBeSwitchedInUplinkList)
Path Switch Request Acknowledge.
void RecvFromLteSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the LTE socket.
void AddS1Interface(Ptr< Socket > s1uSocket, Ipv4Address enbS1uAddress, Ipv4Address sgwS1uAddress)
Add a S1-U interface to the eNB.
void DoInitialContextSetupRequest(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< EpcS1apSapEnb::ErabToBeSetupItem > erabToBeSetupList)
Initial Context Setup Request.
void DoDispose() override
Destructor implementation.
void DoUeContextRelease(uint16_t rnti)
UE Context Release function.
Ipv4Address m_sgwS1uAddress
address of the SGW which terminates all S1-U tunnels
Ptr< Socket > m_lteSocket
raw packet socket to send and receive the packets to and from the LTE radio interface
void SendToS1uSocket(Ptr< Packet > packet, uint32_t teid)
Send a packet to the SGW via the S1-U interface.
void SetS1apSapMme(EpcS1apSapMme *s)
Set the MME side of the S1-AP SAP.
EpcEnbS1SapProvider * GetS1SapProvider()
static TypeId GetTypeId()
Get the type ID.
void SendToLteSocket(Ptr< Packet > packet, uint16_t rnti, uint8_t bid)
Send a packet to the UE via the LTE radio interface of the eNB.
EpcS1apSapEnb * GetS1apSapEnb()
TracedCallback< Ptr< Packet > > m_rxLteSocketPktTrace
Callback to trace RX (reception) data packets from LTE Socket.
void RecvFromS1uSocket(Ptr< Socket > socket)
Method to be assigned to the recv callback of the S1-U socket.
friend class MemberEpcEnbS1SapProvider< EpcEnbApplication >
allow MemberEpcEnbS1SapProvider<EpcEnbApplication> class friend access
std::map< uint64_t, uint16_t > m_imsiRntiMap
UE context info.
EpcEnbS1SapUser * m_s1SapUser
User for the S1 SAP.
Ptr< Socket > m_lteSocket6
raw packet socket to send and receive the packets to and from the LTE radio interface
void DoPathSwitchRequest(EpcEnbS1SapProvider::PathSwitchRequestParameters params)
Path switch request function.
uint16_t m_gtpuUdpPort
UDP port to be used for GTP.
void DoInitialUeMessage(uint64_t imsi, uint16_t rnti)
Initial UE message function.
std::map< uint32_t, EpsFlowId_t > m_teidRbidMap
map telling for each S1-U TEID the corresponding RNTI,BID
friend class MemberEpcS1apSapEnb< EpcEnbApplication >
allow MemberEpcS1apSapEnb<EpcEnbApplication> class friend access
EpcS1apSapMme * m_s1apSapMme
MME side of the S1-AP SAP.
EpcEnbApplication(Ptr< Socket > lteSocket, Ptr< Socket > lteSocket6, uint16_t cellId)
Constructor.
EpcEnbS1SapProvider * m_s1SapProvider
Provider for the S1 SAP.
void SetS1SapUser(EpcEnbS1SapUser *s)
Set the S1 SAP User.
~EpcEnbApplication() override
Destructor.
TracedCallback< Ptr< Packet > > m_rxS1uSocketPktTrace
Callback to trace RX (reception) data packets from S1-U Socket.
This class implements the Service Access Point (SAP) between the LteEnbRrc and the EpcEnbApplication.
This class implements the Service Access Point (SAP) between the LteEnbRrc and the EpcEnbApplication.
virtual void PathSwitchRequestAcknowledge(PathSwitchRequestAcknowledgeParameters params)=0
Request a path switch acknowledge.
virtual void DataRadioBearerSetupRequest(DataRadioBearerSetupRequestParameters params)=0
Request the setup of a DataRadioBearer.
virtual void InitialContextSetupRequest(InitialContextSetupRequestParameters params)=0
Initial context setup request.
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:53
virtual void InitialUeMessage(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, uint64_t stmsi, uint16_t ecgi)=0
Initial UE message.
virtual void ErabReleaseIndication(uint64_t mmeUeS1Id, uint16_t enbUeS1Id, std::list< ErabToBeReleasedIndication > erabToBeReleaseIndication)=0
As per 3GPP TS 36.413 version 9.8.0 section 8.2.3.2.2, the eNB indicates bearer release by sending an...
virtual void PathSwitchRequest(uint64_t enbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list< ErabSwitchedInDownlinkItem > erabToBeSwitchedInDownlinkList)=0
PATH SWITCH REQUEST message, see 3GPP TS 36.413 9.1.5.8.
Tag used to define the RNTI and EPS bearer ID for packets interchanged between the EpcEnbApplication ...
uint8_t GetBid() const
Get Bearer Id function.
uint16_t GetRnti() const
Get RNTI function.
Implementation of the GPRS Tunnelling Protocol header according to GTPv1-U Release 10 as per 3Gpp TS ...
void SetTeid(uint32_t teid)
Set TEID function.
uint32_t GetSerializedSize() const override
uint32_t GetTeid() const
Get a tunnel endpoint identificator (TEID)
void SetLength(uint16_t length)
Set the length in octets of the payload.
an Inet address class
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
A base class which provides memory management and object aggregation.
Definition: object.h:89
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
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:932
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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:86
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
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.
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:706
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:157
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:170
uint8_t m_bid
Bid, the EPS Bearer Identifier.
PathSwitchRequestParameters structure.
Parameters passed to DataRadioBearerSetupRequest ()
Parameters passed to InitialContextSetupRequest ()
PathSwitchRequestAcknowledgeParameters structure.
E-RAB Release Indication Item IEs, 3GPP TS 36.413 version 9.8.0 section 9.1.3.7.
Definition: epc-s1ap-sap.h:72