From 46b0cc35f1e30ad67ab88cc46d7c3ef40e7aaa38 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 10:11:43 +0100 Subject: [PATCH 01/27] drop IP/network from 'weave launch' plus a whole bunch of other small changes to weave script which I'll eventually extract into separate commits. --- weave | 96 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/weave b/weave index e83d11e4..fa6378df 100755 --- a/weave +++ b/weave @@ -3,7 +3,7 @@ set -e usage() { echo "Usage:" - echo "weave launch [-password ] ..." + echo "weave launch [-password ] ..." echo "weave run ..." echo "weave attach " echo "weave detach " @@ -72,8 +72,14 @@ add_iptables_rule() { fi } -add_nat_rule() { - add_iptables_rule nat "$@" +# Delete a rule from iptables, if it exist +delete_iptables_rule() { + IPTABLES_TABLE="$1" + shift 1 + if run_iptables -t $IPTABLES_TABLE -C "$@" >/dev/null 2>&1 + then + run_iptables -t $IPTABLES_TABLE -D "$@" >/dev/null + fi } create_bridge() { @@ -92,6 +98,9 @@ create_bridge() { # Work around the situation where there are no rules allowing traffic # across our bridge. E.g. ufw add_iptables_rule filter FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT + # create a chain for masquerading + run_iptables -t nat -N WEAVE >/dev/null 2>&1 || true + add_iptables_rule nat POSTROUTING -j WEAVE } ip link set dev $BRIDGE up } @@ -101,16 +110,6 @@ destroy_bridge() { ip link del dev $BRIDGE fi run_iptables -t filter -D FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT 2>/dev/null || true -} - -setup_masquerading() { - run_iptables -t nat -N WEAVE >/dev/null 2>&1 || true - add_nat_rule POSTROUTING -j WEAVE - add_nat_rule WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE - add_nat_rule WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE -} - -stop_masquerading() { run_iptables -t nat -F WEAVE >/dev/null 2>&1 || true run_iptables -t nat -D POSTROUTING -j WEAVE >/dev/null 2>&1 || true run_iptables -t nat -X WEAVE >/dev/null 2>&1 || true @@ -118,7 +117,7 @@ stop_masquerading() { # the following borrows from https://github.com/jpetazzo/pipework with_container_netns () { - CONTAINER="$2" + CONTAINER="$1" CONTAINER_PID=$(docker inspect --format='{{ .State.Pid }}' $CONTAINER) if [ "$CONTAINER_PID" = 0 ] ; then @@ -143,6 +142,7 @@ with_container_netns () { # Run the wrapped command STATUS=0 + shift 1 if ! "$@" >$IP_TMPFILE 2>&1 ; then STATUS=1 if [ "$(docker inspect --format='{{ .State.Pid }}' $CONTAINER)" != "$CONTAINER_PID" ] ; then @@ -157,19 +157,34 @@ with_container_netns () { return $STATUS } -# Attach Container-ID $1 to the weave network at CIDR address $2, -# creating a virtual ethernet device if necessary. -# Also turn off tx offload on device $3 inside the namespace. +launch() { + if ! ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU ; then + return 1 + fi + if ! ip link set $GUEST_IFNAME netns $NETNS ; then + # failed before we assigned the veth to the container's + # namespace - delete it + ip link del $LOCAL_IFNAME type veth || true + return 1 + fi + + ip link set $LOCAL_IFNAME master $BRIDGE + ip link set $LOCAL_IFNAME up + ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME + ip netns exec $NETNS ip link set $CONTAINER_IFNAME up + check_command_and_run ethtool ip netns exec $NETNS ethtool -K eth0 tx off >/dev/null +} + attach() { if ip link show $LOCAL_IFNAME >/dev/null 2>&1 ; then # veth name already exists, so assume we set it up already; # just add the IP address. - if ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $2 >/dev/null ; then + if ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $1 >/dev/null ; then # address was there already return 0 fi - if ! ip netns exec $NETNS ip addr add $2 dev $CONTAINER_IFNAME ; then + if ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME ; then return 1 fi @@ -190,9 +205,9 @@ attach() { fi if ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME || - ! ip netns exec $NETNS ip addr add $2 dev $CONTAINER_IFNAME || + ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME || ! ip netns exec $NETNS ip link set $CONTAINER_IFNAME up || - ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $3 tx off >/dev/null ; then + ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $CONTAINER_IFNAME tx off >/dev/null ; then return 1 fi @@ -205,15 +220,13 @@ attach() { ip netns exec $NETNS ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME } -# Detach Container-ID $1 at CIDR address $2 from the weave network -# removing the virtual ethernet device if there are no more addresses detach() { - if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $2 >/dev/null ; then + if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $1 >/dev/null ; then # address is not there, leave the device alone return 0 fi - if ! ip netns exec $NETNS ip addr del $2 dev $CONTAINER_IFNAME ; then + if ! ip netns exec $NETNS ip addr del $1 dev $CONTAINER_IFNAME ; then return 1 fi @@ -228,9 +241,6 @@ detach() { case "$COMMAND" in launch) - [ $# -gt 0 ] || usage - IPADDR=$1 - shift 1 case $(docker inspect --format '{{ .State.Running }} {{ .Config.Image }}' weave 2>/dev/null) in "true $IMAGE") echo "Weave is already running." >&2 @@ -249,8 +259,6 @@ case "$COMMAND" in ;; esac create_bridge - stop_masquerading - setup_masquerading $IPADDR # We set the router name to the bridge mac since that is # stable across re-creations of the containers. # @@ -262,7 +270,7 @@ case "$COMMAND" in # additional parameters, such as resource limits, to docker # when launching the weave container. CONTAINER=$(docker run --privileged -d --name=weave -p 6783:6783/tcp -p 6783:6783/udp $WEAVE_DOCKER_ARGS $IMAGE -name $MACADDR "$@" | tail -n 1) - with_container_netns attach $CONTAINER $IPADDR eth0 + with_container_netns $CONTAINER launch echo $CONTAINER ;; status) @@ -295,40 +303,40 @@ case "$COMMAND" in ;; run) [ $# -gt 0 ] || usage - IPADDR=$1 + CIDR=$1 shift 1 create_bridge CONTAINER=$(docker run -d "$@" | tail -n 1) - with_container_netns attach $CONTAINER $IPADDR $CONTAINER_IFNAME + with_container_netns $CONTAINER attach $CIDR echo $CONTAINER ;; attach) [ $# -gt 1 ] || usage create_bridge - with_container_netns attach $2 $1 $CONTAINER_IFNAME + with_container_netns $2 attach $1 ;; detach) [ $# -gt 1 ] || usage - with_container_netns detach $2 $1 + with_container_netns $2 detach $1 ;; expose) [ $# -gt 0 ] || usage - IPADDR=$1 - shift 1 create_bridge - if ! ip addr show dev $BRIDGE | grep -qF $IPADDR + if ! ip addr show dev $BRIDGE | grep -qF $1 then - ip addr add dev $BRIDGE $IPADDR + ip addr add dev $BRIDGE $1 + add_iptables_rule nat WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE + add_iptables_rule nat WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE fi ;; hide) [ $# -gt 0 ] || usage - IPADDR=$1 - shift 1 create_bridge - if ip addr show dev $BRIDGE | grep -qF $IPADDR + if ip addr show dev $BRIDGE | grep -qF $1 then - ip addr del dev $BRIDGE $IPADDR + ip addr del dev $BRIDGE $1 + delete_iptables_rule nat WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE + delete_iptables_rule nat WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE fi ;; stop) @@ -337,13 +345,11 @@ case "$COMMAND" in fi docker rm -f weave >/dev/null 2>&1 || true check_command_and_run conntrack conntrack -D -p udp --dport 6783 >/dev/null 2>&1 || true - stop_masquerading ;; reset) docker kill weave >/dev/null 2>&1 || true docker rm -f weave >/dev/null 2>&1 || true check_command_and_run conntrack conntrack -D -p udp --dport 6783 >/dev/null 2>&1 || true - stop_masquerading destroy_bridge ;; *) From 0adda9eae90dd57193cf00d35effd9e9250505ed Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 10:11:43 +0100 Subject: [PATCH 02/27] drop IP/network from 'weave launch' plus a whole bunch of other small changes to weave script which I'll eventually extract into separate commits. --- weave | 96 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/weave b/weave index ea6d9a9f..a3231e67 100755 --- a/weave +++ b/weave @@ -3,7 +3,7 @@ set -e usage() { echo "Usage:" - echo "weave launch [-password ] ..." + echo "weave launch [-password ] ..." echo "weave run ..." echo "weave start " echo "weave attach " @@ -73,8 +73,14 @@ add_iptables_rule() { fi } -add_nat_rule() { - add_iptables_rule nat "$@" +# Delete a rule from iptables, if it exist +delete_iptables_rule() { + IPTABLES_TABLE="$1" + shift 1 + if run_iptables -t $IPTABLES_TABLE -C "$@" >/dev/null 2>&1 + then + run_iptables -t $IPTABLES_TABLE -D "$@" >/dev/null + fi } create_bridge() { @@ -93,6 +99,9 @@ create_bridge() { # Work around the situation where there are no rules allowing traffic # across our bridge. E.g. ufw add_iptables_rule filter FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT + # create a chain for masquerading + run_iptables -t nat -N WEAVE >/dev/null 2>&1 || true + add_iptables_rule nat POSTROUTING -j WEAVE } ip link set dev $BRIDGE up } @@ -102,16 +111,6 @@ destroy_bridge() { ip link del dev $BRIDGE fi run_iptables -t filter -D FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT 2>/dev/null || true -} - -setup_masquerading() { - run_iptables -t nat -N WEAVE >/dev/null 2>&1 || true - add_nat_rule POSTROUTING -j WEAVE - add_nat_rule WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE - add_nat_rule WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE -} - -stop_masquerading() { run_iptables -t nat -F WEAVE >/dev/null 2>&1 || true run_iptables -t nat -D POSTROUTING -j WEAVE >/dev/null 2>&1 || true run_iptables -t nat -X WEAVE >/dev/null 2>&1 || true @@ -119,7 +118,7 @@ stop_masquerading() { # the following borrows from https://github.com/jpetazzo/pipework with_container_netns () { - CONTAINER="$2" + CONTAINER="$1" CONTAINER_PID=$(docker inspect --format='{{ .State.Pid }}' $CONTAINER) if [ "$CONTAINER_PID" = 0 ] ; then @@ -144,6 +143,7 @@ with_container_netns () { # Run the wrapped command STATUS=0 + shift 1 if ! "$@" >$IP_TMPFILE 2>&1 ; then STATUS=1 if [ "$(docker inspect --format='{{ .State.Pid }}' $CONTAINER)" != "$CONTAINER_PID" ] ; then @@ -158,19 +158,34 @@ with_container_netns () { return $STATUS } -# Attach Container-ID $1 to the weave network at CIDR address $2, -# creating a virtual ethernet device if necessary. -# Also turn off tx offload on device $3 inside the namespace. +launch() { + if ! ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU ; then + return 1 + fi + if ! ip link set $GUEST_IFNAME netns $NETNS ; then + # failed before we assigned the veth to the container's + # namespace - delete it + ip link del $LOCAL_IFNAME type veth || true + return 1 + fi + + ip link set $LOCAL_IFNAME master $BRIDGE + ip link set $LOCAL_IFNAME up + ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME + ip netns exec $NETNS ip link set $CONTAINER_IFNAME up + check_command_and_run ethtool ip netns exec $NETNS ethtool -K eth0 tx off >/dev/null +} + attach() { if ip link show $LOCAL_IFNAME >/dev/null 2>&1 ; then # veth name already exists, so assume we set it up already; # just add the IP address. - if ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $2 >/dev/null ; then + if ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $1 >/dev/null ; then # address was there already return 0 fi - if ! ip netns exec $NETNS ip addr add $2 dev $CONTAINER_IFNAME ; then + if ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME ; then return 1 fi @@ -191,9 +206,9 @@ attach() { fi if ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME || - ! ip netns exec $NETNS ip addr add $2 dev $CONTAINER_IFNAME || + ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME || ! ip netns exec $NETNS ip link set $CONTAINER_IFNAME up || - ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $3 tx off >/dev/null ; then + ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $CONTAINER_IFNAME tx off >/dev/null ; then return 1 fi @@ -206,15 +221,13 @@ attach() { ip netns exec $NETNS ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME } -# Detach Container-ID $1 at CIDR address $2 from the weave network -# removing the virtual ethernet device if there are no more addresses detach() { - if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $2 >/dev/null ; then + if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $1 >/dev/null ; then # address is not there, leave the device alone return 0 fi - if ! ip netns exec $NETNS ip addr del $2 dev $CONTAINER_IFNAME ; then + if ! ip netns exec $NETNS ip addr del $1 dev $CONTAINER_IFNAME ; then return 1 fi @@ -229,9 +242,6 @@ detach() { case "$COMMAND" in launch) - [ $# -gt 0 ] || usage - IPADDR=$1 - shift 1 case $(docker inspect --format '{{ .State.Running }} {{ .Config.Image }}' weave 2>/dev/null) in "true $IMAGE") echo "Weave is already running." >&2 @@ -250,8 +260,6 @@ case "$COMMAND" in ;; esac create_bridge - stop_masquerading - setup_masquerading $IPADDR # We set the router name to the bridge mac since that is # stable across re-creations of the containers. # @@ -263,7 +271,7 @@ case "$COMMAND" in # additional parameters, such as resource limits, to docker # when launching the weave container. CONTAINER=$(docker run --privileged -d --name=weave -p 6783:6783/tcp -p 6783:6783/udp $WEAVE_DOCKER_ARGS $IMAGE -name $MACADDR "$@" | tail -n 1) - with_container_netns attach $CONTAINER $IPADDR eth0 + with_container_netns $CONTAINER launch echo $CONTAINER ;; status) @@ -296,11 +304,11 @@ case "$COMMAND" in ;; run) [ $# -gt 0 ] || usage - IPADDR=$1 + CIDR=$1 shift 1 create_bridge CONTAINER=$(docker run -d "$@" | tail -n 1) - with_container_netns attach $CONTAINER $IPADDR $CONTAINER_IFNAME + with_container_netns $CONTAINER attach $CIDR echo $CONTAINER ;; start) @@ -314,30 +322,30 @@ case "$COMMAND" in attach) [ $# -gt 1 ] || usage create_bridge - with_container_netns attach $2 $1 $CONTAINER_IFNAME + with_container_netns $2 attach $1 ;; detach) [ $# -gt 1 ] || usage - with_container_netns detach $2 $1 + with_container_netns $2 detach $1 ;; expose) [ $# -gt 0 ] || usage - IPADDR=$1 - shift 1 create_bridge - if ! ip addr show dev $BRIDGE | grep -qF $IPADDR + if ! ip addr show dev $BRIDGE | grep -qF $1 then - ip addr add dev $BRIDGE $IPADDR + ip addr add dev $BRIDGE $1 + add_iptables_rule nat WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE + add_iptables_rule nat WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE fi ;; hide) [ $# -gt 0 ] || usage - IPADDR=$1 - shift 1 create_bridge - if ip addr show dev $BRIDGE | grep -qF $IPADDR + if ip addr show dev $BRIDGE | grep -qF $1 then - ip addr del dev $BRIDGE $IPADDR + ip addr del dev $BRIDGE $1 + delete_iptables_rule nat WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE + delete_iptables_rule nat WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE fi ;; stop) @@ -346,13 +354,11 @@ case "$COMMAND" in fi docker rm -f weave >/dev/null 2>&1 || true check_command_and_run conntrack conntrack -D -p udp --dport 6783 >/dev/null 2>&1 || true - stop_masquerading ;; reset) docker kill weave >/dev/null 2>&1 || true docker rm -f weave >/dev/null 2>&1 || true check_command_and_run conntrack conntrack -D -p udp --dport 6783 >/dev/null 2>&1 || true - stop_masquerading destroy_bridge ;; *) From 85787f2d4e266bfd8aa32ceb2f8dd286c4698882 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 10:21:02 +0100 Subject: [PATCH 03/27] fix 'weave start' post rebase --- weave | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/weave b/weave index a3231e67..1df5e49b 100755 --- a/weave +++ b/weave @@ -313,10 +313,9 @@ case "$COMMAND" in ;; start) [ $# -gt 1 ] || usage - IPADDR=$1 create_bridge CONTAINER=$(docker start $2) - with_container_netns attach $CONTAINER $IPADDR $CONTAINER_IFNAME + with_container_netns $CONTAINER attach $1 echo $CONTAINER ;; attach) From 7a53efe66c4be087142906c593ff4e131f792d95 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 11:27:32 +0100 Subject: [PATCH 04/27] get error handling right --- weave | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/weave b/weave index 1df5e49b..eb62ad64 100755 --- a/weave +++ b/weave @@ -169,10 +169,10 @@ launch() { return 1 fi - ip link set $LOCAL_IFNAME master $BRIDGE - ip link set $LOCAL_IFNAME up - ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME - ip netns exec $NETNS ip link set $CONTAINER_IFNAME up + ip link set $LOCAL_IFNAME master $BRIDGE && + ip link set $LOCAL_IFNAME up && + ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME && + ip netns exec $NETNS ip link set $CONTAINER_IFNAME up && check_command_and_run ethtool ip netns exec $NETNS ethtool -K eth0 tx off >/dev/null } From 9b90e119e5da75a0f27ffae355abd423096b0ba6 Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Fri, 24 Oct 2014 11:38:10 +0100 Subject: [PATCH 05/27] Say 'name' instead of 'identity' in log and status --- router/router.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router/router.go b/router/router.go index 34541035..89ea43ea 100644 --- a/router/router.go +++ b/router/router.go @@ -34,7 +34,7 @@ func NewRouter(iface *net.Interface, name PeerName, password []byte, connLimit i ourself := NewPeer(name, 0, 0, router) router.Ourself = router.Peers.FetchWithDefault(ourself) router.Ourself.StartLocalPeer() - log.Println("Local identity is", router.Ourself.Name) + log.Println("Our name is", router.Ourself.Name) return router } @@ -58,7 +58,7 @@ func (router *Router) Start() { func (router *Router) Status() string { var buf bytes.Buffer - buf.WriteString(fmt.Sprintln("Local identity is", router.Ourself.Name)) + buf.WriteString(fmt.Sprintln("Our name is", router.Ourself.Name)) buf.WriteString(fmt.Sprintln("Sniffing traffic on", router.Iface)) buf.WriteString(fmt.Sprintf("MACs:\n%s", router.Macs)) buf.WriteString(fmt.Sprintf("Peers:\n%s", router.Peers)) From 579f3469c8d6cad7db75db4d5b2e9614eec3dec3 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 12:30:42 +0100 Subject: [PATCH 06/27] simplify code for attach --- weave | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/weave b/weave index eb62ad64..796effef 100755 --- a/weave +++ b/weave @@ -196,29 +196,26 @@ attach() { return 1 fi - if ! ip link set $LOCAL_IFNAME master $BRIDGE || - ! ip link set $LOCAL_IFNAME up || - ! ip link set $GUEST_IFNAME netns $NETNS ; then + if ! ip link set $GUEST_IFNAME netns $NETNS ; then # failed before we assigned the veth to the container's # namespace - delete it ip link del $LOCAL_IFNAME type veth || true return 1 fi - if ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME || + if ! ip link set $LOCAL_IFNAME master $BRIDGE || + ! ip link set $LOCAL_IFNAME up || + ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME || ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME || ! ip netns exec $NETNS ip link set $CONTAINER_IFNAME up || ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $CONTAINER_IFNAME tx off >/dev/null ; then return 1 fi - if ip netns exec $NETNS ip route show | grep '^224\.0\.0\.0/4' >/dev/null ; then - # There's a multicast route already present, leave it alone. - return 0 - fi - # Route multicast packets across the weave network. - ip netns exec $NETNS ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME + if ! ip netns exec $NETNS ip route show | grep '^224\.0\.0\.0/4' >/dev/null ; then + ip netns exec $NETNS ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME + fi } detach() { From 34e240c4a5e2a8dad869efe03e90929ffa05ad95 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 12:49:04 +0100 Subject: [PATCH 07/27] remove misleading comment... attach() and detach() are never invoked directly, plus it's really not that hard to figure out what they do. --- weave | 5 ----- 1 file changed, 5 deletions(-) diff --git a/weave b/weave index ea6d9a9f..b91bbc6a 100755 --- a/weave +++ b/weave @@ -158,9 +158,6 @@ with_container_netns () { return $STATUS } -# Attach Container-ID $1 to the weave network at CIDR address $2, -# creating a virtual ethernet device if necessary. -# Also turn off tx offload on device $3 inside the namespace. attach() { if ip link show $LOCAL_IFNAME >/dev/null 2>&1 ; then # veth name already exists, so assume we set it up already; @@ -206,8 +203,6 @@ attach() { ip netns exec $NETNS ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME } -# Detach Container-ID $1 at CIDR address $2 from the weave network -# removing the virtual ethernet device if there are no more addresses detach() { if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $2 >/dev/null ; then # address is not there, leave the device alone From 6501934a15e9ddf3ec2b2a2971ccdb80c4001769 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 12:50:29 +0100 Subject: [PATCH 08/27] make with_container_netns take the container as the first arg and invoke the subsequent command. This is closer to typical 'with' semantics. --- weave | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/weave b/weave index b91bbc6a..c5b460fa 100755 --- a/weave +++ b/weave @@ -119,7 +119,7 @@ stop_masquerading() { # the following borrows from https://github.com/jpetazzo/pipework with_container_netns () { - CONTAINER="$2" + CONTAINER="$1" CONTAINER_PID=$(docker inspect --format='{{ .State.Pid }}' $CONTAINER) if [ "$CONTAINER_PID" = 0 ] ; then @@ -144,6 +144,7 @@ with_container_netns () { # Run the wrapped command STATUS=0 + shift 1 if ! "$@" >$IP_TMPFILE 2>&1 ; then STATUS=1 if [ "$(docker inspect --format='{{ .State.Pid }}' $CONTAINER)" != "$CONTAINER_PID" ] ; then @@ -162,12 +163,12 @@ attach() { if ip link show $LOCAL_IFNAME >/dev/null 2>&1 ; then # veth name already exists, so assume we set it up already; # just add the IP address. - if ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $2 >/dev/null ; then + if ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $1 >/dev/null ; then # address was there already return 0 fi - if ! ip netns exec $NETNS ip addr add $2 dev $CONTAINER_IFNAME ; then + if ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME ; then return 1 fi @@ -188,9 +189,9 @@ attach() { fi if ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME || - ! ip netns exec $NETNS ip addr add $2 dev $CONTAINER_IFNAME || + ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME || ! ip netns exec $NETNS ip link set $CONTAINER_IFNAME up || - ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $3 tx off >/dev/null ; then + ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $2 tx off >/dev/null ; then return 1 fi @@ -204,12 +205,12 @@ attach() { } detach() { - if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $2 >/dev/null ; then + if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $1 >/dev/null ; then # address is not there, leave the device alone return 0 fi - if ! ip netns exec $NETNS ip addr del $2 dev $CONTAINER_IFNAME ; then + if ! ip netns exec $NETNS ip addr del $1 dev $CONTAINER_IFNAME ; then return 1 fi @@ -258,7 +259,7 @@ case "$COMMAND" in # additional parameters, such as resource limits, to docker # when launching the weave container. CONTAINER=$(docker run --privileged -d --name=weave -p 6783:6783/tcp -p 6783:6783/udp $WEAVE_DOCKER_ARGS $IMAGE -name $MACADDR "$@" | tail -n 1) - with_container_netns attach $CONTAINER $IPADDR eth0 + with_container_netns $CONTAINER attach $IPADDR eth0 echo $CONTAINER ;; status) @@ -295,7 +296,7 @@ case "$COMMAND" in shift 1 create_bridge CONTAINER=$(docker run -d "$@" | tail -n 1) - with_container_netns attach $CONTAINER $IPADDR $CONTAINER_IFNAME + with_container_netns $CONTAINER attach $IPADDR $CONTAINER_IFNAME echo $CONTAINER ;; start) @@ -303,17 +304,17 @@ case "$COMMAND" in IPADDR=$1 create_bridge CONTAINER=$(docker start $2) - with_container_netns attach $CONTAINER $IPADDR $CONTAINER_IFNAME + with_container_netns $CONTAINER attach $IPADDR $CONTAINER_IFNAME echo $CONTAINER ;; attach) [ $# -gt 1 ] || usage create_bridge - with_container_netns attach $2 $1 $CONTAINER_IFNAME + with_container_netns $2 attach $1 $CONTAINER_IFNAME ;; detach) [ $# -gt 1 ] || usage - with_container_netns detach $2 $1 + with_container_netns $2 detach $1 ;; expose) [ $# -gt 0 ] || usage From 5b6a892c38ec926d0c4c1b28debfc9a242f03989 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 12:57:35 +0100 Subject: [PATCH 09/27] refactor: don't extract param to var and shift unless we have to --- weave | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/weave b/weave index c5b460fa..5f987f0d 100755 --- a/weave +++ b/weave @@ -301,10 +301,9 @@ case "$COMMAND" in ;; start) [ $# -gt 1 ] || usage - IPADDR=$1 create_bridge CONTAINER=$(docker start $2) - with_container_netns $CONTAINER attach $IPADDR $CONTAINER_IFNAME + with_container_netns $CONTAINER attach $1 $CONTAINER_IFNAME echo $CONTAINER ;; attach) @@ -318,22 +317,18 @@ case "$COMMAND" in ;; expose) [ $# -gt 0 ] || usage - IPADDR=$1 - shift 1 create_bridge - if ! ip addr show dev $BRIDGE | grep -qF $IPADDR + if ! ip addr show dev $BRIDGE | grep -qF $1 then - ip addr add dev $BRIDGE $IPADDR + ip addr add dev $BRIDGE $1 fi ;; hide) [ $# -gt 0 ] || usage - IPADDR=$1 - shift 1 create_bridge - if ip addr show dev $BRIDGE | grep -qF $IPADDR + if ip addr show dev $BRIDGE | grep -qF $1 then - ip addr del dev $BRIDGE $IPADDR + ip addr del dev $BRIDGE $1 fi ;; stop) From 093b23fa83b2d591c883c7d48a36a4a70220c4b8 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 12:59:47 +0100 Subject: [PATCH 10/27] refactor: it's not an IPADDR but a CIDR --- weave | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/weave b/weave index 5f987f0d..f99c47bf 100755 --- a/weave +++ b/weave @@ -226,7 +226,7 @@ detach() { case "$COMMAND" in launch) [ $# -gt 0 ] || usage - IPADDR=$1 + CIDR=$1 shift 1 case $(docker inspect --format '{{ .State.Running }} {{ .Config.Image }}' weave 2>/dev/null) in "true $IMAGE") @@ -247,7 +247,7 @@ case "$COMMAND" in esac create_bridge stop_masquerading - setup_masquerading $IPADDR + setup_masquerading $CIDR # We set the router name to the bridge mac since that is # stable across re-creations of the containers. # @@ -259,7 +259,7 @@ case "$COMMAND" in # additional parameters, such as resource limits, to docker # when launching the weave container. CONTAINER=$(docker run --privileged -d --name=weave -p 6783:6783/tcp -p 6783:6783/udp $WEAVE_DOCKER_ARGS $IMAGE -name $MACADDR "$@" | tail -n 1) - with_container_netns $CONTAINER attach $IPADDR eth0 + with_container_netns $CONTAINER attach $CIDR eth0 echo $CONTAINER ;; status) @@ -292,11 +292,11 @@ case "$COMMAND" in ;; run) [ $# -gt 0 ] || usage - IPADDR=$1 + CIDR=$1 shift 1 create_bridge CONTAINER=$(docker run -d "$@" | tail -n 1) - with_container_netns $CONTAINER attach $IPADDR $CONTAINER_IFNAME + with_container_netns $CONTAINER attach $CIDR $CONTAINER_IFNAME echo $CONTAINER ;; start) From de96742935c306da6d27f8ff562f6040e7713dfc Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 13:03:28 +0100 Subject: [PATCH 11/27] refactor: remove add_nat_rule it did too little to be worthwhile --- weave | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/weave b/weave index f99c47bf..ecb8d416 100755 --- a/weave +++ b/weave @@ -73,10 +73,6 @@ add_iptables_rule() { fi } -add_nat_rule() { - add_iptables_rule nat "$@" -} - create_bridge() { [ ! -d /sys/class/net/$BRIDGE ] && { ip link add name $BRIDGE type bridge @@ -106,9 +102,9 @@ destroy_bridge() { setup_masquerading() { run_iptables -t nat -N WEAVE >/dev/null 2>&1 || true - add_nat_rule POSTROUTING -j WEAVE - add_nat_rule WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE - add_nat_rule WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE + add_iptables_rule nat POSTROUTING -j WEAVE + add_iptables_rule nat WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE + add_iptables_rule nat WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE } stop_masquerading() { From 560cbabb54dfd95008242f3972c304df555f7b43 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 13:13:34 +0100 Subject: [PATCH 12/27] refactor: simplify 'attach' Move the interface into the container network NS asap, which simplifies error handling. --- weave | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/weave b/weave index ecb8d416..8afcf009 100755 --- a/weave +++ b/weave @@ -175,16 +175,16 @@ attach() { return 1 fi - if ! ip link set $LOCAL_IFNAME master $BRIDGE || - ! ip link set $LOCAL_IFNAME up || - ! ip link set $GUEST_IFNAME netns $NETNS ; then + if ! ip link set $GUEST_IFNAME netns $NETNS ; then # failed before we assigned the veth to the container's # namespace - delete it ip link del $LOCAL_IFNAME type veth || true return 1 fi - if ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME || + if ! ip link set $LOCAL_IFNAME master $BRIDGE || + ! ip link set $LOCAL_IFNAME up || + ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME || ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME || ! ip netns exec $NETNS ip link set $CONTAINER_IFNAME up || ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $2 tx off >/dev/null ; then From 00a4a5e056a565e81822af201987ff65bae00450 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 13:15:15 +0100 Subject: [PATCH 13/27] refactor: simplify multicast route addition in 'attach' --- weave | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/weave b/weave index 8afcf009..176461c5 100755 --- a/weave +++ b/weave @@ -191,13 +191,10 @@ attach() { return 1 fi - if ip netns exec $NETNS ip route show | grep '^224\.0\.0\.0/4' >/dev/null ; then - # There's a multicast route already present, leave it alone. - return 0 - fi - # Route multicast packets across the weave network. - ip netns exec $NETNS ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME + if ! ip netns exec $NETNS ip route show | grep '^224\.0\.0\.0/4' >/dev/null ; then + ip netns exec $NETNS ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME + fi } detach() { From dba87601872fbefa02fe0bdf7c239ffc7b373f85 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 13:43:15 +0100 Subject: [PATCH 14/27] update README --- README.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c0560220..9886e4e7 100644 --- a/README.md +++ b/README.md @@ -55,20 +55,20 @@ containers, one on each host. On $HOST1 run (as root) - host1# weave launch 10.0.0.1/16 + host1# weave launch host1# C=$(weave run 10.0.1.1/24 -t -i ubuntu) The first line starts the weave router, in a container. This needs to -be done once on each host. We tell weave that its IP address should -be 10.0.0.1, and that the weave network is on 10.0.0.0/16. +be done once on each host. The second line runs our application container. We give it an IP -address and network (a subnet of the weave network). `weave run` -invokes `docker run -d` with all the parameters following the IP -address and network. So we could be launching any container this way; -here we just take a stock ubuntu container and launch a shell in -it. There's also a `weave start` command, which invokes `docker start` -for starting existing containers. +address and network, in +[CIDR notation](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation). +`weave run` invokes `docker run -d` with all the parameters following +the IP address and network. So we could be launching any container +this way; here we just take a stock ubuntu container and launch a +shell in it. There's also a `weave start` command, which invokes +`docker start` for starting existing containers. If our application consists of more than one container on this host we simply launch them with a variation on that second line. @@ -81,15 +81,14 @@ unique. We repeat similar steps on $HOST2... - host2# weave launch 10.0.0.2/16 $HOST1 + host2# weave launch $HOST1 host2# C=$(weave run 10.0.1.2/24 -t -i ubuntu) -The only difference, apart from the choice of IP addresses for the -weave router and the application container, is that we tell our weave -that it should peer with the weave on $HOST1 (specified as the IP -address or hostname by which $HOST2 can reach it). NB: if there is a -firewall between $HOST1 and $HOST2, you must open port 6783 for TCP -and UDP. +The only difference, apart from the choice of IP address for the +application container, is that we tell our weave that it should peer +with the weave on $HOST1 (specified as the IP address or hostname by +which $HOST2 can reach it). NB: if there is a firewall between $HOST1 +and $HOST2, you must open port 6783 for TCP and UDP. Note that we could instead have told the weave on $HOST1 to connect to $HOST2, or told both about each other. Order does not matter here; From 83464a38eb5ed6aef0a1cd40342782fcb9093bce Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 14:30:58 +0100 Subject: [PATCH 15/27] remove explicit multicast detection We don't need. Multicast addresses never appear as sources and hence never end up in the peer_cache. And the router always broadcasts frames with destination addresses that aren't in the peer cache. --- router/ethernet_decoder.go | 14 ++------------ router/router.go | 5 +++-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/router/ethernet_decoder.go b/router/ethernet_decoder.go index 62177383..65051909 100644 --- a/router/ethernet_decoder.go +++ b/router/ethernet_decoder.go @@ -67,24 +67,14 @@ func (dec *EthernetDecoder) formICMPMTUPacket(mtu int) ([]byte, error) { var ( // see http://en.wikipedia.org/wiki/Multicast_address#Ethernet - broadcastMAC, _ = net.ParseMAC("ff:ff:ff:ff:ff:ff") - zeroMAC, _ = net.ParseMAC("00:00:00:00:00:00") - stpMACPrefix = []byte{0x01, 0x80, 0xC2, 0x00, 0x00} - ipv4MulticastMACPrefix = []byte{0x01, 0x00, 0x5E} - ipv6MulticastMACPrefix = []byte{0x33, 0x33} + stpMACPrefix = []byte{0x01, 0x80, 0xC2, 0x00, 0x00} + zeroMAC, _ = net.ParseMAC("00:00:00:00:00:00") ) func (dec *EthernetDecoder) DropFrame() bool { return bytes.Equal(stpMACPrefix, dec.eth.DstMAC[:len(stpMACPrefix)]) } -func (dec *EthernetDecoder) BroadcastFrame() bool { - return bytes.Equal(broadcastMAC, dec.eth.DstMAC) || - // treat multicast frames as broadcast - bytes.Equal(ipv4MulticastMACPrefix, dec.eth.DstMAC[:len(ipv4MulticastMACPrefix)]) || - bytes.Equal(ipv6MulticastMACPrefix, dec.eth.DstMAC[:len(ipv6MulticastMACPrefix)]) -} - func (dec *EthernetDecoder) IsPMTUVerify() bool { return bytes.Equal(zeroMAC, dec.eth.SrcMAC) && bytes.Equal(zeroMAC, dec.eth.DstMAC) diff --git a/router/router.go b/router/router.go index 89ea43ea..5d29ff70 100644 --- a/router/router.go +++ b/router/router.go @@ -124,7 +124,8 @@ func (router *Router) handleCapturedPacket(frameData []byte, dec *EthernetDecode frameLen := len(frameData) frameCopy := make([]byte, frameLen, frameLen) copy(frameCopy, frameData) - if !found || dec.BroadcastFrame() { + + if !found { return checkFrameTooBig(router.Ourself.Broadcast(df, frameCopy, dec)) } else { return checkFrameTooBig(router.Ourself.Forward(dstPeer, df, frameCopy, dec)) @@ -287,7 +288,7 @@ func (router *Router) handleUDPPacketFunc(dec *EthernetDecoder, po PacketSink) F checkWarn(po.WritePacket(frame)) dstPeer, found = router.Macs.Lookup(dec.eth.DstMAC) - if !found || dec.BroadcastFrame() || dstPeer != router.Ourself { + if !found || dstPeer != router.Ourself { return checkFrameTooBig(router.Ourself.RelayBroadcast(srcPeer, df, frame, dec), srcPeer) } From d3ba6746a56c236a585caab110925ef6a39d69ea Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 15:36:54 +0100 Subject: [PATCH 16/27] backward compatibility --- weave | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/weave b/weave index 796effef..cc8f9986 100755 --- a/weave +++ b/weave @@ -264,6 +264,12 @@ case "$COMMAND" in # (eth0, wlan0, etc) so the name becomes stable across host # restarts. MACADDR=`cat /sys/class/net/$BRIDGE/address` + # Backward compatibility... Note that the regexp here is far + # from precise, but good enough. + if echo "$1" | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$' >/dev/null ; then + echo "WARNING: $1 parameter swallowed; 'weave launch' no longer takes a CIDR as the first parameter" >&2 + shift 1 + fi # Set WEAVE_DOCKER_ARGS in the environment in order to supply # additional parameters, such as resource limits, to docker # when launching the weave container. From 76a974f88bcf1c9293a190834e047f6739fcd5ba Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 16:07:06 +0100 Subject: [PATCH 17/27] refactor: maintain abstraction --- weave | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/weave b/weave index 176461c5..3ab4bdbd 100755 --- a/weave +++ b/weave @@ -207,7 +207,7 @@ detach() { return 1 fi - if [ -n "$(ip netns exec $NETNS ip -f inet addr show dev ethwe)" ] ; then + if [ -n "$(ip netns exec $NETNS ip -f inet addr show dev $CONTAINER_IFNAME)" ] ; then # other addresses are left, leave the device alone return 0 fi From ce631e7f28d2b2a58168cb14dfa333706a48423b Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Fri, 24 Oct 2014 16:56:58 +0100 Subject: [PATCH 18/27] stricter param count checking --- weave | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/weave b/weave index 3ab4bdbd..302c7ffb 100755 --- a/weave +++ b/weave @@ -256,6 +256,7 @@ case "$COMMAND" in echo $CONTAINER ;; status) + [ $# -eq 0 ] || usage if ! DOCKERIP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' weave 2>/dev/null) ; then echo "Weave is not running." >&2 exit 1 @@ -274,6 +275,7 @@ case "$COMMAND" in fi ;; version) + [ $# -eq 0 ] || usage # Try the running container first; if no luck try the image if ! DOCKERIMAGE=$(docker inspect --format='{{ .Image }}' weave 2>/dev/null) ; then if ! DOCKERIMAGE=$(docker inspect --format='{{ .Id }}' $IMAGE 2>/dev/null) ; then @@ -293,23 +295,23 @@ case "$COMMAND" in echo $CONTAINER ;; start) - [ $# -gt 1 ] || usage + [ $# -eq 2 ] || usage create_bridge CONTAINER=$(docker start $2) with_container_netns $CONTAINER attach $1 $CONTAINER_IFNAME echo $CONTAINER ;; attach) - [ $# -gt 1 ] || usage + [ $# -eq 2 ] || usage create_bridge with_container_netns $2 attach $1 $CONTAINER_IFNAME ;; detach) - [ $# -gt 1 ] || usage + [ $# -eq 2 ] || usage with_container_netns $2 detach $1 ;; expose) - [ $# -gt 0 ] || usage + [ $# -eq 1 ] || usage create_bridge if ! ip addr show dev $BRIDGE | grep -qF $1 then @@ -317,7 +319,7 @@ case "$COMMAND" in fi ;; hide) - [ $# -gt 0 ] || usage + [ $# -eq 1 ] || usage create_bridge if ip addr show dev $BRIDGE | grep -qF $1 then @@ -325,6 +327,7 @@ case "$COMMAND" in fi ;; stop) + [ $# -eq 0 ] || usage if ! docker kill weave >/dev/null 2>&1 ; then echo "Weave is not running." fi @@ -333,6 +336,7 @@ case "$COMMAND" in stop_masquerading ;; reset) + [ $# -eq 0 ] || usage docker kill weave >/dev/null 2>&1 || true docker rm -f weave >/dev/null 2>&1 || true check_command_and_run conntrack conntrack -D -p udp --dport 6783 >/dev/null 2>&1 || true From e265f041827c2e0d4b67d1cfb3cb73a19c4aab3b Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sat, 25 Oct 2014 17:13:44 +0100 Subject: [PATCH 19/27] cosmetic: remove trailing whitespace --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 5ef24b19..c621d770 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -6,7 +6,7 @@ pkgs = "lxc-docker golang ethtool libpcap-dev git mercurial" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = "phusion/ubuntu-14.04-amd64" config.vm.box_url = "https://oss-binaries.phusionpassenger.com/vagrant/boxes/latest/ubuntu-14.04-amd64-vbox.box" - + config.vm.network "private_network", ip: vm_ip config.vm.synced_folder "./", "/home/vagrant/src/github.com/zettio/weave" From e9c5b2c3eaad5b836a0de0a17212051e01daf693 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sat, 25 Oct 2014 19:42:52 +0100 Subject: [PATCH 20/27] refactor: extract weave ports and container name into constants --- weave | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/weave b/weave index 302c7ffb..f0bde4a1 100755 --- a/weave +++ b/weave @@ -33,9 +33,12 @@ command_exists () { [ $# -gt 0 ] || usage IMAGE=zettio/weave +CONTAINER_NAME=weave BRIDGE=weave CONTAINER_IFNAME=ethwe MTU=65535 +PORT=6783 +HTTP_PORT=6784 COMMAND=$1 @@ -221,20 +224,20 @@ case "$COMMAND" in [ $# -gt 0 ] || usage CIDR=$1 shift 1 - case $(docker inspect --format '{{ .State.Running }} {{ .Config.Image }}' weave 2>/dev/null) in + case $(docker inspect --format '{{ .State.Running }} {{ .Config.Image }}' $CONTAINER_NAME 2>/dev/null) in "true $IMAGE") echo "Weave is already running." >&2 exit 1 ;; "false $IMAGE") - docker rm weave >/dev/null + docker rm $CONTAINER_NAME >/dev/null ;; true*) - echo "Found another running container named 'weave'. Aborting." >&2 + echo "Found another running container named '$CONTAINER_NAME'. Aborting." >&2 exit 1 ;; false*) - echo "Found another container named 'weave'. Aborting." >&2 + echo "Found another container named '$CONTAINER_NAME'. Aborting." >&2 exit 1 ;; esac @@ -251,13 +254,13 @@ case "$COMMAND" in # Set WEAVE_DOCKER_ARGS in the environment in order to supply # additional parameters, such as resource limits, to docker # when launching the weave container. - CONTAINER=$(docker run --privileged -d --name=weave -p 6783:6783/tcp -p 6783:6783/udp $WEAVE_DOCKER_ARGS $IMAGE -name $MACADDR "$@" | tail -n 1) + CONTAINER=$(docker run --privileged -d --name=$CONTAINER_NAME -p $PORT:$PORT/tcp -p $PORT:$PORT/udp $WEAVE_DOCKER_ARGS $IMAGE -name $MACADDR "$@" | tail -n 1) with_container_netns $CONTAINER attach $CIDR eth0 echo $CONTAINER ;; status) [ $# -eq 0 ] || usage - if ! DOCKERIP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' weave 2>/dev/null) ; then + if ! DOCKERIP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' $CONTAINER_NAME 2>/dev/null) ; then echo "Weave is not running." >&2 exit 1 fi @@ -266,9 +269,9 @@ case "$COMMAND" in exit 1 fi if command_exists wget ; then - wget -O - -q $DOCKERIP:6784/status + wget -O - -q $DOCKERIP:$HTTP_PORT/status elif command_exists curl ; then - curl $DOCKERIP:6784/status + curl $DOCKERIP:$HTTP_PORT/status else echo "Cannot find wget or curl. Install one of them for 'weave status' to function." >&2 exit 1 @@ -277,7 +280,7 @@ case "$COMMAND" in version) [ $# -eq 0 ] || usage # Try the running container first; if no luck try the image - if ! DOCKERIMAGE=$(docker inspect --format='{{ .Image }}' weave 2>/dev/null) ; then + if ! DOCKERIMAGE=$(docker inspect --format='{{ .Image }}' $CONTAINER_NAME 2>/dev/null) ; then if ! DOCKERIMAGE=$(docker inspect --format='{{ .Id }}' $IMAGE 2>/dev/null) ; then echo "Unable to find $IMAGE image." >&2 exit 1 @@ -328,18 +331,18 @@ case "$COMMAND" in ;; stop) [ $# -eq 0 ] || usage - if ! docker kill weave >/dev/null 2>&1 ; then + if ! docker kill $CONTAINER_NAME >/dev/null 2>&1 ; then echo "Weave is not running." fi - docker rm -f weave >/dev/null 2>&1 || true - check_command_and_run conntrack conntrack -D -p udp --dport 6783 >/dev/null 2>&1 || true + docker rm -f $CONTAINER_NAME >/dev/null 2>&1 || true + check_command_and_run conntrack conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true stop_masquerading ;; reset) [ $# -eq 0 ] || usage - docker kill weave >/dev/null 2>&1 || true - docker rm -f weave >/dev/null 2>&1 || true - check_command_and_run conntrack conntrack -D -p udp --dport 6783 >/dev/null 2>&1 || true + docker kill $CONTAINER_NAME >/dev/null 2>&1 || true + docker rm -f $CONTAINER_NAME >/dev/null 2>&1 || true + check_command_and_run conntrack conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true stop_masquerading destroy_bridge ;; From 007b68c206e5a63b3888c22591e8dd12fef30562 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sat, 25 Oct 2014 19:51:06 +0100 Subject: [PATCH 21/27] explain that peer can be specified as fqdn and contain optional port Closes #137. --- README.md | 6 +++--- weave | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c0560220..d6183f66 100644 --- a/README.md +++ b/README.md @@ -87,9 +87,9 @@ We repeat similar steps on $HOST2... The only difference, apart from the choice of IP addresses for the weave router and the application container, is that we tell our weave that it should peer with the weave on $HOST1 (specified as the IP -address or hostname by which $HOST2 can reach it). NB: if there is a -firewall between $HOST1 and $HOST2, you must open port 6783 for TCP -and UDP. +address or hostname, and optional `:port`, by which $HOST2 can reach +it). NB: if there is a firewall between $HOST1 and $HOST2, you must +open port 6783 for TCP and UDP. Note that we could instead have told the weave on $HOST1 to connect to $HOST2, or told both about each other. Order does not matter here; diff --git a/weave b/weave index f0bde4a1..8b9ca3a6 100755 --- a/weave +++ b/weave @@ -3,7 +3,7 @@ set -e usage() { echo "Usage:" - echo "weave launch [-password ] ..." + echo "weave launch [-password ] ..." echo "weave run ..." echo "weave start " echo "weave attach " @@ -15,7 +15,8 @@ usage() { echo "weave stop" echo "weave reset" echo - echo "where is of the form /" + echo "where is of the form /, and" + echo " is of the form [:]" exit 1 } From d8bea832d3ff43da5adbfbcbf4941d0236adcb36 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sat, 25 Oct 2014 22:04:36 +0100 Subject: [PATCH 22/27] validate CIDR This isn't meant to be precise but supposed to guard against silly mistakes. Closes #116. --- weave | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/weave b/weave index 8b9ca3a6..de850089 100755 --- a/weave +++ b/weave @@ -55,6 +55,15 @@ check_command_and_run() { fi } +validate_cidr() { + # The regexp here is far from precise, but good enough. + if ! echo "$1" | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$' >/dev/null ; then + echo "Invalid CIDR: $1" >&2 + echo "CIDR must of be of form /, e.g. 10.0.1.1/24" >&2 + exit 1 + fi +} + run_iptables() { # -w is recent addition to iptables if [ -z "$CHECKED_IPTABLES_W" ] ; then @@ -223,6 +232,7 @@ detach() { case "$COMMAND" in launch) [ $# -gt 0 ] || usage + validate_cidr $1 CIDR=$1 shift 1 case $(docker inspect --format '{{ .State.Running }} {{ .Config.Image }}' $CONTAINER_NAME 2>/dev/null) in @@ -291,6 +301,7 @@ case "$COMMAND" in ;; run) [ $# -gt 0 ] || usage + validate_cidr $1 CIDR=$1 shift 1 create_bridge @@ -300,6 +311,7 @@ case "$COMMAND" in ;; start) [ $# -eq 2 ] || usage + validate_cidr $1 create_bridge CONTAINER=$(docker start $2) with_container_netns $CONTAINER attach $1 $CONTAINER_IFNAME @@ -307,15 +319,18 @@ case "$COMMAND" in ;; attach) [ $# -eq 2 ] || usage + validate_cidr $1 create_bridge with_container_netns $2 attach $1 $CONTAINER_IFNAME ;; detach) [ $# -eq 2 ] || usage + validate_cidr $1 with_container_netns $2 detach $1 ;; expose) [ $# -eq 1 ] || usage + validate_cidr $1 create_bridge if ! ip addr show dev $BRIDGE | grep -qF $1 then @@ -324,6 +339,7 @@ case "$COMMAND" in ;; hide) [ $# -eq 1 ] || usage + validate_cidr $1 create_bridge if ip addr show dev $BRIDGE | grep -qF $1 then From fad584694629ef553f845c13ed159b97f2797a3c Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sun, 26 Oct 2014 12:13:28 +0000 Subject: [PATCH 23/27] refactor: extract basic container/bridge connection establishment Note that we do not mark the interface in the container as 'up' here since some callers, in particular 'attach', add CIDRs to the interface, and some programs rely on 'up' implying 'has IP address'. --- weave | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/weave b/weave index a4994867..8a1bbcf0 100755 --- a/weave +++ b/weave @@ -175,7 +175,7 @@ with_container_netns () { return $STATUS } -launch() { +connect_container_to_bridge() { if ! ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU ; then return 1 fi @@ -188,7 +188,12 @@ launch() { ip link set $LOCAL_IFNAME master $BRIDGE && ip link set $LOCAL_IFNAME up && - ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME && + ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME + } + + +launch() { + connect_container_to_bridge && ip netns exec $NETNS ip link set $CONTAINER_IFNAME up && check_command_and_run ethtool ip netns exec $NETNS ethtool -K eth0 tx off >/dev/null } @@ -209,20 +214,7 @@ attach() { return 0 fi - if ! ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU ; then - return 1 - fi - - if ! ip link set $GUEST_IFNAME netns $NETNS ; then - # failed before we assigned the veth to the container's - # namespace - delete it - ip link del $LOCAL_IFNAME type veth || true - return 1 - fi - - if ! ip link set $LOCAL_IFNAME master $BRIDGE || - ! ip link set $LOCAL_IFNAME up || - ! ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME || + if ! connect_container_to_bridge || ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME || ! ip netns exec $NETNS ip link set $CONTAINER_IFNAME up || ! check_command_and_run ethtool ip netns exec $NETNS ethtool -K $CONTAINER_IFNAME tx off >/dev/null ; then From acbabc4f9e4e01ece31421b203522523896a905c Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Mon, 27 Oct 2014 08:22:22 +0000 Subject: [PATCH 24/27] s/StatusPort/HttpPort since we are adding functionality other than status --- router/consts.go | 2 +- weaver/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/router/consts.go b/router/consts.go index 2d851dfb..02a93edf 100644 --- a/router/consts.go +++ b/router/consts.go @@ -11,7 +11,7 @@ const ( EthernetOverhead = 14 UDPOverhead = 28 // 20 bytes for IPv4, 8 bytes for UDP Port = 6783 - StatusPort = Port + 1 + HttpPort = Port + 1 DefaultPMTU = 65535 MaxUDPPacketSize = 65536 ChannelSize = 16 diff --git a/weaver/main.go b/weaver/main.go index 7bb0c416..523a5429 100644 --- a/weaver/main.go +++ b/weaver/main.go @@ -141,7 +141,7 @@ func handleHttp(router *weave.Router) { http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, router.Status()) }) - address := fmt.Sprintf(":%d", weave.StatusPort) + address := fmt.Sprintf(":%d", weave.HttpPort) err := http.ListenAndServe(address, nil) if err != nil { log.Fatal("Unable to create http listener: ", err) From 6393e545aea7ae9218d54019be27d56b9b9043c4 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Mon, 27 Oct 2014 09:15:14 +0000 Subject: [PATCH 25/27] introduce 'weave connect' to connect a running router to other peers Getting this to work with 'wget' is just too cumbersome especially when it comes to getting the error message out. So 'curl' only. --- weave | 45 ++++++++++++++++++++++++++++++--------------- weaver/main.go | 8 ++++++++ 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/weave b/weave index de850089..a2bfceda 100755 --- a/weave +++ b/weave @@ -3,13 +3,14 @@ set -e usage() { echo "Usage:" - echo "weave launch [-password ] ..." - echo "weave run ..." - echo "weave start " - echo "weave attach " - echo "weave detach " - echo "weave expose " - echo "weave hide " + echo "weave launch [-password ] ..." + echo "weave run ..." + echo "weave start " + echo "weave attach " + echo "weave detach " + echo "weave expose " + echo "weave hide " + echo "weave connect " echo "weave status" echo "weave version" echo "weave stop" @@ -126,6 +127,17 @@ stop_masquerading() { run_iptables -t nat -X WEAVE >/dev/null 2>&1 || true } +docker_ip() { + if ! DOCKERIP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' $CONTAINER_NAME 2>/dev/null) ; then + echo "Weave is not running." >&2 + exit 1 + fi + if [ -z "$DOCKERIP" ] ; then + echo "Weave is not running." >&2 + exit 1 + fi +} + # the following borrows from https://github.com/jpetazzo/pipework with_container_netns () { CONTAINER="$1" @@ -269,16 +281,19 @@ case "$COMMAND" in with_container_netns $CONTAINER attach $CIDR eth0 echo $CONTAINER ;; + connect) + [ $# -eq 1 ] || usage + docker_ip + if command_exists curl ; then + curl -d peer=$1 $DOCKERIP:$HTTP_PORT/connect + else + echo "Cannot find curl. Install it for 'weave connect' to function." >&2 + exit 1 + fi + ;; status) [ $# -eq 0 ] || usage - if ! DOCKERIP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' $CONTAINER_NAME 2>/dev/null) ; then - echo "Weave is not running." >&2 - exit 1 - fi - if [ -z "$DOCKERIP" ] ; then - echo "Weave is not running." >&2 - exit 1 - fi + docker_ip if command_exists wget ; then wget -O - -q $DOCKERIP:$HTTP_PORT/status elif command_exists curl ; then diff --git a/weaver/main.go b/weaver/main.go index 523a5429..76f1d82f 100644 --- a/weaver/main.go +++ b/weaver/main.go @@ -141,6 +141,14 @@ func handleHttp(router *weave.Router) { http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, router.Status()) }) + http.HandleFunc("/connect", func (w http.ResponseWriter, r *http.Request) { + peer := r.FormValue("peer") + if addr, err := net.ResolveTCPAddr("tcp4", weave.NormalisePeerAddr(peer)); err == nil { + router.ConnectionMaker.InitiateConnection(addr.String()) + } else { + http.Error(w, fmt.Sprint("invalid peer address: ", err), http.StatusBadRequest) + } + }) address := fmt.Sprintf(":%d", weave.HttpPort) err := http.ListenAndServe(address, nil) if err != nil { From 4b8988346fdae9c7a7c461b8bc58daeb0944c715 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Mon, 27 Oct 2014 14:08:54 +0000 Subject: [PATCH 26/27] cosmetic --- weave | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/weave b/weave index 8a1bbcf0..b0841021 100755 --- a/weave +++ b/weave @@ -187,15 +187,15 @@ connect_container_to_bridge() { fi ip link set $LOCAL_IFNAME master $BRIDGE && - ip link set $LOCAL_IFNAME up && - ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME - } + ip link set $LOCAL_IFNAME up && + ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME +} launch() { connect_container_to_bridge && - ip netns exec $NETNS ip link set $CONTAINER_IFNAME up && - check_command_and_run ethtool ip netns exec $NETNS ethtool -K eth0 tx off >/dev/null + ip netns exec $NETNS ip link set $CONTAINER_IFNAME up && + check_command_and_run ethtool ip netns exec $NETNS ethtool -K eth0 tx off >/dev/null } attach() { From 1b9dbad15fb88310b663d45bbc840317d767903f Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Mon, 27 Oct 2014 14:34:59 +0000 Subject: [PATCH 27/27] cosmetic --- weave | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/weave b/weave index 669cc575..ae034cf4 100755 --- a/weave +++ b/weave @@ -3,7 +3,7 @@ set -e usage() { echo "Usage:" - echo "weave launch [-password ] ..." + echo "weave launch [-password ] ..." echo "weave connect " echo "weave run ..." echo "weave start " @@ -16,8 +16,8 @@ usage() { echo "weave stop" echo "weave reset" echo - echo "where is of the form /, and" - echo " is of the form [:]" + echo "where is of the form [:], and" + echo " is of the form /" exit 1 }