Quellcode durchsuchen

Makefile: Cleanup, alpine and amd64 only UDP

Reorganize the Makefile to have different sections for build, test,
release and development.

Move to using Alpine linux as the base image. This means we no longer
need to build iptables and it makes it easier to install other packages
in future (e.g. strongswan).

To allow alpine to be used, static binaries for all platforms are
needed. It's not possible to create these for the UDP backend for
non-amd64 platforms. This is because it relies on CGO. So this PR makes
the UDP backend work on amd64 only.
Tom Denham vor 7 Jahren
Ursprung
Commit
3e883b809e

+ 1 - 0
.gitignore

@@ -5,3 +5,4 @@ cover.out
 .editorconfig
 .idea/
 bash_unit
+dist/qemu-*

+ 2 - 3
Dockerfile.amd64

@@ -1,12 +1,11 @@
-FROM frolvlad/alpine-glibc
+FROM alpine
 
 LABEL maintainer="Tom Denham <tom@tigera.io>"
 
 ENV FLANNEL_ARCH=amd64
 
-RUN apk add --no-cache iproute2 net-tools ca-certificates && update-ca-certificates
+RUN apk add --no-cache iproute2 net-tools ca-certificates iptables && update-ca-certificates
 COPY dist/flanneld-$FLANNEL_ARCH /opt/bin/flanneld
-COPY dist/iptables-$FLANNEL_ARCH /usr/local/bin/iptables
 COPY dist/mk-docker-opts.sh /opt/bin/
 
 ENTRYPOINT ["/opt/bin/flanneld"]

+ 4 - 3
Dockerfile.arm

@@ -1,11 +1,12 @@
-FROM arm32v7/busybox:glibc
+FROM arm32v6/alpine
 
 LABEL maintainer="Tom Denham <tom@tigera.io>"
 
 ENV FLANNEL_ARCH=arm
 
+ADD dist/qemu-$FLANNEL_ARCH-static /usr/bin/qemu-$FLANNEL_ARCH-static
+RUN apk add --no-cache iproute2 net-tools ca-certificates iptables && update-ca-certificates
 COPY dist/flanneld-$FLANNEL_ARCH /opt/bin/flanneld
-COPY dist/iptables-$FLANNEL_ARCH /usr/local/bin/iptables
 COPY dist/mk-docker-opts.sh /opt/bin/
 
-ENTRYPOINT ["/opt/bin/flanneld"]
+ENTRYPOINT ["/opt/bin/flanneld"]

+ 4 - 3
Dockerfile.arm64

@@ -1,11 +1,12 @@
-FROM arm64v8/busybox:glibc
+FROM arm64v8/alpine
 
 LABEL maintainer="Tom Denham <tom@tigera.io>"
 
 ENV FLANNEL_ARCH=arm64
 
+ADD dist/qemu-aarch64-static /usr/bin/qemu-aarch64-static
+RUN apk add --no-cache iproute2 net-tools ca-certificates iptables && update-ca-certificates
 COPY dist/flanneld-$FLANNEL_ARCH /opt/bin/flanneld
-COPY dist/iptables-$FLANNEL_ARCH /usr/local/bin/iptables
 COPY dist/mk-docker-opts.sh /opt/bin/
 
-ENTRYPOINT ["/opt/bin/flanneld"]
+ENTRYPOINT ["/opt/bin/flanneld"]

+ 4 - 3
Dockerfile.ppc64le

@@ -1,11 +1,12 @@
-FROM ppc64le/busybox:glibc
+FROM ppc64le/alpine
 
 LABEL maintainer="Tom Denham <tom@tigera.io>"
 
 ENV FLANNEL_ARCH=ppc64le
 
+ADD dist/qemu-$FLANNEL_ARCH-static /usr/bin/qemu-$FLANNEL_ARCH-static
+RUN apk add --no-cache iproute2 net-tools ca-certificates iptables && update-ca-certificates
 COPY dist/flanneld-$FLANNEL_ARCH /opt/bin/flanneld
-COPY dist/iptables-$FLANNEL_ARCH /usr/local/bin/iptables
 COPY dist/mk-docker-opts.sh /opt/bin/
 
-ENTRYPOINT ["/opt/bin/flanneld"]
+ENTRYPOINT ["/opt/bin/flanneld"]

+ 4 - 3
Dockerfile.s390x

@@ -1,11 +1,12 @@
-FROM s390x/busybox:glibc
+FROM s390x/alpine
 
 LABEL maintainer="Tom Denham <tom@tigera.io>"
 
 ENV FLANNEL_ARCH=s390x
 
