[3] NS-3 Tweaking

최윤하·2023년 2월 5일
0

NS-3 Simulator

목록 보기
3/7
post-thumbnail

Logging

이번에는 Logging에 대해서 자세히 알아보겠습니다.

많은 큰 시스템들은 메시지 logging 기능을 지원합니다.
ns-3는 선택적이고, multi-level 접근법을 제공합니다.
logging은 디버깅 정보, 경고, 에러 메시지 또는 원하는 정보를 쉽게 얻을 때 사용합니다.

로그 메시지는 여러 레벨이 있습니다.

LOG_INFO를 활성화하면 오직 NS_LOG_INFO 매크로에 의해 제공되는 메시지만 제공되지만, LOG_LEVEL_INFO를 활성화하면 NS_LOG_DEBUG, NS_LOG_WARN 그리고 NS_LOG_ERROR 매크로에 의한 정보까지 모두 제공됩니다.

Using NS_LOG

logging은 환경변수 NS_LOG에 의해 설정될 수 있습니다.

먼저, 이전 first.cc 예제에서는 LOG_LEVEL_INFO로 설정했기 때문에 INFO 와 그 이하의 모든 레벨들이 활성화되었습니다.
(NS_LOG_INFO, NS_LOG_DEBUG, NS_LOG_WARN, NS_LOG_ERROR)

그 결과 아래와 같은 로그 메시지가 출력됩니다.

여기서 우리는 더 많은 정보를 얻기 위해 스크립트를 바꾸고 다시 컴파일하는 대신, 환경변수 NS_LOG를 사용할 수 있습니다.

$ export NS_LOG=UdpEchoClientApplication=level_all

client application에 대해 ALL 레벨로 변경해주었습니다.


그 결과 client application에 대해서는 모든 정보가 찍히게 됩니다. 이전과 비교해서는 NS_LOG_FUNCTION 레벨이 추가되었습니다.
그래서 시뮬레이션이 진행되는 동안 해당 application의 function이 불릴 때 마다
<logging component name>:<method name>의 형태로 메시지를 보여줍니다.

어떤 경우에는 어떤 method가 해당 로그 메시지를 발생시켰는지 알기 어렵습니다. 그럴때는 아래와 같이 해주면 됩니다.

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func'

server application도 활성화 시키고 싶을 때는

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:UdpEchoServerApplication=level_all|prefix_func'

로그 메시지가 언제 발생했는지 알고 싶을 때는

$ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time: UdpEchoServerApplication=level_all|prefix_func|prefix_time'

그 결과 더 자세한 로그 메시지가 출력됩니다.

추가적으로, 모든 컴포넌트에 대한 것을 보고싶을 때는

$ export 'NS_LOG=*=level_all|prefix_func|prefix_time'

이 경우에는 output이 매우 많기 때문에, 별도의 파일로 redirection 해줍니다.

$ ./ns3 run scratch/myfirst > log.out 2>&1

Using Command-Line Argument

다음으로, 스크립트를 수정하지 않고 ns-3가 행동하는 것을 바꿀 수 있는 다른 방법은 command-line argument를 이용하는 것입니다.

그러기 위해서는 먼저 main문 안에 다음과 같이 선언해줍니다.

CommandLine cmd;
cmd.Parse (argc, argv);

그리고 'PrintHelp' 옵션을 주어 실행시켜 줍니다.

$ ./ns3 run "scratch/myfirst --PrintHelp"

그러면 아래와 같은 결과가 나옵니다.

일반적으로 사용할 수 있는 argument 리스트입니다.
이것들 중에서 '--PrintAttributes' 라는 옵션을 보면, typeid는 클래스 이름을 의미합니다. 그래서 first.cc에서 PointToPointNetDevice의 Attribute을 설정해주었던 것을 생각하면서

$ ./ns3 run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice"

위와 같이 명령어를 입력하게되면

저희가 설정했던 attribute 이외의 것들도 모두 확인할 수 있습니다.

$ ./ns3 run "scratch/myfirst
--ns3::PointToPointNetDevice::DataRate=5Mbps
--ns3::PointToPointChannel::Delay=2ms
--ns3::UdpEchoClient::MaxPackets=2"

그리고 attribute 값을 command line에서 변경시킬 수 있습니다.

또한, 자신만의 값을 통제할 수도 있습니다.

uint32_t nPackets = 1;

