Você está na página 1de 44

NS examples for wireless scenario

[ A Simple One | A Complex One | Link Error Example | Back to Network Simulator 2 for Wireless ]

This is a simple test scenario for 4x4 grid and 4 flows.


# =================================================== # Author: ZHIBIN WU 06/19/2003 # ==================================================

set set set set

cbr_size 500 cbr_interval 0.002 num_row 4 time_duration 100

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(rp) DSDV ;# routing protocol # # Initialize ns # set ns_ [new Simulator] set tracefd [open simple.tr w] $ns_ trace-all $tracefd # set up topography object set topo [new Topography] $topo load_flatgrid 1000 1000 create-god [expr $num_row * $num_row ] $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 [new $val(chan)] -topoInstance $topo \ -agentTrace ON -routerTrace OFF\ -macTrace ON \ -movementTrace OFF for {set i 0} {$i < [expr $num_row*$num_row]} {incr i} { set node_($i) [$ns_ node]

} set k 0; while {$k < $num_row } { for {set i 0} {$i < $num_row } {incr i} { set m [expr $i+$k*$num_row]; $node_($m) set X_ [expr $i*240]; $node_($m) set Y_ [expr $k*240+20.0]; $node_($m) set Z_ 0.0 } incr k; }; for {set i 0} {$i < $num_row } {incr i} { set udp_($i) [new Agent/UDP] set null_($i) [new Agent/Null] } $ns_ attach-agent $node_(0) $udp_(0) $ns_ attach-agent $node_(7) $udp_(1) $ns_ attach-agent $node_(2) $udp_(2) $ns_ attach-agent $node_(7) $udp_(3) $ns_ attach-agent $node_(6) $null_(0) $ns_ attach-agent $node_(1) $null_(1) $ns_ attach-agent $node_(8) $null_(2) $ns_ attach-agent $node_(15) $null_(3) for {set i 0} {$i < $num_row } {incr i} { $ns_ connect $udp_($i) $null_($i) } for {set i 0} {$i < $num_row } {incr i} { set cbr_($i) [new Application/Traffic/CBR] $cbr_($i) set packetSize_ $cbr_size $cbr_($i) set interval_ 0.5 $cbr_($i) attach-agent $udp_($i) } $ns_ at 11.0234 "$cbr_(0) start" $ns_ at 10.4578 "$cbr_(1) start" $ns_ at 12.7184 "$cbr_(2) start" $ns_ at 12.2456 "$cbr_(3) start" # Tell nodes when the simulation ends # for {set i 0} {$i < [expr $num_row*$num_row] } {incr i} { $ns_ at [expr $time_duration +10.0] "$node_($i) reset"; } $ns_ at [expr $time_duration +10.0] "finish" $ns_ at [expr $time_duration +10.01] "puts \"NS Exiting...\"; $ns_ halt" proc finish {} { global ns_ tracefd $ns_ flush-trace close $tracefd } puts "Starting Simulation..." $ns_ run

However, a more professional way to write the test tcl is to following the way in ns examples. For example, it is better to write traffic patten file and mobility file seperately and then source them in the main test tcl. Those files are generated respectively with cbrgen and setdest tools. Those files are ususally stored in "/ns2.??/tcl/mobility/scene" directory. This is an example for DSDV routing with 50 nodes in a 670*670 m2 area
# ====================================================================== # Default Script Options # ====================================================================== set opt(chan) Channel/WirelessChannel set opt(prop) Propagation/TwoRayGround #set opt(netif) NetIf/SharedMedia set opt(netif) Phy/WirelessPhy #set opt(mac) Mac/802_11 set opt(mac) Mac/802_11 set opt(ifq) Queue/DropTail/PriQueue set opt(ll) LL set opt(ant) Antenna/OmniAntenna set set set set set set set set set set set opt(x) opt(y) opt(cp) opt(sc) opt(ifqlen) opt(nn) opt(seed) opt(stop) opt(tr) opt(rp) opt(lm) 670 ;# X dimension of the topography 670 ;# Y dimension of the topography "../mobility/scene/cbr-50-10-4-512" "../mobility/scene/scen-670x670-50-600-20-0" 50 50 0.0 1000.0 out.tr dsdv "off" ;# max packet in ifq ;# number of nodes ;# simulation time ;# trace file ;# routing protocol script ;# log movement

# ====================================================================== #set AgentTrace ON #set RouterTrace ON #set MacTrace OFF Mac trace on is to use node-config LL LL LL LL LL set set set set set mindelay_ delay_ bandwidth_ off_prune_ off_CtrMcast_ 50us 25us 0 0 0 0 0

#useless code, the only way to toggle

;# not used ;# not used ;# not used

Agent/Null set sport_ Agent/Null set dport_

Agent/CBR set sport_ Agent/CBR set dport_ Agent/TCPSink set sport_ Agent/TCPSink set dport_ Agent/TCP set sport_ Agent/TCP set dport_ Agent/TCP set packetSize_

0 0 0 0 0 0 1460 1

Queue/DropTail/PriQueue set Prefer_Routing_Protocols

# unity gain, omni-directional antennas # set up the antennas to be centered in the node and 1.5 meters above it Antenna/OmniAntenna set X_ 0 Antenna/OmniAntenna set Y_ 0 Antenna/OmniAntenna set Z_ 1.5 Antenna/OmniAntenna set Gt_ 1.0 Antenna/OmniAntenna set Gr_ 1.0 # Initialize the SharedMedia interface with parameters to make # it work like the 914MHz Lucent WaveLAN DSSS radio interface Phy/WirelessPhy set CPThresh_ 10.0 Phy/WirelessPhy set CSThresh_ 1.559e-11 Phy/WirelessPhy set RXThresh_ 3.652e-10 Phy/WirelessPhy set Rb_ 2*1e6 Phy/WirelessPhy set Pt_ 0.2818 Phy/WirelessPhy set freq_ 914e+6 Phy/WirelessPhy set L_ 1.0 # ====================================================================== proc usage { puts puts puts puts puts puts } argv0 } { "Usage: $argv0" "\tmandatory arguments:" "\t\t\[-x MAXX\] \[-y MAXY\]" "\toptional arguments:" "\t\t\[-cp conn pattern\] \[-sc scenario\] \[-nn nodes\]" "\t\t\[-seed seed\] \[-stop sec\] \[-tr tracefile\]\n"

proc getopt {argc argv} { global opt lappend optlist cp nn seed sc stop tr x y for {set i 0} {$i < $argc} {incr i} { set arg [lindex $argv $i] if {[string range $arg 0 0] != "-"} continue set name [string range $arg 1 end] set opt($name) [lindex $argv [expr $i+1]] } }

proc cmu-trace { ttype atype node } { global ns_ tracefd if { $tracefd == "" } { return "" } set T [new CMUTrace/$ttype $atype] $T target [$ns_ set nullAgent_] $T attach $tracefd $T set src_ [$node id] $T node $node return $T }

