Third.cc 예제 파일 설명

Third example scenario

세번째 네트워크 시나리오는 many-to-many 모델이라고 할 수 있습니다. 지난번 두번째 네트워크 시나리오는 one-to-many 모델로 여러개의 노드로 구성된 네트워크가 있고 이 네트워크가 point-to-point를 이용하여 1개의 노드와 연결되는 형태였습니다. 세번째 시나리오는 여러개의 노드로 구성된 서로다른 네트워크가 point-to-point를 이용하여 연결된 형태입니다. 이 시나리오에서 처음 등장하는 것이 WiFi 입니다. 2개의 네트워크가 point-to-point로 연결될 때 첫번째 네트워크는 WiFi를 이용하여 노드를 연결하였고 두번째 네트워크는 이전 시나리오처럼 csmaHelper를 이용하여 네트워크를 구성하였습니다. 이번에도 네트워크 토폴로지를 그림으로 준비해봤습니다.

스크린샷 2018-12-26 오후 9.30.45

네트워크 토폴로지를 보면 마치 공유기를 쓰는 가정집 네트워크가 생각납니다. 가정집 네트워크는 공유기를 이용하여 스마트폰과 노트북, 데스크탑을 사용하고 이때 발생하는 네트워크 패킷은 공유기를 통해 외부 네트워크로 빠져나가서 서비스를 제공하는 서버로 들어가게 됩니다. 이번 시나리오의 네트워크 토폴로지 역시 여러 노드들이 WiFi를 이용해 연결되고 공유기 역할을 하는 1개의 노드를 이용해 다른 네트워크와 통신하게 됩니다. 다른 네트워크 역시 여러 노드로 구성이 되어있습니다. 마치 인터넷과 같은 구조를 띄고 있습니다. 가장 현실적인 시뮬레이션 시나리오라고 생각합니다. 새로운 WiFi 링크를 사용하기 위해서는 ns-3에서 WiFi가 어떻게 구현이 되어있는지 파악하는 과정이 필요합니다. 이번 포스트에서 WiFi가 어떻게 구현되어 있는지까지 다루기에는 내용이 너무 방대해진다고 생각하여 따로 포스팅을 올리겠습니다.

Source Code

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

 /*
   시나리오를 돌리기 위해 필요한 해더 파일
   아래 헤더파일들은 전부 ns-3.29/src 폴더에 포함되어 있다.
 */
#include "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/ssid.h"

// Default Network Topology
//
//   Wifi 10.1.3.0
//                 AP
//  *    *    *    *
//  |    |    |    |    10.1.1.0
// n5   n6   n7   n0 -------------- n1   n2   n3   n4
//                   point-to-point  |    |    |    |
//                                   ================
//                                     LAN 10.1.2.0

using namespace ns3;

// 시뮬레이션 중 로그를 출력하기 위한 코드
NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
int
main (int argc, char *argv[])
{
  bool verbose = true;  // 어플리케이션 로그를 출력할 것인지 말것인지 여부
  uint32_t nCsma = 3;   // csmaGroup에 포함된 노드의 개수
  uint32_t nWifi = 3;   // wifiGroup에 포함된 노드의 개수
  bool tracing = false; // 패킷 정보를 pcap으로 남길 것인지 여부

  /*
  CommandLine 객체를 이용하여 커맨드라인에서 파라미터를 받아올 수 있다.
  커맨드라인을 이용하여 csmaGroup 네트워크 안에 몇개의 노드가 들어갈 것인지 입력한다. (기본값은 3)
  커맨드라인을 이용하여 wifiGroup 네트워크 안에 몇개의 노드가 들어갈 것인지 입력한다.
  로그를 출력할지 말것인지도 커맨드라인을 통해 입력한다.
  pcap 파일을 남길 것인지 말것인지도 커맨드라인을 통해 입력한다.
  */
  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.AddValue ("tracing", "Enable pcap tracing", tracing);

  cmd.Parse (argc,argv);

  // The underlying restriction of 18 is due to the grid position
  // allocator's configuration; the grid layout will exceed the
  // bounding box if more than 18 nodes are provided.
  if (nWifi > 18)
    {
      std::cout << "nWifi should be 18 or less; otherwise grid layout exceeds the bounding box" << std::endl;
      return 1;
    }

  // 만약 로그를 출력하기로 결정했다면 시나리오에서 사용하는 어플리케이션의 로그 레벨을 설정하여 로그가 출력될 수 있도록 한다.
  if (verbose)
    {
      LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
      LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
    }

  // wifiGroup과 csmaGroup에 각각 포함되어 두개의 네트워크를 연결해줄 노드를 2개 만든다.
  NodeContainer p2pNodes;
  p2pNodes.Create (2);

  /*
  만들어진 2개의 노드를 연결해줄 point-to-point 링크를 만든다.
  point-to-point 링크는 5Mbps의 DataRate와 2ms의 Delay를 갖는다.
  */
  PointToPointHelper pointToPoint;
  pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
  pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));

  // 만든 point-to-point 링크를 2개의 노드와 연결한다.
  NetDeviceContainer p2pDevices;
  p2pDevices = pointToPoint.Install (p2pNodes);

  /*
   2개의 노드중 2번째 노드를 csmaGroup에 포함시키고 nCsma 만큼 새로운 노드를 만든다.
   최종적으로 csmaGroup에 포함된 노드의 수는 nCsma + 1
   */
  NodeContainer csmaNodes;
  csmaNodes.Add (p2pNodes.Get (1));
  csmaNodes.Create (nCsma);

  /*
  csmaGroup에 포함된 노드를 연결하기 위해 CsmaHelper를 만든다.
  CsmaHelper는 100Mbps의 DataRate와 6560 nano second의 Delay를 갖는다.
  */
  CsmaHelper csma;
  csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
  csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560)));

  // 만든 CsmaHelper 링크를 csmaGroup에 포함된 노드에 연결한다.
  NetDeviceContainer csmaDevices;
  csmaDevices = csma.Install (csmaNodes);

  /*
   wifiGroup에 nCsma 만큼 새로운 노드를 만든다.
   */
  NodeContainer wifiStaNodes;
  wifiStaNodes.Create (nWifi);
  NodeContainer wifiApNode = p2pNodes.Get (0);

  // Wifi를 쓰기 위한 채널 모델을 만든다.
  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();

  // Wifi를 지원하는 Phy layer를 별도로 만들어준다.
  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
  phy.SetChannel (channel.Create ()); // PHY layer에게 어떤 채널이 사용되는지 알려준다.

  WifiHelper wifi;
  wifi.SetRemoteStationManager ("ns3::AarfWifiManager");

  // Wifi를 지원하는 Mac layer를 별도로 만들어준다.
  // Mac layer 모드를 STA 모드로 설정한다.
  // SSID 를 설정해주고 ActiveProbing은 사용하지 않는다.
  WifiMacHelper mac;
  Ssid ssid = Ssid ("ns-3-ssid");
  mac.SetType ("ns3::StaWifiMac",
               "Ssid", SsidValue (ssid),
               "ActiveProbing", BooleanValue (false));

  // 이렇게 만들어진 WifiHelper를 wifiGroup에 포함된 노드에 포함시켜준다.
  NetDeviceContainer staDevices;
  staDevices = wifi.Install (phy, mac, wifiStaNodes);

  // Mac layer를 제외하고는 AP역시 통신채널이나 Phy layer은 STA와 같은 값을 쓰기 때문에 Mac layer만 변경시켜준다.
  // Mac layer 모드를 AP 모드로 설정한다.
  // SSID 를 설정해준다.
  mac.SetType ("ns3::ApWifiMac",
               "Ssid", SsidValue (ssid));

  // 이렇게 만들어진 새로운 WifiHelper를 wifiApNode에 설치해준다.
  NetDeviceContainer apDevices;
  apDevices = wifi.Install (phy, mac, wifiApNode);

  MobilityHelper mobility;

  /*
   wifiGroup에 포함된 노드가 어떻게 위치되는지 설정한다.
   그리드의 크기는 5 x 10이며 row를 먼저 채워주고 row가 다 차면
   다음 column으로 넘어가서 새로 시작한다.
   */
  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"));

  // WiFi의 STA 노드 (노트북, 데스크탑, 스마트폰 등)는 걷는 속도로 Rectangle(-50, 50, -50, 50)의 범위 안에서 랜덤하게 움직인다.
  mobility.SetMobilityModel ("ns3::RandomWalk2dMobilityModel",
                             "Bounds", RectangleValue (Rectangle (-50, 50, -50, 50)));
  mobility.Install (wifiStaNodes);

  // WiFi의 AP 노드 (공유기)는 고정된 위치에 놓아준다.
  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (wifiApNode);

  // TCP/IP layer 역할을 하는 stack을 모든 노드에 설치한다.
  InternetStackHelper stack;
  stack.Install (csmaNodes);
  stack.Install (wifiApNode);
  stack.Install (wifiStaNodes);

  Ipv4AddressHelper address;

  // 두개의 네트워크를 연결하는 point-to-point 링크에 연결된 NIC는 10.1.1.0의 서브넷 아이디와 255.255.255.0의 서브넷 마스크를 갖는다.
  address.SetBase ("10.1.1.0", "255.255.255.0");
  Ipv4InterfaceContainer p2pInterfaces;
  p2pInterfaces = address.Assign (p2pDevices);

  // csmaGroup에 포함된 노드들은 10.1.2.0의 서브넷 아이디와 255.255.255.0의 서브넷 마스크를 갖는다.
  address.SetBase ("10.1.2.0", "255.255.255.0");
  Ipv4InterfaceContainer csmaInterfaces;
  csmaInterfaces = address.Assign (csmaDevices);

  // wifiGroup에 포함된 노드들은 10.1.3.0의 서브넷 아이디와 255.255.255.0의 서브넷 마스크를 갖는다.
  address.SetBase ("10.1.3.0", "255.255.255.0");
  address.Assign (staDevices);
  address.Assign (apDevices);

  // 시나리오에서 사용할 서버 어플리케이션을 만든다.
  UdpEchoServerHelper echoServer (9);

  ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma)); // csmaGroup중 가장 마지막 노드에 서버 어플리케이션을 설치한다.
  serverApps.Start (Seconds (1.0)); // 서버 어플리케이션은 1초에 시작되고
  serverApps.Stop (Seconds (10.0)); // 10초에 종료된다.

  // 시나리오에서 사용할 클라이언트 어플리케이션을 만든다.
  UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
  echoClient.SetAttribute ("MaxPackets", UintegerValue (1)); // 클라이언트 어플리케이션은 최대 1개의 패킷을 서버로 전송한다
  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));  // 클라이언트 어플리케이션이 서버로 패킷을 전송하는 간격은 1초이다.
  echoClient.SetAttribute ("PacketSize", UintegerValue (1024)); // 클라이언트 어플리케이션이 전송하는 패킷의 크기는 1024Byte 이다.

  ApplicationContainer clientApps =
    echoClient.Install (wifiStaNodes.Get (nWifi - 1)); // wifiGroup의 마지막에서 두번째 노드에 클라이언트 어플리케이션을 설치한다.
  clientApps.Start (Seconds (2.0)); // 클라이언트 어플리케이션은 2초에 시작하여
  clientApps.Stop (Seconds (10.0));  // 10초에 종료된다.

  Ipv4GlobalRoutingHelper::PopulateRoutingTables (); // p2pGroup과 csmaGroup에 공통으로 속한 노드가 패킷을 받은 경우 어느 노드로 패킷을 전달해야하는지 알려준다.

  Simulator::Stop (Seconds (10.0));

  // 만약 tracing이 참이라면 시나리오가 진행되는 동한 이동하는 패킷의 정보를 pcap의 형태로 남겨준다.
  if (tracing == true)
  {
    pointToPoint.EnablePcapAll ("third");
    phy.EnablePcap ("third", apDevices.Get (0));
    csma.EnablePcap ("third", csmaDevices.Get (0), true);
  }

  Simulator::Run ();
  Simulator::Destroy ();
  return 0;
}

