Selaa lähdekoodia

Fix networking issues in RHEL/Centos 6.6

Some parts of the bridge driver code needs to use a different kernel
api or use the already existing apis in slightly different ways to
make the bridge driver work in RHEL/Centos 6.6. This PR provides
those fixes.

Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
Jana Radhakrishnan 10 vuotta sitten
vanhempi
commit
15759edb38
1 muutettua tiedostoa jossa 31 lisäystä ja 11 poistoa
  1. 31 11
      libnetwork/drivers/bridge/bridge.go

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

@@ -2,12 +2,14 @@ package bridge
 
 
 import (
 import (
 	"errors"
 	"errors"
+	"fmt"
 	"net"
 	"net"
 	"os/exec"
 	"os/exec"
 	"strconv"
 	"strconv"
 	"sync"
 	"sync"
 
 
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
+	bri "github.com/docker/libcontainer/netlink"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/driverapi"
 	"github.com/docker/libnetwork/ipallocator"
 	"github.com/docker/libnetwork/ipallocator"
 	"github.com/docker/libnetwork/iptables"
 	"github.com/docker/libnetwork/iptables"
@@ -754,6 +756,20 @@ func (d *driver) DeleteNetwork(nid types.UUID) error {
 	return err
 	return err
 }
 }
 
 
+func addToBridge(ifaceName, bridgeName string) error {
+	iface, err := net.InterfaceByName(ifaceName)
+	if err != nil {
+		return fmt.Errorf("could not find interface %s: %v", ifaceName, err)
+	}
+
+	master, err := net.InterfaceByName(bridgeName)
+	if err != nil {
+		return fmt.Errorf("could not find bridge %s: %v", bridgeName, err)
+	}
+
+	return bri.AddToBridge(iface, master)
+}
+
 func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
 func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointInfo, epOptions map[string]interface{}) error {
 	var (
 	var (
 		ipv6Addr *net.IPNet
 		ipv6Addr *net.IPNet
@@ -821,27 +837,27 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}()
 	}()
 
 
 	// Generate a name for what will be the host side pipe interface
 	// Generate a name for what will be the host side pipe interface
-	name1, err := netutils.GenerateIfaceName(vethPrefix, vethLen)
+	hostIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	// Generate a name for what will be the sandbox side pipe interface
 	// Generate a name for what will be the sandbox side pipe interface
-	name2, err := netutils.GenerateIfaceName(vethPrefix, vethLen)
+	containerIfName, err := netutils.GenerateIfaceName(vethPrefix, vethLen)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	// Generate and add the interface pipe host <-> sandbox
 	// Generate and add the interface pipe host <-> sandbox
 	veth := &netlink.Veth{
 	veth := &netlink.Veth{
-		LinkAttrs: netlink.LinkAttrs{Name: name1, TxQLen: 0},
-		PeerName:  name2}
+		LinkAttrs: netlink.LinkAttrs{Name: hostIfName, TxQLen: 0},
+		PeerName:  containerIfName}
 	if err = netlink.LinkAdd(veth); err != nil {
 	if err = netlink.LinkAdd(veth); err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	// Get the host side pipe interface handler
 	// Get the host side pipe interface handler
-	host, err := netlink.LinkByName(name1)
+	host, err := netlink.LinkByName(hostIfName)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -852,7 +868,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}()
 	}()
 
 
 	// Get the sandbox side pipe interface handler
 	// Get the sandbox side pipe interface handler
-	sbox, err := netlink.LinkByName(name2)
+	sbox, err := netlink.LinkByName(containerIfName)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -879,9 +895,8 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}
 	}
 
 
 	// Attach host side pipe interface into the bridge
 	// Attach host side pipe interface into the bridge
-	if err = netlink.LinkSetMaster(host,
-		&netlink.Bridge{LinkAttrs: netlink.LinkAttrs{Name: config.BridgeName}}); err != nil {
-		return err
+	if err = addToBridge(hostIfName, config.BridgeName); err != nil {
+		return fmt.Errorf("adding interface %s to bridge %s failed: %v", hostIfName, config.BridgeName, err)
 	}
 	}
 
 
 	if !config.EnableUserlandProxy {
 	if !config.EnableUserlandProxy {
@@ -898,11 +913,16 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}
 	}
 	ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
 	ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
 
 
+	// Down the interface before configuring mac address.
+	if err := netlink.LinkSetDown(sbox); err != nil {
+		return fmt.Errorf("could not set link down for container interface %s: %v", containerIfName, err)
+	}
+
 	// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
 	// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
 	mac := electMacAddress(epConfig, ip4)
 	mac := electMacAddress(epConfig, ip4)
 	err = netlink.LinkSetHardwareAddr(sbox, mac)
 	err = netlink.LinkSetHardwareAddr(sbox, mac)
 	if err != nil {
 	if err != nil {
-		return err
+		return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err)
 	}
 	}
 	endpoint.macAddress = mac
 	endpoint.macAddress = mac
 
 
@@ -934,7 +954,7 @@ func (d *driver) CreateEndpoint(nid, eid types.UUID, epInfo driverapi.EndpointIn
 	}
 	}
 
 
 	// Create the sandbox side pipe interface
 	// Create the sandbox side pipe interface
-	endpoint.srcName = name2
+	endpoint.srcName = containerIfName
 	endpoint.addr = ipv4Addr
 	endpoint.addr = ipv4Addr
 
 
 	if config.EnableIPv6 {
 	if config.EnableIPv6 {