proc log-movement {} { global logtimer ns_ ns set ns $ns_ source ../mobility/timer.tcl Class LogTimer -superclass Timer LogTimer instproc timeout {} { global opt node_; for {set i 0} {$i < $opt(nn)} {incr i} { $node_($i) log-movement } $self sched 0.1 } set logtimer [new LogTimer] $logtimer sched 0.1 } # ====================================================================== # Main Program # ====================================================================== getopt $argc $argv # # Source External TCL Scripts # #source ../lib/ns-mobilenode.tcl #if { $opt(rp) != "" } { #source ../mobility/$opt(rp).tcl #} elseif { [catch { set env(NS_PROTO_SCRIPT) } ] == 1 } { #puts "\nenvironment variable NS_PROTO_SCRIPT not set!\n" #exit #} else { #puts "\n*** using script $env(NS_PROTO_SCRIPT)\n\n"; #source $env(NS_PROTO_SCRIPT)

#} #source ../lib/ns-cmutrace.tcl source ../lib/ns-bsnode.tcl source ../mobility/com.tcl # do the get opt again incase the routing protocol file added some more # options to look for getopt $argc $argv if { $opt(x) == 0 || $opt(y) == 0 } { usage $argv0 exit 1 } if {$opt(seed) > 0} { puts "Seeding Random number generator with $opt(seed)\n" ns-random $opt(seed) } # # Initialize Global Variables # set ns_ [new Simulator] set chan [new $opt(chan)] set prop [new $opt(prop)] set topo [new Topography] set tracefd [open $opt(tr) w] $topo load_flatgrid $opt(x) $opt(y) $prop topography $topo # # Create God # create-god $opt(nn) # # log the mobile nodes movements if desired # if { $opt(lm) == "on" } { log-movement } $ns_ node-config -macTrace ON # # # # # # #

Create the specified number of nodes $opt(nn) and "attach" them the channel. Each routing protocol script is expected to have defined a proc create-mobile-node that builds a mobile node and inserts it into the array global $node_($i)

if { [string compare $opt(rp) "dsr"] == 0} { for {set i 0} {$i < $opt(nn) } {incr i} { dsr-create-mobile-node $i } } elseif { [string compare $opt(rp) "dsdv"] == 0} { for {set i 0} {$i < $opt(nn) } {incr i} { dsdv-create-mobile-node $i } }

# # Source the Connection and Movement scripts # if { $opt(cp) == "" } { puts "*** NOTE: no connection pattern specified." set opt(cp) "none" } else { puts "Loading connection pattern..." source $opt(cp) } # # Tell all the nodes when the simulation ends # for {set i 0} {$i < $opt(nn) } {incr i} { $ns_ at $opt(stop).000000001 "$node_($i) reset"; } $ns_ at $opt(stop).00000001 "puts \"NS EXITING...\" ; $ns_ halt" if { $opt(sc) == "" } { puts "*** NOTE: no scenario file specified." set opt(sc) "none" } else { puts "Loading scenario file..." source $opt(sc) puts "Load complete..." } puts $tracefd "M 0.0 nn $opt(nn) x $opt(x) y $opt(y) rp $opt(rp)" puts $tracefd "M 0.0 sc $opt(sc) cp $opt(cp) seed $opt(seed)" puts $tracefd "M 0.0 prop $opt(prop) ant $opt(ant)" puts "Starting Simulation..." $ns_ run

Note that all options listed in the beginning of the file could be initialized with command line arguments by using "getopt $argc $argv" Example 3 : To attach the error model, add following codes:
.......... proc UniformErr {} { set err [new ErrorModel] $err unit packet $err set rate_ 0.05 return $err } # $err rate_ 0.5 "invalid command ErrModel::Command does not support" # the other valid method is " set err [new ErrorModel/Uniform 0.05 pkt] " # the parameter rate ( 0 or 0.9) is a threshold that all packets all going through and 90% packets are # going to be drop proc TwoStateMarkovErr {} { set tmp0 [new ErrorModel/Uniform 0 pkt] set tmp1 [new ErrorModel/Uniform .7 pkt] # Array of states (error models) set m_states [list $tmp0 $tmp1] # Durations for each of the states, tmp, tmp1 and tmp2, respectively set m_periods [list 0.1 .075 ] # Transition state model matrix set m_transmx { {0.9 0.1 } {0.7 0.3 } } set m_trunit byte # Use time-based transition set m_sttype time set m_nstates 2 set m_nstart [lindex $m_states 0] set em [new ErrorModel/MultiState $m_states $m_periods $m_transmx \ $m_trunit $m_sttype $m_nstates $m_nstart] return $em } $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 $chan1 \ -topoInstance $topo \ -agentTrace ON \ -routerTrace OFF\ -macTrace ON \ -movementTrace OFF \ -IncomingErrProc TwoStateMarkovErr #\ #-OutcomingErrProc TwoStateMarkovErr #The other way to configure error # $ns_ node-config --IncomingErrProc $opt(err)

NS examples for wireless scenario


[ A Simple One | A Complex One | Link Error Example | Back to Network Simulator 2 for Wireless ]

This is a simple test scenario for 4x4 grid and 4 flows.


# =================================================== # Author: ZHIBIN WU 06/19/2003 # ==================================================

set set set set

cbr_size 500 cbr_interval 0.002 num_row 4 time_duration 100

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(rp) DSDV ;# routing protocol # # Initialize ns # set ns_ [new Simulator] set tracefd [open simple.tr w] $ns_ trace-all $tracefd

# set up topography object set topo [new Topography] $topo load_flatgrid 1000 1000 create-god [expr $num_row * $num_row ] $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 [new $val(chan)] -topoInstance $topo \ -agentTrace ON -routerTrace OFF\ -macTrace ON \ -movementTrace OFF for {set i 0} {$i < [expr $num_row*$num_row]} {incr i} { set node_($i) [$ns_ node] } set k 0; while {$k < $num_row } { for {set i 0} {$i < $num_row } {incr i} { set m [expr $i+$k*$num_row]; $node_($m) set X_ [expr $i*240]; $node_($m) set Y_ [expr $k*240+20.0]; $node_($m) set Z_ 0.0 } incr k; }; for {set i 0} {$i < $num_row } {incr i} { set udp_($i) [new Agent/UDP] set null_($i) [new Agent/Null] } $ns_ attach-agent $node_(0) $udp_(0) $ns_ attach-agent $node_(7) $udp_(1) $ns_ attach-agent $node_(2) $udp_(2) $ns_ attach-agent $node_(7) $udp_(3) $ns_ attach-agent $node_(6) $null_(0) $ns_ attach-agent $node_(1) $null_(1) $ns_ attach-agent $node_(8) $null_(2) $ns_ attach-agent $node_(15) $null_(3) for {set i 0} {$i < $num_row } {incr i} { $ns_ connect $udp_($i) $null_($i) } for {set i 0} {$i < $num_row } {incr i} { set cbr_($i) [new Application/Traffic/CBR] $cbr_($i) set packetSize_ $cbr_size $cbr_($i) set interval_ 0.5 $cbr_($i) attach-agent $udp_($i) } $ns_ at 11.0234 "$cbr_(0) start" $ns_ at 10.4578 "$cbr_(1) start" $ns_ at 12.7184 "$cbr_(2) start" $ns_ at 12.2456 "$cbr_(3) start" # Tell nodes when the simulation ends #

for {set i 0} {$i < [expr $num_row*$num_row] } {incr i} { $ns_ at [expr $time_duration +10.0] "$node_($i) reset"; } $ns_ at [expr $time_duration +10.0] "finish" $ns_ at [expr $time_duration +10.01] "puts \"NS Exiting...\"; $ns_ halt" proc finish {} { global ns_ tracefd $ns_ flush-trace close $tracefd } puts "Starting Simulation..." $ns_ run

