Sfoglia il codice sorgente

Refactor driverapi, sandbox pkgs

- Move SanboxInfo and Interface structures in sandbox package
  (changed it to Info as per golint)
- Move UUID to new internal pkg types
- Updated .gitignore to ignore IDE project files

Signed-off-by: Alessandro Boch <aboch@docker.com>
Alessandro Boch 10 anni fa
parent
commit
7d24e974cf

+ 3 - 0
libnetwork/.gitignore

@@ -26,3 +26,6 @@ _testmain.go
 # Coverage
 # Coverage
 *.tmp
 *.tmp
 *.coverprofile
 *.coverprofile
+
+# IDE files
+.project

+ 6 - 126
libnetwork/driverapi/driverapi.go

@@ -2,9 +2,9 @@ package driverapi
 
 
 import (
 import (
 	"errors"
 	"errors"
-	"net"
 
 
-	"github.com/docker/libnetwork/netutils"
+	"github.com/docker/libnetwork/sandbox"
+	"github.com/docker/libnetwork/types"
 )
 )
 
 
 var (
 var (
@@ -16,9 +16,6 @@ var (
 	ErrNoEndpoint = errors.New("No endpoint exists")
 	ErrNoEndpoint = errors.New("No endpoint exists")
 )
 )
 
 
-// UUID represents a globally unique ID of various resources like network and endpoint
-type UUID string
-
 // Driver is an interface that every plugin driver needs to implement.
 // Driver is an interface that every plugin driver needs to implement.
 type Driver interface {
 type Driver interface {
 	// Push driver specific config to the driver
 	// Push driver specific config to the driver
@@ -27,136 +24,19 @@ type Driver interface {
 	// CreateNetwork invokes the driver method to create a network passing
 	// CreateNetwork invokes the driver method to create a network passing
 	// the network id and network specific config. The config mechanism will
 	// the network id and network specific config. The config mechanism will
 	// eventually be replaced with labels which are yet to be introduced.
 	// eventually be replaced with labels which are yet to be introduced.
-	CreateNetwork(nid UUID, config interface{}) error
+	CreateNetwork(nid types.UUID, config interface{}) error
 
 
 	// DeleteNetwork invokes the driver method to delete network passing
 	// DeleteNetwork invokes the driver method to delete network passing
 	// the network id.
 	// the network id.
-	DeleteNetwork(nid UUID) error
+	DeleteNetwork(nid types.UUID) error
 
 
 	// CreateEndpoint invokes the driver method to create an endpoint
 	// CreateEndpoint invokes the driver method to create an endpoint
 	// passing the network id, endpoint id, sandbox key and driver
 	// passing the network id, endpoint id, sandbox key and driver
 	// specific config. The config mechanism will eventually be replaced
 	// specific config. The config mechanism will eventually be replaced
 	// with labels which are yet to be introduced.
 	// with labels which are yet to be introduced.
-	CreateEndpoint(nid, eid UUID, key string, config interface{}) (*SandboxInfo, error)
+	CreateEndpoint(nid, eid types.UUID, key string, config interface{}) (*sandbox.Info, error)
 
 
 	// DeleteEndpoint invokes the driver method to delete an endpoint
 	// DeleteEndpoint invokes the driver method to delete an endpoint
 	// passing the network id and endpoint id.
 	// passing the network id and endpoint id.
-	DeleteEndpoint(nid, eid UUID) error
-}
-
-// Interface represents the settings and identity of a network device. It is
-// used as a return type for Network.Link, and it is common practice for the
-// caller to use this information when moving interface SrcName from host
-// namespace to DstName in a different net namespace with the appropriate
-// network settings.
-type Interface struct {
-	// The name of the interface in the origin network namespace.
-	SrcName string
-
-	// The name that will be assigned to the interface once moves inside a
-	// network namespace.
-	DstName string
-
-	// IPv4 address for the interface.
-	Address *net.IPNet
-
-	// IPv6 address for the interface.
-	AddressIPv6 *net.IPNet
-}
-
-// SandboxInfo represents all possible information that
-// the driver wants to place in the sandbox which includes
-// interfaces, routes and gateway
-type SandboxInfo struct {
-	Interfaces []*Interface
-
-	// IPv4 gateway for the sandbox.
-	Gateway net.IP
-
-	// IPv6 gateway for the sandbox.
-	GatewayIPv6 net.IP
-
-	// TODO: Add routes and ip tables etc.
-}
-
-// GetCopy returns a copy of this Interface structure
-func (i *Interface) GetCopy() *Interface {
-	return &Interface{
-		SrcName:     i.SrcName,
-		DstName:     i.DstName,
-		Address:     netutils.GetIPNetCopy(i.Address),
-		AddressIPv6: netutils.GetIPNetCopy(i.AddressIPv6),
-	}
-}
-
-// Equal checks if this instance of Interface is equal to the passed one
-func (i *Interface) Equal(o *Interface) bool {
-	if i == o {
-		return true
-	}
-
-	if o == nil {
-		return false
-	}
-
-	if i.SrcName != o.SrcName || i.DstName != o.DstName {
-		return false
-	}
-
-	if !netutils.CompareIPNet(i.Address, o.Address) {
-		return false
-	}
-
-	if !netutils.CompareIPNet(i.AddressIPv6, o.AddressIPv6) {
-		return false
-	}
-
-	return true
-}
-
-// GetCopy returns a copy of this SandboxInfo structure
-func (s *SandboxInfo) GetCopy() *SandboxInfo {
-	list := make([]*Interface, len(s.Interfaces))
-	for i, iface := range s.Interfaces {
-		list[i] = iface.GetCopy()
-	}
-	gw := netutils.GetIPCopy(s.Gateway)
-	gw6 := netutils.GetIPCopy(s.GatewayIPv6)
-
-	return &SandboxInfo{Interfaces: list, Gateway: gw, GatewayIPv6: gw6}
-}
-
-// Equal checks if this instance of SandboxInfo is equal to the passed one
-func (s *SandboxInfo) Equal(o *SandboxInfo) bool {
-	if s == o {
-		return true
-	}
-
-	if o == nil {
-		return false
-	}
-
-	if !s.Gateway.Equal(o.Gateway) {
-		return false
-	}
-
-	if !s.GatewayIPv6.Equal(o.GatewayIPv6) {
-		return false
-	}
-
-	if (s.Interfaces == nil && o.Interfaces != nil) ||
-		(s.Interfaces != nil && o.Interfaces == nil) ||
-		(len(s.Interfaces) != len(o.Interfaces)) {
-		return false
-	}
-
-	// Note: At the moment, the two lists must be in the same order
-	for i := 0; i < len(s.Interfaces); i++ {
-		if !s.Interfaces[i].Equal(o.Interfaces[i]) {
-			return false
-		}
-	}
-
-	return true
-
+	DeleteEndpoint(nid, eid types.UUID) error
 }
 }

+ 0 - 71
libnetwork/driverapi/driverapi_test.go

@@ -1,71 +0,0 @@
-package driverapi
-
-import (
-	"net"
-	"testing"
-)
-
-func TestInterfaceEqual(t *testing.T) {
-	list := getInterfaceList()
-
-	if !list[0].Equal(list[0]) {
-		t.Fatalf("Interface.Equal() returned false negative")
-	}
-
-	if list[0].Equal(list[1]) {
-		t.Fatalf("Interface.Equal() returned false positive")
-	}
-
-	if list[0].Equal(list[1]) != list[1].Equal(list[0]) {
-		t.Fatalf("Interface.Equal() failed commutative check")
-	}
-}
-
-func TestInterfaceCopy(t *testing.T) {
-	for _, iface := range getInterfaceList() {
-		cp := iface.GetCopy()
-
-		if !iface.Equal(cp) {
-			t.Fatalf("Failed to return a copy of Interface")
-		}
-
-		if iface == cp {
-			t.Fatalf("Failed to return a true copy of Interface")
-		}
-	}
-}
-
-func TestSandboxInfoCopy(t *testing.T) {
-	si := SandboxInfo{Interfaces: getInterfaceList(), Gateway: net.ParseIP("192.168.1.254"), GatewayIPv6: net.ParseIP("2001:2345::abcd:8889")}
-	cp := si.GetCopy()
-
-	if !si.Equal(cp) {
-		t.Fatalf("Failed to return a copy of SandboxInfo")
-	}
-
-	if &si == cp {
-		t.Fatalf("Failed to return a true copy of SanboxInfo")
-	}
-}
-
-func getInterfaceList() []*Interface {
-	_, netv4a, _ := net.ParseCIDR("192.168.30.1/24")
-	_, netv4b, _ := net.ParseCIDR("172.18.255.2/23")
-	_, netv6a, _ := net.ParseCIDR("2001:2345::abcd:8888/80")
-	_, netv6b, _ := net.ParseCIDR("2001:2345::abcd:8889/80")
-
-	return []*Interface{
-		&Interface{
-			SrcName:     "veth1234567",
-			DstName:     "eth0",
-			Address:     netv4a,
-			AddressIPv6: netv6a,
-		},
-		&Interface{
-			SrcName:     "veth7654321",
-			DstName:     "eth1",
-			Address:     netv4b,
-			AddressIPv6: netv6b,
-		},
-	}
-}

+ 11 - 9
libnetwork/drivers/bridge/bridge.go

@@ -10,6 +10,8 @@ import (
 	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/pkg/options"
 	"github.com/docker/libnetwork/pkg/options"
 	"github.com/docker/libnetwork/portmapper"
 	"github.com/docker/libnetwork/portmapper"
+	"github.com/docker/libnetwork/sandbox"
+	"github.com/docker/libnetwork/types"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
 )
 )
 
 
@@ -40,13 +42,13 @@ type Configuration struct {
 }
 }
 
 
 type bridgeEndpoint struct {
 type bridgeEndpoint struct {
-	id          driverapi.UUID
+	id          types.UUID
 	addressIPv4 net.IP
 	addressIPv4 net.IP
 	addressIPv6 net.IP
 	addressIPv6 net.IP
 }
 }
 
 
 type bridgeNetwork struct {
 type bridgeNetwork struct {
-	id driverapi.UUID
+	id types.UUID
 	// bridge interface points to the linux bridge and it's configuration
 	// bridge interface points to the linux bridge and it's configuration
 	bridge   *bridgeInterface
 	bridge   *bridgeInterface
 	endpoint *bridgeEndpoint
 	endpoint *bridgeEndpoint
@@ -95,7 +97,7 @@ func (d *driver) Config(option interface{}) error {
 }
 }
 
 
 // Create a new network using simplebridge plugin
 // Create a new network using simplebridge plugin
-func (d *driver) CreateNetwork(id driverapi.UUID, option interface{}) error {
+func (d *driver) CreateNetwork(id types.UUID, option interface{}) error {
 
 
 	var (
 	var (
 		err error
 		err error
@@ -178,7 +180,7 @@ func (d *driver) CreateNetwork(id driverapi.UUID, option interface{}) error {
 	return nil
 	return nil
 }
 }
 
 
-func (d *driver) DeleteNetwork(nid driverapi.UUID) error {
+func (d *driver) DeleteNetwork(nid types.UUID) error {
 	var err error
 	var err error
 	d.Lock()
 	d.Lock()
 	n := d.network
 	n := d.network
@@ -211,7 +213,7 @@ func (d *driver) DeleteNetwork(nid driverapi.UUID) error {
 	return err
 	return err
 }
 }
 
 
-func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, epOption interface{}) (*driverapi.SandboxInfo, error) {
+func (d *driver) CreateEndpoint(nid, eid types.UUID, sboxKey string, epOption interface{}) (*sandbox.Info, error) {
 	var (
 	var (
 		ipv6Addr *net.IPNet
 		ipv6Addr *net.IPNet
 		ip6      net.IP
 		ip6      net.IP
@@ -303,10 +305,10 @@ func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, epOptio
 		ipv6Addr = &net.IPNet{IP: ip6, Mask: n.bridge.bridgeIPv6.Mask}
 		ipv6Addr = &net.IPNet{IP: ip6, Mask: n.bridge.bridgeIPv6.Mask}
 	}
 	}
 
 
-	var interfaces []*driverapi.Interface
-	sinfo := &driverapi.SandboxInfo{}
+	var interfaces []*sandbox.Interface
+	sinfo := &sandbox.Info{}
 
 
-	intf := &driverapi.Interface{}
+	intf := &sandbox.Interface{}
 	intf.SrcName = name2
 	intf.SrcName = name2
 	intf.DstName = containerVeth
 	intf.DstName = containerVeth
 	intf.Address = ipv4Addr
 	intf.Address = ipv4Addr
@@ -323,7 +325,7 @@ func (d *driver) CreateEndpoint(nid, eid driverapi.UUID, sboxKey string, epOptio
 	return sinfo, nil
 	return sinfo, nil
 }
 }
 
 
-func (d *driver) DeleteEndpoint(nid, eid driverapi.UUID) error {
+func (d *driver) DeleteEndpoint(nid, eid types.UUID) error {
 	var err error
 	var err error
 
 
 	d.Lock()
 	d.Lock()

+ 11 - 9
libnetwork/network.go

@@ -43,6 +43,8 @@ import (
 
 
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/docker/pkg/stringid"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/driverapi"
+	"github.com/docker/libnetwork/sandbox"
+	"github.com/docker/libnetwork/types"
 )
 )
 
 
 // NetworkController provides the interface for controller instance which manages
 // NetworkController provides the interface for controller instance which manages
@@ -91,7 +93,7 @@ type Endpoint interface {
 	Network() string
 	Network() string
 
 
 	// SandboxInfo returns the sandbox information for this endpoint.
 	// SandboxInfo returns the sandbox information for this endpoint.
-	SandboxInfo() *driverapi.SandboxInfo
+	SandboxInfo() *sandbox.Info
 
 
 	// Delete and detaches this endpoint from the network.
 	// Delete and detaches this endpoint from the network.
 	Delete() error
 	Delete() error
@@ -105,23 +107,23 @@ type NetworkDriver struct {
 
 
 type endpoint struct {
 type endpoint struct {
 	name        string
 	name        string
-	id          driverapi.UUID
+	id          types.UUID
 	network     *network
 	network     *network
-	sandboxInfo *driverapi.SandboxInfo
+	sandboxInfo *sandbox.Info
 }
 }
 
 
 type network struct {
 type network struct {
 	ctrlr       *controller
 	ctrlr       *controller
 	name        string
 	name        string
 	networkType string
 	networkType string
-	id          driverapi.UUID
+	id          types.UUID
 	driver      *NetworkDriver
 	driver      *NetworkDriver
 	endpoints   endpointTable
 	endpoints   endpointTable
 	sync.Mutex
 	sync.Mutex
 }
 }
 
 
-type networkTable map[driverapi.UUID]*network
-type endpointTable map[driverapi.UUID]*endpoint
+type networkTable map[types.UUID]*network
+type endpointTable map[types.UUID]*endpoint
 
 
 type controller struct {
 type controller struct {
 	networks networkTable
 	networks networkTable
@@ -165,7 +167,7 @@ func (c *controller) NewNetwork(nd *NetworkDriver, name string, options interfac
 
 
 	network := &network{
 	network := &network{
 		name:   name,
 		name:   name,
-		id:     driverapi.UUID(stringid.GenerateRandomID()),
+		id:     types.UUID(stringid.GenerateRandomID()),
 		ctrlr:  c,
 		ctrlr:  c,
 		driver: nd}
 		driver: nd}
 	network.endpoints = make(endpointTable)
 	network.endpoints = make(endpointTable)
@@ -237,7 +239,7 @@ func (n *network) Delete() error {
 
 
 func (n *network) CreateEndpoint(name string, sboxKey string, options interface{}) (Endpoint, error) {
 func (n *network) CreateEndpoint(name string, sboxKey string, options interface{}) (Endpoint, error) {
 	ep := &endpoint{name: name}
 	ep := &endpoint{name: name}
-	ep.id = driverapi.UUID(stringid.GenerateRandomID())
+	ep.id = types.UUID(stringid.GenerateRandomID())
 	ep.network = n
 	ep.network = n
 
 
 	d := n.driver.internalDriver
 	d := n.driver.internalDriver
@@ -280,7 +282,7 @@ func (ep *endpoint) Network() string {
 	return ep.network.name
 	return ep.network.name
 }
 }
 
 
-func (ep *endpoint) SandboxInfo() *driverapi.SandboxInfo {
+func (ep *endpoint) SandboxInfo() *sandbox.Info {
 	if ep.sandboxInfo == nil {
 	if ep.sandboxInfo == nil {
 		return nil
 		return nil
 	}
 	}

+ 5 - 6
libnetwork/sandbox/configure_linux.go

@@ -4,14 +4,13 @@ import (
 	"fmt"
 	"fmt"
 	"net"
 	"net"
 
 
-	"github.com/docker/libnetwork/driverapi"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
 )
 )
 
 
-func configureInterface(iface netlink.Link, settings *driverapi.Interface) error {
+func configureInterface(iface netlink.Link, settings *Interface) error {
 	ifaceName := iface.Attrs().Name
 	ifaceName := iface.Attrs().Name
 	ifaceConfigurators := []struct {
 	ifaceConfigurators := []struct {
-		Fn         func(netlink.Link, *driverapi.Interface) error
+		Fn         func(netlink.Link, *Interface) error
 		ErrMessage string
 		ErrMessage string
 	}{
 	}{
 		{setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, settings.DstName)},
 		{setInterfaceName, fmt.Sprintf("error renaming interface %q to %q", ifaceName, settings.DstName)},
@@ -34,16 +33,16 @@ func setGatewayIP(gw net.IP) error {
 	})
 	})
 }
 }
 
 
-func setInterfaceIP(iface netlink.Link, settings *driverapi.Interface) error {
+func setInterfaceIP(iface netlink.Link, settings *Interface) error {
 	ipAddr := &netlink.Addr{IPNet: settings.Address, Label: ""}
 	ipAddr := &netlink.Addr{IPNet: settings.Address, Label: ""}
 	return netlink.AddrAdd(iface, ipAddr)
 	return netlink.AddrAdd(iface, ipAddr)
 }
 }
 
 
-func setInterfaceIPv6(iface netlink.Link, settings *driverapi.Interface) error {
+func setInterfaceIPv6(iface netlink.Link, settings *Interface) error {
 	ipAddr := &netlink.Addr{IPNet: settings.Address, Label: ""}
 	ipAddr := &netlink.Addr{IPNet: settings.Address, Label: ""}
 	return netlink.AddrAdd(iface, ipAddr)
 	return netlink.AddrAdd(iface, ipAddr)
 }
 }
 
 
-func setInterfaceName(iface netlink.Link, settings *driverapi.Interface) error {
+func setInterfaceName(iface netlink.Link, settings *Interface) error {
 	return netlink.LinkSetName(iface, settings.DstName)
 	return netlink.LinkSetName(iface, settings.DstName)
 }
 }

+ 3 - 4
libnetwork/sandbox/namespace_linux.go

@@ -7,7 +7,6 @@ import (
 	"runtime"
 	"runtime"
 	"syscall"
 	"syscall"
 
 
-	"github.com/docker/libnetwork/driverapi"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netns"
 	"github.com/vishvananda/netns"
 )
 )
@@ -17,7 +16,7 @@ import (
 // into it when called on method AddInterface or sets the gateway etc.
 // into it when called on method AddInterface or sets the gateway etc.
 type networkNamespace struct {
 type networkNamespace struct {
 	path  string
 	path  string
-	sinfo *driverapi.SandboxInfo
+	sinfo *Info
 }
 }
 
 
 // NewSandbox provides a new sandbox instance created in an os specific way
 // NewSandbox provides a new sandbox instance created in an os specific way
@@ -74,7 +73,7 @@ func loopbackUp() error {
 	return netlink.LinkSetUp(iface)
 	return netlink.LinkSetUp(iface)
 }
 }
 
 
-func (n *networkNamespace) AddInterface(i *driverapi.Interface) error {
+func (n *networkNamespace) AddInterface(i *Interface) error {
 	runtime.LockOSThread()
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 	defer runtime.UnlockOSThread()
 
 
@@ -139,7 +138,7 @@ func (n *networkNamespace) SetGatewayIPv6(gw net.IP) error {
 	return err
 	return err
 }
 }
 
 
-func (n *networkNamespace) Interfaces() []*driverapi.Interface {
+func (n *networkNamespace) Interfaces() []*Interface {
 	return n.sinfo.Interfaces
 	return n.sinfo.Interfaces
 }
 }
 
 

+ 120 - 3
libnetwork/sandbox/sandbox.go

@@ -3,7 +3,7 @@ package sandbox
 import (
 import (
 	"net"
 	"net"
 
 
-	"github.com/docker/libnetwork/driverapi"
+	"github.com/docker/libnetwork/netutils"
 )
 )
 
 
 // Sandbox represents a network sandbox, identified by a specific key.  It
 // Sandbox represents a network sandbox, identified by a specific key.  It
@@ -16,12 +16,12 @@ type Sandbox interface {
 	// method. Note that this doesn't incude network interfaces added in any
 	// method. Note that this doesn't incude network interfaces added in any
 	// other way (such as the default loopback interface which are automatically
 	// other way (such as the default loopback interface which are automatically
 	// created on creation of a sandbox).
 	// created on creation of a sandbox).
-	Interfaces() []*driverapi.Interface
+	Interfaces() []*Interface
 
 
 	// Add an existing Interface to this sandbox. The operation will rename
 	// Add an existing Interface to this sandbox. The operation will rename
 	// from the Interface SrcName to DstName as it moves, and reconfigure the
 	// from the Interface SrcName to DstName as it moves, and reconfigure the
 	// interface according to the specified settings.
 	// interface according to the specified settings.
-	AddInterface(*driverapi.Interface) error
+	AddInterface(*Interface) error
 
 
 	// Set default IPv4 gateway for the sandbox
 	// Set default IPv4 gateway for the sandbox
 	SetGateway(gw net.IP) error
 	SetGateway(gw net.IP) error
@@ -29,3 +29,120 @@ type Sandbox interface {
 	// Set default IPv6 gateway for the sandbox
 	// Set default IPv6 gateway for the sandbox
 	SetGatewayIPv6(gw net.IP) error
 	SetGatewayIPv6(gw net.IP) error
 }
 }
+
+// Info represents all possible information that
+// the driver wants to place in the sandbox which includes
+// interfaces, routes and gateway
+type Info struct {
+	Interfaces []*Interface
+
+	// IPv4 gateway for the sandbox.
+	Gateway net.IP
+
+	// IPv6 gateway for the sandbox.
+	GatewayIPv6 net.IP
+
+	// TODO: Add routes and ip tables etc.
+}
+
+// Interface represents the settings and identity of a network device. It is
+// used as a return type for Network.Link, and it is common practice for the
+// caller to use this information when moving interface SrcName from host
+// namespace to DstName in a different net namespace with the appropriate
+// network settings.
+type Interface struct {
+	// The name of the interface in the origin network namespace.
+	SrcName string
+
+	// The name that will be assigned to the interface once moves inside a
+	// network namespace.
+	DstName string
+
+	// IPv4 address for the interface.
+	Address *net.IPNet
+
+	// IPv6 address for the interface.
+	AddressIPv6 *net.IPNet
+}
+
+// GetCopy returns a copy of this Interface structure
+func (i *Interface) GetCopy() *Interface {
+	return &Interface{
+		SrcName:     i.SrcName,
+		DstName:     i.DstName,
+		Address:     netutils.GetIPNetCopy(i.Address),
+		AddressIPv6: netutils.GetIPNetCopy(i.AddressIPv6),
+	}
+}
+
+// Equal checks if this instance of Interface is equal to the passed one
+func (i *Interface) Equal(o *Interface) bool {
+	if i == o {
+		return true
+	}
+
+	if o == nil {
+		return false
+	}
+
+	if i.SrcName != o.SrcName || i.DstName != o.DstName {
+		return false
+	}
+
+	if !netutils.CompareIPNet(i.Address, o.Address) {
+		return false
+	}
+
+	if !netutils.CompareIPNet(i.AddressIPv6, o.AddressIPv6) {
+		return false
+	}
+
+	return true
+}
+
+// GetCopy returns a copy of this SandboxInfo structure
+func (s *Info) GetCopy() *Info {
+	list := make([]*Interface, len(s.Interfaces))
+	for i, iface := range s.Interfaces {
+		list[i] = iface.GetCopy()
+	}
+	gw := netutils.GetIPCopy(s.Gateway)
+	gw6 := netutils.GetIPCopy(s.GatewayIPv6)
+
+	return &Info{Interfaces: list, Gateway: gw, GatewayIPv6: gw6}
+}
+
+// Equal checks if this instance of SandboxInfo is equal to the passed one
+func (s *Info) Equal(o *Info) bool {
+	if s == o {
+		return true
+	}
+
+	if o == nil {
+		return false
+	}
+
+	if !s.Gateway.Equal(o.Gateway) {
+		return false
+	}
+
+	if !s.GatewayIPv6.Equal(o.GatewayIPv6) {
+		return false
+	}
+
+	if (s.Interfaces == nil && o.Interfaces != nil) ||
+		(s.Interfaces != nil && o.Interfaces == nil) ||
+		(len(s.Interfaces) != len(o.Interfaces)) {
+		return false
+	}
+
+	// Note: At the moment, the two lists must be in the same order
+	for i := 0; i < len(s.Interfaces); i++ {
+		if !s.Interfaces[i].Equal(o.Interfaces[i]) {
+			return false
+		}
+	}
+
+	return true
+
+}

+ 69 - 1
libnetwork/sandbox/sandbox_test.go

@@ -1,6 +1,9 @@
 package sandbox
 package sandbox
 
 
-import "testing"
+import (
+	"net"
+	"testing"
+)
 
 
 func TestSandboxCreate(t *testing.T) {
 func TestSandboxCreate(t *testing.T) {
 	key, err := newKey(t)
 	key, err := newKey(t)
@@ -19,3 +22,68 @@ func TestSandboxCreate(t *testing.T) {
 
 
 	verifySandbox(t, s)
 	verifySandbox(t, s)
 }
 }
+
+func TestInterfaceEqual(t *testing.T) {
+	list := getInterfaceList()
+
+	if !list[0].Equal(list[0]) {
+		t.Fatalf("Interface.Equal() returned false negative")
+	}
+
+	if list[0].Equal(list[1]) {
+		t.Fatalf("Interface.Equal() returned false positive")
+	}
+
+	if list[0].Equal(list[1]) != list[1].Equal(list[0]) {
+		t.Fatalf("Interface.Equal() failed commutative check")
+	}
+}
+
+func TestInterfaceCopy(t *testing.T) {
+	for _, iface := range getInterfaceList() {
+		cp := iface.GetCopy()
+
+		if !iface.Equal(cp) {
+			t.Fatalf("Failed to return a copy of Interface")
+		}
+
+		if iface == cp {
+			t.Fatalf("Failed to return a true copy of Interface")
+		}
+	}
+}
+
+func TestSandboxInfoCopy(t *testing.T) {
+	si := Info{Interfaces: getInterfaceList(), Gateway: net.ParseIP("192.168.1.254"), GatewayIPv6: net.ParseIP("2001:2345::abcd:8889")}
+	cp := si.GetCopy()
+
+	if !si.Equal(cp) {
+		t.Fatalf("Failed to return a copy of Info")
+	}
+
+	if &si == cp {
+		t.Fatalf("Failed to return a true copy of Info")
+	}
+}
+
+func getInterfaceList() []*Interface {
+	_, netv4a, _ := net.ParseCIDR("192.168.30.1/24")
+	_, netv4b, _ := net.ParseCIDR("172.18.255.2/23")
+	_, netv6a, _ := net.ParseCIDR("2001:2345::abcd:8888/80")
+	_, netv6b, _ := net.ParseCIDR("2001:2345::abcd:8889/80")
+
+	return []*Interface{
+		&Interface{
+			SrcName:     "veth1234567",
+			DstName:     "eth0",
+			Address:     netv4a,
+			AddressIPv6: netv6a,
+		},
+		&Interface{
+			SrcName:     "veth7654321",
+			DstName:     "eth1",
+			Address:     netv4b,
+			AddressIPv6: netv6b,
+		},
+	}
+}

+ 5 - 0
libnetwork/types/types.go

@@ -0,0 +1,5 @@
+// Package types contains types that are common across libnetwork project
+package types
+
+// UUID represents a globally unique ID of various resources like network and endpoint
+type UUID string