ns3 (2)

햄스터·2025년 4월 19일

NetworkProject

목록 보기
2/5

CLA (Command Line Arguments)

./waf를 실행할 때, 시뮬레이터 내부 코드의 변수 값을 외부에서, 즉 터미널 밖에서 명령어로 조작하는 방법입니다.

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

다음 3가지 코드로 전부 가능합니다!
알아봅시다.

int main(int argc, char* argv[])
{
	uint32_t max_packets = 1;
    std::string delay = "2ms";
    
    CommandLine cmd;
    cmd.AddValue("howmany", "Number of Packets to echo", max_packets");
    cmd.AddValue("delay", "Line Delay", delay);
    cmd.Parse(argc, argv);
    
    PointToPoint.SetChannelAttribute("Delay", StringValue(delay));
    echoClient.SetAttribute("MaxPackets", UintegerValue(max_packets));

해당 코드를 잘 보면, howmanydelay라는 value를 추가합니다.
이는 Command Line, 즉 Terminal에서 조정 가능한 value로,

$ ./waf --run "fileName --howmany=2 --delay=10ms"처럼 조정이 가능합니다.

중요한 점은 큰따옴표가 붙는다는 점이에요!
CLA 없이 ./waf --run FileName 할 때에는 큰따옴표가 없었죠.

High-Level Tracing

앞서 배웠던 Logging은 말 그대로 원하는 값을 출력하는 '로그'의 역할이고,
Tracing은 이벤트의 발생, 어떤 node에서 무슨 일이 발생했는지 등
네트워크에서 일어난 전반적인 일을 따라가게 해줍니다.

cout같은걸 할 필요가 없고, 정보를 시스템이 생성해주면 그걸 따라가면서 분석만 하면 됩니다.
Tracing을 하면

  • Core System 내로 접근하여 정보 획득이 가능한데, Changing이나 Recompiling같은 추가적인 절차가 필요 없습니다.
  • Debug Build를 신경쓸 필요가 없습니다.
  • Optimized Build가 Debug Build보다 훨씬 빠릅니다.

Tracing System은 Trace Source와 Trace Sink로 나뉘는데,
Trace Source는 실제로 발생하는 이벤트들이고,
Trace Sink는 그 source를 처리하고 수집/분석하는 곳입니다.


우리가 할 일은 Sink를 configure해서 source의 정보를 분석하는 것입니다.

TraceHelper를 이용해서, 이미 define된 trace source를 trace sink로 이어줍니다.
ns3에서 제공해주는 함수고, 좀 더 가볍고 자동화된 방법으로 tracing이 가능하죠.

trace sink를 만들 필요도, source와 sink를 내가 직접 이어줄 필요도 없습니다.
결과물로는 PCAP (Packet Capture)가 나옵니다.

PCAP Tracing

Packet Capture의 줄임입니다.
.pcap 파일 포맷으로 나옵니다.

앞서 네트워크 시뮬레이션을 할 때, Node도 만들고, Channel도 만들고, NetDevice도 만들고, 이어주고, 이것저것 했는데,

이 중 Channel에 해당하던 PointToPoint를 이용한다고손 치면,

코드의 마지막 부분에

pointToPoint.EnablePcapAll("firstcap"); <-- 이거!
Simulator::Run();
Simulator::Destroy();
return 0;

이 딱 한줄만 추가해주면 됩니다.

그러고 run을 해주면 알아서 pcap 파일이 생성되는데요,
그걸 tcpdump를 이용해서 읽어줍니다.

$ tcpdump -nn -tt -r firstcap-0-0.pcap
이 명령어의 의미는
IP주소, 포트번호를 출력하고, (-nn)
timestamp를 초 단위 정밀도를 높여 출력하고, (-tt)
pcap파일을 읽어라 (-r)
정도가 되겠는데, 그건 중요치 않고,

일단 pcap을 tcpdump로 읽어낸다면,

다음과 같이 어디서 어디로 패킷이 어떻게 이동했는지를 명확히 볼 수 있죠.

물론 대표적인 네트워크 분석 툴인 WireShark로도 충분히 읽을 수 있습니다.

Applications

앞서 다룬 Application은 UDPEchoClient/ServerApplication이 전부였는데,
사실 Application은 엄청 종류가 많습니다.

하나의 Node에 여러 Application이 설치될 수 있으며,
우리가 Application을 직접 만들 수도 있지요.

모든 Application은 ns3::Application 클래스를 상속받아야 합니다.

한번 살펴봅시다.

OnOffApplication

ns::OnOffApplication에 속합니다.
특정 목적지로의 반복된 on / off 패턴을 만듭니다.

onTimeoffTime을 만들 수 있고,
Off State일 때에는 아무 트래픽도 없으며,
On State일 때에는 CBR (Constant Bit Rate)의 Traffic을 보냅니다.

OnOffHelper를 이용해 쉽게 만들 수 있구요.
여러가지 Attribute를 설정 가능합니다.

  • onoff.SetAttribute("MaxPackets", UintegerValue(100))
  • onoff.SetAttribute("DataRate", StringValue("14Kb/s")) (미지정 시 500Kb/s)
  • onoff.SetAttribute("PacketSize", UintegerValue(1000)) (미지정 시 512)

이 외에, OnTime, OffTime도 지정 가능합니다.
둘 다 Initial Value는 Constant Time 1입니다.

PacketSink

누군가 트래픽을 쏜다면 누군가는 트래픽을 받아야 합니다.
OnOffApplication에서 쏜 트래픽을 받아서 소모하는 Sink (싱크대) 역할을 합니다.

PacketSink를 만들 때에는 2가지 속성이 필요합니다.

  • Protocol : 어떤 종류의 socket을 사용할 것인지
  • Local : 어떤 주소 (IP, Port)에 Sink를 Bind할 것인지

즉,
PacketSinkHelpersink ("ns3::UdpSocketFactory", Address(InetSocketAddress(Ipv4Address::GetAny(), port)) );
처럼 사용합니다.

UdpEcho

얘도 원리는 같습니다.
서버쪽에는 port가 필수, Client쪽에는 서버의 IP와 PORT가 필수적으로 들어가고,
Helper를 이용해
UdpEchoServerHelper::UdpEchoServerHelper(uint16_t port)처럼 선언합니다.

UdpEcho에도 다음 Attribute들을 SetAttribute(~)로 설정할 수 있습니다.

  • MaxPackets : application이 보낼 최대 패킷의 수입니다. uint32_t
  • Interval : Packet을 보낼 간격입니다. TimeValue
  • PacketSize : 1개 packet의 size입니다. uint32_t

echoClient.SetAttribute("Interval", TimeValue(Seconds(1.0))처럼 사용합니다.

UdpClientServer

Client쪽에선

  • Interval : 패킷을 보낼 간격 TimeValue
  • RemoteAddress : 출력한 패킷의 도착주소 AddressValue
  • RemotePort : 출력한 패킷의 도착포트주소 UintegerValue

등을 설정해줘야 하고,

Server쪽에선

  • Port : 패킷을 listen할 포트넘버 UintegerValue
  • PacketWindowSize : 패킷을 받을 수 있는 Window Size (8의배수) UintegerValue

를 설정해줘야 하며,
역시도 UdpClientHelperUdpServerHelper 등을 이용해 선언합니다.

Application용 함수

Application::에 포함되는 수많은 함수들이 있습니다.
당연히 Application을 상속받는 클래스들은 전부 이용 가능하며,

ApplicationContainer를 상속받는 클래스들이 이용 가능한,
Container 내의 모든 App에게 똑같은 속성을 부여하는
ApplicationContainer::에 포함된 함수들도 존재합니다.

  • Application::SetStartTime(Time time) :
    App의 시작 시간을 설정합니다.
    이 함수가 호출되고, 그만큼의 시간이 지나면 StartApplication()이 호출됩니다.

  • Application::SetStopTime(Time time) :
    App의 종료 시간을 설정합니다.
    이 함수가 호출되고, 그만큼의 시간이 지나면 StopApplication()이 호출됩니다.

  • virtual void Application::StartApplication(void) :
    App의 실질적인 시작 함수입니다.
    얘가 호출돼서 모든게 시작되는거고,
    따라서 모든 Application::을 상속받는 함수들은 StartApplication 또한 명시적으로 만들어줘야 합니다.

  • virtual void Application::StopApplication(void) :
    App의 실질적인 종료 함수입니다.
    StartApplication과 설명은 같습니다.

  • ApplicationContainer::Start(Time time) :
    그냥 모든 App에 하나하나 SetStartTime(Time time)을 해 주는 함수입니다.

  • ApplicationContainer::Stop(Time time) :
    마찬가지입니다.

profile
햄스터가 세상을 지배한다.

0개의 댓글