However, a more professional way to write the test tcl is to following the way in ns examples. For example, it is better to write traffic patten file and mobility file seperately and then source them in the main test tcl. Those files are generated respectively with cbrgen and setdest tools. Those files are ususally stored in "/ns2.??/tcl/mobility/scene" directory. This is an example for DSDV routing with 50 nodes in a 670*670 m2 area
# ====================================================================== # Default Script Options # ====================================================================== set opt(chan) Channel/WirelessChannel set opt(prop) Propagation/TwoRayGround #set opt(netif) NetIf/SharedMedia set opt(netif) Phy/WirelessPhy #set opt(mac) Mac/802_11 set opt(mac) Mac/802_11 set opt(ifq) Queue/DropTail/PriQueue set opt(ll) LL set opt(ant) Antenna/OmniAntenna set set set set set set set set set set set opt(x) opt(y) opt(cp) opt(sc) opt(ifqlen) opt(nn) opt(seed) opt(stop) opt(tr) opt(rp) opt(lm) 670 ;# X dimension of the topography 670 ;# Y dimension of the topography "../mobility/scene/cbr-50-10-4-512" "../mobility/scene/scen-670x670-50-600-20-0" 50 50 0.0 1000.0 out.tr dsdv "off" ;# max packet in ifq ;# number of nodes ;# simulation time ;# trace file ;# routing protocol script ;# log movement

# ====================================================================== #set AgentTrace ON #set RouterTrace ON #set MacTrace OFF Mac trace on is to use node-config LL LL LL LL LL set set set set set mindelay_ delay_ bandwidth_ off_prune_ off_CtrMcast_ 50us 25us 0 0 0 0 0 0 0 0 0 0 0 1460 1

#useless code, the only way to toggle

;# not used ;# not used ;# not used

Agent/Null set sport_ Agent/Null set dport_ Agent/CBR set sport_ Agent/CBR set dport_ Agent/TCPSink set sport_ Agent/TCPSink set dport_ Agent/TCP set sport_ Agent/TCP set dport_ Agent/TCP set packetSize_

Queue/DropTail/PriQueue set Prefer_Routing_Protocols

# unity gain, omni-directional antennas # set up the antennas to be centered in the node and 1.5 meters above it Antenna/OmniAntenna set X_ 0 Antenna/OmniAntenna set Y_ 0 Antenna/OmniAntenna set Z_ 1.5 Antenna/OmniAntenna set Gt_ 1.0 Antenna/OmniAntenna set Gr_ 1.0 # Initialize the SharedMedia interface with parameters to make # it work like the 914MHz Lucent WaveLAN DSSS radio interface Phy/WirelessPhy set CPThresh_ 10.0 Phy/WirelessPhy set CSThresh_ 1.559e-11 Phy/WirelessPhy set RXThresh_ 3.652e-10 Phy/WirelessPhy set Rb_ 2*1e6 Phy/WirelessPhy set Pt_ 0.2818 Phy/WirelessPhy set freq_ 914e+6 Phy/WirelessPhy set L_ 1.0 # ====================================================================== proc usage { puts puts puts puts puts puts argv0 } { "Usage: $argv0" "\tmandatory arguments:" "\t\t\[-x MAXX\] \[-y MAXY\]" "\toptional arguments:" "\t\t\[-cp conn pattern\] \[-sc scenario\] \[-nn nodes\]" "\t\t\[-seed seed\] \[-stop sec\] \[-tr tracefile\]\n"

} proc getopt {argc argv} { global opt lappend optlist cp nn seed sc stop tr x y for {set i 0} {$i < $argc} {incr i} { set arg [lindex $argv $i] if {[string range $arg 0 0] != "-"} continue set name [string range $arg 1 end] set opt($name) [lindex $argv [expr $i+1]] } } proc cmu-trace { ttype atype node } { global ns_ tracefd if { $tracefd == "" } { return "" } set T [new CMUTrace/$ttype $atype] $T target [$ns_ set nullAgent_] $T attach $tracefd $T set src_ [$node id] $T node $node return $T }

proc log-movement {} { global logtimer ns_ ns set ns $ns_ source ../mobility/timer.tcl Class LogTimer -superclass Timer LogTimer instproc timeout {} { global opt node_; for {set i 0} {$i < $opt(nn)} {incr i} { $node_($i) log-movement } $self sched 0.1 } set logtimer [new LogTimer] $logtimer sched 0.1 } # ====================================================================== # Main Program

# ====================================================================== getopt $argc $argv # # Source External TCL Scripts # #source ../lib/ns-mobilenode.tcl #if { $opt(rp) != "" } { #source ../mobility/$opt(rp).tcl #} elseif { [catch { set env(NS_PROTO_SCRIPT) } ] == 1 } { #puts "\nenvironment variable NS_PROTO_SCRIPT not set!\n" #exit #} else { #puts "\n*** using script $env(NS_PROTO_SCRIPT)\n\n"; #source $env(NS_PROTO_SCRIPT) #} #source ../lib/ns-cmutrace.tcl source ../lib/ns-bsnode.tcl source ../mobility/com.tcl # do the get opt again incase the routing protocol file added some more # options to look for getopt $argc $argv if { $opt(x) == 0 || $opt(y) == 0 } { usage $argv0 exit 1 } if {$opt(seed) > 0} { puts "Seeding Random number generator with $opt(seed)\n" ns-random $opt(seed) } # # Initialize Global Variables # set ns_ [new Simulator] set chan [new $opt(chan)] set prop [new $opt(prop)] set topo [new Topography] set tracefd [open $opt(tr) w] $topo load_flatgrid $opt(x) $opt(y) $prop topography $topo # # Create God # create-god $opt(nn) # # log the mobile nodes movements if desired

# if { $opt(lm) == "on" } { log-movement } $ns_ node-config -macTrace ON # # # # # # #

Create the specified number of nodes $opt(nn) and "attach" them the channel. Each routing protocol script is expected to have defined a proc create-mobile-node that builds a mobile node and inserts it into the array global $node_($i)

if { [string compare $opt(rp) "dsr"] == 0} { for {set i 0} {$i < $opt(nn) } {incr i} { dsr-create-mobile-node $i } } elseif { [string compare $opt(rp) "dsdv"] == 0} { for {set i 0} {$i < $opt(nn) } {incr i} { dsdv-create-mobile-node $i } }

# # Source the Connection and Movement scripts # if { $opt(cp) == "" } { puts "*** NOTE: no connection pattern specified." set opt(cp) "none" } else { puts "Loading connection pattern..." source $opt(cp) } # # Tell all the nodes when the simulation ends # for {set i 0} {$i < $opt(nn) } {incr i} { $ns_ at $opt(stop).000000001 "$node_($i) reset"; } $ns_ at $opt(stop).00000001 "puts \"NS EXITING...\" ; $ns_ halt" if { $opt(sc) == "" } { puts "*** NOTE: no scenario file specified." set opt(sc) "none" } else { puts "Loading scenario file..." source $opt(sc) puts "Load complete..."

} puts $tracefd "M 0.0 nn $opt(nn) x $opt(x) y $opt(y) rp $opt(rp)" puts $tracefd "M 0.0 sc $opt(sc) cp $opt(cp) seed $opt(seed)" puts $tracefd "M 0.0 prop $opt(prop) ant $opt(ant)" puts "Starting Simulation..." $ns_ run

