NS3_3.38 AODV网络协议代码解析

/*
 * 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处将一个节点移动到远离其他节点的位置

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值