Loading...

# 10.ns3 路由性能测试实例.md

在本节中,将介绍 ns3 中路由仿真,从路由选择到绘图出结果的一系列流程。

PS:只是本人实验的一系列步骤,不一定是最优做法,但也是一套完整的流程吧,有更好的流程可以互相交流。

# 路由性能好坏的评判标准

通常来说描述一个路由,我们会从 吞吐量,时延,能耗,丢包率,交付率,平均路径长度 等因素来描述路由的好坏。

吞吐量 指的是在单位时间内通过某个网络的实际的数据量。是对实际网络到底有多少数据率在信道上传输。

时延 指的是数据从信源发送到信宿所需的时间。

交付率 指的是发送过程中信宿实际接收的数据包 / 总共发送的数据包。

丢包率 是 1 - 交付率

能耗 指的是一段时间内消耗的能量

路径长度 指的是路由的跳数

# 仿真模拟

为了获取节点收发包的情况,我们需要跟踪设备收发包的情况,这就需要用到 Config 来进行跟踪,

对于 onOffHelperPacketSink 做收发端的情况下,我们可以采用 /NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx 作为 tracking 的地址。

即通过如下方法来绑定 ReceivePacket 作为回调函数

Config::ConnectWithoutContext("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback(&OrrpExample::ReceivePacket, this));

而在 ReceivePacket 中,我们又可以通过

类似如下的方法收集已接收的 packet 信息

void OrrpExample::ReceivePacket(Ptr<const Packet> packet, const Address &)
{
    if ((Simulator::Now() - tmp) < Seconds(1))
    {
        tmpTotal += packet->GetSize();
    }
    else
    {
        while ((Simulator::Now() - tmp) > Seconds(1))
        {
            std::cout << tmp.GetSeconds() << "S throughoutput = " << tmpTotal * 8 / (1e6) << "Mbit" << std::endl;
            std::ostringstream ostrStream;
            ostrStream << "./result/" << m_protocolName << "Test/" << m_protocolName << "Test-size-" << size << "-seed-" << seed << "-nodesLocationType-" << nodesLocationType << "-nodesMove-" << nodesMove << "-width-" << width << "-step-" << step << "-log";
            std::ofstream file(ostrStream.str(), std::ios::app | std::ios::out);
            file << tmp.GetSeconds() << " " << sendSeq.size() * packet->GetSize() * 8 / (1e6) << " " << bytesTotal * 8 / (1e6) << " " << tmpTotal * 8 / (1e6) << "\n";
            file.close();
            tmp += Seconds(1);
            tmpTotal = 0;
        }
        tmpTotal += packet->GetSize();
    }
    std::vector<uint32_t>::iterator iter;
    iter = find(sendSeq.begin(), sendSeq.end(), packet->GetUid());
    int index = iter - sendSeq.begin();
    bytesTotal += packet->GetSize();
    packetsReceived += 1;
    m_delayEstimation.RecordRx(packet);
    m_delay += (Simulator::Now() - sendTime[index]).GetSeconds();
    m_jitter += m_delayEstimation.GetLastJitter();
    if (first_pkt)
    {
        m_firstRx = Simulator::Now();
        first_pkt = false;
    }
    m_lastRx = Simulator::Now();
}

并在仿真的最后,调用自定义的 ReportStatistics 进行最后的分析,并存储结果到本地文件

int main(int argc, char **argv)
{
    OrrpExample test;
    if (!test.Configure(argc, argv))
    {
        NS_FATAL_ERROR("Configuration failed. Aborted.");
    }
    test.Run();
    test.ReportStatistics();
    test.Report(std::cout);
    return 0;
}
void OrrpExample::ReportStatistics()
{
    double Dt = m_lastRx.GetSeconds() - m_firstRx.GetSeconds();
    double kbs = (bytesTotal * 8.0) / (Dt * 1000);
    bytesTotal = 0;
    std::ofstream out(m_CSVfileName.c_str(), std::ios::app);
    int m_nSinks = 1;
    out << kbs / m_nSinks << ","
        << packetsReceived << ","
        << packetsTx << ","
        << packetsReceived / (double)packetsTx << ","
        << m_delay / packetsReceived << ","
        << m_jitter / (packetsReceived * 1000000000.0) << ","
        //   << routingPkts << ","
        //    << m_nSinks << ","
        //    << m_nWifis << ","
        //    << m_protocolName << ","
        //   << m_txrange << ""
        << std::endl;
    std::cout << "吞吐量 " << kbs / m_nSinks << " kbps ,"
              << "收包数" << packetsReceived << ","
              << "发包数" << packetsTx << ","
              << "交付率" << packetsReceived / (double)packetsTx << ","
              << "时延" << m_delay / packetsReceived << ","
              << m_jitter / (packetsReceived * 1000000000.0) << ","
              << std::endl;
    std::ostringstream ostrStream;
    ostrStream << "./result/" << m_protocolName << "Test/" << m_protocolName << "Test-size-" << size << "-seed-" << seed << "-nodesLocationType-" << nodesLocationType << "-nodesMove-" << nodesMove << "-width-" << width << "-step-" << step << "-delay-log";
    std::ofstream file(ostrStream.str(), std::ios::app | std::ios::out);
    file << packetsReceived / (double)packetsTx << " " << m_delay / packetsReceived << " " << kbs / m_nSinks / 1e3 << "\n";
    file.close();
    out.close();
    packetsReceived = 0;
    packetsTx = 0;
    m_delay = 0;
    m_jitter = 0;
    // routingPkts = 0;
}

同理我们也可以计算点到点实时的吞吐量

通过添加 Simulator::Schedule (Seconds (6.0), &OrrpExample::CalculateThroughput,this,endTime); 来调用 CalculateThroughput 来计算实时的吞吐量

void OrrpExample::CalculateThroughput(double endTime)
{
    std::ostringstream ostrStream;
    ostrStream << "./result/orrpTest/orrpTest-size-" << size << "-seed-" << seed << "-nodesLocationType-" << nodesLocationType << "-nodesMove-" << nodesMove << "-width-" << width << "-step-" << step << "-log";
    std::ofstream file;
    file.open(ostrStream.str(), std::ios_base::app);
    Time now = Simulator::Now();
    double cur = (sink->GetTotalRx() - lastTotalRx) * (double)8 / 1e6;
    double TotalRx = sink->GetTotalRx() * (double)8 / 1e6;
    double TotalTx = source->GetTotalTx() * (double)8 / 1e6;
    file << now.GetSeconds() << " " << TotalTx << " " << TotalRx << " " << cur << "\n";
    //  std::cout<<now.GetSeconds () << "s 发送数据: \t" <<"send:"<<source->GetTotalTx ()* (double) 8 / 1e6<<"Mbit"<<std::endl;
    //  std::cout<<now.GetSeconds () << "s 接收数据: \t" <<"receive:"<<sink->GetTotalRx ()* (double) 8 / 1e6<<"Mbit"<<std::endl;
    std::cout << now.GetSeconds() << "s吞吐量: \t" << cur << " Mbit/s" << std::endl; // throughput
                                                                                     // std::cout << now.GetSeconds () << cur << std::endl;//throughput
    lastTotalRx = sink->GetTotalRx();
    file.close();
    if (now < Seconds(endTime))
        //  Simulator::Schedule (MilliSeconds (100), &OrrpExample::CalculateThroughput,this,endTime);
        Simulator::Schedule(Seconds(1), &OrrpExample::CalculateThroughput, this, endTime);
}

详细代码如下所示

#include <vector>
#include <iostream>
#include <cmath>
#include "ns3/aodv-module.h"
#include "ns3/orrp-module.h"
#include "ns3/orrp2d-helper.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/v4ping-helper.h"
#include "ns3/optical-helper.h"
#include "ns3/applications-module.h"
// add by yeyu
#include "ns3/MyPropagationLossModel.h"
#include "ns3/stats-module.h"
#include "ns3/netanim-module.h"
#include <sstream>
#include <string>
using namespace ns3;
//********************* stats result******************//
// 输出结果
//  void ReportStatistics ();
// send callback
void TxPacket(Ptr<const Packet>);
// 打印进度
void PrintProgress(double TotalTime);
// 接收回调
// void ReceivePacket (Ptr<const Packet> packet, const Address &);
uint32_t bytesTotal(0);
uint32_t bytesReceivedTotal(0);
uint32_t packetsReceived(0);
uint32_t packetsTx(0);
DelayJitterEstimation m_delayEstimation;
double m_delay(0);
uint64_t m_jitter(0);
bool first_pkt(true);
std::string m_CSVfileName("orrpTest-routing-output");
Time m_firstRx;
Time m_lastRx;
Time tmp;
uint32_t tmpTotal(0);
std::vector<Time> sendTime;
std::vector<uint32_t> sendSeq;
//********************* stats result******************//
// 接收端应用
Ptr<PacketSink> sink; /* Pointer to the packet sink application */
// 发送端应用
Ptr<OnOffApplication> source;
uint64_t lastTotalRx = 0; /* The value of the last total received bytes */
class OrrpExample
{
public:
    OrrpExample();
    bool Configure(int argc, char **argv);
    void Run();
    /**
     * Report results
     * \param os the output stream
     */
    void Report(std::ostream &os);
    void printRoute(double showTime);
    void CalculateThroughput(double endTime);
    void PhyRxOkTrace(std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble);
    void DevTxTrace(std::string context, Ptr<const Packet> packet);
    void DevRxTrace(std::string context, Ptr<const Packet> packet);
    void ReceivePacket(Ptr<const Packet> packet, const Address &);
    void ReportStatistics();
    void energyChanged(double oldValue, double newValue);
private:
    // parameters
    /// 节点数量
    uint32_t size;
    /// 采用网格布局时节点的距离
    double step;
    /// 仿真总时间 (s)
    double totalTime;
    /// Write per-device PCAP traces if true
    bool pcap;
    /// 是否打印路由表
    bool printRoutes;
    bool nodesMove;
    double m_energyCost;
    double m_energyInit;
    // 节点布局方式 (0: 网格布局;1: 矩形随机布局)
    int nodesLocationType;
    // 随机
    int seed;
    int width;
    // yeyu
    WifiHelper wifi;
    std::vector<Ptr<WifiPhy>> m_phyVector;
    std::string m_protocolName;
    int m_routingProtocol;
    NodeContainer nodes;
    NetDeviceContainer devices;
    Ipv4InterfaceContainer interfaces;
private:
    void CreateNodes();
    void CreateDevices();
    void InstallInternetStack();
    void InstallApplications();
};
void OrrpExample::ReceivePacket(Ptr<const Packet> packet, const Address &)
{
    if ((Simulator::Now() - tmp) < Seconds(1))
    {
        tmpTotal += packet->GetSize();
    }
    else
    {
        while ((Simulator::Now() - tmp) > Seconds(1))
        {
            std::cout << tmp.GetSeconds() << "S throughoutput = " << tmpTotal * 8 / (1e6) << "Mbit" << std::endl;
            std::ostringstream ostrStream;
            ostrStream << "./result/" << m_protocolName << "Test/" << m_protocolName << "Test-size-" << size << "-seed-" << seed << "-nodesLocationType-" << nodesLocationType << "-nodesMove-" << nodesMove << "-width-" << width << "-step-" << step << "-log";
            std::ofstream file(ostrStream.str(), std::ios::app | std::ios::out);
            file << tmp.GetSeconds() << " " << sendSeq.size() * packet->GetSize() * 8 / (1e6) << " " << bytesTotal * 8 / (1e6) << " " << tmpTotal * 8 / (1e6) << "\n";
            file.close();
            tmp += Seconds(1);
            tmpTotal = 0;
        }
        tmpTotal += packet->GetSize();
    }
    std::vector<uint32_t>::iterator iter;
    iter = find(sendSeq.begin(), sendSeq.end(), packet->GetUid());
    int index = iter - sendSeq.begin();
    bytesTotal += packet->GetSize();
    packetsReceived += 1;
    m_delayEstimation.RecordRx(packet);
    //          m_delay += m_delayEstimation.GetLastDelay().GetNanoSeconds();
    m_delay += (Simulator::Now() - sendTime[index]).GetSeconds();
    m_jitter += m_delayEstimation.GetLastJitter();
    //          std::cout<<tmp.GetSeconds()<<"s "<<tmpTotal<<"Byte "<<Simulator::Now().GetSeconds()<<"uid:"<<packet->GetUid()<<" received packet delay="<<(Simulator::Now()-sendTime[index]).GetSeconds()<<"s size= "<<packet->GetSize ()<<std::endl;
    if (first_pkt)
    {
        m_firstRx = Simulator::Now();
        first_pkt = false;
    }
    m_lastRx = Simulator::Now();
}
void TxPacket(Ptr<const Packet> pkt)
{
    // trace packet
    packetsTx += 1;
    m_delayEstimation.PrepareTx(pkt);
    sendSeq.push_back(pkt->GetUid());
    sendTime.push_back(Simulator::Now());
    //    std::cout<<Simulator::Now().GetSeconds()<<"uid:"<<pkt->GetUid()<<" send"<<std::endl;
}
void PrintProgress(double TotalTime)
{
    double now = Simulator::Now().GetSeconds();
    NS_LOG_UNCOND("Progress Completed .. " << (now / TotalTime) * 100 << "%");
    Simulator::Schedule(Seconds(TotalTime / 100), &PrintProgress, TotalTime);
}
void OrrpExample::ReportStatistics()
{
    double Dt = m_lastRx.GetSeconds() - m_firstRx.GetSeconds();
    double kbs = (bytesTotal * 8.0) / (Dt * 1000);
    bytesTotal = 0;
    std::ofstream out(m_CSVfileName.c_str(), std::ios::app);
    int m_nSinks = 1;
    out << kbs / m_nSinks << ","
        << packetsReceived << ","
        << packetsTx << ","
        << packetsReceived / (double)packetsTx << ","
        << m_delay / packetsReceived << ","
        << m_jitter / (packetsReceived * 1000000000.0) << ","
        //   << routingPkts << ","
        //    << m_nSinks << ","
        //    << m_nWifis << ","
        //    << m_protocolName << ","
        //   << m_txrange << ""
        << std::endl;
    std::cout << "吞吐量 " << kbs / m_nSinks << " kbps ,"
              << "收包数" << packetsReceived << ","
              << "发包数" << packetsTx << ","
              << "交付率" << packetsReceived / (double)packetsTx << ","
              << "时延" << m_delay / packetsReceived << ","
              << m_jitter / (packetsReceived * 1000000000.0) << ","
              << std::endl;
    std::ostringstream ostrStream;
    ostrStream << "./result/" << m_protocolName << "Test/" << m_protocolName << "Test-size-" << size << "-seed-" << seed << "-nodesLocationType-" << nodesLocationType << "-nodesMove-" << nodesMove << "-width-" << width << "-step-" << step << "-delay-log";
    std::ofstream file(ostrStream.str(), std::ios::app | std::ios::out);
    file << packetsReceived / (double)packetsTx << " " << m_delay / packetsReceived << " " << kbs / m_nSinks / 1e3 << "\n";
    file.close();
    out.close();
    packetsReceived = 0;
    packetsTx = 0;
    m_delay = 0;
    m_jitter = 0;
    // routingPkts = 0;
}
int main(int argc, char **argv)
{
    OrrpExample test;
    if (!test.Configure(argc, argv))
    {
        NS_FATAL_ERROR("Configuration failed. Aborted.");
    }
    test.Run();
    test.ReportStatistics();
    test.Report(std::cout);
    return 0;
}
//-----------------------------------------------------------------------------
OrrpExample::OrrpExample() : size(30),
                             step(40),
                             totalTime(20),
                             pcap(false),
                             printRoutes(true),
                             seed(1),
                             width(size / 5),
                             nodesMove(false),
                             nodesLocationType(0),
                             m_energyInit(1),
                             m_energyCost(0),
                             m_routingProtocol(2),
                             m_protocolName("aodv")
{
}
bool OrrpExample::Configure(int argc, char **argv)
{
    // Enable ORRP logs by default. Comment this if too noisy
    //
    //   LogComponentEnable("OrrpNeighbors", LOG_LEVEL_WARN);
    //   LogComponentEnable("OrrpNeighbors", LOG_LEVEL_WARN);
    //   LogComponentEnable("OrrpRoutingTable", LOG_LEVEL_WARN);
    LogComponentEnable("Orrp2dRoutingProtocol", LOG_LEVEL_ERROR);
    LogComponentEnable("Orrp2dNeighbors", LOG_LEVEL_ERROR);
    //   LogComponentEnable("OrrpRoutingProtocol", LOG_LEVEL_ALL);
    //  LogComponentEnable("BasicEnergySource", LOG_LEVEL_ALL);
    //  LogComponentEnable("MyLossModel",LOG_LEVEL_ALL);
    //  LogComponentEnable("YansWifiChannel",LOG_LEVEL_ALL);
    //  LogComponentEnable("MyPacketSink",LOG_LEVEL_ALL);
    //  LogComponentEnable("OrrpRoutingProtocol",LOG_LEVEL_ALL);
    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("route", "routing protocol name", m_routingProtocol);
    cmd.AddValue("step", "Grid step, m", step);
    cmd.AddValue("seed", "seed", seed);
    cmd.AddValue("width", "grid width", width);
    cmd.AddValue("nodesMove", "nodes move?", nodesMove);
    cmd.AddValue("nodesLocationType", "the type of nodes location", nodesLocationType);
    cmd.Parse(argc, argv);
    SeedManager::SetSeed(seed);
    return true;
}
void OrrpExample::PhyRxOkTrace(std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
{
    std::cout << "PHYRXOK mode=" << mode << " snr=" << snr << " PacketSize= " << packet->GetSize() << std::endl;
}
void OrrpExample::DevTxTrace(std::string context, Ptr<const Packet> p)
{
    std::cout << " TX p size = " << p->GetSize() << std::endl;
}
void OrrpExample::DevRxTrace(std::string context, Ptr<const Packet> p)
{
    std::cout << " RX p size = : " << p->GetSize() << std::endl;
}
void OrrpExample::Run()
{
    Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue(10)); // enable rts cts all the time.
    CreateNodes();
    CreateDevices();
    //  Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxOk", MakeCallback (&OrrpExample::PhyRxOkTrace,this));
    //  Config::Connect ("/NodeList/*/DeviceList/*/Mac/MacRx", MakeCallback (&OrrpExample::DevRxTrace,this));
    //  Config::Connect ("/NodeList/*/DeviceList/*/Mac/MacTx", MakeCallback (&OrrpExample::DevTxTrace,this));
    InstallInternetStack();
    InstallApplications();
    std::cout << "Starting simulation for " << totalTime << " s ...\n";
    // 动画显示
    AnimationInterface anim("2dTest.xml");
    anim.SetMaxPktsPerTraceFile(99999999999999);
    anim.EnableIpv4RouteTracking("2dTest.route", Seconds(0), Seconds(totalTime), Seconds(1));
    Simulator::Stop(Seconds(totalTime));
    Simulator::Run();
    //  Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxOk", MakeCallback (&OrrpExample::PhyRxOkTrace2,this));
    //  Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxOk", MakeCallback (&PhyRxOkTrace));
    Simulator::Destroy();
}
void OrrpExample::Report(std::ostream &)
{
}
void OrrpExample::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;
    // 节点是否移动
    if (nodesMove)
    {
        mobility.SetMobilityModel("ns3::RandomWalk2dMobilityModel",
                                  "Mode", StringValue("Time"),
                                  "Direction", StringValue("ns3::UniformRandomVariable[Min=0.0|Max=6.283184]"),
                                  //                          "Time", StringValue("0.5s"),
                                  "Speed", StringValue("ns3::UniformRandomVariable[Min=0.0|Max=4.0]"),
                                  //                           "Speed", StringValue("ns3::ConstantRandomVariable[Constant=5.0]"),
                                  "Bounds", StringValue("0|1000|0|1000"));
    }
    // 节点初始部署位置
    switch (nodesLocationType)
    {
    case 0:
        mobility.SetPositionAllocator("ns3::GridPositionAllocator",
                                      "MinX", DoubleValue(100.0),
                                      "MinY", DoubleValue(100.0),
                                      "DeltaX", DoubleValue(step),
                                      "DeltaY", DoubleValue(step),
                                      "GridWidth", UintegerValue(width),
                                      "LayoutType", StringValue("RowFirst"));
        std::cout << "采用网格布局 width = " << width << std::endl;
        break;
    case 1:
        double tmp = 200;
        // 设置节点部署在 200*200 米随机位置
        mobility.SetPositionAllocator("ns3::RandomBoxPositionAllocator",
                                      "X", StringValue("ns3::UniformRandomVariable[Min=0.0|Max=200.0]"),
                                      "Y", StringValue("ns3::UniformRandomVariable[Min=0.0|Max=200.0]"),
                                      "Z", StringValue("ns3::UniformRandomVariable[Min=0.0|Max=0.0]"));
        std::cout << "采用200*200随机2维部署" << std::endl;
        break;
    }
    mobility.Install(nodes);
}
void singleDirectionSend(WifiHelper wifi, double transmitDirectAngel, double theta)
{
    std::vector<Ptr<WifiPhy>> m_phyVector = wifi.getPhyVector();
    for (uint32_t i = 0; i < m_phyVector.size(); i++)
    {
        m_phyVector[i]->setTransmitMode(1);
        m_phyVector[i]->setTransmitDirectAngel(transmitDirectAngel);
        m_phyVector[i]->setTheta(theta);
    }
}
void fourDirectionSend(WifiHelper wifi, double pianzhuanAngel, double angel)
{
    std::vector<Ptr<WifiPhy>> m_phyVector = wifi.getPhyVector();
    for (uint32_t i = 0; i < m_phyVector.size(); i++)
    {
        m_phyVector[i]->setTransmitDirectAngel(pianzhuanAngel);
        m_phyVector[i]->setTheta(angel);
    }
}
void twoDirectionSend(WifiHelper wifi, double transmitDirectAngel, double angel)
{
    std::vector<Ptr<WifiPhy>> m_phyVector = wifi.getPhyVector();
    for (uint32_t i = 0; i < m_phyVector.size(); i++)
    {
        m_phyVector[i]->setTransmitMode(2);
        m_phyVector[i]->setTransmitDirectAngel(transmitDirectAngel);
        m_phyVector[i]->setTheta(angel);
    }
}
void OrrpExample::CreateDevices()
{
    WifiMacHelper wifiMac;
    wifiMac.SetType("ns3::AdhocWifiMac");
    OpticalPhyHelper opticalPhy = OpticalPhyHelper::Default();
    OpticalChannelHelper opticalChannel = OpticalChannelHelper::Default();
    // add loss
    //   Ptr<MyPropagationLossModel> lossModel=CreateObject<MyPropagationLossModel>();
    //   lossModel->SetCLamada(0.151);
    //  Ptr<YansWifiChannel> myChannel=wifiChannel.Create();
    //   myChannel->SetPropagationLossModel(lossModel);
    opticalPhy.SetChannel(opticalChannel.Create());
    opticalPhy.Set("TxPowerStart", DoubleValue(16.0206));
    opticalPhy.Set("TxPowerEnd", DoubleValue(16.0206));
    opticalPhy.Set("TxPowerLevels", UintegerValue(1));
    //  opticalPhy.Set("TxGain", DoubleValue(1));
    //  opticalPhy.Set("RxGain", DoubleValue(1));
    //  opticalPhy.Set("RxSensitivity", DoubleValue(-96));
    //  opticalPhy.Set("CcaEdThreshold", DoubleValue(-99));
    // wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("OfdmRate6Mbps"), "RtsCtsThreshold", UintegerValue (0));
    //  wifi.SetRemoteStationManager ("ns3::MinstrelHtWifiManager");
    devices = wifi.Install(opticalPhy, wifiMac, nodes);
    // create trace file
    //   AsciiTraceHelper ascii;
    //   wifiPhy.EnableAscii(ascii.CreateFileStream ("orrp.tr"),nodes);
}
void OrrpExample::printRoute(double showTime)
{
    Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper>("ArouteTest.routes", std::ios::out);
    orrp.PrintRoutingTableAllAt(Seconds(showTime), routingStream);
}
void OrrpExample::InstallInternetStack()
{
    // you can configure ORRP attributes here using orrp.Set(name, value)
    InternetStackHelper stack;
    switch (m_routingProtocol)
    {
    case 2:
    {
        Orrp2dHelper orrp;
        std::ostringstream os;
        os << "10.0.0." << size;
        orrp.m_dst = Ipv4Address(os.str().c_str());
        orrp.m_origin = Ipv4Address("10.0.0.1");
        stack.SetRoutingHelper(orrp); // has effect on the next Install ()
        m_protocolName = "orrp2d";
        std::cout << "used orrp2d routing proto" << std::endl;
        if (printRoutes)
        {
            Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper>("2dTest.routes", std::ios::out);
            orrp.PrintRoutingTableAllAt(Seconds(totalTime - 0.2), routingStream);
        }
    }
    break;
    case 1:
    {
        OrrpHelper orrp;
        stack.SetRoutingHelper(orrp); // has effect on the next Install ()
        m_protocolName = "orrp";
        std::cout << "used orrp routing proto" << std::endl;
        if (printRoutes)
        {
            Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper>("orrpTest.routes", std::ios::out);
            orrp.PrintRoutingTableAllAt(Seconds(totalTime - 0.2), routingStream);
        }
    }
    break;
    case 0:
    {
        AodvHelper aodv;
        stack.SetRoutingHelper(aodv); // has effect on the next Install ()
        m_protocolName = "aodv";
        std::cout << "used aodv routing proto" << std::endl;
        if (printRoutes)
        {
            Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper>("aodvTest.routes", std::ios::out);
            aodv.PrintRoutingTableAllAt(Seconds(totalTime - 0.2), routingStream);
        }
    }
    break;
    }
    //  OrrpHelper orrp;
    //  stack.SetRoutingHelper (orrp); // 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);
}
void OrrpExample::CalculateThroughput(double endTime)
{
    /*
   std::ostringstream ostrStream;
   ostrStream << "./result/orrpTest/orrpTest-size-"<<size<<"-seed-"<<seed<<"-nodesLocationType-"<<nodesLocationType<<"-nodesMove-"<<nodesMove<<"-width-"<<width<<"-step-"<<step<<"-log";
    std::ofstream file;
    file.open (ostrStream.str (),std::ios_base::app);
    Time now = Simulator::Now ();
    double cur = (sink->GetTotalRx () - lastTotalRx) * (double) 8 / 1e6;
    double TotalRx=sink->GetTotalRx ()* (double) 8 / 1e6;
    double TotalTx=source->GetTotalTx ()* (double) 8 / 1e6;
    file<<now.GetSeconds ()<<""<<TotalTx<<" "<<TotalRx<<" "<<cur<<"\n";
  //  std::cout<<now.GetSeconds () << "s 发送数据: \t" <<"send:"<<source->GetTotalTx ()* (double) 8 / 1e6<<"Mbit"<<std::endl;
  //  std::cout<<now.GetSeconds () << "s 接收数据: \t" <<"receive:"<<sink->GetTotalRx ()* (double) 8 / 1e6<<"Mbit"<<std::endl;
    std::cout << now.GetSeconds () << "s 吞吐量: \t" << cur << "Mbit/s" << std::endl;//throughput
     //std::cout << now.GetSeconds () << cur << std::endl;//throughput
    lastTotalRx = sink->GetTotalRx ();
    file.close ();
    if (now<Seconds (endTime))
      //  Simulator::Schedule (MilliSeconds (100), &OrrpExample::CalculateThroughput,this,endTime);
        Simulator::Schedule (Seconds (1), &OrrpExample::CalculateThroughput,this,endTime);
        */
}
void writeData()
{
    /*
      std::vector<Time> sendTime=source->getSendTimeList ();
      std::vector<Time> receiveTime=sink->getReceiveTimeList ();
      std::vector<uint32_t> sendSeq=source->getSendSeqList ();
      std::vector<uint32_t> receiveSeq=sink->getReceiveSeqList ();
      Time now = Simulator::Now ();
      double TotalRx=sink->GetTotalRx ()* (double) 8 / 1e6;
      double TotalTx=source->GetTotalTx ()* (double) 8 / 1e6;
      double avgThroughput=TotalRx/(sendTime [sendTime.size ()-1]-sendTime [0]).GetSeconds ();
      std::vector<Time> delayList;
      delayList.insert (delayList.begin (),sendTime.size (),Time ());
      Time totalDelay=Time ();
      for (uint32_t i=0;i<receiveTime.size ();i++){
          int seq=receiveSeq [i];
          delayList [seq]=receiveTime [i]-sendTime [seq];
          std::cout<<"序列号:"<<seq<<"的包时延是"<<delayList [seq].GetSeconds ()<<"S"<<std::endl;
          totalDelay+=delayList [seq];
      }
      //output to file
      std::ofstream file;
      file.open ("./result/orrpTest/orrpTest-delay-log",std::ios_base::app);
      file<<(double) receiveTime.size ()/sendTime.size ()<<""<<(totalDelay/receiveTime.size ()).GetSeconds ()<<" "<<avgThroughput<<"\n";
      std::cout<<"丢包率:"<<1-(double) receiveTime.size ()/sendTime.size ()<<std::endl;
      std::cout<<"平均时延:"<<(totalDelay/receiveTime.size ()).GetSeconds ()<<std::endl;
      std::cout<<"平均吞吐量:"<<avgThroughput<<std::endl;
      */
    /*
      std::cout<<"数据包发送和接收时间"<<std::endl;
      for (uint32_t i = 0; i < sendTime.size (); i++)
       {
          std::cout<<sendTime [i].GetSeconds ()<<"S 发送了一个数据包"<<"序列号是"<<sendSeq [i]<<std::endl;
       }
      for (uint32_t i = 0; i < receiveTime.size (); i++){
              std::cout<<receiveTime [i].GetSeconds ()<<"S 接收了一个数据包"<<"序列号是"<<receiveSeq [i]<<std::endl;
      }
      */
}
void OrrpExample::InstallApplications()
{
    std::string dataRate = "1Mbps"; // size of packet, 5/8*1024*1024/1472
    //  std::string dataRate = "1Mbps";
    PacketSinkHelper sinkHelper("ns3::UdpSocketFactory", InetSocketAddress(Ipv4Address::GetAny(), 9));
    //  sinkHelper.SetAttribute("EnableSeqTsSizeHeader",BooleanValue (true));
    // 目的节点 ->sinkApp
    ApplicationContainer sinkApp = sinkHelper.Install(nodes.Get(size - 1));
    sink = StaticCast<PacketSink>(sinkApp.Get(0));
    Address remoteAddress;
    remoteAddress = InetSocketAddress(interfaces.GetAddress(size - 1), 9);
    /* Install TCP/UDP Transmitter on the station */
    OnOffHelper sourceHelper("ns3::UdpSocketFactory", Address());
    //  OnOffHelper sourceHelper ("ns3::UdpSocketFactory", (InetSocketAddress (interfaces.GetAddress (size-1), 9)));
    sourceHelper.SetAttribute("Remote", AddressValue(remoteAddress));
    sourceHelper.SetAttribute("PacketSize", UintegerValue(256));
    sourceHelper.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
    sourceHelper.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
    sourceHelper.SetAttribute("DataRate", DataRateValue(DataRate(dataRate)));
    sourceHelper.SetAttribute("EnableSeqTsSizeHeader", BooleanValue(true));
    // 发送节点 ->sourceHelperApp
    ApplicationContainer sourceApp = sourceHelper.Install(nodes.Get(0));
    sourceApp.Get(0)->TraceConnectWithoutContext("Tx", MakeCallback(&TxPacket));
    source = StaticCast<OnOffApplication>(sourceApp.Get(0));
    // 接收应用启动时间
    sinkApp.Start(Seconds(3.0));
    // 发送应用启动时间
    sourceApp.Start(Seconds(3.0));
    Config::ConnectWithoutContext("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", MakeCallback(&OrrpExample::ReceivePacket, this));
    // progress
    Simulator::Schedule(Seconds(totalTime / 100), &PrintProgress, totalTime);
    //  Simulator::Schedule (Seconds (6.0), &OrrpExample::CalculateThroughput,this,totalTime-0.5);
    //  Simulator::Schedule(Seconds(totalTime)-Seconds(0.1),&writeData);
    sinkApp.Stop(Seconds(totalTime) - Seconds(0.2));
    sourceApp.Stop(Seconds(totalTime) - Seconds(2));
    //  printRoute(1.02017);
}