Note that all options listed in the beginning of the file could be initialized with command line arguments by using "getopt $argc $argv" Example 3 : To attach the error model, add following codes:
.......... proc UniformErr {} { set err [new ErrorModel] $err unit packet $err set rate_ 0.05 return $err } # $err rate_ 0.5 "invalid command ErrModel::Command does not support" # the other valid method is " set err [new ErrorModel/Uniform 0.05 pkt] " # the parameter rate ( 0 or 0.9) is a threshold that all packets all going through and 90% packets are # going to be drop proc TwoStateMarkovErr {} { set tmp0 [new ErrorModel/Uniform 0 pkt] set tmp1 [new ErrorModel/Uniform .7 pkt] # Array of states (error models) set m_states [list $tmp0 $tmp1] # Durations for each of the states, tmp, tmp1 and tmp2, respectively set m_periods [list 0.1 .075 ] # Transition state model matrix set m_transmx { {0.9 0.1 } {0.7 0.3 } } set m_trunit byte # Use time-based transition set m_sttype time

set m_nstates 2 set m_nstart [lindex $m_states 0] set em [new ErrorModel/MultiState $m_states $m_periods $m_transmx \ $m_trunit $m_sttype $m_nstates $m_nstart] return $em } $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 $chan1 \ -topoInstance $topo \ -agentTrace ON \ -routerTrace OFF\ -macTrace ON \ -movementTrace OFF \ -IncomingErrProc TwoStateMarkovErr #\ #-OutcomingErrProc TwoStateMarkovErr #The other way to configure error # $ns_ node-config --IncomingErrProc $opt(err)

A simple example for wireless simulation scenario

#This script creates a 4x4 grid topology and run 4 CBR traffic flows over four pair of#nodes in this grid. # =================================================== # Author: ZHIBIN WU 06/19/2003 # ==================================================

set cbr_size 500 set cbr_interval 0.002 set num_row 4 set time_duration 100

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(rp) DSDV ;# routing protocol # # Initialize ns # set ns_ [new Simulator] set tracefd [open simple.tr w] $ns_ trace-all $tracefd

# set up topography object set topo [new Topography]

$topo load_flatgrid 1000 1000

create-god [expr $num_row * $num_row ]

$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 [new $val(chan)] -topoInstance $topo \

-agentTrace ON -routerTrace OFF\ -macTrace ON \ -movementTrace OFF

for {set i 0} {$i < [expr $num_row*$num_row]} {incr i} {

set node_($i) [$ns_ node] } set k 0; while {$k < $num_row } { for {set i 0} {$i < $num_row } {incr i} { set m [expr $i+$k*$num_row]; $node_($m) set X_ [expr $i*240]; $node_($m) set Y_ [expr $k*240+20.0]; $node_($m) set Z_ 0.0 } incr k; }; for {set i 0} {$i < $num_row } {incr i} { set udp_($i) [new Agent/UDP] set null_($i) [new Agent/Null] } $ns_ attach-agent $node_(0) $udp_(0) $ns_ attach-agent $node_(7) $udp_(1) $ns_ attach-agent $node_(2) $udp_(2) $ns_ attach-agent $node_(7) $udp_(3) $ns_ attach-agent $node_(6) $null_(0) $ns_ attach-agent $node_(1) $null_(1) $ns_ attach-agent $node_(8) $null_(2) $ns_ attach-agent $node_(15) $null_(3) for {set i 0} {$i < $num_row } {incr i} { $ns_ connect $udp_($i) $null_($i) } for {set i 0} {$i < $num_row } {incr i} { set cbr_($i) [new Application/Traffic/CBR] $cbr_($i) set packetSize_ $cbr_size $cbr_($i) set interval_ 0.5 $cbr_($i) attach-agent $udp_($i) }

$ns_ at 11.0234 "$cbr_(0) start" $ns_ at 10.4578 "$cbr_(1) start" $ns_ at 12.7184 "$cbr_(2) start" $ns_ at 12.2456 "$cbr_(3) start" # Tell nodes when the simulation ends # for {set i 0} {$i < [expr $num_row*$num_row] } {incr i} { $ns_ at [expr $time_duration +10.0] "$node_($i) reset"; } $ns_ at [expr $time_duration +10.0] "finish" $ns_ at [expr $time_duration +10.01] "puts \"NS Exiting...\"; $ns_ halt"

proc finish {} { global ns_ tracefd $ns_ flush-trace close $tracefd }

puts "Starting Simulation..." $ns_ run

Ns-2 CMU Trace Analysis [ Introduction | Trace example | Measure throughput & delay | Back to Network Simulator 2 for Wireless ]

Ns-2 has two options to generate traces with different fomats. Basically, you could use
$ns use-newtrace

to generate the new trace and the detailed explanation could be found in Ns Manual. A very good reference about the trace is the ns-2 wiki page. See: http://nsnam.isi.edu/nsnam/index.php/NS-2_Trace_Formats By default, old trace format is used. The source code ./trace/cmu-trace.cc needs to

be read to understand it completely. For instance, the function format_ip will explain the trace of IP part.
void CMUTrace::format_ip(Packet *p, int offset) { struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); // hack the IP address to convert pkt format to hostid format // for now until port ids are removed from IP address. -Padma. int src = Address::instance().get_nodeaddr(ih->saddr()); int dst = Address::instance().get_nodeaddr(ih->daddr()); ............ } void CMUTrace::format_mac(Packet *p, int offset) { else { sprintf(pt_->buffer() + offset, " [%x %x %x %x] ", //*((u_int16_t*) &mh->dh_fc), mh->dh_duration, ETHER_ADDR(mh->dh_ra), ETHER_ADDR(mh->dh_ta), GET_ETHER_TYPE(mh->dh_body)); } ...... }

A typical trace for a CBR traffic is:

s 20.000000000 0 r 20.000000000 0 s 20.000000000 0 s 20.000275000 [0] 0 0 r 20.004947063

_0_ AGT _0_ RTR _0_ RTR _0_ MAC _1_ MAC

--- 6 cbr 512 [0 0 0 0] ------- [0:0 1:0 32 0] [0] 0 --- 6 cbr 512 [0 0 0 0] ------- [0:0 1:0 32 0] [0] 0 --- 6 cbr 532 [0 0 0 0] ------- [0:0 1:0 32 1] [0] 0 --- 6 cbr 584 [13a 1 0 800] ------- [0:0 1:0 32 1] --- 6 cbr 532 [13a 1 0 800] ------- [0:0 1:0 32 1]

[0] 1 0 s 20.004957063 _1_ MAC r 20.004972063 _1_ AGT [0] 1 0 r 20.005261125 _0_ MAC

--- 0 ACK 38 [0 0 0 0] --- 6 cbr 532 [13a 1 0 800] ------- [0:0 1:0 32 1] --- 0 ACK 38 [0 0 0 0]

