```cpp= /* * Copyright (c) 2011-2018 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: Jaume Nin <jaume.nin@cttc.cat> * Manuel Requena <manuel.requena@cttc.es> * Modify: Pengyu Liu <eic_lpy@hust.edu.cn> * Hao Yin <haoyin@uw.edu> * Muyuan Shen <muyuan_shen@hust.edu.cn> */ #include "ns3/applications-module.h" #include "ns3/config-store-module.h" #include "ns3/core-module.h" #include "ns3/flow-monitor-module.h" #include "ns3/internet-module.h" #include "ns3/lte-module.h" #include "ns3/mobility-module.h" #include "ns3/point-to-point-module.h" #include "ns3/lte-ue-phy.h" #include "ns3/lte-ue-net-device.h" #include "ns3/lte-helper.h" #include "ns3/log.h" #include "ns3/network-module.h" using namespace ns3; using namespace std; NS_LOG_COMPONENT_DEFINE("LenaSimpleEpc"); void NotifyConnectionEstablishedUe(std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti) { std::cout << context << " UE IMSI " << imsi << ": connected to CellId " << cellid << " with RNTI " << rnti << std::endl; } void NotifyHandoverStartUe(std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti, uint16_t targetCellId) { std::cout << context << " UE IMSI " << imsi << ": previously connected to CellId " << cellid << " with RNTI " << rnti << ", doing handover to CellId " << targetCellId << std::endl; } void NotifyHandoverEndOkUe(std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti) { std::cout << context << " UE IMSI " << imsi << ": successful handover to CellId " << cellid << " with RNTI " << rnti << std::endl; } void NotifyConnectionEstablishedEnb(std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti) { std::cout << context << " eNB CellId " << cellid << ": successful connection of UE with IMSI " << imsi << " RNTI " << rnti << std::endl; } void NotifyHandoverStartEnb(std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti, uint16_t targetCellId) { std::cout << context << " eNB CellId " << cellid << ": start handover of UE with IMSI " << imsi << " RNTI " << rnti << " to CellId " << targetCellId << std::endl; } void NotifyHandoverEndOkEnb(std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti) { std::cout << context << " eNB CellId " << cellid << ": completed handover of UE with IMSI " << imsi << " RNTI " << rnti << std::endl; } void UePhyMeasurementsCallback(uint16_t cellId, uint16_t rnti, double rsrp, double rsrq, uint8_t componentCarrierId) { std::cout << "Cell ID: " << cellId << ", RNTI: " << rnti << ", RSRP: " << rsrp << " dBm, RSRQ: " << rsrq << " dB, Component Carrier ID: " << (unsigned int)componentCarrierId << std::endl; } int main(int argc, char* argv[]) { // LogComponentEnable ("MyRrMacScheduler", LOG_LEVEL_INFO); //LogComponentEnable("LteUeRrc", LOG_LEVEL_INFO); LogComponentEnable("LteUePhy", LOG_LEVEL_INFO); uint16_t m_nUser = 1; uint16_t numberOfEnbs = 3; uint16_t numBearersPerUe = 0; // although this speed is meaningless in reality, it has to be large to make CQI change double speed = 50000; string datarate = "20Mbps"; uint32_t packetSize = 1200; // Set the simulation time double simTime = 3.0; Config::SetDefault("ns3::UdpClient::Interval", TimeValue(MilliSeconds(10))); Config::SetDefault("ns3::UdpClient::MaxPackets", UintegerValue(1000000)); Config::SetDefault("ns3::LteHelper::UseIdealRrc", BooleanValue(true)); // Command line arguments CommandLine cmd; cmd.AddValue("simTime", "Total duration of the simulation [s])", simTime); cmd.AddValue("datarate", "datarate", datarate); cmd.AddValue("packetSize", "packetSize", packetSize); cmd.AddValue("speed", "x-axis speed of moving UE", speed); cmd.Parse(argc, argv); ConfigStore inputConfig; inputConfig.ConfigureDefaults(); // parse again so you can override default values from the command line cmd.Parse(argc, argv); RngSeedManager::SetSeed(6); RngSeedManager::SetRun(4); Ptr<LteHelper> lteHelper = CreateObject<LteHelper>(); Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper>(); lteHelper->SetEpcHelper(epcHelper); lteHelper->SetSchedulerType("ns3::MyRrMacScheduler"); lteHelper->SetAttribute("PathlossModel", StringValue("ns3::FriisSpectrumPropagationLossModel")); lteHelper->SetHandoverAlgorithmType("ns3::A2A4RsrqHandoverAlgorithm"); lteHelper->SetHandoverAlgorithmAttribute("ServingCellThreshold", UintegerValue(30)); lteHelper->SetHandoverAlgorithmAttribute("NeighbourCellOffset", UintegerValue(2)); Ptr<Node> pgw = epcHelper->GetPgwNode(); // Create a single RemoteHost NodeContainer remoteHostContainer; remoteHostContainer.Create(1); Ptr<Node> remoteHost = remoteHostContainer.Get(0); InternetStackHelper internet; internet.Install(remoteHostContainer); // Create the Internet PointToPointHelper p2ph; p2ph.SetDeviceAttribute("DataRate", DataRateValue(DataRate("100Gb/s"))); p2ph.SetDeviceAttribute("Mtu", UintegerValue(1500)); p2ph.SetChannelAttribute("Delay", TimeValue(MilliSeconds(10))); NetDeviceContainer internetDevices = p2ph.Install(pgw, remoteHost); Ipv4AddressHelper ipv4h; ipv4h.SetBase("1.0.0.0", "255.0.0.0"); Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign(internetDevices); Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress(1); // interface 0 is localhost, 1 is the p2p device // Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1); Ipv4StaticRoutingHelper ipv4RoutingHelper; Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting(remoteHost->GetObject<Ipv4>()); remoteHostStaticRouting->AddNetworkRouteTo(Ipv4Address("7.0.0.0"), Ipv4Mask("255.0.0.0"), 1); NodeContainer ueNodes; NodeContainer enbNodes; enbNodes.Create(numberOfEnbs); ueNodes.Create(m_nUser); // Install Mobility Model Ptr<ListPositionAllocator> enbPositionAlloc = CreateObject<ListPositionAllocator>(); Ptr<ListPositionAllocator> uePositionAlloc = CreateObject<ListPositionAllocator>(); enbPositionAlloc->Add(Vector(0, 0, 25)); enbPositionAlloc->Add(Vector(10000, 0, 25)); //enb #2 enbPositionAlloc->Add(Vector(-10000, 0, 25)); //enb #3 uePositionAlloc->Add(Vector(-15000, 8000, 1.5)); // the moving ue //uePositionAlloc->Add(Vector(10000, 10000, 1.5)); // stable ue #1 //uePositionAlloc->Add(Vector(-10000, 10000, 1.5)); // stable ue #2 //uePositionAlloc->Add(Vector(-10000, -10000, 1.5)); // stable ue #3 //uePositionAlloc->Add(Vector(10000, -10000, 1.5)); // stable ue #4 MobilityHelper enbMobility; enbMobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); enbMobility.SetPositionAllocator(enbPositionAlloc); enbMobility.Install(enbNodes); MobilityHelper ueMobility; ueMobility.SetMobilityModel("ns3::ConstantVelocityMobilityModel"); ueMobility.SetPositionAllocator(uePositionAlloc); ueMobility.Install(ueNodes); /* MobilityHelper mobility; mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel"); mobility.SetPositionAllocator(enbPositionAlloc); mobility.Install(enbNodes); mobility.SetMobilityModel("ns3::ConstantVelocityMobilityModel"); mobility.SetPositionAllocator(uePositionAlloc); mobility.Install(ueNodes); ```*/ // set speed for the moving ue Vector sp(speed, 0, 0); ueNodes.Get(0)->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(sp); // Install LTE Devices to the nodes NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice(enbNodes); NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice(ueNodes); Ptr<LteEnbNetDevice> lteEnbDev = enbLteDevs.Get(0)->GetObject<LteEnbNetDevice>(); Ptr<LteEnbPhy> enbPhy = lteEnbDev->GetPhy(); enbPhy->SetAttribute("TxPower", DoubleValue(30.0)); enbPhy->SetAttribute("NoiseFigure", DoubleValue(5.0)); // Install the IP stack on the UEs internet.Install(ueNodes); Ipv4InterfaceContainer ueIpIface; ueIpIface = epcHelper->AssignUeIpv4Address(NetDeviceContainer(ueLteDevs)); // Assign IP address to UEs, and install applications uint16_t dlPort = 10000; uint16_t ulPort = 20000; Ptr<UniformRandomVariable> startTimeSeconds = CreateObject<UniformRandomVariable>(); startTimeSeconds->SetAttribute("Min", DoubleValue(0)); startTimeSeconds->SetAttribute("Max", DoubleValue(0.010)); for (uint32_t u = 0; u < ueNodes.GetN(); ++u) { Ptr<Node> ueNode = ueNodes.Get(u); // Set the default gateway for the UE Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting(ueNode->GetObject<Ipv4>()); ueStaticRouting->SetDefaultRoute(epcHelper->GetUeDefaultGatewayAddress(), 1); //新增 for (uint32_t b = 0; b < numBearersPerUe; ++b) { ++dlPort; ++ulPort; ApplicationContainer clientApps; ApplicationContainer serverApps; NS_LOG_LOGIC("installing UDP DL app for UE " << u); UdpClientHelper dlClientHelper(ueIpIface.GetAddress(u), dlPort); clientApps.Add(dlClientHelper.Install(remoteHost)); PacketSinkHelper dlPacketSinkHelper("ns3::UdpSocketFactory", InetSocketAddress(Ipv4Address::GetAny(), dlPort)); serverApps.Add(dlPacketSinkHelper.Install(ueNode)); NS_LOG_LOGIC("installing UDP UL app for UE " << u); UdpClientHelper ulClientHelper(remoteHostAddr, ulPort); clientApps.Add(ulClientHelper.Install(ueNode)); PacketSinkHelper ulPacketSinkHelper("ns3::UdpSocketFactory", InetSocketAddress(Ipv4Address::GetAny(), ulPort)); serverApps.Add(ulPacketSinkHelper.Install(remoteHost)); Ptr<EpcTft> tft = Create<EpcTft>(); EpcTft::PacketFilter dlpf; dlpf.localPortStart = dlPort; dlpf.localPortEnd = dlPort; tft->Add(dlpf); EpcTft::PacketFilter ulpf; ulpf.remotePortStart = ulPort; ulpf.remotePortEnd = ulPort; tft->Add(ulpf); EpsBearer bearer(EpsBearer::NGBR_VIDEO_TCP_DEFAULT); lteHelper->ActivateDedicatedEpsBearer(ueLteDevs.Get(u), bearer, tft); Time startTime = Seconds(startTimeSeconds->GetValue()); serverApps.Start(startTime); clientApps.Start(startTime); } // end for b } enum EpsBearer::Qci q = EpsBearer::GBR_CONV_VOICE; EpsBearer bearer(q); // Attach the UEs to the eNB for (uint16_t i = 0; i < m_nUser; i++) { lteHelper->Attach(ueLteDevs.Get(i), enbLteDevs.Get(2)); // side effect: the default EPS bearer will be activated } NS_LOG_LOGIC("setting up applications"); // Install and start applications on UEs and remote host //建立連接 for (uint32_t u = 0; u < ueNodes.GetN(); ++u) { Ptr<NetDevice> ueDevice = ueLteDevs.Get(u); Ptr<LteUeNetDevice> ueLteDevice = ueDevice->GetObject<LteUeNetDevice>(); Ptr<LteUePhy> uePhy = ueLteDevice->GetPhy(); //uePhy->TraceConnectWithoutContext("ReportCurrentCellRsrpSinr", MakeCallback(&UePhyMeasurementsCallback)); } Time udpInterval = Time::FromDouble((packetSize * 8) / static_cast<double>(DataRate(datarate).GetBitRate()), Time::S); // Install and start applications on UEs and remote host //uint16_t dlPort = 1234; /*ApplicationContainer clientApps; ApplicationContainer serverApps; for (uint32_t u = 0; u < ueNodes.GetN(); ++u) { dlPort++; PacketSinkHelper dlPacketSinkHelper("ns3::UdpSocketFactory", InetSocketAddress(Ipv4Address::GetAny(), dlPort)); serverApps.Add(dlPacketSinkHelper.Install(ueNodes.Get(u))); UdpClientHelper dlClient(ueIpIface.GetAddress(u), dlPort); dlClient.SetAttribute("PacketSize", UintegerValue(packetSize)); dlClient.SetAttribute("Interval", TimeValue(udpInterval)); dlClient.SetAttribute("MaxPackets", UintegerValue(0xFFFFFFFF)); clientApps.Add(dlClient.Install(remoteHost)); } serverApps.Start(MilliSeconds(10)); clientApps.Start(MilliSeconds(10)); */ lteHelper->EnableTraces(); // Uncomment to enable PCAP tracing // p2ph.EnablePcapAll("lena-simple-epc"); // Add X2 interface lteHelper->AddX2Interface(enbNodes); //lteHelper->EnablePhyTraces(); //lteHelper->EnableMacTraces(); //lteHelper->EnablePdcpTraces(); Ptr<RadioBearerStatsCalculator> rlcStats = lteHelper->GetRlcStats(); rlcStats->SetAttribute("EpochDuration", TimeValue(Seconds(1.0))); Ptr<RadioBearerStatsCalculator> pdcpStats = lteHelper->GetPdcpStats(); pdcpStats->SetAttribute("EpochDuration", TimeValue(Seconds(1.0))); // connect custom trace sinks for RRC connection establishment and handover notification Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/ConnectionEstablished", MakeCallback(&NotifyConnectionEstablishedEnb)); Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/ConnectionEstablished", MakeCallback(&NotifyConnectionEstablishedUe)); Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverStart", MakeCallback(&NotifyHandoverStartEnb)); Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/HandoverStart", MakeCallback(&NotifyHandoverStartUe)); Config::Connect("/NodeList/*/DeviceList/*/LteEnbRrc/HandoverEndOk", MakeCallback(&NotifyHandoverEndOkEnb)); Config::Connect("/NodeList/*/DeviceList/*/LteUeRrc/HandoverEndOk", MakeCallback(&NotifyHandoverEndOkUe)); FlowMonitorHelper flowmon; Ptr<FlowMonitor> monitor = flowmon.InstallAll(); // flowmon.Install (enbNodes.Get (0)); rlcStats->SetAttribute("EpochDuration", TimeValue(Seconds(simTime))); //--------------------------------------------------- Simulator::Stop(Seconds(simTime)); Simulator::Run(); /*GtkConfigStore config; config.ConfigureAttributes();*/ cout << "Begin Simulation Results" << endl; monitor->CheckForLostPackets(); Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier()); map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats(); double Throughput = 0.0; for (map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin(); i != stats.end(); ++i) { Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(i->first); cout << "Flow ID: " << i->first << " Src Addr " << t.sourceAddress << " Dst Addr " << t.destinationAddress << endl; cout << "Tx Packets = " << i->second.txPackets << endl; cout << "Rx Packets = " << i->second.rxPackets << endl; Throughput = i->second.rxBytes * 8.0 / (i->second.timeLastRxPacket.GetSeconds() - i->second.timeFirstTxPacket.GetSeconds()) / 1024; cout << "Throughput: " << Throughput << " Kbps" << endl; } NS_LOG_UNCOND("Done"); cout << "End Simulation Results" << endl; Simulator::Destroy(); return 0; } ```