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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Jaume Nin <jnin@cttc.cat>
7 * Nicola Baldo <nbaldo@cttc.cat>
8 */
9
10#include "epc-enb-application.h"
11
12#include "epc-gtpu-header.h"
13#include "eps-bearer-tag.h"
14
15#include "ns3/inet-socket-address.h"
16#include "ns3/ipv4.h"
17#include "ns3/log.h"
18#include "ns3/mac48-address.h"
19#include "ns3/uinteger.h"
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("EpcEnbApplication");
25
29
30EpcEnbApplication::EpsFlowId_t::EpsFlowId_t(const uint16_t a, const uint8_t b)
31 : m_rnti(a),
32 m_bid(b)
33{
34}
35
36bool
38{
39 return ((a.m_rnti == b.m_rnti) && (a.m_bid == b.m_bid));
40}
41
42bool
44{
45 return ((a.m_rnti < b.m_rnti) || ((a.m_rnti == b.m_rnti) && (a.m_bid < b.m_bid)));
46}
47
50{
51 static TypeId tid =
52 TypeId("ns3::EpcEnbApplication")
54 .SetGroupName("Lte")
55 .AddTraceSource("RxFromEnb",
56 "Receive data packets from LTE Enb Net Device",
58 "ns3::EpcEnbApplication::RxTracedCallback")
59 .AddTraceSource("RxFromS1u",
60 "Receive data packets from S1-U Net Device",
62 "ns3::EpcEnbApplication::RxTracedCallback");
63 return tid;
64}
65
66void
68{
69 NS_LOG_FUNCTION(this);
70 m_lteSocket = nullptr;
71 m_lteSocket6 = nullptr;
72 m_s1uSocket = nullptr;
73 delete m_s1SapProvider;
74 delete m_s1apSapEnb;
75}
76
77EpcEnbApplication::EpcEnbApplication(Ptr<Socket> lteSocket, Ptr<Socket> lteSocket6, uint16_t cellId)
78 : m_lteSocket(lteSocket),
79 m_lteSocket6(lteSocket6),
80 m_gtpuUdpPort(2152), // fixed by the standard
81 m_s1SapUser(nullptr),
82 m_s1apSapMme(nullptr),
83 m_cellId(cellId)
84{
85 NS_LOG_FUNCTION(this << lteSocket << lteSocket6 << cellId);
86
91}
92
93void
95 Ipv4Address enbAddress,
96 Ipv4Address sgwAddress)
97{
98 NS_LOG_FUNCTION(this << s1uSocket << enbAddress << sgwAddress);
99
100 m_s1uSocket = s1uSocket;
102 m_enbS1uAddress = enbAddress;
103 m_sgwS1uAddress = sgwAddress;
104}
105
110
111void
116
122
123void
128
134
135void
136EpcEnbApplication::DoInitialUeMessage(uint64_t imsi, uint16_t rnti)
137{
138 NS_LOG_FUNCTION(this);
139 // side effect: create entry if not exist
140 m_imsiRntiMap[imsi] = rnti;
141 m_s1apSapMme->InitialUeMessage(imsi, rnti, imsi, m_cellId);
142}
143
144void
146{
147 NS_LOG_FUNCTION(this);
148 uint16_t enbUeS1Id = params.rnti;
149 uint64_t mmeUeS1Id = params.mmeUeS1Id;
150 uint64_t imsi = mmeUeS1Id;
151 // side effect: create entry if not exist
152 m_imsiRntiMap[imsi] = params.rnti;
153
154 uint16_t gci = params.cellId;
155 std::list<EpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList;
156 for (auto bit = params.bearersToBeSwitched.begin(); bit != params.bearersToBeSwitched.end();
157 ++bit)
158 {
159 EpsFlowId_t flowId;
160 flowId.m_rnti = params.rnti;
161 flowId.m_bid = bit->epsBearerId;
162 uint32_t teid = bit->teid;
163
164 EpsFlowId_t rbid(params.rnti, bit->epsBearerId);
165 // side effect: create entries if not exist
166 m_rbidTeidMap[params.rnti][bit->epsBearerId] = teid;
167 m_teidRbidMap[teid] = rbid;
168
170 erab.erabId = bit->epsBearerId;
172 erab.enbTeid = bit->teid;
173
174 erabToBeSwitchedInDownlinkList.push_back(erab);
175 }
176 m_s1apSapMme->PathSwitchRequest(enbUeS1Id, mmeUeS1Id, gci, erabToBeSwitchedInDownlinkList);
177}
178
179void
181{
182 NS_LOG_FUNCTION(this << rnti);
183 auto rntiIt = m_rbidTeidMap.find(rnti);
184 if (rntiIt != m_rbidTeidMap.end())
185 {
186 for (auto bidIt = rntiIt->second.begin(); bidIt != rntiIt->second.end(); ++bidIt)
187 {
188 uint32_t teid = bidIt->second;
189 m_teidRbidMap.erase(teid);
190 NS_LOG_INFO("TEID: " << teid << " erased");
191 }
192 m_rbidTeidMap.erase(rntiIt);
193 NS_LOG_INFO("RNTI: " << rntiIt->first << " erased");
194 }
195}
196
197void
199 uint64_t mmeUeS1Id,
200 uint16_t enbUeS1Id,
201 std::list<EpcS1apSapEnb::ErabToBeSetupItem> erabToBeSetupList)
202{
203 NS_LOG_FUNCTION(this);
204
205 uint64_t imsi = mmeUeS1Id;
206 auto imsiIt = m_imsiRntiMap.find(imsi);
207 NS_ASSERT_MSG(imsiIt != m_imsiRntiMap.end(), "unknown IMSI");
208 uint16_t rnti = imsiIt->second;
209
210 for (auto erabIt = erabToBeSetupList.begin(); erabIt != erabToBeSetupList.end(); ++erabIt)
211 {
212 // request the RRC to setup a radio bearer
214 params.rnti = rnti;
215 params.bearer = erabIt->erabLevelQosParameters;
216 params.bearerId = erabIt->erabId;
217 params.gtpTeid = erabIt->sgwTeid;
219
220 EpsFlowId_t rbid(rnti, erabIt->erabId);
221 // side effect: create entries if not exist
222 m_rbidTeidMap[rnti][erabIt->erabId] = params.gtpTeid;
223 m_teidRbidMap[params.gtpTeid] = rbid;
224 }
225
226 // Send Initial Context Setup Request to RRC
228 params.rnti = rnti;
230}
231
232void
234 uint64_t enbUeS1Id,
235 uint64_t mmeUeS1Id,
236 uint16_t gci,
237 std::list<EpcS1apSapEnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
238{
239 NS_LOG_FUNCTION(this);
240
241 uint64_t imsi = mmeUeS1Id;
242 auto imsiIt = m_imsiRntiMap.find(imsi);
243 NS_ASSERT_MSG(imsiIt != m_imsiRntiMap.end(), "unknown IMSI");
244 uint16_t rnti = imsiIt->second;
246 params.rnti = rnti;
248}
249
250void
252{
253 NS_LOG_FUNCTION(this);
254 if (m_lteSocket6)
255 {
256 NS_ASSERT(socket == m_lteSocket || socket == m_lteSocket6);
257 }
258 else
259 {
260 NS_ASSERT(socket == m_lteSocket);
261 }
262 Ptr<Packet> packet = socket->Recv();
263
264 EpsBearerTag tag;
265 bool found = packet->RemovePacketTag(tag);
266 NS_ASSERT(found);
267 uint16_t rnti = tag.GetRnti();
268 uint8_t bid = tag.GetBid();
269 NS_LOG_INFO("Received packet with RNTI: " << rnti << ", BID: " << +bid);
270 auto rntiIt = m_rbidTeidMap.find(rnti);
271 if (rntiIt == m_rbidTeidMap.end())
272 {
273 NS_LOG_WARN("UE context not found, discarding packet");
274 }
275 else
276 {
277 auto bidIt = rntiIt->second.find(bid);
278 NS_ASSERT(bidIt != rntiIt->second.end());
279 uint32_t teid = bidIt->second;
280 m_rxLteSocketPktTrace(packet->Copy());
281 SendToS1uSocket(packet, teid);
282 }
283}
284
285void
287{
288 NS_LOG_FUNCTION(this << socket);
289 NS_ASSERT(socket == m_s1uSocket);
290 Ptr<Packet> packet = socket->Recv();
291 GtpuHeader gtpu;
292 packet->RemoveHeader(gtpu);
293 uint32_t teid = gtpu.GetTeid();
294 NS_LOG_INFO("Received packet from S1-U interface with GTP TEID: " << teid);
295 auto it = m_teidRbidMap.find(teid);
296 if (it == m_teidRbidMap.end())
297 {
298 NS_LOG_WARN("UE context at cell id " << m_cellId << " not found, discarding packet");
299 }
300 else
301 {
302 m_rxS1uSocketPktTrace(packet->Copy());
303 SendToLteSocket(packet, it->second.m_rnti, it->second.m_bid);
304 }
305}
306
307void
308EpcEnbApplication::SendToLteSocket(Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
309{
310 NS_LOG_FUNCTION(this << packet << rnti << bid << packet->GetSize());
311 EpsBearerTag tag(rnti, bid);
312 packet->AddPacketTag(tag);
313 NS_LOG_INFO("Add EpsBearerTag with RNTI " << rnti << " and bearer ID " << +bid);
314 uint8_t ipType;
315
316 packet->CopyData(&ipType, 1);
317 ipType = (ipType >> 4) & 0x0f;
318
319 int sentBytes;
320 if (ipType == 0x04)
321 {
322 NS_LOG_INFO("Forward packet from eNB's S1-U to LTE stack via IPv4 socket.");
323 sentBytes = m_lteSocket->Send(packet);
324 }
325 else if (ipType == 0x06)
326 {
327 NS_LOG_INFO("Forward packet from eNB's S1-U to LTE stack via IPv6 socket.");
328 sentBytes = m_lteSocket6->Send(packet);
329 }
330 else
331 {
332 NS_ABORT_MSG("EpcEnbApplication::SendToLteSocket - Unknown IP type...");
333 }
334
335 NS_ASSERT(sentBytes > 0);
336}
337
338void
340{
341 NS_LOG_FUNCTION(this << packet << teid << packet->GetSize());
342 GtpuHeader gtpu;
343 gtpu.SetTeid(teid);
344 // From 3GPP TS 29.281 v10.0.0 Section 5.1
345 // Length of the payload + the non obligatory GTP-U header
346 gtpu.SetLength(packet->GetSize() + gtpu.GetSerializedSize() - 8);
347 packet->AddHeader(gtpu);
348 uint32_t flags = 0;
349 NS_LOG_INFO("Forward packet from eNB's LTE to S1-U stack with TEID: " << teid);
351}
352
353void
354EpcEnbApplication::DoReleaseIndication(uint64_t imsi, uint16_t rnti, uint8_t bearerId)
355{
356 NS_LOG_FUNCTION(this << bearerId);
357 std::list<EpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication;
359 erab.erabId = bearerId;
360 erabToBeReleaseIndication.push_back(erab);
361 // From 3GPP TS 23401-950 Section 5.4.4.2, enB sends EPS bearer Identity in Bearer Release
362 // Indication message to MME
363 m_s1apSapMme->ErabReleaseIndication(imsi, rnti, erabToBeReleaseIndication);
364}
365
366} // 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...
MME side of the S1-AP Service Access Point (SAP), provides the MME methods to be called when an S1-AP...
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.
A base class which provides memory management and object aggregation.
Definition object.h:78
Smart pointer class similar to boost::intrusive_ptr.
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: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_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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< 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:684
bool operator==(const EventId &a, const EventId &b)
Definition event-id.h:155
bool operator<(const EventId &a, const EventId &b)
Definition event-id.h:168
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.