/*
* Copyright (c) 2009 IITP RAS
*
* 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
*
* This is an example script for AODV manet routing protocol.
*
* Authors: Pavel Boyko <boyko@iitp.ru>
*/
#include "ns3/aodv-module.h"
//引入AODV(Ad hoc On-Demand Distance Vector)协议模块,该模块用于实现无线自组织网络中的路由功能
#include "ns3/core-module.h"
//引入核心模块,提供了ns-3的核心类和功能,如事件调度、时间模拟等
#include "ns3/internet-module.h"
//引入互联网模块,提供了实现Internet协议(如IP、TCP、UDP等)功能的类和方法
#include "ns3/mobility-module.h"
//引入移动性模块,允许模拟移动节点和移动性模型,用于研究移动网络的行为
#include "ns3/network-module.h"
//引入网络模块,提供了网络拓扑创建和管理的类和方法
#include "ns3/ping-helper.h"
//引入ping-helper,用于在模拟环境中执行ping操作
#include "ns3/point-to-point-module.h"
//引入点对点模块,用于建立和配置点对点网络连接
#include "ns3/yans-wifi-helper.h"
//引入yans-wifi-helper,用于模拟基于YANS(Yet Another Network Simulator)的WiFi网络
#include <cmath>
#include <iostream>
//通过添加cmath和iostream头文件,可以使用数学计算函数和标准输入输出流相关的功能
using namespace ns3;
/**
* \ingroup aodv-examples
* \ingroup examples
* \brief Test script.
*
* This script creates 1-dimensional grid topology and then ping last node from the first one: 创建一维网格拓扑,然后从第一个节点ping最后一个节点
*
* [10.0.0.1] <-- step --> [10.0.0.2] <-- step --> [10.0.0.3] <-- step --> [10.0.0.4]
*
* ping 10.0.0.4
*
* When 1/3 of simulation time has elapsed, one of the nodes is moved out of
* range, thereby breaking the topology. By default, this will result in
* stopping ping replies reception after sequence number 33. If the step size is reduced
* to cover the gap, then also the following pings can be received.
* 当1/3的模拟时间过去时,其中一个节点移出范围,从而破坏拓扑结构。默认情况下,这将导致在序列号33之后停止接收ping回复。如果减小步长以覆盖间隙,则也可以接收到以下ping
*/
class AodvExample
{
public:
AodvExample();
/**
* \brief Configure script parameters
* \param argc is the command line argument count
* \param argv is the command line arguments
* \return true on successful configuration
*/
bool Configure(int argc, char** argv);
/// Run simulation
void Run();
/**
* Report results
* \param os the output stream
*/
void Report(std::ostream& os);
private:
// parameters
/// Number of nodes
uint32_t size;
/// Distance between nodes, meters
double step;
/// Simulation time, seconds
double totalTime;
/// Write per-device PCAP traces if true
bool pcap;
/// Print routes if true
bool printRoutes;
// network
/// nodes used in the example
NodeContainer nodes;
/// devices used in the example
NetDeviceContainer devices;
/// interfaces used in the example
Ipv4InterfaceContainer interfaces;
private:
/// Create the nodes
void CreateNodes();
/// Create the devices
void CreateDevices();
/// Create the network
void InstallInternetStack();
/// Create the simulation applications
void InstallApplications();
};
/**
这段代码是一个名为AodvExample的类定义。它具有以下成员函数和成员变量:
成员函数:
AodvExample():构造函数,用于初始化类的对象。
bool Configure(int argc, char** argv):配置脚本参数的函数。接受命令行参数的数量和参数数组作为输入,返回配置是否成功的布尔值。
void Run():运行模拟的函数。
void Report(std::ostream& os):报告结果的函数。接受一个输出流作为参数。
私有成员变量:
uint32_t size:节点数量。
double step:节点之间的距离(以米为单位)。
double totalTime:模拟的总时间(以秒为单位)。
bool pcap:如果为true,则写入每个设备的PCAP跟踪。
bool printRoutes:如果为true,则打印路由信息。
私有成员变量(网络相关):
NodeContainer nodes:在示例中使用的节点。
NetDeviceContainer devices:在示例中使用的设备。
Ipv4InterfaceContainer interfaces:在示例中使用的接口。
私有成员函数:
void CreateNodes():创建节点的函数。
void CreateDevices():创建设备的函数。
void InstallInternetStack():创建网络的函数。
void InstallApplications():创建模拟应用程序的函数。
这段代码是一个基于AODV(自适应无线网络距离向量)协议的网络仿真示例程序,用于模拟节点间的通信和路由信息传输。它包含了节点、设备、网络配置和应用程序的创建以及模拟运行等功能。
*/
int
main(int argc, char** argv)
{
AodvExample test;
if (!test.Configure(argc, argv))
{
NS_FATAL_ERROR("Configuration failed. Aborted.");
}
test.Run();
test.Report(std::cout);
return 0;
}
/**
这段代码是程序的主函数。主要功能是创建一个AodvExample对象test,并通过调用它的Configure方法来进行配置。
如果配置失败,程序会输出错误信息并中止运行。
接着,程序调用test的Run方法来执行具体的操作,然后通过调用Report方法将结果输出到标准输出流std::cout中。
最后,主函数返回0表示程序正常结束。
*/
//-----------------------------------------------------------------------------
//在构造函数AodvExample()中,对类的成员变量进行初始化,设置了一些默认值
AodvExample::AodvExample()
: size(10),
step(50),
totalTime(100),
pcap(true),
printRoutes(true)
{
}
bool
AodvExample::Configure(int argc, char** argv)
{
// Enable AODV logs by default. Comment this if too noisy
// LogComponentEnable("AodvRoutingProtocol", LOG_LEVEL_ALL);
SeedManager::SetSeed(12345);
CommandLine cmd(__FILE__);
cmd.AddValue("pcap", "Write PCAP traces.", pcap);
cmd.AddValue("printRoutes", "Print routing table dumps.", printRoutes);
cmd.AddValue("size", "Number of nodes.", size);
cmd.AddValue("time", "Simulation time, s.", totalTime);
cmd.AddValue("step", "Grid step, m", step);
cmd.Parse(argc, argv);
return true;
}
//Configure方法用于配置程序的参数。通过解析命令行参数,可以设置是否开启pcap跟踪、打印路由表等参数,并返回配置是否成功
void
AodvExample::Run()
{
// Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue (1)); //
// enable rts cts all the time.
CreateNodes();
CreateDevices();
InstallInternetStack();
InstallApplications();
std::cout << "Starting simulation for " << totalTime << " s ...\n";
Simulator::Stop(Seconds(totalTime));
Simulator::Run();
Simulator::Destroy();
}
//Run方法用于执行模拟器的运行过程。在该方法中,首先创建网络节点、设备、安装网络协议栈和应用程序,然后通过调用Simulator::Stop停止模拟时间,并调用Simulator::Run开始执行模拟器运行,最后调用Simulator::Destroy销毁模拟器
void
AodvExample::Report(std::ostream&)
{
}
//Report方法为空实现,用于生成报告
void
AodvExample::CreateNodes()
{
std::cout << "Creating " << (unsigned)size << " nodes " << step << " m apart.\n";
nodes.Create(size);
// Name nodes
for (uint32_t i = 0; i < size; ++i)
{
std::ostringstream os;
os << "node-" << i;
Names::Add(os.str(), nodes.Get(i));
}
// Create static grid
MobilityHelper mobility;
mobility.SetPositionAllocator("ns3::GridPositionAllocator",
"MinX",
DoubleValue(0.0),
"MinY",
DoubleValue(0.0),
"DeltaX",
DoubleValue(step),
"DeltaY",
DoubleValue(0),
"GridWidth",
UintegerValue(size),
"LayoutType",
StringValue("RowFirst"));
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
mobility.Install(nodes);
}
//CreateNodes方法创建了指定数量的网络节点,并设置网格状分布。节点的位置信息通过MobilityHelper设置,并使用ConstantPositionMobilityModel来模拟节点的位置固定
/**
std::cout打印出要创建的节点数量和节点之间的距离;nodes.Create(size)函数来创建指定数量的节点。这个nodes对象是一个节点容器,用于存储所有创建的节点;通过使用循环,为每个节点生成一个唯一的名称,并将名称与对应的节点对象关联起来。这样可以通过名称来引用特定的节点;
使用MobilityHelper对象来配置节点的位置和移动模型。首先通过调用SetPositionAllocator函数设置节点的位置分配器为ns3::GridPositionAllocator,并传入相关参数,如最小X坐标、最小Y坐标、步长等。然后通过调用SetMobilityModel函数设置节点的移动模型为ns3::ConstantPositionMobilityModel,表示节点不会移动。
通过调用mobility.Install(nodes)将配置好的位置和移动模型安装到节点上,从而完成节点的初始化工作。
*/
void
AodvExample::CreateDevices()
{
WifiMacHelper wifiMac;
wifiMac.SetType("ns3::AdhocWifiMac");
YansWifiPhyHelper wifiPhy;
YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default();
wifiPhy.SetChannel(wifiChannel.Create());
WifiHelper wifi;
wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
"DataMode",
StringValue("OfdmRate6Mbps"),
"RtsCtsThreshold",
UintegerValue(0));
devices = wifi.Install(wifiPhy, wifiMac, nodes);
if (pcap)
{
wifiPhy.EnablePcapAll(std::string("aodv"));
}
}
//CreateDevices方法创建了无线设备,并设置了物理层和链路层的属性。其中,WifiMacHelper设置了无线设备的类型为AdhocWifiMac,YansWifiPhyHelper设置了无线信道,WifiHelper设置了无线局域网的属性,并通过Install方法将设备安装到节点上
void
AodvExample::InstallInternetStack()
{
AodvHelper aodv;
// you can configure AODV attributes here using aodv.Set(name, value)
InternetStackHelper stack;
stack.SetRoutingHelper(aodv); // has effect on the next Install ()
stack.Install(nodes);
Ipv4AddressHelper address;
address.SetBase("10.0.0.0", "255.0.0.0");
interfaces = address.Assign(devices);
if (printRoutes)
{
Ptr<OutputStreamWrapper> routingStream =
Create<OutputStreamWrapper>("aodv.routes", std::ios::out);
Ipv4RoutingHelper::PrintRoutingTableAllAt(Seconds(8), routingStream);
}
}
//InstallInternetStack方法安装了AODV协议栈到网络节点上,并配置了IPv4地址。如果配置中开启了打印路由表的选项,还会在模拟时间达到8秒时打印路由表
/**
调用AodvHelper aodv来创建一个用于配置AODV路由的助手对象。
调用aodv.Set(name, value)来配置AODV路由的属性。调用InternetStackHelper stack来创建一个用于配置网络协议栈的助手对象。
调用stack.SetRoutingHelper(aodv)来设置路由辅助器,将上一步创建的AODV路由配置给网络协议栈。调用stack.Install(nodes)来将网络协议栈安装到之前创建的设备上。这样可以使设备具备IP协议栈功能,并能够进行路由和通信操作。
调用address.SetBase("10.0.0.0", "255.0.0.0")来设置设备的IP地址,其中第一个参数是网络地址,第二个参数是子网掩码。
调用address.Assign(devices)将IP地址分配给设备的网络接口,使得设备能够在网络中进行通信。
如果printRoutes变量为真,则通过调用Ipv4RoutingHelper::PrintRoutingTableAllAt(Seconds(8), routingStream)来打印设备的路由表。这样可以在仿真过程中定期输出路由表的内容,并将其保存到指定的文件中。
*/
void
AodvExample::InstallApplications()
{
PingHelper ping(interfaces.GetAddress(size - 1));
ping.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE));
ApplicationContainer p = ping.Install(nodes.Get(0));
p.Start(Seconds(0));
p.Stop(Seconds(totalTime) - Seconds(0.001));
// move node away
Ptr<Node> node = nodes.Get(size / 2);
//从 nodes 中获取索引为 size / 2 的节点,并将其赋给变量 node
Ptr<MobilityModel> mob = node->GetObject<MobilityModel>();
//从 node 中获取 MobilityModel 实例的指针,并赋给变量 mob
Simulator::Schedule(Seconds(totalTime / 3),
&MobilityModel::SetPosition,
mob,
Vector(1e5, 1e5, 1e5));
//使用 Simulator::Schedule 方法,在 totalTime / 3 秒后执行 MobilityModel::SetPosition 方法,将节点的位置设置为 Vector(1e5, 1e5, 1e5)
}
//InstallApplications方法安装了一个Ping应用程序到网络中的第一个节点,用于模拟数据通信。同时,在模拟时间的1/3处将一个节点移动到远离其他节点的位置