From f30ed558723fa94d6da72d1ef3cf0ce3910f6552 Mon Sep 17 00:00:00 2001 From: Giuseppe Lettieri Date: Tue, 15 May 2012 15:31:22 +0200 Subject: [PATCH] planetlab scripts and utilities --- planetlab/automake.mk | 12 +- planetlab/scripts/Makefile | 107 +++++++++++++++ planetlab/scripts/create_bridge | 9 +- planetlab/scripts/create_port | 7 +- planetlab/scripts/del_bridge | 8 +- planetlab/scripts/del_port | 16 +++ planetlab/scripts/start_ovsdb-server | 17 +++ planetlab/scripts/start_vswitchd | 12 ++ planetlab/vsysc/vsysc.c | 191 +++++++++++++++++++++++++++ 9 files changed, 365 insertions(+), 14 deletions(-) create mode 100644 planetlab/scripts/Makefile create mode 100755 planetlab/scripts/del_port create mode 100644 planetlab/scripts/start_ovsdb-server create mode 100644 planetlab/scripts/start_vswitchd create mode 100644 planetlab/vsysc/vsysc.c diff --git a/planetlab/automake.mk b/planetlab/automake.mk index a08dd8eb5..70c59d15b 100644 --- a/planetlab/automake.mk +++ b/planetlab/automake.mk @@ -1,12 +1,20 @@ sbin_PROGRAMS += \ - planetlab/pltap-ovs/pltap-ovs + planetlab/pltap-ovs/pltap-ovs \ + planetlab/vsysc/vsysc dist_sbin_SCRIPTS += \ + planetlab/scripts/start_ovsdb-server \ + planetlab/scripts/start_vswitchd \ planetlab/scripts/create_bridge \ planetlab/scripts/create_port \ - planetlab/scripts/del_bridge + planetlab/scripts/del_bridge \ + planetlab/scripts/del_port \ + planetlab/scripts/Makefile planetlab_pltap_ovs_pltap_ovs_SOURCES = \ planetlab/pltap-ovs/pltap-ovs.c \ planetlab/pltap-ovs/tunalloc.c \ planetlab/pltap-ovs/tunalloc.h + +planetlab_vsysc_vsysc_SOURCES = \ + planetlab/vsysc/vsysc.c diff --git a/planetlab/scripts/Makefile b/planetlab/scripts/Makefile new file mode 100644 index 000000000..ea7162405 --- /dev/null +++ b/planetlab/scripts/Makefile @@ -0,0 +1,107 @@ +include conf.mk + +# proj1(x@y) = x +proj1=$(word 1,$(subst @, ,$(1))) + +# proj2(x@y) = y +proj2=$(word 2,$(subst @, ,$(1))) + +# get(x-y@1) = x +# get(x-y@2) = y +get=$(word $(call proj2,$(1)),$(subst -, ,$(call proj1,$(1)))) + +# flip(1) = 2 +# flip(2) = 1 +flip=$(if $(findstring 1,$(1)),2,1) + +# opp(x-y@1) = x-y@2 +# opp(x-y@2) = x-y@1 +opp=$(call proj1,$(1))@$(call flip,$(call proj2,$(1))) + +# rget(x-y@1) = y +# rget(x-y@2) = x +rget=$(call get,$(call opp,$(1))) + + +.SECONDARY: + +all: $(addprefix L/,$(shell cat links)) + + +cache/host.%: + @echo "IP lookup for host $*" + @host $(HOST_$*) | sed -n 's/^.*has address *//p' > $@ + +cache/db.%: + @echo "Starting db server on host $*" + @ssh -l $(SLICE) $(HOST_$*) \ + sudo start_ovsdb-server > $@ \ + || { rm $@; exit 1; } + +cache/switchd.%: cache/db.% + @echo "Starting vswitchd on host $*" + @ssh -l $(SLICE) $(HOST_$*) \ + sudo start_vswitchd > $@ \ + || { rm $@; exit 1; } + +cache/bridge.%: cache/switchd.% + @echo "Creating bridge on host $*" + @ssh -l $(SLICE) $(HOST_$*) \ + sudo create_bridge $(IP_$*) > $@ \ + || { rm $@; exit 1; } + + +L/%: cache/link.%@1 cache/link.%@2 + @touch $@ + @echo "Created link $*" + +del.%: del-iface.%@1 del-iface.%@2 + @rm -f L/$* + @echo "Deleted link $*" + +del-iface.%: + @echo "Removing interface for link $(call proj1,$*) from host $(call get,$*)" + @ssh -l $(SLICE) $(HOST_$(call get,$*)) \ + sudo ovs-vsctl del-port L$(call proj1,$*) + @rm -f cache/iface.$* cache/link.$* cache/link.$(call opp,$*) + +del-bridge.%: + @echo "Deleting bridge on host $*" + @if [ -f cache/bridge.$* ]; then \ + ssh -l $(SLICE) $(HOST_$*) \ + sudo del_bridge $$(cat cache/bridge.$*);\ + fi + @rm -f cache/bridge.$* \ + cache/iface.$*-*@1 cache/iface.*-$*@2 \ + cache/link.$*-*@? cache/link.*-$*@? \ + L/$*-* L/*-$* + +graph.dot: + ( echo "digraph $(SLICE) {"; ls L | sed 's/-/->/;s/$$/;/'; echo "}" ) > $@ + +graph.ps: graph.dot + dot -Tps < $^ > $@ + +.PHONY: clean del-links graph.dot + + +clean: $(addprefix del-,$(notdir $(wildcard cache/bridge.*))) + +del-links: $(addprefix del.,$(notdir $(wildcard L/*))) + +.SECONDEXPANSION: + +cache/iface.%: cache/bridge.$$(call get,%) + @echo "Creating iterface for link $(call proj1,$*) on host $(call get,$*)" + @ssh -l $(SLICE) $(HOST_$(call get,$*)) \ + sudo create_port $$(cat $^) L$(call proj1,$*) > $@ \ + || { rm $@; exit 1; } + +cache/link.%: cache/host.$$(call rget,$$*) cache/iface.% cache/iface.$$(call opp,$$*) + @echo "Setting port number of link $(call proj1,$*) on host $(call get,$*)" + @ssh -l $(SLICE) $(HOST_$(call get,$*)) \ + sudo ovs-vsctl set interface L$(call proj1,$*) \ + options:remote_ip=$$(cat cache/host.$(call rget,$*)) \ + options:remote_port=$$(cat cache/iface.$(call opp,$*)) \ + && touch $@ + diff --git a/planetlab/scripts/create_bridge b/planetlab/scripts/create_bridge index 72acfd7f4..ad8830506 100755 --- a/planetlab/scripts/create_bridge +++ b/planetlab/scripts/create_bridge @@ -25,11 +25,9 @@ set -e # ensure ovs-vswitchd is running if ! is_switch_running; then - ovs-vswitchd --pidfile --detach --log-file >/dev/null 2>&1 + echo "ovs-vswitchd not running" >&2 + exit 1 fi -while ! is_switch_running; do - sleep 1 -done # check whether the address is already assigned @@ -44,8 +42,7 @@ if [ ! -z "$TAPNAME" ]; then fi TAPNAME=$(pltap-ovs) -cat < /vsys/vif_up.out& -cat >/vsys/vif_up.in << EOF +vsysc vif_up << EOF $TAPNAME $IP $PREFIX diff --git a/planetlab/scripts/create_port b/planetlab/scripts/create_port index 6fa8ea5f5..211a82781 100755 --- a/planetlab/scripts/create_port +++ b/planetlab/scripts/create_port @@ -10,7 +10,8 @@ if [ -z "$2" ]; then error "Usage ${0##*/} " fi -if ovs-vsctl list-ports "$1" | grep -q "^$2$"; then - exit 0 +set -e +if ! ovs-vsctl list-ports "$1" | grep -q "^$2\$"; then + ovs-vsctl add-port "$1" "$2" -- set interface "$2" type=tunnel fi -ovs-vsctl add-port "$1" "$2" -- set interface "$2" type=tunnel +ovs-appctl netdev-tunnel/get-port "$2" diff --git a/planetlab/scripts/del_bridge b/planetlab/scripts/del_bridge index 9f62afcec..e25ff924d 100755 --- a/planetlab/scripts/del_bridge +++ b/planetlab/scripts/del_bridge @@ -17,8 +17,10 @@ fi # ensure ovs-vswitchd is running if ! is_switch_running; then - exit 0; + echo "ovs-vswitchd not runnig" >&2 + exit 1 fi -ovs-vsctl del-br $1 || true -ovs-appctl exit +if ovs-vsctl bridge-exists "$1"; then + ovs-vsctl del-br $1 +fi diff --git a/planetlab/scripts/del_port b/planetlab/scripts/del_port new file mode 100755 index 000000000..5b1ef8e04 --- /dev/null +++ b/planetlab/scripts/del_port @@ -0,0 +1,16 @@ +#!/bin/bash + +function error +{ + echo $1 >&2 + exit 1 +} + +if [ -z "$1" ]; then + error "Usage ${0##*/} " +fi + +set -e +if ovs-vsctl port-to-br "$2" >/dev/null 2>&1; then + ovs-vsctl del-port "$2" +fi diff --git a/planetlab/scripts/start_ovsdb-server b/planetlab/scripts/start_ovsdb-server new file mode 100644 index 000000000..49bd0a4d0 --- /dev/null +++ b/planetlab/scripts/start_ovsdb-server @@ -0,0 +1,17 @@ +#!/bin/bash + +PIDF=/usr/local/var/run/openvswitch/ovsdb-server.pid + +if [ ! -f "$PIDF" ]; then + sudo ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \ + --remote=db:Open_vSwitch,manager_options \ + --private-key=db:SSL,private_key \ + --certificate=db:SSL,certificate \ + --bootstrap-ca-cert=db:SSL,ca_cert \ + --pidfile --detach +fi +while [ ! -f "$PIDF" ]; do + echo "Waiting for ovsdb-server to start..." >&2 + sleep 1; +done +cat "$PIDF" diff --git a/planetlab/scripts/start_vswitchd b/planetlab/scripts/start_vswitchd new file mode 100644 index 000000000..248e8cbb0 --- /dev/null +++ b/planetlab/scripts/start_vswitchd @@ -0,0 +1,12 @@ +#!/bin/bash + +PIDF=/usr/local/var/run/openvswitch/ovs-vswitchd.pid + +if [ ! -f "$PIDF" ]; then + sudo ovs-vswitchd --pidfile --detach --log-file >/dev/null +fi +while [ ! -f "$PIDF" ]; do + echo "Waiting for ovs-vswitchd to start..." >&2 + sleep 1; +done +cat "$PIDF" diff --git a/planetlab/vsysc/vsysc.c b/planetlab/vsysc/vsysc.c new file mode 100644 index 000000000..98c90e772 --- /dev/null +++ b/planetlab/vsysc/vsysc.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include +#include + +#define VSYS_PATH "/vsys" + +#define MAXPATH 1024 +#define BUFSIZE 4096 + +#define IN 0 +#define OUT 1 + +char ctrl[2][MAXPATH]; /* paths of vsys.in & vsys.out */ + +static void mkpath(int dir, const char* vsys) +{ + static const char *suffix[] = { "in", "out" }; + int n; + + if ( (n = snprintf(ctrl[dir], MAXPATH, "%s/%s.%s", VSYS_PATH, vsys, suffix[dir])) < 0) { + perror(vsys); + exit(EXIT_FAILURE); + } else if (n >= MAXPATH) { + fprintf(stderr, "argument too long\n"); + exit(EXIT_FAILURE); + } +} + +static int open_ctrl(int dir) +{ + int fd; + + if ( (fd = open(ctrl[dir], (dir == IN ? O_WRONLY : O_RDONLY) | O_NONBLOCK)) < 0) { + perror(ctrl[dir]); + exit(EXIT_FAILURE); + } + return fd; +} + + +static void set_nonblocking(int fd) +{ + int val; + + if ( (val = fcntl(fd, F_GETFL, 0)) < 0) { + perror("fcntl F_GETFL"); + exit(EXIT_FAILURE); + } + if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) { + perror("fcntl F_SETFL"); + exit(EXIT_FAILURE); + } +} + +#if 0 +static void print_set(const char* name, int max, const fd_set* set) +{ + int i, n = 0; + fprintf(stderr, "%s: {", name); + for (i = 0; i < max; i++) { + if (FD_ISSET(i, set)) { + if (n++) fprintf(stderr, ", "); + fprintf(stderr, "%d", i); + } + } + fprintf(stderr, "}\n"); +} +#endif + +struct channel { + const char *name; + int active; + int writing; + char buf[BUFSIZE]; + char *rp, *wp; + int rfd, wfd; +}; + +static int active_channels = 0; + +static void channel_init(struct channel *c, const char* name, int rfd, int wfd) +{ + c->name = name; + c->rp = c->buf; + c->wp = c->buf; + c->rfd = rfd; + c->wfd = wfd; + c->active = 1; + active_channels++; +} + +static void channel_fdset(struct channel *c, fd_set* readset, fd_set* writeset) +{ + if (!c->active) + return; + if (c->writing) { + FD_SET(c->wfd, writeset); + } else { + FD_SET(c->rfd, readset); + } +} + +static void channel_run(struct channel *c, const fd_set* readset, const fd_set* writeset) +{ + int n; + + if (!c->active) + return; + if (c->writing) { + if (FD_ISSET(c->wfd, writeset)) { + if ( (n = write(c->wfd, c->wp, c->rp - c->wp)) < 0) { + perror(c->name); + exit(EXIT_FAILURE); + } + c->wp += n; + if (c->wp == c->rp) { + c->wp = c->rp = c->buf; + c->writing = 0; + } + } + } else { + if (FD_ISSET(c->rfd, readset)) { + if ( (n = read(c->rfd, c->rp, BUFSIZE)) < 0) { + perror(c->name); + exit(EXIT_FAILURE); + } + if (n) { + c->wp = c->rp; + c->rp += n; + c->writing = 1; + } else { + close(c->wfd); + c->active = 0; + active_channels--; + } + } + } +} + +static struct channel channels[2]; + + +int main(int argc, char *argv[]) +{ + int fd[2]; /* fds of vsys.in & vsys.out */ + int maxfd; + + fd_set readset, writeset; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + exit(EXIT_FAILURE); + } + + mkpath(IN, argv[1]); + mkpath(OUT, argv[1]); + + maxfd = (STDOUT_FILENO > STDIN_FILENO ? STDOUT_FILENO : STDIN_FILENO); + + fd[OUT] = open_ctrl(OUT); + if (fd[OUT] > maxfd) + maxfd = fd[OUT]; + fd[IN] = open_ctrl(IN); + if (fd[IN] > maxfd) + maxfd = fd[IN]; + + set_nonblocking(STDIN_FILENO); + set_nonblocking(STDOUT_FILENO); + + channel_init(&channels[IN], "IN", STDIN_FILENO, fd[IN]); + channel_init(&channels[OUT], "OUT", fd[OUT], STDOUT_FILENO); + + while (active_channels) { + FD_ZERO(&readset); + FD_ZERO(&writeset); + channel_fdset(&channels[IN], &readset, &writeset); + channel_fdset(&channels[OUT], &readset, &writeset); + if (select(maxfd + 1, &readset, &writeset, NULL, NULL) < 0) { + perror("select"); + exit(EXIT_FAILURE); + } + channel_run(&channels[IN], &readset, &writeset); + channel_run(&channels[OUT], &readset, &writeset); + } + return EXIT_SUCCESS; +} + -- 2.47.0