NS2:添加一個新的自寫協議的方法

本文介紹如何在最新版的NS-2.30中嵌入一個自己寫的簡單新協議,讀者可先不必較真協議的具體實現代碼,先熟悉嵌入流程因爲此代碼還是有一定bug的,但實現一個協議的總體框架是對的。後續文章將對如何寫一個新協議進行解析,如TCL如何傳值到C++等。

一、編寫新協議simple_trans

我們在 NS-2.30目錄下創建一個文件夾 kgn,目錄下有兩個文件: simple_trans.h和simple_trans.cc,這兩個文件就是我們新協議的主體實現文件。

 simple_trans.h代碼內容

#ifndef ns_simple_trans_h
#define ns_simple_trans_h
#include "agent.h"
#include "tclcl.h" 
#include "packet.h" 
#include "address.h" 
#include "ip.h" 
//協議默認傳輸的端口 
#define PROTOCOL_DEFAULT_PORT 1023 
//同步指令(類似於 TCP 協議中三次握手的第一步,事實上我們的這個協議最終就是要實現一個簡化版的三步握手) 
#define PROTOCOL_INIT_SYN 1 

//只有 type 這個是我定義的,其他的內容是 ns2 系統需要的 
struct hdr_simple_trans { 

int type; 

static int offset_; 
inline static int& offset() { 
return offset_; 
} 
inline static hdr_simple_trans * access(const Packet * p) { 
return (hdr_simple_trans*) p->access(offset_); 
} 
}; 


//產生數據包、發送數據包、接收數據包的地方,包括的 target 變量就是數據包發送給的下一個目標。 
class simple_trans_agent : public Agent { 

public : 
simple_trans_agent(); 
virtual void recv(Packet *, Handler *);//“自動”的收到網絡上傳輸的數據包(更深層次的是經過了地址和端口過濾器) 
void send_simple_msg(int type, int target);//創建併發送數據 
int get_target(){ return simple_target; }//接口保護 

protected: 
int simple_target; 
int simple_port; 
int command(int argc, const char*const*argv); 
}; 

//一個定時器(鬧鐘)在到時時候會調用一個 expire (超時)函數 
class SYNTimer : public TimerHandler { 
public: 
SYNTimer(simple_trans_agent* t) : TimerHandler(), t_(t) { 
} 
inline virtual void expire(Event *); 
protected: 
simple_trans_agent* t_; 
}; 

#endif

simple_trans.cc代碼內容
#include "simple_trans.h" 
//顯示系統時間 
#define NOW Scheduler::instance().clock() 
//得到當前節點的地址 
#define MYNODE Address::instance().get_nodeaddr(addr()) 

int hdr_simple_trans::offset_; 

static class simple_transHeaderClass : public PacketHeaderClass { 
public: 
simple_transHeaderClass() : PacketHeaderClass("PacketHeader/simple_trans",sizeof(hdr_simple_trans)) { 
bind_offset(&hdr_simple_trans::offset_); 
} 
} class_simple_transhdr; 

static class simple_transClass : public TclClass { 
public: 
simple_transClass() : TclClass("Agent/simple_trans") {} 
TclObject* create(int, const char*const*) { 
return (new simple_trans_agent()); 
} 
} class_simple_trans; 

simple_trans_agent::simple_trans_agent() : Agent(PT_SIMPLE_TRANS_PACKET), 
simple_target(-1), simple_port(PROTOCOL_DEFAULT_PORT) { 

bind("simple_target_", &simple_target); 
bind("simple_port_", &simple_port); 

} 

//到時了就發送我們的 SYN 信息給我們的目標節點 
void SYNTimer::expire(Event *){ 

t_->send_simple_msg(PROTOCOL_INIT_SYN, t_->get_target()); 

this->resched(1.00); 
} 

void simple_trans_agent::send_simple_msg(int type, int target) { 
//數據包的生成 
Packet* pkt = allocpkt(); 
//數據包的訪問 
hdr_ip *iph = hdr_ip::access(pkt); 
hdr_simple_trans *shdr = hdr_simple_trans::access(pkt); 

if( type == PROTOCOL_INIT_SYN) { 

if( simple_target != -1 ) { 
iph->daddr() = simple_target; 
} else { 
printf(" no target specificed \n "); 
return ; 
} 
iph->dport() = simple_port; 
iph->saddr() = MYNODE; 
shdr->type = PROTOCOL_INIT_SYN; 
send( pkt, 0 ); 
} 
} 

