911 lines
25 KiB
Tcl
Executable file
911 lines
25 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.
|
|
#
|
|
# This work was supported in part by Croatian Ministry of Science
|
|
# and Technology through the research contract #IP-2003-143.
|
|
#
|
|
|
|
#****h* imunes/linkcfg.tcl
|
|
# NAME
|
|
# linkcfg.tcl -- file used for manipultaion with links in IMUNES
|
|
# FUNCTION
|
|
# This module is used to define all the actions used for configuring
|
|
# links in IMUNES.
|
|
#
|
|
# NOTES
|
|
#
|
|
# linkPeers { link_id }
|
|
# Returns node_ids of link endpoints
|
|
#
|
|
# linkByPeers { node1_id node2_id }
|
|
# Returns link_id whose peers are node1 and node2
|
|
#
|
|
# removeLink { link_id }
|
|
# Removes the link and related entries in peering node's configs
|
|
#
|
|
# getLinkBandwidth { link_id }
|
|
# ... in bits per second
|
|
#
|
|
# getLinkBandwidthString { link_id }
|
|
# ... as string
|
|
#
|
|
# getLinkDelay { link_id }
|
|
# ... in microseconds
|
|
#
|
|
# getLinkDelayString { link_id }
|
|
# ... as sting
|
|
#
|
|
# setLinkBandwidth { link_id bandwidth }
|
|
# ... in bits per second
|
|
#
|
|
# setLinkDelay { link_id delay }
|
|
# ... in microseconds
|
|
#
|
|
# All of the above functions are independent to any Tk objects. This means
|
|
# they can be used for implementing tasks external to GUI, yet inside the
|
|
# GUI any updating of related Tk objects (such as text labels etc.) will
|
|
# have to be implemented by additional Tk code.
|
|
#****
|
|
|
|
#****f* linkcfg.tcl/linkPeers
|
|
# NAME
|
|
# linkPeers -- get link's peer nodes
|
|
# SYNOPSIS
|
|
# set link_peers [linkPeers $link_id]
|
|
# FUNCTION
|
|
# Returns node_ids of link endpoints.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * link_peers -- returns nodes_ids of a link endpoints
|
|
# in a list {node1_id node2_id}
|
|
#****
|
|
|
|
proc linkPeers { link } {
|
|
global $link
|
|
|
|
set entry [lsearch -inline [set $link] "nodes {*}"]
|
|
return [lindex $entry 1]
|
|
}
|
|
|
|
#****f* linkcfg.tcl/linkByPeers
|
|
# NAME
|
|
# linkByPeers -- get link id from peer nodes
|
|
# SYNOPSIS
|
|
# set link_id [linkByPeers $node1_id $node2_id]
|
|
# FUNCTION
|
|
# Returns link_id whose peers are node1 and node2.
|
|
# The order of input nodes is irrelevant.
|
|
# INPUTS
|
|
# * node1_id -- node id of the first node
|
|
# * node2_id -- node id of the second node
|
|
# RESULT
|
|
# * link_id -- returns id of a link connecting endpoints
|
|
# node1_id node2_id.
|
|
#****
|
|
|
|
proc linkByPeers { node1 node2 } {
|
|
global link_list
|
|
|
|
foreach link $link_list {
|
|
set peers [linkPeers $link]
|
|
if { $peers == "$node1 $node2" || $peers == "$node2 $node1" } {
|
|
return $link
|
|
}
|
|
}
|
|
}
|
|
|
|
# same as linkByPeers but for links split across canvases
|
|
proc linkByPeersMirror { node1 node2 } {
|
|
foreach ifc [ifcList $node1] {
|
|
set link [lindex [linkByIfc $node1 $ifc] 0]
|
|
set mirror [getLinkMirror $link]
|
|
if { $mirror != "" } {
|
|
set peers [linkPeers $mirror]
|
|
# link node 1 is real node, link node 2 is always pseudo-node
|
|
if { [lindex $peers 0] == $node2 } {
|
|
return $link
|
|
}
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
#****f* linkcfg.tcl/removeLink
|
|
# NAME
|
|
# removeLink -- removes a link.
|
|
# SYNOPSIS
|
|
# removeLink $link_id
|
|
# FUNCTION
|
|
# Removes the link and related entries in peering node's configs.
|
|
# Updates the default route for peer nodes.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
#****
|
|
|
|
proc removeLink { link } {
|
|
global link_list $link
|
|
|
|
set pnodes [linkPeers $link]
|
|
foreach node $pnodes {
|
|
global $node
|
|
set i [lsearch $pnodes $node]
|
|
set peer [lreplace $pnodes $i $i]
|
|
set ifc [ifcByPeer $node $peer]
|
|
netconfClearSection $node "interface $ifc"
|
|
set i [lsearch [set $node] "interface-peer {$ifc $peer}"]
|
|
set $node [lreplace [set $node] $i $i]
|
|
}
|
|
set i [lsearch -exact $link_list $link]
|
|
set link_list [lreplace $link_list $i $i]
|
|
}
|
|
|
|
#****f* linkcfg.tcl/getLinkBandwidth
|
|
# NAME
|
|
# getLinkBandwidth -- get link bandwidth
|
|
# SYNOPSIS
|
|
# set bandwidth [getLinkBandwidth $link_id]
|
|
# FUNCTION
|
|
# Returns the link bandwidth expressed in bits per second.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * bandwidth -- The value of link bandwidth in bits per second.
|
|
#****
|
|
|
|
proc getLinkBandwidth { link } {
|
|
global $link
|
|
|
|
set entry [lsearch -inline [set $link] "bandwidth *"]
|
|
return [lindex $entry 1]
|
|
}
|
|
|
|
#****f* linkcfg.tcl/getLinkBandwidthString
|
|
# NAME
|
|
# getLinkBandwidthString -- get link bandwidth string
|
|
# SYNOPSIS
|
|
# set bandwidth_str [getLinkBandwidthString $link_id]
|
|
# FUNCTION
|
|
# Returns the link bandwidth in form of a number an a mesure unit.
|
|
# Measure unit is automaticaly asigned depending on the value of bandwidth.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * bandwidth_str -- The value of link bandwidth formated in a sting
|
|
# containing a measure unit.
|
|
#****
|
|
|
|
proc getLinkBandwidthString { link } {
|
|
global $link
|
|
set bandstr ""
|
|
set bandwidth [getLinkBandwidth $link]
|
|
if { $bandwidth > 0 } {
|
|
if { $bandwidth >= 660000000 } {
|
|
set bandstr "[format %.2f [expr {$bandwidth / 1000000000.0}]] Gbps"
|
|
} elseif { $bandwidth >= 99000000 } {
|
|
set bandstr "[format %d [expr {$bandwidth / 1000000}]] Mbps"
|
|
} elseif { $bandwidth >= 9900000 } {
|
|
set bandstr "[format %.2f [expr {$bandwidth / 1000000.0}]] Mbps"
|
|
} elseif { $bandwidth >= 990000 } {
|
|
set bandstr "[format %d [expr {$bandwidth / 1000}]] Kbps"
|
|
} elseif { $bandwidth >= 9900 } {
|
|
set bandstr "[format %.2f [expr {$bandwidth / 1000.0}]] Kbps"
|
|
} else {
|
|
set bandstr "$bandwidth bps"
|
|
}
|
|
}
|
|
return $bandstr
|
|
}
|
|
|
|
#****f* linkcfg.tcl/setLinkBandwidth
|
|
# NAME
|
|
# setLinkBandwidth -- set link bandwidth
|
|
# SYNOPSIS
|
|
# setLinkBandwidth $link_id $value
|
|
# FUNCTION
|
|
# Sets the link bandwidth in a bits per second.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# * value -- link bandwidth in bits per second.
|
|
#****
|
|
|
|
proc setLinkBandwidth { link value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "bandwidth *"]
|
|
if { $value <= 0 } {
|
|
set $link [lreplace [set $link] $i $i]
|
|
} else {
|
|
set $link [lreplace [set $link] $i $i "bandwidth $value"]
|
|
}
|
|
}
|
|
|
|
#
|
|
# Marko - XXX document!
|
|
#
|
|
proc getLinkColor { link } {
|
|
global $link defLinkColor
|
|
|
|
set entry [lsearch -inline [set $link] "color *"]
|
|
if { $entry == "" } {
|
|
return $defLinkColor
|
|
} else {
|
|
return [lindex $entry 1]
|
|
}
|
|
}
|
|
|
|
proc setLinkColor { link value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "color *"]
|
|
set $link [lreplace [set $link] $i $i "color $value"]
|
|
}
|
|
|
|
proc getLinkWidth { link } {
|
|
global $link defLinkWidth
|
|
|
|
set entry [lsearch -inline [set $link] "width *"]
|
|
if { $entry == "" } {
|
|
return $defLinkWidth
|
|
} else {
|
|
return [lindex $entry 1]
|
|
}
|
|
}
|
|
|
|
proc setLinkWidth { link value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "width *"]
|
|
set $link [lreplace [set $link] $i $i "width $value"]
|
|
}
|
|
|
|
#****f* linkcfg.tcl/getLinkDelay
|
|
# NAME
|
|
# getLinkDelay -- get link delay
|
|
# SYNOPSIS
|
|
# set delay [getLinkDelay $link_id]
|
|
# FUNCTION
|
|
# Returns the link delay expressed in microseconds.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * delay -- The value of link delay in microseconds.
|
|
#****
|
|
|
|
proc getLinkDelay { link } {
|
|
global $link
|
|
|
|
set entry [lsearch -inline [set $link] "delay *"]
|
|
return [lindex $entry 1]
|
|
}
|
|
|
|
#****f* linkcfg.tcl/getLinkDelayString
|
|
# NAME
|
|
# getLinkDelayString -- get link delay string
|
|
# SYNOPSIS
|
|
# set delay [getLinkDelayString $link_id]
|
|
# FUNCTION
|
|
# Returns the link delay as a string with avalue and measure unit.
|
|
# Measure unit is automaticaly asigned depending on the value of delay.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * delay -- The value of link delay formated in a string
|
|
# containing a measure unit.
|
|
#****
|
|
|
|
proc getLinkDelayString { link } {
|
|
global $link
|
|
|
|
set delay [getLinkDelay $link]
|
|
if { "$delay" != "" } {
|
|
if { $delay >= 10000 } {
|
|
set delstr "[expr {$delay / 1000}] ms"
|
|
} elseif { $delay >= 1000 } {
|
|
set delstr "[expr {$delay * .001}] ms"
|
|
} else {
|
|
set delstr "$delay us"
|
|
}
|
|
} else {
|
|
set delstr ""
|
|
}
|
|
return $delstr
|
|
}
|
|
|
|
#****f* linkcfg.tcl/setLinkDelay
|
|
# NAME
|
|
# setLinkDelay -- set link delay
|
|
# SYNOPSIS
|
|
# setLinkDelay $link_id $value
|
|
# FUNCTION
|
|
# Sets the link delay in microseconds.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# * value -- link delay value in microseconds.
|
|
#****
|
|
|
|
proc setLinkDelay { link value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "delay *"]
|
|
if { $value <= 0 } {
|
|
set $link [lreplace [set $link] $i $i]
|
|
} else {
|
|
set $link [lreplace [set $link] $i $i "delay $value"]
|
|
}
|
|
}
|
|
|
|
#****f* linkcfg.tcl/getLinkBER
|
|
# NAME
|
|
# getLinkBER -- get link BER
|
|
# SYNOPSIS
|
|
# set BER [getLinkBER $link_id]
|
|
# FUNCTION
|
|
# Returns 1/BER value of the link.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * BER -- The value of 1/BER of the link.
|
|
#****
|
|
|
|
proc getLinkBER { link } {
|
|
global $link
|
|
|
|
set entry [lsearch -inline [set $link] "ber *"]
|
|
return [lindex $entry 1]
|
|
}
|
|
|
|
#****f* linkcfg.tcl/setLinkBER
|
|
# NAME
|
|
# setLinkBER -- set link BER
|
|
# SYNOPSIS
|
|
# setLinkBER $link_id value
|
|
# FUNCTION
|
|
# Sets the BER value of the link.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# * value -- The value of 1/BER of the link.
|
|
#****
|
|
|
|
proc setLinkBER { link value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "ber *"]
|
|
if { $value <= 0 } {
|
|
set $link [lreplace [set $link] $i $i]
|
|
} else {
|
|
set $link [lreplace [set $link] $i $i "ber $value"]
|
|
}
|
|
}
|
|
|
|
#****f* linkcfg.tcl/getLinkDup
|
|
# NAME
|
|
# getLinkDup -- get link packet duplicate value
|
|
# SYNOPSIS
|
|
# set duplicate [getLinkDup $link_id]
|
|
# FUNCTION
|
|
# Returns the value of the link duplicate percentage.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * duplicate -- The percentage of the link packet duplicate value.
|
|
#****
|
|
|
|
proc getLinkDup { link } {
|
|
global $link
|
|
|
|
set entry [lsearch -inline [set $link] "duplicate *"]
|
|
return [lindex $entry 1]
|
|
}
|
|
|
|
#****f* linkcfg.tcl/setLinkDup
|
|
# NAME
|
|
# setLinkDup -- set link packet duplicate value
|
|
# SYNOPSIS
|
|
# setLinkDup $link_id $value
|
|
# FUNCTION
|
|
# Set link packet duplicate percentage.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# * value -- The percentage of the link packet duplicate value.
|
|
#****
|
|
|
|
proc setLinkDup { link value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "duplicate *"]
|
|
if { $value <= 0 || $value > 50 } {
|
|
set $link [lreplace [set $link] $i $i]
|
|
} else {
|
|
set $link [lreplace [set $link] $i $i "duplicate $value"]
|
|
}
|
|
}
|
|
|
|
#****f* linkcfg.tcl/getLinkMirror
|
|
# NAME
|
|
# getLinkMirror -- get link's mirror link
|
|
# SYNOPSIS
|
|
# set mirror_link_id [getLinkMirror $link_id]
|
|
# FUNCTION
|
|
# Returns the value of the link's mirror link. Mirror link is the other
|
|
# part of the link connecting node to a pseudo node. Two mirror links
|
|
# present only one physical link.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * mirror_link_id -- Mirror link id
|
|
#****
|
|
|
|
proc getLinkMirror { link } {
|
|
global $link
|
|
|
|
set entry [lsearch -inline [set $link] "mirror *"]
|
|
return [lindex $entry 1]
|
|
}
|
|
|
|
#****f* linkcfg.tcl/setLinkMirror
|
|
# NAME
|
|
# setLinkMirror -- set link's mirror link
|
|
# SYNOPSIS
|
|
# setLinkMirror $link_id $mirror_link_id
|
|
# FUNCTION
|
|
# Sets the value of the link's mirror link. Mirror link is the other
|
|
# part of the link connecting node to a pseudo node. Two mirror links
|
|
# present only one physical link.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# RESULT
|
|
# * mirror_link_id -- Mirror link id
|
|
#****
|
|
|
|
proc setLinkMirror { link value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "mirror *"]
|
|
if { $value == "" } {
|
|
set $link [lreplace [set $link] $i $i]
|
|
} else {
|
|
set $link [lreplace [set $link] $i $i "mirror $value"]
|
|
}
|
|
}
|
|
|
|
#****f* linkcfg.tcl/splitLink
|
|
# NAME
|
|
# splitLink -- slit the link
|
|
# SYNOPSIS
|
|
# set nodes [splitLink $link_id $nodetype]
|
|
# FUNCTION
|
|
# Splits the link in two parts. Each part of the split link is one
|
|
# pseudo link.
|
|
# INPUTS
|
|
# * link_id -- link id
|
|
# * nodetype -- type of the new nodes connecting slit links.
|
|
# Usual value is pseudo.
|
|
# RESULT
|
|
# * nodes -- list of node ids of new nodes.
|
|
#****
|
|
|
|
proc splitLink { link nodetype } {
|
|
global link_list $link
|
|
|
|
set orig_nodes [linkPeers $link]
|
|
set orig_node1 [lindex $orig_nodes 0]
|
|
set orig_node2 [lindex $orig_nodes 1]
|
|
set new_node1 [newNode $nodetype]
|
|
set new_node2 [newNode $nodetype]
|
|
set new_link1 [newObjectId link]
|
|
lappend link_list $new_link1
|
|
set new_link2 [newObjectId link]
|
|
lappend link_list $new_link2
|
|
set ifc1 [ifcByPeer $orig_node1 $orig_node2]
|
|
set ifc2 [ifcByPeer $orig_node2 $orig_node1]
|
|
|
|
global $orig_node1 $orig_node2 $new_node1 $new_node2
|
|
global $new_link1 $new_link2
|
|
set $new_link1 {}
|
|
set $new_link2 {}
|
|
|
|
set i [lsearch [set $orig_node1] "interface-peer {* $orig_node2}"]
|
|
set $orig_node1 [lreplace [set $orig_node1] $i $i \
|
|
"interface-peer {$ifc1 $new_node1}"]
|
|
set i [lsearch [set $orig_node2] "interface-peer {* $orig_node1}"]
|
|
set $orig_node2 [lreplace [set $orig_node2] $i $i \
|
|
"interface-peer {$ifc2 $new_node2}"]
|
|
|
|
lappend $new_link1 "nodes {$orig_node1 $new_node1}"
|
|
lappend $new_link2 "nodes {$orig_node2 $new_node2}"
|
|
|
|
setNodeCanvas $new_node1 [getNodeCanvas $orig_node1]
|
|
setNodeCanvas $new_node2 [getNodeCanvas $orig_node2]
|
|
setNodeCoords $new_node1 [getNodeCoords $orig_node2]
|
|
setNodeCoords $new_node2 [getNodeCoords $orig_node1]
|
|
if { $nodetype != "pseudo" } {
|
|
setNodeLabelCoords $new_node1 [getNodeLabelCoords $orig_node2]
|
|
setNodeLabelCoords $new_node2 [getNodeLabelCoords $orig_node1]
|
|
} else {
|
|
setNodeLabelCoords $new_node1 [getNodeCoords $orig_node2]
|
|
setNodeLabelCoords $new_node2 [getNodeCoords $orig_node1]
|
|
}
|
|
lappend $new_node1 "interface-peer {0 $orig_node1}"
|
|
lappend $new_node2 "interface-peer {0 $orig_node2}"
|
|
|
|
setLinkBandwidth $new_link1 [getLinkBandwidth $link]
|
|
setLinkBandwidth $new_link2 [getLinkBandwidth $link]
|
|
setLinkDelay $new_link1 [getLinkDelay $link]
|
|
setLinkDelay $new_link2 [getLinkDelay $link]
|
|
setLinkBER $new_link1 [getLinkBER $link]
|
|
setLinkBER $new_link2 [getLinkBER $link]
|
|
setLinkDup $new_link1 [getLinkDup $link]
|
|
setLinkDup $new_link2 [getLinkDup $link]
|
|
|
|
set i [lsearch -exact $link_list $link]
|
|
set link_list [lreplace $link_list $i $i]
|
|
|
|
return "$new_node1 $new_node2"
|
|
}
|
|
|
|
#****f* linkcfg.tcl/mergeLink
|
|
# NAME
|
|
# mergeLink -- merge the link
|
|
# SYNOPSIS
|
|
# set new_link_id [mergeLink $link_id]
|
|
# FUNCTION
|
|
# Rebuilts a link from two pseudo link.
|
|
# INPUTS
|
|
# * link_id -- pseudo link id
|
|
# RESULT
|
|
# * new_link_id -- rebuilt link id.
|
|
#****
|
|
|
|
proc mergeLink { link } {
|
|
global link_list node_list
|
|
|
|
set mirror_link [getLinkMirror $link]
|
|
if { $mirror_link == "" } {
|
|
puts "XXX mergeLink called for non-pseudo link!!!"
|
|
return
|
|
}
|
|
set link1_peers [linkPeers $link]
|
|
set link2_peers [linkPeers $mirror_link]
|
|
set orig_node1 [lindex $link1_peers 0]
|
|
set orig_node2 [lindex $link2_peers 0]
|
|
set pseudo_node1 [lindex $link1_peers 1]
|
|
set pseudo_node2 [lindex $link2_peers 1]
|
|
set new_link [newObjectId link]
|
|
global $orig_node1 $orig_node2
|
|
global $new_link
|
|
|
|
set ifc1 [ifcByPeer $orig_node1 $pseudo_node1]
|
|
set ifc2 [ifcByPeer $orig_node2 $pseudo_node2]
|
|
set i [lsearch [set $orig_node1] "interface-peer {* $pseudo_node1}"]
|
|
set $orig_node1 [lreplace [set $orig_node1] $i $i \
|
|
"interface-peer {$ifc1 $orig_node2}"]
|
|
set i [lsearch [set $orig_node2] "interface-peer {* $pseudo_node2}"]
|
|
set $orig_node2 [lreplace [set $orig_node2] $i $i \
|
|
"interface-peer {$ifc2 $orig_node1}"]
|
|
|
|
set $new_link {}
|
|
lappend $new_link "nodes {$orig_node1 $orig_node2}"
|
|
|
|
setLinkBandwidth $new_link [getLinkBandwidth $link]
|
|
setLinkDelay $new_link [getLinkDelay $link]
|
|
setLinkBER $new_link [getLinkBER $link]
|
|
setLinkDup $new_link [getLinkDup $link]
|
|
|
|
set i [lsearch -exact $link_list $link]
|
|
set link_list [lreplace $link_list $i $i]
|
|
set i [lsearch -exact $link_list $mirror_link]
|
|
set link_list [lreplace $link_list $i $i]
|
|
lappend link_list $new_link
|
|
|
|
set i [lsearch -exact $node_list $pseudo_node1]
|
|
set node_list [lreplace $node_list $i $i]
|
|
set i [lsearch -exact $node_list $pseudo_node2]
|
|
set node_list [lreplace $node_list $i $i]
|
|
|
|
return $new_link
|
|
}
|
|
|
|
#****f* linkcfg.tcl/newLink
|
|
# NAME
|
|
# newLink -- create new link
|
|
# SYNOPSIS
|
|
# set new_link_id [newLink $node1_id $node2_id]
|
|
# FUNCTION
|
|
# Creates a new link between nodes node1_id and node2_id. The order of
|
|
# nodes is irrelevant.
|
|
# INPUTS
|
|
# * node1_id -- node id of the peer node
|
|
# * node2_id -- node id of the second peer node
|
|
# RESULT
|
|
# * new_link_id -- new link id.
|
|
#****
|
|
|
|
proc newLink { lnode1 lnode2 } {
|
|
global link_list
|
|
global $lnode1 $lnode2
|
|
global defEthBandwidth defSerBandwidth defSerDelay
|
|
global defLinkColor defLinkWidth
|
|
global curcanvas
|
|
global systype
|
|
|
|
if { [nodeType $lnode1] == "lanswitch" && \
|
|
[nodeType $lnode2] != "router" && \
|
|
[nodeType $lnode2] != "lanswitch" } { set regular no }
|
|
if { [nodeType $lnode2] == "lanswitch" && \
|
|
[nodeType $lnode1] != "router" && \
|
|
[nodeType $lnode1] != "lanswitch" } { set regular no }
|
|
if { [nodeType $lnode1] == "hub" && \
|
|
[nodeType $lnode2] == "hub" } { set regular no }
|
|
# Boeing: added tunnel, ktunnel types to behave as rj45
|
|
if { [nodeType $lnode1] == "rj45" || [nodeType $lnode2] == "rj45" || \
|
|
[nodeType $lnode1] == "tunnel" || [nodeType $lnode2] == "tunnel" || \
|
|
[nodeType $lnode1] == "ktunnel" || [nodeType $lnode2] == "ktunnel" } {
|
|
if { [nodeType $lnode1] == "rj45" || [nodeType $lnode1] == "tunnel" || \
|
|
[nodeType $lnode1] == "ktunnel" } {
|
|
set rj45node $lnode1
|
|
set othernode $lnode2
|
|
} else {
|
|
set rj45node $lnode2
|
|
set othernode $lnode1
|
|
}
|
|
# only allowed to link with certain types
|
|
if { [lsearch {router lanswitch hub pc host wlan} \
|
|
[nodeType $othernode]] < 0} {
|
|
return
|
|
}
|
|
# check if already linked to something else
|
|
if { [lsearch [set $rj45node] "interface-peer *"] > 0 } {
|
|
return
|
|
}
|
|
}
|
|
# Boeing: wlan node is always first of the two nodes
|
|
if { [nodeType $lnode2] == "wlan" } {
|
|
set tmp $lnode1
|
|
set lnode1 $lnode2
|
|
set lnode2 $tmp
|
|
}
|
|
# end Boeing
|
|
|
|
set link [newObjectId link]
|
|
global $link
|
|
set $link {}
|
|
|
|
# pick new interface names or use names from global hint
|
|
set do_auto_addressing 1
|
|
global g_newLink_ifhints
|
|
if { [info exists g_newLink_ifhints] && $g_newLink_ifhints != "" } {
|
|
set ifname1 [lindex $g_newLink_ifhints 0]
|
|
set ifname2 [lindex $g_newLink_ifhints 1]
|
|
set do_auto_addressing 0
|
|
set g_newLink_ifhints ""
|
|
} else {
|
|
set ifname1 [newIfc [chooseIfName $lnode1 $lnode2] $lnode1]
|
|
set ifname2 [newIfc [chooseIfName $lnode2 $lnode1] $lnode2]
|
|
}
|
|
lappend $lnode1 "interface-peer {$ifname1 $lnode2}"
|
|
lappend $lnode2 "interface-peer {$ifname2 $lnode1}"
|
|
# check for existing interface config (supported by API)
|
|
# this allows for interfaces/addresses to be configured before the link
|
|
# is created
|
|
set ipv4_addr1 [getIfcIPv4addr $lnode1 $ifname1]
|
|
set ipv6_addr1 [getIfcIPv6addr $lnode1 $ifname1]
|
|
set ipv4_addr2 [getIfcIPv4addr $lnode2 $ifname2]
|
|
set ipv6_addr2 [getIfcIPv6addr $lnode2 $ifname2]
|
|
|
|
lappend $link "nodes {$lnode1 $lnode2}"
|
|
# parameters for links to wlan are based on wlan parameters
|
|
if { [nodeType $lnode1] == "wlan" } {
|
|
set bandwidth [getLinkBandwidth $lnode1]
|
|
set delay [getLinkDelay $lnode1]
|
|
set model [netconfFetchSection $lnode1 "mobmodel"]
|
|
if { $bandwidth != "" } {
|
|
lappend $link "bandwidth [getLinkBandwidth $lnode1]"
|
|
}
|
|
set ipv4_addr1 [getIfcIPv4addr $lnode1 wireless]
|
|
if { $ipv4_addr1 == "" } { ;# allocate WLAN address now
|
|
setIfcIPv4addr $lnode1 wireless "[findFreeIPv4Net 32].0/32"
|
|
}
|
|
set ipv6_addr1 [getIfcIPv6addr $lnode1 wireless]
|
|
if { $ipv6_addr1 == "" } {
|
|
setIfcIPv6addr $lnode1 wireless "[findFreeIPv6Net 128]::0/128"
|
|
}
|
|
if { [string range $model 0 6] == "coreapi" } {
|
|
set delay 0; # delay controlled by wireless module
|
|
} elseif {$delay != ""} {
|
|
if { [lindex $systype 0] == "FreeBSD" } {
|
|
lappend $link "delay [expr $delay/2]"
|
|
} else {
|
|
lappend $link "delay $delay"
|
|
}
|
|
}
|
|
if { [[typemodel $lnode2].layer] == "NETWORK" } {
|
|
if { $ipv4_addr2 == "" } { autoIPv4addr $lnode2 $ifname2 }
|
|
if { $ipv6_addr2 == "" } { autoIPv6addr $lnode2 $ifname2 }
|
|
}
|
|
# tunnels also excluded from link settings
|
|
} elseif { ([nodeType $lnode1] == "lanswitch" || \
|
|
[nodeType $lnode2] == "lanswitch" || \
|
|
[string first eth "$ifname1 $ifname2"] != -1) && \
|
|
[nodeType $lnode1] != "rj45" && [nodeType $lnode2] != "rj45" && \
|
|
[nodeType $lnode1] != "tunnel" && [nodeType $lnode2] != "tunnel" && \
|
|
[nodeType $lnode1] != "ktunnel" && [nodeType $lnode2] != "ktunnel" } {
|
|
lappend $link "bandwidth $defEthBandwidth"
|
|
} elseif { [string first ser "$ifname1 $ifname2"] != -1 } {
|
|
lappend $link "bandwidth $defSerBandwidth"
|
|
lappend $link "delay $defSerDelay"
|
|
}
|
|
|
|
lappend link_list $link
|
|
|
|
if { [nodeType $lnode2] != "pseudo" &&
|
|
[nodeType $lnode1] != "wlan" &&
|
|
[[typemodel $lnode1].layer] == "NETWORK" } {
|
|
if { $ipv4_addr1 == "" && $do_auto_addressing } {
|
|
autoIPv4addr $lnode1 $ifname1
|
|
}
|
|
if { $ipv6_addr1 == "" && $do_auto_addressing } {
|
|
autoIPv6addr $lnode1 $ifname1
|
|
}
|
|
}
|
|
# assume wlan is always lnode1
|
|
if { [nodeType $lnode1] != "pseudo" &&
|
|
[nodeType $lnode1] != "wlan" &&
|
|
[[typemodel $lnode2].layer] == "NETWORK" } {
|
|
if { $ipv4_addr2 == "" && $do_auto_addressing } {
|
|
autoIPv4addr $lnode2 $ifname2
|
|
}
|
|
if { $ipv6_addr2 == "" && $do_auto_addressing } {
|
|
autoIPv6addr $lnode2 $ifname2
|
|
}
|
|
}
|
|
|
|
# tunnel address based on its name
|
|
if { [nodeType $lnode1] == "tunnel" } {
|
|
set ipaddr "[getNodeName $lnode1]/24"
|
|
setIfcIPv4addr $lnode1 e0 $ipaddr
|
|
}
|
|
if { [nodeType $lnode2] == "tunnel" } {
|
|
set ipaddr "[getNodeName $lnode2]/24"
|
|
setIfcIPv4addr $lnode2 e0 $ipaddr
|
|
}
|
|
|
|
return $link
|
|
}
|
|
|
|
#****f* linkcfg.tcl/linkByIfc
|
|
# NAME
|
|
# linkByIfg -- get link by interface
|
|
# SYNOPSIS
|
|
# set link_id [linkByIfc $node_id $fc]
|
|
# FUNCTION
|
|
# Returns the link id of the link connecting the node's interface
|
|
# INPUTS
|
|
# * node_id -- node id
|
|
# * ifc -- interface
|
|
# RESULT
|
|
# * link_id -- link id.
|
|
#****
|
|
|
|
proc linkByIfc { node ifc } {
|
|
global link_list
|
|
|
|
set peer [peerByIfc $node $ifc]
|
|
set dir ""
|
|
foreach link $link_list {
|
|
set endpoints [linkPeers $link]
|
|
if { $endpoints == "$node $peer" } {
|
|
set dir downstream
|
|
break
|
|
}
|
|
if { $endpoints == "$peer $node" } {
|
|
set dir upstream
|
|
break
|
|
}
|
|
}
|
|
if { $dir == "" } {
|
|
puts "*** linkByIfc error: node=$node ifc=$ifc"
|
|
}
|
|
|
|
return [list $link $dir]
|
|
}
|
|
|
|
# Boeing: jitter
|
|
proc getLinkJitter { link } {
|
|
global $link
|
|
|
|
set entry [lsearch -inline [set $link] "jitter *"]
|
|
return [lindex $entry 1]
|
|
}
|
|
|
|
proc setLinkJitter { link value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "jitter *"]
|
|
if { $value <= 0 } {
|
|
set $link [lreplace [set $link] $i $i]
|
|
} else {
|
|
set $link [lreplace [set $link] $i $i "jitter $value"]
|
|
}
|
|
}
|
|
|
|
# get any type of link attribute
|
|
proc getLinkOpaque { link key } {
|
|
global $link
|
|
|
|
set entry [lsearch -inline [set $link] "$key *"]
|
|
return [lindex $entry 1]
|
|
}
|
|
|
|
# set any type of link attribute
|
|
# passing in a value <= 0 or "" will delete this key
|
|
proc setLinkOpaque { link key value } {
|
|
global $link
|
|
|
|
set i [lsearch [set $link] "$key *"]
|
|
if { $value <= 0 } {
|
|
set $link [lreplace [set $link] $i $i]
|
|
} else {
|
|
set $link [lreplace [set $link] $i $i "$key $value"]
|
|
}
|
|
}
|
|
|
|
#
|
|
# change GUI attributes for a link (width, color, dash)
|
|
#
|
|
proc updateLinkGuiAttr { link attr } {
|
|
global defLinkColor defLinkWidth
|
|
|
|
if { $attr == "" } { return }
|
|
|
|
foreach a $attr {
|
|
set kv [split $a =]
|
|
set key [lindex $kv 0]
|
|
set value [lindex $kv 1]
|
|
|
|
switch -exact -- $key {
|
|
width {
|
|
if { $value == "" } { set value $defLinkWidth }
|
|
setLinkWidth $link $value
|
|
.c itemconfigure "link && $link" -width [getLinkWidth $link]
|
|
}
|
|
color {
|
|
setLinkColor $link $value
|
|
.c itemconfigure "link && $link" -fill [getLinkColor $link]
|
|
}
|
|
dash {
|
|
.c itemconfigure "link && $link" -dash $value
|
|
}
|
|
default {
|
|
puts "warning: unsupported GUI link attribute: $key"
|
|
}
|
|
} ;# end switch
|
|
} ;# end foreach attr
|
|
}
|
|
|