# 结果分析

从上述的代码也可以看出 ns3 的仿真结果可以输出到文件,所以我们可以对文件进行操作,获取想要的结果并生成对应的图像

# gawk 统计

我们可以通过 gawk 来统计文件中数据的均值以做分析。

cat fillName | awk '{if($8!="-nan"){sum+=$5;size=$2+2;n+=1;delay+=$6;cost+=$7;path+=$8}} END {print "Pdr=",sum/n,"reachable =",n/NR,"energyCost=",cost*size/n,"avgCost=",cost/n,"pathLength=",path/n,"delay=",delay/n,"\n",sum/n,"\t",n/NR,"\t",cost*size/n,"\t",cost/n"\t",path/n,"\t",delay/n}'

事实上同样的场景需要做多次,所以我们可以通过 shell 来进行 seed 等变量的改变,然后通过另一个 shell 脚本进行统计

运行脚本例子如下所示:

#!/bin/bash
NODES=(75 100 125 150)
INTERFACE=(12)
ROUTEPROTO=(3 4 0 2)
SEEDS=$(seq 500)
NODESMOVE=(1)
RANGE=250
NODESLOCATIONTYPE=1
TRIALS=1
TOTALTIMES=60
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:bin/
for interNum in ${INTERFACE[@]}
do
    for nodeMove in ${NODESMOVE[@]}
    do
        for range in ${RANGE[@]} 
          do
            for size in ${NODES[@]} 
            do
                for proto in ${ROUTEPROTO[@]}
                do
                for seed in ${SEEDS[@]} 
                do
                    ./waf -v --run "25dTest --nodeSize=$size --nodesMove=$nodeMove --nodesLocationType=$NODESLOCATIONTYPE  --seed=$seed --time=$TOTALTIMES --range=$range --route=$proto --interfaceNum=$interNum"
                      echo a task has done
        #            sleep $TOTALTIMES
                 done
             done
            done
        done
    done