An AWK script example to analyze the trace and calculate throughput For a topology involve 4 flows with distinguishing source and destination nodes, this following awk script gets throughout data and put in wu.dat file
BEGIN {counter1 = 0; counter2 = 0; counter3 = 0; counter4 = 0;} $1~/r/ && $2>50 && $2< 100 && /_12_/ && /AGT/ { counter1 += ($8- 20) size = $8 - 20 } $1~/r/ && $2>50 && $2 <100 && /_13_/ && /AGT/ { counter2 += ($8- 20) size = $8 - 20 } $1~/r/ && $2>50 && $2<100 && /_14_/ && /AGT/ { counter3 += ($8- 20) size = $8 - 20 } $1~/r/ && $2>50 && $2<100 && /_15_/ && /AGT/ { counter4 += ($8- 20) size = $8 - 20 } throughout END { print (size , counter1*8/(50), counter2*8/50, counter3*8/(50), counter4*8/50, (counter1+counter2+counter3+counter4)*8/50 ) >> "wu.dat"}

To analyze the throughout or delay in a finite time duration, we need extract sending and receiving time from the trace file
$2>100 && $2 < 150 && (/_6_/ || /_2_/) && /AGT/ $2>100 && $2 <150 && (/_0_/ || /_9_/) && /AGT/ $2>100 && $2 <150 && (/_12_/ || /_3_/) && /AGT/ $2>100 && $2 <150 && (/_10_/ || /_4_/) && /AGT/ $2>100 && $2 <150 && (/_11_/ || /_8_/) && /AGT/ { print $1, $2, $6 > "dst2.tr" } { print $1, $2, $6 > "dst9.tr" } { print $1, $2, $6 > "dst3.tr" } { print $1, $2, $6 > "dst4.tr" } { print $1, $2, $6 > "dst8.tr" }

The respective new trace files such as "dst2.tr" will keep the sending or receiving time, "s'" or "r" label and, node's MAC address. From those data, we could use a program to calculate the average throughput or mean value of end-to-end delay of the flow.

The C source file to calcualte delay can be downloaded here: To use this C code:
$ gcc delay.c -o delaycal $ ./delaycal dst2.tr wu0.dat wu1.dat

Headers & Addresses in ns-2 [ Common | 802.11 MAC | IP | DSR | Back to Network Simulator 2 for Wireless ] Notice that by default, all packet headers are included. A diagram:

Common-header: Access method:


