diff --git a/netlink/netlink.go b/netlink/netlink.go index dd9b1c16..90883660 100644 --- a/netlink/netlink.go +++ b/netlink/netlink.go @@ -11,8 +11,9 @@ import ( ) var ( - ErrWrongSockType = errors.New("Wrong socket type") - ErrShortResponse = errors.New("Got short response from netlink") + ErrWrongSockType = errors.New("Wrong socket type") + ErrShortResponse = errors.New("Got short response from netlink") + ErrInterfaceExists = errors.New("Network interface already exists") ) // A Route is a subnet associated with the interface to reach it. diff --git a/netlink/netlink_linux.go b/netlink/netlink_linux.go index 738af879..3083cf90 100644 --- a/netlink/netlink_linux.go +++ b/netlink/netlink_linux.go @@ -6,6 +6,7 @@ import ( "io" "math/rand" "net" + "os" "sync/atomic" "syscall" "unsafe" @@ -708,7 +709,16 @@ func NetworkCreateVethPair(name1, name2 string) error { if err := s.Send(wb); err != nil { return err } - return s.HandleAck(wb.Seq) + + if err := s.HandleAck(wb.Seq); err != nil { + if os.IsExist(err) { + return ErrInterfaceExists + } + + return err + } + + return nil } // Add a new VLAN interface with masterDev as its upper device diff --git a/network/veth.go b/network/veth.go index a95bcf48..42a05c6b 100644 --- a/network/veth.go +++ b/network/veth.go @@ -96,16 +96,17 @@ func (v *Veth) Initialize(config *Network, networkState *NetworkState) error { // createVethPair will automatically generage two random names for // the veth pair and ensure that they have been created func createVethPair(prefix string) (name1 string, name2 string, err error) { - name1, err = utils.GenerateRandomName(prefix, 4) - if err != nil { + if name1, err = utils.GenerateRandomName(prefix, 7); err != nil { return } - name2, err = utils.GenerateRandomName(prefix, 4) - if err != nil { + + if name2, err = utils.GenerateRandomName(prefix, 7); err != nil { return } + if err = CreateVethPair(name1, name2); err != nil { return } + return } diff --git a/network/veth_test.go b/network/veth_test.go new file mode 100644 index 00000000..e09a6042 --- /dev/null +++ b/network/veth_test.go @@ -0,0 +1,53 @@ +// +build linux + +package network + +import ( + "testing" + + "github.com/docker/libcontainer/netlink" +) + +func TestGenerateVethNames(t *testing.T) { + if testing.Short() { + return + } + + prefix := "veth" + + name1, name2, err := createVethPair(prefix) + if err != nil { + t.Fatal(err) + } + + if name1 == "" { + t.Fatal("name1 should not be empty") + } + + if name2 == "" { + t.Fatal("name2 should not be empty") + } +} + +func TestCreateDuplicateVethPair(t *testing.T) { + if testing.Short() { + return + } + + prefix := "veth" + + name1, name2, err := createVethPair(prefix) + if err != nil { + t.Fatal(err) + } + + // retry to create the name interfaces and make sure that we get the correct error + err = CreateVethPair(name1, name2) + if err == nil { + t.Fatal("expected error to not be nil with duplicate interface") + } + + if err != netlink.ErrInterfaceExists { + t.Fatalf("expected error to be ErrInterfaceExists but received %q", err) + } +}