8#include "nr-epc-gnb-application.h"
10#include "nr-epc-gtpu-header.h"
11#include "nr-eps-bearer-tag.h"
13#include "ns3/inet-socket-address.h"
16#include "ns3/mac48-address.h"
17#include "ns3/uinteger.h"
22NS_LOG_COMPONENT_DEFINE(
"NrEpcGnbApplication");
24NrEpcGnbApplication::EpsFlowId_t::EpsFlowId_t()
28NrEpcGnbApplication::EpsFlowId_t::EpsFlowId_t(
const uint16_t a,
const uint8_t b)
50 TypeId(
"ns3::NrEpcGnbApplication")
53 .AddTraceSource(
"RxFromGnb",
54 "Receive data packets from NR Gnb Net Device",
55 MakeTraceSourceAccessor(&NrEpcGnbApplication::m_rxNrSocketPktTrace),
56 "ns3::NrEpcGnbApplication::RxTracedCallback")
57 .AddTraceSource(
"RxFromS1u",
58 "Receive data packets from S1-U Net Device",
59 MakeTraceSourceAccessor(&NrEpcGnbApplication::m_rxS1uSocketPktTrace),
60 "ns3::NrEpcGnbApplication::RxTracedCallback");
65NrEpcGnbApplication::DoDispose()
67 NS_LOG_FUNCTION(
this);
69 m_nrSocket6 =
nullptr;
70 m_s1uSocket =
nullptr;
71 delete m_s1SapProvider;
76 Ptr<Socket> nrSocket6,
78 : m_nrSocket(nrSocket),
79 m_nrSocket6(nrSocket6),
82 m_s1apSapMme(nullptr),
85 NS_LOG_FUNCTION(
this << nrSocket << nrSocket6 << cellId);
95 Ipv4Address gnbAddress,
96 Ipv4Address sgwAddress)
98 NS_LOG_FUNCTION(
this << s1uSocket << gnbAddress << sgwAddress);
100 m_s1uSocket = s1uSocket;
102 m_gnbS1uAddress = gnbAddress;
103 m_sgwS1uAddress = sgwAddress;
108 NS_LOG_FUNCTION(
this);
120 return m_s1SapProvider;
136NrEpcGnbApplication::DoInitialUeMessage(uint64_t imsi, uint16_t rnti)
138 NS_LOG_FUNCTION(
this);
140 m_imsiRntiMap[imsi] = rnti;
145NrEpcGnbApplication::DoPathSwitchRequest(NrEpcGnbS1SapProvider::PathSwitchRequestParameters params)
147 NS_LOG_FUNCTION(
this);
148 uint16_t gnbUeS1Id = params.rnti;
149 uint64_t mmeUeS1Id = params.mmeUeS1Id;
150 uint64_t imsi = mmeUeS1Id;
152 m_imsiRntiMap[imsi] = params.rnti;
154 uint16_t gci = params.cellId;
155 std::list<NrEpcS1apSapMme::ErabSwitchedInDownlinkItem> erabToBeSwitchedInDownlinkList;
156 for (
auto bit = params.bearersToBeSwitched.begin(); bit != params.bearersToBeSwitched.end();
160 flowId.m_rnti = params.rnti;
161 flowId.m_bid = bit->epsBearerId;
162 uint32_t teid = bit->teid;
164 EpsFlowId_t rbid(params.rnti, bit->epsBearerId);
166 m_rbidTeidMap[params.rnti][bit->epsBearerId] = teid;
167 m_teidRbidMap[teid] = rbid;
169 NrEpcS1apSapMme::ErabSwitchedInDownlinkItem erab;
170 erab.erabId = bit->epsBearerId;
171 erab.gnbTransportLayerAddress = m_gnbS1uAddress;
172 erab.gnbTeid = bit->teid;
174 erabToBeSwitchedInDownlinkList.push_back(erab);
176 m_s1apSapMme->
PathSwitchRequest(gnbUeS1Id, mmeUeS1Id, gci, erabToBeSwitchedInDownlinkList);
180NrEpcGnbApplication::DoUeContextRelease(uint16_t rnti)
182 NS_LOG_FUNCTION(
this << rnti);
183 auto rntiIt = m_rbidTeidMap.find(rnti);
184 if (rntiIt != m_rbidTeidMap.end())
186 for (
auto bidIt = rntiIt->second.begin(); bidIt != rntiIt->second.end(); ++bidIt)
188 uint32_t teid = bidIt->second;
189 m_teidRbidMap.erase(teid);
190 NS_LOG_INFO(
"TEID: " << teid <<
" erased");
192 m_rbidTeidMap.erase(rntiIt);
193 NS_LOG_INFO(
"RNTI: " << rntiIt->first <<
" erased");
198NrEpcGnbApplication::DoInitialContextSetupRequest(
201 std::list<NrEpcS1apSapGnb::ErabToBeSetupItem> erabToBeSetupList)
203 NS_LOG_FUNCTION(
this);
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;
210 for (
auto erabIt = erabToBeSetupList.begin(); erabIt != erabToBeSetupList.end(); ++erabIt)
213 NrEpcGnbS1SapUser::DataRadioBearerSetupRequestParameters params;
215 params.bearer = erabIt->erabLevelQosParameters;
216 params.bearerId = erabIt->erabId;
217 params.gtpTeid = erabIt->sgwTeid;
220 EpsFlowId_t rbid(rnti, erabIt->erabId);
222 m_rbidTeidMap[rnti][erabIt->erabId] = params.gtpTeid;
223 m_teidRbidMap[params.gtpTeid] = rbid;
227 NrEpcGnbS1SapUser::InitialContextSetupRequestParameters params;
233NrEpcGnbApplication::DoPathSwitchRequestAcknowledge(
237 std::list<NrEpcS1apSapGnb::ErabSwitchedInUplinkItem> erabToBeSwitchedInUplinkList)
239 NS_LOG_FUNCTION(
this);
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;
245 NrEpcGnbS1SapUser::PathSwitchRequestAcknowledgeParameters params;
253 NS_LOG_FUNCTION(
this);
256 NS_ASSERT(socket == m_nrSocket || socket == m_nrSocket6);
260 NS_ASSERT(socket == m_nrSocket);
262 Ptr<Packet> packet = socket->Recv();
265 bool found = packet->RemovePacketTag(tag);
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())
273 NS_LOG_WARN(
"UE context not found, discarding packet");
277 auto bidIt = rntiIt->second.find(bid);
278 NS_ASSERT(bidIt != rntiIt->second.end());
279 uint32_t teid = bidIt->second;
280 m_rxNrSocketPktTrace(packet->Copy());
281 SendToS1uSocket(packet, teid);
288 NS_LOG_FUNCTION(
this << socket);
289 NS_ASSERT(socket == m_s1uSocket);
290 Ptr<Packet> packet = socket->Recv();
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())
298 NS_LOG_WARN(
"UE context at cell id " << m_cellId <<
" not found, discarding packet");
302 m_rxS1uSocketPktTrace(packet->Copy());
303 SendToNrSocket(packet, it->second.m_rnti, it->second.m_bid);
308NrEpcGnbApplication::SendToNrSocket(Ptr<Packet> packet, uint16_t rnti, uint8_t bid)
310 NS_LOG_FUNCTION(
this << packet << rnti << bid << packet->GetSize());
312 packet->AddPacketTag(tag);
313 NS_LOG_INFO(
"Add NrEpsBearerTag with RNTI " << rnti <<
" and bearer ID " << +bid);
316 packet->CopyData(&ipType, 1);
317 ipType = (ipType >> 4) & 0x0f;
322 NS_LOG_INFO(
"Forward packet from gNB's S1-U to NR stack via IPv4 socket.");
323 sentBytes = m_nrSocket->Send(packet);
325 else if (ipType == 0x06)
327 NS_LOG_INFO(
"Forward packet from gNB's S1-U to NR stack via IPv6 socket.");
328 sentBytes = m_nrSocket6->Send(packet);
332 NS_ABORT_MSG(
"NrEpcGnbApplication::SendToNrSocket - Unknown IP type...");
335 NS_ASSERT(sentBytes > 0);
339NrEpcGnbApplication::SendToS1uSocket(Ptr<Packet> packet, uint32_t teid)
341 NS_LOG_FUNCTION(
this << packet << teid << packet->GetSize());
346 gtpu.SetLength(packet->GetSize() + gtpu.GetSerializedSize() - 8);
347 packet->AddHeader(gtpu);
349 NS_LOG_INFO(
"Forward packet from gNB's NR to S1-U stack with TEID: " << teid);
350 m_s1uSocket->SendTo(packet, flags, InetSocketAddress(m_sgwS1uAddress, m_gtpuUdpPort));
354NrEpcGnbApplication::DoReleaseIndication(uint64_t imsi, uint16_t rnti, uint8_t bearerId)
356 NS_LOG_FUNCTION(
this << bearerId);
357 std::list<NrEpcS1apSapMme::ErabToBeReleasedIndication> erabToBeReleaseIndication;
358 NrEpcS1apSapMme::ErabToBeReleasedIndication erab;
359 erab.erabId = bearerId;
360 erabToBeReleaseIndication.push_back(erab);
NrEpcS1apSapGnb * GetS1apSapGnb()
void AddS1Interface(Ptr< Socket > s1uSocket, Ipv4Address gnbS1uAddress, Ipv4Address sgwS1uAddress)
friend class NrMemberEpcGnbS1SapProvider< NrEpcGnbApplication >
allow NrMemberEpcGnbS1SapProvider<NrEpcGnbApplication> class friend access
void SetS1apSapMme(NrEpcS1apSapMme *s)
friend class NrMemberEpcS1apSapGnb< NrEpcGnbApplication >
allow NrMemberEpcS1apSapGnb<NrEpcGnbApplication> class friend access
void RecvFromS1uSocket(Ptr< Socket > socket)
static TypeId GetTypeId()
Get the type ID.
~NrEpcGnbApplication() override
void RecvFromNrSocket(Ptr< Socket > socket)
void SetS1SapUser(NrEpcGnbS1SapUser *s)
NrEpcGnbApplication(Ptr< Socket > nrSocket, Ptr< Socket > nrSocket6, uint16_t cellId)
NrEpcGnbS1SapProvider * GetS1SapProvider()
virtual void InitialContextSetupRequest(InitialContextSetupRequestParameters params)=0
virtual void PathSwitchRequestAcknowledge(PathSwitchRequestAcknowledgeParameters params)=0
virtual void DataRadioBearerSetupRequest(DataRadioBearerSetupRequestParameters params)=0
virtual void ErabReleaseIndication(uint64_t mmeUeS1Id, uint16_t gnbUeS1Id, std::list< ErabToBeReleasedIndication > erabToBeReleaseIndication)=0
As per 3GPP TS 36.413 version 9.8.0 section 8.2.3.2.2, the gNB indicates bearer release by sending an...
virtual void PathSwitchRequest(uint64_t gnbUeS1Id, uint64_t mmeUeS1Id, uint16_t gci, std::list< ErabSwitchedInDownlinkItem > erabToBeSwitchedInDownlinkList)=0
virtual void InitialUeMessage(uint64_t mmeUeS1Id, uint16_t gnbUeS1Id, uint64_t stmsi, uint16_t ecgi)=0
uint8_t m_bid
Bid, the EPS Bearer Identifier.