core-extra/gui/ns2imunes.tcl

394 lines
10 KiB
Tcl

#
# 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 *"]
}