CommandLine cmd;
cmd.AddValue("nPackets", "Number of packets to echo", nPackets);
cmd.Parse (argc, argv);

먼저 main에서 nPackets라는 지역변수를 선언해주고, AddValue 메서드를 사용해서 등록해줍니다.

$ ./ns3 build
$ ./ns3 run "scratch/myfirst --PrintHelp"

그리고 실행하게 되면
위와 같이 'Program Options'라고 우리만의 옵션이 생기게 됩니다. 기본 옵션과 마찬가지로 값을 변경할 수 있습니다.

Tracing

이제부터는 Tracing System에 대해서 알아보겠습니다.
시뮬레이션의 목적은 연구에 사용할 유의미한 output을 만들어내는 것입니다.
단순히 print문을 집어넣거나 logging 모듈을 사용할 수도 있지만, 이런 방법들은 문제점이 많습니다. 그래서 tracing system이 제공됩니다.

ns-3 tracing system은 서로 독립적인 tracing sourcetracing sink 개념으로 이루어집니다. 그리고 source를 sink에 연결하는 메커니즘을 사용합니다.

  • trace source
    event를 만들어내고 흥미로운 data에 대한 접근을 제공합니다.
    trace source는 그 자체로는 쓸모없고
    그 정보(source가 만들어낸)로 실제로 유용한 일을 할 수 있는 코드(sink)와 연결되어야 합니다.

  • trace sink
    source에 의해 제공되는 event와 data의 소비자입니다.

high-level tracing은 helper를 사용하여 미리 정의된 source를 이미 존재하는 sink에 연결합니다.
high-level tracing의 예로는 ASCII, PCAP tracing이 있습니다.

low-level tracing은 source를 custom sink에 직접 연결합니다.

ASCII Tracing

output이 ASCII 파일로 생성되어서 붙여진 이름입니다.

myfirst.cc에서 Simulator::Run()을 호출하기 전에, 아래의 코드를 추가해줍니다.

AsciiTraceHelper ascii;
pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));

마찬가지로 helper를 사용해서 "myfirst.tr"이라는 파일 객체를 만들어주고
EnableAsciiAll()을 호출하여, 모든 point-to-point device들을 ASCII tracing 하게하고
자동으로 trace sink(미리 제공된)가 ASCII 형식으로 패킷에 관한 정보를 작성하게 됩니다.

이제 결과물을 보겠습니다.

output 파일은 한 줄이 매우 긴 여러 줄로 구성되어 있습니다.
각 줄은 trace event에 해당합니다. 위 사진은 한 줄을 보기 쉽게 만든 것입니다.

  • '+'는 device queue에서 enqueue가 되었음을 의미합니다.
    '-'는 dequeue, 'd'는 queue가 가득 차서 패킷이 drop 되었음, 'r'은 net device에서 패킷이 받아졌음을 의미합니다.
  • 2번째는 시뮬레이션 시간입니다(초 단위).
  • 다음은 이 event를 어떤 trace source가 발생시켰는지 알려줍니다.
    0번째 Node의 0번째 device, device 종류는 PointToPoint이고 마지막으로 transmit queue에서 enqueue가 일어났음이 반영되었습니다.
  • 나머지는 매우 직관적입니다. 패킷이 point-to-point 프로토콜로 캡슐화되었고, IPv4 헤더를 가지며 10.1.1.1 에서 10.1.1.2로 향한다. 그리고 UDP 헤더를 가지며 payload(데이터 크기)는 1024byte 임을 의미합니다.

PCAP Tracing

또 다른 high-level tracing system은 PCAP(packet capture) tracing 입니다.
.pcap 형태의 trace 파일이 생성됩니다. 이 파일은 tcpdump, Wireshark 등에 의해서 분석될 수 있습니다.

pointToPoint.EnablePcapAll ("myfirst");

아까와 동일한 위치에 위 코드를 추가해줍니다.
그리고 실행하게 되면 myfirst-0-0.pcap, myfirst-1-0.pcap 파일이 생성됩니다.
<myfirst>-<node 번호>-<device 번호>.pcap 형태 입니다.

이제 tcpdump를 사용해서 output을 분석 해보겠습니다.

$ tcpdump -nn -tt -r myfirst-0-0.pcap

결과를 확인해보면, 우리가 시나리오를 만든대로 패킷이 전송되었음을 확인할 수 있습니다.
Wireshark 프로그램을 사용해서도 확인할 수 있습니다.

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

0개의 댓글