683 lines
22 KiB
Tcl
683 lines
22 KiB
Tcl
#
|
|
# Copyright 2005-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.
|
|
#
|
|
# This work was supported in part by Croatian Ministry of Science
|
|
# and Technology through the research contract #IP-2003-143.
|
|
#
|
|
|
|
# default built-in model to use and its default parameters
|
|
set DEFAULT_WLAN_MODEL basic_range
|
|
set DEFAULT_SCRIPT_MODEL ns2script
|
|
set DEFAULT_WLAN_MODEL_TYPES "3 3 9 9 9"
|
|
set DEFAULT_RANGE 275
|
|
set DEFAULT_WLAN_BW 54000000
|
|
set DEFAULT_WLAN_DELAY 20000
|
|
set DEFAULT_WLAN_MODEL_VALS [list "range=$DEFAULT_RANGE" \
|
|
"bandwidth=$DEFAULT_WLAN_BW" "jitter=0" "delay=$DEFAULT_WLAN_DELAY" \
|
|
"error=0" ]
|
|
# default canvas reference point: X Y lat long alt
|
|
set DEFAULT_REFPT "0 0 47.5791667 -122.132322 2.0"
|
|
|
|
#
|
|
# look for all wlan nodes connected to peer if specified,
|
|
# otherwise in the global list of nodes
|
|
proc findWlanNodes { peer } {
|
|
global node_list
|
|
set wlans { }
|
|
|
|
# search the global node list for the first wlan node
|
|
if { $peer == "" } {
|
|
foreach node $node_list {
|
|
if { [nodeType $node] == "wlan" } {
|
|
lappend wlans $node
|
|
}
|
|
}
|
|
# search peer for wlan node
|
|
} else {
|
|
foreach ifc [ifcList $peer] {
|
|
set node [peerByIfc $peer $ifc]
|
|
if { [nodeType $node] == "wlan" } {
|
|
lappend wlans $node
|
|
}
|
|
}
|
|
}
|
|
return $wlans
|
|
}
|
|
|
|
#
|
|
# Returns 1 if the given interface is wireless
|
|
proc isIfcWireless { node ifc } {
|
|
if { $ifc == "wireless" } {
|
|
# wireless peudo-interface
|
|
return false
|
|
}
|
|
set peer [logicalPeerByIfc $node $ifc]
|
|
if { $peer != "" && [nodeType $peer] == "wlan" } {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
#
|
|
# remove the (green) WLAN GUI links
|
|
#
|
|
proc clearWlanLinks { wlan } {
|
|
global .c
|
|
set search "wlanlink"
|
|
if { $wlan != "" } { set search "wlanlink && $wlan" }
|
|
foreach wlanlink [.c find withtag $search] {
|
|
set tags [.c gettags $wlanlink]
|
|
set lnode1 [lindex $tags 1]
|
|
set lnode2 [lindex $tags 2]
|
|
.c delete $wlanlink
|
|
.c delete -withtags "linklabel && $lnode1 && $lnode2"
|
|
# we could also remove wlan node hash table entry for
|
|
# each wlanlink, but we are assuming wlan node will be
|
|
# destroyed anyway
|
|
}
|
|
}
|
|
|
|
# draws circles in GUI representing wlan range
|
|
proc updateRangeCircles { wlan range } {
|
|
global .c zoom g_selected_model
|
|
set c .c
|
|
|
|
set radius [expr {$zoom * $range/2}]
|
|
$c delete -withtag rangecircles
|
|
if { $radius == 0 } {
|
|
return
|
|
}
|
|
if { $g_selected_model != "none" } {
|
|
return
|
|
}
|
|
foreach ifc [ifcList $wlan] {
|
|
set node [peerByIfc $wlan $ifc]
|
|
set coords [getNodeCoords $node]
|
|
set x [expr {[lindex $coords 0] * $zoom}]
|
|
set y [expr {[lindex $coords 1] * $zoom}]
|
|
set x1 [expr $x - $radius]
|
|
set y1 [expr $y - $radius]
|
|
set x2 [expr $x + $radius]
|
|
set y2 [expr $y + $radius]
|
|
|
|
set newcircle [$c create oval $x1 $y1 $x2 $y2 \
|
|
-width 2 -outline #00A000 -tags "circle rangecircles"]
|
|
}
|
|
}
|
|
|
|
proc linkSelectedNodes { wlan nodes } {
|
|
set canvas [getNodeCanvas $wlan]
|
|
|
|
foreach node $nodes {
|
|
if { $wlan == $node } { continue } ;# don't link to self
|
|
if { [ifcByPeer $wlan $node] != "" } { continue } ;# already linked
|
|
if { [getNodeCanvas $node] != $canvas } { continue }; # on a different canvas
|
|
newGUILink $wlan $node
|
|
}
|
|
}
|
|
|
|
proc linkAllNodes { wlan } {
|
|
global node_list
|
|
|
|
set canvas [getNodeCanvas $wlan]
|
|
|
|
# vars related to the status bar graph
|
|
set num 0
|
|
set num_nodes [llength $node_list]
|
|
statgraph on $num_nodes
|
|
set update_interval [expr {$num_nodes / 15}]
|
|
.c config -cursor watch; update
|
|
|
|
foreach node $node_list {
|
|
statgraph inc 1
|
|
incr num
|
|
# GUI update slows this down considerably, so update every so often
|
|
if { $update_interval > 0 && \
|
|
[expr { ($num % $update_interval) }] == 0 } { update }
|
|
if { [nodeType $node] != "router" } { continue }
|
|
if { [ifcByPeer $wlan $node] != "" } { continue } ;# already linked
|
|
if { [getNodeCanvas $node] != $canvas } { continue }; # on a different canvas
|
|
newGUILink $wlan $node
|
|
}
|
|
.c config -cursor left_ptr; update
|
|
statgraph off 0
|
|
}
|
|
|
|
proc getWlanColor { wlan } {
|
|
global node_list wlanLinkColors
|
|
set colornum 0
|
|
foreach node $node_list {
|
|
if {[nodeType $node] != "wlan"} {
|
|
continue
|
|
}
|
|
if {$node == $wlan} {
|
|
return [lindex $wlanLinkColors $colornum]
|
|
}
|
|
incr colornum
|
|
if { $colornum >= [llength $wlanLinkColors] } { set colornum 0 }
|
|
}
|
|
# default color
|
|
return [lindex $wlanLinkColors 0]
|
|
}
|
|
|
|
# move a node given incremental coordinates
|
|
# dx dy should be adjusted for zoom
|
|
proc moveNodeIncr { c node dx dy } {
|
|
global node_list
|
|
#puts "moveNodeIncr $node $dx $dy"
|
|
# check that node exists
|
|
if {[lsearch $node_list $node] == -1 } {
|
|
return
|
|
}
|
|
# move the node and its links
|
|
set img [$c find withtag "node && $node"]
|
|
set coords [$c coords $img]
|
|
set x [lindex $coords 0]
|
|
set y [lindex $coords 1]
|
|
# move doesn't take incremental coordinates
|
|
set xpos [expr ($x + $dx)]
|
|
set ypos [expr ($y + $dy)]
|
|
moveNode $c $node $img $xpos $ypos $dx $dy
|
|
}
|
|
|
|
# move a node given absolute coordinates
|
|
# xpos,ypos should be adjusted for zoom
|
|
proc moveNodeAbs { c node xpos ypos } {
|
|
global node_list
|
|
# check that node exists
|
|
if {[lsearch $node_list $node] == -1 } {
|
|
return
|
|
}
|
|
# move the node and its links
|
|
if {$xpos != 0 && $ypos != 0} {
|
|
set img [$c find withtag "node && $node"]
|
|
set coords [$c coords $img]
|
|
set x [lindex $coords 0]
|
|
set y [lindex $coords 1]
|
|
# move doesn't take absolute coordinates
|
|
set dx [expr ($xpos - $x)]
|
|
set dy [expr ($ypos - $y)]
|
|
moveNode $c $node $img $xpos $ypos $dx $dy
|
|
}
|
|
}
|
|
|
|
# move a node on the canvas along with its labels and links
|
|
# helper function used by moveNodeIncr and moveNodeAbs
|
|
proc moveNode { c node img xpos ypos dx dy } {
|
|
global zoom
|
|
$c move $img $dx $dy
|
|
set xposz [expr {$xpos / $zoom}]; set yposz [expr {$ypos / $zoom}]
|
|
setNodeCoords $node "$xposz $yposz"
|
|
$c move "nodelabel && $node" $dx $dy
|
|
$c move "highlight && $node" $dx $dy
|
|
$c move "rangecircles && $node" $dx $dy
|
|
lassign [getDefaultLabelOffsets [nodeType $node]] ldx ldy
|
|
setNodeLabelCoords $node "[expr {$xposz + $ldx}] [expr {$yposz + $ldy}]"
|
|
$c addtag need_redraw withtag "link && $node"
|
|
$c addtag need_redraw withtag "wlanlink && $node"
|
|
foreach link [$c find withtag "link && need_redraw"] {
|
|
redrawLink [lindex [$c gettags $link] 1]
|
|
}
|
|
foreach wlanlink [$c find withtag \
|
|
"wlanlink && need_redraw"] {
|
|
redrawWlanLink $wlanlink
|
|
}
|
|
$c delete -withtags selectmark
|
|
$c dtag link need_redraw
|
|
$c dtag wlanlink need_redraw
|
|
|
|
# callback for updating any widgets
|
|
widgets_move_node $c $node 1
|
|
}
|
|
|
|
# called from cfgparse when loading imn file
|
|
proc upgradeWlanConfigs {} {
|
|
global node_list
|
|
set model_list [getPluginsCapList]
|
|
foreach node $node_list {
|
|
if { [nodeType $node] != "wlan" } { continue }
|
|
set modcfg [netconfFetchSection $node "mobmodel"]
|
|
if { [lindex $modcfg 0] == "range" } {
|
|
upgradeWlanRangeConfig $node
|
|
set modcfg [netconfFetchSection $node "mobmodel"]
|
|
}
|
|
foreach model [lrange $modcfg 1 end] {
|
|
if { [lsearch $model_list "*=$model"] == -1 } {
|
|
puts "***Warning: missing model '$model'!"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# backwards compatibility with old config files
|
|
# convert from "range" model to "basic_range" coreapi model
|
|
proc upgradeWlanRangeConfig { wlan } {
|
|
global DEFAULT_RANGE DEFAULT_WLAN_MODEL
|
|
global DEFAULT_WLAN_MODEL_TYPES DEFAULT_WLAN_BW DEFAULT_WLAN_DELAY
|
|
|
|
netconfInsertSection $wlan [list mobmodel coreapi $DEFAULT_WLAN_MODEL]
|
|
set range [getNodeRange $wlan]
|
|
if { $range == "" } { set range $DEFAULT_RANGE }
|
|
set bw [getLinkBandwidth $wlan]
|
|
if { $bw == "" } { set bw $DEFAULT_WLAN_BW }
|
|
set jitter 0
|
|
set delay [getLinkDelay $wlan]
|
|
if { $delay == "" } { set delay $DEFAULT_WLAN_DELAY }
|
|
set per [getLinkBER $wlan]
|
|
if { $per == "" } { set per 0 }
|
|
set types $DEFAULT_WLAN_MODEL_TYPES
|
|
set vals [list "range=$range" "bandwidth=$bw" "jitter=$jitter" \
|
|
"delay=$delay" "error=$per"]
|
|
setCustomConfig $wlan $DEFAULT_WLAN_MODEL $types $vals 0
|
|
setNodeRange $wlan ""
|
|
setLinkBandwidth $wlan ""
|
|
setLinkDelay $wlan ""
|
|
setLinkBER $wlan ""
|
|
}
|
|
|
|
# helper to populate popup config for wlan nodes
|
|
proc wlanConfigDialogHelper { wi target apply } {
|
|
global range DEFAULT_RANGE DEFAULT_WLAN_MODEL changed
|
|
global DEFAULT_WLAN_MODEL_VALS DEFAULT_WLAN_MODEL_TYPES
|
|
global DEFAULT_SCRIPT_MODEL
|
|
global systype
|
|
global plugin_img_edit
|
|
global g_selected_model
|
|
global oper_mode
|
|
|
|
set wlan $target
|
|
set emulation_type [lindex [getEmulPlugin $target] 1]
|
|
|
|
set modcfg [netconfFetchSection $target "mobmodel"]
|
|
set mobmodel [lindex [split $modcfg] 1]
|
|
|
|
# apply values from the config dialog
|
|
if { $apply } {
|
|
|
|
# basic range selected
|
|
if { $g_selected_model == "none" } {
|
|
set mobmodel $DEFAULT_WLAN_MODEL
|
|
# bw/delay/ber
|
|
set rb $wi.wl.note.basic.rb
|
|
set de $wi.wl.note.basic.de
|
|
set jt $wi.wl.note.basic.jt
|
|
set bw [$rb.value get]
|
|
set jitter [$jt.value1 get]
|
|
set delay [$de.value2 get]
|
|
set per [$de.value3 get]
|
|
set types $DEFAULT_WLAN_MODEL_TYPES
|
|
set vals [list "range=$range" "bandwidth=$bw" "jitter=$jitter" \
|
|
"delay=$delay" "error=$per"]
|
|
setCustomConfig $wlan $DEFAULT_WLAN_MODEL $types $vals 0
|
|
# EMANE model selected
|
|
} else {
|
|
set mobmodel $g_selected_model
|
|
}
|
|
|
|
# ns-2 mobility script file
|
|
set scriptcfg [getCustomConfigByID $wlan $DEFAULT_SCRIPT_MODEL]
|
|
if { $scriptcfg != "" } {
|
|
netconfInsertSection $target \
|
|
[list mobmodel coreapi $mobmodel $DEFAULT_SCRIPT_MODEL]
|
|
} else {
|
|
netconfInsertSection $target [list mobmodel coreapi $mobmodel]
|
|
}
|
|
|
|
# ipv4/ipv6 address
|
|
set ipv4changed 0
|
|
set ipv6changed 0
|
|
set ipaddr [$wi.bottom.ipv4.addrv get]
|
|
set oldipaddr [getIfcIPv4addr $target wireless]
|
|
if { $ipaddr != $oldipaddr } {
|
|
setIfcIPv4addr $target wireless $ipaddr
|
|
set changed 1
|
|
set ipv4changed 1
|
|
}
|
|
set ipaddr [$wi.bottom.ipv6.addrv get]
|
|
set oldipaddr [getIfcIPv6addr $target wireless]
|
|
if { $ipaddr != $oldipaddr } {
|
|
setIfcIPv6addr $target wireless $ipaddr
|
|
set changed 1
|
|
set ipv6changed 1
|
|
}
|
|
foreach ifc [ifcList $target] {
|
|
set lnode [lindex [linkByIfc $target $ifc] 0]
|
|
# erase IPv4/IPv6 addresses as needed
|
|
set peer [peerByIfc $target $ifc]
|
|
set peerifc [ifcByPeer $peer $target]
|
|
if { $ipv4changed } { setIfcIPv4addr $peer $peerifc "" }
|
|
if { $ipv6changed } { setIfcIPv6addr $peer $peerifc "" }
|
|
}
|
|
# addresses have been zeroed above to force using the WLAN subnet
|
|
foreach ifc [ifcList $target] {
|
|
set peer [peerByIfc $target $ifc]
|
|
set peerifc [ifcByPeer $peer $target]
|
|
if { $ipv4changed } { autoIPv4addr $peer $peerifc }
|
|
if { $ipv6changed } { autoIPv6addr $peer $peerifc }
|
|
}
|
|
# remove any range circles
|
|
updateRangeCircles $target 0
|
|
|
|
if { $oper_mode == "exec" } {
|
|
# this generates Config Messages for updating the model parameters
|
|
pluginCapsInitialize $target "mobmodel"
|
|
}
|
|
return
|
|
}
|
|
|
|
# use default model/values when none configured for this node
|
|
if { $mobmodel == "" } {
|
|
set mobmodel $DEFAULT_WLAN_MODEL
|
|
set vals $DEFAULT_WLAN_MODEL_VALS
|
|
# look for customized range/bw/jitter/delay/per
|
|
} else {
|
|
set vals [getCustomConfigByID $target $DEFAULT_WLAN_MODEL]
|
|
if { $vals == "" } { set vals $DEFAULT_WLAN_MODEL_VALS }
|
|
}
|
|
|
|
# set radio button variable
|
|
if { $mobmodel == $DEFAULT_WLAN_MODEL } {
|
|
set g_selected_model "none"
|
|
} else {
|
|
set g_selected_model $mobmodel
|
|
}
|
|
|
|
set range [getServiceValuesItem $vals "range" 0]
|
|
set bw [getServiceValuesItem $vals "bandwidth" 1]
|
|
set jitter [getServiceValuesItem $vals "jitter" 2]
|
|
set delay [getServiceValuesItem $vals "delay" 3]
|
|
set per [getServiceValuesItem $vals "error" 4]
|
|
|
|
ttk::labelframe $wi.wl -text "Wireless"
|
|
pack $wi.wl -fill both -expand true -padx 4 -pady 4
|
|
|
|
ttk::notebook $wi.wl.note
|
|
pack $wi.wl.note -fill both -expand true -padx 4 -pady 4
|
|
ttk::notebook::enableTraversal $wi.wl.note
|
|
|
|
##
|
|
## basic range
|
|
##
|
|
ttk::frame $wi.wl.note.basic
|
|
$wi.wl.note add $wi.wl.note.basic -text "Basic" -underline 0
|
|
set txt "The basic range model calculates on/off connectivity based on"
|
|
set txt "$txt pixel\n distance between nodes."
|
|
ttk::label $wi.wl.note.basic.tlab -text $txt
|
|
pack $wi.wl.note.basic.tlab -side top -anchor w -padx 4 -pady 4
|
|
|
|
# range and bandwidth (rb) frame
|
|
set rb $wi.wl.note.basic.rb
|
|
ttk::frame $rb
|
|
ttk::label $rb.rlab -text "Range:"
|
|
ttk::scale $rb.rscale -command "updateRangeCircles $target" \
|
|
-to 1500 -orient horizontal -variable range
|
|
ttk::entry $rb.range -width 5 -textvariable range
|
|
pack $rb.rlab $rb.rscale $rb.range -side left -padx 4 -pady 4
|
|
|
|
# bandwidth
|
|
set spinbox [getspinbox]
|
|
ttk::label $rb.label -anchor w -text "Bandwidth (bps):"
|
|
$spinbox $rb.value -justify right -width 10 -validate focus
|
|
$rb.value configure -validatecommand {checkIntRange %P 0 1000000000} \
|
|
-from 0 -to 1000000000 -increment 1000000
|
|
$rb.value insert 0 $bw
|
|
pack $rb.label $rb.value \
|
|
-side left -padx 4 -pady 4
|
|
pack $rb -side top -anchor w -padx 4 -pady 4
|
|
|
|
# delay and error (de) frame
|
|
set de $wi.wl.note.basic.de
|
|
ttk::frame $de
|
|
|
|
ttk::label $de.label2 -anchor w -text "Delay (us):"
|
|
$spinbox $de.value2 -justify right -width 10 -validate focus
|
|
$de.value2 configure -validatecommand {checkIntRange %P 0 10000000} \
|
|
-from 0 -to 10000000 -increment 5000
|
|
$de.value2 insert 0 $delay
|
|
pack $de.label2 $de.value2 -side left -padx 4 -pady 4
|
|
|
|
$spinbox $de.value3 -justify right -width 5 -validate focus
|
|
if { [lindex $systype 0] == "Linux" } {
|
|
ttk::label $de.label3 -anchor w -text "Loss (%):"
|
|
$de.value3 configure -from 0 -to 100.0 -increment 0.1
|
|
} else { ;# netgraph
|
|
ttk::label $de.label3 -anchor w -text "Bit Error (1/N):"
|
|
$de.value3 configure -width 10 -validatecommand \
|
|
{checkIntRange %P 0 10000000000000} \
|
|
-from 0 -to 10000000000000 -increment 1000
|
|
}
|
|
$de.value3 insert 0 $per
|
|
pack $de.label3 $de.value3 \
|
|
-side left -padx 4 -pady 4
|
|
pack $de -side top -anchor w -padx 4 -pady 4
|
|
|
|
# jitter frame
|
|
set jt $wi.wl.note.basic.jt
|
|
ttk::frame $jt
|
|
ttk::label $jt.label1 -anchor w -text "Jitter (us):"
|
|
$spinbox $jt.value1 -justify right -width 10 -validate focus
|
|
$jt.value1 configure -validatecommand {checkIntRange %P 0 10000000} \
|
|
-from 0 -to 10000000 -increment 5000
|
|
$jt.value1 insert 0 $jitter
|
|
pack $jt.label1 $jt.value1 -side left -padx 4 -pady 4
|
|
pack $jt -side top -anchor w -padx 4 -pady 4
|
|
|
|
###
|
|
### EMANE
|
|
###
|
|
ttk::frame $wi.wl.note.emane
|
|
$wi.wl.note add $wi.wl.note.emane -text "EMANE" -underline 0
|
|
set txt "The EMANE emulation system provides more complex wireless radio"
|
|
set txt "$txt emulation\n using pluggable MAC and PHY modules."
|
|
set txt "$txt Refer to the wiki for configuration option details"
|
|
ttk::label $wi.wl.note.emane.tlab -text $txt
|
|
ttk::button $wi.wl.note.emane.wiki -text "EMANE Wiki" \
|
|
-image $plugin_img_edit -compound right \
|
|
-command \
|
|
"_launchBrowser https://github.com/adjacentlink/emane/wiki"
|
|
pack $wi.wl.note.emane.wiki -side top -anchor w -padx 4 -pady 4
|
|
pack $wi.wl.note.emane.tlab -side top -anchor w -padx 4 -pady 4
|
|
|
|
# models
|
|
set mod $wi.wl.note.emane.models
|
|
ttk::labelframe $mod -text "EMANE Models"
|
|
pack $mod -side top -fill both -expand true -padx 4 -pady 4
|
|
|
|
set side "nw"
|
|
ttk::radiobutton $mod.none -text "none" -command "updateOptBtn $wi none" \
|
|
-value "none" -variable g_selected_model -width 12
|
|
pack $mod.none -side top -anchor w -padx 4 -pady 0
|
|
|
|
set caplist [getPluginsCapList]
|
|
set emane_models {}
|
|
set have_emane_models false
|
|
# TODO: a refresh button here would be nice
|
|
foreach cap $caplist {
|
|
set captype [lindex [split $cap =] 0]
|
|
set capname [lindex [split $cap =] 1]
|
|
if { [string range $capname 0 5] != "emane_" } { continue }
|
|
set emane_model [capTitle $capname]
|
|
|
|
ttk::radiobutton $mod.$capname -text $emane_model -value $capname \
|
|
-variable g_selected_model -width 12 \
|
|
-command "updateOptBtn $wi $emane_model"
|
|
pack $mod.$capname -side top -anchor w -padx 4 -pady 0
|
|
set have_emane_models true
|
|
}
|
|
if { ! $have_emane_models } {
|
|
# show connection dialog box to indicate why there are no EMANE models
|
|
$mod.none configure -text "Please install EMANE" \
|
|
-width "45"
|
|
after 500 {
|
|
update ;# allow dialog layout, otherwise strange results
|
|
pluginConnect "" connect true
|
|
}
|
|
}
|
|
|
|
# options buttons
|
|
set opts $wi.wl.note.emane.opts
|
|
ttk::frame $opts
|
|
ttk::button $opts.model -text "model options" \
|
|
-image $plugin_img_edit -compound right -command "" -state disabled \
|
|
-command "configCap $target \[set g_selected_model\]"
|
|
pack $opts.model -side left -padx 4 -pady 4
|
|
pack $opts -side top -anchor c -padx 4 -pady 4
|
|
|
|
# show correct tab basic/emane based on selection
|
|
if { $g_selected_model == "none" } {
|
|
$wi.wl.note select $wi.wl.note.basic
|
|
} else {
|
|
$wi.wl.note select $wi.wl.note.emane
|
|
}
|
|
updateOptBtn $wi [capTitle $g_selected_model]
|
|
|
|
|
|
# WLAN has not been linked yet, generate addresses here.
|
|
if { [getIfcIPv4addr $target wireless] == "" } {
|
|
setIfcIPv4addr $target wireless "[findFreeIPv4Net 24].0/32"
|
|
}
|
|
if { [getIfcIPv6addr $target wireless] == "" } {
|
|
setIfcIPv6addr $target wireless "[findFreeIPv6Net 64]::0/128"
|
|
}
|
|
|
|
frame $wi.bottom -padx 4 -pady 4
|
|
|
|
# 4. IPv4/IPv6 addresses
|
|
#
|
|
# IPv4 address
|
|
#
|
|
frame $wi.bottom.ipv4
|
|
label $wi.bottom.ipv4.addrl -text "IPv4 subnet" \
|
|
-anchor w
|
|
entry $wi.bottom.ipv4.addrv -bg white -width 30 \
|
|
-validate focus -invcmd "focusAndFlash %W"
|
|
$wi.bottom.ipv4.addrv insert 0 \
|
|
[getIfcIPv4addr $target wireless]
|
|
$wi.bottom.ipv4.addrv configure \
|
|
-vcmd {checkIPv4Net %P}
|
|
|
|
#
|
|
# IPv6 address
|
|
#
|
|
frame $wi.bottom.ipv6
|
|
label $wi.bottom.ipv6.addrl -text "IPv6 subnet" \
|
|
-anchor w
|
|
entry $wi.bottom.ipv6.addrv -bg white -width 30 \
|
|
-validate focus -invcmd "focusAndFlash %W"
|
|
$wi.bottom.ipv6.addrv insert 0 \
|
|
[getIfcIPv6addr $target wireless]
|
|
$wi.bottom.ipv6.addrv configure \
|
|
-vcmd {checkIPv6Net %P}
|
|
|
|
#
|
|
# Link all nodes button
|
|
#
|
|
button $wi.bottom.script -text "ns-2 mobility script..." \
|
|
-command "sendConfRequestMessage -1 $target ns2script 0x1 -1 {}"
|
|
button $wi.bottom.linkall -text "Link to all routers" \
|
|
-command "linkAllNodes $target"
|
|
set msg "Select new WLAN $target members:"
|
|
set cmd "linkSelectedNodes $target"
|
|
button $wi.bottom.memb -text "Choose WLAN members" \
|
|
-command "popupSelectNodes \"$msg\" \"\" {$cmd}"
|
|
|
|
# layout items
|
|
|
|
pack $wi.bottom.ipv4.addrl $wi.bottom.ipv4.addrv -side left
|
|
pack $wi.bottom.ipv4 -side top -anchor w
|
|
pack $wi.bottom.ipv6.addrl $wi.bottom.ipv6.addrv -side left
|
|
pack $wi.bottom.ipv6 -side top -anchor w
|
|
pack $wi.bottom.script $wi.bottom.linkall $wi.bottom.memb \
|
|
-side left -anchor center
|
|
|
|
pack $wi.bottom -side top -anchor w
|
|
}
|
|
|
|
# toggle the enabling/disabling of Basic/EMANE controls
|
|
proc updateOptBtn { wi txt } {
|
|
set s normal
|
|
set bs disabled
|
|
if { $txt == "none" } { set s disabled; set bs !disabled; set txt "model" }
|
|
$wi.wl.note.emane.opts.model configure -text "$txt options" -state $s
|
|
|
|
$wi.wl.note.basic.rb.range configure -state $bs
|
|
$wi.wl.note.basic.rb.rscale state $bs
|
|
if { $bs == "disabled" } { .c delete -withtag rangecircles }
|
|
|
|
# spinbox state: disabled/!disabled (Tk 8.5.8) or disabled/normal (ttk)
|
|
set spinboxstate $bs
|
|
if { [info command ttk::spinbox] == "" && $spinboxstate == "!disabled" } {
|
|
set spinboxstate normal
|
|
}
|
|
$wi.wl.note.basic.rb.value configure -state $spinboxstate
|
|
$wi.wl.note.basic.de.value2 configure -state $spinboxstate
|
|
$wi.wl.note.basic.de.value3 configure -state $spinboxstate
|
|
$wi.wl.note.basic.jt.value1 configure -state $spinboxstate
|
|
}
|
|
|
|
proc wlanDoubleClick { node button } {
|
|
set modeldata [netconfFetchSection $node "mobmodel"]
|
|
# modeldata e.g. = "coreapi emane_rfpipe"
|
|
set modeltype [lindex $modeldata 1]
|
|
if { [string range $modeltype 0 4] == "emane" } {
|
|
if { [string range $modeltype 6 end] == "commeffect" } {
|
|
set cmd "emanecommeffectcontroller"
|
|
if { [catch {exec $cmd & } e] } {
|
|
tk_messageBox -icon error -message "Error launching $cmd: $e"
|
|
}
|
|
}
|
|
} else {
|
|
# TODO: non-EMANE WLAN dialog, e.g. mobility
|
|
}
|
|
}
|
|
|
|
# helper returns true for WLANs configured with EMANE models
|
|
proc isEmane { node } {
|
|
if { [nodeType $node] != "wlan" } {
|
|
return false
|
|
}
|
|
set modeldata [netconfFetchSection $node "mobmodel"]
|
|
set modeltype [lindex $modeldata 1]
|
|
if { [string range $modeltype 0 4] == "emane" } {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
# return the EMANE node (WLAN) having the lowest node number
|
|
# the EMANE global config will be stored with this node
|
|
proc minEmaneNode {} {
|
|
global node_list
|
|
set min ""
|
|
foreach node $node_list {
|
|
if { ![isEmane $node] } { continue }
|
|
set nodenum [string range $node 1 end]
|
|
if { $min == "" || $nodenum < $min } {
|
|
set min $nodenum
|
|
}
|
|
}
|
|
if { $min != "" } { set min "n$min" }
|
|
return $min
|
|
}
|