struct hdr_cmn { enum dir_t { DOWN= -1, NONE= 0, UP= 1 }; packet_t ptype_; // packet type (see above)

int size_; int uid_; int error_; int errbitcnt_; int fecsize_; double ts_; int iface_; dir_t direction_; // source routing char src_rt_valid; //Monarch extn begins nsaddr_t prev_hop_; nsaddr_t next_hop_; int addr_type_; nsaddr_t last_hop_;

// // // //

simulated packet size unique id error flag # of corrupted bits jahn

// timestamp: for q-delay measurement // receiving interface (label) // direction: 0=none, 1=up, -1=down

// // // //

IP addr of forwarding hop next hop for this packet type of next_hop_ addr for tracing on multi-user channels

// called if pkt can't obtain media or isn't ack'd. not called if // droped by a queue FailureCallback xmit_failure_; void *xmit_failure_data_; /* * MONARCH wants to know if the MAC layer is passing this back because * it could not get the RTS through or because it did not receive * an ACK. */ int xmit_reason_; #define XMIT_REASON_RTS 0x01 #define XMIT_REASON_ACK 0x02 // filled in by GOD on first transmission, used for trace analysis int num_forwards_; // how many times this pkt was forwarded int opt_num_forwards_; // optimal #forwards // Monarch extn ends; // tx time for this packet in sec double txtime_; inline double& txtime() { return(txtime_); } static int offset_; // offset for this header inline static int& offset() { return offset_; } inline static hdr_cmn* access(const Packet* p) { return (hdr_cmn*) p->access(offset_); } ..... } hdr_cmn *ch= hdr_cmn::access(pkt); //common header

What's in common header (refer to ./common/packet.h)

ch->ptype() : protocl type. e.g. PT_DSR shows this is a signaling message for DSR protocol, not a normal DATA packet ch->size(); ch->direction() : Up or Down ch->uid() ch->iface(): Interface ch->next_hop(): next hop for this packet. IP address in format nsaddr_t*. So, it is amazing to see some codes like, ch->next_hop=MAC_BRPADCST . MAC_BROADCST is defined as #define MAC_BROADCAST ((u_int32_t) 0xffffffff) and nsaddr_t is also deined as int32_t in config.h (typedef int32_t nsaddr_t; ). Basically, ns2 use 32bit addressing support.

MAC Ethernet Address in 802.11 MAC Header: Access method:


struct hdr_mac802_11 { struct frame_control dh_fc; // 2 byte u_int16_t dh_duration; // 2 u_char dh_da[ETHER_ADDR_LEN]; // 6 u_char dh_sa[ETHER_ADDR_LEN]; // 6 u_char dh_bssid[ETHER_ADDR_LEN]; // 6 u_int16_t dh_scontrol; // 2 u_char dh_body[0]; // XXX Non-ANSI // 1 //not allocate, the address of .... }; ..... u_int32_t src,dst; struct hdr_mac802_11 *dh = HDR_MAC802_11(p); //method to get a 32bit general descriptor of address dst = ETHER_ADDR(dh->dh_ra); src = ETHER_ADDR(dh->dh_ta); //method to set .... int src, dst; STORE4BYTE(&dst, (dh->dh_ra)); STORE4BYTE(&src, (dh->dh_ta));

Ethernet Address is specified in mac.h as (#define ETHER_ADDR_LEN 6 ). Thus, dh_ra and dh_ta are both six-unsinged-character array. Also, there is another defintion

for this operation: #define ETHER_ADDR(x) (GET4BYTE(x)), so only the last 4 bytes are reassembled for a 32-bit address. How MAC address is set? The addr() function is defined in the Class MAC, and the index_ is corresponding internal member ( type is integer).
static int MacIndex = 0; Mac::Mac() : BiConnector(), abstract_(0), netif_(0), tap_(0), ll_(0), channel_(0), callback_(0), hRes_(this), hSend_(this), state_(MAC_IDLE), pktRx_(0), pktTx_(0) { index_ = MacIndex++; bind_bw("bandwidth_", &bandwidth_); bind_time("delay_", &delay_); bind_bool("abstract_", &abstract_); } class Mac : public BiConnector { public: .... inline int addr() { return index_; } protected: .... int index_; // MAC address .... } //alos, the mac-802.11 use index as its mac address to form MAC frames: (see in mac-802_11.cc) .... STORE4BYTE(&index_, (rf->rf_ta));

Space Sharing in MAC-802.11 header As in packet.h


#define HDR_MAC802_11(p) ((hdr_mac802_11 *)hdr_mac::access(p))

There is no define of access function of struct hdr_mac802_11. The problem is that, we acccess the header use the struct mac_hdr, and then convert it to a 802.11 header. Thus, the frame space and frame format should have some realtion: See. size of mac header is 36 bytes, but size of mac-802.11 header in ns-2 is only 24 bytes.

IP Addr in IP header Access Method: (refer to ./common/ip.h )


struct hdr_ip { /* common to IPv{4,6} */ ns_addr_t src_; ns_addr_t dst_; int ttl_; // // /* Monarch extn */ u_int16_t sport_; u_int16_t dport_; /* IPv6 */ int int fid_; prio_; /* flow id */

static int offset_; inline static int& offset() { return offset_; } inline static hdr_ip* access(const Packet* p) { return (hdr_ip*) p->access(offset_); } /* per-field member acces functions */ ns_addr_t& src() { return (src_); } nsaddr_t& saddr() { return (src_.addr_); } int32_t& sport() { return src_.port_;} ns_addr_t& dst() { return (dst_); } nsaddr_t& daddr() { return (dst_.addr_); } int32_t& dport() { return dst_.port_;} int& ttl() { return (ttl_); } /* ipv6 fields */ int& flowid() { return (fid_); } int& prio() { return (prio_); } }; ...... struct ns_addr_t { int32_t addr_; int32_t port_; #ifdef __cplusplus p.dest = ID((Address::instance().get_nodeaddr(iph>daddr())),::IP); p.src = ID(( ns_addr_t& operator= (const ns_addr_t& n) { addr_ = n.addr_; port_ = n.port_; return (*this); } int operator== (const ns_addr_t& n) { return ((addr_ == n.addr_) && (port_ == n.port_)); } p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP); p.src = ID((

#endif // __cplusplus }; hdr_ip *iph = hdr_ip::access(packet);

//method to set address iph->saddr() = Address::instance().create_ipaddr(p.src.addr, RT_PORT); p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP); p.src = ID(( iph->sport() = RT_PORT; iph->daddr() = Address::instance().create_ipaddr(p.dest.addr, RT_PORT); iph->dport() = RT_PORT; iph->ttl() = 255; // method to read address ?? iph->saddr() iph->daddr() p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP); p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);

As seen, ns_addr_t is different from nsaddr_t, it has ip address and port infomation. Just 32 bit is suitable for ip address. Very Important! All things above IP ( Routing, TCP are) are implemented as Agent. Any agent's message must include an IP header. The class Agent has functions like addr() and daddr() to get the address of IP header.
class Agent : public Connector { public: .... inline nsaddr_t& addr() { return here_.addr_; } inline nsaddr_t& port() { return here_.port_; } inline nsaddr_t& daddr() { return dst_.addr_; } inline nsaddr_t& dport() { return dst_.port_; } protected: ... ns_addr_t here_; // address of this agent ns_addr_t dst_; // destination address for pkt flow ... } int Agent::delay_bind_dispatch(const char *varName, const char *localName, TclObject *tracer) { if (delay_bind(varName, localName, "agent_addr_", (int*)&(here_.addr_), tracer)) return TCL_OK; if (delay_bind(varName, localName, "agent_port_", (int*)&(here_.port_), tracer)) return TCL_OK; if (delay_bind(varName, localName, "dst_addr_", (int*)&(dst_.addr_), tracer)) return TCL_OK; if (delay_bind(varName, localName, "dst_port_", (int*)&(dst_.port_), tracer)) return TCL_OK;

......

Class Hierarchy : TclObject ---> NSObject ----> Agent

DSR's SR (Source Route) Header the SR has a path informaton from source to a destination, an SR should have following basic information for a baseline version of DSR protocol:

a path of IP or other addressses a type to show this is route-request, route-reply or route-error an ID to distinguish duplicate requests.
/* same as hdr_cmn in packet.h */

struct sr_addr { int addr_type; nsaddr_t addr;

/* * Metrics that I want to collect at each node */ double Pt_; }; struct route_request { int req_valid_; int req_id_; int req_ttl_; }; /* request header is valid? */ /* unique request identifier */ /* max propagation */

struct route_reply { int rep_valid_; /* reply header is valid? */ int rep_rtlen_; /* # hops in route reply */ struct sr_addr rep_addrs_[MAX_SR_LEN]; }; struct route_error { int err_valid_; /* error header is valid? */ int err_count_; /* number of route errors */ struct link_down err_links_[MAX_ROUTE_ERRORS]; }; ...... class hdr_sr { private: int valid_; int salvaged_; int num_addrs_;

/* is this header actually in the packet? and initialized? */ /* packet has been salvaged? */

int cur_addr_; struct sr_addr addrs_[MAX_SR_LEN]; struct route_request struct route_reply struct route_error ... inline struct sr_addr* addrs() { return addrs_; } ... } //Constructor of Path, convert a SR header into a PATH object Path::Path(struct hdr_sr *srh) { /* make a path from the bits of an NS source route header */ path = new ID[MAX_SR_LEN]; if (! srh->valid()) { len = 0; cur_index = 0; return; } len = srh->num_addrs(); cur_index = srh->cur_addr(); assert(len <= MAX_SR_LEN); for (int i = 0 ; i < len ; i++) path[i] = ID(srh->addrs()[i]); are copied } //note : both type and addr sr_request_; sr_reply_; sr_error_;

hdr_sr *srh = hdr_sr::access(packet); SRPacket p(packet, srh); p.dest = ID((Address::instance().get_nodeaddr(iph->daddr())),::IP); p.src = ID((Address::instance().get_nodeaddr(iph->saddr())),::IP);

To get and set SR header, first we need to turn things into a packet of type SRPacket, in this class, route[n] is use to access ID[n], for each ID[n], use inline nsaddr_t getNSAddr_t() to get this addr; Normally, all SR-related operation are use "ID" not direct 32bit integer to refer. How the address get set at the very beginning of the DSR Agent, use those :
SRNodeNew instproc init args { ...... $dsr_agent_ addr $address_ ...... }

OTcl ( MIT Object TCL )

[ Back to Network Simulator 2 for Wireless Home Page ]

1. The constructor function of a class (object) is:


Init

The init instproc is used to initialize a freshly allocated object that is a direct or indirect instance of the class Object. It is normally called by the system (perhaps from more specialized init instprocs) as part of object creation, but may be called by the user. interprets its arguments as pairs of option keys and option values. Each option key should be the name of a valid method for the object, preceded by a dash. The method should take one argument. For each option key and option value pair, init calls the method on the object, with the option value as its argument. It returns the empty string.
init

To customize object creation, write an init instproc for a class, not an alloc proc. If the option key and option value creation syntax is still desired, then call the Object init instproc by using next. This is discussed in the create instproc in OTcl Classes.
% Class Bagel Bagel % foreach i {1 2 3 4} { Bagel instproc $i {v} {puts $v} } % Bagel abagel abagel % abagel init -1 one -2 two -3 three -4 four! one two three four! init

is conceptually equivalent to the following.

Object instproc init {args} { if {[llength $args]%2 != 0} then { error {uneven number of arguments}

} while {$args != {}} { set key [lindex $args 0] if {[string match {-*} $key]} then { set key [string range $key 1 end] } set val [lindex $args 1] if {[catch {$self $key $val} msg]!=0} then { set opt [list $self $key $val] error "$msg during $opt" } set args [lrange $args 2 end] } return {} }

Interfaces of Wireless MAC in ns-2


[ Back to Network Simulator 2 for Wireless Home Page ] General Architecture of a mobile node in ns-2:

the relationship of MAC could be found in ns-mobilenode.tcl. The source code:


........ # # The following setups up link layer, mac layer, network interface # and physical layer structures for the mobile node. # Node/MobileNode instproc add-interface { channel pmodel lltype mactype \ qtype qlen iftype anttype topo inerrproc outerrproc fecproc} { $self instvar arptable_ nifs_ netif_ mac_ ifq_ ll_ imep_ inerr_ outerr_ fec_ ....... # # Link Layer # $ll arptable $arptable_ $ll mac $mac $ll down-target $ifq

if {$imepflag == "ON" } { $imep recvtarget [$self entry] $imep sendtarget $ll $ll up-target $imep } else { $ll up-target [$self entry] } # # Interface Queue # $ifq target $mac $ifq set limit_ $qlen if {$imepflag != ""} { set drpT [$self mobility-trace Drop "IFQ"] } else { set drpT [cmu-trace Drop "IFQ" $self] } $ifq drop-target $drpT if { $namfp != "" } { $drpT namattach $namfp } # Mac Layer # $mac netif $netif $mac up-target $ll if {$outerr == "" && $fec == ""} { $mac down-target $netif } elseif {$outerr != "" && $fec == ""} { $mac down-target $outerr $outerr target $netif } elseif {$outerr == "" && $fec != ""} { $mac down-target $fec $fec down-target $netif } else { $mac down-target $fec $fec down-target $outerr $err target $netif }

Actually, from top to down path, the structure is ll ---> ifq ----> mac ---> netif . for packets going up, it is netif ---> mac --->ll. Thus, ifq is only used for down path of . however, a scheduler is also only useful to handle outgoing packets. Thus, if we want to implement a scheduler, we have to use something to replace this "ifq" and remake the interface in tcl script.

Multi-rate MAC in ns-2 [ Back to Network Simulator 2 for Wireless Home Page ]

Introduction

First, an introduction on "how ns-2 handle the 802.11 rate": There is a file ns-mac.tcl in ./tcl/lib directory, in this file the MAC/802-11 set datarate_ as 1Mb, and basicRate_ as 1Mb. change these two values could change rate. We have to consider following questions: Atomic operations: 1. The sender determine the rate (how??). calculate NAV, assuming ACK use the same rate( or basic rate??). Send DATA 2. How to let the receiver know the rate? We have to use PLCP header. The SIGNAL field in PLCP header is used for this purpose. 3. Why the receiver needs to know the rate? because it wants to correct receive it and might send ACK with same rate. 4. Using Short PLCP? Two major changes, PLCP preamble is 72 instead of 144 bits (still sent with 1Mbps) The PLCP header is sent with 2Mbps. Control & Feedback for auto-rate 1. Receiver-based Autorate (RBAR). RTS/CTS is necessary, RTS send with lowest rate (1Mbps), the receiver put something in the CTS to tell the sender use which rate (CTS is still sent with lowest rate) 2. ARF (auto-rate fallback), for every 2nd ACK miss( transmission failure) following good transmission, fallback to lower rate and set a timer. Whenever the consecutive 10 good transmission or timer expired, upgrade to higher rate. Then, if miss ACK, fallback to lower rate. 3. Fixed Rate. Assume every node is not moving, the benefits of adaptive autorate is very small. So, for every node pair, we set a fixed rate to follow, either 1,2,5.5,11 Rate .vs. Range 1. Each rate corresponding to a different transmission range. This is to be reflected. 2. Carrier-Sense threshold does not change for different rate. So this is a fixed vaue.

Implementation

1. 2. 3. 4.

set rate short preamble receive threshold AutoRate Scheme 1: ARF

baisc multirate codes (only Implement Feature 1 & 2) (download zip file) And also, there is 8db SNR difference from the 1Mbps and 11Mbps rate. It means that the 1Mbps frames will be decoded in a distance more than 250 meters. it is a baisc multirate setting with rate info attached as Pxtinfo txinfo there is no auto rate selection. Advanced multirate code: Implement Feature 1,2 3 Auto multi-rate codes: (Implement Feature 1,2 3 and a feasible Autorate Scheme) in addition to basic multirate, auto rate and channel access estimation. The design is integrated with a new cross-layer MAC design entity which a new structure of Node_Info is involved. (Link to Design of Cross-layer MAC). For both versions, 6 files need to modified: in ~/mac directoty:

mac-802_11.h mac-802-11.cc wireless-phy.cc. wireless-phy.h

in ~/common directory

mobilenode.cc .allow node to change its rate. It should has its will to stay in a lower rate as wish. packet-stamp.h This is a HACK! The receiver cannot know the rate before decoding the PLCP header, but here we put rate as same as SNR.

Note that whenever switch from versions of multi-rate to non-mulitrate ns codes, make clean & make due to problems with packet-stamp.h otherwise, "segmentation

fault" occurs. Based on the feature, Modifications are described in detail Set Rate in TCL for each node: rate is given in tcl code, and no matter what happens, the node has to use this rate as a fixed value. No matter a received DATA is another rate or not, datarate_ does not change. Only if an auto-rate scheme is in effect............. in mac-802.11.cc getTxrate helps to get the rate info and calculate the timeouts, setTxrate is only used for autorate.............. in mobilenode.cc:
#include "wireless-phy.h" #include "mac-802_11.h" Mac802_11* macptr; ...... //Zhibin - To have an access to change rate! else if (strcmp(argv[1], "change_rate") == 0) { macptr = (Mac802_11*) ifhead_.lh_first->uptarget(); if (macptr) { // Keep attention: supposes only 1 // interface present! macptr->setRate(atoi(argv[2])); fprintf(stderr, "Rate changed to: %d\n\n",\ atoi(argv[2])); return TCL_OK; } else { fprintf(stderr, "Error.. Mac not found..\n"); return(TCL_ERROR); }; return TCL_OK; } ............

Actually, this change might not useful if u don't set it dynamically from tcl file.

in mac-802_11.h
//zhibin-multirate inline double setRate(double newvalue){ return dataRate_ =

newvalue;}; //-----------------

Short Preamble header & different rate for ACK/RTS/CTS/DATA

in mac-802_11.h

// Zhibin- To introduce the short preamble, variables will be bind from ns-default.tcl u_int32_t ShortPreambleLength; double ShortPLCPDataRate; double ShortPLCPHeaderThreshold; // we keep this parameter as part of MIB inline double getEIFS(double r) { // see (802.11-1999, 9.2.10) return(SIFSTime + getDIFS() + (8 * getACKlen(r))/PLCPDataRate); } inline double getShortPLCPHeaderThreshold() { return ShortPLCPHeaderThreshold ; } inline u_int32_t getShortPreambleLength() { return(ShortPreambleLength); } inline double getShortPLCPDataRate() { return(ShortPLCPDataRate); } inline u_int32_t getPLCPHeaderLength() { return(PLCPHeaderLength); } inline u_int32_t getPLCPhdrLen(double r) { return ((r>ShortPLCPHeaderThreshold ) ?((ShortPreambleLength >> 3)+(PLCPHeaderLength >> 3)) :((PreambleLength >> 3)+(PLCPHeaderLength >> 3))); } inline u_int32_t getHdrLen11(double r) { return(getPLCPhdrLen(r) + sizeof(struct hdr_mac802_11) + ETHER_FCS_LEN); } inline u_int32_t getRTSlen(double r) { return(getPLCPhdrLen(r) + sizeof(struct rts_frame)); } inline u_int32_t getCTSlen(double r) { return(getPLCPhdrLen(r) + sizeof(struct cts_frame)); } inline u_int32_t getACKlen(double r) { return(getPLCPhdrLen(r) + sizeof(struct ack_frame));

in ns-default.tcl
Mac/802_11 set ShortPreambleLength_ 72 ; # DataRate of Short PLCP Header. PLCP preample is always sent at DSSS_PLCPDataRate Mac/802_11 set ShortPLCPDataRate_ 2.0e6 ; #-------zhibinwu ---------------Mac/802_11 set ShortPLCPHeaderThreshold_ 1.0e6;

in mac-802_11.cc

parent->bind("ShortPreambleLength_", &ShortPreambleLength); parent->bind("ShortPLCPHeaderThreshold_", &ShortPLCPHeaderThreshold); parent->bind_bw("ShortPLCPDataRate_", &ShortPLCPDataRate);

Has to assume all ACK and RTS/CTS are in basic rate. Thus, probablay 1mbps, Change : getCTSlen() ----> getRTSlen(basicRate_); getRTSlen() ----> getCTSlen(basicRate_); getACKlen() ----> getACKlen(basicRate_); getEIFS ----> getEIFS(basicRate_); getHdrlen11() ----->getHdrlen11(p->txinfo_.getTxRate())

double Mac802_11::txtime(double psz, double drt) { // change wrt Mike's code // double dsz = psz - PLCP_HDR_LEN; // int plcp_hdr = PLCP_HDR_LEN << 3; // double dsz = psz - phymib_.getPLCPhdrLen(); // int plcp_hdr = phymib_.getPLCPhdrLen() << 3; double dsz = psz - phymib_.getPLCPhdrLen(drt); int plcp_hdr = phymib_.getPLCPhdrLen(drt) << 3; int datalen = (int)dsz << 3; // change wrt Mike's code // double t = (((double)plcp_hdr)/phymib_->PLCPDataRate) +

(((double)datalen)/drt); // // double t = (((double)plcp_hdr)/phymib_.getPLCPDataRate()) + (((double)datalen)/drt); double t = 0; if ( drt >phymib_.getShortPLCPHeaderThreshold() ) { /* Zhibin - In this case the are sent at 1 Mbps while * ShortPLCPHeader at 2Mbps and the rest at dataRate_ */ t = (((double)phymib_.getShortPreambleLength())/(phymib_.getPLCPDataRate())) + (((double)phymib_.getPLCPHeaderLength())/(phymib_.getShortPLCPDataRate())) + (((double)datalen)/drt); } else { t = (((double)plcp_hdr)/phymib_.getPLCPDataRate()) + (((double)datalen)/drt); }; return(t); }

Attach and Read Rate information with DATA frame

in packet-stamp.h
inline double getTxRate() {return txRate;} inline void setTxRate(double r) {txRate = r;}

in 802.11.cc

void Mac802_11::sendDATA(Packet *p) { .... if((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) { p->txinfo_.setTxRate(dataRate_); if((u_int32_t)ETHER_ADDR(dh->dh_ra) != MAC_BROADCAST) { ch->size() += phymib_.getHdrLen11(dataRate_); }else{ // GgX - Broadcast packets are always sent at basicRate_ ch->size() += phymib_.getHdrLen11(basicRate_); };

..... }

SNR of different Rates ( Drop packets of higher rate if SNR is low)

In wireless-phy.cc IN sendup fucntion, first get the rate information of the packet. ( The default rate is 1M,if unset in MAC layer)

double rate = p->txinfo_.getTxRate(); int rate_index; //zhibinwu, find the rate index in rate table for ( int rate_index=0; rate_index< NUM_RATE_80211b; i++) { if ( rate == RXRate_[rate_index]) break; } if (rate_index==4) printf ("ERROR! RATE NOT FOUND!\N"); if (Pr < RXThresh_[rate_index]) { /* * We can detect, but not successfully receive * this packet. */ hdr_cmn *hdr = HDR_CMN(p); hdr->error() = 1; #if DEBUG > 3 printf("SM %f.9 _%d_ drop pkt from %d low POWER %e/%e\n", Scheduler::instance().clock(), node()->index(), p->txinfo_.getNode()->index(), Pr,RXThresh_[rate_index]); #endif }

And

RXRate_[0]= 1000000; RXrate_[1]= 2000000; RxRate_[2]= 5500000; RxRate_[3]= 11000000; RXThresh_[0] = 0.1; RXThresh_[1] = 0.2; RXThresh_[2] = 0.3; RXThresh_[3] = 0.4;

// // // //

receive receive receive receive

power power power power

threshold threshold threshold threshold

(W) (W) (W) (W)

for for for for

each each each each

rate rate rate rate

in wireless-phy.h

#define NUM_RATE_80211b 4; double RXRate_[NUM_RATE_80211b]; double RXThresh_[NUM_RATE_80211b]; for each rate // receive power threshold (W)

ARF ARF relies on MAC retransmission (set retry limit as 7 will be good)

1. 2. 3. 4. 5.

Define rate array in MAC; set a varible in MAC to flag miss ACK event. Set a conunter to counter consecutive transmissions In retransmit data, downgrade-rate, reset ch->size() and ch->txtime(); In recvACK, prepare upgrade-rate

In mac-802_11.cc
//zhibinwu optRate_[0] optRate_[1] optRate_[2] optRate_[3] = = = = 1000000; 2000000; 5500000; 11000000;

missACK = false; ACKcounter = 0; void Mac802_11::recvACK(Packet *p) { //zhibinwu ----------ARF----

missACK_ = false; ACKcounter_++; if ( ACKcounter_ >10 ) { //upgrade datarate int m; for (m=0;m<4;m++) { if ( optRate_[m] == dataRate_ && m!=3) { dataRate_ = optRate_[m+1]; break; } } //printf(" the new datarate is %f\n", dataRate_); ACKcounter_ = 0; } //------------------------------} void Mac802_11::RetransmitDATA() { //zhibinwu's code to do ARF (AutoRate Fallback) ACKcounter_ = 0; // no successive ACKs if (missACK_ == false)) missACK_ = true; //first missed ACK does not trigger fallback else if ( dataRate_ == basicRate_) { //already fallback to lowest } else { //previous rate is datarate_ as same as getTxRate ch->size() -= phymib_.getHdrLen11(pktTx_>txinfo_.getTxRate()); // assert pktTx and change size int m; for (m=0;m<4;m++) { if ( optRate_[m] == dataRate_ && m!=0) { dataRate_ = optRate_[m-1]; } } //calculate new size ch->size() += phymib_.getHdrLen11(dataRate_); ch->txtime() = txtime(ch->size(), dataRate_); pktTx_->txinfo_.setTxRate(dataRate_);

} // =============ARF---end========= }

Appendix: PHY Model In ns-2, the model is TwoRayground. It is for long range. Basically it means the attenuation factor 4 is used instead of 2. Pr = PtGtGrht2hr2 / (Ld4) The original setting is:
Tx Power CSThreshold RxThreshold 0.2818W (24.5dbm) 1.559e-11 W (-102.5db) 3.652e-10 W (-91.1db)

((3.652/1.559)*10)^0.25 =2.2 2.2*250 = 550 Modified model for 802.11b


TxPower CST RxThreshold[0] RxThreshold[1] RxThreshold[2] RxThreshold[3] 0.031622777 W (15dbm) -100dbm (1e-13 W) -94dbm 3.9811e-13 W -91dbm 7.9433e-13W -87dbm 1.9953e-12 W -82dbm 6.3096e-12 W

Você também pode gostar