ns2 새로운 어플리케이션 추가LionHeart

|
새로운 어플리케이션 추가 


==================================================================================

[참고 : Marc Greis's Tutorial의 "VII. A new protocol fo ns" ]

본 내용은 위 사이트의 NS by Example의 내용을 학습하면서 정리한 것입니다.
여기서 정리된 내용으로 인해 발생 할 수 있는 문제에 대해서는 책임을 지지 않습니다.
USE AT YOUR OWN RISK!

==================================================================================

■ 본 예제는 Marc Greis's Tutorial의 ping 예제를 추가하는 부분을 정리한 것임. 최근 NS 버전에는

ping이 작성되어 있으므로 NS에 새로운 Application을 추가하는 방법을 학습하기 위한 예제로 이름만

수정하여 작성하였음.

■ 따라서 소스 자체에 대한 의미보다는 NS에 새로운 어플리케이션을 추가하는 방법적인면에 중점을 두고 이해 바람.

■ 실습을 위해 "ping" 이라는 명칭 대신 "hoya"라는 예제명으로 고쳐 작성.

■ OTcl과 C++ 링크에 대한 부분은 본 블로그의 [OTcl & C++ Linkage]를 참조하거나 기타 다른 NS2 관련 사이트를 참조.


■ hoya.h

========================================================================================

/* This is a ping example included in the ns2 */
/* I modified the ping.h and ping.cc as hoya */
 
#ifndef ns_hoya_h
#define ns_hoya_h

#include "agent.h"
#include "tclcl.h"
#include "packet.h"
#include "address.h"
#include "ip.h"

// "hoya"라는 새로운 프로토콜에 대한 패킷 헤더 구조를 정의

// ret | send_time 두 개의 필드로 "hoya"의 패킷 헤더를 정의

struct hdr_hoya {

 // 0: sender -> the node,   1: sender <- the node

 // 즉, 0이면 ping_request, 1이면 ping_reply가 될 것임
 char ret;

 // timestamp when this packet is sent.

 // 나중에 RTT(round_trip_time)를 계산하기 위함

 double send_time;

 // Header access methods

// 패킷으로 부터 "hoya" 패킷에 접근하기 위한 방법을 정의하는 매크로
 static int offset_; // required by PacketHeaderManager
 inline static int& offset() { return offset_; }
 inline static hdr_hoya* access(const Packet* p) {
  return (hdr_hoya*) p->access(offset_);
 }
};


// declare "HoyaAgent" as a subclass of "Agent"
// 나중에 이 클래스에 대한 객체를 생성하기 위해
// TclClass를 상속합든 HoyaClass를 정의해야함
class HoyaAgent : public Agent {
public:
 HoyaAgent();
 virtual int command(int argc, const char*const* argv);
 virtual void recv(Packet*, Handler*);
};

#endif // ns_hoya_h

========================================================================================

■ hoya.cc

========================================================================================

/* This is a ping example included in the ns2 */
/* I modified the ping.h and ping.cc as hoya */

 

#include "hoya.h"

int hdr_hoya::offset_;
static class HoyaHeaderClass : public PacketHeaderClass {
public:
 HoyaHeaderClass() : PacketHeaderClass("PacketHeader/Hoya", sizeof(hdr_hoya))
 {
  bind_offset(&hdr_hoya::offset_);
 }
} class_hoyahdr;


// HoyaAgent 객체를 생성하기 위해 TclClass 상속받는 HoyaClass 생성
// C++ (HoyaAgent)와 Tcl (Agent/Hoya)를 링크하게 됨.
// NS 실행시 static vairable를 실행하여 HoyaClass의 인스턴스가 생성됨
// 따라서 Tcl에서 "new Agent/Hoya" 명령어를 통해 HoyaAgent::create()가 호출됨

static class HoyaClass : public TclClass {
public:
 HoyaClass() : TclClass("Agent/Hoya") {}
 TclObject* create(int, const char*const*)
 {
  return (new HoyaAgent());
 }
} class_hoya;


// constructor : Tcl과 C++에서 접근되는 변수들을 binding
// '_'로 끝나는 변수들은 local object scope를 가짐
HoyaAgent::HoyaAgent() : Agent(PT_HOYA)  // PT_HOYA : packet.h에 추가될 프로토콜 이름
{
 // Tcl 인스턴스 변수 "packetSize_ " 와 C++ 변수 "size_" 바인딩
 // bind()는 클래스의 생성자에 있어야 함
 // Tcl 변수는 ns-default.tcl 에 등록하거나 시뮬레이션 스크립트에서 정의 가능.
 bind("packetSize_", &size_);
}


// HoyaAgent 클래스에 대한 Tcl 명령어가 호출될 때 실행되는 메소드
int HoyaAgent::command(int argc, const char*const* argv)
{
 if (argc == 2) {
  // 즉,
  // set hoyaagent [new Agent/Hoya]
  // $hoyaagent start
  // 명령어 실행에 대한 command() 의 처리 코드
  if (strcmp(argv[1], "start") == 0) {
   // Create a new packet
   Packet* pkt = allocpkt();
   // Access the Hoya header for the new packet:
   hdr_hoya* hdr = hdr_hoya::access(pkt);
   // Set the 'ret' field to 0, so the receiving node
   // knows that it has to generate an echo packet
   hdr->ret = 0;
   // Store the current time in the 'send_time' field
   hdr->send_time = Scheduler::instance().clock();
   // Send the packet
   send(pkt, 0);
   // return TCL_OK, so the calling function knows that
   // the command has been processed
   return (TCL_OK);
  }
 }
 // If the command hasn't been processed by HoyaAgent()::command,
 // call the command() function for the base class
 return (Agent::command(argc, argv));
}


// 수신 패킷에 대한 처리를 위한 코드를 작성
void HoyaAgent::recv(Packet* pkt, Handler*)
{
 // Access the IP header for the received packet:
 hdr_ip* hdrip = hdr_ip::access(pkt);
 // Access the Hoya header for the received packet:
 hdr_hoya* hdr = hdr_hoya::access(pkt);
 // Is the 'ret' field = 0 (i.e. the receiving node is being hoyaed)?
 if (hdr->ret == 0) {
  // Send an 'echo'. First save the old packet's send_time
  double stime = hdr->send_time;
  // Discard the packet
  Packet::free(pkt);
  // Create a new packet
  Packet* pktret = allocpkt();
  // Access the Hoya header for the new packet:
  hdr_hoya* hdrret = hdr_hoya::access(pktret);
  // Set the 'ret' field to 1, so the receiver won't send
  // another echo
  hdrret->ret = 1;
  // Set the send_time field to the correct value
  hdrret->send_time = stime;
  // Send the packet
  send(pktret, 0);
 } else {
  // A packet was received. Use tcl.eval to call the Tcl
  // interpreter with the hoya results.
  // Note: In the Tcl code, a procedure
  // 'Agent/Hoya recv {from rtt}' has to be defined which
  // allows the user to react to the hoya result.
  char out[100];
  // Prepare the output to the Tcl interpreter. Calculate the
  // round trip time
  sprintf(out, "%s recv %d %3.1f", name(),
   hdrip->src_.addr_ >> Address::instance().NodeShift_[1],
   (Scheduler::instance().clock()-hdr->send_time) * 1000);
  Tcl& tcl = Tcl::instance();
  tcl.eval(out);
  // Discard the packet
  Packet::free(pkt);
 }
}


========================================================================================

 

 

■ hoya.tcl

========================================================================================

#Create a simulator object
set ns [new Simulator]

#Open a trace file
set nf [open hoya_out.nam w]
$ns namtrace-all $nf

#Define a 'finish' procedure
proc finish {} {
        global ns nf
        $ns flush-trace
        close $nf
        exec nam hoya_out.nam &
        exit 0
}

#Create three nodes
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]

