Sixth.cc 예제 파일 설명

Sixth example scenario

여섯번째 예제는 fifth.cc와 굉장히 유사합니다. 네트워크 부분은 아예 똑같은 소스코드로 구성되어있습니다. 노드 2개중 1개는 사용자가 만든 MyApp이라는 어플리케이션을 사용하고, 다른 한쪽에서는 받은 패킷을 버리는 PacketSinkHelper 어플리케이션을 사용합니다. point-to-point 채널을 이용하여 2개의 노드를 통신하고 TCP를 transmission layer 프로토콜로 사용합니다.

그렇다면 여섯번째 예제는 5번째 예제와 어떠한 차이가 있을까요? 유일한 차이점은 바로 Tracing 데이터를 출력하는 방법에 있습니다. fifth.cc는 Tracing 데이터를 그냥 터미널에 출력하는 방법을 사용했습니다. 사실 터미널에 바로 출력하는 방법은 Tracing 데이터를 사용하기 불편하다는 문제가 있습니다. 일반적으로 Tracing 데이터가 굉장히 긴데, 이를 터미널창에 바로 출력하게 되면 데이터를 한눈에 파악하기 힘들고 Tracing 데이터와 일반 출력이 섞여서 어떤 값들이 출력되었는지 알기 힘들다는 문제가 있습니다. 하지만 가장 큰 문제는 Tracing 데이터를 원하는 형태로 가공하는데 불편하다는 문제가 있습니다.

fifth.cc만해도 서로 다른 2가지 Tracing 데이터가 섞여 있었습니다. 1개는 CWND에 대한 데이터였고 다른 1개는 Packet Loss에 대한 Tracing 데이터였습니다. 만약 CWND의 그래프를 그리고 싶다고 하면 CWND 데이터만 모여있는 파일이 필요한데 CWND 데이터와 Packet Loss 데이터가 섞여 있다면 그래프를 그리기 전 미리 두개의 데이터를 나눠줘야 한다는 문제가 있습니다. 심지어 데이터가 파일로 저장되지 않고 터미널에 출력된다면 출력된 데이터를 파일로 저장해야한다는 문제도 있습니다. NS3에서는 사용자가 이런 불편을 겪지 않도록 Tracing 데이터를 파일에 저장하고, 서로 다른 2개의 Tracing 데이터를 다른 파일에 나누어 저장하는 기능을 제공하고 있습니다. 이번 포스팅에서는 이 내용에 대해 짧게 다뤄보도록 하겠습니다.

Source Code


  //파라미터로 받은 OutPutStream을 이용하여 Stream에 Tracing 데이터를 넣는다.  
  static void
  CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
  {
  NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
  *stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
  }

  // 파라미터로 받은 Pcap File Wrapper를 이용하여 Loss가 발생한 Packet을 Pcap 파일의 형태로 저장한다.  
  static void
  RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
  {
    NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
    file->Write (Simulator::Now (), p);
  }


  // Ascii 파일로 CWND 데이터를 저장할 수 있도록 Output Stream을 만들고 CallBack 함수를 만들 때 stream 역시 파라미터로 넘겨준다.  
  AsciiTraceHelper asciiTraceHelper;
  Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("sixth.cwnd");
  ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream));

  // Pcap 파일로 Packet Loss 데이터를 저장할 수 있도록 Pcap 파일의 OutputStream을 만들고 CallBack 함수를 만들 때 stream 역시 파라미터로 넘겨준다.
  PcapHelper pcapHelper;
  Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", std::ios::out, PcapHelper::DLT_PPP);
  devices.Get (1)->TraceConnectWithoutContext ("PhyRxDrop", MakeBoundCallback (&RxDrop, file));

실행결과

이전 fifth.cc와 소스코드가 대부분 유사하기 때문에 차이가 있는 부분만 가져왔습니다. 이전에는 CallBack 함수를 만들 때 MakeCallback 함수를 이용하고 CallBack 함수의 함수명만 넘겨줬지만 이번에는 MakeBoundCallback 함수를 이용하여 CallBack 함수의 함수명과 stream 파라미터를 넘겨줍니다. 파라미터로 받은 OutputStream과 PcapFileWrapper를 이용하여 Tracing 데이터를 파일에 저장합니다. 이렇게 소스코드를 작성하면, CWND 데이터는 Ascii 파일로 저장되고, Packet Loss 데이터는 Pcap 파일로 저장되게 됩니다.

sixth.cwnd       sixth.pcap

Sixth.cc 시나리오 파일을 실행시키면 2개의 파일이 생성됩니다. 물론 기존처럼 Tracing 데이터가 터미널에 출력되기도 합니다. 이렇게 Tracing 데이터가 각각 나뉘어서 서로 다른 2개의 파일에 저장되면 데이터를 시각화 하는등, 데이터를 사용하는데 용이합니다.

fifth-cc-result

위와 같이 Tracing 데이터를 이용하여 그래프를 그리는 것 역시 쉽게 그릴 수 있습니다.

import matplotlib.pyplot as plt

with open("sixth.cwnd", "rt") as f:
    data = f.read()

cwnd = []
time = []
loss = []

for line in data.split("\n"):
        t, s, _ = map(float, line.split("\t"))
        time.append(t)
        cwnd.append(s)

plt.title("Fifth.cc Tracing Result")
plt.xlabel("Time(s)")
plt.ylabel("CWND size(Byte)")
plt.grid(True)

plt.plot(time, cwnd, label="CWND size")
plt.legend(loc="upper right", frameon=True)
plt.savefig("fifth-cc-result")
plt.close()

Loss 데이터는 Pcap 파일로 저장되있기 때문에 따로 소스코드에 Loss를 그리는 코드는 넣지 않았습니다. 위 그래프는 이전 Fifth.cc에서 그린 그래프를 그대로 가져온 것이기 때문에 타이틀도 Fifth.cc로 표시되있고 Loss도 그려져 있습니다. 이부분은 양해부탁드립니다. 이것으로 이번 포스팅은 마치도록 하겠습니다. 이번 포스팅은 지난번 예제 파일과 매우 유사해서 비교적 짧께 끝난거 같네요. 드디어 마지막 예제파일입니다. 다음 포스팅에서 마지막 예제파일인 Seven.cc을 다뤄보도록 하겠습니다.

카테고리:

업데이트:

댓글남기기