-#
+
# Copyright 2004, 2005 University of Zagreb, Croatia. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# and Technology through the research contract #IP-2003-143.
#
-#****h* imunes/exec.tcl
-# NAME
-# exec.tcl -- file used for all the actions regarding
-# FUNCTION
-# This module is used for all actions that are executed during the
-# simulation, i.e.in the exec mode.
-#****
-#****f* exec.tcl/nexec_local
-# NAME
-# nexec_local -- remove link from GUI
-# SYNOPSIS
-# set result [nexec_local $args]
-# FUNCTION
-# Locally executes the program passed by args. Returns the results
-# of the program.
-# INPUTS
-# * args -- program name and arguments that are to be evaluated.
-# RESULT
-# * result -- the program standard output.
-#****
-proc nexec_local { args } {
- eval exec $args
-}
-
-
-#****f* exec.tcl/Read_exec_results
-# NAME
-# Read_exec_results -- read exec results
-# SYNOPSIS
-# Read_exec_results $sock
-# FUNCTION
-# Reads one line from socket. If the socket is closed the line is not read.
-# When the string Kraj is read, the exec_result_ready variable is set to 1,
-# otherwise the line is appended to the exec_results list.
-# INPUTS
-# * sock -- socket
-#****
-proc Read_exec_results {sock} {
- global exec_results exec_results_ready
- if {[eof $sock] || [catch {gets $sock line}]} {
- close $sock
- } else {
- if {$line=="Kraj"} {
- set exec_results [string range $exec_results 0 [expr [string length $exec_results] - 2]]
- set exec_results_ready 1
- } else {
- append exec_results $line "\n"
- }
- }
- return
-}
-
#****f* exec.tcl/nexec
# NAME
# nexec -- execute program
#****
proc nexec { args } {
global remote_exec editor_only
- global exec_sock exec_results exec_results_ready
- global exec_sockets_opened
+ global execSock
+
+ if { $remote_exec } {
+ if { ![info exists execSock] || $execSock == "" } {
+ remoteStart
+ }
+ }
if { $editor_only } {
tk_messageBox -title "Editor only" \
}
if { $remote_exec } {
- if { ! $exec_sockets_opened } {
- open_exec_sockets
- if { ! [info exists exec_sock] } {
- tk_messageBox -title "Editor only" \
- -message "Cannot open sockets.\nMode changed to \"editor only\"." \
- -type ok
- set editor_only true
- return ""
- }
- }
- set exec_results ""
- puts $exec_sock "$args"
- vwait exec_results_ready
- return $exec_results
+ rexec $execSock $args
} else {
eval exec $args
}
}
-#****f* exec.tcl/Read_monitor_results
-# NAME
-# Read_monitor_results -- read monitor results
-# SYNOPSIS
-# Read_monitor_results $sock
-# FUNCTION
-# Reads one line from socket. If the socket is closed the line is not read.
-# When the string Kraj is read, the monitor_result_ready variable is set
-# to 1, otherwise the line is appended to the monitor_results list.
-# INPUTS
-# * sock -- socket
-#****
-# And now the same for monitor
-proc Read_monitor_results {sock} {
- global monitor_results monitor_results_ready
- if {[eof $sock] || [catch {gets $sock line}]} {
- close $sock
- } else {
- if {$line=="Kraj"} {
- set monitor_results \
- [string range $monitor_results 0 \
- [expr [string length $monitor_results] - 2]]
- set monitor_results_ready 1
- } else {
- append monitor_results $line "\n"
- }
- }
-}
-
-
#****f* exec.tcl/nexec_monitor
# NAME
# nexec_monitor -- execute monitor
# FUNCTION
# Executes the sting given in args variable. The sting is not executed
# if IMUNES is running in editor only mode. Execution of a string can
-# be local or remote. Opens an execute socket if it is not yet opened.
-# Sends the arguments to monitor_sock if the remote execution is
+# be local or remote. Opens a monitor socket if it is not yet opened.
+# Sends the arguments to monitor socket if the remote execution is
# selected, otherwise executes arguments locally.
# INPUTS
# * args -- the string that should be executed locally or remotely.
#****
proc nexec_monitor { args } {
global remote_exec editor_only
- global monitor_sock monitor_results monitor_results_ready
- global exec_sockets_opened
+ global monSock
+
+ if { $remote_exec } {
+ if { ![info exists monSock] || $monSock == "" } {
+ remoteStart
+ }
+ }
if { $editor_only } {
tk_messageBox -title "Editor only" \
}
if { $remote_exec } {
- if { ! $exec_sockets_opened } { open_exec_sockets }
- set monitor_results ""
- puts $monitor_sock "$args"
- vwait monitor_results_ready
- return $monitor_results
+ rexec $monSock $args
} else {
eval exec $args
}
}
-#****f* exec.tcl/open_exec_sockets
-# NAME
-# open_exec_sockets -- open execute socket
-# SYNOPSIS
-# open_exec_sockets
-# FUNCTION
-# Opens a socket for remote execution. Opens an exec socket and
-# a monitor socket. The ip address and port numbers for sockets
-# are defined in exec_hosts variable. The exec_host variable is
-# also set.
-#****
-proc open_exec_sockets {} {
- global exec_hosts remote_exec exec_sockets_opened
- global exec_host exec_port monitor_port exec_sock monitor_sock
- global editor_only
-
- if { ! $remote_exec } { return }
-
- set remote_exec false
- set n [llength $exec_hosts]
- for { set i 0 } { $i < $n } { incr i } {
- if { [lindex [lindex $exec_hosts $i] 3] } {
- set exec_host [lindex [lindex $exec_hosts $i] 0]
- set exec_port [lindex [lindex $exec_hosts $i] 1]
- set monitor_port [lindex [lindex $exec_hosts $i] 2]
- set remote_exec true
- break
- }
- }
-
- if { ! $remote_exec } { return }
-
- set fail true
- while {$fail} {
-
- if { ! [info exists exec_sock] || ! [info exists monitor_sock] } {
- catch {set exec_sock [socket -async $exec_host $exec_port]}
- catch {set monitor_sock [socket -async $exec_host $monitor_port]}
- }
-
- if { [info exists exec_sock] && [info exists monitor_sock] } {
- for { set i 1 } { $i <= 4 } { incr i } {
- if {([lindex [fconfigure $exec_sock -sockname] 0] != "0.0.0.0") &&
- ([lindex [fconfigure $monitor_sock -sockname] 0] != "0.0.0.0")
- && ([catch {fconfigure $exec_sock -peername} a] == 0)
- && ([catch {fconfigure $monitor_sock -peername} a] == 0) } {
- set fail false
- break
- } else {
- after 250 ;# Max 2 sec for socket creation
- }
- }
- }
-
- if { $fail } {
- set sel [tk_dialog .box "Socket problems" \
- "Cannot open sockets {$exec_host,$exec_port|$monitor_port}" \
- "" 0 "Retry" "Configure remote hosts" "Editor only mode" ]
- switch $sel {
- 0 { ;# retry
- }
- 1 { configRemoteHosts
- ;# Never comes back!?
- set at_least_one_up false
- set n [llength $exec_hosts]
- for { set i 0 } { $i < $n } { incr i } {
- if { [lindex [lindex $exec_hosts $i] 3] } {
- set exec_host [lindex [lindex $exec_hosts $i] 0]
- set exec_port [lindex [lindex $exec_hosts $i] 1]
- set monitor_port [lindex [lindex $exec_hosts $i] 2]
- set at_least_one_up true
- break
- }
- }
- if { $remote_exec && ! $at_least_one_up } {
- set editor_only true
- .menubar.experiment entryconfigure \
- "Execute" -state disabled
- }
- }
-
- 2 { set editor_only true
- .menubar.experiment entryconfigure "Execute" -state disabled
- set fail false
- return
- }
- default { }
- }
- }
- }
-
- fconfigure $exec_sock -buffering line
- fileevent $exec_sock readable [list Read_exec_results $exec_sock]
-
- fconfigure $monitor_sock -buffering line
- fileevent $monitor_sock readable [list Read_monitor_results $monitor_sock]
-
- set exec_sockets_opened true
-}
-
#****f* exec.tcl/setOperMode
# NAME
# editor mode (editor_only variable is set).
# When changing the mode to edit, all required buttons are enabled
# (except for simulation/Terminate button that is disabled) and
-# procedure vimageCleanup is called.
+# procedure cleanupCfg is called.
# INPUTS
# * mode -- the new operating mode. Can be edit or exec.
#****
proc setOperMode { mode } {
global oper_mode activetool node_list
global nmbufs nmbclusters
- global editor_only
+ global editor_only remote_exec execSock
if { $mode == "exec" } { ;# let's try something, sockets should be opened
nexec id -u
.menubar.tools entryconfigure "Rearrange selected" -state disabled
.menubar.experiment entryconfigure "Execute" -state disabled
.menubar.experiment entryconfigure "Terminate" -state normal
+ .menubar.experiment entryconfigure "Configure remote hosts" \
+ -state disabled
.menubar.edit entryconfigure "Undo" -state disabled
.menubar.edit entryconfigure "Redo" -state disabled
set oper_mode exec
set nmbufs [lindex [split [nexec sysctl kern.ipc.nmbufs]] 1]
set nmbclusters [lindex [split [nexec sysctl kern.ipc.nmbclusters]] 1]
monitor_loop
- deployCfg
+ if { $remote_exec } {
+ nexec create_conf_file config.imn
+ dumpCfg file $execSock
+ nexec close_conf_file
+ nexec imunes -b config.imn
+ nexec rm config.imn
+ } else {
+ deployCfg
+ }
} else {
if {$oper_mode != "edit"} {
- vimageCleanup
+ #vimageCleanup
+ cleanupCfg
.menubar.tools entryconfigure "Rearrange all" -state normal
.menubar.tools entryconfigure "Rearrange selected" -state normal
}
.menubar.experiment entryconfigure "Execute" -state normal
}
.menubar.experiment entryconfigure "Terminate" -state disabled
+ .menubar.experiment entryconfigure "Configure remote hosts" \
+ -state normal
.menubar.edit entryconfigure "Undo" -state normal
.menubar.edit entryconfigure "Redo" -state normal
set oper_mode edit
+ remoteClose
}
.c config -cursor left_ptr
}
puts $line
} else {
.bottom.textbox config -text "$line"
- animateCursor
}
}
}
}
+#****f* exec.tcl/l3node.start
+# NAME
+# l3node.start -- layer 3 node start
+# SYNOPSIS
+# l3node.start $eid $node
+# FUNCTION
+# Starts a new layer 3 node (pc, host or router). The node can be
+# started if it is instantiated.
+# Simulates the booting proces of a node, starts all the services
+# and assignes the ip addresses to the interfaces.
+# INPUTS
+# * eid -- experiment id
+# * node -- node id
+#****
+proc l3node.start { eid node } {
+ global remote_exec execSock
+
+ set node_id "$eid\_$node"
+
+ nexec rm -fr /tmp/$node_id
+ nexec mkdir /tmp/$node_id
+ nexec chmod 1777 /tmp/$node_id
+ foreach ifc [ifcList $node] {
+ set mtu [getIfcMTU $node $ifc]
+ nexec vimage $node_id ifconfig $ifc mtu $mtu
+ }
+
+ if { [getCustomEnabled $node] == true } {
+ set bootcmd [getCustomCmd $node]
+ set bootcfg [getCustomConfig $node]
+ } else {
+ set bootcmd ""
+ set bootcfg ""
+ }
+ if { $bootcmd == "" || $bootcfg =="" } {
+ set bootcfg [[typemodel $node].cfggen $node]
+ set bootcmd [[typemodel $node].bootcmd $node]
+ }
+ if { ! $remote_exec } {
+ set fileId [open /tmp/$node_id/boot.conf w]
+ foreach line $bootcfg {
+ puts $fileId $line
+ }
+ close $fileId
+ } else {
+ nexec create_conf_file /tmp/$node_id/boot.conf
+ foreach line $bootcfg {
+ puts $execSock $line
+ }
+ nexec close_conf_file
+ }
+ catch "nexec vimage $node_id $bootcmd /tmp/$node_id/boot.conf &"
+}
+
+#****f* exec.tcl/l3node.shutdown
+# NAME
+# l3node.shutdown -- layer 3 node shutdown
+# SYNOPSIS
+# l3node.shutdown $eid $node
+# FUNCTION
+# Shutdowns a layer 3 node (pc, host or router).
+# Simulates the shutdown proces of a node, kills all the services
+# and deletes ip addresses of all interfaces.
+# INPUTS
+# * eid -- experiment id
+# * node -- node id
+#****
+proc l3node.shutdown { eid node } {
+ set node_id "$eid\_$node"
+ catch "nexec vimage $node_id kill -9 -1 2> /dev/null"
+ foreach ifc [ifcList $node] {
+ foreach ipv4 [getIfcIPv4addr $node $ifc] {
+ catch "nexec vimage $node_id ifconfig $ifc $ipv4 -alias"
+ }
+ foreach ipv6 [getIfcIPv6addr $node $ifc] {
+ catch "nexec vimage $node_id ifconfig $ifc inet6 $ipv6 -alias"
+ }
+ }
+}
+
+
+#****f* exec.tcl/l3node.destroy
+# NAME
+# l3node.destroy -- layer 3 node destroy
+# SYNOPSIS
+# l3node.destroy $eid $node
+# FUNCTION
+# Destroys a layer 3 node (pc, host or router).
+# Destroys all the interfaces of the node by sending a shutdown message
+# to netgraph nodes and on the end destroys the vimage itself.
+# INPUTS
+# * eid -- experiment id
+# * node -- node id
+#****
+proc l3node.destroy {eid node } {
+ set node_id "$eid\_$node"
+ foreach ifc [ifcList $node] {
+ catch { nexec ngctl msg $ifc@$node_id: shutdown }
+ }
+ catch {nexec vimage -d $node_id}
+ nexec rm -fr /tmp/$node_id
+}
+
#****f* exec.tcl/deployCfg
# NAME
global eid
global node_list link_list supp_router_models
global mac_byte4 mac_byte5
- global exec_host remote_exec
+ global remote_exec
set mac_byte4 0
set mac_byte5 0
set t_start [clock seconds]
- vimageCleanup
+ #vimageCleanup
+ cleanupCfg
catch { nexec mv /etc/resolv.conf /etc/resolv.conf.bak }
catch { nexec kldload ng_ether }
continue
}
statline "Configuring node [getNodeName $node]"
- set node_id "$eid\_$node"
- set model [getNodeModel $node]
- if { [lsearch -exact {router pc host} $type] >= 0 } {
- nexec rm -fr /tmp/$node_id
- nexec mkdir /tmp/$node_id
- nexec chmod 1777 /tmp/$node_id
- foreach ifc [ifcList $node] {
- set mtu [getIfcMTU $node $ifc]
- nexec vimage $node_id ifconfig $ifc mtu $mtu
- }
-
- if { [getCustomEnabled $node] == true } {
- set bootcmd [getCustomCmd $node]
- set bootcfg [getCustomConfig $node]
- } else {
- set bootcmd ""
- set bootcfg ""
- }
- if { $bootcmd == "" || $bootcfg =="" } {
- set bootcfg [[typemodel $node].cfggen $node]
- set bootcmd [[typemodel $node].bootcmd $node]
- }
- if { ! $remote_exec } {
- set fileId [open /tmp/$node_id/boot.conf w]
- foreach line $bootcfg {
- puts $fileId $line
- }
- close $fileId
- } else {
- nexec create_conf_file /tmp/$node_id/boot.conf
- foreach line $bootcfg {
- nexec $line
- }
- nexec close_conf_file
- }
- catch "nexec vimage $node_id $bootcmd /tmp/$node_id/boot.conf &"
- }
+ [typemodel $node].start $eid $node
}
statline "Network topology instantiated in [expr [clock seconds] - $t_start] seconds ([llength $node_list] nodes and [llength $link_list] links)."
# SYNOPSIS
# vimageCleanup
# FUNCTION
-# Called upon the termination of the simulation. If cleans all
-# the imunes objects created by the simulation that is terminated.
+# Called in special circumstances only. If cleans all
+# the imunes objects from the kernel (vimages and netgraph nodes).
#****
proc vimageCleanup {} {
global .c
set vimages [lreplace $vimages $defindex $defindex]
# Detach / destroy / reassign interfaces pipe, eiface, iface, bridge
- set ngnodes [split [nexec ngctl l | tail -n +3] "\r"]
+ set ngnodes [split [nexec ngctl l | tail -n +3] "
+"]
foreach ngline $ngnodes {
set node [lindex [eval list $ngline] 1]
statline "Shutting down netgraph node $node"
downstream={ BER=$ber duplicate=$dup } }"
}
+#****f* exec.tcl/cleanupCfg
+# NAME
+# cleanupCfg -- cleanup configuration
+# SYNOPSIS
+# cleanupCfg
+# FUNCTION
+# Called upon the termination of the simulation. If cleans all
+# the imunes objects created by the simulation that is terminated.
+# Operates in three steps, first shutdowns all the nodes, than all
+# the links and on the end destroys all the nodes.
+#****
+proc cleanupCfg { } {
+ global .c link_list eid node_list
+
+ set t_start [clock seconds]
+
+#shutting down nodes...
+
+ foreach node $node_list {
+ set type [nodeType $node]
+ set name [getNodeName $node]
+ if { $type != "pseudo" } {
+ statline "Shutting down node $name"
+ [typemodel $node].shutdown $eid $node
+ }
+ }
+
+#shutting down links...
+
+ for { set pending_links $link_list } { $pending_links != "" } {} {
+ set link [lindex $pending_links 0]
+ set i [lsearch -exact $pending_links $link]
+ set pending_links [lreplace $pending_links $i $i]
+
+ set lnode1 [lindex [linkPeers $link] 0]
+ set lnode2 [lindex [linkPeers $link] 1]
+ set ifname1 [ifcByPeer $lnode1 $lnode2]
+ set ifname2 [ifcByPeer $lnode2 $lnode1]
+
+ if { [getLinkMirror $link] != "" } {
+ set mirror_link [getLinkMirror $link]
+ set i [lsearch -exact $pending_links $mirror_link]
+ set pending_links [lreplace $pending_links $i $i]
+
+ set p_lnode2 $lnode2
+ set lnode2 [lindex [linkPeers $mirror_link] 0]
+ set ifnode2 [ifcByPeer $lnode2 [getNodeMirror $p_lnode2]]
+ }
+ set lname $eid\_$lnode1-$lnode2
+ statline "Shutting down netgraph node $lname"
+ catch "nexec ngctl msg $lname: shutdown"
+ }
+
+
+#destroying nodes...
+
+ foreach node $node_list {
+ set type [nodeType $node]
+ set name [getNodeName $node]
+ if { $type != "pseudo" } {
+ statline "Destroying node $node"
+ [typemodel $node].destroy $eid $node
+ }
+ }
+
+#all the rest...
+ catch { nexec rm -f /usr/local/etc/quagga/Quagga.conf }
+ catch { nexec mv /etc/resolv.conf.bak /etc/resolv.conf }
+ statline "Cleanup completed in [expr [clock seconds] - $t_start] seconds."
+
+}
+
+#****f* exec.tcl/openFwrd
+# NAME
+# openFwrd -- open port forwarding
+# SYNOPSIS
+# set result [openFwrd lPort rPort rHost]
+# FUNCTION
+# Called upon starting remote execution with ssh port forwarding.
+# Works only on unix hosts, opens a secure connection from local host
+# to remote host. Uses a key authentication. Returns the proces id
+# of port forwarding
+# INPUTS
+# lPort -- local port
+# rPort -- remote port
+# rHost -- remote host in the form: userName@hostName
+# RESULT
+# * result -- proces id of ssh port forwarding
+#****
+proc openFwrd { lPort rPort rHost } {
+ global tcl_platform platform
+ if { $tcl_platform(platform) == "unix" } {
+ set pid [exec ssh -N -L $lPort:localhost:$rPort $rHost &]
+ return $pid
+ }
+}
+
+#****f* exec.tcl/closeFwrd
+# NAME
+# closeFwrd -- close port forwarding
+# SYNOPSIS
+# set result [closeFwrd pid]
+# FUNCTION
+# Called upon ending remote execution with ssh port forwarding.
+# Works only on unix hosts, closes a secure connection from a local host
+# to the remote host.
+# INPUTS
+# pid -- proces id
+#****
+proc closeFwrd { pid } {
+ global tcl_platform platform
+ if { $tcl_platform(platform) == "unix" } {
+ catch {eval exec kill $pid}
+ return ""
+ }
+}
+
+#****f* exec.tcl/open_sock
+# NAME
+# open_sock -- open socket
+# SYNOPSIS
+# set sock [open_sock rHost rPort]
+# FUNCTION
+# Called upon starting remote execution. Opens a socket.
+# If the ssh encryption is used a socket to the local port is opened,
+# else a socket to the remote host is used. If the creation of
+# socket fails, an empty string is returend.
+# INPUTS
+# rHost -- remote host in the form: hostName
+# rPort -- remote port
+# RESULT
+# * sock -- socket
+#****
+proc open_sock { rHost rPort } {
+ global ssh
+
+ if { $ssh } {
+ catch { set sock [socket localhost [expr $rPort + 10]] }
+ } else {
+ catch { set sock [socket $rHost $rPort] }
+ }
+ if { [info exists sock] } {
+ return $sock
+ } else {
+ return ""
+ }
+}
+
+#****f* exec.tcl/close_sock
+# NAME
+# close_sock -- close socket
+# SYNOPSIS
+# set sock [close_sock sock]
+# FUNCTION
+# Called upon ending remote execution. Closes a socket and returns an empty string.
+# INPUTS
+# sock -- socket that is being closed
+# RESULT
+# * sock -- an empty string
+#****
+proc close_sock { sock } {
+ catch { close $sock }
+ return ""
+}
+
+#****f* exec.tcl/rexec
+# NAME
+# rexec -- remote exec
+# SYNOPSIS
+# rexec io command
+# FUNCTION
+# Called upon remote execution of a command. Puts the command on the io, and reads the response
+# until a string Kraj is read. Returns all the received lines before string Kraj.
+# INPUTS
+# io -- socket on which the command is passed
+# command -- command that is remotly executed
+# RESULT
+# * response -- the command output
+#****
+proc rexec { io command } {
+ set response ""
+
+ puts $io $command
+ flush $io
+
+ gets $io line
+ if { $line == "Kraj rada" } {
+ close $io
+ }
+ if {$line != "Kraj" } {
+ set response $line
+ gets $io line
+ }
+ while { $line != "Kraj" } {
+ append response "\n" $line
+ gets $io line
+ }
+ return $response
+}
+
+#****f* exec.tcl/remoteStart
+# NAME
+# remoteStart -- remoteStart
+# SYNOPSIS
+# remoteStart
+# FUNCTION
+# Starts the remote execution. Reads the parameters from the gui, decides
+# to open an encrypted chanel or e reguar socket for remote execution.
+# If the sockets cannot be opened, a message box is displayed.
+#****
+proc remoteStart {} {
+ global monSock execSock mpid epid lmPort lePort editor_only ssh
+ global remote_exec exec_hosts exec_host
+
+ if { ! $remote_exec } { return }
+
+ set remote_exec false
+ set n [llength $exec_hosts]
+ for { set i 0 } { $i < $n } { incr i } {
+ if { [lindex [lindex $exec_hosts $i] 3] } {
+ set rHost [lindex [lindex $exec_hosts $i] 0]
+ set rePort [lindex [lindex $exec_hosts $i] 1]
+ set rmPort [lindex [lindex $exec_hosts $i] 2]
+ set ssh [lindex [lindex $exec_hosts $i] 4]
+ set userName [lindex [lindex $exec_hosts $i] 5]
+ set remote_exec true
+ set exec_host $rHost
+ break
+ }
+ }
+
+ if { ! $remote_exec } { return }
+
+
+ if { (![info exists mpid] || $mpid == "") && $ssh } {
+ set mpid [openFwrd [expr $rmPort + 10] $rmPort $userName@$rHost]
+ }
+ if { (![info exists epid] || $epid == "") && $ssh } {
+ set epid [openFwrd [expr $rePort + 10] $rePort $userName@$rHost]
+ }
+ after 500 { set t 1 }
+ vwait t
+ if { ![info exists monSock] || $monSock == "" } {
+ set monSock [open_sock $rHost $rmPort]
+ }
+ if { ![info exists execSock] || $execSock == "" } {
+ set execSock [open_sock $rHost $rePort]
+ }
+ if { $monSock == "" || $execSock == "" } {
+ set sel [tk_dialog .box "Socket problems" \
+ "Cannot open sockets" \
+ "" 0 "Retry" "Configure remote hosts" "Editor only mode" ]
+ switch $sel {
+ 0 {
+ remoteStart
+ }
+ 1 {
+ configRemoteHosts
+ }
+ 2 {
+ set editor_only true
+ }
+
+ }
+ }
+}
+
+#****f* exec.tcl/remoteClose
+# NAME
+# remoteClose
+# SYNOPSIS
+# remoteClose -- closes the remote execution
+# FUNCTION
+# Closes the remote execution of the experiment. Closes all the sockets.
+#****
+proc remoteClose { } {
+ global execSock monSock remote_exec mpid epid
+
+ if { $remote_exec } {
+ set execSock [close_sock $execSock]
+ set monSock [close_sock $monSock]
+ if { [info exists mpid] && ($mpid != "") } {
+ set mpid [closeFwrd $mpid]
+ }
+ if { [info exists epid] && ($epid != "") } {
+ set epid [closeFwrd $epid]
+ }
+ }
+ return
+}