int simple_trans_agent::command(int argc, const char*const* argv) { 

if( argc == 2 ) { 
if( !strcmp( argv[1], "begin" ) ) { 

//sendsend_simple_msg( PROTOCOL_INIT_SYN, simple_target ); 
SYNTimer *syn_timer = new SYNTimer(this); 
syn_timer->resched(1.00); 

return (TCL_OK); 
} 
} 

if( argc == 3 ) { 

if( !strcmp( argv[1], "set-target" ) ) { 

simple_target = atoi( argv[2] ); 

printf("=>set-target = %d \n ", simple_target); 

return (TCL_OK); 
} 
} 

return (Agent::command(argc, argv)); 
} 

void simple_trans_agent::recv(Packet *p, Handler *) { 

hdr_ip *iph = hdr_ip::access(p); 
hdr_simple_trans *shdr = hdr_simple_trans::access(p); 

if( shdr->type == PROTOCOL_INIT_SYN ) { 

printf("=>At %lf node %d receive PROTOCOL_INIT_SYN signaling from node %d \n", 
NOW, MYNODE, iph->saddr()); 

} else { 

printf(" wrong type siganling \n"); 
} 
} 

二、對packet.h進行修改

在 NS-2.30/common/packet.h :

(1)在enum packet_t中的最後加入 PT_SIMPLE_TRANS_PACKET,  (注意後面的逗號不能省略)
(2)在 class p_info 中最後加入name_[PT_SIMPLE_TRANS_PACKET] = "simple_trans_packet" ; (注意後面的分號不能省略)

packet.h關鍵代碼內容:

//add by song
PT_SIMPLE_TRANS_PACKET
// insert new packet types here
PT_NTYPE // This MUST be the LAST one

name_[PT_SIMPLE_TRANS_PACKET] = "SIMPLE_trans_packet";
name_[PT_NTYPE]= "undefined";

具體截圖如下:
1、

 

2、

三、對ns-2.30進行重新編譯

最後一步,就是編譯我們整個協議將其鍵入到 ns 中了,編譯前我們要修改 makefile 文件(root權限下修改才能保存),由於我們是在ns-2.30/kgn 目錄中所以, makefile 需要修改的有兩個地方:

在 INCLUDES = 中加入 -I./kgn ,加入這個的好處就是我們在其他目錄使用 simple_trans.h 的時候不用將 kgn 次級目錄包含進去;

在 OBJ_CC = 中加入 kgn/simple_trans.o \ 。

makefile關鍵代碼內容:

INCLUDES = \
    -I.  \
    -I. \
    -I/home/song/ns-allinone-2.35/tclcl-1.20 -I/home/song/ns-allinone-2.35/otcl-1.14 -I/home/song/ns-allinone-2.35/include -I/home/song/ns-allinone-2.35/include -I/home/song/ns-allinone-2.35/include -I/usr/include/pcap \  
    -I./tcp -I./sctp -I./common -I./link -I./queue \
    -I./adc -I./apps -I./mac -I./mobile -I./trace \
    -I./routing -I./tools -I./classifier -I./mcast \
    -I./diffusion3/lib/main -I./diffusion3/lib \
    -I./diffusion3/lib/nr -I./diffusion3/ns \
    -I./diffusion3/filter_core -I./asim/ -I./qs \
    -I./diffserv -I./satellite \
    -I./wpan\
    -I./kgn

OBJ_CC = \ 
tools/random.o tools/rng.o tools/ranvar.o common/misc.o common/timer-handler.o \
common/scheduler.o common/object.o common/packet.o \
common/ip.o routing/route.o common/connector.o common/ttl.o \
trace/trace.o trace/trace-ip.o \
classifier/classifier.o classifier/classifier-addr.o \
classifier/classifier-hash.o \
classifier/classifier-virtual.o \
classifier/classifier-mcast.o \
classifier/classifier-bst.o \
classifier/classifier-mpath.o mcast/replicator.o \
...... 
queue/delayer.o \
xcp/xcpq.o xcp/xcp.o xcp/xcp-end-sys.o \
wpan/p802_15_4csmaca.o wpan/p802_15_4fail.o \
wpan/p802_15_4hlist.o wpan/p802_15_4mac.o \
wpan/p802_15_4nam.o wpan/p802_15_4phy.o \
wpan/p802_15_4sscs.o wpan/p802_15_4timer.o \
wpan/p802_15_4trace.o wpan/p802_15_4transac.o \
apps/pbc.o \
kgn/simple_trans.o \
$(OBJ_STL)

