618 lines
20 KiB
Tcl
618 lines
20 KiB
Tcl
|
#
|
||
|
# Copyright 2011-2013 the Boeing Company.
|
||
|
# See the LICENSE file included in this distribution.
|
||
|
#
|
||
|
|
||
|
set g_traffic_start_opt 0
|
||
|
set g_traffic_flows ""
|
||
|
|
||
|
# preset MGEN traffic pattern parameters
|
||
|
# fields are name [list dst params]
|
||
|
array set traffic_presets {
|
||
|
"00 1 kbps" {"" "PERIODIC \[1.0 125\]"}
|
||
|
"01 10 kbps" {"" "PERIODIC \[10.0 125\]"}
|
||
|
"02 100 kbps" {"" "PERIODIC \[10.0 1250\]"}
|
||
|
"03 512 kbps" {"" "PERIODIC \[50.0 1280\]"}
|
||
|
"04 POISSON 10 kbps" {"" "POISSON \[10.0 125\]"}
|
||
|
"05 POISSON 100 kbps" {"" "POISSON \[10.0 1250\]"}
|
||
|
"06 POISSON 512 kbps" {"" "POISSON \[50.0 1280\]"}
|
||
|
"07 3s fixed BURST 75kbps every 15s" {"" "BURST \[REGULAR 15.0 PERIODIC \[10.0 938\] FIXED 3.0\]"}
|
||
|
"08 0-5s random BURST 100kbps randomly every 10s" {"" "BURST \[RANDOM 10.0 PERIODIC \[10.0 1250\] EXP 5.0\]"}
|
||
|
"09 3s fixed BURST 256kbps randomly every 5s" {"" "BURST \[RANDOM 5.0 PERIODIC \[25.0 1280\] FIXED 3.0\]"}
|
||
|
"10 JITTER 10 kbps 0.05-0.15s" {"" "JITTER \[10.0 125 0.5\]"}
|
||
|
"11 JITTER 75 kbps 0.08-0.12s" {"" "JITTER \[10.0 938 0.2\]"}
|
||
|
"12 CLONE pcap file" {"" "CLONE \[tcpdump /tmp/source.pcap \[0\]\]"}
|
||
|
"13 CLONE pcap file continuous" {"" "CLONE \[tcpdump /tmp/source.pcap \[-1\]\]"}
|
||
|
"14 100 kbps multicast" {"224.225.1.1" "PERIODIC \[10.0 1250\]"}
|
||
|
"15 POISSON 384 kbps multicast" {"224.225.2.1" "POISSON \[40.0 1200\]"}
|
||
|
}
|
||
|
|
||
|
proc popupTrafficDialog {} {
|
||
|
global plugin_img_add plugin_img_edit plugin_img_del g_traffic_start_opt
|
||
|
global oper_mode
|
||
|
|
||
|
set wi .traffic1
|
||
|
catch {destroy $wi}
|
||
|
toplevel $wi
|
||
|
|
||
|
wm transient $wi .
|
||
|
wm resizable $wi 0 0
|
||
|
wm title $wi "CORE traffic flows"
|
||
|
|
||
|
if { ![info exists g_traffic_start_opt] } { set g_traffic_start_opt 0 }
|
||
|
|
||
|
labelframe $wi.f -text "Traffic flows"
|
||
|
listbox $wi.f.flows -selectmode extended -width 50 -exportselection 0 \
|
||
|
-yscrollcommand "$wi.f.flows_scroll set"
|
||
|
scrollbar $wi.f.flows_scroll -command "$wi.f.flows yview"
|
||
|
pack $wi.f.flows $wi.f.flows_scroll -pady 4 -fill both -side left
|
||
|
pack $wi.f -padx 4 -pady 4 -fill both -side top
|
||
|
bind $wi.f.flows <Double-Button-1> "trafficHelper $wi edit"
|
||
|
bind $wi.f.flows <<ListboxSelect>> "trafficHelper $wi sel"
|
||
|
|
||
|
frame $wi.bbar
|
||
|
button $wi.bbar.new -image $plugin_img_add -command "trafficHelper $wi new"
|
||
|
button $wi.bbar.save -image $plugin_img_edit \
|
||
|
-command "trafficHelper $wi edit"
|
||
|
button $wi.bbar.del -image $plugin_img_del -command "trafficHelper $wi del"
|
||
|
label $wi.bbar.help -text \
|
||
|
"Press the new button to define a new traffic flow."
|
||
|
|
||
|
pack $wi.bbar.new $wi.bbar.save $wi.bbar.del -side left
|
||
|
pack $wi.bbar.help -padx 8 -side left
|
||
|
pack $wi.bbar -padx 4 -pady 4 -fill both -side top
|
||
|
|
||
|
labelframe $wi.traf -text "Traffic options"
|
||
|
frame $wi.traf.opt
|
||
|
radiobutton $wi.traf.opt.opt1 -variable g_traffic_start_opt -value 0 \
|
||
|
-text "Do not start traffic flows automatically"
|
||
|
radiobutton $wi.traf.opt.opt2 -variable g_traffic_start_opt -value 1 \
|
||
|
-text "Start traffic flows after all nodes have booted"
|
||
|
radiobutton $wi.traf.opt.opt3 -variable g_traffic_start_opt -value 2 \
|
||
|
-text "Start traffic flows after routing has converged" -state disabled
|
||
|
pack $wi.traf.opt.opt1 $wi.traf.opt.opt2 $wi.traf.opt.opt3 \
|
||
|
-side top -anchor w
|
||
|
pack $wi.traf.opt -side top
|
||
|
frame $wi.traf.btn
|
||
|
set buttonstate disabled
|
||
|
if { $oper_mode == "exec" } { set buttonstate normal }
|
||
|
button $wi.traf.btn.start -text "Start all flows" \
|
||
|
-command startTrafficScripts -state $buttonstate
|
||
|
button $wi.traf.btn.stop -text "Stop all flows" \
|
||
|
-command stopTrafficScripts -state $buttonstate
|
||
|
button $wi.traf.btn.startsel -text "Start selected" \
|
||
|
-command "trafficHelper $wi start" -state $buttonstate
|
||
|
button $wi.traf.btn.stopsel -text "Stop selected" \
|
||
|
-command "trafficHelper $wi stop" -state $buttonstate
|
||
|
pack $wi.traf.btn.start $wi.traf.btn.stop $wi.traf.btn.startsel \
|
||
|
$wi.traf.btn.stopsel -side left
|
||
|
pack $wi.traf.btn -side top -fill x
|
||
|
pack $wi.traf -side top -fill x
|
||
|
|
||
|
# save/cancel buttons
|
||
|
frame $wi.b -borderwidth 4
|
||
|
button $wi.b.close -text "Close" -command \
|
||
|
".c delete withtag twonode; destroy $wi"
|
||
|
pack $wi.b.close -side bottom
|
||
|
pack $wi.b -side bottom
|
||
|
|
||
|
refreshTrafficList $wi
|
||
|
}
|
||
|
|
||
|
# helper for start, stop, delete selected, or add/modify flows
|
||
|
proc trafficHelper { wi cmd } {
|
||
|
set selected [$wi.f.flows curselection]
|
||
|
# listbox select
|
||
|
if { $cmd == "sel" } { .c delete withtag "twonode" }
|
||
|
# start/stop/delete selected
|
||
|
if { $cmd == "del" || $cmd == "sel" || $cmd == "start" || $cmd == "stop" } {
|
||
|
foreach i $selected {
|
||
|
set name [$wi.f.flows get $i]
|
||
|
if { $cmd == "del" } {
|
||
|
removeTrafficFlow $name
|
||
|
refreshTrafficList $wi
|
||
|
} elseif { $cmd == "sel" } {
|
||
|
set flow [getTrafficFlow $name]
|
||
|
set srcnode [lindex $flow 4]
|
||
|
if { $srcnode != "" } {
|
||
|
set tags "twonode $srcnode"
|
||
|
drawNodeCircle $srcnode 30 green $tags ""
|
||
|
}
|
||
|
set dstnode [lindex $flow 5]
|
||
|
if { $dstnode != "" } {
|
||
|
set tags "twonode $dstnode"
|
||
|
drawNodeCircle $dstnode 30 red $tags ""
|
||
|
}
|
||
|
} else {
|
||
|
set flow [getTrafficFlow $name]
|
||
|
if { $flow == "" } { continue }
|
||
|
startstopTrafficScript $flow $cmd
|
||
|
}
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
set selected [lindex $selected 0]
|
||
|
if { $selected == "" } {
|
||
|
set name ""
|
||
|
} else {
|
||
|
set name [$wi.f.flows get $selected]
|
||
|
}
|
||
|
if { $cmd == "edit" && $name == "" } { return }
|
||
|
if { $cmd == "new" } {
|
||
|
# TODO: find the next flow number and set the name
|
||
|
set name ""
|
||
|
}
|
||
|
popupTraffic2Dialog $name
|
||
|
}
|
||
|
|
||
|
proc refreshTrafficList { wi } {
|
||
|
global g_traffic_flows
|
||
|
|
||
|
$wi.f.flows delete 0 end
|
||
|
if { ![info exists g_traffic_flows] } { set g_traffic_flows "" }
|
||
|
|
||
|
foreach flow $g_traffic_flows {
|
||
|
set name [lindex $flow 0]
|
||
|
$wi.f.flows insert end $name
|
||
|
}
|
||
|
}
|
||
|
|
||
|
proc popupTraffic2Dialog { name } {
|
||
|
global g_twoNodeSelect g_twoNodeSelectCallback activetool
|
||
|
global traffic_flow_protocol traffic_presets
|
||
|
global g_traffic_pat
|
||
|
|
||
|
set wi .traffic
|
||
|
catch {destroy $wi}
|
||
|
toplevel $wi
|
||
|
|
||
|
set activetool select
|
||
|
|
||
|
wm transient $wi
|
||
|
wm resizable $wi 0 0
|
||
|
wm title $wi "Edit traffic flow"
|
||
|
|
||
|
set g_twoNodeSelect ""
|
||
|
set g_twoNodeSelectCallback selectTwoNodeTrafficCallback
|
||
|
|
||
|
labelframe $wi.e -text "Flow configuration"
|
||
|
|
||
|
frame $wi.e.flow -borderwidth 4
|
||
|
label $wi.e.flow.namel -text "name"
|
||
|
entry $wi.e.flow.name -bg white -width 20
|
||
|
label $wi.e.flow.numl -text "flow number"
|
||
|
entry $wi.e.flow.num -bg white -width 4
|
||
|
label $wi.e.flow.timestartl -text "start time"
|
||
|
entry $wi.e.flow.timestart -bg white -width 4
|
||
|
label $wi.e.flow.timestopl -text "stop time"
|
||
|
entry $wi.e.flow.timestop -bg white -width 4
|
||
|
pack $wi.e.flow.namel $wi.e.flow.name \
|
||
|
$wi.e.flow.numl $wi.e.flow.num $wi.e.flow.timestartl \
|
||
|
$wi.e.flow.timestart $wi.e.flow.timestopl $wi.e.flow.timestop -side left
|
||
|
pack $wi.e.flow -side top -fill both
|
||
|
|
||
|
# sending node
|
||
|
frame $wi.e.nodes -borderwidth 4
|
||
|
set sf $wi.e.nodes.src
|
||
|
labelframe $sf -text "source"
|
||
|
|
||
|
frame $sf.n -borderwidth 4
|
||
|
label $sf.n.srcl -text "source node"
|
||
|
radiobutton $sf.n.src -text " (none) " -variable g_twoNodeSelect \
|
||
|
-value "$sf.n.src" -indicatoron off -activebackground green \
|
||
|
-selectcolor green -padx 4 -pady 4
|
||
|
pack $sf.n.srcl $sf.n.src -side left -padx 4 -pady 4
|
||
|
pack $sf.n -side top -anchor w
|
||
|
|
||
|
frame $sf.ipp
|
||
|
button $sf.ipp.ipl -text "IP" -command \
|
||
|
"popupAddressPicker $sf.n.src $sf.ipp.ip"
|
||
|
entry $sf.ipp.ip -bg white -width 15
|
||
|
label $sf.ipp.pl -text "port"
|
||
|
entry $sf.ipp.p -bg white -width 5
|
||
|
pack $sf.ipp.ipl $sf.ipp.ip $sf.ipp.pl $sf.ipp.p -side left -padx 4 -pady 4
|
||
|
pack $sf.ipp -side top -anchor w
|
||
|
|
||
|
frame $sf.traff -borderwidth 4
|
||
|
label $sf.traff.protol -text "protocol"
|
||
|
tk_optionMenu $sf.traff.proto traffic_flow_protocol "TCP" "UDP" "SINK"
|
||
|
label $sf.traff.tosl -text "TOS"
|
||
|
entry $sf.traff.tos -bg white -width 5
|
||
|
pack $sf.traff.protol $sf.traff.proto $sf.traff.tosl \
|
||
|
$sf.traff.tos -side left
|
||
|
pack $sf.traff -side top
|
||
|
|
||
|
frame $sf.patt -borderwidth 4
|
||
|
label $sf.patt.patl -text "pattern"
|
||
|
set trafficpresetsMenu [tk_optionMenu $sf.patt.pat g_traffic_pat presets]
|
||
|
entry $sf.patt.p -bg white -width 20
|
||
|
pack $sf.patt.patl $sf.patt.pat $sf.patt.p -side left
|
||
|
pack $sf.patt -side top
|
||
|
|
||
|
frame $sf.log -borderwidth 4
|
||
|
label $sf.log.l -text "log file"
|
||
|
entry $sf.log.file -bg white -width 30
|
||
|
pack $sf.log.l $sf.log.file -side left
|
||
|
pack $sf.log -side top
|
||
|
|
||
|
# receiving node
|
||
|
set df $wi.e.nodes.dst
|
||
|
labelframe $df -text "destination"
|
||
|
|
||
|
frame $df.n -borderwidth 4
|
||
|
label $df.n.dstl -text "destination node"
|
||
|
radiobutton $df.n.dst -text " (none) " -variable g_twoNodeSelect \
|
||
|
-value "$df.n.dst" -indicatoron off -activebackground red \
|
||
|
-selectcolor red -padx 4 -pady 4
|
||
|
button $df.n.clear -text "clear" -command "$df.n.dst configure -text \" (none) \""
|
||
|
pack $df.n.dstl $df.n.dst $df.n.clear -side left -padx 4 -pady 4
|
||
|
pack $df.n -side top -anchor w
|
||
|
|
||
|
frame $df.ipp
|
||
|
button $df.ipp.ipl -text "IP" -command \
|
||
|
"popupAddressPicker $df.n.dst $df.ipp.ip"
|
||
|
entry $df.ipp.ip -bg white -width 15
|
||
|
label $df.ipp.pl -text "port"
|
||
|
entry $df.ipp.p -bg white -width 5
|
||
|
pack $df.ipp.ipl $df.ipp.ip $df.ipp.pl $df.ipp.p -side left -padx 4 -pady 4
|
||
|
pack $df.ipp -side top -anchor w
|
||
|
|
||
|
frame $df.log -borderwidth 4
|
||
|
label $df.log.l -text "log file"
|
||
|
entry $df.log.file -bg white -width 30
|
||
|
pack $df.log.l $df.log.file -side left
|
||
|
pack $df.log -side top
|
||
|
|
||
|
pack $sf $df -side left -fill both
|
||
|
pack $wi.e.nodes -side top -fill x
|
||
|
|
||
|
frame $wi.e.extra -borderwidth 4
|
||
|
label $wi.e.extra.lab -text "additional MGEN parameters"
|
||
|
entry $wi.e.extra.txt -bg white -width 40
|
||
|
pack $wi.e.extra.lab $wi.e.extra.txt -side left
|
||
|
pack $wi.e.extra -side top -fill x
|
||
|
|
||
|
pack $wi.e -side top
|
||
|
|
||
|
set g_traffic_pat presets
|
||
|
|
||
|
# save/cancel buttons
|
||
|
frame $wi.b -borderwidth 4
|
||
|
button $wi.b.apply -text "Apply" \
|
||
|
-command "popdownTrafficDialog $wi save \"$name\""
|
||
|
button $wi.b.cancel -text "Cancel" \
|
||
|
-command "popdownTrafficDialog $wi cancel \"$name\""
|
||
|
pack $wi.b.cancel $wi.b.apply -side right
|
||
|
pack $wi.b -side bottom
|
||
|
|
||
|
# populate traffic presets
|
||
|
$trafficpresetsMenu delete 0
|
||
|
foreach p [lsort -dictionary [array names traffic_presets]] {
|
||
|
set txt [string range $p 3 end]
|
||
|
$trafficpresetsMenu add radiobutton -label $txt -value $txt \
|
||
|
-variable g_traffic_pay \
|
||
|
-command "trafficPresets $wi \"$p\""
|
||
|
}
|
||
|
|
||
|
# default values
|
||
|
.c delete withtag "twonode"
|
||
|
set flow ""
|
||
|
if {$name != "" } { set flow [getTrafficFlow $name] }
|
||
|
if { $flow == "" } {
|
||
|
set flownum [nextTrafficFlowNumber]
|
||
|
$wi.e.flow.name insert 0 $name
|
||
|
$wi.e.flow.num insert 0 $flownum
|
||
|
$wi.e.flow.timestart insert 0 "0.0"
|
||
|
|
||
|
set traffic_flow_protocol "UDP"
|
||
|
$sf.ipp.p insert 0 "5000"
|
||
|
$df.ipp.p insert 0 "5000"
|
||
|
$df.log.file insert 0 "/var/log/mgen$flownum.log"
|
||
|
# load values from flow list
|
||
|
} else {
|
||
|
$wi.e.flow.name insert 0 [lindex $flow 0]
|
||
|
$wi.e.flow.num insert 0 [lindex $flow 1]
|
||
|
$wi.e.flow.timestart insert 0 [lindex $flow 2]
|
||
|
$wi.e.flow.timestop insert 0 [lindex $flow 3]
|
||
|
set srcnode [lindex $flow 4]
|
||
|
if { $srcnode != "" } {
|
||
|
set tags "twonode $srcnode twonode$sf.n.src"
|
||
|
$wi.e.nodes.src.n.src configure -text " $srcnode "
|
||
|
drawNodeCircle $srcnode 30 green $tags ""
|
||
|
}
|
||
|
set dstnode [lindex $flow 5]
|
||
|
if { $dstnode != "" } {
|
||
|
set tags "twonode $dstnode twonode$df.n.dst"
|
||
|
$wi.e.nodes.dst.n.dst configure -text " $dstnode "
|
||
|
drawNodeCircle $dstnode 30 red $tags ""
|
||
|
}
|
||
|
$wi.e.nodes.src.ipp.ip insert 0 [lindex $flow 6]
|
||
|
$wi.e.nodes.src.ipp.p insert 0 [lindex $flow 7]
|
||
|
$wi.e.nodes.src.log.file insert 0 [lindex $flow 8]
|
||
|
$wi.e.nodes.dst.ipp.ip insert 0 [lindex $flow 9]
|
||
|
$wi.e.nodes.dst.ipp.p insert 0 [lindex $flow 10]
|
||
|
$wi.e.nodes.dst.log.file insert 0 [lindex $flow 11]
|
||
|
set traffic_flow_protocol [lindex $flow 12]
|
||
|
$wi.e.nodes.src.traff.tos insert 0 [lindex $flow 13]
|
||
|
$wi.e.nodes.src.patt.p insert 0 [lindex $flow 14]
|
||
|
$wi.e.extra.txt insert 0 [lindex $flow 15]
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# fill in traffic pattern field when preset has been selected from menu
|
||
|
proc trafficPresets { wi preset } {
|
||
|
global traffic_presets
|
||
|
set patterndata $traffic_presets($preset)
|
||
|
set dst [lindex $patterndata 0]
|
||
|
set params [lindex $patterndata 1]
|
||
|
|
||
|
set sf $wi.e.nodes.src
|
||
|
$sf.patt.p delete 0 end
|
||
|
$sf.patt.p insert end $params
|
||
|
|
||
|
set df $wi.e.nodes.dst
|
||
|
if { $dst != "" } {
|
||
|
$df.ipp.ip delete 0 end
|
||
|
$df.ipp.ip insert end $dst
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# close the traffic window
|
||
|
proc popdownTrafficDialog { wi cmd oldname } {
|
||
|
global g_traffic_flows traffic_flow_protocol oper_mode
|
||
|
if { $cmd == "cancel" } {
|
||
|
.c delete withtag "twonode"
|
||
|
destroy $wi
|
||
|
return
|
||
|
}
|
||
|
# apply button was pressed
|
||
|
set num [$wi.e.flow.num get]
|
||
|
set name [$wi.e.flow.name get]
|
||
|
set start [$wi.e.flow.timestart get]
|
||
|
if { $start == "" || $start < 0.0 } { set start 0.0 }
|
||
|
set stop [$wi.e.flow.timestop get]
|
||
|
|
||
|
foreach n [list src dst] {
|
||
|
set ${n}node [string trim [$wi.e.nodes.$n.n.$n cget -text]]
|
||
|
set ${n}ip [$wi.e.nodes.$n.ipp.ip get]
|
||
|
set ${n}port [$wi.e.nodes.$n.ipp.p get]
|
||
|
set ${n}log [$wi.e.nodes.$n.log.file get]
|
||
|
|
||
|
}
|
||
|
set proto $traffic_flow_protocol
|
||
|
set tos [$wi.e.nodes.src.traff.tos get]
|
||
|
set pat [$wi.e.nodes.src.patt.p get]
|
||
|
set extra [$wi.e.extra.txt get]
|
||
|
|
||
|
if { $oldname != "" } { removeTrafficFlow $oldname }
|
||
|
|
||
|
set trafficentry [list "$name" $num "$start" "$stop" "$srcnode" "$dstnode" \
|
||
|
"$srcip" "$srcport" "$srclog" \
|
||
|
"$dstip" "$dstport" "$dstlog" \
|
||
|
"$proto" "$tos" "$pat" "$extra"]
|
||
|
lappend g_traffic_flows $trafficentry
|
||
|
refreshTrafficList .traffic1
|
||
|
.c delete withtag "twonode"
|
||
|
destroy $wi
|
||
|
if { $oper_mode == "exec" } {
|
||
|
set sock [lindex [getEmulPlugin $srcnode] 2]
|
||
|
sendTrafficScript $trafficentry $sock
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# called from editor.tcl:button1 when user clicks on a node
|
||
|
# search for IP address and populate
|
||
|
proc selectTwoNodeTrafficCallback { } {
|
||
|
set wi .traffic
|
||
|
|
||
|
if { ![winfo exists $wi] } { return }; # user has closed window
|
||
|
foreach n [list src dst] {
|
||
|
set node$n [string trim [$wi.e.nodes.$n.n.$n cget -text]]
|
||
|
if { [set node$n] == "(none)" } { set node$n "" }
|
||
|
$wi.e.nodes.$n.ipp.ip delete 0 end
|
||
|
}
|
||
|
$wi.e.nodes.src.ipp.ip insert 0 [getDestinationAddress $nodedst $nodesrc]
|
||
|
$wi.e.nodes.dst.ipp.ip insert 0 [getDestinationAddress $nodesrc $nodedst]
|
||
|
|
||
|
if { [$wi.e.flow.name get] == "" && $nodesrc != "" && $nodedst != "" } {
|
||
|
set num [$wi.e.flow.num get]
|
||
|
$wi.e.flow.name insert 0 "flow $num from $nodesrc to $nodedst"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
proc popupAddressPicker { ctl dstentry } {
|
||
|
set wi .addressPicker
|
||
|
|
||
|
set node [string trim [$ctl cget -text]]
|
||
|
|
||
|
catch {destroy $wi}
|
||
|
toplevel $wi
|
||
|
|
||
|
wm transient $wi
|
||
|
wm resizable $wi 0 0
|
||
|
wm title $wi "Select IP"
|
||
|
|
||
|
# listbox
|
||
|
labelframe $wi.a -text "IP addresses"
|
||
|
listbox $wi.a.addrs -selectmode single -width 16 -exportselection 0 \
|
||
|
-yscrollcommand "$wi.a.addrs_scroll set"
|
||
|
scrollbar $wi.a.addrs_scroll -command "$wi.a.addrs yview"
|
||
|
pack $wi.a.addrs $wi.a.addrs_scroll -pady 4 -fill both -side left
|
||
|
pack $wi.a -padx 4 -pady 4 -fill both -side top
|
||
|
bind $wi.a.addrs <Double-Button-1> "popdownAddressPicker $wi $dstentry"
|
||
|
|
||
|
# OK button
|
||
|
frame $wi.b -borderwidth 4
|
||
|
button $wi.b.ok -text "OK" -command "popdownAddressPicker $wi $dstentry"
|
||
|
pack $wi.b.ok $wi.b -side bottom
|
||
|
|
||
|
# populate the address list
|
||
|
if { $node == "" || $node == "(none)" } { return }
|
||
|
set dst [$dstentry get]
|
||
|
set i 0; set selected 0
|
||
|
foreach ifc [ifcList $node] {
|
||
|
set addr [lindex [split [getIfcIPv4addr $node $ifc] /] 0]
|
||
|
$wi.a.addrs insert end $addr
|
||
|
if { $addr == $dst } { set selected $i }
|
||
|
incr i
|
||
|
}
|
||
|
$wi.a.addrs selection set $selected
|
||
|
}
|
||
|
|
||
|
proc popdownAddressPicker { wi dstentry } {
|
||
|
$dstentry delete 0 end
|
||
|
set sel [$wi.a.addrs curselection]
|
||
|
if { $sel != "" } { $dstentry insert 0 [$wi.a.addrs get $sel] }
|
||
|
destroy $wi
|
||
|
}
|
||
|
|
||
|
proc nextTrafficFlowNumber { } {
|
||
|
global g_traffic_flows
|
||
|
set max 0
|
||
|
foreach flow $g_traffic_flows {
|
||
|
set n [lindex $flow 1]
|
||
|
if { $n > $max } { set max $n }
|
||
|
}
|
||
|
set next [expr {$max + 1}]
|
||
|
return $next
|
||
|
}
|
||
|
|
||
|
proc getTrafficFlow { name } {
|
||
|
global g_traffic_flows
|
||
|
foreach flow $g_traffic_flows {
|
||
|
if { [lindex $flow 0] == $name } { return $flow }
|
||
|
}
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
proc removeTrafficFlow { name } {
|
||
|
global g_traffic_flows
|
||
|
for { set i 0 } { $i < [llength $g_traffic_flows] } { incr i } {
|
||
|
set flow [lindex $g_traffic_flows $i]
|
||
|
if { [lindex $flow 0] == $name } {
|
||
|
set g_traffic_flows [lreplace $g_traffic_flows $i $i]
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
# returns a list of node numbers and MGEN scripts for a particular flow
|
||
|
proc getTrafficScripts { flow } {
|
||
|
if { $flow == "" } { return [list "" "" "" ""] }
|
||
|
|
||
|
set name [lindex $flow 0]
|
||
|
set num [lindex $flow 1]
|
||
|
set start [lindex $flow 2]
|
||
|
set stop [lindex $flow 3]
|
||
|
set srcnode [lindex $flow 4]
|
||
|
set dstnode [lindex $flow 5]
|
||
|
set srcip "" ;#[lindex $flow 6] source IP is currently ignored
|
||
|
set srcport [lindex $flow 7]
|
||
|
set srclog [lindex $flow 8]
|
||
|
set dstip [lindex $flow 9]
|
||
|
set dstport [lindex $flow 10]
|
||
|
set dstlog [lindex $flow 11]
|
||
|
set proto [lindex $flow 12]
|
||
|
set tos [lindex $flow 13]
|
||
|
set patt [lindex $flow 14]
|
||
|
set extra [lindex $flow 15]
|
||
|
|
||
|
foreach n [list src dst] {
|
||
|
if { [set ${n}ip] != "" } {
|
||
|
if { [set ${n}port] != "" } {
|
||
|
set n${n} "[set ${n}ip]/[set ${n}port]"
|
||
|
} else {
|
||
|
set n${n} [set ${n}ip]
|
||
|
}
|
||
|
} else { set n${n} [set ${n}port] }
|
||
|
}
|
||
|
if { $tos != "" } { set tos "TOS $tos " }
|
||
|
|
||
|
set s ""; set d ""
|
||
|
|
||
|
if { $srcnode != "" } {
|
||
|
set s "# CORE MGEN script: $name"
|
||
|
set s "$s\n$start ON $num $proto SRC $nsrc DST $ndst $patt $tos$extra"
|
||
|
}
|
||
|
if { $dstnode != "" } {
|
||
|
set d "# CORE MGEN script: $name"
|
||
|
if { [isMulticast $dstip] } {
|
||
|
set d "$d\n$start JOIN $dstip"
|
||
|
if { $dstport != "" } { set d "$d PORT $dstport" }
|
||
|
}
|
||
|
set d "$d\n$start LISTEN $proto $dstport"
|
||
|
}
|
||
|
|
||
|
if { $stop != "" } {
|
||
|
if { $s != "" } { set s "$s\n$stop OFF $num" }
|
||
|
if { $d != "" } {
|
||
|
set d "$d\n$stop IGNORE $proto $dstport"
|
||
|
if { [isMulticast $dstip] } {
|
||
|
set d "$d\n$stop LEAVE $dstip"
|
||
|
if { $dstport != "" } { set d "$d PORT $dstport" }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return [list $srcnode $dstnode "$s\n" "$d\n"]
|
||
|
}
|
||
|
|
||
|
# send File API messages to create traffic scripts on nodes
|
||
|
proc sendTrafficScripts { sock } {
|
||
|
global g_traffic_flows
|
||
|
foreach flow $g_traffic_flows { sendTrafficScript $flow $sock }
|
||
|
}
|
||
|
|
||
|
proc sendTrafficScript { flow sock } {
|
||
|
set scripts [getTrafficScripts $flow]
|
||
|
set srcnode [lindex $scripts 0]
|
||
|
set dstnode [lindex $scripts 1]
|
||
|
set flownum [lindex $flow 1]
|
||
|
set name "flow$flownum.mgn"
|
||
|
if { $srcnode != "" } {
|
||
|
set data [lindex $scripts 2]
|
||
|
set data_len [string length $data]
|
||
|
sendFileMessage $sock $srcnode "" $name "" $data $data_len
|
||
|
}
|
||
|
if { $dstnode != "" } {
|
||
|
set data [lindex $scripts 3]
|
||
|
set data_len [string length $data]
|
||
|
sendFileMessage $sock $dstnode "" $name "" $data $data_len
|
||
|
}
|
||
|
}
|
||
|
|
||
|
proc startTrafficScripts { } {
|
||
|
global g_traffic_flows
|
||
|
foreach flow $g_traffic_flows { startstopTrafficScript $flow start }
|
||
|
}
|
||
|
|
||
|
proc stopTrafficScripts { } {
|
||
|
global g_traffic_flows
|
||
|
foreach flow $g_traffic_flows { startstopTrafficScript $flow stop }
|
||
|
}
|
||
|
|
||
|
proc startstopTrafficScript { flow startstop } {
|
||
|
set flownum [lindex $flow 1]
|
||
|
set srcnode [lindex $flow 4]
|
||
|
set dstnode [lindex $flow 5]
|
||
|
set srclog [lindex $flow 8]
|
||
|
set dstlog [lindex $flow 11]
|
||
|
set name "flow$flownum.mgn"
|
||
|
set mgen "mgen" ;# assume mgen is in PATH, otherwise change this
|
||
|
|
||
|
# start receiving script first, then sender
|
||
|
foreach n [list dst src] {
|
||
|
set sock [lindex [getEmulPlugin [set ${n}node]] 2]
|
||
|
if { [set ${n}node] == "" || $sock == -1 } { continue }
|
||
|
if { $startstop == "start" } {
|
||
|
set cmd "$mgen instance [set ${n}node]$name input $name"
|
||
|
if { [set ${n}log] != "" } { set cmd "$cmd output [set ${n}log]" }
|
||
|
} else {
|
||
|
set cmd "$mgen instance [set ${n}node]$name stop"
|
||
|
}
|
||
|
sendExecMessage $sock [set ${n}node] $cmd 0 0
|
||
|
}
|
||
|
}
|
||
|
|