diff --git a/ovl/ovs/README.md b/ovl/ovs/README.md new file mode 100644 index 00000000..c3c376a5 --- /dev/null +++ b/ovl/ovs/README.md @@ -0,0 +1,78 @@ +# Xcluster/ovl - ovs + +Open vSwitch is used in the xcluster VMs, not on the host as a VM-VM +network (as the image on https://www.openvswitch.org/ shows). + + +## Usage + +Test; +``` +./ovs.sh test > $log +``` + +Manual tests; +``` +./ovs.sh test start_base > $log +# On a VM; +ovs-vsctl -V +grep -v JSON /etc/openvswitch/conf.db | jq +ovs-vsctl add-br br0 +ovs-appctl dpctl/show +#ovs-vsctl add-br br1 -- set Bridge br1 datapath_type=netdev +ovs-appctl dpif/show-dp-features br0 +ovs-vsctl add-port br0 eth1 +ovs-vsctl add-port br0 vlan10 tag=10 -- set Interface vlan10 type=internal +i=$(hostname | cut -d- -f2 | sed -re 's,^0+,,') +ip link set up dev vlan10 +ip addr add 3000::$i/120 dev vlan10 +ping -c1 3000::$i +``` + + +## Build + +``` +# Clone; +mkdir -p $GOPATH/src/github.com/openvswitch +cd $GOPATH/src/github.com/openvswitch +git clone --depth=1 https://github.com/openvswitch/ovs.git +# Build; +cdo ovs +eval $(./ovs.sh env | grep SYSD) +cd $GOPATH/src/github.com/openvswitch/ovs +./boot.sh +./configure +make -j$(nproc) +make DESTDIR=$SYSD install +``` + +### Build with XDP support + +[afxdp doc](https://docs.openvswitch.org/en/latest/intro/install/afxdp/) + +``` +cdo xdp +./xdp.sh libbpf_build +cdo ovs +eval $(./ovs.sh env | grep SYSD) +eval $(xc env | grep -e '__kobj') +bpflibd=$(readlink -f $__kobj/source)/tools/lib/bpf/build/usr +cd $GOPATH/src/github.com/openvswitch/ovs +LDFLAGS=-L$bpflibd/lib64 CPPFLAGS=-I$bpflibd/include ./configure --enable-afxdp +make -j$(nproc) +make DESTDIR=$SYSD install +``` + +## Links + +In no particular order or usefulness. + +* https://www.openvswitch.org/ +* https://github.com/openvswitch/ovs/ +* https://kumul.us/switches-ovs-vs-linux-bridge-simplicity-rules/ +* https://www.plixer.com/blog/openflow-vs-netflow/ +* https://www.linuxtechi.com/install-use-openvswitch-kvm-centos-7-rhel-7/ +* https://arthurchiao.art/blog/ovs-deep-dive-6-internal-port/ +* https://arthurchiao.art/blog/ovs-deep-dive-1-vswitchd/ + diff --git a/ovl/ovs/default/bin/ovs_test b/ovl/ovs/default/bin/ovs_test new file mode 100755 index 00000000..6445dd7d --- /dev/null +++ b/ovl/ovs/default/bin/ovs_test @@ -0,0 +1,115 @@ +#! /bin/sh +## +## ovs_test -- +## +## Test script for ovs executed in xcluster. +## +## Commands; +## + +prg=$(basename $0) +dir=$(dirname $0); dir=$(readlink -f $dir) +me=$dir/$prg +tmp=/tmp/${prg}_$$ +test -n "$DOMAIN" || DOMAIN=xcluster + +die() { + echo "ERROR: $*" >&2 + rm -rf $tmp + exit 1 +} +help() { + grep '^##' $0 | cut -c3- + rm -rf $tmp + exit 0 +} +test -n "$1" || help +echo "$1" | grep -qi "^help\|-h" && help + +log() { + echo "$prg: $*" >&2 +} +dbg() { + test -n "$__verbose" && echo "$prg: $*" >&2 +} + +cmd_tcase_create_br0() { + tcase "Create ovs bridge; br0" + ovs-vsctl add-br br0 + ovs-vsctl add-port br0 eth1 +} +cmd_tcase_create_netns() { + tcase "Create netns; ns1, ns2" + create_netns ns1 + create_netns ns2 +} +create_netns() { + ip netns add $1 + ip netns exec $1 ip link set up dev lo +} +cmd_tcase_add_ports() { + tcase "Add vanilla interfaces in netns's" + ovs-vsctl add-port br0 ns1 -- set Interface ns1 type=internal + ovs-vsctl add-port br0 ns2 -- set Interface ns2 type=internal + add_ports 1 + add_ports 2 +} +add_ports() { + local i=$(hostname | cut -d- -f2 | sed -re 's,^0+,,') + local ns=ns$1 + local ip4=10.10.$i.$1 + ip link set netns $ns $ns + ip netns exec $ns ip link set up dev $ns + ip netns exec $ns ip addr add $ip4/16 dev $ns + ip netns exec $ns ip -6 addr add 1100::$ip4/112 dev $ns +} +cmd_tcase_ping_all() { + tcase "Ping all from ns1 and ns2" + ping_all 1 + ping_all 2 +} +ping_all() { + local ns=ns$1 + local i + for i in $(seq 1 $__nvm); do + ping_one $ns 10.10.$i.1 || tdie 10.10.$i.1 + ping_one $ns 10.10.$i.2 || tdie 10.10.$i.2 + tex ping_one $ns 1100::10.10.$i.1 || tdie 1100::10.10.$i.1 + tex ping_one $ns 1100::10.10.$i.2 || tdie 1100::10.10.$i.2 + done +} +ping_one() { + ip netns exec $1 ping -W1 -c1 $2 +} + + +. /etc/profile +. /usr/lib/xctest +indent=' ' + + +# Get the command +cmd=$1 +shift +grep -q "^cmd_$cmd()" $0 || die "Invalid command [$cmd]" + +while echo "$1" | grep -q '^--'; do + if echo $1 | grep -q =; then + o=$(echo "$1" | cut -d= -f1 | sed -e 's,-,_,g') + v=$(echo "$1" | cut -d= -f2-) + eval "$o=\"$v\"" + else + o=$(echo "$1" | sed -e 's,-,_,g') + eval "$o=yes" + fi + shift +done +unset o v +long_opts=`set | grep '^__' | cut -d= -f1` + +# Execute command +trap "die Interrupted" INT TERM +cmd_$cmd "$@" +status=$? +rm -rf $tmp +exit $status diff --git a/ovl/ovs/default/etc/init.d/20ovs.rc b/ovl/ovs/default/etc/init.d/20ovs.rc new file mode 100755 index 00000000..925c1a57 --- /dev/null +++ b/ovl/ovs/default/etc/init.d/20ovs.rc @@ -0,0 +1,21 @@ +#! /bin/sh + +export PATH="/bin:/sbin:/usr/bin:/usr/sbin" +. /etc/profile + +die() { + echo "$@" + exit 1 +} + +hostname | grep -Eq 'vm-[0-9]+$' || die "Invalid hostname [$(hostname)]" +i=$(hostname | cut -d- -f2 | sed -re 's,^0+,,') +test $i -gt 200 && exit 0 + +SYSTEM_ID=$(printf '35f15062-7e2b-11e9-b640-0000000100%02x\n' $i) +echo $SYSTEM_ID > /etc/machine-id +mkdir -p /etc/openvswitch +echo $SYSTEM_ID > /etc/openvswitch/system-id.conf +ovsdb-tool create /etc/openvswitch/conf.db /usr/local/share/openvswitch/vswitch.ovsschema + +/usr/local/share/openvswitch/scripts/ovs-ctl --system-id=$SYSTEM_ID start diff --git a/ovl/ovs/ovs.sh b/ovl/ovs/ovs.sh new file mode 100755 index 00000000..c51482a2 --- /dev/null +++ b/ovl/ovs/ovs.sh @@ -0,0 +1,142 @@ +#! /bin/sh +## +## ovs.sh -- +## +## Help script for xcluster ovl/ovs. +## +## Commands; +## + +prg=$(basename $0) +dir=$(dirname $0); dir=$(readlink -f $dir) +me=$dir/$prg +tmp=/tmp/${prg}_$$ + +die() { + echo "ERROR: $*" >&2 + rm -rf $tmp + exit 1 +} +help() { + grep '^##' $0 | cut -c3- + rm -rf $tmp + exit 0 +} +test -n "$1" || help +echo "$1" | grep -qi "^help\|-h" && help + +log() { + echo "$prg: $*" >&2 +} +dbg() { + test -n "$__verbose" && echo "$prg: $*" >&2 +} + +## env +## Print environment. +## +cmd_env() { + + test -n "$SYSD" || SYSD=$XCLUSTER_WORKSPACE/sys + if test "$cmd" = "env"; then + set | grep -E '^(__.*|SYSD)=' + return 0 + fi + + test -n "$XCLUSTER" || die 'Not set [$XCLUSTER]' + test -x "$XCLUSTER" || die "Not executable [$XCLUSTER]" + eval $($XCLUSTER env) +} + +## test --list +## test [--xterm] [test...] > logfile +## Exec tests +## +cmd_test() { + if test "$__list" = "yes"; then + grep '^test_' $me | cut -d'(' -f1 | sed -e 's,test_,,' + return 0 + fi + + cmd_env + start=starts + test "$__xterm" = "yes" && start=start + rm -f $XCLUSTER_TMP/cdrom.iso + + if test -n "$1"; then + for t in $@; do + test_$t + done + else + test_default + fi + + now=$(date +%s) + tlog "Xcluster test ended. Total time $((now-begin)) sec" + +} + +test_start_base() { + export __image=$XCLUSTER_HOME/hd.img + echo "$XOVLS" | grep -q private-reg && unset XOVLS + export __nrouters=0 + test -n "$TOPOLOGY" && \ + . $($XCLUSTER ovld network-topology)/$TOPOLOGY/Envsettings + xcluster_start network-topology iptools ovs +} + +test_default() { + tlog "=== ovs: Basic test" + test_start_base + otcw create_br0 + otcw create_netns + otcw add_ports + otcw ping_all + xcluster_stop +} + +## man [command] +## Show a ovs man-page. List if no command is specified. +cmd_man() { + cmd_env + MANPATH=$SYSD/usr/local/share/man + if test -z "$1"; then + local f + for f in $(find $MANPATH -type f); do + basename $f + done + return 0 + fi + export MANPATH + xterm -bg '#ddd' -fg '#222' -geometry 80x45 -T $1 -e man $1 & +} + +## +. $($XCLUSTER ovld test)/default/usr/lib/xctest +indent='' + +# Get the command +cmd=$1 +shift +grep -q "^cmd_$cmd()" $0 $hook || die "Invalid command [$cmd]" + +while echo "$1" | grep -q '^--'; do + if echo $1 | grep -q =; then + o=$(echo "$1" | cut -d= -f1 | sed -e 's,-,_,g') + v=$(echo "$1" | cut -d= -f2-) + eval "$o=\"$v\"" + else + o=$(echo "$1" | sed -e 's,-,_,g') + eval "$o=yes" + fi + shift +done +unset o v +long_opts=`set | grep '^__' | cut -d= -f1` + +# Execute command +trap "die Interrupted" INT TERM +cmd_$cmd "$@" +status=$? +rm -rf $tmp +exit $status diff --git a/ovl/ovs/tar b/ovl/ovs/tar new file mode 100755 index 00000000..404d47cd --- /dev/null +++ b/ovl/ovs/tar @@ -0,0 +1,45 @@ +#! /bin/sh +# NOTE: A common pattern is to specify "-" (stdout) as out-file, +# so there must be NO log printouts to stdout! + +dir=$(dirname $0); dir=$(readlink -f $dir) +tmp=/tmp/$USER/xcluster_$$ +die() { + echo "ERROR: $*" >&2 + rm -rf $tmp + exit 1 +} +log() { + echo "INFO: $*" >&2 +} + +test -n "$1" || die "No out-file" + +mkdir -p $tmp +cp -R $dir/default/* $tmp + +eval $($dir/ovs.sh env | grep SYSD) +OVSD=$SYSD/usr/local +test -x $OVSD/bin/ovs-vsctl || die "Ovs not built?" +$XCLUSTER install_prog --dest=$tmp $OVSD/sbin/ovs* +$XCLUSTER install_prog --dest=$tmp $OVSD/bin/ovs* +mkdir -p $tmp/usr/local/share +cp -R $OVSD/share/openvswitch $tmp/usr/local/share +rm -r $tmp/usr/local/share/openvswitch/python +eval $($XCLUSTER env | grep __kobj) +bpflibd=$(readlink -f $__kobj/source)/tools/lib/bpf/build/usr +f=$bpflibd/lib64/libbpf.so.0 +if test -r $f; then + log "Including libbpf.so" + mkdir -p $tmp/usr/lib/x86_64-linux-gnu + cp -L $f $tmp/usr/lib/x86_64-linux-gnu +else + log "NOT including libbpf.so" +fi + +$XCLUSTER install_prog --dest=$tmp jq + +cd $tmp +tar cf "$1" * +cd - > /dev/null +rm -rf $tmp