구현

(NS-3) IRSML 시뮬레이션 직접 구성하기 - 2

Beige00 2024. 2. 6. 17:12

결국 기존 논문에 제시된 시뮬레이션 토폴로지로 Adhoc network data를 뽑아내는데는 실패했다.

다음은 최종으로 건드렸던 코드이다.

#include <sstream>
#include <random>
#include <string>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/config-store-module.h"
#include "ns3/netanim-module.h"
#include "ns3/internet-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/aodv-helper.h"

#define SIMULATION_NUM 1020
#define SIMULATION_AREA 1000
#define SIMULATION_TIME 2400
#define APnum 17
#define TransmitPower 12
#define ReceiverSensitivity -76
#define TransmissionRange 250
#define BERthreshold 0.000001
#define MinSNR 25
#define dataRate 54

using namespace ns3;

NS_LOG_COMPONENT_DEFINE("IRSMLResult");

int numberOfMHs[7] = {30,35,40,45,50,55,60};
int APx[] = {250,500,750,200,400,600,800,250,500,750,200,400,600,800,250,500,750};
int APy[] = {166,166,166,333,333,333,333,500,500,500,665,665,665,665,832,832,832};
Ptr<PacketSink> psink1;
Ptr<PacketSink> psink2;
uint64_t lastTotalRx1=0;
uint64_t lastTotalRx2=0;

