ns2模擬學習(六)-自定義協議
阿新 • • 發佈:2019-02-17
這次,我是仿照ns2中的sctp,實現了一個多宿主的UDP協議,目前還比較簡單,只能獲取端到端的rtt,能夠明顯看到資料包的亂序情況。中間遇到遇到一些小波折,記錄在此,以備後用。
在ns2目錄下增加資料夾mpudpns2,放置所有的原始檔。
除錯的log,採用的是[1],放在mpudpns2檔案下即可使用。當然這個log程式是C語言的,用在C++的環境中需要在h檔案中,增加一個巨集定義
#ifdef __cplusplus
extern "C" {
#endif
#複製原有的內容
#ifdef __cplusplus
}
#endif
定義協議標頭檔案mpudphdr.h,裡面定義個兩種資料包型別,hdr_mpudp和hdr_mpudp_ack。定義如下:
在mpudp.cc檔案內定義類註冊相應的資料包頭偏移,就是Packet中的結構體中的bits_會攜帶自定義協議頭的空間,之後可以通過型別轉換,將bits_中的記憶體進行強制轉換,獲取自定義的報文頭,(hdr_mpudp *) p->access(offset_)。註冊報文頭偏移的類如下:struct hdr_mpudp { double timestamp; int flowid; int packetid; // Packet header access functions static int offset_; inline static int &offset() { return offset_; } inline static hdr_mpudp*access(const Packet * p) { return (hdr_mpudp *) p->access(offset_); } }; struct hdr_mpudp_ack { double timestamp; double mpudp_timestamp;//is the timestamp in hdr_mpudp; int packetid; int flow_id_; // Packet header access functions static int offset_; inline static int &offset() { return offset_; } inline static hdr_mpudp_ack*access(const Packet * p) { return (hdr_mpudp_ack *) p->access(offset_); } };
這個時候,需要在ns-packet.tcl(在ns2.35/tcl/lib/資料夾下)指令碼中寫入相應報文頭的名字,名字與PacketHeader/MpUdp中的第二項保持一致。如果不增加這一項,根本不能在Packet中訪問自定義的資料報頭。static class MpUdpHeaderClass:public PacketHeaderClass { public: MpUdpHeaderClass():PacketHeaderClass("PacketHeader/MpUdp",sizeof(hdr_mpudp)){ bind_offset(&hdr_mpudp::offset_); } }class_mpudp_header; static class MpUdpAckHeaderClass:public PacketHeaderClass { public: MpUdpAckHeaderClass():PacketHeaderClass("PacketHeader/MpUdpAck",sizeof(hdr_mpudp_ack)) { bind_offset(&hdr_mpudp_ack::offset_); } }class_mpudpack_header;
# Application-Layer Protocols:
Message # a protocol to carry text messages
Ping # Ping
PBC # PBC
MpUdp
MpUdpAck
在ns-lib.tcl中仿照SCTP的處理方式,增加相應的命令處理,修改了兩處:
//ns-lib.tcl?line=1516 Simulator instproc attach-agent { node agent } if {[lindex [split [$agent info class] "/"] 1] == "MpUdpAgent"} { $agent instvar multihome_bindings_ set binding_ {} set addr [$agent set agent_addr_] set port [$agent set agent_port_] lappend binding_ $addr lappend binding_ $port lappend multihome_bindings_ $binding_ } //ns-lib.tcl Simulator instproc connect {src dst} if {[lindex [split [$src info class] "/"] 1] == "MpUdpAgent"} { $self multihome-connect $src $dst }
另外,需要定義資料包型別和相應的名稱
// insert new packet types here
static const packet_t PT_MPUDP=73; //[zsy-2017]
static const packet_t PT_MPUDP_ACK=74;//[zsy-2017]
static packet_t PT_NTYPE = 75; // This MUST be the LAST one
name_[PT_MPUDP]="MPUDP";
name_[PT_MPUDP_ACK]="MPUDP_ACK";
在Makefile.in中增加需要編譯的原始檔:
mpudpns2/log.o mpudpns2/mpudp.o\
之後在ns-2.35檔案下執行./configure 生成makefile,執行make,編譯
最後的模擬指令碼mpudp.tcl
set ns [new Simulator]
set host0_core [$ns node]
set host0_if0 [$ns node]
set host0_if1 [$ns node]
$host0_core color Red
$host0_if0 color Red
$host0_if1 color Red
$ns multihome-add-interface $host0_core $host0_if0
$ns multihome-add-interface $host0_core $host0_if1
set host1_core [$ns node]
set host1_if0 [$ns node]
set host1_if1 [$ns node]
$host1_core color Blue
$ns multihome-add-interface $host1_core $host1_if0
$ns multihome-add-interface $host1_core $host1_if1
set router [$ns node]
$ns duplex-link $host0_if0 $router 1Mb 200ms DropTail
$ns duplex-link $host0_if1 $router 1Mb 100ms DropTail
$ns duplex-link $host1_if0 $router 2Mb 200ms DropTail
$ns duplex-link $host1_if1 $router 2Mb 100ms DropTail
set mpudp0 [new Agent/MpUdpAgent]
$ns multihome-attach-agent $host0_core $mpudp0
$mpudp0 sender_trace "mpudpsender.txt"
set mpudp1 [new Agent/MpUdpAgent]
$mpudp1 receiver_trace "mpudpreceiver.txt"
$ns multihome-attach-agent $host1_core $mpudp1
$ns connect $mpudp0 $mpudp1
set cbr0 [new Application/Traffic/CBR]
$cbr0 set type_ CBR
$cbr0 set packet_size_ 1000
$cbr0 set rate_ 1mb
$cbr0 set random_ false
$cbr0 attach-agent $mpudp0
$ns at 0.1 "$cbr0 start"
$ns at 5.0 "$cbr0 stop"
$ns run
最後的程式碼下載[2].
接收端接收到的ack之後答應的日誌,可以明顯反映出資料包的亂序情況:
flowid packeid timerecvack timesender timereceiver pt
1 1 0.8205 0.1080 0.4200 74
1 3 0.8365 0.1240 0.4360 74
1 5 0.8525 0.1400 0.4520 74
1 7 0.8685 0.1560 0.4680 74
1 9 0.8845 0.1720 0.4840 74
1 11 0.9005 0.1880 0.5000 74
0 0 0.9125 0.1000 0.5120 74
1 13 0.9165 0.2040 0.5160 74
0 2 0.9285 0.1160 0.5280 74
1 15 0.9325 0.2200 0.5320 74
0 4 0.9445 0.1320 0.5440 74
1 17 0.9485 0.2360 0.5480 74
0 6 0.9605 0.1480 0.5600 74
1 19 0.9645 0.2520 0.5640 74
0 8 0.9765 0.1640 0.5760 74
原有執行指令碼上的拓補:
~~host0_if0~~ ~~host1_if0~~
/ (1)200ms \ / (3)200ms \
host0_core -router- -host1_core
\ (2)100ms / \ (4)100ms /
~host0_if1~~ ~host2_if1~~
這種方式帶來了路由上的歧義,才會導致模擬結果中一條路徑的單向時延為0.3,另一個為0.4。因此在中間增加一個router,讓host0_if0與host0_if1之間的路徑唯一確定。