구현

IRSML 시뮬레이션 직접 구성하기 - 4

Beige00 2024. 2. 22. 17:16

우선 구해낸 데이터가 옳게 구한 데이터이든 아니든 간에 어짜피 아니라 판단되면 나중에 csv 파일에 들어갈 데이터만 바꿔서 다시 실행해주면 된다고 생각한다.

따라서 구현-3 에서 구현한 코드에 결과물을 csv로 정리해서 나오게 추가 구현을 해주고, 이를 Colab에 옮겨서 일단 학습부터 해볼 것이다.

 

더보기
#include <sstream>
#include <fstream>
#include <ns3/core-module.h>
#include <ns3/network-module.h>
#include <ns3/applications-module.h>
#include <ns3/mobility-module.h>
#include <ns3/internet-module.h>
#include <ns3/yans-wifi-helper.h>
#include <ns3/aodv-helper.h>
#include <ns3/adhoc-wifi-mac.h>
#include <ns3/wifi-mac-queue.h>
#include <ns3/qos-txop.h>
#include <vector>
#include <string>

using namespace ns3;

std::vector<std::vector<std::string>> QL;
std::vector<std::vector<std::string>> TP;
uint32_t APnum = 3;


void makeCsvFile(const std::string& filename, const std::vector<std::vector<std::string>>& data){
    std::ofstream file(filename);
    for(const auto& row : data){
        for(auto it = row.begin(); it!=row.end(); ++it){
            file<<*it;
            if(next(it)!=row.end()){
                file<<",";
            }
        }
        file<<std::endl;
    }
    file.close();
}

void TracingParameter(NetDeviceContainer n){
    for(uint32_t i=0; i<n.GetN(); i++){
        PointerValue ptr;
        
        n.Get(i)->GetAttribute("Mac",ptr);
        Ptr<AdhocWifiMac> mac = ptr.Get<AdhocWifiMac>();
        Ptr<WifiMacQueue> txop = mac->GetTxopQueue(AC_BE);
        QL.push_back({std::to_string(Simulator::Now().GetSeconds()),std::to_string(i),std::to_string(txop->GetNPackets())});
    }
    for(uint32_t i=0; i<APnum; i++){
        Ptr<PacketSink> psink;
        ApplicationContainer app = n.Get(i)->GetNode()->GetApplication(0);
        psink = StaticCast<PacketSink>(app.Get(0));
        double averageTL = ((psink->GetTotalRx()*8)/(1e6*Simulator::Now().GetSeconds()));
        TP.push_back({std::to_string(Simulator::Now().GetSeconds()),std::to_string(i),std::to_string(averageTL)});
    }
    Simulator::Schedule(Seconds(1.0),&TracingParameter,n);
}


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

    QL.push_back({"Second","NodeID","QueueLength"});
    TP.push_back({"Second","NodeID","ThroughPut"});

    static unsigned int seed = 5323;

    seed = 8253729*seed + 2396403;

    int runN = seed%3;
    double TotalTime = 250.0;
    seed %= 32768;


    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(250.0));
    wifiPhy.SetErrorRateModel("ns3::YansErrorRateModel");
    wifiPhy.SetChannel(wifiChannel.Create());
    WifiMacHelper mac;
    wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager");
    mac.SetType("ns3::AdhocWifiMac","QosSupported",BooleanValue(true));
    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);

    ApplicationContainer sources;

    for(uint32_t i=0; i<12; i++){
        uint32_t port = 9;
        for(uint32_t j=0; j<APnum; j++){
            auto ipv4 = ApNodes.Get(j)->GetObject<Ipv4>();
            const auto address = ipv4->GetAddress(1,0).GetLocal();
            InetSocketAddress sinkSocket (address, port++);
            sinkSocket.SetTos(0x70);
            BulkSendHelper sourceHelper ("ns3::TcpSocketFactory",sinkSocket);
            sources.Add(sourceHelper.Install(mobileNodes.Get(i)));
        }
      }
    sources.Start(Seconds(2.0));
    sources.Stop(Seconds(TotalTime-2.0));


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

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

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


    Simulator::Schedule(Seconds(4.0),&TracingParameter,allDevices);
    Simulator::Stop(Seconds(TotalTime));

    Simulator::Run();
    Simulator::Destroy();
    makeCsvFile("QueueLength.csv",QL);
    makeCsvFile("ThroughPut.csv",TP);
}