具體截圖如下:
1、

2、


(3)重新編譯NS2源碼Terminal中完成以下步驟)。編譯完成重新安裝後,可以進行測試。
1、進入ns-2.30目錄
2、運行make clean
3、運行make

四、編寫TCL進行測試:

# This script is created by NSG2 beta1 
# <http://wushoupong.googlepages.com/nsg> 

#=================================== 
# Simulation parameters setup 
#=================================== 
Antenna/OmniAntenna set Gt_ 1 ;#Transmit antenna gain 
Antenna/OmniAntenna set Gr_ 1 ;#Receive antenna gain 
set val(chan) Channel/WirelessChannel ;# channel type 
set val(prop) Propagation/TwoRayGround ;# radio-propagation model 
set val(netif) Phy/WirelessPhy ;# network interface type 
set val(mac) Mac/802_11 ;# MAC type 
set val(ifq) Queue/DropTail/PriQueue ;# interface queue type 
set val(ll) LL ;# link layer type 
set val(ant) Antenna/OmniAntenna ;# antenna model 
set val(ifqlen) 50 ;# max packet in ifq 
set val(nn) 2 ;# number of mobilenodes 
set val(rp) DSDV ;# routing protocol 
set val(x) 499 ;# X dimension of topography 
set val(y) 401 ;# Y dimension of topography 
set val(stop) 10.0 ;# time of simulation end 

#=================================== 
# Initialization 
#=================================== 
#Create a ns simulator 
set ns [new Simulator] 

#Setup topography object 
set topo [new Topography] 
$topo load_flatgrid $val(x) $val(y) 
create-god $val(nn) 

#Open the NS trace file 
set tracefile [open out.tr w] 
$ns trace-all $tracefile 

#Open the NAM trace file 
set namfile [open out.nam w] 
$ns namtrace-all $namfile 
$ns namtrace-all-wireless $namfile $val(x) $val(y) 
set chan [new $val(chan)];#Create wireless channel 

#=================================== 
# Mobile node parameter setup 
#=================================== 
$ns node-config -adhocRouting $val(rp) \
-llType $val(ll) \
-macType $val(mac) \
-ifqType $val(ifq) \
-ifqLen $val(ifqlen) \
-antType $val(ant) \
-propType $val(prop) \
-phyType $val(netif) \
-channel $chan \
-topoInstance $topo \
-agentTrace ON \
-routerTrace ON \
-macTrace ON \
-movementTrace ON

#=================================== 
# Nodes Definition 
#=================================== 
#Create 2 nodes 
set n0 [$ns node] 
$n0 set X_ 300 
$n0 set Y_ 300 
$n0 set Z_ 0.0 
$ns initial_node_pos $n0 20 
set n1 [$ns node] 
$n1 set X_ 545 
$n1 set Y_ 300 
$n1 set Z_ 0.0 
$ns initial_node_pos $n1 20 

#=================================== 
# Agents Definition 
#=================================== 
set sT1 [new Agent/simple_trans] 
#$sT1 set-target [AddrParams addr2id [$n1 node-addr]] 
$sT1 set simple_target_ [AddrParams addr2id [$n1 node-addr]] 
$n0 attach $sT1 1023 

set sT2 [new Agent/simple_trans] 
$n1 attach $sT2 1023 
$sT2 set interval_ 0.1 
#=================================== 
# Applications Definition 
#=================================== 

#=================================== 
# Termination 
#=================================== 
#Define a 'finish' procedure 
proc finish {} { 
global ns tracefile namfile 
$ns flush-trace 
close $tracefile 
close $namfile 
#exec nam out.nam & 
exit 0 
} 
for {set i 0} {$i < $val(nn) } { incr i } { 
$ns at $val(stop) "\$n$i reset" 
} 
$ns at 1.0 "$sT1 begin" 
$ns at $val(stop) "$ns nam-end-wireless $val(stop)" 
$ns at $val(stop) "finish" 
$ns at $val(stop) "puts \"done\" ; $ns halt" 
$ns run

注意:TCL腳本文件中的節點配置語句中,符號“\”後面不能有空格,
否則在執行ns simple_trans.tcl時,會報錯。
$ns node-config -adhocRouting  $val(rp) \
                -llType        $val(ll) \
                -macType       $val(mac) \
                ......
                -channel       $chan \
                -topoInstance  $topo \
                -agentTrace    ON \
                -routerTrace   ON \
                -macTrace      ON \
                -movementTrace ON


運行效果截圖:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章