378 lines
9.9 KiB
Tcl
378 lines
9.9 KiB
Tcl
|
#
|
||
|
# Copyright 2007-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.
|
||
|
#
|
||
|
|
||
|
# Boeing: refactor menus
|
||
|
set TOOLSMENUPATH .menubar.tools
|
||
|
set TOPOMENUPATH ${TOOLSMENUPATH}.t_g
|
||
|
menu $TOPOMENUPATH -tearoff 1
|
||
|
${TOOLSMENUPATH} add cascade -label "Topology generator" -underline 0 -menu ${TOPOMENUPATH}
|
||
|
# also throughout:
|
||
|
# s/.menubar.t_g/${TOPOMENUPATH}/g
|
||
|
# s///g
|
||
|
# end Boeing
|
||
|
|
||
|
set m ${TOPOMENUPATH}.random
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Random" -menu $m -underline 0
|
||
|
foreach i [list 1 5 10 15 20 30 40 50 75 100] {
|
||
|
set n $m.$i
|
||
|
menu $n -tearoff 0
|
||
|
$m add command -label "R($i)" -command "R \[newNodes $i\]"
|
||
|
}
|
||
|
|
||
|
set m ${TOPOMENUPATH}.grid
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Grid" -menu $m -underline 0
|
||
|
foreach i [list 1 5 10 15 20 25 30 35 40 50 60 70 80 90 100] {
|
||
|
set n $m.$i
|
||
|
menu $n -tearoff 0
|
||
|
$m add command -label "G($i)" -command "G \[newNodes $i\]"
|
||
|
}
|
||
|
|
||
|
set m ${TOPOMENUPATH}.gridc
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Connected Grid" -menu $m -underline 0
|
||
|
|
||
|
for { set i 1 } { $i <= 10 } { incr i } {
|
||
|
set n $m.$i
|
||
|
menu $n -tearoff 0
|
||
|
$m add cascade -label "$i x N" -menu $n -underline 0
|
||
|
for { set j 1 } { $j <= 10 } { incr j } {
|
||
|
$n add command -label "$i x $j" -command "Gchelper $i $j"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set m ${TOPOMENUPATH}.chain
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Chain" -menu $m -underline 0
|
||
|
for { set i 2 } { $i <= 24 } { incr i } {
|
||
|
$m add command -label "P($i)" -command "P \[newNodes $i\]"
|
||
|
}
|
||
|
# Boeing
|
||
|
foreach i [list 32 64 128] {
|
||
|
$m add command -label "P($i)" -command "P \[newNodes $i\]"
|
||
|
}
|
||
|
# end Boeing
|
||
|
|
||
|
set m ${TOPOMENUPATH}.star
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Star" -menu $m -underline 0
|
||
|
for { set i 3 } { $i <= 25 } { incr i } {
|
||
|
$m add command -label "S($i)" \
|
||
|
-command "Kb \[newNodes 1\] \[newNodes [expr {$i - 1}]\]"
|
||
|
}
|
||
|
|
||
|
set m ${TOPOMENUPATH}.cycle
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Cycle" -menu $m -underline 0
|
||
|
for { set i 3 } { $i <= 24 } { incr i } {
|
||
|
$m add command -label "C($i)" -command "C \[newNodes $i\]"
|
||
|
}
|
||
|
|
||
|
set m ${TOPOMENUPATH}.wheel
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Wheel" -menu $m -underline 0
|
||
|
for { set i 4 } { $i <= 25 } { incr i } {
|
||
|
$m add command -label "W($i)" \
|
||
|
-command "W \"\[newNodes 1\] \[newNodes [expr {$i - 1}]\]\""
|
||
|
}
|
||
|
|
||
|
set m ${TOPOMENUPATH}.cube
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Cube" -menu $m -underline 0
|
||
|
for { set i 2 } { $i <= 6 } { incr i } {
|
||
|
$m add command -label "Q($i)" \
|
||
|
-command "Q \[newNodes [expr {int(pow(2,$i))}]\]"
|
||
|
}
|
||
|
|
||
|
set m ${TOPOMENUPATH}.clique
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Clique" -menu $m -underline 0
|
||
|
for { set i 3 } { $i <= 24 } { incr i } {
|
||
|
$m add command -label "K($i)" -command "K \[newNodes $i\]"
|
||
|
}
|
||
|
|
||
|
set m ${TOPOMENUPATH}.bipartite
|
||
|
menu $m -tearoff 0
|
||
|
${TOPOMENUPATH} add cascade -label "Bipartite" -menu $m -underline 0
|
||
|
|
||
|
for { set i 1 } { $i <= 12 } { incr i } {
|
||
|
set n $m.$i
|
||
|
menu $n -tearoff 0
|
||
|
$m add cascade -label "K($i,N)" -menu $n -underline 0
|
||
|
for { set j $i } { $j <= [expr {24 - $i}] } { incr j } {
|
||
|
$n add command -label "K($i,$j)" -command "Kbhelper $i $j"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
proc newNodes { n } {
|
||
|
global curcanvas grid sizex sizey activetool activetoolp CORE_DATA_DIR
|
||
|
global g_last_selected_node_type
|
||
|
|
||
|
if { [lsearch {select start link bgobjs} $activetool] >= 0 } {
|
||
|
set activetoolp ""
|
||
|
}
|
||
|
# some other tool is selected besides layer-2/3 nodes
|
||
|
if { $activetoolp != "routers" && $activetoolp != "hubs" } {
|
||
|
if { [info exists g_last_selected_node_type] && \
|
||
|
$g_last_selected_node_type != "" } {
|
||
|
set parent [lindex $g_last_selected_node_type 0]
|
||
|
set b [lindex $g_last_selected_node_type 1]
|
||
|
set imgf [lindex $g_last_selected_node_type 2]
|
||
|
popupMenuChoose $parent $b $imgf
|
||
|
} else {
|
||
|
# select router by default (this properly sets some globals)
|
||
|
set icon "$CORE_DATA_DIR/icons/tiny/router.gif"
|
||
|
popupMenuChoose "routers" "router" $icon
|
||
|
}
|
||
|
}
|
||
|
|
||
|
set v {}
|
||
|
set r [expr {($n - 1) * (1 + 4 / $n) * $grid / 2}]
|
||
|
set x0 [expr {$sizex / 2}]
|
||
|
set y0 [expr {$sizey / 2}]
|
||
|
set twopidivn [expr {acos(0) * 4 / $n}]
|
||
|
|
||
|
set dy 32
|
||
|
if { [lsearch {router rj45} $activetool] >= 0 } {
|
||
|
set dy 28
|
||
|
} elseif { [lsearch {hub lanswitch} $activetool] >= 0 } {
|
||
|
set dy 24
|
||
|
}
|
||
|
|
||
|
for { set i 0 } { $i < $n } { incr i } {
|
||
|
if { $activetoolp == "routers" } {
|
||
|
set new_node [newNode router]
|
||
|
setNodeModel $new_node $activetool
|
||
|
} else {
|
||
|
set new_node [newNode $activetool]
|
||
|
}
|
||
|
set x [expr {$x0 + $r * cos($twopidivn * $i)}]
|
||
|
set y [expr {$y0 - $r * sin($twopidivn * $i)}]
|
||
|
setNodeCoords $new_node "$x $y"
|
||
|
setNodeLabelCoords $new_node "$x [expr {$y + $dy}]"
|
||
|
setNodeCanvas $new_node $curcanvas
|
||
|
lappend v $new_node
|
||
|
}
|
||
|
|
||
|
return $v
|
||
|
}
|
||
|
|
||
|
proc topoGenDone { v } {
|
||
|
global changed activetool
|
||
|
|
||
|
set activetool select
|
||
|
set changed 1
|
||
|
updateUndoLog
|
||
|
redrawAll
|
||
|
selectNodes $v
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Chain
|
||
|
#
|
||
|
proc P { v } {
|
||
|
.c config -cursor watch; update
|
||
|
set n [llength $v]
|
||
|
for { set i 0 } { $i < [expr {$n - 1}] } { incr i } {
|
||
|
newLink [lindex $v $i] [lindex $v [expr {($i + 1) % $n}]]
|
||
|
}
|
||
|
topoGenDone $v
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Cycle
|
||
|
#
|
||
|
proc C { v } {
|
||
|
.c config -cursor watch; update
|
||
|
set n [llength $v]
|
||
|
for { set i 0 } { $i < $n } { incr i } {
|
||
|
newLink [lindex $v $i] [lindex $v [expr {($i + 1) % $n}]]
|
||
|
}
|
||
|
topoGenDone $v
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Wheel
|
||
|
#
|
||
|
proc W { v } {
|
||
|
.c config -cursor watch; update
|
||
|
set n [llength $v]
|
||
|
set vr [lindex $v 0]
|
||
|
set vt "$v [lindex $v 1]"
|
||
|
for { set i 1 } { $i < $n } { incr i } {
|
||
|
newLink $vr [lindex $v $i]
|
||
|
newLink [lindex $v $i] [lindex $vt [expr {$i + 1}]]
|
||
|
}
|
||
|
topoGenDone $v
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Cube
|
||
|
#
|
||
|
proc Q { v } {
|
||
|
set n [llength $v]
|
||
|
set order [expr int(log($n)/log(2))]
|
||
|
for { set i 0 } { $i < $order } { incr i } {
|
||
|
animateCursor
|
||
|
set d [expr {int(pow(2, $i))}]
|
||
|
for { set j 0 } { $j < $n } { incr j } {
|
||
|
if { [llength [ifcList [lindex $v $j]]] <= $i} {
|
||
|
newLink [lindex $v $j] [lindex $v [expr {($j + $d) % $n}]]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
topoGenDone $v
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Clique
|
||
|
#
|
||
|
proc K { v } {
|
||
|
set n [llength $v]
|
||
|
for { set i 0 } { $i < [expr {$n - 1}] } { incr i } {
|
||
|
animateCursor
|
||
|
for { set j [expr {$i + 1}] } { $j < $n } {incr j } {
|
||
|
newLink [lindex $v $i] [lindex $v $j]
|
||
|
}
|
||
|
}
|
||
|
topoGenDone $v
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Bipartite
|
||
|
#
|
||
|
proc Kb { v1 v2 } {
|
||
|
set n1 [llength $v1]
|
||
|
set n2 [llength $v2]
|
||
|
for { set i 0 } { $i < $n1 } { incr i } {
|
||
|
animateCursor
|
||
|
for { set j 0 } { $j < $n2 } {incr j } {
|
||
|
newLink [lindex $v1 $i] [lindex $v2 $j]
|
||
|
}
|
||
|
}
|
||
|
topoGenDone "$v1 $v2"
|
||
|
}
|
||
|
|
||
|
proc Kbhelper { n m } {
|
||
|
set v [newNodes [expr $n + $m]]
|
||
|
Kb [lrange $v 0 [expr $n -1]] [lrange $v $n end]
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Random
|
||
|
#
|
||
|
proc R { v } {
|
||
|
global curcanvas
|
||
|
set c .c
|
||
|
set min 20
|
||
|
set xmax [expr {[lindex [getCanvasSize $curcanvas] 0] - 2*$min}]
|
||
|
set ymax [expr {[lindex [getCanvasSize $curcanvas] 1] - 2*$min}]
|
||
|
|
||
|
expr { srand([clock clicks -milliseconds]) }
|
||
|
|
||
|
.c config -cursor watch; update
|
||
|
foreach node $v {
|
||
|
set x [expr { int(rand() * $xmax) + $min} ]
|
||
|
set y [expr { int(rand() * $ymax) + $min} ]
|
||
|
setNodeCoords $node "$x $y"
|
||
|
set dy 28
|
||
|
setNodeLabelCoords $node "$x [expr {$y + $dy}]"
|
||
|
}
|
||
|
topoGenDone $v
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Grid
|
||
|
#
|
||
|
proc G { v } {
|
||
|
global curcanvas
|
||
|
set c .c
|
||
|
set step 100
|
||
|
set min 50
|
||
|
set xmax [expr {[lindex [getCanvasSize $curcanvas] 0] - 2*$min}]
|
||
|
set ymax [expr {[lindex [getCanvasSize $curcanvas] 1] - 2*$min}]
|
||
|
|
||
|
.c config -cursor watch; update
|
||
|
set x $min
|
||
|
set y $min
|
||
|
foreach node $v {
|
||
|
if { $x >= $xmax } { ;# end of the row
|
||
|
set x $min
|
||
|
incr y $step
|
||
|
if { $y >= $ymax } {
|
||
|
# xmax and ymax reached -- out of canvas space here!
|
||
|
set y $ymax
|
||
|
}
|
||
|
}
|
||
|
setNodeCoords $node "$x $y"
|
||
|
set dy 28
|
||
|
setNodeLabelCoords $node "$x [expr {$y + $dy}]"
|
||
|
incr x $step
|
||
|
}
|
||
|
topoGenDone $v
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# Connected Grid
|
||
|
#
|
||
|
proc Gc { v n m } {
|
||
|
set step 100
|
||
|
set dy 28
|
||
|
set y $step
|
||
|
|
||
|
set nodenum 0
|
||
|
|
||
|
# m is number of rows
|
||
|
for { set i 0 } { $i < $m } { incr i } {
|
||
|
animateCursor
|
||
|
set x 0 ;# start a new row
|
||
|
# n is number of columns
|
||
|
for { set j 0 } { $j < $n } {incr j } {
|
||
|
incr x $step
|
||
|
set node [lindex $v $nodenum]
|
||
|
setNodeCoords $node "$x $y"
|
||
|
setNodeLabelCoords $node "$x [expr {$y + $dy}]"
|
||
|
if { $x > $step } { ;# link each node with prev in row
|
||
|
set lastnode [lindex $v [expr {$nodenum - 1}]]
|
||
|
newLink $lastnode $node
|
||
|
}
|
||
|
if { $y > $step } { ;# link each node with above in column
|
||
|
set lastnode [lindex $v [expr {$nodenum - $n}]]
|
||
|
newLink $lastnode $node
|
||
|
}
|
||
|
incr nodenum 1 ;# on to the next column
|
||
|
}
|
||
|
incr y $step ;# on to the next row
|
||
|
}
|
||
|
topoGenDone $v
|
||
|
}
|
||
|
|
||
|
proc Gchelper { n m } {
|
||
|
set v [newNodes [expr $n * $m]]
|
||
|
Gc $v $n $m
|
||
|
}
|