//csv 파일을 결과로 출력해내는 최종 코드이다. 추후 데이터 소스의 문제가 있다고 판단될 시,
//데이터를 구하는 Tracing 부분만 수정해서 사용하면 될 것이다.

만들어낸 Csv 파일의 모습

그러나 아직 ns3에서 해줄 일이 끝나지 않았다.

우리가 사용할 방식은 SL, Regression이기 때문에 csv 파일에 결과 값인 PBP가 있어야하는 것이다.

따라서 Tracing file에 PBP를 써주어야한다.

일단 TCPbulkApplication이 설치되어있는 MH들과 PacketSinkApplication이 설치되어있는 AP에서 PBP를 따로 구해서 기록해줘야할 것 같다고 접근했다.

 

그러면 어떻게 PBP를 구해야할까?

처음에 생각한건 그냥 MH에서 보낸 데이터 갯수의 총합과 AP 측에서 받은 데이터의 총합의 비율을 떠올렸으나, 이 경우 

Packet Block이 아니라 Packet Loss까지 포함하게 된다.

논문의 PBP 정의를 살펴보자.

PBP의 정의

즉, Source to destination의 route PBP는 1-( 1 - 모든 s to d i,j간 경로상의 PBP의 곱 ) 이다.

이를 구하는 함수를 짤 것이다.

일단 i,j가 이웃인 경우에 PBP를 구해야한다.

그럼 각 링크 별로 전부 PBP를 구해야하는 건데, 어떻게 해야 각 링크별로 PBP를 구할까?

일단 ns3 자체에서 지원하는 방법을 알아봤는데 FlowMonitor를 사용하여 생성하는 방법이 있는 것 같다.

생성해낸 Csv 파일

더보기
#include <sstream>
#include <fstream>
#include <ns3/core-module.h>
#include <ns3/network-module.h>
#include <ns3/applications-module.h>
#include <ns3/mobility-module.h>
#include <ns3/internet-module.h>
#include <ns3/yans-wifi-helper.h>
#include <ns3/aodv-helper.h>
#include <ns3/adhoc-wifi-mac.h>
#include <ns3/wifi-mac-queue.h>
#include <ns3/qos-txop.h>
#include <vector>
#include <string>
#include <ns3/flow-monitor-module.h>
#include <ns3/netanim-module.h>


using namespace ns3;

std::vector<std::vector<std::string>> QL;
std::vector<std::vector<std::string>> TP;
std::vector<std::vector<std::string>> FM;
uint32_t APnum = 3;
uint8_t srcIP[4];
uint8_t dstIP[4];


void makeCsvFile(const std::string& filename, const std::vector<std::vector<std::string>>& data){
    std::ofstream file(filename);
    for(const auto& row : data){
        for(auto it = row.begin(); it!=row.end(); ++it){
            file<<*it;
            if(next(it)!=row.end()){
                file<<",";
            }
        }
        file<<std::endl;
    }
    file.close();
}

