打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
转:MFlood协议实现
前言        在”NS與網絡模擬”一書的第七章案例分析,作者介紹了一個無線路由通訊協定(wireless routing protocol)-MFlood,因為作者在寫書時,可能使用的ns的版本是ns-2.26,所以使得一些ns-2.27的使用者無法成功的執行此範例。
在筆者辛苦努力的debug之下,參考了DSDV的寫法,最後卻因為”運氣好”的關係使得Mflood可以成功的運作,為何說是運氣好,這是因為筆者也不知道為何把” port-dmux”加入mflood.cc的command function內就OK了,若是有知道的人,請您一定要寫信告訴筆者。
[原因----感謝Yung-Mu Chen的來信]
in tcl/lib/ns-mobilenode.tcl
2.26
line 249 to 255
249        set dmux_ [$self demux]
250        set classifier_ [$self entry]
251
252        if { [Simulator set RouterTrace_] == "ON" } {
253                #
254                # Send Target
255                #
>******************
2.27
line 249 to 258
249        set dmux_ [$self demux]
250        set classifier_ [$self entry]
251
252        # let the routing agent know about the port dmux
253        $agent port-dmux $dmux_
254
255        if { [Simulator set RouterTrace_] == "ON" } {
256                #
257                # Send Target
258                #
>*******************
In line 253, it accesses "port-dmux".
This causes the Mflood protocol faiulre in 2.27, becaues it access a
non-existing function called port-dmux on the Agent object.
[Mflood的安裝方法]
1.      修改ns-lib.tcl
Simulator instproc create-wireless-node args {
……
OMNIMCAST {
eval $node addr $args
set ragent [$self create-omnimcast-agent $node]
}
MFlood {
set ragent [$self create-mflood-agent $node]
}
DumbAgent {
set ragent [$self create-dumb-agent $node]
}
……
}
另外在空白的地方加入底下的程式碼
Simulator instproc create-tora-agent { node } {
set ragent [new Agent/TORA [$node id]]
$node set ragent_ $ragent
return $ragent
}
Simulator instproc create-mflood-agent {node} {
set ragent [new Agent/MFlood [$node id]]
$node set ragent_ $ragent
return $ragent
}
2.      修改ns-packet.tcl
foreach prot {
MFlood
AODV
……
}
3.      修改packet.h
enum packet_t {
……
PT_AODV,
PT_MFLOOD,
……
}
p_info() {
……
name_[PT_AODV]= "AODV";
name_[PT_MFLOOD]="MFlood";
……
}
4.      修改Makefile
在OBJ_CC中增加一行:
mflood/mflood.o mflood/mflood-seqtable.o\
5.      在ns的目錄下新增一個目錄mflood,然後使用文字編輯器把mflood.cc、mflood.h、mflood-packet.h、mflood-seqtable.cc、和mflood-seqtable.h放到此目錄下。程式碼如下:
mflood.cc
#include "mflood.h"
#include "mflood-packet.h"
#include <random.h>
#include <cmu-trace.h>
#include <iostream>
// New packet type
int hdr_mflood::offset_;
static class MFloodHeaderClass : public PacketHeaderClass {
public:
MFloodHeaderClass() : PacketHeaderClass("PacketHeader/MFlood",
sizeof(hdr_mflood)) {
bind_offset(&hdr_mflood::offset_);
}
} class_mfloodhdr;
// TCL Hooks
static class MFloodclass : public TclClass {
public:
MFloodclass() : TclClass("Agent/MFlood") {}
TclObject* create(int argc, const char*const* argv) {
assert(argc == 5);
return (new MFlood((nsaddr_t) atoi(argv[4]))); // PBO agrv[4] is index_}
}
} class_rtProtoMFlood;
int MFlood::command(int argc, const char*const* argv) {
Tcl& tcl = Tcl::instance();
if(argc == 2) {
if(strncasecmp(argv[1], "id", 2) == 0) {
tcl.resultf("%d", index_);
return TCL_OK;
}
else if (strcmp(argv[1], "uptarget") == 0) {
if (uptarget_ != 0)
tcl.result(uptarget_->name());
return (TCL_OK);
}
} else if(argc == 3) {
if(strcmp(argv[1], "index_") == 0) {
index_ = atoi(argv[2]);
return TCL_OK;
} else if(strcmp(argv[1], "log-target") == 0 || strcmp(argv[1], "tracetarget") == 0) {
logtarget = (Trace*) TclObject::lookup(argv[2]);
if(logtarget == 0) return TCL_ERROR;
return TCL_OK;
}
else if (strcmp(argv[1], "uptarget") == 0) {
if (*argv[2] == '0') {
target_ = 0;
return (TCL_OK);
}
uptarget_ = (NsObject*)TclObject::lookup(argv[2]);
if (uptarget_ == 0) {
tcl.resultf("no such object %s", argv[2]);
return (TCL_ERROR);
}
return (TCL_OK);
}
//底下的碼是筆者新增的
else if (strcasecmp (argv[1], "port-dmux") == 0) {
TclObject *obj;
port_dmux_ = (NsObject *) obj;
return TCL_OK;
}
}
return Agent::command(argc, argv);
}
MFlood::MFlood(nsaddr_t id) : Agent(PT_MFLOOD), port_dmux_(0) {
index_ = id;
logtarget = 0;
myseq_ = 0;
}
// Route Handling Functions
void MFlood::rt_resolve(Packet *p) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
struct hdr_mflood *fh = HDR_MFLOOD(p);
MFlood_RTEntry* rt;
rt = rtable_.rt_lookup(ih->saddr());
if(rt == NULL) {
rt = new MFlood_RTEntry(ih->saddr(), fh->seq_);
LIST_INSERT_HEAD(&rtable_.rthead,rt,rt_link);
printf("%.8f %d,no uptarget,\n",NOW_,index_);
forward(rt,p,FORWARD_DELAY);
printf("%.8f %d,no rt,so forward.rt_seq:%d,pkt seq:%d\n",NOW_,index_,rt->max_seqno,fh->seq_);
rtable_.rt_print();
}
// else if(rt->seq_ < fh->seq_ )
else if(rt->isNewSeq(fh->seq_) )
{
printf("%.8f %d,no uptarget,\n",NOW_,index_);
forward(rt, p, FORWARD_DELAY);
//  rt->seq_ = fh->seq_;
rt->addSeq(fh->seq_);
printf("%.8f %d,rt seq too small,so forward,rt_seq:%d,packet seq:%d.\n", NOW_,index_,rt->max_seqno,fh->seq_);
rtable_.rt_print();
}
else
{
drop(p, "LOWSEQ");
}
}
// Packet Reception Routines
void MFlood::recv(Packet *p, Handler*) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
struct hdr_mflood *fh = HDR_MFLOOD(p);
assert(initialized());
if((ih->saddr() == index_) && (ch->num_forwards() == 0)) { // Must be a packet I'm originating...
ch->size() += IP_HDR_LEN;  // Add the IP Header
ih->ttl_ = NETWORK_DIAMETER;
fh->seq_ = myseq_++;
forward((MFlood_RTEntry*)1,p,0);
return;
} else if(ih->saddr() == index_) { // I received a packet that I sent.  Probably a routing loop.
drop(p, DROP_RTR_ROUTE_LOOP);
return;
} else {  // Packet I'm forwarding...
if(--ih->ttl_ == 0) { // Check the TTL.  If it is zero, then discard.
drop(p, DROP_RTR_TTL);
return;
}
}
rt_resolve(p);
}
// Packet Transmission Routines
void MFlood::forward(MFlood_RTEntry* rt, Packet *p, double delay) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
assert(ih->ttl_ > 0);
assert(rt != 0);
// assert(rt->rt_flags == RTF_UP);
ch->next_hop_ = -1; //Broadcast address
ch->addr_type() = NS_AF_INET;
ch->direction() = hdr_cmn::DOWN;       //important: change the packet's direction
if(delay > 0.0) {
Scheduler::instance().schedule(target_, p, Random::uniform(delay*2));
} else {  // Not a broadcast packet, no delay, send immediately
Scheduler::instance().schedule(target_, p, 0.);
}
}
mflood.h
#ifndef _mflood_h_
#define _mflood_h_
#include <sys/types.h>
#include <cmu-trace.h>
#include <priqueue.h>
#include "mflood-seqtable.h"
//筆者把原本NOW改成NOW_,這樣就不會在編譯時有warning
#define NOW_ (Scheduler::instance().clock())
#define NETWORK_DIAMETER        30             // 30 hops
// The followings are used for the forward() function. Controls pacing.
#define FORWARD_DELAY 0.01          // random delay
#define NO_DELAY -1.0                 // no delay
class MFlood: public Agent {
/ *
* make some friends first
*/
friend class MFlood_RTEntry;
public:
MFlood(nsaddr_t id);
void recv(Packet *p, Handler *);
protected:
int             command(int, const char *const *);
int             initialized() { return 1 && target_; }
void rt_resolve(Packet *p);
void forward(MFlood_RTEntry *rt, Packet *p, double delay);
nsaddr_t index_;
MFlood_RTable rtable_;
Trace *logtarget;
NsObject *uptarget_;
// 底下是筆者新增加的
NsObject *port_dmux_;
private:
u_int32_t myseq_;
};
#endif
mflood-packet.h
#ifndef __mflood_packet_h__
#define __mflood_packet_h__
#define HDR_MFLOOD(p)  ((struct hdr_mflood*)hdr_mflood::access(p))
struct hdr_mflood{
u_int32_t seq_;
static int offset_; // required by PacketHeaderManager
inline static int& offset() { return offset_; }
inline static hdr_mflood* access(const Packet* p) {
return (hdr_mflood*) p->access(offset_);
}
};
#endif
mflood-seqtable.cc
#include "mflood/mflood-seqtable.h"
// The Routing Table
MFlood_RTEntry::MFlood_RTEntry() {
src_ = 0;
for(int i=0;i<REM_SEQ_COUNT;i++)
rt_seqnos[i] = 0xffffffff;
max_seqno = 0;
min_seqno = 0;
seq_it = 0;
};
// The Routing Table
MFlood_RTEntry::MFlood_RTEntry(nsaddr_t src,u_int32_t seq) {
src_ = src;
for(int i=0;i<REM_SEQ_COUNT;i++)
rt_seqnos[i] = 0xffffffff;
rt_seqnos[0] = seq;
max_seqno = seq;
min_seqno = 0;
seq_it = 1;
};
bool MFlood_RTEntry::isNewSeq(u_int32_t seq)
{
if(seq > max_seqno)
return true;
//採用min_seqno來拋棄掉太久以前的包
if(seq < min_seqno)
return false;
for(int i=0;i<REM_SEQ_COUNT;i++)
if(seq == rt_seqnos[i])
return false;
return true;
}
void MFlood_RTEntry::addSeq(u_int32_t seq)
{
u_int16_t min_it = 0;
if(seq < min_seqno)
return;
if(seq > max_seqno)
max_seqno = seq;
/*
for(int i=0;i<REM_SEQ_COUNT;i++)
if(seq == rt_seqnos)
return;
*/
rt_seqnos[seq_it++] = seq;
seq_it %= REM_SEQ_COUNT;
min_seqno = 0xffffffff;
//計算出min_seqno
for(int i=0;i<REM_SEQ_COUNT;i++)
if(min_seqno > rt_seqnos[i])
min_seqno = rt_seqnos[i];
}
// The Routing Table
MFlood_RTEntry*
MFlood_RTable::rt_lookup(nsaddr_t id) {
MFlood_RTEntry *rt = rthead.lh_first;
for(; rt; rt = rt->rt_link.le_next) {
if(rt->src_ == id)
break;
}
return rt;
}
void
MFlood_RTable::rt_delete(nsaddr_t id) {
MFlood_RTEntry *rt = rt_lookup(id);
if(rt) {
LIST_REMOVE(rt, rt_link);
delete rt;
}
}
void
MFlood_RTable::rt_print() {
MFlood_RTEntry *rt = rthead.lh_first;
printf("\n Seq table:\n");
for(; rt; rt = rt->rt_link.le_next) {
printf("index: %d , seq: %d \n",rt->src_,rt->max_seqno);
}
return;
}
mflood-seqtable.h
#ifndef __mflood_rtable_h__
#define __mflood_rtable_h__
#include <assert.h>
#include <sys/types.h>
#include <config.h>
#include <lib/bsd-list.h>
#include <scheduler.h>
#define INFINITY2        0xff
#define RTF_DOWN 0
#define RTF_UP 1
#define REM_SEQ_COUNT 1000
class MFlood_RTEntry{
friend class MFlood_RTable;
friend class MFlood;
public:
MFlood_RTEntry();
MFlood_RTEntry(nsaddr_t src, u_int32_t seq);
bool isNewSeq(u_int32_t seq);
void addSeq(u_int32_t seq);
protected:
LIST_ENTRY(MFlood_RTEntry) rt_link;
nsaddr_t        src_;
u_int32_t rt_seqnos[REM_SEQ_COUNT];
u_int32_t max_seqno;
u_int32_t min_seqno;
u_int16_t  seq_it;
};
class MFlood_RTable{
friend class MFlood;
public:
MFlood_RTable(){LIST_INIT(&rthead);}
void rt_delete(nsaddr_t id);
MFlood_RTEntry* rt_lookup(nsaddr_t id);
void rt_print();
private:
LIST_HEAD(MFlood_rthead, MFlood_RTEntry) rthead;
};
#endif
[測試]
mflood.tcl
======================================================================
# Define options
# ======================================================================
set val(ifqlen)         50                           ;# max packet in ifq
set val(nn)             3                           ;# number of mobilenodes
set val(rp)             MFlood                       ;# routing protocol
set val(chan)       Channel/WirelessChannel
set val(prop)       Propagation/TwoRayGround
set val(netif)      Phy/WirelessPhy
set val(mac)        Mac/802_11
set val(ifq)        Queue/DropTail/PriQueue
set val(ll)         LL
set val(ant)        Antenna/OmniAntenna
set val(stop)     200
# ======================================================================
# Main Program
# ======================================================================
#ns-random 0
# Initialize Global Variables
set ns_ [new Simulator]
set tracefd [open mflood.tr w]
$ns_ trace-all $tracefd
set namtrace    [open mflood.nam w]
$ns_ namtrace-all-wireless $namtrace 1000 500
# set up topography
set topo [new Topography]
$topo load_flatgrid 1000 500
# Create God
create-god $val(nn)
# Create the specified number of mobilenodes [$val(nn)] and "attach" them
# to the channel.
# configure node
set channel [new Channel/WirelessChannel]
$channel set errorProbability_ 0.0
$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 $channel \
-topoInstance $topo \
-agentTrace ON \
-routerTrace ON\
-macTrace OFF \
-movementTrace OFF
for {set i 0} {$i < $val(nn) } {incr i} {
set node_($i) [$ns_ node]
$node_($i) random-motion 0
}
# Provide initial (X,Y, for now Z=0) co-ordinates for mobilenodes
$node_(0) set X_ 100.0
$node_(0) set Y_ 200.0
$node_(0) set Z_ 0.0
$node_(1) set X_ 250.0
$node_(1) set Y_ 200.0
$node_(1) set Z_ 0.0
$node_(2) set X_ 400.0
$node_(2) set Y_ 200.0
$node_(2) set Z_ 0.0
# Define node initial position in nam
for {set i 0} {$i < $val(nn)} {incr i} {
# 20 defines the node size in nam, must adjust it according to your scenario
# The function must be called after mobility model is defined
$ns_ initial_node_pos $node_($i) 20
}
set udp_(0) [new Agent/UDP]
$ns_ attach-agent $node_(0) $udp_(0)
set null_(0) [new Agent/Null]
$ns_ attach-agent $node_(2) $null_(0)
$ns_ connect $udp_(0) $null_(0)
set cbr_(0) [new Application/Traffic/CBR]
$cbr_(0) set packetSize_ 512
$cbr_(0) set interval_ 4.0
$cbr_(0) set random_ 1
$cbr_(0) set maxpkts_ 10000
$cbr_(0) attach-agent $udp_(0)
$ns_ at 10.0 "$cbr_(0) start"
# Tell nodes when the simulation ends
for {set i 0} {$i < $val(nn) } {incr i} {
$ns_ at $val(stop).0 "$node_($i) reset";
}
$ns_ at $val(stop).0 "stop"
$ns_ at $val(stop).01 "puts \"NS EXITING...\" ; $ns_ halt"
proc stop {} {
global ns_ tracefd
$ns_ flush-trace
close $tracefd
}
puts "Starting Simulation..."
$ns_ run
執行完後會產生一mflood.tr,內容如下
s 10.000000000 _0_ AGT  --- 0 cbr 512 [0 0 0 0] ------- [0:0 2:0 32 0] [0] 0 0
r 10.000000000 _0_ RTR  --- 0 cbr 512 [0 0 0 0] ------- [0:0 2:0 32 0] [0] 0 0
s 10.000000000 _0_ RTR  --- 0 cbr 532 [0 0 0 0] ------- [0:0 2:0 30 0] [0] 0 0
r 10.004812500 _1_ RTR  --- 0 cbr 532 [0 ffffffff 0 800] ------- [0:0 2:0 30 0] [0] 1 0
f 10.006574953 _1_ RTR  --- 0 cbr 532 [0 ffffffff 0 800] ------- [0:0 2:0 29 0] [0] 1 0
r 10.011667453 _0_ RTR  --- 0 cbr 532 [0 ffffffff 1 800] ------- [0:0 2:0 29 0] [0] 2 0
D 10.011667453 _0_ RTR LOOP 0 cbr 532 [0 ffffffff 1 800] ------- [0:0 2:0 29 0] [0] 2 0
……
這個結果跟書本上的結果是一樣的。
[結語]
這個範例是一個不錯的範例,作者在介紹完如何新增mflood到ns2之後的”場景測試”這個小節,讓三個節點移動,並量測因為移動而對於傳輸速率的影響,所以若是對於此範例有興趣的人,應該好好把這個實驗做一次。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
ns: record: can't read "firstPktTime_": no such variable的解决办法
NS2中仿真分析基于CSMA/CA的WLAN的捕获效应
vxworks(2.0.2)版本中对于arp的处理
两个结构一样的表进行数据差分
C语言单链表逆置
找出有序链表交集并存入新链表
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服