[7] NS-3 Tracing(2)

최윤하·2023년 2월 7일
0

NS-3 Simulator

목록 보기
7/7
post-thumbnail

시나리오 분석(fifth.cc)

지난 포스팅에 이어서 tracing을 사용한 congestion window 테스트 예제를 보겠습니다.

네트워크에서 혼잡이 발생했을 때, 송신 측의 윈도우 크기를 조절하여 데이터의 전송량을 강제로 줄이는 것을 '혼잡제어'라고 합니다.
송신 측은 자신의 최종 윈도우 크기를 정할 때, 수신 측이 보내준 윈도우 크기와 자신이 네트워크 상황을 고려해서 정한 윈도우 크기인 혼잡 윈도우(Congestion Window, CWND)중에서 더 작은 값을 사용합니다.

네트워크 구성은 아래 그림과 같습니다.

우리는 ns-3 TCP congestion window의 변화를 보고싶습니다.
그래서 네트워크 flow를 만들고, sender 소켓(node 0)의 CongestionWindow attribute를 hooking 해야합니다.
이것을 쉽게 하기 위해서 node 0를 위한 우리만의 간단한 application을 만들어줍니다.
(application은 각 node마다 설치되는 것임!!)

코드는 생략하겠습니다.
examples/tutorial/tutorial-app.cc에서 확인할 수 있습니다.

본격적으로 코드를 보겠습니다.

congestion window가 업데이트 되었을 때, 이벤트를 전달받을 trace sink를 만들어줍니다.

static void
CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
{
	NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
}

이 함수는 congestion window가 바뀔 때 마다 시뮬레이션 시간과 새로운 값을 로그 메시지로 출력합니다.

그리고 또 다른 trace sink도 추가해줍니다.
우리는 error model을 추가할건데, 이것이 잘 작동하는지 보기 위해서 패킷이 어디서 drop 되었는지 보여주는 역할입니다.

static void
RxDrop (Ptr<const Packet> p)
{
	NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
}

이 trace sink는 point-to-point NetDevice의 “PhyRxDrop” trace source와 연결될 것 입니다. 이 source는 NetDevice에서 패킷이 drop 되었을 때 영향을 받습니다.

error model을 추가하는 이유는, 만약 시뮬레이션이 완벽하게 작동하면 congestion window는 그냥 쭉 증가하기만 할 것 입니다. 그래서 더 흥미로운 형태를 보기 위해서 패킷을 drop 시킬 error model을 도입했습니다.

main을 보겠습니다.
2개의 node를 만들고 point-to-point channel로 연결합니다.

int
main (int argc, char *argv[])
{
	NodeContainer nodes;
    nodes.Create (2);

	PointToPointHelper pointToPoint;
	pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); 
    pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

	NetDeviceContainer devices;
	devices = pointToPoint.Install (nodes);

앞서 설명한 것 처럼, RateErrorModel을 사용해서 주어진 error rate로 receiver node(node 1)에 error를 설정합니다.

Ptr<RateErrorModel> em = CreateObject<RateErrorModel> (); 
em->SetAttribute ("ErrorRate", DoubleValue (0.00001));
devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (em));

그리고 Internet stack을 설치하고 IP 주소를 할당합니다.

InternetStackHelper stack;
stack.Install (nodes);

Ipv4AddressHelper address;
address.SetBase ("10.1.1.0", "255.255.255.252");
Ipv4InterfaceContainer interfaces = address.Assign (devices);

이번 예제에서 우리가 TCP를 사용하기 때문에, destination node(node 1)에 대해 몇가지 설정이 필요합니다.

PacketSinkHelper에서 ns3::TcpSocketFactory 클래스를 사용해서 소켓을 생성하라고 시킵니다.
두번째 인자는 Bind에 사용되는 주소와 포트번호입니다.

uint16_t sinkPort = 8080;
Address sinkAddress (InetSocketAddress(interfaces.GetAddress (1), sinkPort));

PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1));

sinkApps.Start (Seconds (0.));
sinkApps.Stop (Seconds (20.));

PacketSink application은 단순히 트래픽을 받고 소비하는 application입니다.
node 1에 설치해줍니다.

sender쪽 소켓을 생성하고 trace source와 연결합니다.

Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());

ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeCallback (&CwndChange));

그리고 우리가 만든 application을 생성합니다.

Ptr<MyApp> app = CreateObject<MyApp> ();
app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
nodes.Get (0)->AddApplication (app);
app->Start (Seconds (1.));
app->Stop (Seconds (20.));

Setup(...)은 application에게 어떤 소켓을 사용할 지, 어떤 주소에 연결할 지, 매 이벤트마다 보낼 데이터의 크기, 총 보낼 이벤트 수 그리고 이벤트에서 데이터를 생성할 rate을 알려줍니다.
그리고 application을 node 0에 설치합니다.

마지막으로, 남은 source와 sink를 연결해줍니다.

devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeCallback (&RxDrop));

결과

시뮬레이션 실행 결과, 변화하는 congestion window와 패킷이 drop되는 것이 잘 나타남을 확인할 수 있습니다.

output을 아래 명령어로 redirection 해줍니다.

$ ./ns3 run fifth > cwnd.dat 2>&1

먼저, stdout(표준출력)을 cwnd.dat으로 리다이렉션 해주고
2>&1로 stderr(표준에러)를 stdout으로 리다이렉션 해줍니다. 즉, 바뀐곳인 cwnd.dat으로!
여기서 '&'는 1이 stdout로 인식되게 합니다. 아니면 '1'이라는 이름의 파일로 인식해버립니다.

그리고 시각화를 위해서 gnuplot을 사용해줍니다.

$ gnuplot
gnuplot> set terminal png size 640,480 
gnuplot> set output "cwnd.png"
gnuplot> plot "cwnd.dat" using 1:2 title 'Congestion Window' with linespoints 
gnuplot> exit

그래프를 통해서 쉽게 흐름을 파악할 수 있습니다.

❗❗초보자의 수준에서 작성 된 글입니다❗❗
잘못 된 내용이 있으면 피드백 부탁드립니다.

0개의 댓글