int
main(int argc, char* argv[]){

    std::random_device rd;

    //for(int i=0; i<SIMULATION_NUM; i++){

        SeedManager::SetSeed(10);
        SeedManager::SetRun(1);

        //node 수 select
        uint32_t nWifi;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<int> dis(0,6);
        nWifi = numberOfMHs[dis(gen)];

        //AP
        NodeContainer sinkNodes;
        sinkNodes.Create(APnum);

        NodeContainer adhocNodes;
        adhocNodes.Create(nWifi);

        NodeContainer allNodes;
        allNodes.Add(sinkNodes);
        allNodes.Add(adhocNodes);
           
        NetDeviceContainer allDevicesMH;
        NetDeviceContainer allDevicesAP;

        //RTS&CTS setting
        Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold",StringValue("0"));

  

        //Set AP mobility model
        MobilityHelper mobility;
        Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
        for(int i=0; i<APnum; i++){
            positionAlloc->Add(Vector(APx[i],APy[i],0));
        }
        mobility.SetPositionAllocator(positionAlloc);
        mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
        mobility.Install(sinkNodes);
        
        //Set MH mobility Model
        ObjectFactory points;
        points.SetTypeId("ns3::RandomRectanglePositionAllocator");
        points.Set("X",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=1000.0]"));
        points.Set("Y",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=1000.0]"));
        Ptr<PositionAllocator> waypos = points.Create() -> GetObject<PositionAllocator>();   
        mobility.SetMobilityModel("ns3::RandomWaypointMobilityModel",
        "Speed",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=20.0]"),
        "Pause",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=2.0]"),
        "PositionAllocator",PointerValue(waypos));
        mobility.Install(adhocNodes);


        //Set Wifi
        WifiHelper wifi;
        wifi.SetStandard(WIFI_STANDARD_80211ac);
        YansWifiPhyHelper wifiPhy;
        YansWifiChannelHelper wifiChannel;
        wifiChannel.SetPropagationDelay("ns3::ConstantSpeedPropagationDelayModel");
        wifiChannel.AddPropagationLoss("ns3::RangePropagationLossModel","MaxRange",DoubleValue(TransmissionRange));
        wifiPhy.SetErrorRateModel("ns3::YansErrorRateModel");
        wifiPhy.SetChannel(wifiChannel.Create());
        WifiMacHelper wifiMac;
        wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager","DataMode",StringValue("OfdmRate54Mbps"),"ControlMode",StringValue("VhtMcs0"));
        wifiMac.SetType("ns3::AdhocWifiMac");
        allDevicesMH = wifi.Install(wifiPhy,wifiMac,adhocNodes);
        allDevicesAP = wifi.Install(wifiPhy,wifiMac,sinkNodes);
        NetDeviceContainer allDevices = NetDeviceContainer(allDevicesAP, allDevicesMH);

        //IPv4 setting
        InternetStackHelper internet;
        AodvHelper aodv;
        internet.SetRoutingHelper(aodv);
        internet.Install(allNodes);
        Ipv4AddressHelper address;
        address.SetBase("10.1.1.0","255.255.255.0");
        Ipv4InterfaceContainer allInterfaces;
        allInterfaces = address.Assign(allDevices);



        uint16_t port1 = 9;

        //sink app install to AP
        PacketSinkHelper sink1 ("ns3::UdpSocketFactory",InetSocketAddress(Ipv4Address::GetAny(), port1));
        ApplicationContainer apps_sink1 = sink1.Install(sinkNodes);
        psink1 = StaticCast<PacketSink> (apps_sink1.Get(16));
        psink2 = StaticCast<PacketSink> (apps_sink1.Get(9));
        apps_sink1.Start(Seconds(0.0));
        apps_sink1.Stop(Seconds(SIMULATION_TIME));

        Ptr<FlowMonitor> flowmon;
        FlowMonitorHelper flowmonHelper;
        flowmon = flowmonHelper.InstallAll();
        AnimationInterface anim("IRSML2_demo.xml");
        anim.SetMobilityPollInterval(Seconds(2.0));
        anim.SetMaxPktsPerTraceFile(99999999);
        for(int i=0; i<APnum; i++){
            anim.UpdateNodeSize(i,6,6);
            anim.SetConstantPosition(sinkNodes.Get(i),APx[i],APy[i],0);
            anim.UpdateNodeColor(i,255,255,102);
            anim.UpdateNodeDescription(i,"AP"+std::to_string(i));
        }
        for(uint32_t i=APnum; i<allDevices.GetN();i++){
            anim.UpdateNodeDescription(i,"MH"+std::to_string(i));
        }
        anim.EnablePacketMetadata(true);
        anim.EnableIpv4RouteTracking("IRSML2_routetable.xml",Seconds(1),Seconds(SIMULATION_TIME-1),Seconds(SIMULATION_TIME/2));
        anim.EnableIpv4L3ProtocolCounters(Seconds(0),Seconds(SIMULATION_TIME-1));
        anim.EnableQueueCounters(Seconds(0),Seconds(SIMULATION_TIME-1));
        
        wifiPhy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11_RADIO);
        wifiPhy.EnablePcap("IRSML2",allDevicesAP.Get(0));
        wifiPhy.EnablePcap("IRSML2-Mobile",allDevicesMH.Get(0));

        Simulator::Stop(Seconds(SIMULATION_TIME));
        Simulator::Run();
        flowmon->SerializeToXmlFile("IRSML2_flowmetrics.xml",true,true);
        double average1 = ((psink1->GetTotalRx()*8)/(1e6*SIMULATION_TIME));
        double average2 = ((psink2->GetTotalRx()*8))/(1e6*SIMULATION_TIME);
        lastTotalRx1=psink1->GetTotalRx();
        lastTotalRx2=psink2->GetTotalRx();
        
        Simulator::Destroy();
        std::cout<<"\n 17 Access Point Average throughput: "<<average1<<" Mbit/s"<<std::endl;
        std::cout<<"\n 17 Access Point LastTotalRx: "<<lastTotalRx1<<" Mbit"<<std::endl;
        std::cout<<"\n 4 Access Point Average throughput: "<<average2<<" Mbit/s"<<std::endl;
        std::cout<<"\n 4 Access Point LastTotalRx: "<<lastTotalRx2<<" Mbit"<<std::endl;
    //}
    
}

내가 구상했던 작동은 다음과 같다.

 

1. 랜덤하게 Mobile Host의 수를 결정.

2. APnum만큼의 Ap node 또한 생성.

