Sfoglia il codice sorgente

Merge pull request #193 from mrjana/cnm

Modify driver Join api to only allow dst prefix
Madhu Venugopal 10 anni fa
parent
commit
9247a5bf68

+ 2 - 2
libnetwork/driverapi/driverapi.go

@@ -83,8 +83,8 @@ type InterfaceInfo interface {
 // InterfaceNameInfo provides a go interface for the drivers to assign names
 // to interfaces.
 type InterfaceNameInfo interface {
-	// SetNames method assigns the srcName and dstName for the interface.
-	SetNames(srcName, dstName string) error
+	// SetNames method assigns the srcName and dstPrefix for the interface.
+	SetNames(srcName, dstPrefix string) error
 
 	// ID returns the numerical id that was assigned to the interface by the driver
 	// CreateEndpoint.

+ 2 - 2
libnetwork/drivers/bridge/bridge.go

@@ -21,7 +21,7 @@ const (
 	networkType             = "bridge"
 	vethPrefix              = "veth"
 	vethLen                 = 7
-	containerVeth           = "eth0"
+	containerVethPrefix     = "eth"
 	maxAllocatePortAttempts = 10
 	ifaceID                 = 1
 )
@@ -545,7 +545,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	// Create the sandbox side pipe interface
 	intf := &sandbox.Interface{}
 	intf.SrcName = name2
-	intf.DstName = containerVeth
+	intf.DstName = containerVethPrefix
 	intf.Address = ipv4Addr
 
 	if config.EnableIPv6 {

+ 1 - 1
libnetwork/endpoint.go

@@ -291,7 +291,7 @@ func (ep *endpoint) Join(containerID string, options ...EndpointOption) (*Contai
 	for _, i := range ifaces {
 		iface := &sandbox.Interface{
 			SrcName: i.srcName,
-			DstName: i.dstName,
+			DstName: i.dstPrefix,
 			Address: &i.addr,
 		}
 		if i.addrv6.IP.To16() != nil {

+ 8 - 8
libnetwork/endpoint_info.go

@@ -40,12 +40,12 @@ type InterfaceInfo interface {
 }
 
 type endpointInterface struct {
-	id      int
-	mac     net.HardwareAddr
-	addr    net.IPNet
-	addrv6  net.IPNet
-	srcName string
-	dstName string
+	id        int
+	mac       net.HardwareAddr
+	addr      net.IPNet
+	addrv6    net.IPNet
+	srcName   string
+	dstPrefix string
 }
 
 type endpointJoinInfo struct {
@@ -130,9 +130,9 @@ func (i *endpointInterface) AddressIPv6() net.IPNet {
 	return (*types.GetIPNetCopy(&i.addrv6))
 }
 
-func (i *endpointInterface) SetNames(srcName string, dstName string) error {
+func (i *endpointInterface) SetNames(srcName string, dstPrefix string) error {
 	i.srcName = srcName
-	i.dstName = dstName
+	i.dstPrefix = dstPrefix
 	return nil
 }
 

+ 32 - 0
libnetwork/libnetwork_test.go

@@ -23,6 +23,7 @@ import (
 	"github.com/docker/libnetwork/netutils"
 	"github.com/docker/libnetwork/options"
 	"github.com/docker/libnetwork/types"
+	"github.com/vishvananda/netlink"
 	"github.com/vishvananda/netns"
 )
 
@@ -730,6 +731,35 @@ func TestNetworkQuery(t *testing.T) {
 
 const containerID = "valid_container"
 
+func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) {
+	origns, err := netns.Get()
+	if err != nil {
+		t.Fatalf("Could not get the current netns: %v", err)
+	}
+	defer origns.Close()
+
+	key := info.SandboxKey()
+	f, err := os.OpenFile(key, os.O_RDONLY, 0)
+	if err != nil {
+		t.Fatalf("Failed to open network namespace path %q: %v", key, err)
+	}
+	defer f.Close()
+
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
+	nsFD := f.Fd()
+	if err = netns.Set(netns.NsHandle(nsFD)); err != nil {
+		t.Fatalf("Setting to the namespace pointed to by the sandbox %s failed: %v", key, err)
+	}
+	defer netns.Set(origns)
+
+	_, err = netlink.LinkByName("eth0")
+	if err != nil {
+		t.Fatalf("Could not find the interface eth0 inside the sandbox: %v", err)
+	}
+}
+
 func TestEndpointJoin(t *testing.T) {
 	if !netutils.IsRunningInContainer() {
 		defer netutils.SetupTestNetNS(t)()
@@ -786,6 +816,8 @@ func TestEndpointJoin(t *testing.T) {
 	if info.SandboxKey() == "" {
 		t.Fatalf("Expected an non-empty sandbox key for a joined endpoint. Instead found a empty sandbox key")
 	}
+
+	checkSandbox(t, info)
 }
 
 func TestEndpointJoinInvalidContainerId(t *testing.T) {

+ 12 - 2
libnetwork/sandbox/namespace_linux.go

@@ -20,8 +20,10 @@ var once sync.Once
 // interface. It represents a linux network namespace, and moves an interface
 // into it when called on method AddInterface or sets the gateway etc.
 type networkNamespace struct {
-	path  string
-	sinfo *Info
+	path        string
+	sinfo       *Info
+	nextIfIndex int
+	sync.Mutex
 }
 
 func createBasePath() {
@@ -167,6 +169,11 @@ func (n *networkNamespace) RemoveInterface(i *Interface) error {
 }
 
 func (n *networkNamespace) AddInterface(i *Interface) error {
+	n.Lock()
+	i.DstName = fmt.Sprintf("%s%d", i.DstName, n.nextIfIndex)
+	n.nextIfIndex++
+	n.Unlock()
+
 	runtime.LockOSThread()
 	defer runtime.UnlockOSThread()
 
@@ -214,7 +221,10 @@ func (n *networkNamespace) AddInterface(i *Interface) error {
 		return err
 	}
 
+	n.Lock()
 	n.sinfo.Interfaces = append(n.sinfo.Interfaces, i)
+	n.Unlock()
+
 	return nil
 }
 

+ 6 - 2
libnetwork/sandbox/sandbox.go

@@ -20,7 +20,9 @@ type Sandbox interface {
 
 	// Add an existing Interface to this sandbox. The operation will rename
 	// from the Interface SrcName to DstName as it moves, and reconfigure the
-	// interface according to the specified settings.
+	// interface according to the specified settings. The caller is expected
+	// to only provide a prefix for DstName. The AddInterface api will auto-generate
+	// an appropriate suffix for the DstName to disambiguate.
 	AddInterface(*Interface) error
 
 	// Remove an interface from the sandbox by renamin to original name
@@ -62,7 +64,9 @@ type Interface struct {
 	SrcName string
 
 	// The name that will be assigned to the interface once moves inside a
-	// network namespace.
+	// network namespace. When the caller passes in a DstName, it is only
+	// expected to pass a prefix. The name will modified with an appropriately
+	// auto-generated suffix.
 	DstName string
 
 	// IPv4 address for the interface.

+ 45 - 11
libnetwork/sandbox/sandbox_linux_test.go

@@ -15,6 +15,8 @@ import (
 const (
 	vethName1     = "wierdlongname1"
 	vethName2     = "wierdlongname2"
+	vethName3     = "wierdlongname3"
+	vethName4     = "wierdlongname4"
 	sboxIfaceName = "containername"
 )
 
@@ -36,33 +38,59 @@ func newInfo(t *testing.T) (*Info, error) {
 	veth := &netlink.Veth{
 		LinkAttrs: netlink.LinkAttrs{Name: vethName1, TxQLen: 0},
 		PeerName:  vethName2}
-	err := netlink.LinkAdd(veth)
-	if err != nil {
+	if err := netlink.LinkAdd(veth); err != nil {
 		return nil, err
 	}
 
 	// Store the sandbox side pipe interface
 	// This is needed for cleanup on DeleteEndpoint()
-	intf := &Interface{}
-	intf.SrcName = vethName2
-	intf.DstName = sboxIfaceName
+	intf1 := &Interface{}
+	intf1.SrcName = vethName2
+	intf1.DstName = sboxIfaceName
 
 	ip4, addr, err := net.ParseCIDR("192.168.1.100/24")
 	if err != nil {
 		return nil, err
 	}
-	intf.Address = addr
-	intf.Address.IP = ip4
+	intf1.Address = addr
+	intf1.Address.IP = ip4
 
 	// ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
 	ip6, addrv6, err := net.ParseCIDR("fe80::2/64")
 	if err != nil {
 		return nil, err
 	}
-	intf.AddressIPv6 = addrv6
-	intf.AddressIPv6.IP = ip6
+	intf1.AddressIPv6 = addrv6
+	intf1.AddressIPv6.IP = ip6
+
+	veth = &netlink.Veth{
+		LinkAttrs: netlink.LinkAttrs{Name: vethName3, TxQLen: 0},
+		PeerName:  vethName4}
+
+	if err := netlink.LinkAdd(veth); err != nil {
+		return nil, err
+	}
+
+	intf2 := &Interface{}
+	intf2.SrcName = vethName4
+	intf2.DstName = sboxIfaceName
+
+	ip4, addr, err = net.ParseCIDR("192.168.2.100/24")
+	if err != nil {
+		return nil, err
+	}
+	intf2.Address = addr
+	intf2.Address.IP = ip4
 
-	sinfo := &Info{Interfaces: []*Interface{intf}}
+	// ip6, addrv6, err := net.ParseCIDR("2001:DB8::ABCD/48")
+	ip6, addrv6, err = net.ParseCIDR("fe80::3/64")
+	if err != nil {
+		return nil, err
+	}
+	intf2.AddressIPv6 = addrv6
+	intf2.AddressIPv6.IP = ip6
+
+	sinfo := &Info{Interfaces: []*Interface{intf1, intf2}}
 	sinfo.Gateway = net.ParseIP("192.168.1.1")
 	// sinfo.GatewayIPv6 = net.ParseIP("2001:DB8::1")
 	sinfo.GatewayIPv6 = net.ParseIP("fe80::1")
@@ -97,7 +125,13 @@ func verifySandbox(t *testing.T, s Sandbox) {
 	}
 	defer netns.Set(origns)
 
-	_, err = netlink.LinkByName(sboxIfaceName)
+	_, err = netlink.LinkByName(sboxIfaceName + "0")
+	if err != nil {
+		t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName,
+			err)
+	}
+
+	_, err = netlink.LinkByName(sboxIfaceName + "1")
 	if err != nil {
 		t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName,
 			err)