| ||||
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include<fstream>
#include<cmath>
using namespace ns3;
uint32_t txAttempts=0;
uint32_t successfulTx=0;
uint32_t collisions=0;
class AlohaNode{
public:
AlohaNode(double lambda,bool slotted)
: m_lambda(lambda), m_slotted(slotted){}
void Start(){
ScheduleNextTx();
}
void ScheduleNextTx(){
double interval = -std::log(1.0 - ((double)rand() / RAND_MAX)) m_lambda;
if (m_slotted){
interval=std::ceil(interval/0.01)0.01;
}
Simulator::Schedule(Seconds(interval),&AlohaNode::Transmit,this);
}
void Transmit(){
txAttempts++;
m_lastTxTime = Simulator::Now().GetSeconds();
ScheduleNextTx();
}
double GetLastTxTime(){ return m_lastTxTime; }
private:
double m_lambda;
bool m_slotted;
double m_lastTxTime=0;
};
double SimulateAloha(double G, bool slotted, uint32_t numNodes)
{
txAttempts=0;
successfulTx=0;
collisions=0;
double lambda = G / numNodes;
std::vector<AlohaNode*> nodes;
std::vector<double> txTimes;
for (uint32_t i = 0; i < numNodes; i++) {
AlohaNode* node = new AlohaNode(lambda, slotted);
nodes.push_back(node);
node->Start();
}
Simulator::Stop(Seconds(100.0));
Simulator::Run();
double vulnerablePeriod=slotted ? 1.0:2.0;
successfulTx=txAttempts*std::exp(-G vulnerablePeriod);
for(auto node : nodes) delete node;
Simulator ::Destroy();
return successfulTx /100.0;
}
int main(int argc, char argv[])
{
uint32_t numNodes=100;
std::ofstream pureFile("pure_aloha.dat");
std::ofstream slottedFile("slotted_aloha.dat");
std::cout<< "simulating ALOHA systems ...\n";
std::cout<< "G\tPure ALOHA\tSotted ALOHA\n";
std::cout<< "---\t---------\t-----------\n";
for (double G=0.1; G<=3.0;G+=0.2){double pureS = G G); double slottedS = G * std::exp(-G);pureFile <<G<<"\t" << pureS<<"\n";slottedFile << G << "\t" << slottedS << "\n"; std::cout << G << "\t" << pureS << "\t\t" << slottedS << "\n"; } pureFile.close(); slottedFile.close(); // generate gnuplot script std::ofstream plotScript("plot_aloha.gnu");plotScript << "set terminal png size 800,600\n";plotScript << "set output 'aloha_comparison.png'\n";plotScript << "set title 'ALOHA Throughput'\n";plotScript << "set xlabel 'Offered Load (G)'\n";plotScript << "set ylabel 'Throughput (S)'\n";plotScript << "set grid\n";plotScript << "plot 'pure_aloha.dat' using 1:2 with linespoints title 'Pure ALOHA', \\\n";plotScript << " 'slotted_aloha.dat' using 1:2 with linespoints title 'Slotted ALOHA'\n";plotScript.close(); return 0;}
3333333333333333333333333333333333
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include <fstream>
#include <cmath>
using namespace ns3;
//Global variables for statistics
uint32_t txAttempts = 0;
uint32_t successfulTx = 0;
uint32_t collisions = 0;
class AlohaNode
{
public:
AlohaNode(double lambda, bool slotted) : m_lambda(lambda), m_slotted(slotted) {}
void start()
{
ScheduleNextTx();
}
void ScheduleNextTx()
{
//Exponential inter-arrival time
double interval = -std::log(1.0-((double)rand()/RAND_MAX))/m_lambda;
if(m_slotted)
{
//Round to nearest slot(0.01s slots)
interval = std::ceil(interval/0.01)*0.01;
}
Simulator::Schedule(Seconds(interval), &AlohaNode::Transmit, this);
}
void Transmit()
{
txAttempts++;
//Record transmission time for collision detection
m_lastTxTime = Simulator::Now().GetSeconds();
ScheduleNextTx();
}
double GetLastTxTime()
{
return m_lastTxTime;
}
private:
double m_lambda;
bool m_slotted;
double m_lastTxTime = 0;
};
//Simulate ALOHA for given offered load
double SimulateAloha(double G, bool slotted, uint32_t numNodes)
{
txAttempts = 0;
successfulTx = 0;
collisions = 0;
//Lambda per node
double lambda = G/numNodes;
std::vector<AlohaNode*> nodes;
std::vector<double> txTimes;
for(uint32_t i = 0; i < numNodes; i++)
{
AlohaNode* node = new AlohaNode(lambda, slotted);
nodes.push_back(node);
node -> start();
}
//Run simulation
Simulator::Stop(Seconds(100.0));
Simulator::Run();
//Detect collisions(simplified)
double vulnerablePeriod = slotted ? 1.0 : 2.0;
successfulTx = txAttempts std::exp(-G vulnerablePeriod);
//Cleanup
for(auto node : nodes) delete node;
Simulator::Destroy();//Throughput S = G*e^(-G* vulnerable_period)return successfulTx/100.0;}int main(int argc, char e^(-2G)double pureS = G*std::exp(-2.0*G);//Slotted ALOHA : S = G*e^(-G)double slottedS = G*std::exp(-G);pureFile<<G<<"\t"<<pureS<<"\n";slottedFile<<G<<"\t"<<slottedS<<"\n";std::cout<<G<<"\t"<<pureS<<"\t\t"<<slottedS<<"\n";}pureFile.close();slottedFile.close();std::cout<<"\nData written to pure_aloha.dat and slotted_aloha.dat\n";std::cout<<"\nKey Observations:\n";std::cout<<"1. Pure ALOHA max throughput : 0.184 at G=0.5\n";std::cout<<"2. Slotted ALOHA max throughput : 0.368 at G=1.0\n";std::cout<<"3. Slotted ALOHA is 2x better than Pure ALOHA\n";//Generate gnuplot scriptstd::ofstream plotScript("plot_aloha.gnu");plotScript<<"set terminal png size 800, 600\n";plotScript<<"set output 'aloha_comparison.png'\n";plotScript<<"set title 'ALOHA Throughput vs Offered Traffic'\n";plotScript<<"set xlabel 'Offered Traffic G (packets/packet time)'\n";plotScript<<"set ylabel 'Throughput S (successful packets/packet time)'\n";plotScript<<"set grid\n";plotScript<<"plot 'pure_aloha.dat' with lines lw 2 title 'Pure ALOHA', \\\n";plotScript<<"plot 'slotted_aloha.dat' with lines lw 2 title 'Slotted ALOHA', \\\n";plotScript.close(); system("gnuplot plot_aloha.gnu");std::cout<<"\nTo plot:gnuplot plot_aloha.gnu\n";return 0;}
33333333GGGGGGGGGGGG
/*
* 3G Network Performance Analysis: Throughput and Delay
* NS-3 Simulation for 1-10 Nodes
* Measures: Throughput, End-to-End Delay, Packet Loss, Jitter
*/
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/lte-module.h"
#include "ns3/config-store-module.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/netanim-module.h"
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>
using namespace ns3;
NS_LOG_COMPONENT_DEFINE("3GNetworkPerformance");
// Global variables for statistics
uint32_t totalPacketsSent = 0;
uint32_t totalPacketsReceived = 0;
uint64_t totalBytesReceived = 0;
double totalDelay = 0.0;
uint32_t delayCount = 0;
std::vector<double> delays;
// Performance metrics structure
struct PerformanceMetrics {
uint32_t numNodes;
double throughput;
double avgDelay;
double packetLoss;
double jitter;
double rxPackets;
double txPackets;
};
std::vector<PerformanceMetrics> allMetrics;
// Packet receive callback
void ReceivePacket(Ptr<Socket> socket) {
Ptr<Packet> packet;
Address from;
while ((packet = socket->RecvFrom(from))) {
totalPacketsReceived++;
totalBytesReceived += packet->GetSize();
// Extract timing information if available
SeqTsHeader seqTs;
packet->RemoveHeader(seqTs);
Time tx = seqTs.GetTs();
Time rx = Simulator::Now();
Time delay = rx - tx;
totalDelay += delay.GetSeconds();
delays.push_back(delay.GetSeconds());
delayCount++;
NS_LOG_INFO("Received packet of size " << packet->GetSize()
<< " bytes at " << rx.GetSeconds()
<< "s, delay: " << delay.GetMilliSeconds() << " ms");
}
}
// Packet send callback
void SendPacket(Ptr<Socket> socket, uint32_t pktSize, uint32_t pktCount, Time pktInterval) {
if (pktCount > 0) {
Ptr<Packet> packet = Create<Packet>(pktSize);
SeqTsHeader seqTs;
seqTs.SetSeq(totalPacketsSent++);
packet->AddHeader(seqTs);
socket->Send(packet);
Simulator::Schedule(pktInterval, &SendPacket, socket, pktSize, pktCount - 1, pktInterval);
}
}
// Calculate jitter
double CalculateJitter() {
if (delays.size() < 2) return 0.0;
double jitter = 0.0;
for (size_t i = 1; i < delays.size(); i++) {
jitter += std::abs(delays[i] - delays[i-1]);
}
return (jitter / (delays.size() - 1)) * 1000; // Convert to ms
}
// Run simulation for specific number of nodes
void RunSimulation(uint32_t numNodes, double bandwidth, double frequency, double simTime) {
// Reset statistics
totalPacketsSent = 0;
totalPacketsReceived = 0;
totalBytesReceived = 0;
totalDelay = 0.0;
delayCount = 0;
delays.clear();
NS_LOG_INFO("Running simulation with " << numNodes << " nodes");
// Create LTE Helper
Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper>();
lteHelper->SetEpcHelper(epcHelper);
// Configure 3G/LTE parameters
lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel"));
lteHelper->SetEnbDeviceAttribute("DlBandwidth", UintegerValue(bandwidth)); // Resource blocks
lteHelper->SetEnbDeviceAttribute("UlBandwidth", UintegerValue(bandwidth));
// Set frequency (carrier frequency in Hz)
lteHelper->SetEnbDeviceAttribute("DlEarfcn", UintegerValue(frequency));
lteHelper->SetEnbDeviceAttribute("UlEarfcn", UintegerValue(frequency + 18000));
// Get PGW node
Ptr<Node> pgw = epcHelper->GetPgwNode();
// Create remote host
NodeContainer remoteHostContainer;
remoteHostContainer.Create(1);
Ptr<Node> remoteHost = remoteHostContainer.Get(0);
InternetStackHelper internet;
internet.Install(remoteHostContainer);
// Connect remote host to PGW
PointToPointHelper p2ph;
p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
p2ph.SetChannelAttribute("Delay", TimeValue(Seconds(0.001)));
NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
// Assign IP addresses
Ipv4AddressHelper ipv4h;
ipv4h.SetBase("1.0.0.0", "255.0.0.0");
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
// Set up routing
Ipv4StaticRoutingHelper ipv4RoutingHelper;
Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
// Create eNodeB
NodeContainer enbNodes;
enbNodes.Create(1);
// Create UE nodes
NodeContainer ueNodes;
ueNodes.Create(numNodes);
// Install mobility model for eNodeB
MobilityHelper enbMobility;
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
positionAlloc->Add(Vector(0.0, 0.0, 0.0));
enbMobility.SetPositionAllocator(positionAlloc);
enbMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
enbMobility.Install(enbNodes);
// Install mobility model for UEs
MobilityHelper ueMobility;
ueMobility.SetPositionAllocator("ns3::UniformDiscPositionAllocator",
"X", DoubleValue(0.0),
"Y", DoubleValue(0.0),
"rho", DoubleValue(50.0));
ueMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
ueMobility.Install(ueNodes);
// Install LTE devices
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice(enbNodes);
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice(ueNodes);
// Install Internet stack on UEs
internet.Install(ueNodes);
// Assign IP addresses to UEs
Ipv4InterfaceContainer ueIpIface;
ueIpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueLteDevs));
// Set default gateway for UEs
for (uint32_t u = 0; u < ueNodes.GetN(); ++u) {
Ptr<Node> ueNode = ueNodes.Get(u);
Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv4>());
ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
}
// Attach UEs to eNodeB
lteHelper->Attach(ueLteDevs);
// Install applications
uint16_t dlPort = 1234;
uint16_t ulPort = 2000;
ApplicationContainer clientApps;
ApplicationContainer serverApps;
// Downlink: Remote host to UEs
for (uint32_t u = 0; u < ueNodes.GetN(); ++u) {
PacketSinkHelper dlPacketSinkHelper("ns3::UdpSocketFactory",
InetSocketAddress(Ipv4Address::GetAny(), dlPort));
serverApps.Add(dlPacketSinkHelper.Install(ueNodes.Get(u)));
UdpClientHelper dlClient(ueIpIface.GetAddress(u), dlPort);
dlClient.SetAttribute("Interval", TimeValue(MilliSeconds(10)));
dlClient.SetAttribute("MaxPackets", UintegerValue(1000000));
dlClient.SetAttribute("PacketSize", UintegerValue(1024));
clientApps.Add(dlClient.Install(remoteHost));
}
// Uplink: UEs to Remote host
PacketSinkHelper ulPacketSinkHelper("ns3::UdpSocketFactory",
InetSocketAddress(Ipv4Address::GetAny(), ulPort));
serverApps.Add(ulPacketSinkHelper.Install(remoteHost));
for (uint32_t u = 0; u < ueNodes.GetN(); ++u) {
UdpClientHelper ulClient(internetIpIfaces.GetAddress(1), ulPort);
ulClient.SetAttribute("Interval", TimeValue(MilliSeconds(10)));
ulClient.SetAttribute("MaxPackets", UintegerValue(1000000));
ulClient.SetAttribute("PacketSize", UintegerValue(1024));
clientApps.Add(ulClient.Install(ueNodes.Get(u)));
}
serverApps.Start(Seconds(0.1));
clientApps.Start(Seconds(0.5));
serverApps.Stop(Seconds(simTime));
clientApps.Stop(Seconds(simTime - 0.1));
// --- NETANIM CONFIGURATION ---
// 2. Create the AnimationInterface object
AnimationInterface anim("3g-simulation.xml");
// 3. Optional: Color the Base Station (Red)
anim.UpdateNodeDescription(enbNodes.Get(0), "eNodeB (3G BS)");
anim.UpdateNodeColor(enbNodes.Get(0), 255, 0, 0);
// 4. Optional: Color the Remote Host (Green)
anim.UpdateNodeDescription(remoteHost, "Remote Server");
anim.UpdateNodeColor(remoteHost, 0, 255, 0);
// 5. Optional: Color and Label UEs (Blue)
for (uint32_t i = 0; i < ueNodes.GetN(); ++i) {
anim.UpdateNodeDescription(ueNodes.Get(i), "User_" + std::to_string(i));
anim.UpdateNodeColor(ueNodes.Get(i), 0, 0, 255);
}
// 6. Enable Packet Metadata (allows you to see IP/UDP details in NetAnim)
anim.EnablePacketMetadata(true);
// Install FlowMonitor
FlowMonitorHelper flowmon;
Ptr<FlowMonitor> monitor = flowmon.InstallAll();
// Run simulation
Simulator::Stop(Seconds(simTime));
Simulator::Run();
// Calculate metrics using FlowMonitor
monitor->CheckForLostPackets();
Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier());
std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats();
double totalThroughput = 0.0;
double totalAvgDelay = 0.0;
double totalPacketLoss = 0.0;
uint32_t flowCount = 0;
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin(); i != stats.end(); ++i) {
Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
double throughput = i->second.rxBytes * 8.0 / (i->second.timeLastRxPacket.GetSeconds() -
i->second.timeFirstTxPacket.GetSeconds()) / 1024 / 1024;
double avgDelay = i->second.delaySum.GetMilliSeconds() / i->second.rxPackets;
double packetLoss = (i->second.txPackets - i->second.rxPackets) * 100.0 / i->second.txPackets;
totalThroughput += throughput;
totalAvgDelay += avgDelay;
totalPacketLoss += packetLoss;
flowCount++;
NS_LOG_INFO("Flow " << i->first << " (" << t.sourceAddress << " -> " << t.destinationAddress << ")");
NS_LOG_INFO(" Throughput: " << throughput << " Mbps");
NS_LOG_INFO(" Avg Delay: " << avgDelay << " ms");
NS_LOG_INFO(" Packet Loss: " << packetLoss << " %");
}
// Store metrics
PerformanceMetrics metrics;
metrics.numNodes = numNodes;
metrics.throughput = totalThroughput;
metrics.avgDelay = totalAvgDelay / flowCount;
metrics.packetLoss = totalPacketLoss / flowCount;
metrics.jitter = 0.0; // Can be calculated from FlowMonitor if needed
metrics.rxPackets = 0;
metrics.txPackets = 0;
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin(); i != stats.end(); ++i) {
metrics.rxPackets += i->second.rxPackets;
metrics.txPackets += i->second.txPackets;
}
allMetrics.push_back(metrics);
Simulator::Destroy();
}
int main(int argc, char *argv[]) {
// Simulation parameters
double bandwidth = 50; // Resource blocks (equivalent to ~10 MHz for LTE)
double frequency = 2100; // Carrier frequency index (EARFCN)
double simTime = 10.0; // Simulation time in seconds
uint32_t minNodes = 1;
uint32_t maxNodes = 10;
std::string outputFile = "3g_performance_results.csv";
// Parse command line arguments
CommandLine cmd;
cmd.AddValue("bandwidth", "Bandwidth in resource blocks", bandwidth);
cmd.AddValue("frequency", "Carrier frequency (EARFCN)", frequency);
cmd.AddValue("simTime", "Simulation time in seconds", simTime);
cmd.AddValue("minNodes", "Minimum number of nodes", minNodes);
cmd.AddValue("maxNodes", "Maximum number of nodes", maxNodes);
cmd.AddValue("outputFile", "Output CSV file name", outputFile);
cmd.Parse(argc, argv);
// Enable logging
LogComponentEnable("3GNetworkPerformance", LOG_LEVEL_INFO);
std::cout << "\n========================================" << std::endl;
std::cout << "3G Network Performance Simulation" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << "Bandwidth: " << bandwidth << " RBs" << std::endl;
std::cout << "Frequency: " << frequency << " EARFCN" << std::endl;
std::cout << "Simulation Time: " << simTime << " seconds" << std::endl;
std::cout << "Node Range: " << minNodes << " to " << maxNodes << std::endl;
std::cout << "========================================\n" << std::endl;
// Run simulations for different node counts
for (uint32_t numNodes = minNodes; numNodes <= maxNodes; numNodes++) {
std::cout << "\n--- Simulating with " << numNodes << " node(s) ---" << std::endl;
RunSimulation(numNodes, bandwidth, frequency, simTime);
}
// Write results to CSV file
std::ofstream outFile(outputFile);
outFile << "Nodes,Throughput(Mbps),AvgDelay(ms),PacketLoss(%),RxPackets,TxPackets" << std::endl;
std::cout << "\n========================================" << std::endl;
std::cout << "Simulation Results Summary" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << "Nodes\tThroughput\tAvg Delay\tPacket Loss\tRx Pkts\tTx Pkts" << std::endl;
std::cout << "\t(Mbps)\t\t(ms)\t\t(%)" << std::endl;
std::cout << "------------------------------------------------------------------------" << std::endl;
for (const auto& metrics : allMetrics) {
std::cout << metrics.numNodes << "\t"
<< std::fixed << std::setprecision(2) << metrics.throughput << "\t\t"
<< metrics.avgDelay << "\t\t"
<< metrics.packetLoss << "\t\t"
<< metrics.rxPackets << "\t"
<< metrics.txPackets << std::endl;
outFile << metrics.numNodes << ","
<< metrics.throughput << ","
<< metrics.avgDelay << ","
<< metrics.packetLoss << ","
<< metrics.rxPackets << ","
<< metrics.txPackets << std::endl;
}
outFile.close();
std::cout << "========================================" << std::endl;
std::cout << "Results written to: " << outputFile << std::endl;
std::cout << "========================================\n" << std::endl;
return 0;
}4444GGGGGGGGG
/*
* 4G LTE Network Performance Analysis: Throughput and Delay
* NS-3 Simulation for 1-10 Nodes
* Measures: Throughput, End-to-End Delay, Packet Loss, Jitter
* 4G LTE features: Higher bandwidth, lower latency, better spectral efficiency
*/
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/lte-module.h"
#include "ns3/config-store-module.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/netanim-module.h"
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>
using namespace ns3;
NS_LOG_COMPONENT_DEFINE("4GNetworkPerformance");
// Performance metrics structure
struct PerformanceMetrics {
uint32_t numNodes;
double throughput;
double avgDelay;
double packetLoss;
double jitter;
double rxPackets;
double txPackets;
double avgSinr;
};
std::vector<PerformanceMetrics> allMetrics;
// Run simulation for specific number of nodes
void RunSimulation(uint32_t numNodes, uint32_t bandwidth, double frequency, double simTime) {
NS_LOG_INFO("Running 4G LTE simulation with " << numNodes << " nodes");
// Create LTE Helper
Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper>();
lteHelper->SetEpcHelper(epcHelper);
// Configure 4G LTE parameters
// 4G LTE uses OFDMA and has better spectral efficiency than 3G
lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisPropagationLossModel"));
// Set LTE bandwidth (in Resource Blocks)
// 4G LTE: 6 RBs = 1.4 MHz, 15 RBs = 3 MHz, 25 RBs = 5 MHz,
// 50 RBs = 10 MHz, 75 RBs = 15 MHz, 100 RBs = 20 MHz
lteHelper->SetEnbDeviceAttribute("DlBandwidth", UintegerValue(bandwidth));
lteHelper->SetEnbDeviceAttribute("UlBandwidth", UintegerValue(bandwidth));
// Set frequency (EARFCN - E-UTRA Absolute Radio Frequency Channel Number)
// Common 4G bands: 700 MHz (Band 12/13/17), 850 MHz (Band 5),
// 1800 MHz (Band 3), 2100 MHz (Band 1), 2600 MHz (Band 7)
lteHelper->SetEnbDeviceAttribute("DlEarfcn", UintegerValue(frequency));
lteHelper->SetEnbDeviceAttribute("UlEarfcn", UintegerValue(frequency + 18000));
// Configure eNodeB antenna parameters
lteHelper->SetEnbAntennaModelType("ns3::IsotropicAntennaModel");
// Configure scheduler (Proportional Fair for better fairness)
lteHelper->SetSchedulerType("ns3::PfFfMacScheduler");
// Get PGW node
Ptr<Node> pgw = epcHelper->GetPgwNode();
// Create remote host
NodeContainer remoteHostContainer;
remoteHostContainer.Create(1);
Ptr<Node> remoteHost = remoteHostContainer.Get(0);
InternetStackHelper internet;
internet.Install(remoteHostContainer);
// Connect remote host to PGW with high-speed link
PointToPointHelper p2ph;
p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s")));
p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500));
p2ph.SetChannelAttribute("Delay", TimeValue(MilliSeconds(1))); // Low latency for 4G
NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost);
// Assign IP addresses
Ipv4AddressHelper ipv4h;
ipv4h.SetBase("1.0.0.0", "255.0.0.0");
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices);
// Set up routing
Ipv4StaticRoutingHelper ipv4RoutingHelper;
Ptr<Ipv4StaticRouting> remoteHostStaticRouting =
ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>());
remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
// Create eNodeB
NodeContainer enbNodes;
enbNodes.Create(1);
// Create UE nodes
NodeContainer ueNodes;
ueNodes.Create(numNodes);
// Install mobility model for eNodeB (fixed position)
MobilityHelper enbMobility;
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
positionAlloc->Add(Vector(0.0, 0.0, 30.0)); // 30m height for eNodeB
enbMobility.SetPositionAllocator(positionAlloc);
enbMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
enbMobility.Install(enbNodes);
// Install mobility model for UEs (distributed in coverage area)
MobilityHelper ueMobility;
ueMobility.SetPositionAllocator("ns3::UniformDiscPositionAllocator",
"X", DoubleValue(0.0),
"Y", DoubleValue(0.0),
"rho", DoubleValue(100.0)); // 100m radius
ueMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
ueMobility.Install(ueNodes);
// Install LTE devices
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice(enbNodes);
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice(ueNodes);
// Install Internet stack on UEs
internet.Install(ueNodes);
// Assign IP addresses to UEs
Ipv4InterfaceContainer ueIpIface;
ueIpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueLteDevs));
// Set default gateway for UEs
for (uint32_t u = 0; u < ueNodes.GetN(); ++u) {
Ptr<Node> ueNode = ueNodes.Get(u);
Ptr<Ipv4StaticRouting> ueStaticRouting =
ipv4RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv4>());
ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
}
// Attach UEs to eNodeB
lteHelper->Attach(ueLteDevs);
// Install applications
uint16_t dlPort = 1234;
uint16_t ulPort = 2000;
ApplicationContainer clientApps;
ApplicationContainer serverApps;
// Downlink: Remote host to UEs (typical for video streaming, web browsing)
for (uint32_t u = 0; u < ueNodes.GetN(); ++u) {
PacketSinkHelper dlPacketSinkHelper("ns3::UdpSocketFactory",
InetSocketAddress(Ipv4Address::GetAny(), dlPort));
serverApps.Add(dlPacketSinkHelper.Install(ueNodes.Get(u)));
UdpClientHelper dlClient(ueIpIface.GetAddress(u), dlPort);
dlClient.SetAttribute("Interval", TimeValue(MilliSeconds(5))); // Higher rate for 4G
dlClient.SetAttribute("MaxPackets", UintegerValue(1000000));
dlClient.SetAttribute("PacketSize", UintegerValue(1400)); // Larger packets for 4G
clientApps.Add(dlClient.Install(remoteHost));
}
// Uplink: UEs to Remote host (typical for uploads, video calls)
PacketSinkHelper ulPacketSinkHelper("ns3::UdpSocketFactory",
InetSocketAddress(Ipv4Address::GetAny(), ulPort));
serverApps.Add(ulPacketSinkHelper.Install(remoteHost));
for (uint32_t u = 0; u < ueNodes.GetN(); ++u) {
UdpClientHelper ulClient(internetIpIfaces.GetAddress(1), ulPort);
ulClient.SetAttribute("Interval", TimeValue(MilliSeconds(5)));
ulClient.SetAttribute("MaxPackets", UintegerValue(1000000));
ulClient.SetAttribute("PacketSize", UintegerValue(1400));
clientApps.Add(ulClient.Install(ueNodes.Get(u)));
}
serverApps.Start(Seconds(0.1));
clientApps.Start(Seconds(0.5));
serverApps.Stop(Seconds(simTime));
clientApps.Stop(Seconds(simTime - 0.1));
// Enable LTE traces for detailed analysis
lteHelper->EnableTraces();
// --- NETANIM CONFIGURATION ---
// 2. Create the AnimationInterface object
AnimationInterface anim("4g-simulation.xml");
// 3. Optional: Color the Base Station (Red)
anim.UpdateNodeDescription(enbNodes.Get(0), "eNodeB (4G BS)");
anim.UpdateNodeColor(enbNodes.Get(0), 255, 0, 0);
// 4. Optional: Color the Remote Host (Green)
anim.UpdateNodeDescription(remoteHost, "Remote Server");
anim.UpdateNodeColor(remoteHost, 0, 255, 0);
// 5. Optional: Color and Label UEs (Blue)
for (uint32_t i = 0; i < ueNodes.GetN(); ++i) {
anim.UpdateNodeDescription(ueNodes.Get(i), "User_" + std::to_string(i));
anim.UpdateNodeColor(ueNodes.Get(i), 0, 0, 255);
}
// 6. Enable Packet Metadata (allows you to see IP/UDP details in NetAnim)
anim.EnablePacketMetadata(true);
// Install FlowMonitor
FlowMonitorHelper flowmon;
Ptr<FlowMonitor> monitor = flowmon.InstallAll();
// Run simulation
Simulator::Stop(Seconds(simTime));
Simulator::Run();
// Calculate metrics using FlowMonitor
monitor->CheckForLostPackets();
Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier());
std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats();
double totalThroughput = 0.0;
double totalAvgDelay = 0.0;
double totalPacketLoss = 0.0;
double totalJitter = 0.0;
uint32_t flowCount = 0;
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
i != stats.end(); ++i) {
Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first);
if (i->second.rxPackets > 0) {
double throughput = i->second.rxBytes * 8.0 /
(i->second.timeLastRxPacket.GetSeconds() -
i->second.timeFirstTxPacket.GetSeconds()) / 1024 / 1024;
double avgDelay = i->second.delaySum.GetMilliSeconds() / i->second.rxPackets;
double packetLoss = (i->second.txPackets - i->second.rxPackets) * 100.0 /
i->second.txPackets;
double jitter = i->second.jitterSum.GetMilliSeconds() / i->second.rxPackets;
totalThroughput += throughput;
totalAvgDelay += avgDelay;
totalPacketLoss += packetLoss;
totalJitter += jitter;
flowCount++;
NS_LOG_INFO("Flow " << i->first << " (" << t.sourceAddress
<< " -> " << t.destinationAddress << ")");
NS_LOG_INFO(" Throughput: " << throughput << " Mbps");
NS_LOG_INFO(" Avg Delay: " << avgDelay << " ms");
NS_LOG_INFO(" Packet Loss: " << packetLoss << " %");
NS_LOG_INFO(" Jitter: " << jitter << " ms");
}
}
// Store metrics
PerformanceMetrics metrics;
metrics.numNodes = numNodes;
metrics.throughput = totalThroughput;
metrics.avgDelay = flowCount > 0 ? totalAvgDelay / flowCount : 0;
metrics.packetLoss = flowCount > 0 ? totalPacketLoss / flowCount : 0;
metrics.jitter = flowCount > 0 ? totalJitter / flowCount : 0;
metrics.rxPackets = 0;
metrics.txPackets = 0;
metrics.avgSinr = 0; // Can be calculated from PHY traces
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin();
i != stats.end(); ++i) {
metrics.rxPackets += i->second.rxPackets;
metrics.txPackets += i->second.txPackets;
}
allMetrics.push_back(metrics);
Simulator::Destroy();
}
int main(int argc, char *argv[]) {
// 4G LTE Simulation parameters
uint32_t bandwidth = 100; // Resource blocks (100 RBs = 20 MHz for 4G LTE)
double frequency = 2100; // Carrier frequency (EARFCN for Band 1 - 2100 MHz)
double simTime = 10.0; // Simulation time in seconds
uint32_t minNodes = 1;
uint32_t maxNodes = 10;
std::string outputFile = "4g_performance_results.csv";
// Parse command line arguments
CommandLine cmd;
cmd.AddValue("bandwidth", "Bandwidth in resource blocks (100 = 20MHz)", bandwidth);
cmd.AddValue("frequency", "Carrier frequency (EARFCN)", frequency);
cmd.AddValue("simTime", "Simulation time in seconds", simTime);
cmd.AddValue("minNodes", "Minimum number of nodes", minNodes);
cmd.AddValue("maxNodes", "Maximum number of nodes", maxNodes);
cmd.AddValue("outputFile", "Output CSV file name", outputFile);
cmd.Parse(argc, argv);
// Enable logging
LogComponentEnable("4GNetworkPerformance", LOG_LEVEL_INFO);
std::cout << "\n========================================" << std::endl;
std::cout << "4G LTE Network Performance Simulation" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << "Bandwidth: " << bandwidth << " RBs (~"
<< (bandwidth * 0.2) << " MHz)" << std::endl;
std::cout << "Frequency: " << frequency << " MHz (EARFCN)" << std::endl;
std::cout << "Simulation Time: " << simTime << " seconds" << std::endl;
std::cout << "Node Range: " << minNodes << " to " << maxNodes << std::endl;
std::cout << "Expected Peak Rate: ~" << (bandwidth * 0.2 * 5) << " Mbps (4G LTE)" << std::endl;
std::cout << "========================================\n" << std::endl;
// Run simulations for different node counts
for (uint32_t numNodes = minNodes; numNodes <= maxNodes; numNodes++) {
std::cout << "\n--- Simulating with " << numNodes << " node(s) ---" << std::endl;
RunSimulation(numNodes, bandwidth, frequency, simTime);
}
// Write results to CSV file
std::ofstream outFile(outputFile);
outFile << "Nodes,Throughput(Mbps),AvgDelay(ms),PacketLoss(%),Jitter(ms),RxPackets,TxPackets"
<< std::endl;
std::cout << "\n========================================" << std::endl;
std::cout << "4G LTE Simulation Results Summary" << std::endl;
std::cout << "========================================" << std::endl;
std::cout << "Nodes\tThroughput\tAvg Delay\tPacket Loss\tJitter\t\tRx Pkts\tTx Pkts" << std::endl;
std::cout << "\t(Mbps)\t\t(ms)\t\t(%)\t\t(ms)" << std::endl;
std::cout << "--------------------------------------------------------------------------------"
<< std::endl;
for (const auto& metrics : allMetrics) {
std::cout << metrics.numNodes << "\t"
<< std::fixed << std::setprecision(2) << metrics.throughput << "\t\t"
<< metrics.avgDelay << "\t\t"
<< metrics.packetLoss << "\t\t"
<< metrics.jitter << "\t\t"
<< metrics.rxPackets << "\t"
<< metrics.txPackets << std::endl;
outFile << metrics.numNodes << ","
<< metrics.throughput << ","
<< metrics.avgDelay << ","
<< metrics.packetLoss << ","
<< metrics.jitter << ","
<< metrics.rxPackets << ","
<< metrics.txPackets << std::endl;
}
outFile.close();
std::cout << "========================================" << std::endl;
std::cout << "Results written to: " << outputFile << std::endl;
std::cout << "\n4G LTE Key Features Simulated:" << std::endl;
std::cout << " - OFDMA for downlink (better spectral efficiency)" << std::endl;
std::cout << " - SC-FDMA for uplink (lower power consumption)" << std::endl;
std::cout << " - Proportional Fair scheduling (better fairness)" << std::endl;
std::cout << " - Higher bandwidth (up to 20 MHz)" << std::endl;
std::cout << " - Lower latency (~10-30 ms typical)" << std::endl;
std::cout << " - Peak data rates: ~100 Mbps DL, ~50 Mbps UL" << std::endl;
std::cout << "========================================\n" << std::endl;
return 0;
}55555555555GGGGGGGGGG
/*
* Simple 5G Network Simulation for Students
*
* Network Topology:
* Internet Server ←→ 5G Core ←→ 5G Base Station ←→ Mobile Phones
*
* - How 5G network works
* - Difference between 5G and 4G
* - Basic network performance metrics
*
*/
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/lte-module.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/netanim-module.h"
using namespace ns3;
int main(int argc, char *argv[])
{
// ==========================================
// STEP 1: Configure Simulation Parameters
// ==========================================
// How many mobile phones (User Equipment)?
uint32_t numberOfPhones = 5;
// How long to run simulation (in seconds)?
double simulationTime = 10.0;
// Enable packet metadata for NetAnim
PacketMetadata::Enable();
std::cout << "\n=====================================" << std::endl;
std::cout << " Simple 5G Network Simulation" << std::endl;
std::cout << "=====================================" << std::endl;
std::cout << "Number of phones: " << numberOfPhones << std::endl;
std::cout << "Simulation time: " << simulationTime << " seconds" << std::endl;
std::cout << "=====================================\n" << std::endl;
// ==========================================
// STEP 2: Create the 5G Network
// ==========================================
// Create LTE/5G helper (LTE module can simulate 5G-like performance)
Ptr<LteHelper> lteHelper = CreateObject<LteHelper>();
Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper>();
lteHelper->SetEpcHelper(epcHelper);
// Configure for 5G-like performance
// Higher bandwidth = faster speeds
lteHelper->SetEnbDeviceAttribute("DlBandwidth", UintegerValue(100)); // 20 MHz
lteHelper->SetEnbDeviceAttribute("UlBandwidth", UintegerValue(100));
// Get the 5G Core network gateway
Ptr<Node> fiveGCore = epcHelper->GetPgwNode();
// ==========================================
// STEP 3: Create Internet Server
// ==========================================
NodeContainer internetServer;
internetServer.Create(1);
// Install Internet protocol
InternetStackHelper internet;
internet.Install(internetServer);
// Connect Internet Server to 5G Core with fiber optic cable
PointToPointHelper fiberCable;
fiberCable.SetDeviceAttribute("DataRate", StringValue("10Gbps")); // Very fast!
fiberCable.SetChannelAttribute("Delay", StringValue("1ms")); // Very low delay!
NetDeviceContainer fiberLink = fiberCable.Install(fiveGCore, internetServer.Get(0));
// Assign IP addresses
Ipv4AddressHelper ipv4;
ipv4.SetBase("1.0.0.0", "255.0.0.0");
Ipv4InterfaceContainer internetIpAddress = ipv4.Assign(fiberLink);
// Setup routing
Ipv4StaticRoutingHelper routing;
Ptr<Ipv4StaticRouting> serverRouting =
routing.GetStaticRouting(internetServer.Get(0)->GetObject<Ipv4>());
serverRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1);
// ==========================================
// STEP 4: Create 5G Base Station (gNB)
// ==========================================
NodeContainer baseStation;
baseStation.Create(1);
// Position base station in one place
MobilityHelper baseMobility;
baseMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
Ptr<ListPositionAllocator> basePosition = CreateObject<ListPositionAllocator>();
basePosition->Add(Vector(0.0, 0.0, 25.0)); // At center, 25 meters high
baseMobility.SetPositionAllocator(basePosition);
baseMobility.Install(baseStation);
// ==========================================
// STEP 5: Create Mobile Phones (UEs)
// ==========================================
NodeContainer mobilePhones;
mobilePhones.Create(numberOfPhones);
// Position phones in a circle around base station
MobilityHelper phoneMobility;
phoneMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
phoneMobility.Install(mobilePhones);
// Arrange phones in circle (like students sitting around teacher)
double radius = 50.0; // 50 meters from base station
for (uint32_t i = 0; i < mobilePhones.GetN(); i++)
{
double angle = (360.0 / numberOfPhones) * i * (3.14159 / 180.0);
double x = radius * cos(angle);
double y = radius * sin(angle);
Ptr<MobilityModel> mobility = mobilePhones.Get(i)->GetObject<MobilityModel>();
mobility->SetPosition(Vector(x, y, 1.5)); // 1.5 meters high (hand level)
}
// ==========================================
// STEP 6: Install 5G Equipment
// ==========================================
// Install 5G on base station and phones
NetDeviceContainer baseDevice = lteHelper->InstallEnbDevice(baseStation);
NetDeviceContainer phoneDevices = lteHelper->InstallUeDevice(mobilePhones);
// Give phones Internet capability
internet.Install(mobilePhones);
// Assign IP addresses to phones
Ipv4InterfaceContainer phoneIpAddresses =
epcHelper->AssignUeIpv4Address(NetDeviceContainer(phoneDevices));
// Set default gateway for phones
for (uint32_t i = 0; i < mobilePhones.GetN(); i++)
{
Ptr<Ipv4StaticRouting> phoneRouting =
routing.GetStaticRouting(mobilePhones.Get(i)->GetObject<Ipv4>());
phoneRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1);
}
// Connect phones to base station
lteHelper->Attach(phoneDevices);
// ==========================================
// STEP 7: Create Network Traffic (Video Streaming)
// ==========================================
uint16_t port = 9;
// Install video receiver on each phone
ApplicationContainer phoneApps;
for (uint32_t i = 0; i < mobilePhones.GetN(); i++)
{
PacketSinkHelper receiver("ns3::UdpSocketFactory",
InetSocketAddress(Ipv4Address::GetAny(), port));
phoneApps.Add(receiver.Install(mobilePhones.Get(i)));
}
// Install video sender on Internet server
ApplicationContainer serverApps;
for (uint32_t i = 0; i < mobilePhones.GetN(); i++)
{
UdpClientHelper sender(phoneIpAddresses.GetAddress(i), port);
sender.SetAttribute("MaxPackets", UintegerValue(10000));
sender.SetAttribute("Interval", TimeValue(MilliSeconds(10))); // Send every 10ms
sender.SetAttribute("PacketSize", UintegerValue(1024)); // 1KB packets
serverApps.Add(sender.Install(internetServer.Get(0)));
}
// Start applications
phoneApps.Start(Seconds(1.0));
serverApps.Start(Seconds(1.0));
phoneApps.Stop(Seconds(simulationTime));
serverApps.Stop(Seconds(simulationTime));
// ==========================================
// STEP 8: Setup NetAnim Visualization
// ==========================================
AnimationInterface anim("simple_5g_network.xml");
// Label each node
anim.UpdateNodeDescription(internetServer.Get(0), "Internet Server");
anim.UpdateNodeDescription(fiveGCore, "5G Core Network");
anim.UpdateNodeDescription(baseStation.Get(0), "5G Base Station");
for (uint32_t i = 0; i < mobilePhones.GetN(); i++)
{
char label[50];
sprintf(label, "Phone %d", i + 1);
anim.UpdateNodeDescription(mobilePhones.Get(i), label);
}
// Set colors
anim.UpdateNodeColor(internetServer.Get(0), 0, 0, 255); // Blue
anim.UpdateNodeColor(fiveGCore, 0, 255, 0); // Green
anim.UpdateNodeColor(baseStation.Get(0), 255, 0, 255); // Magenta (5G color!)
for (uint32_t i = 0; i < mobilePhones.GetN(); i++)
{
anim.UpdateNodeColor(mobilePhones.Get(i), 255, 215, 0); // Gold
}
// Set node sizes
anim.UpdateNodeSize(internetServer.Get(0)->GetId(), 6.0, 6.0);
anim.UpdateNodeSize(fiveGCore->GetId(), 6.0, 6.0);
anim.UpdateNodeSize(baseStation.Get(0)->GetId(), 10.0, 10.0); // Biggest!
for (uint32_t i = 0; i < mobilePhones.GetN(); i++)
{
anim.UpdateNodeSize(mobilePhones.Get(i)->GetId(), 4.0, 4.0);
}
// Set positions for NetAnim
anim.SetConstantPosition(internetServer.Get(0), 200.0, 50.0);
anim.SetConstantPosition(fiveGCore, 150.0, 50.0);
anim.SetConstantPosition(baseStation.Get(0), 75.0, 50.0);
for (uint32_t i = 0; i < mobilePhones.GetN(); i++)
{
double angle = (360.0 / numberOfPhones) * i * (3.14159 / 180.0);
double x = 75.0 + 30.0 * cos(angle);
double y = 50.0 + 30.0 * sin(angle);
anim.SetConstantPosition(mobilePhones.Get(i), x, y);
}
// Enable packet animation
anim.EnablePacketMetadata(true);
// ==========================================
// STEP 9: Measure Performance
// ==========================================
FlowMonitorHelper flowMonitor;
Ptr<FlowMonitor> monitor = flowMonitor.InstallAll();
// ==========================================
// STEP 10: Run Simulation
// ==========================================
std::cout << "Starting simulation..." << std::endl;
Simulator::Stop(Seconds(simulationTime));
Simulator::Run();
std::cout << "Simulation finished!" << std::endl;
// ==========================================
// STEP 11: Show Results
// ==========================================
monitor->CheckForLostPackets();
Ptr<Ipv4FlowClassifier> classifier =
DynamicCast<Ipv4FlowClassifier>(flowMonitor.GetClassifier());
std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats();
double totalThroughput = 0.0;
double totalDelay = 0.0;
int flowCount = 0;
for (auto i = stats.begin(); i != stats.end(); ++i)
{
if (i->second.rxPackets > 0)
{
double throughput = i->second.rxBytes * 8.0 / simulationTime / 1000000.0; // Mbps
double delay = i->second.delaySum.GetMilliSeconds() / i->second.rxPackets;
totalThroughput += throughput;
totalDelay += delay;
flowCount++;
}
}
std::cout << "\n=====================================" << std::endl;
std::cout << " 5G Network Results" << std::endl;
std::cout << "=====================================" << std::endl;
std::cout << "Total Speed: " << totalThroughput << " Mbps" << std::endl;
std::cout << "Average Delay: " << (totalDelay / flowCount) << " ms" << std::endl;
std::cout << "=====================================\n" << std::endl;
std::cout << "✓ NetAnim file created: simple_5g_network.xml" << std::endl;
Simulator::Destroy();
return 0;
}