5G-LENA nr-v3.3-161-gad18933f
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-epc-pgw-application.cc
1// Copyright (c) 2018 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4//
5// Author: Manuel Requena <manuel.requena@cttc.es>
6// (based on epc-sgw-pgw-application.cc)
7
8#include "nr-epc-pgw-application.h"
9
10#include "nr-epc-gtpu-header.h"
11
12#include "ns3/abort.h"
13#include "ns3/inet-socket-address.h"
14#include "ns3/ipv4-l3-protocol.h"
15#include "ns3/ipv4.h"
16#include "ns3/ipv6-header.h"
17#include "ns3/ipv6-l3-protocol.h"
18#include "ns3/ipv6.h"
19#include "ns3/log.h"
20#include "ns3/mac48-address.h"
21
22namespace ns3
23{
24
25NS_LOG_COMPONENT_DEFINE("NrEpcPgwApplication");
26
28// NrUeInfo
30
31NrEpcPgwApplication::NrUeInfo::NrUeInfo()
32{
33 NS_LOG_FUNCTION(this);
34}
35
36void
37NrEpcPgwApplication::NrUeInfo::AddBearer(uint8_t bearerId, uint32_t teid, Ptr<NrEpcTft> tft)
38{
39 NS_LOG_FUNCTION(this << (uint16_t)bearerId << teid << tft);
40 m_teidByBearerIdMap[bearerId] = teid;
41 return m_tftClassifier.Add(tft, teid);
42}
43
44void
45NrEpcPgwApplication::NrUeInfo::RemoveBearer(uint8_t bearerId)
46{
47 NS_LOG_FUNCTION(this << (uint16_t)bearerId);
48 auto it = m_teidByBearerIdMap.find(bearerId);
49 m_tftClassifier.Delete(it->second); // delete tft
50 m_teidByBearerIdMap.erase(bearerId);
51}
52
53uint32_t
54NrEpcPgwApplication::NrUeInfo::Classify(Ptr<Packet> p, uint16_t protocolNumber)
55{
56 NS_LOG_FUNCTION(this << p);
57 // we hardcode DOWNLINK direction since the PGW is expected to
58 // classify only downlink packets (uplink packets will go to the
59 // internet without any classification).
60 return m_tftClassifier.Classify(p, NrEpcTft::DOWNLINK, protocolNumber);
61}
62
63Ipv4Address
64NrEpcPgwApplication::NrUeInfo::GetSgwAddr()
65{
66 return m_sgwAddr;
67}
68
69void
70NrEpcPgwApplication::NrUeInfo::SetSgwAddr(Ipv4Address sgwAddr)
71{
72 m_sgwAddr = sgwAddr;
73}
74
75Ipv4Address
76NrEpcPgwApplication::NrUeInfo::GetUeAddr()
77{
78 return m_ueAddr;
79}
80
81void
82NrEpcPgwApplication::NrUeInfo::SetUeAddr(Ipv4Address ueAddr)
83{
84 m_ueAddr = ueAddr;
85}
86
87Ipv6Address
88NrEpcPgwApplication::NrUeInfo::GetUeAddr6()
89{
90 return m_ueAddr6;
91}
92
93void
94NrEpcPgwApplication::NrUeInfo::SetUeAddr6(Ipv6Address ueAddr)
95{
96 m_ueAddr6 = ueAddr;
97}
98
100// NrEpcPgwApplication
102
103TypeId
105{
106 static TypeId tid =
107 TypeId("ns3::NrEpcPgwApplication")
108 .SetParent<Object>()
109 .SetGroupName("Nr")
110 .AddTraceSource("RxFromTun",
111 "Receive data packets from internet in Tunnel NetDevice",
112 MakeTraceSourceAccessor(&NrEpcPgwApplication::m_rxTunPktTrace),
113 "ns3::NrEpcPgwApplication::RxTracedCallback")
114 .AddTraceSource("RxFromS1u",
115 "Receive data packets from S5 Socket",
116 MakeTraceSourceAccessor(&NrEpcPgwApplication::m_rxS5PktTrace),
117 "ns3::NrEpcPgwApplication::RxTracedCallback");
118 return tid;
119}
120
121void
122NrEpcPgwApplication::DoDispose()
123{
124 NS_LOG_FUNCTION(this);
125 m_s5uSocket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
126 m_s5uSocket = nullptr;
127 m_s5cSocket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket>>());
128 m_s5cSocket = nullptr;
129}
130
131NrEpcPgwApplication::NrEpcPgwApplication(const Ptr<VirtualNetDevice> tunDevice,
132 Ipv4Address s5Addr,
133 const Ptr<Socket> s5uSocket,
134 const Ptr<Socket> s5cSocket)
135 : m_pgwS5Addr(s5Addr),
136 m_s5uSocket(s5uSocket),
137 m_s5cSocket(s5cSocket),
138 m_tunDevice(tunDevice),
139 m_gtpuUdpPort(2152), // fixed by the standard
140 m_gtpcUdpPort(2123) // fixed by the standard
141{
142 NS_LOG_FUNCTION(this << tunDevice << s5Addr << s5uSocket << s5cSocket);
143 m_s5uSocket->SetRecvCallback(MakeCallback(&NrEpcPgwApplication::RecvFromS5uSocket, this));
144 m_s5cSocket->SetRecvCallback(MakeCallback(&NrEpcPgwApplication::RecvFromS5cSocket, this));
145}
146
148{
149 NS_LOG_FUNCTION(this);
150}
151
152bool
154 const Address& source,
155 const Address& dest,
156 uint16_t protocolNumber)
157{
158 NS_LOG_FUNCTION(this << source << dest << protocolNumber << packet << packet->GetSize());
159 m_rxTunPktTrace(packet->Copy());
160
161 // get IP address of UE
162 if (protocolNumber == Ipv4L3Protocol::PROT_NUMBER)
163 {
164 Ipv4Header ipv4Header;
165 packet->PeekHeader(ipv4Header);
166 Ipv4Address ueAddr = ipv4Header.GetDestination();
167 NS_LOG_LOGIC("packet addressed to UE " << ueAddr);
168
169 // find corresponding NrUeInfo address
170 auto it = m_ueInfoByAddrMap.find(ueAddr);
171 if (it == m_ueInfoByAddrMap.end())
172 {
173 NS_LOG_WARN("unknown UE address " << ueAddr);
174 }
175 else
176 {
177 Ipv4Address sgwAddr = it->second->GetSgwAddr();
178 uint32_t teid = it->second->Classify(packet, protocolNumber);
179 if (teid == 0)
180 {
181 NS_LOG_WARN("no matching bearer for this packet");
182 }
183 else
184 {
185 SendToS5uSocket(packet, sgwAddr, teid);
186 }
187 }
188 }
189 else if (protocolNumber == Ipv6L3Protocol::PROT_NUMBER)
190 {
191 Ipv6Header ipv6Header;
192 packet->PeekHeader(ipv6Header);
193 Ipv6Address ueAddr = ipv6Header.GetDestination();
194 NS_LOG_LOGIC("packet addressed to UE " << ueAddr);
195
196 // find corresponding NrUeInfo address
197 auto it = m_ueInfoByAddrMap6.find(ueAddr);
198 if (it == m_ueInfoByAddrMap6.end())
199 {
200 NS_LOG_WARN("unknown UE address " << ueAddr);
201 }
202 else
203 {
204 Ipv4Address sgwAddr = it->second->GetSgwAddr();
205 uint32_t teid = it->second->Classify(packet, protocolNumber);
206 if (teid == 0)
207 {
208 NS_LOG_WARN("no matching bearer for this packet");
209 }
210 else
211 {
212 SendToS5uSocket(packet, sgwAddr, teid);
213 }
214 }
215 }
216 else
217 {
218 NS_ABORT_MSG("Unknown IP type");
219 }
220
221 // there is no reason why we should notify the TUN
222 // VirtualNetDevice that he failed to send the packet: if we receive
223 // any bogus packet, it will just be silently discarded.
224 const bool succeeded = true;
225 return succeeded;
226}
227
228void
230{
231 NS_LOG_FUNCTION(this << socket);
232 NS_ASSERT(socket == m_s5uSocket);
233 Ptr<Packet> packet = socket->Recv();
234 m_rxS5PktTrace(packet->Copy());
235
236 NrGtpuHeader gtpu;
237 packet->RemoveHeader(gtpu);
238 uint32_t teid = gtpu.GetTeid();
239
240 SendToTunDevice(packet, teid);
241}
242
243void
245{
246 NS_LOG_FUNCTION(this << socket);
247 NS_ASSERT(socket == m_s5cSocket);
248 Ptr<Packet> packet = socket->Recv();
249 NrGtpcHeader header;
250 packet->PeekHeader(header);
251 uint16_t msgType = header.GetMessageType();
252
253 switch (msgType)
254 {
255 case NrGtpcHeader::CreateSessionRequest:
256 DoRecvCreateSessionRequest(packet);
257 break;
258
259 case NrGtpcHeader::ModifyBearerRequest:
260 DoRecvModifyBearerRequest(packet);
261 break;
262
263 case NrGtpcHeader::DeleteBearerCommand:
264 DoRecvDeleteBearerCommand(packet);
265 break;
266
267 case NrGtpcHeader::DeleteBearerResponse:
268 DoRecvDeleteBearerResponse(packet);
269 break;
270
271 default:
272 NS_FATAL_ERROR("GTP-C message not supported");
273 break;
274 }
275}
276
277void
278NrEpcPgwApplication::DoRecvCreateSessionRequest(Ptr<Packet> packet)
279{
280 NS_LOG_FUNCTION(this);
281
283 packet->RemoveHeader(msg);
284 uint64_t imsi = msg.GetImsi();
285 uint16_t cellId = msg.GetUliEcgi();
286 NS_LOG_DEBUG("cellId " << cellId << " IMSI " << imsi);
287
288 auto ueit = m_ueInfoByImsiMap.find(imsi);
289 NS_ASSERT_MSG(ueit != m_ueInfoByImsiMap.end(), "unknown IMSI " << imsi);
290 ueit->second->SetSgwAddr(m_sgwS5Addr);
291
292 NrGtpcHeader::Fteid_t sgwS5cFteid = msg.GetSenderCpFteid();
293 NS_ASSERT_MSG(sgwS5cFteid.interfaceType == NrGtpcHeader::S5_SGW_GTPC, "Wrong interface type");
294
296 msgOut.SetTeid(sgwS5cFteid.teid);
297 msgOut.SetCause(NrGtpcCreateSessionResponseMessage::REQUEST_ACCEPTED);
298
299 NrGtpcHeader::Fteid_t pgwS5cFteid;
300 pgwS5cFteid.interfaceType = NrGtpcHeader::S5_PGW_GTPC;
301 pgwS5cFteid.teid = sgwS5cFteid.teid;
302 pgwS5cFteid.addr = m_pgwS5Addr;
303 msgOut.SetSenderCpFteid(pgwS5cFteid);
304
305 std::list<NrGtpcCreateSessionRequestMessage::BearerContextToBeCreated> bearerContexts =
307 NS_LOG_DEBUG("BearerContextsToBeCreated size = " << bearerContexts.size());
308
309 std::list<NrGtpcCreateSessionResponseMessage::BearerContextCreated> bearerContextsCreated;
310 for (auto& bearerContext : bearerContexts)
311 {
312 uint32_t teid = bearerContext.sgwS5uFteid.teid;
313 NS_LOG_DEBUG("bearerId " << (uint16_t)bearerContext.epsBearerId << " SGW "
314 << bearerContext.sgwS5uFteid.addr << " TEID " << teid);
315
316 ueit->second->AddBearer(bearerContext.epsBearerId, teid, bearerContext.tft);
317
319 bearerContextOut.fteid.interfaceType = NrGtpcHeader::S5_PGW_GTPU;
320 bearerContextOut.fteid.teid = teid;
321 bearerContextOut.fteid.addr = m_pgwS5Addr;
322 bearerContextOut.epsBearerId = bearerContext.epsBearerId;
323 bearerContextOut.bearerLevelQos = bearerContext.bearerLevelQos;
324 bearerContextOut.tft = bearerContext.tft;
325 bearerContextsCreated.push_back(bearerContextOut);
326 }
327
328 NS_LOG_DEBUG("BearerContextsCreated size = " << bearerContextsCreated.size());
329 msgOut.SetBearerContextsCreated(bearerContextsCreated);
330 msgOut.SetTeid(sgwS5cFteid.teid);
331 msgOut.ComputeMessageLength();
332
333 Ptr<Packet> packetOut = Create<Packet>();
334 packetOut->AddHeader(msgOut);
335 NS_LOG_DEBUG("Send CreateSessionResponse to SGW " << sgwS5cFteid.addr);
336 m_s5cSocket->SendTo(packetOut, 0, InetSocketAddress(sgwS5cFteid.addr, m_gtpcUdpPort));
337}
338
339void
340NrEpcPgwApplication::DoRecvModifyBearerRequest(Ptr<Packet> packet)
341{
342 NS_LOG_FUNCTION(this);
343
344 NrGtpcModifyBearerRequestMessage msg;
345 packet->RemoveHeader(msg);
346 uint64_t imsi = msg.GetImsi();
347 uint16_t cellId = msg.GetUliEcgi();
348 NS_LOG_DEBUG("cellId " << cellId << " IMSI " << imsi);
349
350 auto ueit = m_ueInfoByImsiMap.find(imsi);
351 NS_ASSERT_MSG(ueit != m_ueInfoByImsiMap.end(), "unknown IMSI " << imsi);
352 ueit->second->SetSgwAddr(m_sgwS5Addr);
353
354 std::list<NrGtpcModifyBearerRequestMessage::BearerContextToBeModified> bearerContexts =
355 msg.GetBearerContextsToBeModified();
356 NS_LOG_DEBUG("BearerContextsToBeModified size = " << bearerContexts.size());
357
358 for (auto& bearerContext : bearerContexts)
359 {
360 Ipv4Address sgwAddr = bearerContext.fteid.addr;
361 uint32_t teid = bearerContext.fteid.teid;
362 NS_LOG_DEBUG("bearerId " << (uint16_t)bearerContext.epsBearerId << " SGW " << sgwAddr
363 << " TEID " << teid);
364 }
365
366 NrGtpcModifyBearerResponseMessage msgOut;
367 msgOut.SetCause(NrGtpcIes::REQUEST_ACCEPTED);
368 msgOut.SetTeid(imsi);
369 msgOut.ComputeMessageLength();
370
371 Ptr<Packet> packetOut = Create<Packet>();
372 packetOut->AddHeader(msgOut);
373 NS_LOG_DEBUG("Send ModifyBearerResponse to SGW " << m_sgwS5Addr);
374 m_s5cSocket->SendTo(packetOut, 0, InetSocketAddress(m_sgwS5Addr, m_gtpcUdpPort));
375}
376
377void
378NrEpcPgwApplication::DoRecvDeleteBearerCommand(Ptr<Packet> packet)
379{
380 NS_LOG_FUNCTION(this);
381
382 NrGtpcDeleteBearerCommandMessage msg;
383 packet->RemoveHeader(msg);
384
385 std::list<uint8_t> epsBearerIds;
386 for (auto& bearerContext : msg.GetBearerContexts())
387 {
388 NS_LOG_DEBUG("ebid " << (uint16_t)bearerContext.m_epsBearerId);
389 epsBearerIds.push_back(bearerContext.m_epsBearerId);
390 }
391
392 NrGtpcDeleteBearerRequestMessage msgOut;
393 msgOut.SetEpsBearerIds(epsBearerIds);
394 msgOut.SetTeid(msg.GetTeid());
395 msgOut.ComputeMessageLength();
396
397 Ptr<Packet> packetOut = Create<Packet>();
398 packetOut->AddHeader(msgOut);
399 NS_LOG_DEBUG("Send DeleteBearerRequest to SGW " << m_sgwS5Addr);
400 m_s5cSocket->SendTo(packetOut, 0, InetSocketAddress(m_sgwS5Addr, m_gtpcUdpPort));
401}
402
403void
404NrEpcPgwApplication::DoRecvDeleteBearerResponse(Ptr<Packet> packet)
405{
406 NS_LOG_FUNCTION(this);
407
408 NrGtpcDeleteBearerResponseMessage msg;
409 packet->RemoveHeader(msg);
410
411 uint64_t imsi = msg.GetTeid();
412 auto ueit = m_ueInfoByImsiMap.find(imsi);
413 NS_ASSERT_MSG(ueit != m_ueInfoByImsiMap.end(), "unknown IMSI " << imsi);
414
415 for (auto& epsBearerId : msg.GetEpsBearerIds())
416 {
417 // Remove de-activated bearer contexts from PGW side
418 NS_LOG_INFO("PGW removing bearer " << (uint16_t)epsBearerId << " of IMSI " << imsi);
419 ueit->second->RemoveBearer(epsBearerId);
420 }
421}
422
423void
424NrEpcPgwApplication::SendToTunDevice(Ptr<Packet> packet, uint32_t teid)
425{
426 NS_LOG_FUNCTION(this << packet << teid);
427 NS_LOG_LOGIC("packet size: " << packet->GetSize() << " bytes");
428
429 uint8_t ipType;
430 packet->CopyData(&ipType, 1);
431 ipType = (ipType >> 4) & 0x0f;
432
433 uint16_t protocol = 0;
434 if (ipType == 0x04)
435 {
436 protocol = 0x0800;
437 }
438 else if (ipType == 0x06)
439 {
440 protocol = 0x86DD;
441 }
442 else
443 {
444 NS_ABORT_MSG("Unknown IP type");
445 }
446
447 m_tunDevice->Receive(packet,
448 protocol,
449 m_tunDevice->GetAddress(),
450 m_tunDevice->GetAddress(),
451 NetDevice::PACKET_HOST);
452}
453
454void
455NrEpcPgwApplication::SendToS5uSocket(Ptr<Packet> packet, Ipv4Address sgwAddr, uint32_t teid)
456{
457 NS_LOG_FUNCTION(this << packet << sgwAddr << teid);
458
459 NrGtpuHeader gtpu;
460 gtpu.SetTeid(teid);
461 // From 3GPP TS 29.281 v10.0.0 Section 5.1
462 // Length of the payload + the non obligatory GTP-U header
463 gtpu.SetLength(packet->GetSize() + gtpu.GetSerializedSize() - 8);
464 packet->AddHeader(gtpu);
465 uint32_t flags = 0;
466 m_s5uSocket->SendTo(packet, flags, InetSocketAddress(sgwAddr, m_gtpuUdpPort));
467}
468
469void
470NrEpcPgwApplication::AddSgw(Ipv4Address sgwS5Addr)
471{
472 NS_LOG_FUNCTION(this << sgwS5Addr);
473 m_sgwS5Addr = sgwS5Addr;
474}
475
476void
478{
479 NS_LOG_FUNCTION(this << imsi);
480 Ptr<NrUeInfo> ueInfo = Create<NrUeInfo>();
481 m_ueInfoByImsiMap[imsi] = ueInfo;
482}
483
484void
485NrEpcPgwApplication::SetUeAddress(uint64_t imsi, Ipv4Address ueAddr)
486{
487 NS_LOG_FUNCTION(this << imsi << ueAddr);
488 auto ueit = m_ueInfoByImsiMap.find(imsi);
489 NS_ASSERT_MSG(ueit != m_ueInfoByImsiMap.end(), "unknown IMSI" << imsi);
490 ueit->second->SetUeAddr(ueAddr);
491 m_ueInfoByAddrMap[ueAddr] = ueit->second;
492}
493
494void
495NrEpcPgwApplication::SetUeAddress6(uint64_t imsi, Ipv6Address ueAddr)
496{
497 NS_LOG_FUNCTION(this << imsi << ueAddr);
498 auto ueit = m_ueInfoByImsiMap.find(imsi);
499 NS_ASSERT_MSG(ueit != m_ueInfoByImsiMap.end(), "unknown IMSI " << imsi);
500 m_ueInfoByAddrMap6[ueAddr] = ueit->second;
501 ueit->second->SetUeAddr6(ueAddr);
502}
503
504} // namespace ns3
static TypeId GetTypeId()
Get the type ID.
void RecvFromS5cSocket(Ptr< Socket > socket)
bool RecvFromTunDevice(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
void SetUeAddress(uint64_t imsi, Ipv4Address ueAddr)
void SendToTunDevice(Ptr< Packet > packet, uint32_t teid)
void AddSgw(Ipv4Address sgwS5Addr)
NrEpcPgwApplication(const Ptr< VirtualNetDevice > tunDevice, Ipv4Address s5Addr, const Ptr< Socket > s5uSocket, const Ptr< Socket > s5cSocket)
void SetUeAddress6(uint64_t imsi, Ipv6Address ueAddr)
void RecvFromS5uSocket(Ptr< Socket > socket)
void SendToS5uSocket(Ptr< Packet > packet, Ipv4Address sgwS5uAddress, uint32_t teid)
NrGtpcHeader::Fteid_t GetSenderCpFteid() const
std::list< BearerContextToBeCreated > GetBearerContextsToBeCreated() const
void SetBearerContextsCreated(std::list< BearerContextCreated > bearerContexts)
void SetSenderCpFteid(NrGtpcHeader::Fteid_t fteid)
Header of the GTPv2-C protocol.
uint8_t GetMessageType() const
void SetTeid(uint32_t teid)
void SetLength(uint16_t length)
void SetTeid(uint32_t teid)
uint32_t GetTeid() const
Ipv4Address addr
IPv4 address.
InterfaceType_t interfaceType
Interface type.