#Connect the nodes with two links
$ns duplex-link $n0 $n1 1Mb 10ms DropTail
$ns duplex-link $n1 $n2 1Mb 10ms DropTail

#Define a 'recv' function for the class 'Agent/Hoya'
Agent/Hoya instproc recv {from rtt} {
 $self instvar node_
 puts "node [$node_ id] received hoya answer from \
              $from with round-trip-time $rtt ms."
}

#Create two hoya agents and attach them to the nodes n0 and n2
set p0 [new Agent/Hoya]
$ns attach-agent $n0 $p0

set p1 [new Agent/Hoya]
$ns attach-agent $n2 $p1

#Connect the two agents
$ns connect $p0 $p1

#Schedule events
$ns at 0.2 "$p0 start"
$ns at 0.4 "$p1 start"
$ns at 0.6 "$p0 start"
$ns at 0.6 "$p1 start"
$ns at 1.0 "finish"

#Run the simulation
$ns run

========================================================================================

■ NS 수정사항

1. 일단 hoya.h와 hoya.cc 소스 코드를 ns-2.xx 폴더내에 작성합니다
(이 폴더내에 따로 hoya라는 폴더를 만들어서 이 폴더에서 코드를 저장해도 무방함).

2. packet.h의 enum packet_t { 부분에 "PT_HOYA"를 추가하고, class p_info { 의 p_info()내에
name_[PT_HOYA] = "Hoya"를 추가합니다. (아마도 common 디렉토리에 있을 것)

3. tcl/lib/ns-default.tcl 파일에 "Agent/Hoya set packetSize_ 64"를 추가

4. tcl/lib/ns-packet.tcl 파일에 foreach proto { 부분에 "Hoya" 추가 (위치는 그다지 중요하지 않은것 같음)

5. Makefile에 "OBJ_CC" 부분에 "hoya/hoya.o \" 라고 추가(hoya 폴더를 따로 만들어 작성한경우임).

6. 컴파일 :  make depend; make

7. hoya.tcl 실행해보기.

[출처] [NS2] 새로운 어플리케이션 추가 (ex. Ping)|작성자 호야다


And