Browse Source

Merge pull request #860 from tomdee/simplify-packaging

Makefile: Cleanup, alpine and amd64 only UDP
Tom Denham 7 years ago
parent
commit
1e0f20eab1

+ 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