void TracingParameter(NetDeviceContainer n){
    for(uint32_t i=0; i<n.GetN(); i++){
        PointerValue ptr;
        
        n.Get(i)->GetAttribute("Mac",ptr);
        Ptr<AdhocWifiMac> mac = ptr.Get<AdhocWifiMac>();
        Ptr<WifiMacQueue> txop = mac->GetTxopQueue(AC_BE);
        QL.push_back({std::to_string(Simulator::Now().GetSeconds()),std::to_string(i),std::to_string(txop->GetNPackets())});
    }
    for(uint32_t i=0; i<APnum; i++){
        Ptr<PacketSink> psink;
        ApplicationContainer app = n.Get(i)->GetNode()->GetApplication(0);
        psink = StaticCast<PacketSink>(app.Get(0));
        double averageTL = ((psink->GetTotalRx()*8)/(1e6*Simulator::Now().GetSeconds()));
        TP.push_back({std::to_string(Simulator::Now().GetSeconds()),std::to_string(i),std::to_string(averageTL)});
    }
    Simulator::Schedule(Seconds(1.0),&TracingParameter,n);
}


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

    QL.push_back({"Second","NodeID","QueueLength"});
    TP.push_back({"Second","NodeID","ThroughPut"});
    FM.push_back({"Flow ID","Src","Dst","Tx","Rx","Throughput"});

    static unsigned int seed = 5323;

    seed = 8253729*seed + 2396403;

    int runN = seed%3;
    double TotalTime = 250.0;
    seed %= 32768;


    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(250.0));
    wifiPhy.SetErrorRateModel("ns3::YansErrorRateModel");
    wifiPhy.SetChannel(wifiChannel.Create());
    WifiMacHelper mac;
    wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager");
    mac.SetType("ns3::AdhocWifiMac","QosSupported",BooleanValue(true));
    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);

    ApplicationContainer sources;

    for(uint32_t i=0; i<12; i++){
        uint32_t port = 9;
        for(uint32_t j=0; j<APnum; j++){
            auto ipv4 = ApNodes.Get(j)->GetObject<Ipv4>();
            const auto address = ipv4->GetAddress(1,0).GetLocal();
            InetSocketAddress sinkSocket (address, port++);
            sinkSocket.SetTos(0x70);
            BulkSendHelper sourceHelper ("ns3::TcpSocketFactory",sinkSocket);
            sources.Add(sourceHelper.Install(mobileNodes.Get(i)));
        }
      }
    sources.Start(Seconds(2.0));
    sources.Stop(Seconds(TotalTime-2.0));


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

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

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

    Ptr<FlowMonitor> flowmon;
    FlowMonitorHelper flow;
    flowmon = flow.InstallAll();

    Simulator::Schedule(Seconds(4.0),&TracingParameter,allDevices);
    Simulator::Stop(Seconds(TotalTime));

    Simulator::Run();
    flowmon->CheckForLostPackets();
    Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier> (flow.GetClassifier ());
    std::map<FlowId, FlowMonitor::FlowStats> stats = flowmon->GetFlowStats ();

    for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator iter = stats.begin (); iter != stats.end (); ++iter)
    {
        Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow (iter->first);
        t.sourceAddress.Serialize(srcIP);
        t.destinationAddress.Serialize(dstIP);
        std::string srcAddr,dstAddr;
        for(int i=0; i<4; i++){
            srcAddr+=std::to_string(srcIP[i]);
            srcAddr+=".";
            dstAddr+=std::to_string(dstIP[i]);
            dstAddr+=".";
        }
        FM.push_back({std::to_string(iter->first), srcAddr,dstAddr,std::to_string(iter->second.txPackets),
        std::to_string(iter->second.rxPackets),std::to_string(iter->second.rxBytes * 8.0 / (iter->second.timeLastRxPacket.GetSeconds()-iter->second.timeFirstTxPacket.GetSeconds()) / 1024)});
    }
    Simulator::Destroy();
    makeCsvFile("QueueLength.csv",QL);
    makeCsvFile("ThroughPut.csv",TP);
    makeCsvFile("FlowMetrics.csv",FM);
}

//csv 파일을 결과로 출력해내는 최종 코드이다. 추후 데이터 소스의 문제가 있다고 판단될 시,
//데이터를 구하는 Tracing 부분만 수정해서 사용하면 될 것이다.

이제 저 csv 파일을 이용해서 PBP를 계산해내고, 각 src->dst 에 따라 Link Number를 지정해주어 학습에 사용하기 용이하게 분류해주는 방법을 생각해봐야겠다.