相比较上一篇含有EPC网络的LTE仿真程序,本文又增加了基于X2接口的内部切换仿真流程。下面将是这样的网络拓扑:
一个UE,两个eNB,一个作为源基站,一个作为切换基站
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/lte-module.h"
#include "ns3/applications-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/config-store-module.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("LenaX2HandoverExample");
//Define Trace sinks function
void
NotifyConnectionEstablishedUe (std::string context,
uint64_t imsi,
uint16_t cellid,
uint16_t rnti)
{
std::cout << Simulator::Now ().GetSeconds () << " " << 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 << Simulator::Now ().GetSeconds () << " " << 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 << Simulator::Now ().GetSeconds () << " " << 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 << Simulator::Now ().GetSeconds () << " " << 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 << Simulator::Now ().GetSeconds () << " " << 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 << Simulator::Now ().GetSeconds () << " " << context
<< " eNB CellId " << cellid
<< ": completed handover of UE with IMSI " << imsi
<< " RNTI " << rnti
<< std::endl;
}
/**
* Sample simulation script for a X2-based handover.
* It instantiates two eNodeB, attaches one UE to the 'source' eNB and
* triggers a handover of the UE towards the 'target' eNB.
*/
int
main (int argc, char *argv[])
{
// LogLevel logLevel = (LogLevel)(LOG_PREFIX_FUNC | LOG_PREFIX_TIME | LOG_LEVEL_ALL);
// LogComponentEnable ("LteHelper", logLevel);
// LogComponentEnable ("EpcHelper", logLevel);
// LogComponentEnable ("EpcEnbApplication", logLevel);
// LogComponentEnable ("EpcX2", logLevel);
// LogComponentEnable ("EpcSgwPgwApplication", logLevel);
// LogComponentEnable ("LteEnbRrc", logLevel);
// LogComponentEnable ("LteEnbNetDevice", logLevel);
// LogComponentEnable ("LteUeRrc", logLevel);
// LogComponentEnable ("LteUeNetDevice", logLevel);
uint16_t numberOfUes = 1;
uint16_t numberOfEnbs = 2;
uint16_t numBearersPerUe = 2;
double simTime = 0.300;
double distance = 100.0;
// change some default attributes so that they are reasonable for
// this scenario, but do this before processing command line
// arguments, so that the user is allowed to override these settings
Config::SetDefault ("ns3::UdpClient::Interval", TimeValue (MilliSeconds (10)));
Config::SetDefault ("ns3::UdpClient::MaxPackets", UintegerValue (1000000));
Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (false));
// Command line arguments
CommandLine cmd;
cmd.AddValue ("numberOfUes", "Number of UEs", numberOfUes);
cmd.AddValue ("numberOfEnbs", "Number of eNodeBs", numberOfEnbs);
cmd.AddValue ("simTime", "Total duration of the simulation (in seconds)", simTime);
cmd.Parse (argc, argv);
Ptr lteHelper = CreateObject ();
Ptr epcHelper = CreateObject ();
lteHelper->SetEpcHelper (epcHelper);//告诉lte 含有epc
lteHelper->SetSchedulerType ("ns3::RrFfMacScheduler");
lteHelper->SetHandoverAlgorithmType ("ns3::NoOpHandoverAlgorithm"); // disable automatic handover,选择切换算法,A2A4RsrpHandoverAlgorithm A3RsrpHandoverAlgorithm
//epcHelper自动创建和配置PGW,下面取出PGW
Ptr pgw = epcHelper->GetPgwNode ();
// Create a single RemoteHost
NodeContainer remoteHostContainer;
remoteHostContainer.Create (1);
Ptr 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 (Seconds (0.010)));
NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);//在remoteHost pgw安装P2P设备
Ipv4AddressHelper ipv4h;
ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);//为 remoteHostStaticRouting pgw分配IP
Ipv4Address remoteHostAddr = internetIpIfaces.GetAddress (1);//取得remotehost IP
// Routing of the Internet Host (towards the LTE network)
Ipv4StaticRoutingHelper ipv4RoutingHelper;
Ptr remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ());
// interface 0 is localhost, 1 is the p2p device
remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);//UE默认在网络7.0.0.0
//创建LTE接入网节点
NodeContainer ueNodes;
NodeContainer enbNodes;
enbNodes.Create (numberOfEnbs);
ueNodes.Create (numberOfUes);
// Install Mobility Model
Ptr positionAlloc = CreateObject ();
for (uint16_t i = 0; i < numberOfEnbs; i++)
{
positionAlloc->Add (Vector (distance * 2 * i - distance, 0, 0));//enb初始位置(distance*2i-distance,0,0)
}
for (uint16_t i = 0; i < numberOfUes; i++)
{
positionAlloc->Add (Vector (0, 0, 0));//UE初始位置(0,0,0)
}
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.SetPositionAllocator (positionAlloc);
mobility.Install (enbNodes);
mobility.Install (ueNodes);
// Install LTE Devices in eNB and UEs
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes);
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes);
// Install the IP stack on the UEs
internet.Install (ueNodes);
Ipv4InterfaceContainer ueIpIfaces;
ueIpIfaces = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevs));
//建立网关在下面循环里
// Attach all UEs to the first eNodeB
for (uint16_t i = 0; i < numberOfUes; i++)
{
lteHelper->Attach (ueLteDevs.Get (i), enbLteDevs.Get (0));//指定所有UE关联到enbdev(0)
}
//未指定承载则默认EPS承载将会建立
NS_LOG_LOGIC ("setting up applications");//控制台输出提醒开始安装app
// Install and start applications on UEs and remote host
uint16_t dlPort = 10000;
uint16_t ulPort = 20000;
// randomize a bit start times to avoid simulation artifacts
// (e.g., buffer overflows due to packet transmissions happening
// exactly at the same time)
Ptr startTimeSeconds = CreateObject ();
startTimeSeconds->SetAttribute ("Min", DoubleValue (0));
startTimeSeconds->SetAttribute ("Max", DoubleValue (0.010));
for (uint32_t u = 0; u < numberOfUes; ++u)
{
Ptr ue = ueNodes.Get (u);
// Set the default gateway for the UE
Ptr ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject ());
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 (ueIpIfaces.GetAddress (u), dlPort);//dl 目的 Usr
clientApps.Add (dlClientHelper.Install (remoteHost));//客户端是remotehost
PacketSinkHelper dlPacketSinkHelper ("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), dlPort));
serverApps.Add (dlPacketSinkHelper.Install (ue));
NS_LOG_LOGIC ("installing UDP UL app for UE " << u);
UdpClientHelper ulClientHelper (remoteHostAddr, ulPort);//ul 目的 remoteHost
clientApps.Add (ulClientHelper.Install (ue));
PacketSinkHelper ulPacketSinkHelper ("ns3::UdpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), ulPort));
serverApps.Add (ulPacketSinkHelper.Install (remoteHost));
Ptr tft = Create ();
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);//不再是默认EPS承载而是专用承载
Time startTime = Seconds (startTimeSeconds->GetValue ());//随机开始
serverApps.Start (startTime);
clientApps.Start (startTime);
} // end for bearer
}//end for Usr
// Add X2 inteface
lteHelper->AddX2Interface (enbNodes);//至少两个enb,每两个之间加入X2
// X2-based Handover
lteHelper->HandoverRequest (Seconds (0.100), ueLteDevs.Get (0), enbLteDevs.Get (0), enbLteDevs.Get (1));//人工触发切换
// Uncomment to enable PCAP tracing
//p2ph.EnablePcapAll("lena-x2-handover");
lteHelper->EnablePhyTraces ();
lteHelper->EnableMacTraces ();
lteHelper->EnableRlcTraces ();
lteHelper->EnablePdcpTraces ();
Ptr rlcStats = lteHelper->GetRlcStats ();
rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (0.05)));
Ptr pdcpStats = lteHelper->GetPdcpStats ();
pdcpStats->SetAttribute ("EpochDuration", TimeValue (Seconds (0.05)));
// 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));
//利用类Config的一个静态成员函数Connect将二者关联source sink ,MakeCallback 使参数函数变成回调函数
Simulator::Stop (Seconds (simTime));
Simulator::Run ();
// GtkConfigStore config;
// config.ConfigureAttributes ();
Simulator::Destroy ();
return 0;
}
以上实现了通过默认EPS承载建立起UE到远程网络remotehost之间的通信。