399 lines
10 KiB
Tcl
Executable file
399 lines
10 KiB
Tcl
Executable file
#
|
|
# Copyright 2005-2013 the Boeing Company.
|
|
# See the LICENSE file included in this distribution.
|
|
#
|
|
|
|
#
|
|
# Copyright 2004-2008 University of Zagreb, Croatia.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
# SUCH DAMAGE.
|
|
#
|
|
|
|
#
|
|
#****h* imunes/ns2imunes.tcl
|
|
# NAME
|
|
# ns2imunes.tcl -- file used for converting from ns2 scripts to IMUNES conf
|
|
# file
|
|
# FUNCTION
|
|
# This module implements functionality for converting ns2 scripts into
|
|
# IMUNES conf file. Now, only basic ns2 functionalities are implemented, those
|
|
# that can't be written in IMUNES config file or those that are not implemented
|
|
# yet are ignored.
|
|
#****
|
|
|
|
#****f* ns2imunes.tcl/ns2im
|
|
# NAME
|
|
# ns2im -- converts ns2 script into IMUNES and draws topology
|
|
# SYNOPSIS
|
|
# ns2im $ns2script
|
|
# FUNCTION
|
|
# Implements basic logic for converting between formats.
|
|
# INPUTS
|
|
# * srcfile -- ns2 scripy
|
|
#****
|
|
|
|
proc ns2im { srcfile } {
|
|
global node_list
|
|
global link_list
|
|
global canvas_list
|
|
global curcanvas
|
|
global cfg
|
|
set cfg {}
|
|
set node_list {}
|
|
set link_list {}
|
|
set canvas_list {}
|
|
source $srcfile
|
|
foreach node $node_list {
|
|
setNodeCanvas $node $curcanvas
|
|
}
|
|
changeNodeType
|
|
setDefaultRoutes
|
|
arrangeNodes
|
|
dumpCfg string cfg
|
|
loadCfg $cfg
|
|
redrawAll
|
|
if { [file exists out.nam] == 1 } {
|
|
file delete out.nam
|
|
}
|
|
}
|
|
|
|
#****f* ns2imunes.tcl/new
|
|
# NAME
|
|
# new -- basic/main ns2 function, invoked in ns2 script
|
|
# SYNOPSIS
|
|
# set ns [new Simulator]
|
|
# FUNCTION
|
|
# Points to our main function: root-func.
|
|
# INPUTS
|
|
# * object -- can be Simulator, Agent, Application.
|
|
#****
|
|
|
|
proc new {object} {
|
|
set arg [split $object "/"]
|
|
set typepc "TCP UDP RTP RTCP"
|
|
set typehost "TCPSink Null"
|
|
if {$object == "Simulator"} {
|
|
return root-func
|
|
} elseif {[lindex $arg 0] == "Agent"} {
|
|
return nullfunc
|
|
} elseif {[lindex $arg 0] == "Application"} {
|
|
return nullfunc
|
|
} else {
|
|
return nullfunc
|
|
}
|
|
}
|
|
|
|
#****f* ns2imunes.tcl/nullfunc
|
|
# NAME
|
|
# nullfunc -- does nothing; needed for avoiding errors.
|
|
# SYNOPSIS
|
|
# nullfunc args
|
|
# INPUTS
|
|
# * can be any number of inputs
|
|
#****
|
|
proc nullfunc {args} {
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/root-func
|
|
# NAME
|
|
# root-func -- calls other functions
|
|
# SYNOPSIS
|
|
# root-func ns_command $args
|
|
# FUNCTION
|
|
# For input node this procedure enables or disables custom configuration.
|
|
# INPUTS
|
|
# * ns_command -- first arg is always name of the function
|
|
# * args -- argument for function; there can be any number of arguments
|
|
# RESULT
|
|
# Returns result of function $ns_command
|
|
#****
|
|
proc root-func {ns_command args} {
|
|
catch {
|
|
if {$args == ""} {
|
|
set x [$ns_command]
|
|
return $x
|
|
} else {
|
|
set y [$ns_command $args]
|
|
return $y
|
|
}
|
|
} value
|
|
return $value
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/node
|
|
# NAME
|
|
# node -- creates new node, ns_command invoked from root-func
|
|
# SYNOPSIS
|
|
# set node [node]
|
|
# RESULT
|
|
# * node_id -- node id of a new node of type router
|
|
#****
|
|
proc node {} {
|
|
set default "router"
|
|
return [newNode $default]
|
|
}
|
|
|
|
|
|
#not implemented yet in IMUNES
|
|
proc simplex-link { linkdata } {
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/duplex-link
|
|
# NAME
|
|
# duplex-link -- creates new link, ns_command invoked from root-func
|
|
# SYNOPSIS
|
|
# duplex-link $linkdata_list
|
|
# INPUTS
|
|
# * linkdata -- list that describes link
|
|
# RESULT
|
|
# * new_link_id -- new link id.
|
|
#****
|
|
proc duplex-link { linkdata } {
|
|
set node1 [lindex $linkdata 0]
|
|
set node2 [lindex $linkdata 1]
|
|
set bw [lindex $linkdata 2]
|
|
set dly [lindex $linkdata 3]
|
|
set type [lindex $linkdata 4]
|
|
set link [newLink $node1 $node2]
|
|
|
|
set bandwidth [getBandwidth $bw]
|
|
setLinkBandwidth $link $bandwidth
|
|
|
|
set delay [getDelay $dly]
|
|
setLinkDelay $link $delay
|
|
|
|
set queueingDiscipline [getQueingDiscipline $type]
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/changeNodeType
|
|
# NAME
|
|
# changeNodeType -- passes through list node_list and changes type of node.
|
|
# SYNOPSIS
|
|
# changeNodeType
|
|
# FUNCTION
|
|
# Passes through list node_list and calls procedures for changing type of
|
|
# node if node has more than one neighbour.
|
|
#****
|
|
proc changeNodeType {} {
|
|
global node_list
|
|
foreach node $node_list {
|
|
set ifc [ifcList $node]
|
|
set ifcnum [llength $ifc]
|
|
if { $ifcnum == 1 } {
|
|
setNodeModel $node "PC"
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/setDefaultRoutes
|
|
# NAME
|
|
# setDefaultRoutes -- sets default routes for non router nodes
|
|
# SYNOPSIS
|
|
# setDefaultRoutes
|
|
#****
|
|
proc setDefaultRoutes {} {
|
|
global node_list
|
|
foreach node $node_list {
|
|
set type [nodeType $node]
|
|
if { $type == "pc" || $type == "host" } {
|
|
set interfaces [ifcList $node]
|
|
foreach ifc $interfaces {
|
|
autoIPv4defaultroute $node $ifc
|
|
autoIPv6defaultroute $node $ifc
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/getBandwidth
|
|
# NAME
|
|
# getBandwith -- returns bandwidth value in bits
|
|
# SYNOPSIS
|
|
# getBandwith $bandwith
|
|
# FUNCTION
|
|
# Detects input unit, and returns bandwidth value in bits.
|
|
# INPUTS
|
|
# * bw -- bandwidth
|
|
#****
|
|
proc getBandwidth { bw } {
|
|
regexp {[0-9]+} $bw value
|
|
regexp {[A-Za-z]+} $bw unit
|
|
switch $unit {
|
|
"Kb" "return [expr $value*1000]"
|
|
"Mb" "return [expr $value*1000000]"
|
|
"Gb" "return [expr $value*1000000000]"
|
|
}
|
|
}
|
|
|
|
#****f* ns2imunes.tcl/getDelay
|
|
# NAME
|
|
# getDelay -- returns delay value in microseconds
|
|
# SYNOPSIS
|
|
# getDelay $dly
|
|
# FUNCTION
|
|
# Detects input unit, and returns delay value in microseconds.
|
|
# INPUTS
|
|
# * dly -- delay
|
|
#****
|
|
proc getDelay { dly } {
|
|
regexp {[0-9]+} $dly value
|
|
regexp {[a-z]+} $dly unit
|
|
switch $unit {
|
|
"ms" " return [expr $value*1000] "
|
|
"us" " return $value "
|
|
}
|
|
}
|
|
|
|
#****f* ns2imunes.tcl/getQueingDiscipline
|
|
# NAME
|
|
# getQueingDiscipline -- returns queing discipline
|
|
# SYNOPSIS
|
|
# getQueingDiscipline $type
|
|
# INPUTS
|
|
# * type -- type of queing discipline written in ns2 format
|
|
#****
|
|
proc getQueingDiscipline { type } {
|
|
if {[string match "DropTail" $type]} {
|
|
return "droptail"
|
|
} elseif {[string match "CBQ" $type] ||\
|
|
[string match "WFQ" $type]} {
|
|
return "fair-queue"
|
|
} elseif {[string match "DRR" $type]} {
|
|
return "drr-queue"
|
|
}
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/arrangeNodes
|
|
# NAME
|
|
# arrangeNodes -- calculates coordinates for nodes
|
|
# SYNOPSIS
|
|
# arrangeNodes
|
|
# FUNCTION
|
|
# Calculates and writes coordinates for every node in global variable
|
|
# node_list.
|
|
#****
|
|
proc arrangeNodes {} {
|
|
global node_list
|
|
global activetool
|
|
#with next foreach loop we divide nodes on layer3/router
|
|
#nodes and edge (pc, host) nodes
|
|
set routers {}
|
|
set edgeNodes {}
|
|
foreach node $node_list {
|
|
set type [nodeType $node]
|
|
if { $type == "router" } {
|
|
lappend routers $node
|
|
} else {
|
|
lappend edgeNodes $node
|
|
}
|
|
}
|
|
set center {450 310}
|
|
set i 0
|
|
set rnum [llength $routers]
|
|
set pi [expr 2*asin(1.0)]
|
|
#next foreach loop: we arrange nodes that we have denoted as
|
|
#layer3/router nodes; we place them in a elipse circle and their
|
|
#regular peers (pc or host) are placed above them
|
|
foreach rnode $routers {
|
|
set fi [expr $i*(2*$pi)/$rnum]
|
|
set r [expr 200*(1.0-0.4*abs(sin($fi)))]
|
|
set ximage [expr [lindex $center 0] - $r*cos($fi)]
|
|
set yimage [expr [lindex $center 1] - $r*sin($fi)]
|
|
|
|
setNodeCoords $rnode "$ximage $yimage"
|
|
setNodeLabelCoords $rnode "$ximage [expr $yimage + 24]"
|
|
set regularPeers [getRegularPeers $rnode]
|
|
set regpeernum [llength $regularPeers]
|
|
set j 0
|
|
foreach peer $regularPeers {
|
|
if { [hasCoords $peer] >= 0 } {
|
|
continue
|
|
}
|
|
set fi1 [expr ($j-$regpeernum/2)*(2*$pi/3)/$regpeernum]
|
|
set ximage1 [expr $ximage - 200*cos($fi+$fi1)]
|
|
set yimage1 [expr $yimage - 200*sin($fi+$fi1)]
|
|
setNodeCoords $peer "$ximage1 $yimage1"
|
|
set dy 32
|
|
setNodeLabelCoords $peer "$ximage1 [expr $yimage1 + $dy]"
|
|
incr j
|
|
}
|
|
incr i
|
|
}
|
|
if { $routers == "" } {
|
|
set i 0
|
|
foreach node $edgeNodes {
|
|
set fi [expr $i*(2*$pi)/[llength $edgeNodes]]
|
|
set r [expr 200*(1.0-0.5*abs(sin($fi)))]
|
|
set ximage [expr [lindex $center 0] - $r*cos($fi)]
|
|
set yimage [expr [lindex $center 1] - $r*sin($fi)]
|
|
setNodeCoords $node "$ximage $yimage"
|
|
set dy 32
|
|
setNodeLabelCoords $node "$ximage [expr $yimage + $dy]"
|
|
incr i
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/getRegularPeers
|
|
# NAME
|
|
# getRegularPeers -- returns list of pc's and hosts connected with router $node
|
|
# SYNOPSIS
|
|
# getRegularPeers $node_id
|
|
# INPUTS
|
|
# * node -- node_id of router to which we are finding peers
|
|
#****
|
|
proc getRegularPeers { node } {
|
|
set interfaces [ifcList $node]
|
|
set regularpeers ""
|
|
foreach ifc $interfaces {
|
|
set peer [peerByIfc $node $ifc]
|
|
if { [nodeType $peer] == "pc" || [nodeType $peer] == "host"} {
|
|
lappend regularpeers $peer
|
|
}
|
|
}
|
|
return $regularpeers
|
|
}
|
|
|
|
|
|
#****f* ns2imunes.tcl/hasCoords
|
|
# NAME
|
|
# hasCoords -- detects existence of coords
|
|
# SYNOPSIS
|
|
# getRegularPeers $node_id
|
|
# INPUTS
|
|
# * node -- node_id of node.
|
|
# RESULT
|
|
# * >=0 -- coords are assigned to $node
|
|
# * ==1 -- coords are not assigned to $node
|
|
#****
|
|
proc hasCoords {node} {
|
|
global $node
|
|
return [lsearch [set $node] "iconcoords *"]
|
|
}
|