+ADD dist/qemu-$FLANNEL_ARCH-static /usr/bin/qemu-$FLANNEL_ARCH-static
+RUN apk add --no-cache iproute2 net-tools ca-certificates iptables && update-ca-certificates
 COPY dist/flanneld-$FLANNEL_ARCH /opt/bin/flanneld
-COPY dist/iptables-$FLANNEL_ARCH /usr/local/bin/iptables
 COPY dist/mk-docker-opts.sh /opt/bin/
 
-ENTRYPOINT ["/opt/bin/flanneld"]
+ENTRYPOINT ["/opt/bin/flanneld"]

+ 12 - 0
Documentation/building.md

@@ -7,6 +7,18 @@ The most reliable way to build flannel is by using Docker.
 To build flannel in a container run `make dist/flanneld-amd64`.
 You will now have a `flanneld-amd64` binary in the `dist` directory.
 
+## Building for other platforms
+
+If you're not running `amd64` then you need to manually set `ARCH` before running `make`. For example, to produce a 
+`flanneld-s390x` binary and image, run
+* ARCH=s390x make image
+
+If you want to cross-compile for a different platform (e.g. you're running `amd64` but you want to produce `arm` binaries) then you need the qemu-static binaries to be present in `/usr/bin`. They can be installed on Ubuntu with
+* `sudo apt-get install qemu-user-static`
+
+Then you should be able to set the ARCH as above
+* ARCH=arm make image
+
 ## Building manually
 
 1. Make sure you have required dependencies installed on your machine.

+ 78 - 86
Makefile

@@ -6,6 +6,18 @@ REGISTRY?=quay.io/coreos/flannel
 # Default tag and architecture. Can be overridden
 TAG?=$(shell git describe --tags --dirty)
 ARCH?=amd64
+# Only enable CGO (and build the UDP backend) on AMD64
+ifeq ($(ARCH),amd64)
+	CGO_ENABLED=1
+else
+	CGO_ENABLED=0
+endif
+
+# Go version to use for builds
+GO_VERSION=1.8.3
+
+# K8s version used for Makefile helpers
+K8S_VERSION=v1.6.6
 
 # These variables can be overridden by setting an environment variable.
 TEST_PACKAGES?=pkg/ip subnet subnet/etcdv2 network backend/hostgw
@@ -13,33 +25,42 @@ TEST_PACKAGES_EXPANDED=$(TEST_PACKAGES:%=github.com/coreos/flannel/%)
 PACKAGES?=$(TEST_PACKAGES) network
 PACKAGES_EXPANDED=$(PACKAGES:%=github.com/coreos/flannel/%)
 
-# Set the (cross) compiler to use for different architectures
-ifeq ($(ARCH),amd64)
-	CC=gcc
-endif
-ifeq ($(ARCH),arm)
-	CC=arm-linux-gnueabihf-gcc
-endif
-ifeq ($(ARCH),arm64)
-	CC=aarch64-linux-gnu-gcc
-endif
-ifeq ($(ARCH),ppc64le)
-	CC=powerpc64le-linux-gnu-gcc
-endif
-ifeq ($(ARCH),s390x)
-	CC=s390x-linux-gnu-gcc
-endif
-
-GOARM=7
-
-# List images with gcloud alpha container images list-tags gcr.io/google_containers/kube-cross
-KUBE_CROSS_TAG=v1.8.3-1
-IPTABLES_VERSION=1.4.21
+### BUILDING
+clean:
+	rm -f dist/flanneld*
+	rm -f dist/*.aci
+	rm -f dist/*.docker
+	rm -f dist/*.tar.gz
 
 dist/flanneld: $(shell find . -type f  -name '*.go')
 	go build -o dist/flanneld \
-	  -ldflags "-s -w -X github.com/coreos/flannel/version.Version=$(TAG)"
+	  -ldflags '-s -w -X github.com/coreos/flannel/version.Version=$(TAG) -extldflags "-static"'
+
+# This will build flannel natively using golang image
+dist/flanneld-$(ARCH):
+	# valid values for ARCH are [amd64 arm arm64 ppc64le s390x]
+	docker run -e CGO_ENABLED=$(CGO_ENABLED) -e GOARCH=$(ARCH) \
+		-u $(shell id -u):$(shell id -g) \
+		-v /usr/bin/qemu-$(ARCH)-static:/usr/bin/qemu-$(ARCH)-static \
+		-v $(CURDIR):/go/src/github.com/coreos/flannel:ro \
+		-v $(CURDIR)/dist:/go/src/github.com/coreos/flannel/dist \
+		golang:$(GO_VERSION) /bin/bash -c '\
+		cd /go/src/github.com/coreos/flannel && \
+		make -e dist/flanneld && \
+		mv dist/flanneld dist/flanneld-$(ARCH)'
+
+## Create a docker image on disk for a specific arch and tag
+image:	dist/flanneld-$(TAG)-$(ARCH).docker
+dist/flanneld-$(TAG)-$(ARCH).docker: dist/flanneld-$(ARCH)
+	docker build -f Dockerfile.$(ARCH) -t $(REGISTRY):$(TAG)-$(ARCH) .
+	docker save -o dist/flanneld-$(TAG)-$(ARCH).docker $(REGISTRY):$(TAG)-$(ARCH)
+
+# amd64 gets an image with the suffix too (i.e. it's the default)
+ifeq ($(ARCH),amd64)
+	docker build -f Dockerfile.$(ARCH) -t $(REGISTRY):$(TAG) .
+endif
 
+### TESTING
 test: license-check gofmt
 	# Run the unit tests
 	docker run --cap-add=NET_ADMIN --rm -v $(shell pwd):/go/src/github.com/coreos/flannel golang:1.8.3 go test -v -cover $(TEST_PACKAGES_EXPANDED)
@@ -60,6 +81,9 @@ cover:
 	go test -coverprofile cover.out $(PACKAGES_EXPANDED)
 	go tool cover -html=cover.out
 
+license-check:
+	./license-check.sh
+
 # Throw an error if gofmt finds problems.
 # "read" will return a failure return code if there is no output. This is inverted wth the "!"
 gofmt:
@@ -68,15 +92,6 @@ gofmt:
 gofmt-fix:
 	gofmt -w $(PACKAGES)
 
-license-check:
-	./license-check.sh
-
-update-glide:
-	# go get -d -u github.com/Masterminds/glide
-	glide update --strip-vendor
-	# go get -d -u github.com/sgotti/glide-vc
-	glide vc --only-code --no-tests
-
 bash_unit:
 	wget https://raw.githubusercontent.com/pgrange/bash_unit/v1.6.0/bash_unit
 	chmod +x bash_unit
@@ -112,49 +127,23 @@ dist/flanneld-e2e-$(TAG)-$(ARCH).docker:
 docker-push: dist/flanneld-$(TAG)-$(ARCH).docker
 	docker push $(REGISTRY):$(TAG)-$(ARCH)
 
-# amd64 gets an image with the suffix too (i.e. it's the default)
-ifeq ($(ARCH),amd64)
-	docker push $(REGISTRY):$(TAG)
-endif
+# Make a release after creating a tag
+# To build cross platform Docker images, the qemu-static binaries are needed. On ubuntu "apt-get install  qemu-user-static"
+release: tar.gz dist/qemu-s390x-static dist/qemu-ppc64le-static dist/qemu-aarch64-static dist/qemu-arm-static #release-tests
+	ARCH=amd64 make dist/flanneld-$(TAG)-amd64.docker
+	ARCH=arm make dist/flanneld-$(TAG)-arm.docker
+	ARCH=arm64 make dist/flanneld-$(TAG)-arm64.docker
+	ARCH=ppc64le make dist/flanneld-$(TAG)-ppc64le.docker
+	ARCH=s390x make dist/flanneld-$(TAG)-s390x.docker
+	@echo "Everything should be built for $(TAG)"
+	@echo "Add all flanneld-* and *.tar.gz files from dist/ to the Github release"
+	@echo "Use make docker-push-all to push the images to a registry"
 
-## Build an architecture specific flanneld binary
-dist/flanneld-$(ARCH):
-	# Build for other platforms with 'ARCH=$$ARCH make dist/flanneld-$$ARCH'
-	# valid values for $$ARCH are [amd64 arm arm64 ppc64le s390x]
-	docker run -e CC=$(CC) -e GOARM=$(GOARM) -e GOARCH=$(ARCH) \
-		-u $(shell id -u):$(shell id -g) \
-	    -v $(CURDIR):/go/src/github.com/coreos/flannel:ro \
-        -v $(CURDIR)/dist:/go/src/github.com/coreos/flannel/dist \
-	    gcr.io/google_containers/kube-cross:$(KUBE_CROSS_TAG) /bin/bash -c '\
-		cd /go/src/github.com/coreos/flannel && \
-		CGO_ENABLED=1 make -e dist/flanneld && \
-		mv dist/flanneld dist/flanneld-$(ARCH) && \
-		file dist/flanneld-$(ARCH)'
-
-## Build an architecture specific iptables binary
-dist/iptables-$(ARCH):
-	docker run -e CC=$(CC) -e GOARM=$(GOARM) -e GOARCH=$(ARCH) \
-			-u $(shell id -u):$(shell id -g) \
-            -v $(CURDIR):/go/src/github.com/coreos/flannel:ro \
-            -v $(CURDIR)/dist:/go/src/github.com/coreos/flannel/dist \
-            gcr.io/google_containers/kube-cross:$(KUBE_CROSS_TAG) /bin/bash -c '\
-            curl -sSL http://www.netfilter.org/projects/iptables/files/iptables-$(IPTABLES_VERSION).tar.bz2 | tar -jxv && \
-            cd iptables-$(IPTABLES_VERSION) && \
-            ./configure \
-                --prefix=/usr \
-                --mandir=/usr/man \
-                --disable-shared \
-                --disable-devel \
-                --disable-nftables \
-                --enable-static \
-                --host=amd64 && \
-            make && \
-            cp iptables/xtables-multi /go/src/github.com/coreos/flannel/dist/iptables-$(ARCH) && \
-            cd /go/src/github.com/coreos/flannel && \
-            file dist/iptables-$(ARCH)'
+dist/qemu-%-static:
+	cp /usr/bin/$(@F) dist
 
 ## Build a .tar.gz for the amd64 ppc64le arm arm64 flanneld binary
-tar.gz:	
+tar.gz:
 	ARCH=amd64 make dist/flanneld-amd64
 	tar --transform='flags=r;s|-amd64||' -zcvf dist/flannel-$(TAG)-linux-amd64.tar.gz -C dist flanneld-amd64 mk-docker-opts.sh ../README.md
 	tar -tvf dist/flannel-$(TAG)-linux-amd64.tar.gz
@@ -171,17 +160,6 @@ tar.gz:
 	tar --transform='flags=r;s|-s390x||' -zcvf dist/flannel-$(TAG)-linux-s390x.tar.gz -C dist flanneld-s390x mk-docker-opts.sh ../README.md
 	tar -tvf dist/flannel-$(TAG)-linux-s390x.tar.gz
 
-## Make a release after creating a tag
-release: tar.gz release-tests
-	ARCH=amd64 make dist/flanneld-$(TAG)-amd64.docker
-	ARCH=arm make dist/flanneld-$(TAG)-arm.docker
-	ARCH=arm64 make dist/flanneld-$(TAG)-arm64.docker
-	ARCH=ppc64le make dist/flanneld-$(TAG)-ppc64le.docker
-	ARCH=s390x make dist/flanneld-$(TAG)-s390x.docker
-	@echo "Everything should be built for $(TAG)"
-	@echo "Add all flanneld-* and *.tar.gz files from dist/ to the Github release"
-	@echo "Use make docker-push-all to push the images to a registry"
-
 release-tests: bash_unit
 	# Run the functional tests with different etcd versions.
 	ETCD_IMG="quay.io/coreos/etcd:latest"  ./bash_unit dist/functional-test.sh
@@ -199,6 +177,14 @@ release-tests: bash_unit
 	# K8S_VERSION="1.4.12" ./bash_unit dist/functional-test-k8s.sh   #kube-flannel.yml is incompatible
 	# K8S_VERSION="1.3.10" ./bash_unit dist/functional-test-k8s.sh   #kube-flannel.yml is incompatible
 
+docker-push: dist/flanneld-$(TAG)-$(ARCH).docker
+	docker push $(REGISTRY):$(TAG)-$(ARCH)
+
+# amd64 gets an image with the suffix too (i.e. it's the default)
+ifeq ($(ARCH),amd64)
+	docker push $(REGISTRY):$(TAG)
+endif
+
 docker-push-all:
 	ARCH=amd64 make docker-push
 	ARCH=arm make docker-push
@@ -215,6 +201,13 @@ flannel-git:
 	ARCH=ppc64le REGISTRY=quay.io/coreos/flannel-git make clean dist/flanneld-$(TAG)-ppc64le.docker docker-push
 	ARCH=s390x REGISTRY=quay.io/coreos/flannel-git make clean dist/flanneld-$(TAG)-s390x.docker docker-push
 
+### DEVELOPING
+update-glide:
+	# go get -d -u github.com/Masterminds/glide
+	glide update --strip-vendor
+	# go get -d -u github.com/sgotti/glide-vc
+	glide vc --only-code --no-tests
+
 install:
 	# This is intended as just a developer convenience to help speed up non-containerized builds
 	# It is NOT how you install flannel
@@ -223,7 +216,7 @@ install:
 minikube-start:
 	minikube start --network-plugin cni
 
-minikube-build-image: dist/iptables-amd64
+minikube-build-image:
 	CGO_ENABLED=1 go build -v -o dist/flanneld-amd64
 	# Make sure the minikube docker is being used "eval $(minikube docker-env)"
 	sh -c 'eval $$(minikube docker-env) && docker build -f Dockerfile.amd64 -t flannel/minikube .'
@@ -253,7 +246,6 @@ run-etcd: stop-etcd
 stop-etcd:
 	@-docker rm -f flannel-etcd
 
-K8S_VERSION=v1.6.6
 run-k8s-apiserver: stop-k8s-apiserver
 	docker run --detach --net=host \
 	  --name calico-k8s-apiserver \
@@ -270,4 +262,4 @@ run-local-kube-flannel-with-prereqs: run-etcd run-k8s-apiserver dist/flanneld
 
 run-local-kube-flannel:
 	# Currently this requires the netconf to be in /etc/kube-flannel/net-conf.json
-	sudo NODE_NAME=test dist/flanneld --kube-subnet-mgr --kube-api-url http://127.0.0.1:8080
+	sudo NODE_NAME=test dist/flanneld --kube-subnet-mgr --kube-api-url http://127.0.0.1:8080

+ 1 - 1
backend/udp/cproxy.go → backend/udp/cproxy_amd64.go

@@ -14,7 +14,7 @@
 
 package udp
 
-//#include "proxy.h"
+//#include "proxy_amd64.h"
 import "C"
 
 import (

+ 1 - 1
backend/udp/proxy.c → backend/udp/proxy_amd64.c

@@ -29,7 +29,7 @@
 #include <fcntl.h>
 
 #define CMD_DEFINE
-#include "proxy.h"
+#include "proxy_amd64.h"
 
 struct ip_net {
 	in_addr_t ip;

+ 0 - 0
backend/udp/proxy.h → backend/udp/proxy_amd64.h


+ 2 - 58
backend/udp/udp.go

@@ -11,17 +11,14 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+// +build !amd64
 
 package udp
 
 import (
-	"encoding/json"
 	"fmt"
 
-	"golang.org/x/net/context"
-
 	"github.com/coreos/flannel/backend"
-	"github.com/coreos/flannel/pkg/ip"
 	"github.com/coreos/flannel/subnet"
 )
 
@@ -29,59 +26,6 @@ func init() {
 	backend.Register("udp", New)
 }
 
-const (
-	defaultPort = 8285
-)
-
-type UdpBackend struct {
-	sm       subnet.Manager
-	extIface *backend.ExternalInterface
-}
-
 func New(sm subnet.Manager, extIface *backend.ExternalInterface) (backend.Backend, error) {
-	be := UdpBackend{
-		sm:       sm,
-		extIface: extIface,
-	}
-	return &be, nil
-}
-
-func (be *UdpBackend) RegisterNetwork(ctx context.Context, config *subnet.Config) (backend.Network, error) {
-	cfg := struct {
-		Port int
-	}{
-		Port: defaultPort,
-	}
-
-	// Parse our configuration
-	if len(config.Backend) > 0 {
-		if err := json.Unmarshal(config.Backend, &cfg); err != nil {
-			return nil, fmt.Errorf("error decoding UDP backend config: %v", err)
-		}
-	}
-
-	// Acquire the lease form subnet manager
-	attrs := subnet.LeaseAttrs{
-		PublicIP: ip.FromIP(be.extIface.ExtAddr),
-	}
-
-	l, err := be.sm.AcquireLease(ctx, &attrs)
-	switch err {
-	case nil:
-
-	case context.Canceled, context.DeadlineExceeded:
-		return nil, err
-
-	default:
-		return nil, fmt.Errorf("failed to acquire lease: %v", err)
-	}
-
-	// Tunnel's subnet is that of the whole overlay network (e.g. /16)
-	// and not that of the individual host (e.g. /24)
-	tunNet := ip.IP4Net{
-		IP:        l.Subnet.IP,
-		PrefixLen: config.Network.PrefixLen,
-	}
-
-	return newNetwork(be.sm, be.extIface, cfg.Port, tunNet, l)
+	return nil, fmt.Errorf("UDP backend is not supported on this architecture")
 }

+ 87 - 0
backend/udp/udp_amd64.go

@@ -0,0 +1,87 @@
+// Copyright 2015 flannel authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package udp
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"golang.org/x/net/context"
+
+	"github.com/coreos/flannel/backend"
+	"github.com/coreos/flannel/pkg/ip"
+	"github.com/coreos/flannel/subnet"
+)
+
+func init() {
+	backend.Register("udp", New)
+}
+
+const (
+	defaultPort = 8285
+)
+
+type UdpBackend struct {
+	sm       subnet.Manager
+	extIface *backend.ExternalInterface
+}
+
+func New(sm subnet.Manager, extIface *backend.ExternalInterface) (backend.Backend, error) {
+	be := UdpBackend{
+		sm:       sm,
+		extIface: extIface,
+	}
+	return &be, nil
+}
+
+func (be *UdpBackend) RegisterNetwork(ctx context.Context, config *subnet.Config) (backend.Network, error) {
+	cfg := struct {
+		Port int
+	}{
+		Port: defaultPort,
+	}
+
+	// Parse our configuration
+	if len(config.Backend) > 0 {
+		if err := json.Unmarshal(config.Backend, &cfg); err != nil {
+			return nil, fmt.Errorf("error decoding UDP backend config: %v", err)
+		}
+	}
+
+	// Acquire the lease form subnet manager
+	attrs := subnet.LeaseAttrs{
+		PublicIP: ip.FromIP(be.extIface.ExtAddr),
+	}
+
+	l, err := be.sm.AcquireLease(ctx, &attrs)
+	switch err {
+	case nil:
+
+	case context.Canceled, context.DeadlineExceeded:
+		return nil, err
+
+	default:
+		return nil, fmt.Errorf("failed to acquire lease: %v", err)
+	}
+
+	// Tunnel's subnet is that of the whole overlay network (e.g. /16)
+	// and not that of the individual host (e.g. /24)
+	tunNet := ip.IP4Net{
+		IP:        l.Subnet.IP,
+		PrefixLen: config.Network.PrefixLen,
+	}
+
+	return newNetwork(be.sm, be.extIface, cfg.Port, tunNet, l)
+}

+ 4 - 175
backend/udp/udp_network.go

@@ -11,189 +11,18 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+// +build !amd64
 
 package udp
 
 import (
 	"fmt"
-	"net"
-	"os"
-	"sync"
-	"syscall"
-
-	log "github.com/golang/glog"
-	"github.com/vishvananda/netlink"
-	"golang.org/x/net/context"
 
 	"github.com/coreos/flannel/backend"
 	"github.com/coreos/flannel/pkg/ip"
 	"github.com/coreos/flannel/subnet"
 )
 
-const (
-	encapOverhead = 28 // 20 bytes IP hdr + 8 bytes UDP hdr
-)
-
-type network struct {
-	backend.SimpleNetwork
-	name   string
-	port   int
-	ctl    *os.File
-	ctl2   *os.File
-	tun    *os.File
-	conn   *net.UDPConn
-	tunNet ip.IP4Net
-	sm     subnet.Manager
-}
-
-func newNetwork(sm subnet.Manager, extIface *backend.ExternalInterface, port int, nw ip.IP4Net, l *subnet.Lease) (*network, error) {
-	n := &network{
-		SimpleNetwork: backend.SimpleNetwork{
-			SubnetLease: l,
-			ExtIface:    extIface,
-		},
-		port: port,
-		sm:   sm,
-	}
-
-	n.tunNet = nw
-
-	if err := n.initTun(); err != nil {
-		return nil, err
-	}
-
-	var err error
-	n.conn, err = net.ListenUDP("udp4", &net.UDPAddr{IP: extIface.IfaceAddr, Port: port})
-	if err != nil {
-		return nil, fmt.Errorf("failed to start listening on UDP socket: %v", err)
-	}
-
-	n.ctl, n.ctl2, err = newCtlSockets()
-	if err != nil {
-		return nil, fmt.Errorf("failed to create control socket: %v", err)
-	}
-
-	return n, nil
-}
-
-func (n *network) Run(ctx context.Context) {
-	defer func() {
-		n.tun.Close()
-		n.conn.Close()
-		n.ctl.Close()
-		n.ctl2.Close()
-	}()
-
-	// one for each goroutine below
-	wg := sync.WaitGroup{}
-	defer wg.Wait()
-
-	wg.Add(1)
-	go func() {
-		runCProxy(n.tun, n.conn, n.ctl2, n.tunNet.IP, n.MTU())
-		wg.Done()
-	}()
-
-	log.Info("Watching for new subnet leases")
-
-	evts := make(chan []subnet.Event)
-
-	wg.Add(1)
-	go func() {
-		subnet.WatchLeases(ctx, n.sm, n.SubnetLease, evts)
-		wg.Done()
-	}()
-
-	for {
-		select {
-		case evtBatch := <-evts:
-			n.processSubnetEvents(evtBatch)
-
-		case <-ctx.Done():
-			stopProxy(n.ctl)
-			return
-		}
-	}
-}
-
-func (n *network) MTU() int {
-	return n.ExtIface.Iface.MTU - encapOverhead
-}
-
-func newCtlSockets() (*os.File, *os.File, error) {
-	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	f1 := os.NewFile(uintptr(fds[0]), "ctl")
-	f2 := os.NewFile(uintptr(fds[1]), "ctl")
-	return f1, f2, nil
-}
-
-func (n *network) initTun() error {
-	var tunName string
-	var err error
-
-	n.tun, tunName, err = ip.OpenTun("flannel%d")
-	if err != nil {
-		return fmt.Errorf("failed to open TUN device: %v", err)
-	}
-
-	err = configureIface(tunName, n.tunNet, n.MTU())
-	return err
-}
-
-func configureIface(ifname string, ipn ip.IP4Net, mtu int) error {
-	iface, err := netlink.LinkByName(ifname)
-	if err != nil {
-		return fmt.Errorf("failed to lookup interface %v", ifname)
-	}
-
-	err = netlink.AddrAdd(iface, &netlink.Addr{IPNet: ipn.ToIPNet(), Label: ""})
-	if err != nil {
-		return fmt.Errorf("failed to add IP address %v to %v: %v", ipn.String(), ifname, err)
-	}
-
-	err = netlink.LinkSetMTU(iface, mtu)
-	if err != nil {
-		return fmt.Errorf("failed to set MTU for %v: %v", ifname, err)
-	}
-
-	err = netlink.LinkSetUp(iface)
-	if err != nil {
-		return fmt.Errorf("failed to set interface %v to UP state: %v", ifname, err)
-	}
-
-	// explicitly add a route since there might be a route for a subnet already
-	// installed by Docker and then it won't get auto added
-	err = netlink.RouteAdd(&netlink.Route{
-		LinkIndex: iface.Attrs().Index,
-		Scope:     netlink.SCOPE_UNIVERSE,
-		Dst:       ipn.Network().ToIPNet(),
-	})
-	if err != nil && err != syscall.EEXIST {
-		return fmt.Errorf("failed to add route (%v -> %v): %v", ipn.Network().String(), ifname, err)
-	}
-
-	return nil
-}
-
-func (n *network) processSubnetEvents(batch []subnet.Event) {
-	for _, evt := range batch {
-		switch evt.Type {
-		case subnet.EventAdded:
-			log.Info("Subnet added: ", evt.Lease.Subnet)
-
-			setRoute(n.ctl, evt.Lease.Subnet, evt.Lease.Attrs.PublicIP, n.port)
-
-		case subnet.EventRemoved:
-			log.Info("Subnet removed: ", evt.Lease.Subnet)
-
-			removeRoute(n.ctl, evt.Lease.Subnet)
-
-		default:
-			log.Error("Internal error: unknown event type: ", int(evt.Type))
-		}
-	}
-}
+func newNetwork(sm subnet.Manager, extIface *backend.ExternalInterface, port int, nw ip.IP4Net, l *subnet.Lease) (*backend.SimpleNetwork, error) {
+	return nil, fmt.Errorf("UDP backend is not supported on this architecture")
+}

+ 199 - 0
backend/udp/udp_network_amd64.go

@@ -0,0 +1,199 @@
+// Copyright 2015 flannel authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package udp
+
+import (
+	"fmt"
+	"net"
+	"os"
+	"sync"
+	"syscall"
+
+	log "github.com/golang/glog"
+	"github.com/vishvananda/netlink"
+	"golang.org/x/net/context"
+
+	"github.com/coreos/flannel/backend"
+	"github.com/coreos/flannel/pkg/ip"
+	"github.com/coreos/flannel/subnet"
+)
+
+const (
+	encapOverhead = 28 // 20 bytes IP hdr + 8 bytes UDP hdr
+)
+
+type network struct {
+	backend.SimpleNetwork
+	name   string
+	port   int
+	ctl    *os.File
+	ctl2   *os.File
+	tun    *os.File
+	conn   *net.UDPConn
+	tunNet ip.IP4Net
+	sm     subnet.Manager
+}
+
+func newNetwork(sm subnet.Manager, extIface *backend.ExternalInterface, port int, nw ip.IP4Net, l *subnet.Lease) (*network, error) {
+	n := &network{
+		SimpleNetwork: backend.SimpleNetwork{
+			SubnetLease: l,
+			ExtIface:    extIface,
+		},
+		port: port,
+		sm:   sm,
+	}
+
+	n.tunNet = nw
+
+	if err := n.initTun(); err != nil {
+		return nil, err
+	}
+
+	var err error
+	n.conn, err = net.ListenUDP("udp4", &net.UDPAddr{IP: extIface.IfaceAddr, Port: port})
+	if err != nil {
+		return nil, fmt.Errorf("failed to start listening on UDP socket: %v", err)
+	}
+
+	n.ctl, n.ctl2, err = newCtlSockets()
+	if err != nil {
+		return nil, fmt.Errorf("failed to create control socket: %v", err)
+	}
+
+	return n, nil
+}
+
+func (n *network) Run(ctx context.Context) {
+	defer func() {
+		n.tun.Close()
+		n.conn.Close()
+		n.ctl.Close()
+		n.ctl2.Close()
+	}()
+
+	// one for each goroutine below
+	wg := sync.WaitGroup{}
+	defer wg.Wait()
+
+	wg.Add(1)
+	go func() {
+		runCProxy(n.tun, n.conn, n.ctl2, n.tunNet.IP, n.MTU())
+		wg.Done()
+	}()
+
+	log.Info("Watching for new subnet leases")
+
+	evts := make(chan []subnet.Event)
+
+	wg.Add(1)
+	go func() {
+		subnet.WatchLeases(ctx, n.sm, n.SubnetLease, evts)
+		wg.Done()
+	}()
+
+	for {
+		select {
+		case evtBatch := <-evts:
+			n.processSubnetEvents(evtBatch)
+
+		case <-ctx.Done():
+			stopProxy(n.ctl)
+			return
+		}
+	}
+}
+
+func (n *network) MTU() int {
+	return n.ExtIface.Iface.MTU - encapOverhead
+}
+
+func newCtlSockets() (*os.File, *os.File, error) {
+	fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	f1 := os.NewFile(uintptr(fds[0]), "ctl")
+	f2 := os.NewFile(uintptr(fds[1]), "ctl")
+	return f1, f2, nil
+}
+
+func (n *network) initTun() error {
+	var tunName string
+	var err error
+
+	n.tun, tunName, err = ip.OpenTun("flannel%d")
+	if err != nil {
+		return fmt.Errorf("failed to open TUN device: %v", err)
+	}
+
+	err = configureIface(tunName, n.tunNet, n.MTU())
+	return err
+}
+
+func configureIface(ifname string, ipn ip.IP4Net, mtu int) error {
+	iface, err := netlink.LinkByName(ifname)
+	if err != nil {
+		return fmt.Errorf("failed to lookup interface %v", ifname)
+	}
+
+	err = netlink.AddrAdd(iface, &netlink.Addr{IPNet: ipn.ToIPNet(), Label: ""})
+	if err != nil {
+		return fmt.Errorf("failed to add IP address %v to %v: %v", ipn.String(), ifname, err)
+	}
+
+	err = netlink.LinkSetMTU(iface, mtu)
+	if err != nil {
+		return fmt.Errorf("failed to set MTU for %v: %v", ifname, err)
+	}
+
+	err = netlink.LinkSetUp(iface)
+	if err != nil {
+		return fmt.Errorf("failed to set interface %v to UP state: %v", ifname, err)
+	}
+
+	// explicitly add a route since there might be a route for a subnet already
+	// installed by Docker and then it won't get auto added
+	err = netlink.RouteAdd(&netlink.Route{
+		LinkIndex: iface.Attrs().Index,
+		Scope:     netlink.SCOPE_UNIVERSE,
+		Dst:       ipn.Network().ToIPNet(),
+	})
+	if err != nil && err != syscall.EEXIST {
+		return fmt.Errorf("failed to add route (%v -> %v): %v", ipn.Network().String(), ifname, err)
+	}
+
+	return nil
+}
+
+func (n *network) processSubnetEvents(batch []subnet.Event) {
+	for _, evt := range batch {
+		switch evt.Type {
+		case subnet.EventAdded:
+			log.Info("Subnet added: ", evt.Lease.Subnet)
+
+			setRoute(n.ctl, evt.Lease.Subnet, evt.Lease.Attrs.PublicIP, n.port)
+
+		case subnet.EventRemoved:
+			log.Info("Subnet removed: ", evt.Lease.Subnet)
+
+			removeRoute(n.ctl, evt.Lease.Subnet)
+
+		default:
+			log.Error("Internal error: unknown event type: ", int(evt.Type))
+		}
+	}
+}

BIN
dist/iptables-amd64


BIN
dist/iptables-arm


BIN
dist/iptables-arm64


BIN
dist/iptables-ppc64le


BIN
dist/iptables-s390x