From 255989b8359011aa2d5987b5926c59a94cced1eb Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Thu, 2 Oct 2014 21:54:48 +0000 Subject: [PATCH 1/2] Introduce more entropy in veth name generation The current 4 chars are not enough, bumped to 7 Signed-off-by: Michael Crosby --- netlink/netlink.go | 5 ++-- netlink/netlink_linux.go | 12 ++++++++- network/veth.go | 9 ++++--- network/veth_test.go | 53 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 network/veth_test.go 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) + } +} From b9d08491f6629898f04a0976ea8a31bc5b058b30 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Thu, 2 Oct 2014 22:03:25 +0000 Subject: [PATCH 2/2] Add loop for veth pair creation on ErrInterfaceExists Signed-off-by: Michael Crosby --- network/veth.go | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/network/veth.go b/network/veth.go index 42a05c6b..e5185de7 100644 --- a/network/veth.go +++ b/network/veth.go @@ -5,6 +5,7 @@ package network import ( "fmt" + "github.com/docker/libcontainer/netlink" "github.com/docker/libcontainer/utils" ) @@ -96,16 +97,24 @@ 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) { - if name1, err = utils.GenerateRandomName(prefix, 7); err != nil { - return - } + for i := 0; i < 10; i++ { + if name1, err = utils.GenerateRandomName(prefix, 7); err != nil { + return + } - if name2, err = utils.GenerateRandomName(prefix, 7); err != nil { - return - } + if name2, err = utils.GenerateRandomName(prefix, 7); err != nil { + return + } - if err = CreateVethPair(name1, name2); err != nil { - return + if err = CreateVethPair(name1, name2); err != nil { + if err == netlink.ErrInterfaceExists { + continue + } + + return + } + + break } return