返回

为方便读者,本教材中连续四行及以上程序源码(脚本),本网站将直接提供,直接输入使用。

(1)第96页第2行开始共12行如下:
sudo apt-get update
sudo apt-get -y install build-essential libsqlite3-dev libboost-all-dev libssl-dev git python3-setuptools castxml gir1.2-goocanvas-2.0 gir1.2-gtk-3.0 libgirepository1.0-dev python3-dev python3-gi python3-gi-cairo python3-pip python3-pygraphviz python3-pygccxml
sudo apt-get -y install g++ pkg-config sqlite3 qt5-default mercurial ipython3 openmpi-bin openmpi-common openmpi-doc libopenmpi-dev autoconf cvs bzr unrar gdb valgrind uncrustify doxygen graphviz imagemagick python3-sphinx dia tcpdump libxml2 libxml2-dev cmake libc6-dev libc6-dev-i386 libclang-6.0-dev llvm-6.0-dev automake vtun lxc uml-utilities libgtk-3-dev
sudo ln -s /usr/bin/python3 /usr/bin/python
python -m pip install --user cxxfilt pybindgen
(2)第96页第16行开始共7行如下:
deb http://archive.ubuntu.com/ubuntu/ trusty main universe restricted multiverse
deb https://mirrors.aliyun.com/ubuntu/ xenial main
deb-src https://mirrors.aliyun.com/ubuntu/ xenial main
deb https://mirrors.aliyun.com/ubuntu/ xenial universe
deb-src https://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://cz.archive.ubuntu.com/ubuntu bionic main universe
deb http://mirrors.aliyun.com/ubuntu bionic main universe
(3)第97页倒数第19行到第105页倒数第12行实验完整代码如下:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#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"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("LteTcpX2Handover");
std::ofstream g_ueMeasurements;
std::ofstream g_packetSinkRx;
std::ofstream g_cqiTrace;
std::ofstream g_tcpCongStateTrace;
std::ofstream g_positionTrace;
//执行进度报告函数
void ReportProgress (Time reportingInterval) {
std::cout << "*** Simulation time: " << std::fixed << std::setprecision (1) << Simulator::Now ().GetSeconds () << "s" << std::endl;
Simulator::Schedule (reportingInterval, &ReportProgress, reportingInterval);
}
//从类似”/NodeList/3/DeviceList/1/Mac/Assoc”的字符串中抽取节点ID
uint32_t ContextToNodeId (std::string context) {
std::string sub = context.substr (10);
uint32_t pos = sub.find ("/Device");
return atoi (sub.substr (0,pos).c_str ());
}
void NotifyUdpReceived (std::string context, Ptr p, const Address &addr) {
std::cout << Simulator::Now ().GetSeconds () << " node "<< ContextToNodeId (context)
<< " UDP received" << std::endl;
}
void NotifyConnectionEstablishedUe (std::string context, uint64_t imsi, uint16_t cellid, uint16_t rnti) {
std::cout << Simulator::Now ().GetSeconds () << " node "<< ContextToNodeId (context)
<< " UE IMSI " << imsi<< ": connected to CellId " << cellid<< " with RNTI " < ue, Time interval) {
Vector v = ue->GetObject ()->GetPosition ();
g_positionTrace << std::setw (7) << std::setprecision (3) << std::fixed 
<< Simulator::Now ().GetSeconds () << " "<< v.x << " " << v.y << std::endl;
Simulator::Schedule (interval, &TracePosition, ue, interval);
}
void NotifyUeMeasurements (std::string context, uint16_t rnti, uint16_t cellId, double rsrpDbm, double rsrqDbm, bool servingCell, uint8_t ccId) {
g_ueMeasurements << std::setw (7) << std::setprecision (3) << std::fixed 
<< Simulator::Now ().GetSeconds () << " " << std::setw (3) << cellId << " " 
<< std::setw (3) << (servingCell ? "1" : "0") << " " << std::setw (8) << rsrpDbm 
<< " " << std::setw (8) << rsrqDbm << std::endl;
}
void NotifyPacketSinkRx (std::string context, Ptr packet, const Address &address) {
g_packetSinkRx << std::setw (7) << std::setprecision (3) << std::fixed 
<< Simulator::Now ().GetSeconds () << " " << std::setw (5) << packet->GetSize () << std::endl;
}
void NotifyCqiReport (std::string context, uint16_t rnti, uint8_t cqi) {
g_cqiTrace << std::setw (7) << std::setprecision (3) << std::fixed 
<< Simulator::Now ().GetSeconds () << " " << std::setw (4) << ContextToNodeId (context)
<< " " << std::setw (4) << rnti  << " " << std::setw (3) << static_cast (cqi) << std::endl;
}
void CongStateTrace (const TcpSocketState::TcpCongState_t oldValue, const TcpSocketState::TcpCongState_t newValue) {
g_tcpCongStateTrace << std::setw (7) << std::setprecision (3) << std::fixed
<< Simulator::Now ().GetSeconds () << " "<< std::setw (4) 
<< TcpSocketState::TcpCongStateName[newValue] << std::endl;
}
void ConnectTcpTrace (void) {
Config::ConnectWithoutContext ("/NodeList/1/$ns3::TcpL4Protocol/SocketList/0/CongState", MakeCallback (&CongStateTrace));
}
//基于RSRQ度量的X2自动切换程序,其实例化两个eNodeB,UE关联到其中一个eNodeB
//在UE移动过程中,其测量RSRQ并进行切换
int main (int argc, char *argv[]) {
uint16_t numberOfUes = 1;
uint16_t numberOfEnbs = 2;
//命令行可改变的参数
double x2Distance = 500.0; // m
double yDistanceForUe = 1000.0;   // m
double speed = 20;       // m/s
double enbTxPowerDbm = 46.0;
std::string handoverType = "A2A4";
bool useRlcUm = false;
bool verbose = false;
bool pcap = false;
//其他常量
LogLevel logLevel = (LogLevel)(LOG_PREFIX_ALL | LOG_LEVEL_ALL);
std::string traceFilePrefix = "lte-tcp-x2-handover";
Time positionTracingInterval = Seconds (5);
Time reportingInterval = Seconds (10);
uint32_t ftpSize = 200000000; // 200 MB
uint16_t port = 4000;  //端口号
Config::SetDefault ("ns3::LteHelper::UseIdealRrc", BooleanValue (true));
CommandLine cmd;
cmd.AddValue ("speed", "Speed of the UE (m/s)", speed);
cmd.AddValue ("x2Distance", "Distance between eNB at X2 (meters)", x2Distance);
cmd.AddValue ("yDistanceForUe", "y value (meters) for UE", yDistanceForUe);
cmd.AddValue ("enbTxPowerDbm", "TX power (dBm) used by eNBs", enbTxPowerDbm);
cmd.AddValue ("useRlcUm", "Use LTE RLC UM mode", useRlcUm);
cmd.AddValue ("handoverType", "Handover type (A2A4 or A3Rsrp)", handoverType);
cmd.AddValue ("pcap", "Enable pcap tracing", pcap);
cmd.AddValue ("verbose", "Enable verbose logging", verbose);
cmd.Parse (argc, argv);
double simTime = 50; //仿真时长
// 如果移动开启,根据速度调整仿真时长
if (speed < 10 && speed != 0) {
std::cout << "Select a speed at least 10 m/s, or zero" << std::endl;
exit (1);
} else if (speed >= 10) {
// Handover around the middle of the total simTime
simTime = (double)(numberOfEnbs + 1) * x2Distance / speed;
}
if (verbose) {
LogComponentEnable ("EpcX2", logLevel);
LogComponentEnable ("A2A4RsrqHandoverAlgorithm", logLevel);
LogComponentEnable ("A3RsrpHandoverAlgorithm", logLevel);
}
if (useRlcUm == false) {
Config::SetDefault ("ns3::LteEnbRrc::EpsBearerToRlcMapping", EnumValue (LteEnbRrc::RLC_AM_ALWAYS));
}
g_ueMeasurements.open ((traceFilePrefix + ".ue-measurements.dat").c_str(), std::ofstream::out);
g_ueMeasurements << "# time   cellId   isServingCell?  RSRP(dBm)  RSRQ(dB)" << std::endl;
g_packetSinkRx.open ((traceFilePrefix + ".tcp-receive.dat").c_str(), std::ofstream::out);
g_packetSinkRx << "# time   bytesRx" << std::endl;
g_cqiTrace.open ((traceFilePrefix + ".cqi.dat").c_str(), std::ofstream::out);
g_cqiTrace << "# time   nodeId   rnti  cqi" << std::endl;
g_tcpCongStateTrace.open ((traceFilePrefix + ".tcp-state.dat").c_str(), std::ofstream::out);
g_tcpCongStateTrace << "# time   congState" << std::endl;
g_positionTrace.open ((traceFilePrefix + ".position.dat").c_str(), std::ofstream::out);
g_positionTrace << "# time   congState" << std::endl;
Ptr lteHelper = CreateObject ();
Ptr epcHelper = CreateObject ();
lteHelper->SetEpcHelper (epcHelper);
lteHelper->SetSchedulerType ("ns3::RrFfMacScheduler");
if (handoverType == "A2A4") {
lteHelper->SetHandoverAlgorithmType ("ns3::A2A4RsrqHandoverAlgorithm");
lteHelper->SetHandoverAlgorithmAttribute ("ServingCellThreshold", UintegerValue (30));
lteHelper->SetHandoverAlgorithmAttribute ("NeighbourCellOffset", UintegerValue (1));
} else if (handoverType == "A3Rsrp") {
lteHelper->SetHandoverAlgorithmType ("ns3::A3RsrpHandoverAlgorithm");
lteHelper->SetHandoverAlgorithmAttribute ("Hysteresis", DoubleValue (3.0));
lteHelper->SetHandoverAlgorithmAttribute ("TimeToTrigger", TimeValue (MilliSeconds (256)));
} else {
std::cout << "Unknown handover type: " << handoverType << std::endl;
exit (1);
}
//创建单个RemoteHost
NodeContainer remoteHostContainer;
remoteHostContainer.Create (1);
Ptr remoteHost = remoteHostContainer.Get (0);
InternetStackHelper internet;
internet.Install (remoteHostContainer);
// 创建假象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 (epcHelper->GetPgwNode (), remoteHost);
Ipv4AddressHelper ipv4h;
ipv4h.SetBase ("1.0.0.0", "255.0.0.0");
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);
Ipv4StaticRoutingHelper ipv4RoutingHelper;
Ptr remoteHostStaticRouting = 
ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject ());
//接口0为localhost,接口1为p2p设备
remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), 
Ipv4Mask ("255.0.0.0"), 1);
NodeContainer ueNodes;
NodeContainer enbNodes;
enbNodes.Create (numberOfEnbs);
ueNodes.Create (numberOfUes);
//eNB上安装移动模型
Ptr enbPositionAlloc = CreateObject ();
for (uint16_t i = 0; i < numberOfEnbs; i++){
Vector enbPosition (x2Distance * (i + 1), x2Distance, 0);
enbPositionAlloc->Add (enbPosition);
}
MobilityHelper enbMobility;
enbMobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
enbMobility.SetPositionAllocator (enbPositionAlloc);
enbMobility.Install (enbNodes);
//UE上安装移动模型
MobilityHelper ueMobility;
ueMobility.SetMobilityModel ("ns3::ConstantVelocityMobilityModel");
ueMobility.Install (ueNodes);
ueNodes.Get (0)->GetObject ()->SetPosition (Vector (0, yDistanceForUe, 0));
ueNodes.Get (0)->GetObject ()
->SetVelocity (Vector (speed, 0, 0));
//在eNB和UE上安装LTE设备
Config::SetDefault ("ns3::LteEnbPhy::TxPower", DoubleValue (enbTxPowerDbm));
NetDeviceContainer enbLteDevs = lteHelper->InstallEnbDevice (enbNodes);
NetDeviceContainer ueLteDevs = lteHelper->InstallUeDevice (ueNodes);
//UE上安装IP栈
internet.Install (ueNodes);
Ipv4InterfaceContainer ueIpIfaces;
ueIpIfaces = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueLteDevs));
//将所有UE关联至第1个eNodeB
for (uint16_t i = 0; i < numberOfUes; i++){
lteHelper->Attach (ueLteDevs.Get (i), enbLteDevs.Get (0));
}
Ptr ueStaticRouting = 
ipv4RoutingHelper.GetStaticRouting (ueNodes.Get (0)->GetObject ());
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);
BulkSendHelper ftpServer ("ns3::TcpSocketFactory", Address ());
AddressValue remoteAddress (InetSocketAddress (ueIpIfaces.GetAddress (0), port));
ftpServer.SetAttribute ("Remote", remoteAddress);
ftpServer.SetAttribute ("MaxBytes", UintegerValue (ftpSize));
NS_LOG_LOGIC ("setting up TCP flow from remote host to UE");
ApplicationContainer sourceApp = ftpServer.Install (remoteHost);
sourceApp.Start (Seconds (1));
sourceApp.Stop (Seconds (simTime));
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress);
ApplicationContainer sinkApp = sinkHelper.Install (ueNodes.Get (0));
sinkApp.Start (Seconds (1));
sinkApp.Stop (Seconds (simTime));
Ptr tft = Create ();
EpcTft::PacketFilter dlpf;
dlpf.localPortStart = port;
dlpf.localPortEnd = port;
tft->Add (dlpf);
EpsBearer bearer (EpsBearer::NGBR_VIDEO_TCP_DEFAULT);
lteHelper->ActivateDedicatedEpsBearer (ueLteDevs.Get (0), bearer, tft);
//添加X2接口
lteHelper->AddX2Interface (enbNodes);
//追踪数据包
if (pcap){
p2ph.EnablePcapAll ("lte-tcp-x2-handover");
}
lteHelper->EnablePhyTraces ();
lteHelper->EnableMacTraces ();
lteHelper->EnableRlcTraces ();
lteHelper->EnablePdcpTraces ();
Ptr rlcStats = lteHelper->GetRlcStats ();
rlcStats->SetAttribute ("EpochDuration", TimeValue (Seconds (1.0)));
Ptr pdcpStats = lteHelper->GetPdcpStats ();
pdcpStats->SetAttribute ("EpochDuration", TimeValue (Seconds (1.0)));
//连接自定义跟踪接收器,用于RRC连接建立和切换通知
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 ("/NodeList/4/DeviceList/*/ComponentCarrierMapUe/*/LteUePhy/ReportUeMeasurements", MakeCallback (&NotifyUeMeasurements));
Config::Connect ("/NodeList/4/ApplicationList/*/$ns3::PacketSink/Rx",MakeCallback (&NotifyPacketSinkRx));
Config::Connect ("/NodeList/*/DeviceList/*/$ns3::LteEnbNetDevice/ComponentCarrierMap/*/FfMacScheduler/$ns3::RrFfMacScheduler/WidebandCqiReport", MakeCallback (&NotifyCqiReport));
//时延跟踪连接,直到TCP套接字存在
Simulator::Schedule (Seconds (1.001), &ConnectTcpTrace);
//启动位置追踪
Simulator::Schedule (Seconds (0), &TracePosition, ueNodes.Get(0), positionTracingInterval);
//开始执行程序
Vector vUe = ueNodes.Get (0)->GetObject ()->GetPosition ();
Vector vEnb1 = enbNodes.Get (0)->GetObject ()->GetPosition ();
Vector vEnb2 = enbNodes.Get (1)->GetObject ()->GetPosition ();
std::cout << "Initial positions:  UE: (" << vUe.x << "," << vUe.y << "), "
<< "eNB1: (" << vEnb1.x << "," << vEnb1.y << "), "
<< "eNB2: (" << vEnb2.x << "," << vEnb2.y << ")" << std::endl;
std::cout << "Simulation time: " << simTime << " sec" << std::endl;
Simulator::Schedule (reportingInterval, &ReportProgress, reportingInterval);
Simulator::Stop (Seconds (simTime));
Simulator::Run ();
Simulator::Destroy ();
//关闭文件描述符
g_ueMeasurements.close ();
g_cqiTrace.close ();
g_packetSinkRx.close ();
g_tcpCongStateTrace.close ();
g_positionTrace.close ();
return 0;
}
(4)第106页第3行到第107页倒数第5行实验完整代码如下:
import sys
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
import argparse
matplotlib.rcParams['font.sans-serif']=['SimHei']   # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus']=False     # 正常显示负号
plt.figure(figsize=(8, 4))
parser = argparse.ArgumentParser()
# 位置参数
parser.add_argument("--fileName", help="file name", default="../lte-tcp-x2-handover.tcp-receive.dat")
parser.add_argument("--plotName", help="plot name", default="lte-tcp-x2-handover.tcp-throughput.pdf")
#可选的时间步长参数
parser.add_argument("--timestep", help="timestep resolution in seconds (default 0.1)")
parser.add_argument("--title", help="title string", default="LTE切换对TCP吞吐量影响")
args = parser.parse_args()
timestep = 0.1
if args.timestep is not None:
    timestep = float(args.timestep)
