Commit 8a303684 authored by Kevin Atkinson's avatar Kevin Atkinson

Merge branch 'oml'


parents 2ae5f2cd 7bd2dd0f
......@@ -102,6 +102,12 @@ proc tb-fix-interface {vnode lanlink iface} {}
proc tb-set-node-usesharednode {node weight} {}
proc tb-set-node-sharingmode {node sharemode} {}
#add for OML
proc tb-set-use-oml {args} {}
proc tb-set-oml-server {node} {}
proc tb-set-oml-mp {args} {}
proc tb-set-oml-use-control {args} {}
proc tb-set-security-level {level} {
switch -- $level {
......@@ -424,7 +424,20 @@ Simulator instproc run {} {
var_import ::GLOBALS::optarray_order
var_import ::GLOBALS::optarray_count
var_import ::GLOBALS::dpdb
#for oml begin
var_import ::TBCOMPAT::oml_use_control
if { $oml_use_control == 0 } {
set ::TBCOMPAT::nodelist [list]
foreach node [lsort [array names node_list]] {
lappend ::TBCOMPAT::nodelist $node
uplevel #0 { set omllan [$ns make-lan ${::TBCOMPAT::nodelist} 100Mb 0ms] }
#for oml end
if {$ran == 1} {
perror "The Simulator 'run' statement can only be run once."
......@@ -139,6 +139,19 @@ namespace eval TBCOMPAT {
variable EINEVALUE {^([-\w\.\+\,\s\/]+)$}
variable EINEORDER {^\d+$}
# OML measurement stuff.
set oml_mps {}
# OML-server listening port.
set oml_server_port 8000
# OML-server node.
set omlserver omlserver
# flag to identify which network is used to send measurement data
# by default, use control network.
set oml_use_control 1
# Mapping of "resource classes" and "reservation types" to bootstrap
# values, where a resource class is a symbolic string provided by the user
# (e.g. Client, Server), and a reservation type is a resource name provided
......@@ -1980,3 +1993,258 @@ proc tb-set-link-layer {link mylayer} {
$link set layer $mylayer
# The following codes are written, in order to use OML to send data to a server
# in an Emulab experiment. It will define a node to run OML server and create
# two files (MP.c and MP.h) for users. (mp represents measurement point in
# context of OML.)
# This procedure is to define a node to run omlserver.
# It will allocate an additional machine from Emulab and configure it
# (OS and set a start-command to start a oml2-server process).
# The name for this server will always be omlserver.
proc tb-set-use-oml {args} {
var_import ::TBCOMPAT::omlserver
var_import ::TBCOMPAT::oml_server_port
uplevel #0 {set omlserver [$ns node]}
uplevel #0 {set oml_server_port ${::TBCOMPAT::oml_server_port} }
uplevel #0 {tb-set-node-os $omlserver UBUNTU10-OML}
uplevel #0 {set omlserverstartcmd "/usr/bin/oml2-server -l $oml_server_port --logfile=/local/logs/oml-server.log --data-dir=/local/logs"}
uplevel #0 {tb-set-node-startcmd $omlserver $omlserverstartcmd}
# This procedure will assign a user-defined node to be omlserver.
# Configure OS and start-command for this machine.
proc tb-set-oml-server {node} {
var_import ::TBCOMPAT::oml_server_port
var_import ::TBCOMPAT::omlserver
if { $node == {} } {
perror "\[tb-set-oml-serve\] tb-set-oml-server <server_node>"
perror "No parameters are provided"
if { [$node info class] != "Node" } {
perror "\[tb-set-oml-serve\] tb-set-oml-server <server_node>"
perror "The parameter is not a node"
#puts "oml server name: $node\n"
$node set osid UBUNTU10-OML
set command "/usr/bin/oml2-server -l $oml_server_port --logfile=/local/logs/oml-server.log --data-dir=/local/logs"
set omlcommand "($command ; /usr/local/etc/emulab/startcmddone \$?)"
$node start-command $omlcommand
set omlserver $node
# set the flag. New lan will be constructed at
proc tb-set-oml-use-control {flag} {
var_import ::TBCOMPAT::oml_use_control
set oml_use_control $flag
# add a mp to the global variable
proc tb-set-oml-mp {args} {
var_import ::TBCOMPAT::oml_mps
if { $args == {} } {
perror "\[tb-set-oml-mp\] please specify parameters."
set mp $args
# check the parameters
set metrics [split $mp " "]
set count [llength $metrics]
set metrics_c [expr (($count-1)/2)]
#check format
if { $count ==0 || $count ==1 ||$count%2==0 || $metrics_c == 0 } {
perror "\[tb-set-oml-mp\] tb-set-oml-mp <mp_name> (<metric_id> <metric_type>)+"
set oml_mps [linsert $oml_mps [llength $oml_mps] $mp]
# write "#include <>" into files
proc oml_write_include {h_fd s_fd} {
set h_include "#include <oml2/omlc.h>\n#include <ocomm/o_log.h>\n#include <stdio.h>\n\n"
puts $h_fd $h_include
set s_include "#include \"MP.h\"\n"
puts $s_fd $s_include
# analyze one mp and write into files
# tb-analyze-store-mp mp_name <metric_id metric_type>...
proc tb-analyze-store-mp {mp h_fd s_fd} {
var_import ::TBCOMPAT::expdir
puts "tb-analyze-store-mp is called"
puts $mp
puts stderr $mp
#set mp [string range $arg1 1 [expr [string length $arg1] - 2 ] ]
#puts $mp
set metrics [split $mp " "]
set count [llength $metrics]
set metrics_c [expr (($count-1)/2)]
# get the name of this mp.
set mp_name [lindex $metrics 0]
set struct_def [format "static OmlMP* oml_%s_mp = NULL;\n" $mp_name]
set fun_def [format "void oml_%s(" $mp_name]
set fun_body [format "\tOmlValueU v\[%d\];\n" $metrics_c]
append struct_def \
[format "static OmlMPDef oml_%s_def \[\] = \{\n" $mp_name]
# get metrics in this mp
set i 0
while { $i < $metrics_c } {
set metric_name [lindex $metrics [expr $i*2+1]]
set type [lindex $metrics [expr $i*2+2]]
if { [string compare $type "STRING"] == 0
|| [string compare $type "string"] == 0 } {
set oml_type "OML_STRING_VALUE"
append fun_def [format "char* %s, " $metric_name]
append fun_body \
[format "\tomlc_set_const_string(v\[%d\], %s);\n" $i $metric_name]
} elseif { [string compare $type "INT"] == 0
|| [string compare $type "int"] == 0 } {
set oml_type "OML_LONG_VALUE"
append fun_def [format "int %s, " $metric_name]
append fun_body \
[format "\tomlc_set_long(v\[%d\], %s);\n" $i $metric_name]
} elseif { [string compare $type "DOUBLE"] == 0
|| [string compare $type "double"] == 0 } {
set oml_type "OML_DOUBLE_VALUE"
append fun_def [format "double %s, " $metric_name]
append fun_body \
[format "\tomlc_set_double(v\[%d\], %s);\n" $i $metric_name]
} else {
set struct_def [format "type \"%s\" not support\n" $type]
perror "\[tb-analyze-store-mp\] ${struct_def}"
append struct_def [format "\t\{\"%s\", %s\},\n" $metric_name $oml_type]
incr i 1
};#end of while
append struct_def "\t\{NULL, (OmlValueT)0\},\n\};\n\n"
puts $s_fd $struct_def
set fun_def [string trimright $fun_def ", "]
# write declaration into the header file
set fun_dec [format "%s);\n" $fun_def]
puts $h_fd $fun_dec
# write definition and body into the source file
append fun_def ") \{"
puts $s_fd $fun_def
append fun_body \
[format "\tomlc_inject(oml_%s_mp, v);\n\}\n\n" $mp_name]
puts $s_fd $fun_body
# write oml initialization into MP.c and MP.h
proc oml_write_init {h_fd s_fd} {
var_import ::GLOBALS::pid
var_import ::GLOBALS::eid
var_import ::TBCOMPAT::oml_mps
var_import ::TBCOMPAT::omlserver
var_import ::TBCOMPAT::oml_server_port
var_import ::TBCOMPAT::oml_use_control
set init_def "void initialize_oml()"
set init_dec [format "%s;" $init_def]
puts $h_fd $init_dec
append init_def " {\n\tint argc = 7;\n"
append init_def "\tconst char *argv\[\] = \{\"emulab_oml\", \"--oml-id\", \"emulab_oml\","
set oml_server "${omlserver}"
if {$oml_use_control == 1} {
# if use control network, then use long name
set oml_server "${omlserver}.${eid}.${pid}"
append init_def "\"--oml-exp-id\", \"$eid\", \"--oml-server\", \"tcp:$oml_server:$oml_server_port\"\};\n"
append init_def "\tomlc_init(argv\[0\], &argc, argv, o_log);\n"
set i 0
while { $i < [llength $oml_mps] } {
set mp [lindex $oml_mps $i]
#puts $mp
set mp_name [lindex [split $mp " "] 0]
set cmd [format "\toml_%s_mp = omlc_add_mp(\"%s\", oml_%s_def);\n" $mp_name $mp_name $mp_name ]
append init_def $cmd
incr i 1
append init_def "\tomlc_start();\n}\n"
puts $s_fd $init_def
# called by
# create MP.c and MP.h and analyze measurement points and write definitions to
# these two files. The location for these two files is /proj/pid/exp/eid/.
proc begin_oml_code_generator {} {
var_import ::TBCOMPAT::oml_mps
# If users do not define any measurement points. Just return
# It will not create MP.c and MP.h
if { $oml_mps == {} } {
# puts "begin oml code generator\n"
# create and open MP.c and MP.h at /proj/pid/exp/eid/
if { [string compare ${::TBCOMPAT::expdir} "/proj/PID/exp/EID/"] == 0 } {
puts stderr "\[oml_code_generator\] expdir is not initialized"
if { ![file isdirectory ${::TBCOMPAT::expdir}] } {
perror "\[oml_code_generator\] ${::TBCOMPAT::expdir} is not a directory"
if { [catch {open "${::TBCOMPAT::expdir}MP.c" w} s_fd] } {
perror "\[oml_code_generator\] could not open MP.c\n$s_fd"
if { [catch {open "${::TBCOMPAT::expdir}MP.h" w} h_fd] } {
perror "\[oml_code_generator\] could not open MP.h\n$h_fd"
# Make header C++ compatible
puts $h_fd "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"
# write "#includes" into MP.c and MP.h
oml_write_include $h_fd $s_fd
# write definitions of measurement points.
set i 0
while { $i < [llength $oml_mps] } {
set mp [lindex $oml_mps $i]
#puts $mp
tb-analyze-store-mp $mp $h_fd $s_fd
incr i 1
# write initialization
oml_write_init $h_fd $s_fd
puts $h_fd "\n#ifdef __cplusplus\n}\n#endif\n"
close $h_fd
close $s_fd
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment