```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;
}
```