4 ### expected to be run as root
8 #################### global vars
10 DB_CONF_FILE=@DBDIR@/conf.db
11 DB_SCHEMA=@pkgdatadir@/vswitch.ovsschema
12 DB_LOG=@LOGDIR@/ovs-db.log
14 DB_SOCKET=$RUN_DIR/db.sock
16 SWITCH_LOG=@LOGDIR@/ovs-switch.log
18 #################### helper functions
20 function kill_pltap_ovs () {
21 killall pltap-ovs 2>/dev/null || :
31 err_msg="$COMMAND $SUBCOMMAND $(echo $params | perl -pe 's/\S+/<$&>/g')"
33 [[ -z "$@" ]] && error "$err_msg"
34 pname=$(echo -n $p|perl -pe 's/\W/_/g')
35 eval $pname="$1"; shift
37 [[ -n "$@" ]] && error "$err_msg"
40 function is_switch_running {
41 ovs-appctl --target=ovs-vswitchd version >& /dev/null
44 function is_db_running {
45 ovs-appctl --target=ovsdb-server version >& /dev/null
50 echo $(ip addr show to "$IP/32" | perl -ne '/^\s*\d+:\s*([\w-]+):/ && print $1')
53 function wait_server () {
58 expire=$(($(date +%s) + $timeout))
60 ## wait for it to be up - xxx todo - could use a timeout of some kind
61 while [ ! -f "$pid_file" ]; do
62 echo "Waiting for $server_name to start... $(($expire - $(date +%s)))s left" >&2
64 [ $(date +%s) -ge $expire ] && return 1
69 function wait_device () {
70 local tapname=$1; shift
71 local timeout=$1; shift
73 local expire=$(($(date +%s) + $timeout))
75 while ! ip link show up | egrep -q "^[0-9]+: +$tapname:"; do
76 echo "Waiting for $tapname to come UP...$(($expire - $(date +%s)))s left" >&2
78 [ $(date +%s) -ge $expire ] && return 1
83 ######################################## startup
84 function start_db () {
88 conf_dir=$(dirname $DB_CONF_FILE)
89 [ -d $conf_dir ] || mkdir -p $conf_dir
90 [ -f $DB_CONF_FILE ] || ovsdb-tool create $DB_CONF_FILE $DB_SCHEMA
93 [ -d $RUN_DIR ] || mkdir -p $RUN_DIR
96 [ -f $DB_CONF_FILE ] || { echo "Could not initialize $DB_CONF_FILE - exiting" ; exit 1 ; }
97 [ -d $RUN_DIR ] || { echo "Could not initialize $RUN_DIR - exiting" ; exit 1 ; }
100 ovsdb-server $DB_CONF_FILE \
101 --remote=punix:$DB_SOCKET \
102 --remote=db:Open_vSwitch,Open_vSwitch,manager_options \
103 --private-key=db:Open_vSwitch,SSL,private_key \
104 --certificate=db:Open_vSwitch,SSL,certificate \
105 --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
108 --detach >& /dev/null
109 wait_server $RUN_DIR/ovsdb-server.pid ovsdb-server 30
112 function start_switch () {
115 # ensure ovsdb-server is running
116 is_db_running || { echo "ovsdb-server not running" >&2 ; exit 1 ; }
120 --log-file=$SWITCH_LOG \
122 unix:$DB_SOCKET >& /dev/null
123 wait_server $RUN_DIR/ovs-vswitchd.pid ovs-vswitchd 30
126 function stop_db () {
127 ovs-appctl --target=ovsdb-server exit || :
130 function stop_switch () {
131 ovs-appctl --target=ovs-vswitchd exit || :
136 [ -n "$pids" ] && ps $pids
149 #################### create functions
150 function create_bridge () {
152 get_params "bridge IP/PREFIX" "$1" "$2"
156 PREFIX=${IP_PREFIX#*/}
159 if ! is_switch_running; then
160 # we can create the bridge even if ovs-vswitchd is not running,
161 # but we need a running ovsdb-server
162 is_db_running || { echo "ovsdb-server not running" >&2; exit 1; }
168 ovs-vsctl --db=unix:$DB_SOCKET $W -- --may-exist add-br "$bridge" \
169 -- set bridge "$bridge" datapath_type=planetlab \
170 -- set interface "$bridge" options:local_ip="$IP" option:local_netmask="$PREFIX" \
173 # check that the bridge has actually been created
175 local tap=$(ovs-appctl netdev-pltap/get-tapname "$bridge")
180 function create_port () {
182 get_params "bridge port" "$@"
185 if ! is_switch_running; then
186 # we can create the port even if ovs-vswitchd is not running,
187 # but we need a running ovsdb-server
188 is_db_running || { echo "ovsdb-server not running" >&2; exit 1; }
193 ovs-vsctl --db=unix:$DB_SOCKET $W -- --may-exist add-port "$bridge" "$port" \
194 -- set interface "$port" type=tunnel
197 function get_local_endpoint () {
199 get_params "local_port" "$@"
201 is_switch_running || { echo "ovs-vswitchd not running" >&2; exit 1; }
204 ovs-appctl --target=ovs-vswitchd netdev-tunnel/get-port "$local_port"
207 function set_remote_endpoint () {
209 get_params "local_port remote_ip remote_UDP_port" "$@"
212 if ! is_switch_running; then
213 # we can store the info even if ovs-vswitchd is not running,
214 # but we need a running ovsdb-server
215 is_db_running || { echo "ovsdb-server not running" >&2; exit 1; }
220 ovs-vsctl --db=unix:$DB_SOCKET $W set interface $local_port \
221 options:remote_ip=$remote_ip \
222 options:remote_port=$remote_UDP_port
225 function set_controller () {
227 get_params "bridge_name controller" "$@"
229 # ensure ovs-vswitchd is running
230 is_switch_running || { echo "ovs-vswitchd not running" >&2 ; exit 1 ; }
233 ovs-vsctl --db=unix:$DB_SOCKET set-controller "$bridge_name" "$controller"
236 function del_controller () {
238 get_params "bridge_name" "$@"
240 # ensure ovs-vswitchd is running
241 is_switch_running || { echo "ovs-vswitchd not running" >&2 ; exit 1 ; }
244 ovs-vsctl --db=unix:$DB_SOCKET del-controller "$bridge_name"
247 #################### del functions
248 function del_bridge () {
250 get_params "bridge_name" "$@"
253 if ! is_switch_running; then
254 # we can delete the bridge even if ovs-vswitchd is not running,
255 # but we need a running ovsdb-server
256 is_db_running || { echo "ovsdb-server not running" >&2; exit 1; }
260 ovs-vsctl --db=unix:$DB_SOCKET $W -- --if-exists del-br $bridge_name
263 function del_port () {
265 get_params "port" "$@"
268 if ! is_switch_running; then
269 # we can delete the port even if ovs-vswitchd is not running,
270 # but we need a running ovsdb-server
271 is_db_running || { echo "ovsdb-server not running" >&2; exit 1; }
275 ovs-vsctl --db=unix:$DB_SOCKET $W -- --if-exists del-port "$port"
282 is_db_running || { echo "ovsdb-server not running" >&2; exit 1; }
284 ovs-vsctl --db=unix:$DB_SOCKET show
287 function get_local_ip () {
289 get_params "bridge" "$@"
292 ovs-vsctl --db=unix:$DB_SOCKET br-exists "$bridge" || return
293 local ip=$(ovs-vsctl get interface "$bridge" options:local_ip)
294 local netmask=$(ovs-vsctl get interface "$bridge" options:local_netmask)
295 eval echo $ip/$netmask
298 function get_local_links () {
300 get_params "bridge" "$@"
303 ovs-vsctl --db=unix:$DB_SOCKET br-exists "$bridge" || return
304 ovs-vsctl --db=unix:$DB_SOCKET list-ifaces "$bridge"
307 function get_mac () {
309 get_params "bridge" "$@"
312 local tap=$(ovs-appctl netdev-pltap/get-tapname "$bridge")
313 ifconfig "$tap" | awk '/HWaddr/ { print $5 }'
316 ### for demos - connect to an ndnmap deployment to visualize links bandwidth
317 # this expects 3 arguments
318 # an interface name, L<id1>-<id2> based on your ids in conf.mk
319 # the hostname for a ndnmap deployment
320 # a linkid, this is the id that this link has in your ndnmap scenario (hard-coded in some json file)
321 # this one-shot function writes the current statistics onto the ndnmap site
322 # it needs to be called regularly so that ndnmap can do the bw computations
323 # would make sense for the caller to redirect stderr onto some relevant location
324 function gmap_probe_once () {
328 rx_bytes=$(ovs-appctl netdev-tunnel/get-rx-bytes $iface)
329 tx_bytes=$(ovs-appctl netdev-tunnel/get-tx-bytes $iface)
330 rx_bits=$(($rx_bytes*8))
331 tx_bits=$(($tx_bytes*8))
332 now=$(date +%s).$(date +%N)
333 trigger=http://${hostname}/bw/${linkid}/${now}/${rx_bits}/${tx_bits}
334 # curl -s -L $trigger | grep -q "Got it" || echo Missed event with $trigger
336 curl -s -L $trigger >& /dev/null
339 ### the front end, manages pid and so on
340 function gmap_probe () {
345 [ -z "$looptime" ] && looptime=1
346 pid_file=/var/run/openvswitch/gmap-$iface.pid
347 if [ -f $pid_file ] ; then
349 [ -n "$pid" ] && kill $pid >& /dev/null
352 # close std fds so that ssh invokations can return
356 gmap_probe_once $iface $hostname $linkid
359 # this is the pid for the background process
364 SUPPORTED_SUBCOMMANDS="start stop status
365 start_db stop_db start_switch stop_switch
366 create_bridge create_port del_bridge del_port
367 show get_local_endpoint set_remote_endpoint
368 set_controller del_controller gmap_probe
369 get_local_ip get_local_links get_mac"
372 message="Usage: $COMMAND <subcommand> ...
373 Supported subcommands are (dash or underscore is the same):
374 $SUPPORTED_SUBCOMMANDS"
375 [[ -z "$@" ]] && error "$message"
378 # support dashes instead of underscores
379 SUBCOMMAND=$(echo $SUBCOMMAND | sed -e s,-,_,g)
381 for supported in $SUPPORTED_SUBCOMMANDS; do [ "$SUBCOMMAND" = "$supported" ] && found=yes; done
383 [ -z "$found" ] && error $message