done

awk 统计例子如下所示:

#!/bin/bash
NODES=(75 100 125 150)
INTERFACE=(8)
RANGE=(50)
TOTALTIMES=60
ROUTEPROTO=(5)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:bin/
echo $1
IFS=$(echo -en "\n\b")#注意这里 \n 前面没有空格
for interNum in ${INTERFACE[@]}; do
    for range in ${RANGE[@]}; do
        for size in ${NODES[@]}; do
            for proto in ${ROUTEPROTO[@]}; do
                pname=""
                case $proto in
                0)
                    pname="VBF实验结果"
                    resFile="VBF"
                    ;;
                1)
                    pname="CORRP实验结果"
                    resFile="CORRP"
                    ;;
                2)
                    pname="HH VBF实验结果"
                    resFile="HH-VBF"
                    ;;
                3)
                    pname="o orrp实验结果"
                    resFile="ORRP"
                    ;;
                4)
                    pname="vorrp实验结果"
                    resFile="VORR"
                    ;;
                5)
                    pname="R-orrp实验结果"
                    resFile="RORR"                   
                    ;;
                esac
                #echo $RANGE"m 范围 -"$size"节点 -"$interNum"interfaceNum-"$TOTALTIMES"S"--$pname
                #cat $RANGE"m 范围 -"$size"节点 -"$interNum"interfaceNum-"$TOTALTIMES"S"--${pname} | awk '{if ($8!="-nan"){sum+=$5;size=$2+2;n+=1;delay+=$6;cost+=$7;path+=$8}} END {print "Pdr=",sum/n,"reachable =",n/NR,"energyCost=",cost*size/n,"avgCost=",cost/n,"pathLength=",path/n,"delay=",delay/n,"\n",sum/n,"\t",n/NR,"\t",cost*size/n,"\t",cost/n"\t",path/n,"\t",delay/n}'
                cat $RANGE"m范围-"$size"节点-"$interNum"interfaceNum-"$TOTALTIMES"S"--${pname} | awk '{if($8!="-nan"){sum+=$5;size=$2+2;n+=1;delay+=$6;cost+=$7;path+=$8}} END {print size-2,"\t",sum/n,"\t",n/NR,"\t",cost*size/n,"\t",cost/n"\t",path/n,"\t",delay/n}'>>${resFile}.txt
                #echo a task has done
                echo a task has done
            done
        done
    done
done
IFS=$(echo -en " \n\t")#注意这里 \n 前面有个空格
echo "end"

# gnuplot 绘制结果图

我们可以采用类似于这样的脚本来绘制图像

set style line 80 lt rgb "#000000" lw 5
set style line 81 lt 0  # dashed
set style line 81 lt rgb "#000000"  # grey
set grid back linestyle 81
set ytics 0.1
set xtics 5
set style line 1 lt rgb "#00A000" lw 2 pt 9 pointsize 2
set style line 2 lt rgb "#A00000" lw 2 pt 11 pointsize 2
set style line 3 lt rgb "#5060D0" lw 2 pt 1 pointsize 2
set style line 4 lt rgb "#F25900" lw 2 pt 2 pointsize 2
set style line 5 lt rgb "#A00000" lw 1 pt 8 pointsize 2
set style line 6 lt rgb "#00A000" lw 1 pt 2 pointsize 2
set style line 7 lt rgb "#5060D0" lw 1 pt 4 pointsize 2
set style line 8 lt rgb "#F25900" lw 1 pt 6 pointsize 2


#set output ".pdf"
set xlabel "Numbers of nodes" font ",20"
set ylabel "Packet delivery ratio(%)" font ",20" offset 1.5,0,0
set key at 85,0.4 font ",20" height 0.9 width 0.5 spacing 1
set key box 
set xrange [40:90]
set yrange [0:1]
plot  "0.5-20-15-orrp2d.txt" u 1:2 title "RR" w lp ls 2, "0.5-20-15-o-orrp.txt" u 1:2 title "ORRP" w lp ls 1,  "0.5-20-15-R-ORR.txt" u 1:2 title "  R-ORR" w lp ls 7, "v-orrp.txt" u 1:2 title "  V-ORR" w lp ls 8
set terminal postscript eps color solid linewidth 2 "Helvetica" 20
set output "pdr.eps"
replot
set output

绘图例子

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

jluyeyu 微信支付

微信支付

jluyeyu 支付宝

支付宝