[5] NS-3 Building Wireless Network

최윤하·2023년 2월 6일
0

NS-3 Simulator

목록 보기
5/7
post-thumbnail

이번에는 무선 네트워크를 만들어 보겠습니다.
ns-3는 IEEE 802.11 모델을 제공합니다.
시나리오 파일은 examples/tutorial/third.cc를 사용합니다.

시나리오 분석(third.cc)

이번에도 네트워크 topology 그림이 등장합니다.
second.cc에서 구성한 네트워크 왼쪽에 무선 네트워크가 추가된 것을 볼 수 있습니다.

이 그림은 default topology를 나타냅니다. 즉, 유/무선 네트워크의 node 개수를 바꿀 수 있다는 의미입니다.
second.cc에서 nCsma를 사용해서 extra CSMA node의 개수를 바꿀 수 있었던 것 처럼, nWifi로 STA(station) node의 개수를 컨트롤 할 수 있습니다.

AP(access point)는 항상 1개만 있다고 생각합니다.
point-to-point link의 가장 왼쪽 node가 무선 네트워크의 AP가 됩니다.

이전 예제들과 마찬가지로 익숙한 코드들은 간단히 넘어가겠습니다.

먼저, logging component를 정의합니다.

NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");

그리고 command line parameter를 추가합니다.

bool verbose = true;
uint32_t nCsma = 3;
uint32_t nWifi = 3;

CommandLine cmd;
cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
cmd.Parse (argc,argv);

if (verbose)
{
	LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO); 
    LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
}

다음으로 2개의 node를 만들어 point-to-point link를 만들어줍니다.

NodeContainer p2pNodes;
p2pNodes.Create (2);

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

NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install (p2pNodes);

마찬가지로 버스(CSMA) 네트워크를 만들어 줍니다.

NodeContainer csmaNodes;
csmaNodes.Add (p2pNodes.Get (1)); 
csmaNodes.Create (nCsma);

CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps")); 
csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));

NetDeviceContainer csmaDevices; 
csmaDevices = csma.Install (csmaNodes);

마지막으로, Wi-Fi 네트워크의 node를 만들어 줍니다.
nWifi개 만큼의 station node를 생성하고, point-to-point link의 가장 왼쪽 node를 AP로 사용할 것 입니다.

NodeContainer wifiStaNodes; 
wifiStaNodes.Create (nWifi);
NodeContainer wifiApNode = p2pNodes.Get (0);

다음은 wifi device와 channel을 만들 것입니다.
먼저, physical helper와 channel helper를 default 값으로 설정합니다.

YansWifiChannelHelper channel = YansWifiChannelHelper::Default (); 
YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();

그리고 channel object와 PHY layer object가 같은 무선 medium을 공유하도록 설정해줍니다.

phy.SetChannel (channel.Create ());

PHY helper 설정은 끝났습니다. 이제 MAC(Medium Access Control)만 신경쓰면 됩니다.

WifiMacHelper mac;
Ssid ssid = Ssid ("ns-3-ssid");

두번째 줄에서, 나중에 MAC layer 구현에서 "Ssid" attribute에 사용될 SSID(Service Set Identifier) 객체를 생성합니다.
SSID란 쉽게 말해서 여러 Wi-Fi를 구분해주는 이름입니다.

WifiHelper를 생성합니다.

WifiHelper wifi;

이제 4개의 helper와 Ssid 객체를 사용해서 Wi-Fi 모델을 node에 설치할 준비가 되었습니다.

mac.SetType ("ns3::StaWifiMac", "Ssid", SsidValue (ssid), "ActiveProbing", BooleanValue (false));

첫번째 인자는 어떤 종류의 MAC layer를 만들지, 두번째는 Ssid, 마지막 ActiveProbing은 false로 설정하여 station들이 AP 비콘 프레임을 듣도록 합니다.

이제 wifi station node들에게 설치해줍니다.

NetDeviceContainer staDevices;
staDevices = wifi.Install (phy, mac, wifiStaNodes);

다음으로, AP node를 설정합니다.
먼저, 아까 설정했던 WifiMacHelper의 attribute을 변경해줍니다.

mac.SetType ("ns3::ApWifiMac", "Ssid", SsidValue (ssid));

그리고 station들과 같은 PHY-level attribute을 공유하는 AP를 만들어줍니다.

NetDeviceContainer apDevices;
apDevices = wifi.Install (phy, mac, wifiApNode);

이제, AP node는 가만히 있고 STA node들은 bounding box 안에서 움직이도록 만들고 싶습니다.
mobility helper에게 2D grid에 STA node들을 배치하라고 말합니다.

MobilityHelper mobility;

mobility.SetPositionAllocator ("ns3::GridPositionAllocator", 
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (5.0),
"DeltaY", DoubleValue (10.0),
"GridWidth", UintegerValue (3), "LayoutType", StringValue ("RowFirst"));

이제 node들이 어떻게 움직일지 설정해줍니다.

mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel", 
"Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));

RandomWalk2dMobilityModel을 사용하여 node들이 랜덤한 방향으로 랜덤한 속도로 움직이게 합니다.

마지막으로 mobility 모델을 STA node에 설치합니다.

mobility.Install (wifiStaNodes);

AP node는 가만히 있도록 설정하고 설치합니다.

mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (wifiApNode);

여기까지 node, device, channel을 만들었고 model도 결정하였습니다. 이제 protocol stack을 설치해줄 차례입니다.

InternetStackHelper stack; 
stack.Install (csmaNodes); 
stack.Install (wifiApNode); 
stack.Install (wifiStaNodes);

다음은 IP 주소를 할당해줍니다.

Ipv4AddressHelper address;

address.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer p2pInterfaces; 
p2pInterfaces = address.Assign (p2pDevices);

address.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4InterfaceContainer csmaInterfaces; 
csmaInterfaces = address.Assign (csmaDevices);

address.SetBase ("10.1.3.0", "255.255.255.0");
address.Assign (staDevices); 
address.Assign (apDevices);

이제 echo server를 맨 위 그림에서 가장 오른쪽 node(n4)로 설정해줍니다.

UdpEchoServerHelper echoServer (9);

ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma)); 
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));

echo client는 마지막 STA node(n7)로 설정해줍니다.

UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9); 
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));

ApplicationContainer clientApps = echoClient.Install (wifiStaNodes.Get (nWifi - 1));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));

internetwork를 만들었으니 internetwork routing이 필요합니다.

Ipv4GlobalRoutingHelper::PopulateRoutingTables ();

한 가지 놀라운 사실은, 우리가 만든 시뮬레이션이 자연적으로는 절대 멈추지 않는다는 것입니다.
왜냐하면 AP가 비콘 프레임을 계속 만들어내기 때문입니다. 그래서 언제 정지하라고 말해줘야합니다.

Simulator::Stop (Seconds (10.0));

tracing도 만들어줍니다.

pointToPoint.EnablePcapAll ("third");
phy.EnablePcap ("third", apDevices.Get (0));
csma.EnablePcap ("third", csmaDevices.Get (0), true);

마지막으로

Simulator::Run ();
Simulator::Destroy (); 

시뮬레이션 실행

$ cp examples/tutorial/third.cc scratch/mythird.cc
$ ./ns3 run 'scratch/mythird --tracing=1'

결과


결과를 확인해보면, 무선 네트워크에 있는 client(10.1.3.3)와 CSMA에 있는 server(10.1.2.4) 사이에 패킷이 전달 되었음을 확인할 수 있습니다.

생성된 trace 파일도 확인할 수 있습니다.

“third-0-0.pcap”는 n0의 point-to-point device,
“third-1-0.pcap”는 n1의 point-to-point device,
“third-0-1.pcap”는 Wi-Fi 네트워크의 promiscuous trace,
“third-1-1.pcap”는 CSMA 네트워크의 promiscuous trace 입니다.

결과 분석

먼저, echo client가 있는 Wi-Fi 네트워크부터 보겠습니다.

$ tcpdump -nn -tt -r third-0-1.pcap

link type이 802.11임을 볼 수 있습니다.
나머지 출력값에 대한 해석은 개인적으로 해보시기 바랍니다.(무슨 뜻인지 모르겠습니다)

다음으로, STA node들이 실제로 움직이고 있는지 확인해보겠습니다. 여기에서 tracing의 source와 sink 개념이 사용됩니다.

우리는 미리 정의된 course change trace source(코스가 바뀌면 event를 발생시키는..)를 사용할 것입니다.
그리고 우리에게 유용한 정보를 보여줄 trace sink 코드를 작성해야합니다.
main문 위에 아래의 함수를 추가하면 됩니다.

void
CourseChange (std::string context, Ptr<const MobilityModel> model)
{
	Vector position = model->GetPosition ();
    NS_LOG_UNCOND (context << " x = " << position.x << ", y = " << position.y);
}

mobility model로 부터 위치 정보를 뽑아내어 x, y 좌표를 로그 메시지로 찍습니다.

그리고 source와 sink를 연결해줍니다.
trace source의 path string을 만들어 Connect 메서드에 넘겨줍니다.
그리고 콜백함수로 아까 만든 CourseChange를 지정합니다.
자세한 내용은 다음 Tracing 챕터에서 설명하겠습니다.

std::ostringstream oss; 
oss <<
"/NodeList/" << wifiStaNodes.Get (nWifi - 1)->GetId () << 
"/$ns3::MobilityModel/CourseChange";

Config::Connect (oss.str (), MakeCallback (&CourseChange));

이제 n7의 course change 이벤트 변화는 우리의 trace sink로 올 것이고, 새로운 위치를 출력할 것 입니다.
위 코드를 Simulator::Run() 위에 추가하고 실행시킵니다.

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

0개의 댓글