3. 토폴로지에 주어진 AP node 의 위치를 참고해 ConstantPositionMobilityModel을 이용해 Ap node 위치 결정.

4. RandomWayPoint에 주어진 Simulator parameter를 입력 후 AdhocWifi 생성.

5. Routing Protocol은 Adhoc Distance Vector 사용.

6. PacketSinkHelper를 AP node에 설치, OnOffApplication을 MH node에 설치. MH node의 OnOffApplication은 모든 AP node IP에 연결한다.

7. Animation file(xml) 생성, 패킷 캡처 파일 생성.

 

그러나 이것 저것 고쳐봐도 계속해서 작동하지 않았고 최종적으로는 DelayNegative error에서 더 이상 개선점을 찾지 못해 일단 보류하였다. 예상되는 문제점으로는 다음의 문제점이 있다.

 

1. 너무 토폴로지가 무거워서 시뮬레이터가 오작동.

(가능성 높음. 그냥 Example로 주어진 AdhocNetwork에 host 수를 늘리거나 DataRate를 늘리는 등 이벤트 량을 늘릴 시 동일한 DelayNegative error가 발생했음. 찾아보니 OverFlow라고 함.

https://groups.google.com/g/ns-3-users/c/qqcVRhpyy8M)

 

2. 구현 상의 문제.

 

일단 무엇이 되었던 간에, Parameter만 추상적으로 주어지고 나머지 프로토콜이나 구체적인 환경은 제시되지 않아 문제점을 쉽사리 예측할 수가 없었다.

 

그렇게 고민을 하고 있던 와중 교수님과 면담을 하는 과정에서 굳이 IRSML 논문에 제시된 시나리오를 그대로 따라간 데이터를 이용할 필요가 없다는 조언을 받았다.

생각해보면 지금 내가 하고자 하는 일은 IRSML 논문의 Validation이 아니라 알고리즘이 적용되었을 때 효과가 있나? 이고,

해당 논문에서는 일반적인 Network 상황에 적용을 가정하였으므로 내가 짠 Adhoc Network 환경에서도 작동을 해야만 한다.

그래서 좀 더 가벼운 Network Topology와 Scenario를 직접 작성해보았다.

#include <sstream>
#include <ns3/core-module.h>
#include <ns3/network-module.h>
#include <ns3/applications-module.h>
#include <ns3/netanim-module.h>
#include <ns3/mobility-module.h>
#include <ns3/internet-module.h>
#include <ns3/flow-monitor-module.h>
#include <ns3/yans-wifi-helper.h>
#include <ns3/aodv-helper.h>

using namespace ns3;

Ptr<PacketSink> psink1;
Ptr<PacketSink> psink2;
Ptr<PacketSink> psink3;

int
main(int argc, char* argv[]){

    static unsigned int seed = 5323;

    seed = 8253729*seed + 2396403;

    int runN = seed%3;

    seed %= 32768;


    uint32_t APnum = 3;
    double TotalTime = 300.0;
    SeedManager::SetSeed(seed);
    SeedManager::SetRun(runN);

    NodeContainer ApNodes;
    ApNodes.Create(APnum);
    NodeContainer mobileNodes;
    mobileNodes.Create(12);

    NodeContainer adhocNodes;
    adhocNodes.Add(ApNodes);
    adhocNodes.Add(mobileNodes);
    
    NetDeviceContainer mobileDevices;
    NetDeviceContainer APDevices;

    //RTS&CTS setting
    Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold",StringValue("0"));


    MobilityHelper mobility;
    Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
    positionAlloc->Add(Vector(250,350,0));
    positionAlloc->Add(Vector(125,150,0));
    positionAlloc->Add(Vector(375,150,0));
    mobility.SetPositionAllocator(positionAlloc);
    mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
    mobility.Install(ApNodes);

    ObjectFactory points;
    points.SetTypeId("ns3::RandomRectanglePositionAllocator");
    points.Set("X",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=500.0]"));
    points.Set("Y",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=500.0]"));
    Ptr<PositionAllocator> waypos = points.Create()->GetObject<PositionAllocator>();
    mobility.SetMobilityModel("ns3::RandomWaypointMobilityModel",
    "Speed",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=20.0]"),
    "Pause",StringValue("ns3::UniformRandomVariable[Min=0.0|Max=2.0]"),
    "PositionAllocator",PointerValue(waypos));
    mobility.Install(mobileNodes);

    WifiHelper wifi;
    wifi.SetStandard(WIFI_STANDARD_80211ac);
    YansWifiPhyHelper wifiPhy;
    YansWifiChannelHelper wifiChannel;
    wifiChannel.SetPropagationDelay("ns3::ConstantSpeedPropagationDelayModel");
    wifiChannel.AddPropagationLoss("ns3::RangePropagationLossModel","MaxRange",DoubleValue(150.0));
    wifiPhy.SetErrorRateModel("ns3::YansErrorRateModel");
    wifiPhy.SetChannel(wifiChannel.Create());
    WifiMacHelper mac;
    wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager");
    mac.SetType("ns3::AdhocWifiMac");
    mobileDevices = wifi.Install(wifiPhy,mac,mobileNodes);
    APDevices = wifi.Install(wifiPhy,mac,ApNodes);
    NetDeviceContainer allDevices = NetDeviceContainer(APDevices,mobileDevices);

    InternetStackHelper internet;
    AodvHelper aodv;
    internet.SetRoutingHelper(aodv);
    internet.Install(adhocNodes);
    Ipv4AddressHelper address;
    address.SetBase("10.1.1.0","255.255.255.0");
    Ipv4InterfaceContainer allInterfaces;
    allInterfaces = address.Assign(allDevices);

    uint16_t port1 = 50000;
    uint16_t port2 = 50001;
    uint16_t port3 = 50002;

    BulkSendHelper sourceHelper1 ("ns3::TcpSocketFactory",InetSocketAddress(allInterfaces.GetAddress(0),port1));
    ApplicationContainer sourceApp1 = sourceHelper1.Install(mobileNodes);
    sourceApp1.Start(Seconds(20.0));
    sourceApp1.Stop(Seconds(TotalTime-20.0));

    BulkSendHelper sourceHelper2 ("ns3::TcpSocketFactory",InetSocketAddress(allInterfaces.GetAddress(1),port2));
    ApplicationContainer sourceApp2 = sourceHelper2.Install(mobileNodes);
    sourceApp2.Start(Seconds(20.0));
    sourceApp2.Stop(Seconds(TotalTime-20.0));

    BulkSendHelper sourceHelper3 ("ns3::TcpSocketFactory",InetSocketAddress(allInterfaces.GetAddress(2),port3));
    ApplicationContainer sourceApp3 = sourceHelper3.Install(mobileNodes);
    sourceApp3.Start(Seconds(20.0));
    sourceApp3.Stop(Seconds(TotalTime-20.0));

    PacketSinkHelper sinkHelper1 ("ns3::TcpSocketFactory",InetSocketAddress(Ipv4Address::GetAny(), port1));
    ApplicationContainer sinkApp1 = sinkHelper1.Install(ApNodes.Get(0));
    sinkApp1.Start(Seconds(0.0));
    sinkApp1.Stop(Seconds(TotalTime));

    PacketSinkHelper sinkHelper2 ("ns3::TcpSocketFactory",InetSocketAddress(Ipv4Address::GetAny(), port2));
    ApplicationContainer sinkApp2 = sinkHelper2.Install(ApNodes.Get(1));
    sinkApp2.Start(Seconds(0.0));
    sinkApp2.Stop(Seconds(TotalTime));

    PacketSinkHelper sinkHelper3 ("ns3::TcpSocketFactory",InetSocketAddress(Ipv4Address::GetAny(), port3));
    ApplicationContainer sinkApp3 = sinkHelper3.Install(ApNodes.Get(2));
    sinkApp3.Start(Seconds(0.0));
    sinkApp3.Stop(Seconds(TotalTime));

    psink1 = StaticCast<PacketSink> (sinkApp1.Get(0));
    psink2 = StaticCast<PacketSink> (sinkApp2.Get(0));
    psink3 = StaticCast<PacketSink> (sinkApp3.Get(0));


    Ptr<FlowMonitor> flowmon;
    FlowMonitorHelper flow;
    flowmon = flow.InstallAll();
    AnimationInterface anim ("IRSML_demo.xml");
    anim.SetMaxPktsPerTraceFile(100000000);
    anim.UpdateNodeDescription(0,"AP-1");
    anim.UpdateNodeDescription(1,"AP-2");
    anim.UpdateNodeDescription(2,"AP-3");
    anim.EnablePacketMetadata(true);
    anim.EnableIpv4RouteTracking("IRSML_routes.xml",Seconds(1),Seconds(TotalTime),Seconds(TotalTime/2));
    anim.EnableIpv4L3ProtocolCounters(Seconds(0),Seconds(TotalTime-1));
    anim.EnableQueueCounters(Seconds(0),Seconds(TotalTime-1));
    
    wifiPhy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11_RADIO);
    wifiPhy.EnablePcap("IRSML",allDevices.Get(0));
    wifiPhy.EnablePcap("IRSML-Mobile",allDevices.Get(6));

    Simulator::Stop(Seconds(TotalTime));

    Simulator::Run();
    flowmon->SerializeToXmlFile("IRSML_flowmetrics.xml",true,true);
    Simulator::Destroy();
    double averageThro1 = ((psink1->GetTotalRx()*8)/(1e6*TotalTime));
    double averageThro2 = ((psink2->GetTotalRx()*8)/(1e6*TotalTime));
    double averageThro3 = ((psink3->GetTotalRx()*8)/(1e6*TotalTime));
    std::cout<<"Access Point 1 info:"<<std::endl;
    std::cout<<"TotalRx : "<<psink1->GetTotalRx()<<" bytes"<<std::endl;
    std::cout<<"Average Throughput : "<<averageThro1<<" Mbit/s"<<std::endl;
    std::cout<<"Access Point 2 info:"<<std::endl;
    std::cout<<"TotalRx : "<<psink2->GetTotalRx()<<" bytes"<<std::endl;
    std::cout<<"Average Throughput : "<<averageThro2<<" Mbit/s"<<std::endl;
    std::cout<<"Access Point 3 info:"<<std::endl;
    std::cout<<"TotalRx : "<<psink3->GetTotalRx()<<" bytes"<<std::endl;
    std::cout<<"Average Throughput : "<<averageThro3<<" Mbit/s"<<std::endl;


}

 

시나리오를 경량화하면서 anim xml 파일의 크기 또한 줄어들었고, Average Throughput과 Total Rx도 정상적으로 찍히기 시작했다.

1.01GB 까지는 bad alloc 오류가 발생하지 않는 듯 하다.
최종 각 AP Throughput

이 Flow monitor 파일을 봤을 때도 어느정도 납득이 되는 Adhoc Network data가 수집되었음을 알 수 있다.

또한 Packet Loss Ratio 등 여러가지 데이터도 동시에 수집이 되고 있다.

Flow monitor 파일을 확인하던 중, 10.1.1.10 (node 9)와 10.1.1.2 (Ap node 2)의 통신이 되지 않는 것을 확인했다.

node 9의 movement history와 AP 들의 Coverage 정보이다. AP node 2의 Coverage에는 잠시동안만 들어가는 것을 볼 수 있다.

일단 AP 들의 Coverage를 150m 에서 250m 로 늘리고 데이터를 재수집하는 것으로 Test Scenario 구현을 마무리 짓기로 결정하였다. 구현에 너무 많은 시간이 지체됐기에  다음부터 Attribute들을 추출해서 ML 로 데이터를 옮기는 작업을 시작해야겠다.