실행결과

At time 2s client sent 1024 bytes to 10.1.2.4 port 9
At time 2.01796s server received 1024 bytes from 10.1.3.3 port 49153
At time 2.01796s server sent 1024 bytes to 10.1.3.3 port 49153
At time 2.03364s client received 1024 bytes from 10.1.2.4 port 9

실행결과는 지난 2개의 시나리오 결과와 다를게 없습니다. 그이유는 저런 실행결과와 가장 크게 영향이 있는 부분은 시나리오에 사용되는 application이기 때문인데 first.cc 부터 third.cc까지 모두 UdpEcho 어플리케이션을 사용했기 때문입니다. 차이점은 네트워크가 어떻게 구성되어 있는지, 네트워크에 어떤 통신 채널이 사용되었는지만 차이가 있습니다. 따라서 통신채널의 차이에 따른 소스코드의 차이는 있지만 똑같은 어플리케이션을 사용하기 때문에 같은 결과를 반환합니다. 그나마 pcap 파일에서 차이를 보여주기 때문에 pcap 파일을 살펴보도록 하겠습니다.

스크린샷 2018-12-26 오후 11.04.44

third-0-1.pcap 파일을 보면 WiFi AP에서 송신하는 Beacon frame을 캡쳐한 pcap 파일을 확인할 수 있습니다. 이러한 pcap 파일은 wifi를 이용하기 때문에 나타나는 것입니다. 따라서 이러한 파일을 보면 시나리오의 통신 채널로 wifi가 사용되었음을 알 수 있게 해줍니다.

지금까지 3개의 시나리오를 살펴보았습니다. 3개의 시나리오 파일 결과는 모두 같았지만 네트워크 토폴로지가 모두 달랐고 사용된 통신 채널이 다른 경우도 있었습니다. 지금까지 유선 네트워크(point-to-point, csma)와 무선 네트워크(wifi)를 살펴보았습니다. 아직 다루지 못한 통신 채널인 LTE는 이후의 포스팅에서 차차 다뤄보도록 하겠습니다. 다음 포스팅 주제는 시나리오 Log를 수집하는 방법에 대해 다뤄보도록 하겠습니다.

카테고리:

업데이트:

댓글남기기