5G-LENA nr-v4.0
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-no-backhaul-epc-helper.cc
1// Copyright (c) 2019 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 the original point-to-point-epc-helper.cc)
7
8#include "nr-no-backhaul-epc-helper.h"
9
10#include "ns3/boolean.h"
11#include "ns3/icmpv6-l4-protocol.h"
12#include "ns3/internet-stack-helper.h"
13#include "ns3/ipv4-static-routing-helper.h"
14#include "ns3/ipv6-static-routing-helper.h"
15#include "ns3/log.h"
16#include "ns3/nr-epc-gnb-application.h"
17#include "ns3/nr-epc-mme-application.h"
18#include "ns3/nr-epc-pgw-application.h"
19#include "ns3/nr-epc-sgw-application.h"
20#include "ns3/nr-epc-ue-nas.h"
21#include "ns3/nr-epc-x2.h"
22#include "ns3/nr-gnb-net-device.h"
23#include "ns3/nr-gnb-rrc.h"
24#include "ns3/nr-ue-net-device.h"
25#include "ns3/packet-socket-address.h"
26#include "ns3/point-to-point-helper.h"
27
28namespace ns3
29{
30
31NS_LOG_COMPONENT_DEFINE("NrNoBackhaulEpcHelper");
32
33NS_OBJECT_ENSURE_REGISTERED(NrNoBackhaulEpcHelper);
34
36 : m_gtpuUdpPort(2152), // fixed by the standard
37 m_s11LinkDataRate(DataRate("10Gb/s")),
38 m_s11LinkDelay(Seconds(0)),
39 m_s11LinkMtu(3000),
40 m_gtpcUdpPort(2123), // fixed by the standard
41 m_s5LinkDataRate(DataRate("10Gb/s")),
42 m_s5LinkDelay(Seconds(0)),
43 m_s5LinkMtu(3000)
44{
45 NS_LOG_FUNCTION(this);
46 // To access the attribute value within the constructor
47 ObjectBase::ConstructSelf(AttributeConstructionList());
48
49 int retval;
50
51 // since we use point-to-point links for links between the core network nodes,
52 // we use a /30 subnet which can hold exactly two addresses
53 // (remember that net broadcast and null address are not valid)
54 m_x2Ipv4AddressHelper.SetBase("12.0.0.0", "255.255.255.252");
55 m_s11Ipv4AddressHelper.SetBase("13.0.0.0", "255.255.255.252");
56 m_s5Ipv4AddressHelper.SetBase("14.0.0.0", "255.255.255.252");
57
58 // we use a /8 net for all UEs
59 m_uePgwAddressHelper.SetBase("7.0.0.0", "255.0.0.0");
60
61 // we use a /64 IPv6 net all UEs
62 m_uePgwAddressHelper6.SetBase("7777:f00d::", Ipv6Prefix(64));
63
64 // Create PGW, SGW and MME nodes
65 m_pgw = CreateObject<Node>();
66 m_sgw = CreateObject<Node>();
67 m_mme = CreateObject<Node>();
68 InternetStackHelper internet;
69 internet.Install(m_pgw);
70 internet.Install(m_sgw);
71 internet.Install(m_mme);
72
73 // The Tun device resides in different 64 bit subnet.
74 // We must create an unique route to tun device for all the packets destined
75 // to all 64 bit IPv6 prefixes of UEs, based by the unique 48 bit network prefix of this EPC
76 // network
77 Ipv6StaticRoutingHelper ipv6RoutingHelper;
78 Ptr<Ipv6StaticRouting> pgwStaticRouting =
79 ipv6RoutingHelper.GetStaticRouting(m_pgw->GetObject<Ipv6>());
80 pgwStaticRouting->AddNetworkRouteTo("7777:f00d::", Ipv6Prefix(64), Ipv6Address("::"), 1, 0);
81
82 // create TUN device implementing tunneling of user data over GTP-U/UDP/IP in the PGW
83 m_tunDevice = CreateObject<VirtualNetDevice>();
84
85 // allow jumbo packets
86 m_tunDevice->SetAttribute("Mtu", UintegerValue(30000));
87
88 // yes we need this
89 m_tunDevice->SetAddress(Mac48Address::Allocate());
90
91 m_pgw->AddDevice(m_tunDevice);
92 NetDeviceContainer tunDeviceContainer;
93 tunDeviceContainer.Add(m_tunDevice);
94 // the TUN device is on the same subnet as the UEs, so when a packet
95 // addressed to an UE arrives at the internet to the WAN interface of
96 // the PGW it will be forwarded to the TUN device.
97 Ipv4InterfaceContainer tunDeviceIpv4IfContainer = AssignUeIpv4Address(tunDeviceContainer);
98
99 // the TUN device for IPv6 address is on the different subnet as the
100 // UEs, it will forward the UE packets as we have inserted the route
101 // for all UEs at the time of assigning UE addresses
102 Ipv6InterfaceContainer tunDeviceIpv6IfContainer = AssignUeIpv6Address(tunDeviceContainer);
103
104 // Set Forwarding of the IPv6 interface
105 tunDeviceIpv6IfContainer.SetForwarding(0, true);
106 tunDeviceIpv6IfContainer.SetDefaultRouteInAllNodes(0);
107
108 // Create S5 link between PGW and SGW
109 PointToPointHelper p2ph;
110 p2ph.SetDeviceAttribute("DataRate", DataRateValue(m_s5LinkDataRate));
111 p2ph.SetDeviceAttribute("Mtu", UintegerValue(m_s5LinkMtu));
112 p2ph.SetChannelAttribute("Delay", TimeValue(m_s5LinkDelay));
113 NetDeviceContainer pgwSgwDevices = p2ph.Install(m_pgw, m_sgw);
114 NS_LOG_LOGIC("IPv4 ifaces of the PGW after installing p2p dev: "
115 << m_pgw->GetObject<Ipv4>()->GetNInterfaces());
116 NS_LOG_LOGIC("IPv4 ifaces of the SGW after installing p2p dev: "
117 << m_sgw->GetObject<Ipv4>()->GetNInterfaces());
118 Ptr<NetDevice> pgwDev = pgwSgwDevices.Get(0);
119 Ptr<NetDevice> sgwDev = pgwSgwDevices.Get(1);
120 m_s5Ipv4AddressHelper.NewNetwork();
121 Ipv4InterfaceContainer pgwSgwIpIfaces = m_s5Ipv4AddressHelper.Assign(pgwSgwDevices);
122 NS_LOG_LOGIC("IPv4 ifaces of the PGW after assigning Ipv4 addr to S5 dev: "
123 << m_pgw->GetObject<Ipv4>()->GetNInterfaces());
124 NS_LOG_LOGIC("IPv4 ifaces of the SGW after assigning Ipv4 addr to S5 dev: "
125 << m_sgw->GetObject<Ipv4>()->GetNInterfaces());
126
127 Ipv4Address pgwS5Address = pgwSgwIpIfaces.GetAddress(0);
128 Ipv4Address sgwS5Address = pgwSgwIpIfaces.GetAddress(1);
129
130 // Create S5-U socket in the PGW
131 Ptr<Socket> pgwS5uSocket =
132 Socket::CreateSocket(m_pgw, TypeId::LookupByName("ns3::UdpSocketFactory"));
133 retval = pgwS5uSocket->Bind(InetSocketAddress(pgwS5Address, m_gtpuUdpPort));
134 NS_ASSERT(retval == 0);
135
136 // Create S5-C socket in the PGW
137 Ptr<Socket> pgwS5cSocket =
138 Socket::CreateSocket(m_pgw, TypeId::LookupByName("ns3::UdpSocketFactory"));
139 retval = pgwS5cSocket->Bind(InetSocketAddress(pgwS5Address, m_gtpcUdpPort));
140 NS_ASSERT(retval == 0);
141
142 // Create NrEpcPgwApplication
143 m_pgwApp =
144 CreateObject<NrEpcPgwApplication>(m_tunDevice, pgwS5Address, pgwS5uSocket, pgwS5cSocket);
145 m_pgw->AddApplication(m_pgwApp);
146
147 // Connect NrEpcPgwApplication and virtual net device for tunneling
148 m_tunDevice->SetSendCallback(MakeCallback(&NrEpcPgwApplication::RecvFromTunDevice, m_pgwApp));
149
150 // Create S5-U socket in the SGW
151 Ptr<Socket> sgwS5uSocket =
152 Socket::CreateSocket(m_sgw, TypeId::LookupByName("ns3::UdpSocketFactory"));
153 retval = sgwS5uSocket->Bind(InetSocketAddress(sgwS5Address, m_gtpuUdpPort));
154 NS_ASSERT(retval == 0);
155
156 // Create S5-C socket in the SGW
157 Ptr<Socket> sgwS5cSocket =
158 Socket::CreateSocket(m_sgw, TypeId::LookupByName("ns3::UdpSocketFactory"));
159 retval = sgwS5cSocket->Bind(InetSocketAddress(sgwS5Address, m_gtpcUdpPort));
160 NS_ASSERT(retval == 0);
161
162 // Create S1-U socket in the SGW
163 Ptr<Socket> sgwS1uSocket =
164 Socket::CreateSocket(m_sgw, TypeId::LookupByName("ns3::UdpSocketFactory"));
165 retval = sgwS1uSocket->Bind(InetSocketAddress(Ipv4Address::GetAny(), m_gtpuUdpPort));
166 NS_ASSERT(retval == 0);
167
168 // Create NrEpcSgwApplication
169 m_sgwApp =
170 CreateObject<NrEpcSgwApplication>(sgwS1uSocket, sgwS5Address, sgwS5uSocket, sgwS5cSocket);
171 m_sgw->AddApplication(m_sgwApp);
172 m_sgwApp->AddPgw(pgwS5Address);
173 m_pgwApp->AddSgw(sgwS5Address);
174
175 // Create S11 link between MME and SGW
176 PointToPointHelper s11P2ph;
177 s11P2ph.SetDeviceAttribute("DataRate", DataRateValue(m_s11LinkDataRate));
178 s11P2ph.SetDeviceAttribute("Mtu", UintegerValue(m_s11LinkMtu));
179 s11P2ph.SetChannelAttribute("Delay", TimeValue(m_s11LinkDelay));
180 NetDeviceContainer mmeSgwDevices = s11P2ph.Install(m_mme, m_sgw);
181 NS_LOG_LOGIC("MME's IPv4 ifaces after installing p2p dev: "
182 << m_mme->GetObject<Ipv4>()->GetNInterfaces());
183 NS_LOG_LOGIC("SGW's IPv4 ifaces after installing p2p dev: "
184 << m_sgw->GetObject<Ipv4>()->GetNInterfaces());
185 Ptr<NetDevice> mmeDev = mmeSgwDevices.Get(0);
186 Ptr<NetDevice> sgwS11Dev = mmeSgwDevices.Get(1);
187 m_s11Ipv4AddressHelper.NewNetwork();
188 Ipv4InterfaceContainer mmeSgwIpIfaces = m_s11Ipv4AddressHelper.Assign(mmeSgwDevices);
189 NS_LOG_LOGIC("MME's IPv4 ifaces after assigning Ipv4 addr to S11 dev: "
190 << m_mme->GetObject<Ipv4>()->GetNInterfaces());
191 NS_LOG_LOGIC("SGW's IPv4 ifaces after assigning Ipv4 addr to S11 dev: "
192 << m_sgw->GetObject<Ipv4>()->GetNInterfaces());
193
194 Ipv4Address mmeS11Address = mmeSgwIpIfaces.GetAddress(0);
195 Ipv4Address sgwS11Address = mmeSgwIpIfaces.GetAddress(1);
196
197 // Create S11 socket in the MME
198 Ptr<Socket> mmeS11Socket =
199 Socket::CreateSocket(m_mme, TypeId::LookupByName("ns3::UdpSocketFactory"));
200 retval = mmeS11Socket->Bind(InetSocketAddress(mmeS11Address, m_gtpcUdpPort));
201 NS_ASSERT(retval == 0);
202
203 // Create S11 socket in the SGW
204 Ptr<Socket> sgwS11Socket =
205 Socket::CreateSocket(m_sgw, TypeId::LookupByName("ns3::UdpSocketFactory"));
206 retval = sgwS11Socket->Bind(InetSocketAddress(sgwS11Address, m_gtpcUdpPort));
207 NS_ASSERT(retval == 0);
208
209 // Create MME Application and connect with SGW via S11 interface
210 m_mmeApp = CreateObject<NrEpcMmeApplication>();
211 m_mme->AddApplication(m_mmeApp);
212 m_mmeApp->AddSgw(sgwS11Address, mmeS11Address, mmeS11Socket);
213 m_sgwApp->AddMme(mmeS11Address, sgwS11Socket);
214}
215
217{
218 NS_LOG_FUNCTION(this);
219}
220
221TypeId
223{
224 NS_LOG_FUNCTION_NOARGS();
225 static TypeId tid =
226 TypeId("ns3::NrNoBackhaulEpcHelper")
227 .SetParent<NrEpcHelper>()
228 .SetGroupName("Nr")
229 .AddConstructor<NrNoBackhaulEpcHelper>()
230 .AddAttribute("S5LinkDataRate",
231 "The data rate to be used for the next S5 link to be created",
232 DataRateValue(DataRate("10Gb/s")),
233 MakeDataRateAccessor(&NrNoBackhaulEpcHelper::m_s5LinkDataRate),
234 MakeDataRateChecker())
235 .AddAttribute("S5LinkDelay",
236 "The delay to be used for the next S5 link to be created",
237 TimeValue(Seconds(0)),
238 MakeTimeAccessor(&NrNoBackhaulEpcHelper::m_s5LinkDelay),
239 MakeTimeChecker())
240 .AddAttribute("S5LinkMtu",
241 "The MTU of the next S5 link to be created",
242 UintegerValue(2000),
243 MakeUintegerAccessor(&NrNoBackhaulEpcHelper::m_s5LinkMtu),
244 MakeUintegerChecker<uint16_t>())
245 .AddAttribute("S11LinkDataRate",
246 "The data rate to be used for the next S11 link to be created",
247 DataRateValue(DataRate("10Gb/s")),
248 MakeDataRateAccessor(&NrNoBackhaulEpcHelper::m_s11LinkDataRate),
249 MakeDataRateChecker())
250 .AddAttribute("S11LinkDelay",
251 "The delay to be used for the next S11 link to be created",
252 TimeValue(Seconds(0)),
253 MakeTimeAccessor(&NrNoBackhaulEpcHelper::m_s11LinkDelay),
254 MakeTimeChecker())
255 .AddAttribute("S11LinkMtu",
256 "The MTU of the next S11 link to be created.",
257 UintegerValue(2000),
258 MakeUintegerAccessor(&NrNoBackhaulEpcHelper::m_s11LinkMtu),
259 MakeUintegerChecker<uint16_t>())
260 .AddAttribute("X2LinkDataRate",
261 "The data rate to be used for the next X2 link to be created",
262 DataRateValue(DataRate("10Gb/s")),
263 MakeDataRateAccessor(&NrNoBackhaulEpcHelper::m_x2LinkDataRate),
264 MakeDataRateChecker())
265 .AddAttribute("X2LinkDelay",
266 "The delay to be used for the next X2 link to be created",
267 TimeValue(Seconds(0)),
268 MakeTimeAccessor(&NrNoBackhaulEpcHelper::m_x2LinkDelay),
269 MakeTimeChecker())
270 .AddAttribute("X2LinkMtu",
271 "The MTU of the next X2 link to be created. Note that, because of some "
272 "big X2 messages, you need a big MTU.",
273 UintegerValue(3000),
274 MakeUintegerAccessor(&NrNoBackhaulEpcHelper::m_x2LinkMtu),
275 MakeUintegerChecker<uint16_t>())
276 .AddAttribute("X2LinkPcapPrefix",
277 "Prefix for Pcap generated by X2 link",
278 StringValue("x2"),
279 MakeStringAccessor(&NrNoBackhaulEpcHelper::m_x2LinkPcapPrefix),
280 MakeStringChecker())
281 .AddAttribute("X2LinkEnablePcap",
282 "Enable Pcap for X2 link",
283 BooleanValue(false),
284 MakeBooleanAccessor(&NrNoBackhaulEpcHelper::m_x2LinkEnablePcap),
285 MakeBooleanChecker());
286 return tid;
287}
288
289void
290NrNoBackhaulEpcHelper::DoDispose()
291{
292 NS_LOG_FUNCTION(this);
293 m_tunDevice->SetSendCallback(
294 MakeNullCallback<bool, Ptr<Packet>, const Address&, const Address&, uint16_t>());
295 m_tunDevice = nullptr;
296 m_sgwApp = nullptr;
297 m_sgw->Dispose();
298 m_pgwApp = nullptr;
299 m_pgw->Dispose();
300 m_mmeApp = nullptr;
301 m_mme->Dispose();
302}
303
304void
306 Ptr<NetDevice> nrGnbNetDevice,
307 std::vector<uint16_t> cellIds)
308{
309 NS_LOG_FUNCTION(this << gnb << nrGnbNetDevice << cellIds.size());
310 NS_ASSERT(gnb == nrGnbNetDevice->GetNode());
311
312 int retval;
313
314 // add an IPv4 stack to the previously created gNB
315 InternetStackHelper internet;
316 internet.Install(gnb);
317 NS_LOG_LOGIC("number of Ipv4 ifaces of the gNB after node creation: "
318 << gnb->GetObject<Ipv4>()->GetNInterfaces());
319
320 // create NR socket for the gNB
321 Ptr<Socket> nrGnbSocket =
322 Socket::CreateSocket(gnb, TypeId::LookupByName("ns3::PacketSocketFactory"));
323 PacketSocketAddress nrGnbSocketBindAddress;
324 nrGnbSocketBindAddress.SetSingleDevice(nrGnbNetDevice->GetIfIndex());
325 nrGnbSocketBindAddress.SetProtocol(Ipv4L3Protocol::PROT_NUMBER);
326 retval = nrGnbSocket->Bind(nrGnbSocketBindAddress);
327 NS_ASSERT(retval == 0);
328 PacketSocketAddress nrGnbSocketConnectAddress;
329 nrGnbSocketConnectAddress.SetPhysicalAddress(Mac48Address::GetBroadcast());
330 nrGnbSocketConnectAddress.SetSingleDevice(nrGnbNetDevice->GetIfIndex());
331 nrGnbSocketConnectAddress.SetProtocol(Ipv4L3Protocol::PROT_NUMBER);
332 retval = nrGnbSocket->Connect(nrGnbSocketConnectAddress);
333 NS_ASSERT(retval == 0);
334
335 // create NR socket for the gNB
336 Ptr<Socket> nrGnbSocket6 =
337 Socket::CreateSocket(gnb, TypeId::LookupByName("ns3::PacketSocketFactory"));
338 PacketSocketAddress nrGnbSocketBindAddress6;
339 nrGnbSocketBindAddress6.SetSingleDevice(nrGnbNetDevice->GetIfIndex());
340 nrGnbSocketBindAddress6.SetProtocol(Ipv6L3Protocol::PROT_NUMBER);
341 retval = nrGnbSocket6->Bind(nrGnbSocketBindAddress6);
342 NS_ASSERT(retval == 0);
343 PacketSocketAddress nrGnbSocketConnectAddress6;
344 nrGnbSocketConnectAddress6.SetPhysicalAddress(Mac48Address::GetBroadcast());
345 nrGnbSocketConnectAddress6.SetSingleDevice(nrGnbNetDevice->GetIfIndex());
346 nrGnbSocketConnectAddress6.SetProtocol(Ipv6L3Protocol::PROT_NUMBER);
347 retval = nrGnbSocket6->Connect(nrGnbSocketConnectAddress6);
348 NS_ASSERT(retval == 0);
349
350 NS_LOG_INFO("Create NrEpcGnbApplication for cell ID " << cellIds.at(0));
351 Ptr<NrEpcGnbApplication> gnbApp =
352 CreateObject<NrEpcGnbApplication>(nrGnbSocket, nrGnbSocket6, cellIds.at(0));
353 gnb->AddApplication(gnbApp);
354 NS_ASSERT(gnb->GetNApplications() == 1);
355 NS_ASSERT_MSG(gnb->GetApplication(0)->GetObject<NrEpcGnbApplication>(),
356 "cannot retrieve NrEpcGnbApplication");
357 NS_LOG_LOGIC("gnb: " << gnb << ", gnb->GetApplication (0): " << gnb->GetApplication(0));
358
359 NS_LOG_INFO("Create NrEpcX2 entity");
360 Ptr<NrEpcX2> x2 = CreateObject<NrEpcX2>();
361 gnb->AggregateObject(x2);
362}
363
364void
365NrNoBackhaulEpcHelper::AddX2Interface(Ptr<Node> gnb1, Ptr<Node> gnb2)
366{
367 NS_LOG_FUNCTION(this << gnb1 << gnb2);
368
369 // Create a point to point link between the two eNBs with
370 // the corresponding new NetDevices on each side
371 PointToPointHelper p2ph;
372 p2ph.SetDeviceAttribute("DataRate", DataRateValue(m_x2LinkDataRate));
373 p2ph.SetDeviceAttribute("Mtu", UintegerValue(m_x2LinkMtu));
374 p2ph.SetChannelAttribute("Delay", TimeValue(m_x2LinkDelay));
375 NetDeviceContainer gnbDevices = p2ph.Install(gnb1, gnb2);
376 NS_LOG_LOGIC("number of Ipv4 ifaces of the gNB #1 after installing p2p dev: "
377 << gnb1->GetObject<Ipv4>()->GetNInterfaces());
378 NS_LOG_LOGIC("number of Ipv4 ifaces of the gNB #2 after installing p2p dev: "
379 << gnb2->GetObject<Ipv4>()->GetNInterfaces());
380
381 if (m_x2LinkEnablePcap)
382 {
383 p2ph.EnablePcapAll(m_x2LinkPcapPrefix);
384 }
385
386 m_x2Ipv4AddressHelper.NewNetwork();
387 Ipv4InterfaceContainer gnbIpIfaces = m_x2Ipv4AddressHelper.Assign(gnbDevices);
388 NS_LOG_LOGIC("number of Ipv4 ifaces of the gNB #1 after assigning Ipv4 addr to X2 dev: "
389 << gnb1->GetObject<Ipv4>()->GetNInterfaces());
390 NS_LOG_LOGIC("number of Ipv4 ifaces of the gNB #2 after assigning Ipv4 addr to X2 dev: "
391 << gnb2->GetObject<Ipv4>()->GetNInterfaces());
392
393 Ipv4Address gnb1X2Address = gnbIpIfaces.GetAddress(0);
394 Ipv4Address gnb2X2Address = gnbIpIfaces.GetAddress(1);
395
396 // Add X2 interface to both eNBs' X2 entities
397 Ptr<NrEpcX2> gnb1X2 = gnb1->GetObject<NrEpcX2>();
398 Ptr<NrEpcX2> gnb2X2 = gnb2->GetObject<NrEpcX2>();
399
400 Ptr<NetDevice> gnb1NrDev = gnb1->GetDevice(0);
401 Ptr<NetDevice> gnb2NrDev = gnb2->GetDevice(0);
402
403 DoAddX2Interface(gnb1X2, gnb1NrDev, gnb1X2Address, gnb2X2, gnb2NrDev, gnb2X2Address);
404}
405
406void
408 const Ptr<NetDevice>& gnb1NrDev,
409 const Ipv4Address& gnb1X2Address,
410 const Ptr<NrEpcX2>& gnb2X2,
411 const Ptr<NetDevice>& gnb2NrDev,
412 const Ipv4Address& gnb2X2Address) const
413{
414 NS_LOG_FUNCTION(this);
415
416 Ptr<NrGnbNetDevice> gnb1NrDevice = gnb1NrDev->GetObject<NrGnbNetDevice>();
417 Ptr<NrGnbNetDevice> gnb2NrDevice = gnb2NrDev->GetObject<NrGnbNetDevice>();
418
419 NS_ABORT_MSG_IF(!gnb1NrDevice, "Unable to find NrGnbNetDevice for the first gNB");
420 NS_ABORT_MSG_IF(!gnb2NrDevice, "Unable to find NrGnbNetDevice for the second gNB");
421
422 std::vector<uint16_t> gnb1CellIds = gnb1NrDevice->GetCellIds();
423 std::vector<uint16_t> gnb2CellIds = gnb2NrDevice->GetCellIds();
424
425 uint16_t gnb1CellId = gnb1CellIds.at(0);
426 uint16_t gnb2CellId = gnb2CellIds.at(0);
427
428 NS_LOG_LOGIC("NrGnbNetDevice #1 = " << gnb1NrDev << " - CellId = " << gnb1CellId);
429 NS_LOG_LOGIC("NrGnbNetDevice #2 = " << gnb2NrDev << " - CellId = " << gnb2CellId);
430
431 gnb1X2->AddX2Interface(gnb1CellId, gnb1X2Address, gnb2CellIds, gnb2X2Address);
432 gnb2X2->AddX2Interface(gnb2CellId, gnb2X2Address, gnb1CellIds, gnb1X2Address);
433
434 gnb1NrDevice->GetRrc()->AddX2Neighbour(gnb2CellId);
435 gnb2NrDevice->GetRrc()->AddX2Neighbour(gnb1CellId);
436}
437
438void
439NrNoBackhaulEpcHelper::AddUe(Ptr<NetDevice> ueDevice, uint64_t imsi)
440{
441 NS_LOG_FUNCTION(this << imsi << ueDevice);
442
443 m_mmeApp->AddUe(imsi);
444 m_pgwApp->AddUe(imsi);
445}
446
447uint8_t
449 uint64_t imsi,
450 Ptr<NrEpcTft> tft,
451 NrEpsBearer bearer)
452{
453 NS_LOG_FUNCTION(this << ueDevice << imsi);
454
455 // we now retrieve the IPv4/IPv6 address of the UE and notify it to the SGW;
456 // we couldn't do it before since address assignment is triggered by
457 // the user simulation program, rather than done by the EPC
458 Ptr<Node> ueNode = ueDevice->GetNode();
459 Ptr<Ipv4> ueIpv4 = ueNode->GetObject<Ipv4>();
460 Ptr<Ipv6> ueIpv6 = ueNode->GetObject<Ipv6>();
461 NS_ASSERT_MSG(ueIpv4 || ueIpv6,
462 "UEs need to have IPv4/IPv6 installed before EPS bearers can be activated");
463
464 if (ueIpv4)
465 {
466 int32_t interface = ueIpv4->GetInterfaceForDevice(ueDevice);
467 if (interface >= 0 && ueIpv4->GetNAddresses(interface) == 1)
468 {
469 Ipv4Address ueAddr = ueIpv4->GetAddress(interface, 0).GetLocal();
470 NS_LOG_LOGIC(" UE IPv4 address: " << ueAddr);
471 m_pgwApp->SetUeAddress(imsi, ueAddr);
472 }
473 }
474 if (ueIpv6)
475 {
476 int32_t interface6 = ueIpv6->GetInterfaceForDevice(ueDevice);
477 if (interface6 >= 0 && ueIpv6->GetNAddresses(interface6) == 2)
478 {
479 Ipv6Address ueAddr6 = ueIpv6->GetAddress(interface6, 1).GetAddress();
480 NS_LOG_LOGIC(" UE IPv6 address: " << ueAddr6);
481 m_pgwApp->SetUeAddress6(imsi, ueAddr6);
482 }
483 }
484 uint8_t bearerId = m_mmeApp->AddBearer(imsi, tft, bearer);
485 DoActivateEpsBearerForUe(ueDevice, tft, bearer);
486
487 return bearerId;
488}
489
490void
492 const Ptr<NrEpcTft>& tft,
493 const NrEpsBearer& bearer) const
494{
495 NS_LOG_FUNCTION(this);
496 Ptr<NrUeNetDevice> ueNrDevice = DynamicCast<NrUeNetDevice>(ueDevice);
497 if (!ueNrDevice)
498 {
499 // You may wonder why this is not an assert. Well, take a look in epc-test-s1u-downlink
500 // and -uplink: we are using CSMA to simulate UEs.
501 NS_LOG_WARN("Unable to find NrUeNetDevice while activating the EPS bearer");
502 }
503 else
504 {
505 // Schedule with context so that logging statements have Node ID
506 Simulator::ScheduleWithContext(ueNrDevice->GetNode()->GetId(),
507 Time(),
509 ueNrDevice->GetNas(),
510 bearer,
511 tft);
512 }
513}
514
515Ptr<Node>
517{
518 return m_pgw;
519}
520
521Ipv4InterfaceContainer
523{
524 auto ipv4ifaces = m_uePgwAddressHelper.Assign(ueDevices);
525 Ipv4StaticRoutingHelper ipv4RoutingHelper;
526 for (size_t i = 0; i < ueDevices.GetN(); i++)
527 {
528 if (!DynamicCast<NrUeNetDevice>(ueDevices.Get(i)))
529 {
530 continue;
531 }
532 auto ueNode = ueDevices.Get(i)->GetNode();
533 Ptr<Ipv4StaticRouting> ueStaticRouting =
534 ipv4RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv4>());
535 ueStaticRouting->SetDefaultRoute(GetUeDefaultGatewayAddress(), 1);
536 }
537 return ipv4ifaces;
538}
539
540Ipv6InterfaceContainer
542{
543 for (auto iter = ueDevices.Begin(); iter != ueDevices.End(); iter++)
544 {
545 Ptr<Icmpv6L4Protocol> icmpv6 = (*iter)->GetNode()->GetObject<Icmpv6L4Protocol>();
546 icmpv6->SetAttribute("DAD", BooleanValue(false));
547 }
548 auto ipv6ifaces = m_uePgwAddressHelper6.Assign(ueDevices);
549 Ipv6StaticRoutingHelper ipv6RoutingHelper;
550 for (size_t i = 0; i < ueDevices.GetN(); i++)
551 {
552 if (!DynamicCast<NrUeNetDevice>(ueDevices.Get(i)))
553 {
554 continue;
555 }
556 auto ueNode = ueDevices.Get(i)->GetNode();
557 Ptr<Ipv6StaticRouting> ueStaticRouting =
558 ipv6RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv6>());
559 ueStaticRouting->SetDefaultRoute(GetUeDefaultGatewayAddress6(), 1);
560 }
561 return ipv6ifaces;
562}
563
564Ipv4Address
566{
567 // return the address of the tun device
568 return m_pgw->GetObject<Ipv4>()->GetAddress(1, 0).GetLocal();
569}
570
571Ipv6Address
573{
574 // return the address of the tun device
575 return m_pgw->GetObject<Ipv6>()->GetAddress(1, 1).GetAddress();
576}
577
578Ptr<Node>
580{
581 return m_sgw;
582}
583
584void
586 Ipv4Address gnbAddress,
587 Ipv4Address sgwAddress,
588 std::vector<uint16_t> cellIds)
589{
590 NS_LOG_FUNCTION(this << gnb << gnbAddress << sgwAddress << cellIds.size());
591
592 // create S1-U socket for the gNB
593 Ptr<Socket> gnbS1uSocket =
594 Socket::CreateSocket(gnb, TypeId::LookupByName("ns3::UdpSocketFactory"));
595 int retval = gnbS1uSocket->Bind(InetSocketAddress(gnbAddress, m_gtpuUdpPort));
596 NS_ASSERT(retval == 0);
597
598 Ptr<NrEpcGnbApplication> gnbApp = gnb->GetApplication(0)->GetObject<NrEpcGnbApplication>();
599 NS_ASSERT_MSG(gnbApp, "NrEpcGnbApplication not available");
600 gnbApp->AddS1Interface(gnbS1uSocket, gnbAddress, sgwAddress);
601
602 NS_LOG_INFO("Connect S1-AP interface");
603 for (uint16_t cellId : cellIds)
604 {
605 NS_LOG_DEBUG("Adding MME and SGW for cell ID " << cellId);
606 m_mmeApp->AddGnb(cellId, gnbAddress, gnbApp->GetS1apSapGnb());
607 m_sgwApp->AddGnb(cellId, gnbAddress, sgwAddress);
608 }
609 gnbApp->SetS1apSapMme(m_mmeApp->GetS1apSapMme());
610}
611
612int64_t
614{
615 int64_t currentStream = stream;
616 NS_ABORT_MSG_UNLESS(m_pgw && m_sgw && m_mme, "Running AssignStreams on empty node pointers");
617 InternetStackHelper internet;
618 NodeContainer nc;
619 nc.Add(m_pgw);
620 nc.Add(m_sgw);
621 nc.Add(m_mme);
622 currentStream += internet.AssignStreams(nc, currentStream);
623 return (currentStream - stream);
624}
625
626std::pair<Ptr<Node>, Ipv4Address>
627NrNoBackhaulEpcHelper::SetupRemoteHost(std::optional<std::string> dataRate,
628 std::optional<uint16_t> mtu,
629 std::optional<Time> delay)
630{
631 // create the internet and install the IP stack on the UEs
632 // get SGW/PGW and create a single RemoteHost
633 Ptr<Node> pgw = GetPgwNode();
634 NodeContainer remoteHostContainer;
635 remoteHostContainer.Create(1);
636 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
637 InternetStackHelper internet;
638 internet.Install(remoteHostContainer);
639
640 // connect a remoteHost to pgw. Setup routing too
641 PointToPointHelper p2ph;
642 if (dataRate.has_value())
643 {
644 p2ph.SetDeviceAttribute("DataRate", StringValue(dataRate.value()));
645 }
646 if (mtu.has_value())
647 {
648 p2ph.SetDeviceAttribute("Mtu", UintegerValue(mtu.value()));
649 }
650 if (delay.has_value())
651 {
652 p2ph.SetChannelAttribute("Delay", TimeValue(delay.value()));
653 }
654 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
655
656 // Setup IPv4 addresses and routing from remoteHost to the UEs through PGW
657 Ipv4AddressHelper ipv4h;
658 Ipv4StaticRoutingHelper ipv4RoutingHelper;
659 ipv4h.SetBase("1.0.0.0", "255.0.0.0");
660 Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
661 Ptr<Ipv4StaticRouting> remoteHostStaticRouting4 =
662 ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
663 remoteHostStaticRouting4->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
664 return std::make_pair(remoteHost, internetIpIfaces.GetAddress(0, 0));
665}
666
667std::pair<Ptr<Node>, Ipv6Address>
668NrNoBackhaulEpcHelper::SetupRemoteHost6(std::optional<std::string> dataRate,
669 std::optional<uint16_t> mtu,
670 std::optional<Time> delay)
671{
672 // create the internet and install the IP stack on the UEs
673 // get SGW/PGW and create a single RemoteHost
674 Ptr<Node> pgw = GetPgwNode();
675 NodeContainer remoteHostContainer;
676 remoteHostContainer.Create(1);
677 Ptr<Node> remoteHost = remoteHostContainer.Get(0);
678 InternetStackHelper internet;
679 internet.Install(remoteHostContainer);
680
681 // connect a remoteHost to pgw. Setup routing too
682 PointToPointHelper p2ph;
683 if (dataRate.has_value())
684 {
685 p2ph.SetDeviceAttribute("DataRate", StringValue(dataRate.value()));
686 }
687 if (mtu.has_value())
688 {
689 p2ph.SetDeviceAttribute("Mtu", UintegerValue(mtu.value()));
690 }
691 if (delay.has_value())
692 {
693 p2ph.SetChannelAttribute("Delay", TimeValue(delay.value()));
694 }
695 NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
696
697 // Setup IPv6 addresses and routing from remoteHost to the UEs through PGW
698 Ipv6AddressHelper ipv6h;
699 ipv6h.SetBase(Ipv6Address("6001:db80::"), Ipv6Prefix(64));
700 Ipv6InterfaceContainer internetIpIfaces = ipv6h.Assign(internetDevices);
701 internetIpIfaces.SetForwarding(0, true);
702 internetIpIfaces.SetDefaultRouteInAllNodes(0);
703
704 Ipv6StaticRoutingHelper ipv6RoutingHelper;
705 Ptr<Ipv6StaticRouting> remoteHostStaticRouting =
706 ipv6RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv6>());
707 remoteHostStaticRouting
708 ->AddNetworkRouteTo("7777:f00d::", Ipv6Prefix(64), internetIpIfaces.GetAddress(0, 1), 1, 0);
709 return std::make_pair(remoteHost, internetIpIfaces.GetAddress(1, 1));
710}
711
712} // namespace ns3
Base helper class to handle the creation of the EPC entities.
bool RecvFromTunDevice(Ptr< Packet > packet, const Address &source, const Address &dest, uint16_t protocolNumber)
void ActivateEpsBearer(NrEpsBearer bearer, Ptr< NrEpcTft > tft)
This class contains the specification of EPS Bearers.
The NrGnbNetDevice class.
Create an EPC network with PointToPoint links between the core network nodes.
void AddGnb(Ptr< Node > gnbNode, Ptr< NetDevice > nrGnbNetDevice, std::vector< uint16_t > cellIds) override
int64_t AssignStreams(int64_t stream) override
Ptr< Node > GetPgwNode() const override
Ipv4InterfaceContainer AssignUeIpv4Address(NetDeviceContainer ueDevices) override
void AddS1Interface(Ptr< Node > gnb, Ipv4Address gnbAddress, Ipv4Address sgwAddress, std::vector< uint16_t > cellIds) override
void AddUe(Ptr< NetDevice > ueNrDevice, uint64_t imsi) override
std::pair< Ptr< Node >, Ipv6Address > SetupRemoteHost6(std::optional< std::string > dataRate, std::optional< uint16_t > mtu, std::optional< Time > delay) override
void AddX2Interface(Ptr< Node > gnbNode1, Ptr< Node > gnbNode2) override
Ipv6InterfaceContainer AssignUeIpv6Address(NetDeviceContainer ueDevices) override
uint8_t ActivateEpsBearer(Ptr< NetDevice > ueNrDevice, uint64_t imsi, Ptr< NrEpcTft > tft, NrEpsBearer bearer) override
Ipv4Address GetUeDefaultGatewayAddress() override
virtual void DoActivateEpsBearerForUe(const Ptr< NetDevice > &ueDevice, const Ptr< NrEpcTft > &tft, const NrEpsBearer &bearer) const
DoActivateEpsBearerForUe: Schedule ActivateEpsBearer on the UE.
Ipv6Address GetUeDefaultGatewayAddress6() override
std::pair< Ptr< Node >, Ipv4Address > SetupRemoteHost(std::optional< std::string > dataRate, std::optional< uint16_t > mtu, std::optional< Time > delay) override
Ptr< Node > GetSgwNode() const override
virtual void DoAddX2Interface(const Ptr< NrEpcX2 > &gnb1X2, const Ptr< NetDevice > &gnb1NrDev, const Ipv4Address &gnb1X2Address, const Ptr< NrEpcX2 > &gnb2X2, const Ptr< NetDevice > &gnb2NrDev, const Ipv4Address &gnb2X2Address) const
DoAddX2Interface: Call AddX2Interface on top of the Gnb device pointers.