#从输入文件创建每个时间步位的直方图
times=[]
bits_per_timestep=[]
fd = open(args.fileName, 'r')
current_time = 0
current_bits = 0 
for line in fd:
    l = line.split()
    if line.startswith("#"):
        continue
    timestamp = float(l[0])
    if (timestamp < (current_time + timestep)):
        current_bits = current_bits + int(l[1])*8
    else:
        times.append(current_time + timestep)
        bits_per_timestep.append(current_bits)
        current_time = current_time + timestep
        while (current_time + timestep <= timestamp):
            times.append(current_time + timestep)
            bits_per_timestep.append(0)
            current_time = current_time + timestep
        current_bits = int(l[1])*8
# 完成最后一个样本
times.append(current_time + timestep)
bits_per_timestep.append(current_bits)
fd.close()
if len(times) == 0:
    print("No data points found, exiting...")
    sys.exit(1)
#将观察到的每时间步位数转换为Mb/s并绘制
rate_in_mbps = [float(x/timestep)/1e6 for x in bits_per_timestep]
plt.plot(times, rate_in_mbps)
plt.xlabel('时间 (s)')
plt.ylabel('速率 (Mb/s)')
plt.ylim([0,20])
plt.title(args.title)
plotname = args.plotName
plt.savefig(plotname, format='pdf')
plt.close()
sys.exit (0)
(5)第108页第1行到第109页第4行实验完整代码如下:
import sys
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
import argparse
matplotlib.rcParams['font.sans-serif']=['SimHei']   # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus']=False     # 正常显示负号
plt.figure(figsize=(8, 4))
parser = argparse.ArgumentParser()
# 位置参数
parser.add_argument("--fileName", help="file name", default="../lte-tcp-x2-handover.ue-measurements.dat")
parser.add_argument("--plotName", help="plot name", default="lte-tcp-x2-handover.rsrq.pdf")
#可选的时间步长参数
parser.add_argument("--title", help="title string", default="LTE handover RSRQ")
args = parser.parse_args()
times1=[]
times2=[]
values1=[]
values2=[]
fd = open(args.fileName, 'r')
for line in fd:
    l = line.split()
    if line.startswith("#"):
        continue
    if l[1] == "1":
        times1.append(float(l[0]))
        values1.append(float(l[4]))
    elif l[1] == "2":
        times2.append(float(l[0]))
        values2.append(float(l[4]))
fd.close()
if len(times1) == 0:
    print("No data points found, exiting...")
    sys.exit(1)
plt.scatter(times1, values1, marker='.', label='cell 1', color='red')
if len(times2) != 0:
    plt.scatter(times2, values2, marker='.', label='cell 2', color='blue')
plt.xlabel('时间 (s)')
plt.ylabel('RSRQ (dB)')
plt.title(args.title)
plotname = args.plotName
plt.savefig(plotname, format='pdf')
plt.close()
sys.exit (0)