From e7ae43e5173fdbef178d0f0f0e9be007d43db142 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Sun, 10 Apr 2016 18:22:38 -0700 Subject: [PATCH 01/23] README: add some more details on what CNI is We needed a bit more intro material to scope what CNI does. Here is my attempt. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ada58371..58fcc2f2 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ CNI, the _Container Network Interface_, is a proposed standard for configuring network interfaces for Linux application containers. The standard consists of a simple specification for how executable plugins can be used to configure network namespaces; this repository also contains a go library implementing that specification. +CNI concerns itself with setting up network connectivity of containers and removing allocated resources when the container is deleted. +Because of this focus CNI has a wide range of support and the specification is simple to implement. + The specification itself is contained in [SPEC.md](SPEC.md). ## Why develop CNI? From 5019e283b186724608091f1a78b523e1cb85e838 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Sun, 10 Apr 2016 18:23:06 -0700 Subject: [PATCH 02/23] README: add some material on what CNI isn't We get some questions about this stuff from time to time and I want to acknowledge we have thought about them but aren't currently tackling them. --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 58fcc2f2..ccc6aea4 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,16 @@ lo Link encap:Local Loopback RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) ``` +## What might CNI do in the future? + +CNI currently covers a wide range of needs for network configuration due to it simple model and API. +However, in the future CNI might want to branch out into other directions: + +- Dynamic updates to existing network configuration +- Dynamic policies for network bandwidth and firewall rules + +If these topics of are interest please contact the team via the mailing list or IRC and find some like minded people in the community to put a proposal together. + ## Contact For any questions about CNI, please reach out on the mailing list or IRC: From 9044dc2831da93465c9c67d31f8144f09f0b36e3 Mon Sep 17 00:00:00 2001 From: Gabe Rosenhouse Date: Sun, 17 Apr 2016 18:28:10 -0700 Subject: [PATCH 03/23] Extract testhelpers from loopback test suite --- pkg/testhelpers/testhelpers.go | 69 ++++++++++++++++++++ plugins/main/loopback/loopback_suite_test.go | 50 -------------- plugins/main/loopback/loopback_test.go | 5 +- 3 files changed, 72 insertions(+), 52 deletions(-) create mode 100644 pkg/testhelpers/testhelpers.go diff --git a/pkg/testhelpers/testhelpers.go b/pkg/testhelpers/testhelpers.go new file mode 100644 index 00000000..f1ccb24e --- /dev/null +++ b/pkg/testhelpers/testhelpers.go @@ -0,0 +1,69 @@ +// Copyright 2016 CNI 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 testhelpers + +import ( + "fmt" + "os" + "runtime" + + "golang.org/x/sys/unix" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func MakeNetworkNS(containerID string) string { + namespace := "/var/run/netns/" + containerID + pid := unix.Getpid() + tid := unix.Gettid() + + err := os.MkdirAll("/var/run/netns", 0600) + Expect(err).NotTo(HaveOccurred()) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + go (func() { + defer GinkgoRecover() + + err = unix.Unshare(unix.CLONE_NEWNET) + Expect(err).NotTo(HaveOccurred()) + + fd, err := os.Create(namespace) + Expect(err).NotTo(HaveOccurred()) + defer fd.Close() + + err = unix.Mount("/proc/self/ns/net", namespace, "none", unix.MS_BIND, "") + Expect(err).NotTo(HaveOccurred()) + })() + + Eventually(namespace).Should(BeAnExistingFile()) + + fd, err := unix.Open(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid), unix.O_RDONLY, 0) + Expect(err).NotTo(HaveOccurred()) + + defer unix.Close(fd) + + _, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(fd), uintptr(unix.CLONE_NEWNET), 0) + Expect(e1).To(BeZero()) + + return namespace +} + +func RemoveNetworkNS(networkNS string) error { + err := unix.Unmount(networkNS, unix.MNT_DETACH) + + err = os.RemoveAll(networkNS) + return err +} diff --git a/plugins/main/loopback/loopback_suite_test.go b/plugins/main/loopback/loopback_suite_test.go index 36d646a2..be179aa8 100644 --- a/plugins/main/loopback/loopback_suite_test.go +++ b/plugins/main/loopback/loopback_suite_test.go @@ -15,18 +15,12 @@ package main_test import ( - "fmt" - "os" - "runtime" - "github.com/onsi/gomega/gexec" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "testing" - - "golang.org/x/sys/unix" ) var pathToLoPlugin string @@ -45,47 +39,3 @@ var _ = BeforeSuite(func() { var _ = AfterSuite(func() { gexec.CleanupBuildArtifacts() }) - -func makeNetworkNS(containerID string) string { - namespace := "/var/run/netns/" + containerID - pid := unix.Getpid() - tid := unix.Gettid() - - err := os.MkdirAll("/var/run/netns", 0600) - Expect(err).NotTo(HaveOccurred()) - - runtime.LockOSThread() - defer runtime.UnlockOSThread() - go (func() { - defer GinkgoRecover() - - err = unix.Unshare(unix.CLONE_NEWNET) - Expect(err).NotTo(HaveOccurred()) - - fd, err := os.Create(namespace) - Expect(err).NotTo(HaveOccurred()) - defer fd.Close() - - err = unix.Mount("/proc/self/ns/net", namespace, "none", unix.MS_BIND, "") - Expect(err).NotTo(HaveOccurred()) - })() - - Eventually(namespace).Should(BeAnExistingFile()) - - fd, err := unix.Open(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid), unix.O_RDONLY, 0) - Expect(err).NotTo(HaveOccurred()) - - defer unix.Close(fd) - - _, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(fd), uintptr(unix.CLONE_NEWNET), 0) - Expect(e1).To(BeZero()) - - return namespace -} - -func removeNetworkNS(networkNS string) error { - err := unix.Unmount(networkNS, unix.MNT_DETACH) - - err = os.RemoveAll(networkNS) - return err -} diff --git a/plugins/main/loopback/loopback_test.go b/plugins/main/loopback/loopback_test.go index fbacc707..037fbfeb 100644 --- a/plugins/main/loopback/loopback_test.go +++ b/plugins/main/loopback/loopback_test.go @@ -22,6 +22,7 @@ import ( "strings" "github.com/appc/cni/pkg/ns" + "github.com/appc/cni/pkg/testhelpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gbytes" @@ -39,7 +40,7 @@ var _ = Describe("Loopback", func() { BeforeEach(func() { command = exec.Command(pathToLoPlugin) containerID = "some-container-id" - networkNS = makeNetworkNS(containerID) + networkNS = testhelpers.MakeNetworkNS(containerID) environ = []string{ fmt.Sprintf("CNI_CONTAINERID=%s", containerID), @@ -52,7 +53,7 @@ var _ = Describe("Loopback", func() { }) AfterEach(func() { - Expect(removeNetworkNS(networkNS)).To(Succeed()) + Expect(testhelpers.RemoveNetworkNS(networkNS)).To(Succeed()) }) Context("when given a network namespace", func() { From 4fc8a90277d47cf68836d40a27d52b30977d584e Mon Sep 17 00:00:00 2001 From: Gabe Rosenhouse Date: Sun, 17 Apr 2016 18:35:49 -0700 Subject: [PATCH 04/23] Extract inode inspection functions into testhelpers --- pkg/ns/ns_test.go | 38 ++++++++++------------------------ pkg/testhelpers/testhelpers.go | 17 +++++++++++++++ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/pkg/ns/ns_test.go b/pkg/ns/ns_test.go index d9f182cf..42fc6322 100644 --- a/pkg/ns/ns_test.go +++ b/pkg/ns/ns_test.go @@ -22,28 +22,12 @@ import ( "os/exec" "path/filepath" - "golang.org/x/sys/unix" - "github.com/appc/cni/pkg/ns" + "github.com/appc/cni/pkg/testhelpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) -func getInode(path string) (uint64, error) { - file, err := os.Open(path) - if err != nil { - return 0, err - } - defer file.Close() - return getInodeF(file) -} - -func getInodeF(file *os.File) (uint64, error) { - stat := &unix.Stat_t{} - err := unix.Fstat(int(file.Fd()), stat) - return stat.Ino, err -} - const CurrentNetNS = "/proc/self/ns/net" var _ = Describe("Linux namespace operations", func() { @@ -81,13 +65,13 @@ var _ = Describe("Linux namespace operations", func() { }) It("executes the callback within the target network namespace", func() { - expectedInode, err := getInode(targetNetNSPath) + expectedInode, err := testhelpers.GetInode(targetNetNSPath) Expect(err).NotTo(HaveOccurred()) var actualInode uint64 var innerErr error err = ns.WithNetNS(targetNetNS, false, func(*os.File) error { - actualInode, innerErr = getInode(CurrentNetNS) + actualInode, innerErr = testhelpers.GetInode(CurrentNetNS) return nil }) Expect(err).NotTo(HaveOccurred()) @@ -97,13 +81,13 @@ var _ = Describe("Linux namespace operations", func() { }) It("provides the original namespace as the argument to the callback", func() { - hostNSInode, err := getInode(CurrentNetNS) + hostNSInode, err := testhelpers.GetInode(CurrentNetNS) Expect(err).NotTo(HaveOccurred()) var inputNSInode uint64 var innerErr error err = ns.WithNetNS(targetNetNS, false, func(inputNS *os.File) error { - inputNSInode, err = getInodeF(inputNS) + inputNSInode, err = testhelpers.GetInodeF(inputNS) return nil }) Expect(err).NotTo(HaveOccurred()) @@ -113,7 +97,7 @@ var _ = Describe("Linux namespace operations", func() { }) It("restores the calling thread to the original network namespace", func() { - preTestInode, err := getInode(CurrentNetNS) + preTestInode, err := testhelpers.GetInode(CurrentNetNS) Expect(err).NotTo(HaveOccurred()) err = ns.WithNetNS(targetNetNS, false, func(*os.File) error { @@ -121,7 +105,7 @@ var _ = Describe("Linux namespace operations", func() { }) Expect(err).NotTo(HaveOccurred()) - postTestInode, err := getInode(CurrentNetNS) + postTestInode, err := testhelpers.GetInode(CurrentNetNS) Expect(err).NotTo(HaveOccurred()) Expect(postTestInode).To(Equal(preTestInode)) @@ -129,14 +113,14 @@ var _ = Describe("Linux namespace operations", func() { Context("when the callback returns an error", func() { It("restores the calling thread to the original namespace before returning", func() { - preTestInode, err := getInode(CurrentNetNS) + preTestInode, err := testhelpers.GetInode(CurrentNetNS) Expect(err).NotTo(HaveOccurred()) _ = ns.WithNetNS(targetNetNS, false, func(*os.File) error { return errors.New("potato") }) - postTestInode, err := getInode(CurrentNetNS) + postTestInode, err := testhelpers.GetInode(CurrentNetNS) Expect(err).NotTo(HaveOccurred()) Expect(postTestInode).To(Equal(preTestInode)) @@ -152,10 +136,10 @@ var _ = Describe("Linux namespace operations", func() { Describe("validating inode mapping to namespaces", func() { It("checks that different namespaces have different inodes", func() { - hostNSInode, err := getInode(CurrentNetNS) + hostNSInode, err := testhelpers.GetInode(CurrentNetNS) Expect(err).NotTo(HaveOccurred()) - testNsInode, err := getInode(targetNetNSPath) + testNsInode, err := testhelpers.GetInode(targetNetNSPath) Expect(err).NotTo(HaveOccurred()) Expect(hostNSInode).NotTo(Equal(0)) diff --git a/pkg/testhelpers/testhelpers.go b/pkg/testhelpers/testhelpers.go index f1ccb24e..4eb42bdc 100644 --- a/pkg/testhelpers/testhelpers.go +++ b/pkg/testhelpers/testhelpers.go @@ -11,6 +11,8 @@ // 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 testhelpers provides common support behavior for tests package testhelpers import ( @@ -24,6 +26,21 @@ import ( . "github.com/onsi/gomega" ) +func GetInode(path string) (uint64, error) { + file, err := os.Open(path) + if err != nil { + return 0, err + } + defer file.Close() + return GetInodeF(file) +} + +func GetInodeF(file *os.File) (uint64, error) { + stat := &unix.Stat_t{} + err := unix.Fstat(int(file.Fd()), stat) + return stat.Ino, err +} + func MakeNetworkNS(containerID string) string { namespace := "/var/run/netns/" + containerID pid := unix.Getpid() From 1bbc87ab5458fb884de98fccc99c78bf7be4dbb1 Mon Sep 17 00:00:00 2001 From: Gabe Rosenhouse Date: Sun, 17 Apr 2016 18:48:50 -0700 Subject: [PATCH 05/23] Add basic unit tests of testhelpers --- pkg/testhelpers/testhelpers_suite_test.go | 31 ++++++++ pkg/testhelpers/testhelpers_test.go | 96 +++++++++++++++++++++++ test | 2 +- 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 pkg/testhelpers/testhelpers_suite_test.go create mode 100644 pkg/testhelpers/testhelpers_test.go diff --git a/pkg/testhelpers/testhelpers_suite_test.go b/pkg/testhelpers/testhelpers_suite_test.go new file mode 100644 index 00000000..88bfc3d6 --- /dev/null +++ b/pkg/testhelpers/testhelpers_suite_test.go @@ -0,0 +1,31 @@ +// Copyright 2016 CNI 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 testhelpers_test + +import ( + "math/rand" + + . "github.com/onsi/ginkgo" + "github.com/onsi/ginkgo/config" + . "github.com/onsi/gomega" + + "testing" +) + +func TestTesthelpers(t *testing.T) { + rand.Seed(config.GinkgoConfig.RandomSeed) + RegisterFailHandler(Fail) + RunSpecs(t, "Testhelpers Suite") +} diff --git a/pkg/testhelpers/testhelpers_test.go b/pkg/testhelpers/testhelpers_test.go new file mode 100644 index 00000000..ce328f01 --- /dev/null +++ b/pkg/testhelpers/testhelpers_test.go @@ -0,0 +1,96 @@ +// Copyright 2016 CNI 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 testhelpers_test contains unit tests of the testhelpers +// +// Some of this stuff is non-trivial and can interact in surprising ways +// with the Go runtime. Better be safe. +package testhelpers_test + +import ( + "fmt" + "math/rand" + "path/filepath" + + "golang.org/x/sys/unix" + + "github.com/appc/cni/pkg/testhelpers" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Test helper functions", func() { + Describe("MakeNetworkNS", func() { + It("should return the filepath to a network namespace", func() { + containerID := fmt.Sprintf("c-%x", rand.Int31()) + nsPath := testhelpers.MakeNetworkNS(containerID) + + Expect(nsPath).To(BeAnExistingFile()) + + testhelpers.RemoveNetworkNS(containerID) + }) + + It("should return a network namespace different from that of the caller", func() { + containerID := fmt.Sprintf("c-%x", rand.Int31()) + + By("discovering the inode of the current netns") + originalNetNSPath := currentNetNSPath() + originalNetNSInode, err := testhelpers.GetInode(originalNetNSPath) + Expect(err).NotTo(HaveOccurred()) + + By("creating a new netns") + createdNetNSPath := testhelpers.MakeNetworkNS(containerID) + defer testhelpers.RemoveNetworkNS(createdNetNSPath) + + By("discovering the inode of the created netns") + createdNetNSInode, err := testhelpers.GetInode(createdNetNSPath) + Expect(err).NotTo(HaveOccurred()) + + By("comparing the inodes") + Expect(createdNetNSInode).NotTo(Equal(originalNetNSInode)) + }) + + It("should not leak the new netns onto any threads in the process", func() { + containerID := fmt.Sprintf("c-%x", rand.Int31()) + + By("creating a new netns") + createdNetNSPath := testhelpers.MakeNetworkNS(containerID) + defer testhelpers.RemoveNetworkNS(createdNetNSPath) + + By("discovering the inode of the created netns") + createdNetNSInode, err := testhelpers.GetInode(createdNetNSPath) + Expect(err).NotTo(HaveOccurred()) + + By("comparing against the netns inode of every thread in the process") + for _, netnsPath := range allNetNSInCurrentProcess() { + netnsInode, err := testhelpers.GetInode(netnsPath) + Expect(err).NotTo(HaveOccurred()) + Expect(netnsInode).NotTo(Equal(createdNetNSInode)) + } + }) + }) +}) + +func currentNetNSPath() string { + pid := unix.Getpid() + tid := unix.Gettid() + return fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid) +} + +func allNetNSInCurrentProcess() []string { + pid := unix.Getpid() + paths, err := filepath.Glob(fmt.Sprintf("/proc/%d/task/*/ns/net", pid)) + Expect(err).NotTo(HaveOccurred()) + return paths +} diff --git a/test b/test index c02b360b..c5171bd4 100755 --- a/test +++ b/test @@ -11,7 +11,7 @@ set -e source ./build -TESTABLE="plugins/ipam/dhcp plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types pkg/utils" +TESTABLE="plugins/ipam/dhcp plugins/main/loopback pkg/invoke pkg/ns pkg/skel pkg/types pkg/utils pkg/testhelpers" FORMATTABLE="$TESTABLE libcni pkg/ip pkg/ns pkg/types pkg/ipam plugins/ipam/host-local plugins/main/bridge plugins/meta/flannel plugins/meta/tuning" # user has not provided PKG override From b09af2ff912efb1a62036fe25a1a11c22da60247 Mon Sep 17 00:00:00 2001 From: Gabe Rosenhouse Date: Sun, 17 Apr 2016 19:44:00 -0700 Subject: [PATCH 06/23] Fix issues with MakeNetworkNS test helper --- pkg/testhelpers/testhelpers.go | 49 ++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/pkg/testhelpers/testhelpers.go b/pkg/testhelpers/testhelpers.go index 4eb42bdc..0963121d 100644 --- a/pkg/testhelpers/testhelpers.go +++ b/pkg/testhelpers/testhelpers.go @@ -19,6 +19,7 @@ import ( "fmt" "os" "runtime" + "sync" "golang.org/x/sys/unix" @@ -43,37 +44,51 @@ func GetInodeF(file *os.File) (uint64, error) { func MakeNetworkNS(containerID string) string { namespace := "/var/run/netns/" + containerID - pid := unix.Getpid() - tid := unix.Gettid() err := os.MkdirAll("/var/run/netns", 0600) Expect(err).NotTo(HaveOccurred()) - runtime.LockOSThread() - defer runtime.UnlockOSThread() + // create an empty file at the mount point + mountPointFd, err := os.Create(namespace) + Expect(err).NotTo(HaveOccurred()) + mountPointFd.Close() + + var wg sync.WaitGroup + wg.Add(1) + + // do namespace work in a dedicated goroutine, so that we can safely + // Lock/Unlock OSThread without upsetting the lock/unlock state of + // the caller of this function go (func() { + defer wg.Done() + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + defer GinkgoRecover() + // capture current thread's original netns + pid := unix.Getpid() + tid := unix.Gettid() + currentThreadNetNSPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid) + originalNetNS, err := unix.Open(currentThreadNetNSPath, unix.O_RDONLY, 0) + Expect(err).NotTo(HaveOccurred()) + defer unix.Close(originalNetNS) + + // create a new netns on the current thread err = unix.Unshare(unix.CLONE_NEWNET) Expect(err).NotTo(HaveOccurred()) - fd, err := os.Create(namespace) + // bind mount the new netns from the current thread onto the mount point + err = unix.Mount(currentThreadNetNSPath, namespace, "none", unix.MS_BIND, "") Expect(err).NotTo(HaveOccurred()) - defer fd.Close() - err = unix.Mount("/proc/self/ns/net", namespace, "none", unix.MS_BIND, "") - Expect(err).NotTo(HaveOccurred()) + // reset current thread's netns to the original + _, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(originalNetNS), uintptr(unix.CLONE_NEWNET), 0) + Expect(e1).To(BeZero()) })() - Eventually(namespace).Should(BeAnExistingFile()) - - fd, err := unix.Open(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid), unix.O_RDONLY, 0) - Expect(err).NotTo(HaveOccurred()) - - defer unix.Close(fd) - - _, _, e1 := unix.Syscall(unix.SYS_SETNS, uintptr(fd), uintptr(unix.CLONE_NEWNET), 0) - Expect(e1).To(BeZero()) + wg.Wait() return namespace } From 260c7f96bf104ac077f72b6b2e3efc472a03b8b8 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 6 Apr 2016 11:03:31 -0500 Subject: [PATCH 07/23] ns: fix reading net namespace in multi-threaded processes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /proc/self/ns/net gives the main thread's namespace, not necessarily the namespace of the thread that's running the testcases. This causes sporadic failures of the tests. For example, with a testcase reading inodes after switching netns: /proc/27686/task/27689/ns/net 4026532565 /proc/self/ns/net 4026531969 /proc/27686/task/27689/ns/net 4026532565 See also: https://github.com/vishvananda/netns/commit/008d17ae001344769b031375bdb38a86219154c6 Running Suite: pkg/ns Suite =========================== Random Seed: 1459953577 Will run 6 of 6 specs • Failure [0.028 seconds] Linux namespace operations /cni/gopath/src/github.com/appc/cni/pkg/ns/ns_test.go:167 WithNetNS /cni/gopath/src/github.com/appc/cni/pkg/ns/ns_test.go:166 executes the callback within the target network namespace [It] /cni/gopath/src/github.com/appc/cni/pkg/ns/ns_test.go:97 Expected : 4026531969 to equal : 4026532565 /cni/gopath/src/github.com/appc/cni/pkg/ns/ns_test.go:96 ------------------------------ ••••• Summarizing 1 Failure: [Fail] Linux namespace operations WithNetNS [It] executes the callback within the target network namespace /cni/gopath/src/github.com/appc/cni/pkg/ns/ns_test.go:96 Ran 6 of 6 Specs in 0.564 seconds FAIL! -- 5 Passed | 1 Failed | 0 Pending | 0 Skipped --- FAIL: TestNs (0.56s) FAIL --- pkg/ns/ns_test.go | 22 +++++++--------------- pkg/testhelpers/testhelpers.go | 14 +++++++++++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/pkg/ns/ns_test.go b/pkg/ns/ns_test.go index 42fc6322..7ad882f5 100644 --- a/pkg/ns/ns_test.go +++ b/pkg/ns/ns_test.go @@ -28,13 +28,9 @@ import ( . "github.com/onsi/gomega" ) -const CurrentNetNS = "/proc/self/ns/net" - var _ = Describe("Linux namespace operations", func() { Describe("WithNetNS", func() { var ( - originalNetNS *os.File - targetNetNSName string targetNetNSPath string targetNetNS *os.File @@ -42,8 +38,6 @@ var _ = Describe("Linux namespace operations", func() { BeforeEach(func() { var err error - originalNetNS, err = os.Open(CurrentNetNS) - Expect(err).NotTo(HaveOccurred()) targetNetNSName = fmt.Sprintf("test-netns-%d", rand.Int()) @@ -60,8 +54,6 @@ var _ = Describe("Linux namespace operations", func() { err := exec.Command("ip", "netns", "del", targetNetNSName).Run() Expect(err).NotTo(HaveOccurred()) - - Expect(originalNetNS.Close()).To(Succeed()) }) It("executes the callback within the target network namespace", func() { @@ -71,7 +63,7 @@ var _ = Describe("Linux namespace operations", func() { var actualInode uint64 var innerErr error err = ns.WithNetNS(targetNetNS, false, func(*os.File) error { - actualInode, innerErr = testhelpers.GetInode(CurrentNetNS) + actualInode, innerErr = testhelpers.GetInodeCurNetNS() return nil }) Expect(err).NotTo(HaveOccurred()) @@ -81,7 +73,7 @@ var _ = Describe("Linux namespace operations", func() { }) It("provides the original namespace as the argument to the callback", func() { - hostNSInode, err := testhelpers.GetInode(CurrentNetNS) + hostNSInode, err := testhelpers.GetInodeCurNetNS() Expect(err).NotTo(HaveOccurred()) var inputNSInode uint64 @@ -97,7 +89,7 @@ var _ = Describe("Linux namespace operations", func() { }) It("restores the calling thread to the original network namespace", func() { - preTestInode, err := testhelpers.GetInode(CurrentNetNS) + preTestInode, err := testhelpers.GetInodeCurNetNS() Expect(err).NotTo(HaveOccurred()) err = ns.WithNetNS(targetNetNS, false, func(*os.File) error { @@ -105,7 +97,7 @@ var _ = Describe("Linux namespace operations", func() { }) Expect(err).NotTo(HaveOccurred()) - postTestInode, err := testhelpers.GetInode(CurrentNetNS) + postTestInode, err := testhelpers.GetInodeCurNetNS() Expect(err).NotTo(HaveOccurred()) Expect(postTestInode).To(Equal(preTestInode)) @@ -113,14 +105,14 @@ var _ = Describe("Linux namespace operations", func() { Context("when the callback returns an error", func() { It("restores the calling thread to the original namespace before returning", func() { - preTestInode, err := testhelpers.GetInode(CurrentNetNS) + preTestInode, err := testhelpers.GetInodeCurNetNS() Expect(err).NotTo(HaveOccurred()) _ = ns.WithNetNS(targetNetNS, false, func(*os.File) error { return errors.New("potato") }) - postTestInode, err := testhelpers.GetInode(CurrentNetNS) + postTestInode, err := testhelpers.GetInodeCurNetNS() Expect(err).NotTo(HaveOccurred()) Expect(postTestInode).To(Equal(preTestInode)) @@ -136,7 +128,7 @@ var _ = Describe("Linux namespace operations", func() { Describe("validating inode mapping to namespaces", func() { It("checks that different namespaces have different inodes", func() { - hostNSInode, err := testhelpers.GetInode(CurrentNetNS) + hostNSInode, err := testhelpers.GetInodeCurNetNS() Expect(err).NotTo(HaveOccurred()) testNsInode, err := testhelpers.GetInode(targetNetNSPath) diff --git a/pkg/testhelpers/testhelpers.go b/pkg/testhelpers/testhelpers.go index 0963121d..004006a9 100644 --- a/pkg/testhelpers/testhelpers.go +++ b/pkg/testhelpers/testhelpers.go @@ -27,6 +27,16 @@ import ( . "github.com/onsi/gomega" ) +func getCurrentThreadNetNSPath() string { + pid := unix.Getpid() + tid := unix.Gettid() + return fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid) +} + +func GetInodeCurNetNS() (uint64, error) { + return GetInode(getCurrentThreadNetNSPath()) +} + func GetInode(path string) (uint64, error) { file, err := os.Open(path) if err != nil { @@ -68,9 +78,7 @@ func MakeNetworkNS(containerID string) string { defer GinkgoRecover() // capture current thread's original netns - pid := unix.Getpid() - tid := unix.Gettid() - currentThreadNetNSPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid) + currentThreadNetNSPath := getCurrentThreadNetNSPath() originalNetNS, err := unix.Open(currentThreadNetNSPath, unix.O_RDONLY, 0) Expect(err).NotTo(HaveOccurred()) defer unix.Close(originalNetNS) From b5e56b3dabaebe247d094dc4ecedcf3cafb67596 Mon Sep 17 00:00:00 2001 From: Gabe Rosenhouse Date: Sun, 17 Apr 2016 20:27:02 -0700 Subject: [PATCH 08/23] Document use of goroutine and lockosthread in test helpers --- pkg/testhelpers/testhelpers.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/pkg/testhelpers/testhelpers.go b/pkg/testhelpers/testhelpers.go index 004006a9..e9a0fb3f 100644 --- a/pkg/testhelpers/testhelpers.go +++ b/pkg/testhelpers/testhelpers.go @@ -52,6 +52,33 @@ func GetInodeF(file *os.File) (uint64, error) { return stat.Ino, err } +/* +A note about goroutines, Linux namespaces and runtime.LockOSThread + +In Linux, network namespaces have thread affinity. + +In the Go language runtime, goroutines do not have affinity for OS threads. +The Go runtime scheduler moves goroutines around amongst OS threads. It +is supposed to be transparent to the Go programmer. + +In order to address cases where the programmer needs thread affinity, Go +provides runtime.LockOSThread and runtime.UnlockOSThread() + +However, the Go runtime does not reference count the Lock and Unlock calls. +Repeated calls to Lock will succeed, but the first call to Unlock will unlock +everything. Therefore, it is dangerous to hide a Lock/Unlock in a library +function, such as in this package. + +The code below, in MakeNetworkNS, avoids this problem by spinning up a new +Go routine specifically so that LockOSThread can be called on it. Thus +goroutine-thread affinity is maintained long enough to perform all the required +namespace operations. + +Because the LockOSThread call is performed inside this short-lived goroutine, +there is no effect either way on the caller's goroutine-thread affinity. + +* */ + func MakeNetworkNS(containerID string) string { namespace := "/var/run/netns/" + containerID @@ -68,7 +95,7 @@ func MakeNetworkNS(containerID string) string { // do namespace work in a dedicated goroutine, so that we can safely // Lock/Unlock OSThread without upsetting the lock/unlock state of - // the caller of this function + // the caller of this function. See block comment above. go (func() { defer wg.Done() From d53ffe1b400bbaa20c644f2e55a275ab06cc54fe Mon Sep 17 00:00:00 2001 From: Stefan Junker Date: Wed, 20 Apr 2016 17:54:12 +0200 Subject: [PATCH 09/23] README: clarify what CNI is The word "standard" does not represent what CNI is actually trying to be. --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ccc6aea4..c96526f3 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,15 @@ ## What is CNI? -CNI, the _Container Network Interface_, is a proposed standard for configuring network interfaces for Linux application containers. -The standard consists of a simple specification for how executable plugins can be used to configure network namespaces; this repository also contains a go library implementing that specification. - +CNI, the _Container Network Interface_, is a project to help configure network interfaces for Linux application containers. CNI concerns itself with setting up network connectivity of containers and removing allocated resources when the container is deleted. Because of this focus CNI has a wide range of support and the specification is simple to implement. -The specification itself is contained in [SPEC.md](SPEC.md). +The project repository contains a [simple specification](SPEC.md) for how executable plugins can be used to configure network namespaces, and a number of plugins, libraries and utilities written in Go that can be used to get started with CNI. + +The specification and the plugin architecture form a template system with perfectly clear interfaces. +This allows developers to integrate their existing container networking solutions with a thin CNI wrapper plugin. +It also gives a good framework to create new container networking solutions from scratch. ## Why develop CNI? From 4298aa94a56b6327573b050c43a6fb2b38e91e7d Mon Sep 17 00:00:00 2001 From: Piotr Skamruk Date: Mon, 7 Mar 2016 16:40:27 +0100 Subject: [PATCH 10/23] pkg/utils: add functions to work with sysctl --- pkg/utils/sysctl/sysctl_linux.go | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 pkg/utils/sysctl/sysctl_linux.go diff --git a/pkg/utils/sysctl/sysctl_linux.go b/pkg/utils/sysctl/sysctl_linux.go new file mode 100644 index 00000000..c0fba382 --- /dev/null +++ b/pkg/utils/sysctl/sysctl_linux.go @@ -0,0 +1,58 @@ +// Copyright 2016 CNI 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. + +// build +linux + +package sysctl + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "strings" +) + +// Sysctl provides a method to set/get values from /proc/sys - in linux systems +// new interface to set/get values of variables formerly handled by sysctl syscall +// If optional `params` have only one string value - this function will +// set this value into coresponding sysctl variable +func Sysctl(name string, params ...string) (string, error) { + if len(params) > 1 { + return "", fmt.Errorf("unexcepted additional parameters") + } else if len(params) == 1 { + return setSysctl(name, params[0]) + } + return getSysctl(name) +} + +func getSysctl(name string) (string, error) { + fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1)) + fullName = filepath.Clean(fullName) + data, err := ioutil.ReadFile(fullName) + if err != nil { + return "", err + } + + return string(data[:len(data)-1]), nil +} + +func setSysctl(name, value string) (string, error) { + fullName := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1)) + fullName = filepath.Clean(fullName) + if err := ioutil.WriteFile(fullName, []byte(value), 0644); err != nil { + return "", err + } + + return getSysctl(name) +} From a1dab0aa400d4f23877267838d5a8fc8bcaa43d6 Mon Sep 17 00:00:00 2001 From: Piotr Skamruk Date: Mon, 7 Mar 2016 16:41:04 +0100 Subject: [PATCH 11/23] macvlan: set proxy_arp in time of creating interface Resolves CNI part of https://github.com/coreos/rkt/issues/1765 Second part would be adding similar lines into kvm flavored macvlan support (in time of creating macvtap device). --- plugins/main/macvlan/macvlan.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/main/macvlan/macvlan.go b/plugins/main/macvlan/macvlan.go index f6891a34..0635f263 100644 --- a/plugins/main/macvlan/macvlan.go +++ b/plugins/main/macvlan/macvlan.go @@ -26,9 +26,14 @@ import ( "github.com/appc/cni/pkg/ns" "github.com/appc/cni/pkg/skel" "github.com/appc/cni/pkg/types" + "github.com/appc/cni/pkg/utils/sysctl" "github.com/vishvananda/netlink" ) +const ( + IPv4InterfaceArpProxySysctlTemplate = "net.ipv4.conf.%s.proxy_arp" +) + type NetConf struct { types.NetConf Master string `json:"master"` @@ -80,7 +85,7 @@ func createMacvlan(conf *NetConf, ifName string, netns *os.File) error { return fmt.Errorf("failed to lookup master %q: %v", conf.Master, err) } - // due to kernel bug we have to create with tmpname or it might + // due to kernel bug we have to create with tmpName or it might // collide with the name on the host and error out tmpName, err := ip.RandomVethName() if err != nil { @@ -101,6 +106,14 @@ func createMacvlan(conf *NetConf, ifName string, netns *os.File) error { return fmt.Errorf("failed to create macvlan: %v", err) } + // TODO: duplicate following lines for ipv6 support, when it will be added in other places + ipv4SysctlValueName := fmt.Sprintf(IPv4InterfaceArpProxySysctlTemplate, tmpName) + if _, err := sysctl.Sysctl(ipv4SysctlValueName, "1"); err != nil { + // remove the newly added link and ignore errors, because we already are in a failed state + _ = netlink.LinkDel(mv) + return fmt.Errorf("failed to set proxy_arp on newly added interface %q: %v", tmpName, err) + } + return ns.WithNetNS(netns, false, func(_ *os.File) error { err := renameLink(tmpName, ifName) if err != nil { From 41a5dfac331f5fd921c85dd71e82535c92c24ec8 Mon Sep 17 00:00:00 2001 From: Tom Denham Date: Fri, 22 Apr 2016 12:52:28 -0700 Subject: [PATCH 12/23] Remove reference to policy on accepting PRs There is to policy --- CONTRIBUTING.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3c9e213e..c17c687b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,8 +5,6 @@ pull requests. This document outlines some of the conventions on development workflow, commit message formatting, contact points and other resources to make it easier to get your contribution accepted. -For more information on the policy for accepting contributions, see [POLICY](POLICY.md) - # Certificate of Origin By contributing to this project you agree to the Developer Certificate of From a993ef5f7f8711264e8a9bad8a7bb50086a8c1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20L=C3=B3pez=20Galeiras?= Date: Tue, 3 May 2016 12:21:58 +0200 Subject: [PATCH 13/23] plugins/bridge: clean masquerading rules In the Add command we set up masquerading rules that didn't have a corresponding clean-up code in Del. Add the clean-up code. --- plugins/main/bridge/bridge.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index e4bc106c..cc363a41 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -238,14 +238,25 @@ func cmdDel(args *skel.CmdArgs) error { return err } - err = ipam.ExecDel(n.IPAM.Type, args.StdinData) + var ipn *net.IPNet + err = ns.WithNetNSPath(args.Netns, false, func(hostNS *os.File) error { + var err error + ipn, err = ip.DelLinkByNameAddr(args.IfName, netlink.FAMILY_V4) + return err + }) if err != nil { return err } - return ns.WithNetNSPath(args.Netns, false, func(hostNS *os.File) error { - return ip.DelLinkByName(args.IfName) - }) + if n.IPMasq { + chain := utils.FormatChainName(n.Name, args.ContainerID) + comment := utils.FormatComment(n.Name, args.ContainerID) + if err = ip.TeardownIPMasq(ipn, chain, comment); err != nil { + return err + } + } + + return ipam.ExecDel(n.IPAM.Type, args.StdinData) } func main() { From 61f20da4f2ba2b38af9916ab18b410ff335a414e Mon Sep 17 00:00:00 2001 From: Vipin Jain Date: Wed, 4 May 2016 20:29:13 -0700 Subject: [PATCH 14/23] README: add contiv to cni supported networking --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c96526f3..ed4b0215 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ Hence we are proposing this specification, along with an initial set of plugins - [Cloud Foundry - a platform for cloud applications](https://github.com/cloudfoundry-incubator/guardian-cni-adapter) - [Weave - a multi-host Docker network](https://github.com/weaveworks/weave) - [Project Calico - a layer 3 virtual network](https://github.com/projectcalico/calico-cni) +- [Contiv Networking - policy networking for various use cases](https://github.com/contiv/netplugin) ## Contributing to CNI From 04dbf7ce45637e370141374b861755e23fa3e562 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Fri, 6 May 2016 08:39:21 -0700 Subject: [PATCH 15/23] README: fix badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ed4b0215..47c9968a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![Build Status](https://travis-ci.org/appc/cni.svg?branch=master)](https://travis-ci.org/appc/cni) -[![Coverage Status](https://coveralls.io/repos/github/appc/cni/badge.svg?branch=master)](https://coveralls.io/github/appc/cni?branch=master) +[![Build Status](https://travis-ci.org/containernetworking/cni.svg?branch=master)](https://travis-ci.org/appc/cni) +[![Coverage Status](https://coveralls.io/repos/github/containernetworking/cni/badge.svg?branch=master)](https://coveralls.io/github/appc/cni?branch=master) # CNI - the Container Network Interface From 419711fee338ef101f832c3528734a3af61eaf2a Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Fri, 6 May 2016 08:39:55 -0700 Subject: [PATCH 16/23] README: fix badge links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 47c9968a..ed040f96 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![Build Status](https://travis-ci.org/containernetworking/cni.svg?branch=master)](https://travis-ci.org/appc/cni) -[![Coverage Status](https://coveralls.io/repos/github/containernetworking/cni/badge.svg?branch=master)](https://coveralls.io/github/appc/cni?branch=master) +[![Build Status](https://travis-ci.org/containernetworking/cni.svg?branch=master)](https://travis-ci.org/containernetworking/cni) +[![Coverage Status](https://coveralls.io/repos/github/containernetworking/cni/badge.svg?branch=master)](https://coveralls.io/github/containernetworking/cni?branch=master) # CNI - the Container Network Interface From 2c482f433c3c408b919f5da075e77f7b9a829812 Mon Sep 17 00:00:00 2001 From: Stefan Junker Date: Wed, 4 May 2016 16:06:05 +0200 Subject: [PATCH 17/23] *: appc/cni -> containernetworking/cni The project has been moved so internally we simply rename everything. Consumers are recommended to update their vendored version of cni. --- CONTRIBUTING.md | 4 ++-- Documentation/dhcp.md | 2 +- Documentation/host-local.md | 2 +- Godeps/Godeps.json | 2 +- README.md | 6 +++--- build | 2 +- cnitool/cni.go | 2 +- libcni/api.go | 4 ++-- pkg/invoke/delegate.go | 2 +- pkg/invoke/exec.go | 2 +- pkg/invoke/find_test.go | 2 +- pkg/ip/link.go | 2 +- pkg/ipam/ipam.go | 6 +++--- pkg/ns/ns_test.go | 4 ++-- pkg/skel/skel.go | 2 +- pkg/testhelpers/testhelpers_test.go | 2 +- pkg/types/args_test.go | 2 +- plugins/ipam/dhcp/daemon.go | 4 ++-- plugins/ipam/dhcp/lease.go | 4 ++-- plugins/ipam/dhcp/main.go | 4 ++-- plugins/ipam/dhcp/options.go | 2 +- plugins/ipam/dhcp/options_test.go | 2 +- plugins/ipam/host-local/allocator.go | 6 +++--- plugins/ipam/host-local/config.go | 2 +- plugins/ipam/host-local/main.go | 6 +++--- plugins/main/bridge/bridge.go | 12 ++++++------ plugins/main/ipvlan/ipvlan.go | 10 +++++----- plugins/main/loopback/loopback.go | 6 +++--- plugins/main/loopback/loopback_suite_test.go | 2 +- plugins/main/loopback/loopback_test.go | 4 ++-- plugins/main/macvlan/macvlan.go | 12 ++++++------ plugins/main/ptp/ptp.go | 12 ++++++------ plugins/meta/flannel/flannel.go | 6 +++--- plugins/meta/tuning/tuning.go | 6 +++--- 34 files changed, 74 insertions(+), 74 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c17c687b..c056968c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,9 +14,9 @@ contribution. See the [DCO](DCO) file for details. # Email and Chat -The project uses the the cni-dev email list and #appc on Freenode for chat: +The project uses the the cni-dev email list and IRC chat: - Email: [cni-dev](https://groups.google.com/forum/#!forum/cni-dev) -- IRC: #[appc](irc://irc.freenode.org:6667/#appc) IRC channel on freenode.org +- IRC: #[containernetworking](irc://irc.freenode.org:6667/#containernetworking) channel on freenode.org Please avoid emailing maintainers found in the MAINTAINERS file directly. They are very busy and read the mailing lists. diff --git a/Documentation/dhcp.md b/Documentation/dhcp.md index 298e96e0..7451c2c8 100644 --- a/Documentation/dhcp.md +++ b/Documentation/dhcp.md @@ -3,7 +3,7 @@ ## Overview With dhcp plugin the containers can get an IP allocated by a DHCP server already running on your network. -This can be especially useful with plugin types such as [macvlan](https://github.com/appc/cni/blob/master/Documentation/macvlan.md). +This can be especially useful with plugin types such as [macvlan](https://github.com/containernetworking/cni/blob/master/Documentation/macvlan.md). Because a DHCP lease must be periodically renewed for the duration of container lifetime, a separate daemon is required to be running. The same plugin binary can also be run in the daemon mode. diff --git a/Documentation/host-local.md b/Documentation/host-local.md index 35aba355..37446157 100644 --- a/Documentation/host-local.md +++ b/Documentation/host-local.md @@ -32,7 +32,7 @@ It stores the state locally on the host filesystem, therefore ensuring uniquenes * `routes` (string, optional): list of routes to add to the container namespace. Each route is a dictionary with "dst" and optional "gw" fields. If "gw" is omitted, value of "gateway" will be used. ## Supported arguments -The following [CNI_ARGS](https://github.com/appc/cni/blob/master/SPEC.md#parameters) are supported: +The following [CNI_ARGS](https://github.com/containernetworking/cni/blob/master/SPEC.md#parameters) are supported: * `ip`: request a specific IP address from the subnet. If it's not available, the plugin will exit with an error diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index d0ace65d..e362e06a 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,5 +1,5 @@ { - "ImportPath": "github.com/appc/cni", + "ImportPath": "github.com/containernetworking/cni", "GoVersion": "go1.6", "Packages": [ "./..." diff --git a/README.md b/README.md index ed040f96..f4467d3e 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Hence we are proposing this specification, along with an initial set of plugins ## Contributing to CNI -We welcome contributions, including [bug reports](https://github.com/appc/cni/issues), and code and documentation improvements. +We welcome contributions, including [bug reports](https://github.com/containernetworking/cni/issues), and code and documentation improvements. If you intend to contribute to code or documentation, please read [CONTRIBUTING.md](CONTRIBUTING.md). Also see the [contact section](#contact) in this README. ## How do I use CNI? @@ -157,6 +157,6 @@ If these topics of are interest please contact the team via the mailing list or ## Contact -For any questions about CNI, please reach out on the mailing list or IRC: +For any questions about CNI, please reach out on the mailing list: - Email: [cni-dev](https://groups.google.com/forum/#!forum/cni-dev) -- IRC: #[appc](irc://irc.freenode.org:6667/#appc) IRC channel on freenode.org +- IRC: #[containernetworking](irc://irc.freenode.org:6667/#containernetworking) channel on freenode.org diff --git a/build b/build index 815b360d..2acc8f27 100755 --- a/build +++ b/build @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -e -ORG_PATH="github.com/appc" +ORG_PATH="github.com/containernetworking" REPO_PATH="${ORG_PATH}/cni" if [ ! -h gopath/src/${REPO_PATH} ]; then diff --git a/cnitool/cni.go b/cnitool/cni.go index 62ac6759..91255c7f 100644 --- a/cnitool/cni.go +++ b/cnitool/cni.go @@ -20,7 +20,7 @@ import ( "path/filepath" "strings" - "github.com/appc/cni/libcni" + "github.com/containernetworking/cni/libcni" ) const ( diff --git a/libcni/api.go b/libcni/api.go index 77ca5d22..340a20cc 100644 --- a/libcni/api.go +++ b/libcni/api.go @@ -17,8 +17,8 @@ package libcni import ( "strings" - "github.com/appc/cni/pkg/invoke" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/invoke" + "github.com/containernetworking/cni/pkg/types" ) type RuntimeConf struct { diff --git a/pkg/invoke/delegate.go b/pkg/invoke/delegate.go index 0a8198c3..ddf1d172 100644 --- a/pkg/invoke/delegate.go +++ b/pkg/invoke/delegate.go @@ -19,7 +19,7 @@ import ( "os" "strings" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types" ) func DelegateAdd(delegatePlugin string, netconf []byte) (*types.Result, error) { diff --git a/pkg/invoke/exec.go b/pkg/invoke/exec.go index 337bfcb8..a85eede6 100644 --- a/pkg/invoke/exec.go +++ b/pkg/invoke/exec.go @@ -21,7 +21,7 @@ import ( "os" "os/exec" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types" ) func pluginErr(err error, output []byte) error { diff --git a/pkg/invoke/find_test.go b/pkg/invoke/find_test.go index 4135538d..be4cc2dd 100644 --- a/pkg/invoke/find_test.go +++ b/pkg/invoke/find_test.go @@ -19,7 +19,7 @@ import ( "io/ioutil" "path/filepath" - "github.com/appc/cni/pkg/invoke" + "github.com/containernetworking/cni/pkg/invoke" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) diff --git a/pkg/ip/link.go b/pkg/ip/link.go index 1ba529da..df168124 100644 --- a/pkg/ip/link.go +++ b/pkg/ip/link.go @@ -20,7 +20,7 @@ import ( "net" "os" - "github.com/appc/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/ns" "github.com/vishvananda/netlink" ) diff --git a/pkg/ipam/ipam.go b/pkg/ipam/ipam.go index f0adfb7f..d9fbff74 100644 --- a/pkg/ipam/ipam.go +++ b/pkg/ipam/ipam.go @@ -18,9 +18,9 @@ import ( "fmt" "os" - "github.com/appc/cni/pkg/invoke" - "github.com/appc/cni/pkg/ip" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/invoke" + "github.com/containernetworking/cni/pkg/ip" + "github.com/containernetworking/cni/pkg/types" "github.com/vishvananda/netlink" ) diff --git a/pkg/ns/ns_test.go b/pkg/ns/ns_test.go index 7ad882f5..a901eb35 100644 --- a/pkg/ns/ns_test.go +++ b/pkg/ns/ns_test.go @@ -22,8 +22,8 @@ import ( "os/exec" "path/filepath" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/testhelpers" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/testhelpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) diff --git a/pkg/skel/skel.go b/pkg/skel/skel.go index 5c3532db..7347b078 100644 --- a/pkg/skel/skel.go +++ b/pkg/skel/skel.go @@ -22,7 +22,7 @@ import ( "log" "os" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types" ) // CmdArgs captures all the arguments passed in to the plugin diff --git a/pkg/testhelpers/testhelpers_test.go b/pkg/testhelpers/testhelpers_test.go index ce328f01..62d45856 100644 --- a/pkg/testhelpers/testhelpers_test.go +++ b/pkg/testhelpers/testhelpers_test.go @@ -25,7 +25,7 @@ import ( "golang.org/x/sys/unix" - "github.com/appc/cni/pkg/testhelpers" + "github.com/containernetworking/cni/pkg/testhelpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) diff --git a/pkg/types/args_test.go b/pkg/types/args_test.go index 23aaf817..61fd2233 100644 --- a/pkg/types/args_test.go +++ b/pkg/types/args_test.go @@ -17,7 +17,7 @@ package types_test import ( "reflect" - . "github.com/appc/cni/pkg/types" + . "github.com/containernetworking/cni/pkg/types" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" diff --git a/plugins/ipam/dhcp/daemon.go b/plugins/ipam/dhcp/daemon.go index dabedf72..2386f9a9 100644 --- a/plugins/ipam/dhcp/daemon.go +++ b/plugins/ipam/dhcp/daemon.go @@ -27,8 +27,8 @@ import ( "runtime" "sync" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" "github.com/coreos/go-systemd/activation" ) diff --git a/plugins/ipam/dhcp/lease.go b/plugins/ipam/dhcp/lease.go index 90c223c7..82e2fc60 100644 --- a/plugins/ipam/dhcp/lease.go +++ b/plugins/ipam/dhcp/lease.go @@ -27,8 +27,8 @@ import ( "github.com/d2g/dhcp4client" "github.com/vishvananda/netlink" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/types" ) // RFC 2131 suggests using exponential backoff, starting with 4sec diff --git a/plugins/ipam/dhcp/main.go b/plugins/ipam/dhcp/main.go index da44d576..b5378315 100644 --- a/plugins/ipam/dhcp/main.go +++ b/plugins/ipam/dhcp/main.go @@ -20,8 +20,8 @@ import ( "os" "path/filepath" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" ) const socketPath = "/run/cni/dhcp.sock" diff --git a/plugins/ipam/dhcp/options.go b/plugins/ipam/dhcp/options.go index f2712c28..b11ec21d 100644 --- a/plugins/ipam/dhcp/options.go +++ b/plugins/ipam/dhcp/options.go @@ -20,7 +20,7 @@ import ( "net" "time" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types" "github.com/d2g/dhcp4" ) diff --git a/plugins/ipam/dhcp/options_test.go b/plugins/ipam/dhcp/options_test.go index 0a140cef..f69ae7bc 100644 --- a/plugins/ipam/dhcp/options_test.go +++ b/plugins/ipam/dhcp/options_test.go @@ -18,7 +18,7 @@ import ( "net" "testing" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types" "github.com/d2g/dhcp4" ) diff --git a/plugins/ipam/host-local/allocator.go b/plugins/ipam/host-local/allocator.go index 2b867ce5..55a3ae6f 100644 --- a/plugins/ipam/host-local/allocator.go +++ b/plugins/ipam/host-local/allocator.go @@ -18,9 +18,9 @@ import ( "fmt" "net" - "github.com/appc/cni/pkg/ip" - "github.com/appc/cni/pkg/types" - "github.com/appc/cni/plugins/ipam/host-local/backend" + "github.com/containernetworking/cni/pkg/ip" + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/plugins/ipam/host-local/backend" ) type IPAllocator struct { diff --git a/plugins/ipam/host-local/config.go b/plugins/ipam/host-local/config.go index 08ca07e3..a0e493cd 100644 --- a/plugins/ipam/host-local/config.go +++ b/plugins/ipam/host-local/config.go @@ -19,7 +19,7 @@ import ( "fmt" "net" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/types" ) // IPAMConfig represents the IP related network configuration. diff --git a/plugins/ipam/host-local/main.go b/plugins/ipam/host-local/main.go index 9f67e8a5..d2f3c305 100644 --- a/plugins/ipam/host-local/main.go +++ b/plugins/ipam/host-local/main.go @@ -15,10 +15,10 @@ package main import ( - "github.com/appc/cni/plugins/ipam/host-local/backend/disk" + "github.com/containernetworking/cni/plugins/ipam/host-local/backend/disk" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" ) func main() { diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index cc363a41..3c058e1a 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -23,12 +23,12 @@ import ( "runtime" "syscall" - "github.com/appc/cni/pkg/ip" - "github.com/appc/cni/pkg/ipam" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" - "github.com/appc/cni/pkg/utils" + "github.com/containernetworking/cni/pkg/ip" + "github.com/containernetworking/cni/pkg/ipam" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/utils" "github.com/vishvananda/netlink" ) diff --git a/plugins/main/ipvlan/ipvlan.go b/plugins/main/ipvlan/ipvlan.go index 85919772..6de0cb9e 100644 --- a/plugins/main/ipvlan/ipvlan.go +++ b/plugins/main/ipvlan/ipvlan.go @@ -21,11 +21,11 @@ import ( "os" "runtime" - "github.com/appc/cni/pkg/ip" - "github.com/appc/cni/pkg/ipam" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/ip" + "github.com/containernetworking/cni/pkg/ipam" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" "github.com/vishvananda/netlink" ) diff --git a/plugins/main/loopback/loopback.go b/plugins/main/loopback/loopback.go index dabe8078..1e5095d0 100644 --- a/plugins/main/loopback/loopback.go +++ b/plugins/main/loopback/loopback.go @@ -17,9 +17,9 @@ package main import ( "os" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" "github.com/vishvananda/netlink" ) diff --git a/plugins/main/loopback/loopback_suite_test.go b/plugins/main/loopback/loopback_suite_test.go index be179aa8..e3557479 100644 --- a/plugins/main/loopback/loopback_suite_test.go +++ b/plugins/main/loopback/loopback_suite_test.go @@ -32,7 +32,7 @@ func TestLoopback(t *testing.T) { var _ = BeforeSuite(func() { var err error - pathToLoPlugin, err = gexec.Build("github.com/appc/cni/plugins/main/loopback") + pathToLoPlugin, err = gexec.Build("github.com/containernetworking/cni/plugins/main/loopback") Expect(err).NotTo(HaveOccurred()) }) diff --git a/plugins/main/loopback/loopback_test.go b/plugins/main/loopback/loopback_test.go index 037fbfeb..7c009d1d 100644 --- a/plugins/main/loopback/loopback_test.go +++ b/plugins/main/loopback/loopback_test.go @@ -21,8 +21,8 @@ import ( "os/exec" "strings" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/testhelpers" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/testhelpers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gbytes" diff --git a/plugins/main/macvlan/macvlan.go b/plugins/main/macvlan/macvlan.go index 0635f263..febf2fc0 100644 --- a/plugins/main/macvlan/macvlan.go +++ b/plugins/main/macvlan/macvlan.go @@ -21,12 +21,12 @@ import ( "os" "runtime" - "github.com/appc/cni/pkg/ip" - "github.com/appc/cni/pkg/ipam" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" - "github.com/appc/cni/pkg/utils/sysctl" + "github.com/containernetworking/cni/pkg/ip" + "github.com/containernetworking/cni/pkg/ipam" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/utils/sysctl" "github.com/vishvananda/netlink" ) diff --git a/plugins/main/ptp/ptp.go b/plugins/main/ptp/ptp.go index 3035c643..2cd5185a 100644 --- a/plugins/main/ptp/ptp.go +++ b/plugins/main/ptp/ptp.go @@ -24,12 +24,12 @@ import ( "github.com/vishvananda/netlink" - "github.com/appc/cni/pkg/ip" - "github.com/appc/cni/pkg/ipam" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" - "github.com/appc/cni/pkg/utils" + "github.com/containernetworking/cni/pkg/ip" + "github.com/containernetworking/cni/pkg/ipam" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" + "github.com/containernetworking/cni/pkg/utils" ) func init() { diff --git a/plugins/meta/flannel/flannel.go b/plugins/meta/flannel/flannel.go index 6653baca..096fe6d6 100644 --- a/plugins/meta/flannel/flannel.go +++ b/plugins/meta/flannel/flannel.go @@ -29,9 +29,9 @@ import ( "strconv" "strings" - "github.com/appc/cni/pkg/invoke" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/invoke" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" ) const ( diff --git a/plugins/meta/tuning/tuning.go b/plugins/meta/tuning/tuning.go index 91118dfb..f48d3226 100644 --- a/plugins/meta/tuning/tuning.go +++ b/plugins/meta/tuning/tuning.go @@ -25,9 +25,9 @@ import ( "path/filepath" "strings" - "github.com/appc/cni/pkg/ns" - "github.com/appc/cni/pkg/skel" - "github.com/appc/cni/pkg/types" + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" ) // TuningConf represents the network tuning configuration. From 5d67d22caa363eb957e91aa3bc77666d5a77ec2f Mon Sep 17 00:00:00 2001 From: Stefan Junker Date: Wed, 11 May 2016 18:50:25 +0200 Subject: [PATCH 18/23] plugins/{ptp,bridge}: teardown first This will allow the IPAM allocations to be cleared in case the interfaces and iptables rules are non-existent. --- plugins/main/bridge/bridge.go | 6 +++++- plugins/main/ptp/ptp.go | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index 3c058e1a..77c52156 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -238,6 +238,10 @@ func cmdDel(args *skel.CmdArgs) error { return err } + if err := ipam.ExecDel(n.IPAM.Type, args.StdinData); err != nil { + return err + } + var ipn *net.IPNet err = ns.WithNetNSPath(args.Netns, false, func(hostNS *os.File) error { var err error @@ -256,7 +260,7 @@ func cmdDel(args *skel.CmdArgs) error { } } - return ipam.ExecDel(n.IPAM.Type, args.StdinData) + return nil } func main() { diff --git a/plugins/main/ptp/ptp.go b/plugins/main/ptp/ptp.go index 2cd5185a..f92c49ef 100644 --- a/plugins/main/ptp/ptp.go +++ b/plugins/main/ptp/ptp.go @@ -195,6 +195,10 @@ func cmdDel(args *skel.CmdArgs) error { return fmt.Errorf("failed to load netconf: %v", err) } + if err := ipam.ExecDel(conf.IPAM.Type, args.StdinData); err != nil { + return err + } + var ipn *net.IPNet err := ns.WithNetNSPath(args.Netns, false, func(hostNS *os.File) error { var err error @@ -213,7 +217,7 @@ func cmdDel(args *skel.CmdArgs) error { } } - return ipam.ExecDel(conf.IPAM.Type, args.StdinData) + return nil } func main() { From ec78e7cf1e79e8d69bac3fc13a0674e6b9255eea Mon Sep 17 00:00:00 2001 From: Jonathan Boulle Date: Tue, 10 May 2016 12:12:05 +0200 Subject: [PATCH 19/23] MAINTAINERS: add Tom Denham and Gabe Rosenhouse --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 619c9574..b76133a0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1,3 +1,5 @@ +Gabe Rosenhouse (@rosenhouse) Michael Bridgen (@squaremo) Stefan Junker (@steveeJ) +Tom Denham (@tomdee) Zach Gershman (@zachgersh) From 979044ad2f7b7002258209e4ada2df4dd25d9747 Mon Sep 17 00:00:00 2001 From: Angus Lees Date: Fri, 13 May 2016 17:18:39 +1000 Subject: [PATCH 20/23] pkg/ns: use correct syscall number on arm --- pkg/ns/ns.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ns/ns.go b/pkg/ns/ns.go index 4f0814f1..ea848224 100644 --- a/pkg/ns/ns.go +++ b/pkg/ns/ns.go @@ -24,7 +24,7 @@ import ( var setNsMap = map[string]uintptr{ "386": 346, "amd64": 308, - "arm": 374, + "arm": 375, } // SetNS sets the network namespace on a target file. From a80bcc037169f1ee67590a0b30a0d23ffc2dd7c3 Mon Sep 17 00:00:00 2001 From: Angus Lees Date: Fri, 13 May 2016 17:32:40 +1000 Subject: [PATCH 21/23] pkg/ns: evaluate syscall number at compile-time Previously this code used a run-time map lookup keyed by runtime.GOOS/GOARCH. This version uses conditional compilation to make this choice at compile time, giving immediate feedback for unsupported platforms. --- pkg/ns/consts_linux_386.go | 17 +++++++++++++++++ pkg/ns/consts_linux_amd64.go | 17 +++++++++++++++++ pkg/ns/consts_linux_arm.go | 17 +++++++++++++++++ pkg/ns/ns.go | 17 +---------------- 4 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 pkg/ns/consts_linux_386.go create mode 100644 pkg/ns/consts_linux_amd64.go create mode 100644 pkg/ns/consts_linux_arm.go diff --git a/pkg/ns/consts_linux_386.go b/pkg/ns/consts_linux_386.go new file mode 100644 index 00000000..fd6ed8a0 --- /dev/null +++ b/pkg/ns/consts_linux_386.go @@ -0,0 +1,17 @@ +// Copyright 2015 CNI 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 ns + +const setNsNr = 346 diff --git a/pkg/ns/consts_linux_amd64.go b/pkg/ns/consts_linux_amd64.go new file mode 100644 index 00000000..a86a68a4 --- /dev/null +++ b/pkg/ns/consts_linux_amd64.go @@ -0,0 +1,17 @@ +// Copyright 2015 CNI 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 ns + +const setNsNr = 308 diff --git a/pkg/ns/consts_linux_arm.go b/pkg/ns/consts_linux_arm.go new file mode 100644 index 00000000..5beaaf3f --- /dev/null +++ b/pkg/ns/consts_linux_arm.go @@ -0,0 +1,17 @@ +// Copyright 2015 CNI 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 ns + +const setNsNr = 375 diff --git a/pkg/ns/ns.go b/pkg/ns/ns.go index ea848224..72533993 100644 --- a/pkg/ns/ns.go +++ b/pkg/ns/ns.go @@ -21,24 +21,9 @@ import ( "syscall" ) -var setNsMap = map[string]uintptr{ - "386": 346, - "amd64": 308, - "arm": 375, -} - // SetNS sets the network namespace on a target file. func SetNS(f *os.File, flags uintptr) error { - if runtime.GOOS != "linux" { - return fmt.Errorf("unsupported OS: %s", runtime.GOOS) - } - - trap, ok := setNsMap[runtime.GOARCH] - if !ok { - return fmt.Errorf("unsupported arch: %s", runtime.GOARCH) - } - - _, _, err := syscall.RawSyscall(trap, f.Fd(), flags, 0) + _, _, err := syscall.RawSyscall(setNsNr, f.Fd(), flags, 0) if err != 0 { return err } From f4eb76318ea8e8f4946aaf3cc2272d0db578573b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 28 Apr 2016 11:26:47 -0500 Subject: [PATCH 22/23] macvlan: sysctl must be set in macvlan interface's namespace The macvlan is initially created in a separate network namespace and the sysctl must be set in that namespace too. --- plugins/main/macvlan/macvlan.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/plugins/main/macvlan/macvlan.go b/plugins/main/macvlan/macvlan.go index febf2fc0..ce05871f 100644 --- a/plugins/main/macvlan/macvlan.go +++ b/plugins/main/macvlan/macvlan.go @@ -106,17 +106,18 @@ func createMacvlan(conf *NetConf, ifName string, netns *os.File) error { return fmt.Errorf("failed to create macvlan: %v", err) } - // TODO: duplicate following lines for ipv6 support, when it will be added in other places - ipv4SysctlValueName := fmt.Sprintf(IPv4InterfaceArpProxySysctlTemplate, tmpName) - if _, err := sysctl.Sysctl(ipv4SysctlValueName, "1"); err != nil { - // remove the newly added link and ignore errors, because we already are in a failed state - _ = netlink.LinkDel(mv) - return fmt.Errorf("failed to set proxy_arp on newly added interface %q: %v", tmpName, err) - } - return ns.WithNetNS(netns, false, func(_ *os.File) error { + // TODO: duplicate following lines for ipv6 support, when it will be added in other places + ipv4SysctlValueName := fmt.Sprintf(IPv4InterfaceArpProxySysctlTemplate, tmpName) + if _, err := sysctl.Sysctl(ipv4SysctlValueName, "1"); err != nil { + // remove the newly added link and ignore errors, because we already are in a failed state + _ = netlink.LinkDel(mv) + return fmt.Errorf("failed to set proxy_arp on newly added interface %q: %v", tmpName, err) + } + err := renameLink(tmpName, ifName) if err != nil { + _ = netlink.LinkDel(mv) return fmt.Errorf("failed to rename macvlan to %q: %v", ifName, err) } return nil From 89ab9299abcc165ad41189c407f8691eb95f8262 Mon Sep 17 00:00:00 2001 From: Minhan Xia Date: Tue, 5 Apr 2016 10:50:28 -0700 Subject: [PATCH 23/23] plugins/bridge: add support to set hairpin mode --- Documentation/bridge.md | 2 ++ plugins/main/bridge/bridge.go | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Documentation/bridge.md b/Documentation/bridge.md index bda5ac5c..f9c7f2c4 100644 --- a/Documentation/bridge.md +++ b/Documentation/bridge.md @@ -19,6 +19,7 @@ If the bridge is missing, the plugin will create one on first use and, if gatewa "bridge": "mynet0", "isGateway": true, "ipMasq": true, + "hairpinMode": true, "ipam": { "type": "host-local", "subnet": "10.10.0.0/16" @@ -34,4 +35,5 @@ If the bridge is missing, the plugin will create one on first use and, if gatewa * `isGateway` (boolean, optional): assign an IP address to the bridge. Defaults to false. * `ipMasq` (boolean, optional): set up IP Masquerade on the host for traffic originating from this network and destined outside of it. Defaults to false. * `mtu` (integer, optional): explicitly set MTU to the specified value. Defaults to the value chosen by the kernel. +* `hairpinMode` (boolean, optional): set hairpin mode for interfaces on the bridge. Defaults to false. * `ipam` (dictionary, required): IPAM configuration to be used for this network. diff --git a/plugins/main/bridge/bridge.go b/plugins/main/bridge/bridge.go index 77c52156..9082b05f 100644 --- a/plugins/main/bridge/bridge.go +++ b/plugins/main/bridge/bridge.go @@ -36,10 +36,11 @@ const defaultBrName = "cni0" type NetConf struct { types.NetConf - BrName string `json:"bridge"` - IsGW bool `json:"isGateway"` - IPMasq bool `json:"ipMasq"` - MTU int `json:"mtu"` + BrName string `json:"bridge"` + IsGW bool `json:"isGateway"` + IPMasq bool `json:"ipMasq"` + MTU int `json:"mtu"` + HairpinMode bool `json:"hairpinMode"` } func init() { @@ -123,7 +124,7 @@ func ensureBridge(brName string, mtu int) (*netlink.Bridge, error) { return br, nil } -func setupVeth(netns string, br *netlink.Bridge, ifName string, mtu int) error { +func setupVeth(netns string, br *netlink.Bridge, ifName string, mtu int, hairpinMode bool) error { var hostVethName string err := ns.WithNetNSPath(netns, false, func(hostNS *os.File) error { @@ -151,6 +152,11 @@ func setupVeth(netns string, br *netlink.Bridge, ifName string, mtu int) error { return fmt.Errorf("failed to connect %q to bridge %v: %v", hostVethName, br.Attrs().Name, err) } + // set hairpin mode + if err = netlink.LinkSetHairpin(hostVeth, hairpinMode); err != nil { + return fmt.Errorf("failed to setup hairpin mode for %v: %v", hostVethName, err) + } + return nil } @@ -180,7 +186,7 @@ func cmdAdd(args *skel.CmdArgs) error { return err } - if err = setupVeth(args.Netns, br, args.IfName, n.MTU); err != nil { + if err = setupVeth(args.Netns, br, args.IfName, n.MTU, n.HairpinMode); err != nil { return err }