From 76a8cbba1174c97806387767e797be331d25f5d7 Mon Sep 17 00:00:00 2001 From: Arnaud Porterie Date: Sun, 22 Feb 2015 17:24:22 -0800 Subject: [PATCH 1/6] WIP - Bridge refactoring Signed-off-by: Arnaud Porterie --- libnetwork/bridge/bridge.go | 253 +++++++++++++++++++++++++++++- libnetwork/bridge/interface.go | 23 +++ libnetwork/bridge/setup.go | 51 ++++++ libnetwork/bridge/setup_device.go | 54 +++++++ libnetwork/bridge/setup_ipv4.go | 67 ++++++++ libnetwork/bridge/utils.go | 73 +++++++++ libnetwork/namespace.go | 1 + 7 files changed, 514 insertions(+), 8 deletions(-) create mode 100644 libnetwork/bridge/interface.go create mode 100644 libnetwork/bridge/setup.go create mode 100644 libnetwork/bridge/setup_device.go create mode 100644 libnetwork/bridge/setup_ipv4.go create mode 100644 libnetwork/bridge/utils.go diff --git a/libnetwork/bridge/bridge.go b/libnetwork/bridge/bridge.go index 16fbe9a4d0..5f47458cf1 100644 --- a/libnetwork/bridge/bridge.go +++ b/libnetwork/bridge/bridge.go @@ -6,26 +6,263 @@ import ( "github.com/docker/libnetwork" ) -const networkType = "bridgednetwork" +const ( + NetworkType = "simplebridge" + VethPrefix = "veth" +) -type bridgeConfiguration struct { - Subnet net.IPNet +type Configuration struct { + BridgeName string + AddressIPv4 *net.IPNet + AddressIPv6 *net.IPNet + FixedCIDR string + FixedCIDRv6 string + EnableIPv6 bool + EnableIPTables bool + EnableIPForwarding bool } func init() { - libnetwork.RegisterNetworkType(networkType, Create, &bridgeConfiguration{}) + libnetwork.RegisterNetworkType(NetworkType, Create, &Configuration{}) } -func Create(config *bridgeConfiguration) (libnetwork.Network, error) { - return &bridgeNetwork{Config: *config}, nil +/* + +func Create() + +- NewBridgeInterface(*Configuration) (*BridgeInterface, error) + . Issues LinkByName on config.BridgeName +- Create BridgeSetup instance with sequence of steps +- if !bridgeInterface.Exists() + . Add DeviceCreation (error if non-default name) + . Add AddressIPv4: set IPv4 (with automatic election if necessary) +- General case + . Add option EnableIPv6 if no IPv6 on bridge (disable_ipv6=0 + set IPv6) + . Verify configured addresses (with v4 and v6 updated in config) + . Add FixedCIDR v4: register subnet on IP Allocator + . Add FixedCIDR v6: register subnet on IP Allocator, route +- Add IPTables setup +- Add IPForward setup (depends on FixedCIDRv6) +- err := bridgeSetup.Apply() + +*/ + +func Create(config *Configuration) (libnetwork.Network, error) { + bridgeIntfc := NewInterface(config) + bridgeSetup := NewBridgeSetup(bridgeIntfc) + + // If the bridge interface doesn't exist, we need to start the setup steps + // by creating a new device and assigning it an IPv4 address. + bridgeAlreadyExists := bridgeIntfc.Exists() + if !bridgeAlreadyExists { + bridgeSetup.QueueStep(SetupDevice) + bridgeSetup.QueueStep(SetupBridgeIPv4) + } + + // Conditionnally queue setup steps depending on configuration values. + optSteps := []struct { + Condition bool + Fn SetupStep + }{ + // Enable IPv6 on the bridge if required. We do this even for a + // previously existing bridge, as it may be here from a previous + // installation where IPv6 wasn't supported yet and needs to be + // assigned an IPv6 link-local address. + {config.EnableIPv6, SetupBridgeIPv6}, + + // We ensure that the bridge has the expectedIPv4 and IPv6 addresses in + // the case of a previously existing device. + {bridgeAlreadyExists, SetupVerifyConfiguredAddresses}, + + // Setup the bridge to allocate containers IPv4 addresses in the + // specified subnet. + {config.FixedCIDR != "", SetupFixedCIDRv4}, + + // Setup the bridge to allocate containers global IPv6 addresses in the + // specified subnet. + {config.FixedCIDRv6 != "", SetupFixedCIDRv6}, + + // Setup IPTables. + {config.EnableIPTables, SetupIPTables}, + + // Setup IP forwarding. + {config.EnableIPForwarding, SetupIPForwarding}, + } + + for _, step := range optSteps { + if step.Condition { + bridgeSetup.QueueStep(step.Fn) + } + } + + // Apply the prepared list of steps, and abort at the first error. + bridgeSetup.QueueStep(SetupDeviceUp) + if err := bridgeSetup.Apply(); err != nil { + return nil, err + } + + return &bridgeNetwork{*config}, nil } +/* +func Create(config *Configuration) (libnetwork.Network, error) { + var ( + addrv4 netlink.Addr + addrsv6 []netlink.Addr + ) + + b := &bridgeNetwork{Config: *config} + if b.Config.BridgeName == "" { + b.Config.BridgeName = DefaultBridge + } + + link, err := netlink.LinkByName(b.Config.BridgeName) + if err != nil { + // The bridge interface doesn't exist, but we only attempt to create it + // if using the default name. + if b.Config.BridgeName != DefaultBridge { + return nil, err + } + + // Create the bridge interface. + if addrv4, addrsv6, err = createBridge(&b.Config); err != nil { + return nil, err + } + } else { + // The bridge interface exists: start by getting its configured + // addresses and verify if it matches the requested configuration. + addrv4, addrsv6, err = getInterfaceAddr(link) + if err != nil { + return nil, err + } + + if b.Config.AddressIPv4 != "" { + bridgeIP, _, err := net.ParseCIDR(b.Config.AddressIPv4) + if err != nil { + return nil, err + } + if !addrv4.IP.Equal(bridgeIP) { + return nil, fmt.Errorf("Bridge IP %s does not match requested configuration %s", addrv4.IP, bridgeIP) + } + } + + // A bridge might exist but not have any IPv6 addr associated with it + // yet (for example, an existing Docker installation that has only been + // used with IPv4 and docker0 already is set up). In that case, we can + // perform the bridge init for IPv6 here, else we will error out below + // if --ipv6=true. + if len(addrsv6) == 0 && config.EnableIPv6 { + if err := setupIPv6Bridge(iface, config); err != nil { + return nil, err + } + } + } + + return b, nil +} +*/ + +/* +func createBridge(config *Configuration) (netlink.Addr, []netlink.Addr, error) { + // Formats an error return with default values. + fmtError := func(format string, params ...interface{}) (netlink.Addr, []netlink.Addr, error) { + return netlink.Addr{}, nil, fmt.Errorf(format, params...) + } + + // Elect a subnet for the bridge interface. + bridgeIPNet, err := electBridgeNetwork(config) + if err != nil { + return fmtError("Failed to elect bridge network: %v", err) + } + log.Debugf("Creating bridge interface %q with network %s", config.BridgeName, bridgeIPNet) + + // We attempt to create the bridge, and ignore the returned error if it is + // already existing. + iface, err := createBridgeInterface(config.BridgeName) + if err != nil && !os.IsExist(err) { + return netlink.Addr{}, nil, err + } + + // Configure bridge IPv4. + if err := netlink.AddrAdd(iface, &netlink.Addr{bridgeIPNet, ""}); err != nil { + return fmtError("Failed to add address %s to bridge: %v", bridgeIPNet, err) + } + + // Configure bridge IPv6. + if config.EnableIPv6 { + if err := setupIPv6Bridge(iface, config); err != nil { + return fmtError("Failed to setup bridge IPv6: %v", err) + } + } + + // Up the bridge interface. + if err := netlink.LinkSetUp(iface); err != nil { + return fmtError("Failed to up network bridge: %v", err) + } + + if config.FixedCIDRv6 != "" { + dest, network, err := net.ParseCIDR(config.FixedCIDRv6) + if err != nil { + return fmtError("Invalid bridge fixed CIDR IPv6 %q: %v", config.FixedCIDRv6, err) + } + + // Set route to global IPv6 subnet + log.Infof("Adding route to IPv6 network %q via device %q", dest, iface) + if err := netlink.RouteAdd(&netlink.Route{Dst: network, LinkIndex: iface.Attrs().Index}); err != nil { + return fmtError("Could not add route to IPv6 network %q via device %q", config.FixedCIDRv6, iface) + } + } + + return getInterfaceAddrByName(config.BridgeName) +} + +func checkBridgeConfig(iface netlink.Link, config *Configuration) (netlink.Addr, []netlink.Addr, error) { + addrv4, addrsv6, err := getInterfaceAddr(iface) + if err != nil { + return netlink.Addr{}, nil, err + } + + // If config dictates a specific IP for the bridge, we have to check if it + // corresponds to reality. + if config.AddressIPv4 != "" { + bridgeIP, _, err := net.ParseCIDR(config.AddressIPv4) + if err != nil { + return netlink.Addr{}, nil, err + } + if !addrv4.IP.Equal(bridgeIP) { + return netlink.Addr{}, nil, fmt.Errorf("bridge ip (%s) does not match existing configuration %s", addrv4.IP, bridgeIP) + } + } + + return addrv4, addrsv6, nil +} + +func setupIPv6Bridge(iface netlink.Link, config *Configuration) error { + procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6" + if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil { + return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err) + } + + ip, net, err := net.ParseCIDR(config.AddressIPv6) + if err != nil { + return fmt.Errorf("Invalid bridge IPv6 address %q: %v", config.AddressIPv6, err) + } + + net.IP = ip + if err := netlink.AddrAdd(iface, &netlink.Addr{net, ""}); err != nil { + return fmt.Errorf("Failed to add address %s to bridge: %v", net, err) + } + + return nil +} +*/ + type bridgeNetwork struct { - Config bridgeConfiguration + Config Configuration } func (b *bridgeNetwork) Type() string { - return networkType + return NetworkType } func (b *bridgeNetwork) Link(name string) ([]*libnetwork.Interface, error) { diff --git a/libnetwork/bridge/interface.go b/libnetwork/bridge/interface.go new file mode 100644 index 0000000000..7e6ba7fc91 --- /dev/null +++ b/libnetwork/bridge/interface.go @@ -0,0 +1,23 @@ +package bridge + +import "github.com/vishvananda/netlink" + +type Interface struct { + Config *Configuration + Link netlink.Link +} + +func NewInterface(config *Configuration) *Interface { + i := &Interface{ + Config: config, + } + + // Attempt to find an existing bridge named with the specified name. + i.Link, _ = netlink.LinkByName(i.Config.BridgeName) + return i +} + +// Exists indicates if the existing bridge interface exists on the system. +func (i *Interface) Exists() bool { + return i.Link != nil +} diff --git a/libnetwork/bridge/setup.go b/libnetwork/bridge/setup.go new file mode 100644 index 0000000000..ae05b54bdc --- /dev/null +++ b/libnetwork/bridge/setup.go @@ -0,0 +1,51 @@ +package bridge + +type SetupStep func(*Interface) error + +type BridgeSetup struct { + bridge *Interface + steps []SetupStep +} + +func NewBridgeSetup(b *Interface) *BridgeSetup { + return &BridgeSetup{bridge: b} +} + +func (b *BridgeSetup) Apply() error { + for _, fn := range b.steps { + if err := fn(b.bridge); err != nil { + return err + } + } + return nil +} + +func (b *BridgeSetup) QueueStep(step SetupStep) { + b.steps = append(b.steps, step) +} + +//---------------------------------------------------------------------------// + +func SetupBridgeIPv6(b *Interface) error { + return nil +} + +func SetupVerifyConfiguredAddresses(b *Interface) error { + return nil +} + +func SetupFixedCIDRv4(b *Interface) error { + return nil +} + +func SetupFixedCIDRv6(b *Interface) error { + return nil +} + +func SetupIPTables(b *Interface) error { + return nil +} + +func SetupIPForwarding(b *Interface) error { + return nil +} diff --git a/libnetwork/bridge/setup_device.go b/libnetwork/bridge/setup_device.go new file mode 100644 index 0000000000..9b06f2386f --- /dev/null +++ b/libnetwork/bridge/setup_device.go @@ -0,0 +1,54 @@ +package bridge + +import ( + "fmt" + "math/rand" + "net" + + log "github.com/Sirupsen/logrus" + "github.com/docker/docker/pkg/parsers/kernel" + "github.com/vishvananda/netlink" +) + +const ( + DefaultBridgeName = "docker0" +) + +func SetupDevice(b *Interface) error { + // We only attempt to create the bridge when the requested device name is + // the default one. + if b.Config.BridgeName != DefaultBridgeName { + return fmt.Errorf("bridge device with non default name %q must be created manually", b.Config.BridgeName) + } + + // Set the Interface netlink.Bridge. + b.Link = &netlink.Bridge{ + LinkAttrs: netlink.LinkAttrs{ + Name: b.Config.BridgeName, + }, + } + + // Only set the bridge's MAC address if the kernel version is > 3.3, as it + // was not supported before that. + kv, err := kernel.GetKernelVersion() + if err == nil && (kv.Kernel >= 3 && kv.Major >= 3) { + b.Link.Attrs().HardwareAddr = generateRandomMAC() + log.Debugf("Setting bridge mac address to %s", b.Link.Attrs().HardwareAddr) + } + + return netlink.LinkAdd(b.Link) +} + +func SetupDeviceUp(b *Interface) error { + return netlink.LinkSetUp(b.Link) +} + +func generateRandomMAC() net.HardwareAddr { + hw := make(net.HardwareAddr, 6) + for i := 0; i < 6; i++ { + hw[i] = byte(rand.Intn(255)) + } + hw[0] &^= 0x1 // clear multicast bit + hw[0] |= 0x2 // set local assignment bit (IEEE802) + return hw +} diff --git a/libnetwork/bridge/setup_ipv4.go b/libnetwork/bridge/setup_ipv4.go new file mode 100644 index 0000000000..fd86604110 --- /dev/null +++ b/libnetwork/bridge/setup_ipv4.go @@ -0,0 +1,67 @@ +package bridge + +import ( + "fmt" + "net" + + log "github.com/Sirupsen/logrus" + "github.com/vishvananda/netlink" +) + +var bridgeNetworks []*net.IPNet + +func init() { + // Here we don't follow the convention of using the 1st IP of the range for the gateway. + // This is to use the same gateway IPs as the /24 ranges, which predate the /16 ranges. + // In theory this shouldn't matter - in practice there's bound to be a few scripts relying + // on the internal addressing or other stupid things like that. + // They shouldn't, but hey, let's not break them unless we really have to. + for _, addr := range []string{ + "172.17.42.1/16", // Don't use 172.16.0.0/16, it conflicts with EC2 DNS 172.16.0.23 + "10.0.42.1/16", // Don't even try using the entire /8, that's too intrusive + "10.1.42.1/16", + "10.42.42.1/16", + "172.16.42.1/24", + "172.16.43.1/24", + "172.16.44.1/24", + "10.0.42.1/24", + "10.0.43.1/24", + "192.168.42.1/24", + "192.168.43.1/24", + "192.168.44.1/24", + } { + ip, net, err := net.ParseCIDR(addr) + if err != nil { + log.Errorf("Failed to parse address %s", addr) + continue + } + net.IP = ip + bridgeNetworks = append(bridgeNetworks, net) + } +} + +func SetupBridgeIPv4(b *Interface) error { + bridgeIPv4, err := electBridgeIPv4(b.Config) + if err != nil { + return err + } + + log.Debugf("Creating bridge interface %q with network %s", b.Config.BridgeName, bridgeIPv4) + return netlink.AddrAdd(b.Link, &netlink.Addr{bridgeIPv4, ""}) +} + +func electBridgeIPv4(config *Configuration) (*net.IPNet, error) { + // Use the requested IPv4 IP and mark when available. + if config.AddressIPv4 != nil { + return config.AddressIPv4, nil + } + + // Try to automatically elect appropriate brige IPv4 settings. + for _, n := range bridgeNetworks { + // TODO CheckNameserverOverlaps + // TODO CheckRouteOverlaps + return n, nil + } + + return nil, fmt.Errorf("Couldn't find an address range for interface %q", config.BridgeName) +} diff --git a/libnetwork/bridge/utils.go b/libnetwork/bridge/utils.go new file mode 100644 index 0000000000..a4e6a11b96 --- /dev/null +++ b/libnetwork/bridge/utils.go @@ -0,0 +1,73 @@ +package bridge + +import "github.com/vishvananda/netlink" + +/* +func electBridgeNetwork(config *Configuration) (*net.IPNet, error) { + // Is a bridge IP is provided as part of the configuration, we only check + // its validity. + if config.AddressIPv4 != "" { + ip, network, err := net.ParseCIDR(config.AddressIPv4) + if err != nil { + return nil, err + } + network.IP = ip + return network, nil + } + + // No bridge IP was specified: we have to elect one ourselves from a set of + // predetermined networks. + for _, n := range bridgeNetworks { + // TODO CheckNameserverOverlaps + // TODO CheckRouteOverlaps + return n, nil + } + + return nil, fmt.Errorf("Couldn't find an address range for interface %q", config.BridgeName) +} + +func createBridgeInterface(name string) (netlink.Link, error) { + link := &netlink.Bridge{ + LinkAttrs: netlink.LinkAttrs{ + Name: name, + }, + } + + // Only set the bridge's MAC address if the kernel version is > 3.3, as it + // was not supported before that. + kv, err := kernel.GetKernelVersion() + if err == nil && (kv.Kernel >= 3 && kv.Major >= 3) { + link.Attrs().HardwareAddr = generateRandomMAC() + log.Debugf("Setting bridge mac address to %s", link.Attrs().HardwareAddr) + } + + if err := netlink.LinkAdd(link); err != nil { + return nil, err + } + return netlink.LinkByName(name) +} +*/ + +func getInterfaceAddr(iface netlink.Link) (netlink.Addr, []netlink.Addr, error) { + v4addr, err := netlink.AddrList(iface, netlink.FAMILY_V4) + if err != nil { + return netlink.Addr{}, nil, err + } + + v6addr, err := netlink.AddrList(iface, netlink.FAMILY_V6) + if err != nil { + return netlink.Addr{}, nil, err + } + + // We only return the first IPv4 address, and the complete slice of IPv6 + // addresses. + return v4addr[0], v6addr, nil +} + +func getInterfaceAddrByName(ifaceName string) (netlink.Addr, []netlink.Addr, error) { + iface, err := netlink.LinkByName(ifaceName) + if err != nil { + return netlink.Addr{}, nil, err + } + return getInterfaceAddr(iface) +} diff --git a/libnetwork/namespace.go b/libnetwork/namespace.go index 99607a090c..c09c3505e3 100644 --- a/libnetwork/namespace.go +++ b/libnetwork/namespace.go @@ -14,6 +14,7 @@ func NewNamespace(path string) (Namespace, error) { } func (n *networkNamespace) AddInterface(i *Interface) error { + // TODO Open pipe, pass fd to child and write serialized Interface on it. if err := reexec(reexecMoveInterface, i.SrcName, i.DstName); err != nil { return err } From 1f3b1febc7e30d0087e73374fe85dfcfffcfd636 Mon Sep 17 00:00:00 2001 From: Arnaud Porterie Date: Sun, 22 Feb 2015 17:58:52 -0800 Subject: [PATCH 2/6] WIP - Bridge refactoring Signed-off-by: Arnaud Porterie --- libnetwork/bridge/bridge.go | 7 ++--- libnetwork/bridge/interface.go | 9 ++++++ libnetwork/bridge/setup.go | 8 ------ libnetwork/bridge/setup_device.go | 24 +++++++--------- libnetwork/bridge/setup_ipv4.go | 8 +++--- libnetwork/bridge/setup_ipv6.go | 32 +++++++++++++++++++++ libnetwork/bridge/setup_verify.go | 46 +++++++++++++++++++++++++++++++ libnetwork/bridge/utils.go | 26 ----------------- libnetwork/cmd/test/main.go | 4 +-- libnetwork/pkg/options/options.go | 4 +-- 10 files changed, 107 insertions(+), 61 deletions(-) create mode 100644 libnetwork/bridge/setup_ipv6.go create mode 100644 libnetwork/bridge/setup_verify.go diff --git a/libnetwork/bridge/bridge.go b/libnetwork/bridge/bridge.go index 5f47458cf1..3599735988 100644 --- a/libnetwork/bridge/bridge.go +++ b/libnetwork/bridge/bridge.go @@ -14,7 +14,6 @@ const ( type Configuration struct { BridgeName string AddressIPv4 *net.IPNet - AddressIPv6 *net.IPNet FixedCIDR string FixedCIDRv6 string EnableIPv6 bool @@ -60,7 +59,7 @@ func Create(config *Configuration) (libnetwork.Network, error) { } // Conditionnally queue setup steps depending on configuration values. - optSteps := []struct { + for _, step := range []struct { Condition bool Fn SetupStep }{ @@ -87,9 +86,7 @@ func Create(config *Configuration) (libnetwork.Network, error) { // Setup IP forwarding. {config.EnableIPForwarding, SetupIPForwarding}, - } - - for _, step := range optSteps { + } { if step.Condition { bridgeSetup.QueueStep(step.Fn) } diff --git a/libnetwork/bridge/interface.go b/libnetwork/bridge/interface.go index 7e6ba7fc91..cd336367ba 100644 --- a/libnetwork/bridge/interface.go +++ b/libnetwork/bridge/interface.go @@ -2,6 +2,10 @@ package bridge import "github.com/vishvananda/netlink" +const ( + DefaultBridgeName = "docker0" +) + type Interface struct { Config *Configuration Link netlink.Link @@ -12,6 +16,11 @@ func NewInterface(config *Configuration) *Interface { Config: config, } + // Initialize the bridge name to the default if unspecified. + if i.Config.BridgeName == "" { + i.Config.BridgeName = DefaultBridgeName + } + // Attempt to find an existing bridge named with the specified name. i.Link, _ = netlink.LinkByName(i.Config.BridgeName) return i diff --git a/libnetwork/bridge/setup.go b/libnetwork/bridge/setup.go index ae05b54bdc..3ba81106a3 100644 --- a/libnetwork/bridge/setup.go +++ b/libnetwork/bridge/setup.go @@ -26,14 +26,6 @@ func (b *BridgeSetup) QueueStep(step SetupStep) { //---------------------------------------------------------------------------// -func SetupBridgeIPv6(b *Interface) error { - return nil -} - -func SetupVerifyConfiguredAddresses(b *Interface) error { - return nil -} - func SetupFixedCIDRv4(b *Interface) error { return nil } diff --git a/libnetwork/bridge/setup_device.go b/libnetwork/bridge/setup_device.go index 9b06f2386f..8256f1fbbf 100644 --- a/libnetwork/bridge/setup_device.go +++ b/libnetwork/bridge/setup_device.go @@ -10,21 +10,17 @@ import ( "github.com/vishvananda/netlink" ) -const ( - DefaultBridgeName = "docker0" -) - -func SetupDevice(b *Interface) error { +func SetupDevice(i *Interface) error { // We only attempt to create the bridge when the requested device name is // the default one. - if b.Config.BridgeName != DefaultBridgeName { - return fmt.Errorf("bridge device with non default name %q must be created manually", b.Config.BridgeName) + if i.Config.BridgeName != DefaultBridgeName { + return fmt.Errorf("bridge device with non default name %q must be created manually", i.Config.BridgeName) } // Set the Interface netlink.Bridge. - b.Link = &netlink.Bridge{ + i.Link = &netlink.Bridge{ LinkAttrs: netlink.LinkAttrs{ - Name: b.Config.BridgeName, + Name: i.Config.BridgeName, }, } @@ -32,15 +28,15 @@ func SetupDevice(b *Interface) error { // was not supported before that. kv, err := kernel.GetKernelVersion() if err == nil && (kv.Kernel >= 3 && kv.Major >= 3) { - b.Link.Attrs().HardwareAddr = generateRandomMAC() - log.Debugf("Setting bridge mac address to %s", b.Link.Attrs().HardwareAddr) + i.Link.Attrs().HardwareAddr = generateRandomMAC() + log.Debugf("Setting bridge mac address to %s", i.Link.Attrs().HardwareAddr) } - return netlink.LinkAdd(b.Link) + return netlink.LinkAdd(i.Link) } -func SetupDeviceUp(b *Interface) error { - return netlink.LinkSetUp(b.Link) +func SetupDeviceUp(i *Interface) error { + return netlink.LinkSetUp(i.Link) } func generateRandomMAC() net.HardwareAddr { diff --git a/libnetwork/bridge/setup_ipv4.go b/libnetwork/bridge/setup_ipv4.go index fd86604110..5c4bb748f2 100644 --- a/libnetwork/bridge/setup_ipv4.go +++ b/libnetwork/bridge/setup_ipv4.go @@ -40,14 +40,14 @@ func init() { } } -func SetupBridgeIPv4(b *Interface) error { - bridgeIPv4, err := electBridgeIPv4(b.Config) +func SetupBridgeIPv4(i *Interface) error { + bridgeIPv4, err := electBridgeIPv4(i.Config) if err != nil { return err } - log.Debugf("Creating bridge interface %q with network %s", b.Config.BridgeName, bridgeIPv4) - return netlink.AddrAdd(b.Link, &netlink.Addr{bridgeIPv4, ""}) + log.Debugf("Creating bridge interface %q with network %s", i.Config.BridgeName, bridgeIPv4) + return netlink.AddrAdd(i.Link, &netlink.Addr{bridgeIPv4, ""}) } func electBridgeIPv4(config *Configuration) (*net.IPNet, error) { diff --git a/libnetwork/bridge/setup_ipv6.go b/libnetwork/bridge/setup_ipv6.go new file mode 100644 index 0000000000..ac8642004f --- /dev/null +++ b/libnetwork/bridge/setup_ipv6.go @@ -0,0 +1,32 @@ +package bridge + +import ( + "fmt" + "io/ioutil" + "net" + + "github.com/vishvananda/netlink" +) + +var BridgeIPv6 *net.IPNet + +const BridgeIPv6Str = "fe80::1/64" + +func init() { + // We allow ourselves to panic in this special case because we indicate a + // failure to parse a compile-time define constant. + if ip, netw, err := net.ParseCIDR(BridgeIPv6Str); err == nil { + BridgeIPv6 = &net.IPNet{IP: ip, Mask: netw.Mask} + } else { + panic(fmt.Sprintf("Cannot parse default bridge IPv6 address %q: %v", BridgeIPv6Str, err)) + } +} + +func SetupBridgeIPv6(i *Interface) error { + // Enable IPv6 on the bridge + procFile := "/proc/sys/net/ipv6/conf/" + i.Config.BridgeName + "/disable_ipv6" + if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil { + return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err) + } + return netlink.AddrAdd(i.Link, &netlink.Addr{BridgeIPv6, ""}) +} diff --git a/libnetwork/bridge/setup_verify.go b/libnetwork/bridge/setup_verify.go new file mode 100644 index 0000000000..b825592ee5 --- /dev/null +++ b/libnetwork/bridge/setup_verify.go @@ -0,0 +1,46 @@ +package bridge + +import ( + "fmt" + + "github.com/vishvananda/netlink" +) + +func SetupVerifyConfiguredAddresses(i *Interface) error { + // Fetch a single IPv4 and a slice of IPv6 addresses from the bridge. + addrv4, addrsv6, err := getInterfaceAddresses(i.Link) + if err != nil { + return err + } + + // Verify that the bridge IPv4 address matches the requested configuration. + if i.Config.AddressIPv4 != nil && !addrv4.IP.Equal(i.Config.AddressIPv4.IP) { + return fmt.Errorf("Bridge IPv4 (%s) does not match requested configuration %s", addrv4.IP, i.Config.AddressIPv4.IP) + } + + // Verify that one of the bridge IPv6 addresses matches the requested + // configuration. + for _, addrv6 := range addrsv6 { + if addrv6.String() == BridgeIPv6.String() { + return nil + } + } + + return fmt.Errorf("Bridge IPv6 addresses do not match the expected bridge configuration %s", BridgeIPv6) +} + +func getInterfaceAddresses(iface netlink.Link) (netlink.Addr, []netlink.Addr, error) { + v4addr, err := netlink.AddrList(iface, netlink.FAMILY_V4) + if err != nil { + return netlink.Addr{}, nil, err + } + + v6addr, err := netlink.AddrList(iface, netlink.FAMILY_V6) + if err != nil { + return netlink.Addr{}, nil, err + } + + // We only return the first IPv4 address, and the complete slice of IPv6 + // addresses. + return v4addr[0], v6addr, nil +} diff --git a/libnetwork/bridge/utils.go b/libnetwork/bridge/utils.go index a4e6a11b96..b17dd63cf0 100644 --- a/libnetwork/bridge/utils.go +++ b/libnetwork/bridge/utils.go @@ -1,7 +1,5 @@ package bridge -import "github.com/vishvananda/netlink" - /* func electBridgeNetwork(config *Configuration) (*net.IPNet, error) { // Is a bridge IP is provided as part of the configuration, we only check @@ -47,27 +45,3 @@ func createBridgeInterface(name string) (netlink.Link, error) { return netlink.LinkByName(name) } */ - -func getInterfaceAddr(iface netlink.Link) (netlink.Addr, []netlink.Addr, error) { - v4addr, err := netlink.AddrList(iface, netlink.FAMILY_V4) - if err != nil { - return netlink.Addr{}, nil, err - } - - v6addr, err := netlink.AddrList(iface, netlink.FAMILY_V6) - if err != nil { - return netlink.Addr{}, nil, err - } - - // We only return the first IPv4 address, and the complete slice of IPv6 - // addresses. - return v4addr[0], v6addr, nil -} - -func getInterfaceAddrByName(ifaceName string) (netlink.Addr, []netlink.Addr, error) { - iface, err := netlink.LinkByName(ifaceName) - if err != nil { - return netlink.Addr{}, nil, err - } - return getInterfaceAddr(iface) -} diff --git a/libnetwork/cmd/test/main.go b/libnetwork/cmd/test/main.go index 151c2e7191..020e49e4b0 100644 --- a/libnetwork/cmd/test/main.go +++ b/libnetwork/cmd/test/main.go @@ -12,8 +12,8 @@ import ( func main() { _, net, _ := net.ParseCIDR("192.168.100.1/24") - options := libnetwork.DriverParams{"Subnet": *net} - netw, err := libnetwork.NewNetwork("bridgednetwork", options) + options := libnetwork.DriverParams{"AddressIPv4": net} + netw, err := libnetwork.NewNetwork("simplebridge", options) if err != nil { log.Fatal(err) } diff --git a/libnetwork/pkg/options/options.go b/libnetwork/pkg/options/options.go index d5bc063d0f..a128cde770 100644 --- a/libnetwork/pkg/options/options.go +++ b/libnetwork/pkg/options/options.go @@ -45,10 +45,10 @@ func GenerateFromModel(options Generic, model interface{}) (interface{}, error) for name, value := range options { field := res.Elem().FieldByName(name) if !field.IsValid() { - return nil, NoSuchFieldError{name, reflect.TypeOf(model).Name()} + return nil, NoSuchFieldError{name, resType.String()} } if !field.CanSet() { - return nil, CannotSetFieldError{name, reflect.TypeOf(model).Name()} + return nil, CannotSetFieldError{name, resType.String()} } field.Set(reflect.ValueOf(value)) } From 796d58af9e5ae2199993e70886c9df8026dd17c9 Mon Sep 17 00:00:00 2001 From: Arnaud Porterie Date: Sun, 22 Feb 2015 21:11:12 -0800 Subject: [PATCH 3/6] WIP - Bridge refactoring Signed-off-by: Arnaud Porterie --- libnetwork/bridge/bridge.go | 40 ----------------- libnetwork/bridge/setup.go | 12 ++--- libnetwork/bridge/setup_device.go | 3 ++ libnetwork/bridge/setup_ipv4.go | 75 +++++++++++++++++++++++++++++-- libnetwork/cmd/test/main.go | 3 +- 5 files changed, 83 insertions(+), 50 deletions(-) diff --git a/libnetwork/bridge/bridge.go b/libnetwork/bridge/bridge.go index 3599735988..a7c5215b76 100644 --- a/libnetwork/bridge/bridge.go +++ b/libnetwork/bridge/bridge.go @@ -212,46 +212,6 @@ func createBridge(config *Configuration) (netlink.Addr, []netlink.Addr, error) { return getInterfaceAddrByName(config.BridgeName) } - -func checkBridgeConfig(iface netlink.Link, config *Configuration) (netlink.Addr, []netlink.Addr, error) { - addrv4, addrsv6, err := getInterfaceAddr(iface) - if err != nil { - return netlink.Addr{}, nil, err - } - - // If config dictates a specific IP for the bridge, we have to check if it - // corresponds to reality. - if config.AddressIPv4 != "" { - bridgeIP, _, err := net.ParseCIDR(config.AddressIPv4) - if err != nil { - return netlink.Addr{}, nil, err - } - if !addrv4.IP.Equal(bridgeIP) { - return netlink.Addr{}, nil, fmt.Errorf("bridge ip (%s) does not match existing configuration %s", addrv4.IP, bridgeIP) - } - } - - return addrv4, addrsv6, nil -} - -func setupIPv6Bridge(iface netlink.Link, config *Configuration) error { - procFile := "/proc/sys/net/ipv6/conf/" + config.BridgeName + "/disable_ipv6" - if err := ioutil.WriteFile(procFile, []byte{'0', '\n'}, 0644); err != nil { - return fmt.Errorf("Unable to enable IPv6 addresses on bridge: %v", err) - } - - ip, net, err := net.ParseCIDR(config.AddressIPv6) - if err != nil { - return fmt.Errorf("Invalid bridge IPv6 address %q: %v", config.AddressIPv6, err) - } - - net.IP = ip - if err := netlink.AddrAdd(iface, &netlink.Addr{net, ""}); err != nil { - return fmt.Errorf("Failed to add address %s to bridge: %v", net, err) - } - - return nil -} */ type bridgeNetwork struct { diff --git a/libnetwork/bridge/setup.go b/libnetwork/bridge/setup.go index 3ba81106a3..2d17f7a7f2 100644 --- a/libnetwork/bridge/setup.go +++ b/libnetwork/bridge/setup.go @@ -7,8 +7,8 @@ type BridgeSetup struct { steps []SetupStep } -func NewBridgeSetup(b *Interface) *BridgeSetup { - return &BridgeSetup{bridge: b} +func NewBridgeSetup(i *Interface) *BridgeSetup { + return &BridgeSetup{bridge: i} } func (b *BridgeSetup) Apply() error { @@ -26,18 +26,18 @@ func (b *BridgeSetup) QueueStep(step SetupStep) { //---------------------------------------------------------------------------// -func SetupFixedCIDRv4(b *Interface) error { +func SetupFixedCIDRv4(i *Interface) error { return nil } -func SetupFixedCIDRv6(b *Interface) error { +func SetupFixedCIDRv6(i *Interface) error { return nil } -func SetupIPTables(b *Interface) error { +func SetupIPTables(i *Interface) error { return nil } -func SetupIPForwarding(b *Interface) error { +func SetupIPForwarding(i *Interface) error { return nil } diff --git a/libnetwork/bridge/setup_device.go b/libnetwork/bridge/setup_device.go index 8256f1fbbf..d2e285b77f 100644 --- a/libnetwork/bridge/setup_device.go +++ b/libnetwork/bridge/setup_device.go @@ -10,6 +10,7 @@ import ( "github.com/vishvananda/netlink" ) +// SetupDevice create a new bridge interface/ func SetupDevice(i *Interface) error { // We only attempt to create the bridge when the requested device name is // the default one. @@ -32,9 +33,11 @@ func SetupDevice(i *Interface) error { log.Debugf("Setting bridge mac address to %s", i.Link.Attrs().HardwareAddr) } + // Call out to netlink to create the device. return netlink.LinkAdd(i.Link) } +// SetupDeviceUp ups the given bridge interface. func SetupDeviceUp(i *Interface) error { return netlink.LinkSetUp(i.Link) } diff --git a/libnetwork/bridge/setup_ipv4.go b/libnetwork/bridge/setup_ipv4.go index 5c4bb748f2..974e7e2032 100644 --- a/libnetwork/bridge/setup_ipv4.go +++ b/libnetwork/bridge/setup_ipv4.go @@ -5,6 +5,7 @@ import ( "net" log "github.com/Sirupsen/logrus" + "github.com/docker/docker/pkg/networkfs/resolvconf" "github.com/vishvananda/netlink" ) @@ -56,12 +57,80 @@ func electBridgeIPv4(config *Configuration) (*net.IPNet, error) { return config.AddressIPv4, nil } + // We don't check for an error here, because we don't really care if we + // can't read /etc/resolv.conf. So instead we skip the append if resolvConf + // is nil. It either doesn't exist, or we can't read it for some reason. + nameservers := []string{} + if resolvConf, _ := resolvconf.Get(); resolvConf != nil { + nameservers = append(nameservers, resolvconf.GetNameserversAsCIDR(resolvConf)...) + } + // Try to automatically elect appropriate brige IPv4 settings. for _, n := range bridgeNetworks { - // TODO CheckNameserverOverlaps - // TODO CheckRouteOverlaps - return n, nil + if err := checkNameserverOverlaps(nameservers, n); err == nil { + if err := checkRouteOverlaps(n); err == nil { + return n, nil + } + } } return nil, fmt.Errorf("Couldn't find an address range for interface %q", config.BridgeName) } + +func checkNameserverOverlaps(nameservers []string, toCheck *net.IPNet) error { + for _, ns := range nameservers { + _, nsNetwork, err := net.ParseCIDR(ns) + if err != nil { + return err + } + if networkOverlaps(toCheck, nsNetwork) { + return fmt.Errorf("Requested network %s overlaps with name server") + } + } + return nil +} + +func checkRouteOverlaps(toCheck *net.IPNet) error { + networks, err := netlink.RouteList(nil, netlink.FAMILY_V4) + if err != nil { + return err + } + + for _, network := range networks { + // TODO Is that right? + if network.Dst != nil && networkOverlaps(toCheck, network.Dst) { + return fmt.Errorf("Requested network %s overlaps with an existing network") + } + } + return nil +} + +func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool { + if len(netX.IP) == len(netY.IP) { + if firstIP, _ := networkRange(netX); netY.Contains(firstIP) { + return true + } + if firstIP, _ := networkRange(netY); netX.Contains(firstIP) { + return true + } + } + return false +} + +func networkRange(network *net.IPNet) (net.IP, net.IP) { + var netIP net.IP + if network.IP.To4() != nil { + netIP = network.IP.To4() + } else if network.IP.To16() != nil { + netIP = network.IP.To16() + } else { + return nil, nil + } + + lastIP := make([]byte, len(netIP), len(netIP)) + + for i := 0; i < len(netIP); i++ { + lastIP[i] = netIP[i] | ^network.Mask[i] + } + return netIP.Mask(network.Mask), net.IP(lastIP) +} diff --git a/libnetwork/cmd/test/main.go b/libnetwork/cmd/test/main.go index 020e49e4b0..bb2d041068 100644 --- a/libnetwork/cmd/test/main.go +++ b/libnetwork/cmd/test/main.go @@ -10,7 +10,8 @@ import ( ) func main() { - _, net, _ := net.ParseCIDR("192.168.100.1/24") + ip, net, _ := net.ParseCIDR("192.168.100.1/24") + net.IP = ip options := libnetwork.DriverParams{"AddressIPv4": net} netw, err := libnetwork.NewNetwork("simplebridge", options) From 46864de1d7da8f8592dbb2cc6ae454cb036ac4ec Mon Sep 17 00:00:00 2001 From: Arnaud Porterie Date: Sun, 22 Feb 2015 21:32:48 -0800 Subject: [PATCH 4/6] WIP - Fixed CIDR v4 and v6 Signed-off-by: Arnaud Porterie --- libnetwork/bridge/bridge.go | 8 ++++---- libnetwork/bridge/interface.go | 16 ++++++++++++++++ libnetwork/bridge/setup.go | 8 -------- libnetwork/bridge/setup_fixedcidrv4.go | 16 ++++++++++++++++ libnetwork/bridge/setup_fixedcidrv6.go | 11 +++++++++++ libnetwork/bridge/setup_ipv4.go | 3 +-- libnetwork/bridge/setup_verify.go | 24 ++---------------------- 7 files changed, 50 insertions(+), 36 deletions(-) create mode 100644 libnetwork/bridge/setup_fixedcidrv4.go create mode 100644 libnetwork/bridge/setup_fixedcidrv6.go diff --git a/libnetwork/bridge/bridge.go b/libnetwork/bridge/bridge.go index a7c5215b76..ab3e2bd202 100644 --- a/libnetwork/bridge/bridge.go +++ b/libnetwork/bridge/bridge.go @@ -14,8 +14,8 @@ const ( type Configuration struct { BridgeName string AddressIPv4 *net.IPNet - FixedCIDR string - FixedCIDRv6 string + FixedCIDR *net.IPNet + FixedCIDRv6 *net.IPNet EnableIPv6 bool EnableIPTables bool EnableIPForwarding bool @@ -75,11 +75,11 @@ func Create(config *Configuration) (libnetwork.Network, error) { // Setup the bridge to allocate containers IPv4 addresses in the // specified subnet. - {config.FixedCIDR != "", SetupFixedCIDRv4}, + {config.FixedCIDR != nil, SetupFixedCIDRv4}, // Setup the bridge to allocate containers global IPv6 addresses in the // specified subnet. - {config.FixedCIDRv6 != "", SetupFixedCIDRv6}, + {config.FixedCIDRv6 != nil, SetupFixedCIDRv6}, // Setup IPTables. {config.EnableIPTables, SetupIPTables}, diff --git a/libnetwork/bridge/interface.go b/libnetwork/bridge/interface.go index cd336367ba..414f42ea9f 100644 --- a/libnetwork/bridge/interface.go +++ b/libnetwork/bridge/interface.go @@ -30,3 +30,19 @@ func NewInterface(config *Configuration) *Interface { func (i *Interface) Exists() bool { return i.Link != nil } + +// Addresses returns a single IPv4 address and all IPv6 addresses for the +// bridge interface. +func (i *Interface) Addresses() (netlink.Addr, []netlink.Addr, error) { + v4addr, err := netlink.AddrList(i.Link, netlink.FAMILY_V4) + if err != nil { + return netlink.Addr{}, nil, err + } + + v6addr, err := netlink.AddrList(i.Link, netlink.FAMILY_V6) + if err != nil { + return netlink.Addr{}, nil, err + } + + return v4addr[0], v6addr, nil +} diff --git a/libnetwork/bridge/setup.go b/libnetwork/bridge/setup.go index 2d17f7a7f2..c0cbbe98ae 100644 --- a/libnetwork/bridge/setup.go +++ b/libnetwork/bridge/setup.go @@ -26,14 +26,6 @@ func (b *BridgeSetup) QueueStep(step SetupStep) { //---------------------------------------------------------------------------// -func SetupFixedCIDRv4(i *Interface) error { - return nil -} - -func SetupFixedCIDRv6(i *Interface) error { - return nil -} - func SetupIPTables(i *Interface) error { return nil } diff --git a/libnetwork/bridge/setup_fixedcidrv4.go b/libnetwork/bridge/setup_fixedcidrv4.go new file mode 100644 index 0000000000..bf5dc2701a --- /dev/null +++ b/libnetwork/bridge/setup_fixedcidrv4.go @@ -0,0 +1,16 @@ +package bridge + +import ( + log "github.com/Sirupsen/logrus" + "github.com/docker/docker/daemon/networkdriver/ipallocator" +) + +func SetupFixedCIDRv4(i *Interface) error { + addrv4, _, err := i.Addresses() + if err != nil { + return err + } + + log.Debugf("Using IPv4 subnet: %v", i.Config.FixedCIDR) + return ipallocator.RegisterSubnet(addrv4.IPNet, i.Config.FixedCIDR) +} diff --git a/libnetwork/bridge/setup_fixedcidrv6.go b/libnetwork/bridge/setup_fixedcidrv6.go new file mode 100644 index 0000000000..bb15cf5880 --- /dev/null +++ b/libnetwork/bridge/setup_fixedcidrv6.go @@ -0,0 +1,11 @@ +package bridge + +import ( + log "github.com/Sirupsen/logrus" + "github.com/docker/docker/daemon/networkdriver/ipallocator" +) + +func SetupFixedCIDRv6(i *Interface) error { + log.Debugf("Using IPv6 subnet: %v", i.Config.FixedCIDRv6) + return ipallocator.RegisterSubnet(i.Config.FixedCIDRv6, i.Config.FixedCIDRv6) +} diff --git a/libnetwork/bridge/setup_ipv4.go b/libnetwork/bridge/setup_ipv4.go index 974e7e2032..8068eea748 100644 --- a/libnetwork/bridge/setup_ipv4.go +++ b/libnetwork/bridge/setup_ipv4.go @@ -52,7 +52,7 @@ func SetupBridgeIPv4(i *Interface) error { } func electBridgeIPv4(config *Configuration) (*net.IPNet, error) { - // Use the requested IPv4 IP and mark when available. + // Use the requested IPv4 CIDR when available. if config.AddressIPv4 != nil { return config.AddressIPv4, nil } @@ -128,7 +128,6 @@ func networkRange(network *net.IPNet) (net.IP, net.IP) { } lastIP := make([]byte, len(netIP), len(netIP)) - for i := 0; i < len(netIP); i++ { lastIP[i] = netIP[i] | ^network.Mask[i] } diff --git a/libnetwork/bridge/setup_verify.go b/libnetwork/bridge/setup_verify.go index b825592ee5..7baf8cf3e2 100644 --- a/libnetwork/bridge/setup_verify.go +++ b/libnetwork/bridge/setup_verify.go @@ -1,14 +1,10 @@ package bridge -import ( - "fmt" - - "github.com/vishvananda/netlink" -) +import "fmt" func SetupVerifyConfiguredAddresses(i *Interface) error { // Fetch a single IPv4 and a slice of IPv6 addresses from the bridge. - addrv4, addrsv6, err := getInterfaceAddresses(i.Link) + addrv4, addrsv6, err := i.Addresses() if err != nil { return err } @@ -28,19 +24,3 @@ func SetupVerifyConfiguredAddresses(i *Interface) error { return fmt.Errorf("Bridge IPv6 addresses do not match the expected bridge configuration %s", BridgeIPv6) } - -func getInterfaceAddresses(iface netlink.Link) (netlink.Addr, []netlink.Addr, error) { - v4addr, err := netlink.AddrList(iface, netlink.FAMILY_V4) - if err != nil { - return netlink.Addr{}, nil, err - } - - v6addr, err := netlink.AddrList(iface, netlink.FAMILY_V6) - if err != nil { - return netlink.Addr{}, nil, err - } - - // We only return the first IPv4 address, and the complete slice of IPv6 - // addresses. - return v4addr[0], v6addr, nil -} From 4a8b8498a71b1d7d83eb394978c6076c76a98bed Mon Sep 17 00:00:00 2001 From: Arnaud Porterie Date: Sun, 22 Feb 2015 21:36:25 -0800 Subject: [PATCH 5/6] WIP - Remove commented code Signed-off-by: Arnaud Porterie --- libnetwork/bridge/bridge.go | 134 ------------------------------------ 1 file changed, 134 deletions(-) diff --git a/libnetwork/bridge/bridge.go b/libnetwork/bridge/bridge.go index ab3e2bd202..0723829c71 100644 --- a/libnetwork/bridge/bridge.go +++ b/libnetwork/bridge/bridge.go @@ -25,27 +25,6 @@ func init() { libnetwork.RegisterNetworkType(NetworkType, Create, &Configuration{}) } -/* - -func Create() - -- NewBridgeInterface(*Configuration) (*BridgeInterface, error) - . Issues LinkByName on config.BridgeName -- Create BridgeSetup instance with sequence of steps -- if !bridgeInterface.Exists() - . Add DeviceCreation (error if non-default name) - . Add AddressIPv4: set IPv4 (with automatic election if necessary) -- General case - . Add option EnableIPv6 if no IPv6 on bridge (disable_ipv6=0 + set IPv6) - . Verify configured addresses (with v4 and v6 updated in config) - . Add FixedCIDR v4: register subnet on IP Allocator - . Add FixedCIDR v6: register subnet on IP Allocator, route -- Add IPTables setup -- Add IPForward setup (depends on FixedCIDRv6) -- err := bridgeSetup.Apply() - -*/ - func Create(config *Configuration) (libnetwork.Network, error) { bridgeIntfc := NewInterface(config) bridgeSetup := NewBridgeSetup(bridgeIntfc) @@ -101,119 +80,6 @@ func Create(config *Configuration) (libnetwork.Network, error) { return &bridgeNetwork{*config}, nil } -/* -func Create(config *Configuration) (libnetwork.Network, error) { - var ( - addrv4 netlink.Addr - addrsv6 []netlink.Addr - ) - - b := &bridgeNetwork{Config: *config} - if b.Config.BridgeName == "" { - b.Config.BridgeName = DefaultBridge - } - - link, err := netlink.LinkByName(b.Config.BridgeName) - if err != nil { - // The bridge interface doesn't exist, but we only attempt to create it - // if using the default name. - if b.Config.BridgeName != DefaultBridge { - return nil, err - } - - // Create the bridge interface. - if addrv4, addrsv6, err = createBridge(&b.Config); err != nil { - return nil, err - } - } else { - // The bridge interface exists: start by getting its configured - // addresses and verify if it matches the requested configuration. - addrv4, addrsv6, err = getInterfaceAddr(link) - if err != nil { - return nil, err - } - - if b.Config.AddressIPv4 != "" { - bridgeIP, _, err := net.ParseCIDR(b.Config.AddressIPv4) - if err != nil { - return nil, err - } - if !addrv4.IP.Equal(bridgeIP) { - return nil, fmt.Errorf("Bridge IP %s does not match requested configuration %s", addrv4.IP, bridgeIP) - } - } - - // A bridge might exist but not have any IPv6 addr associated with it - // yet (for example, an existing Docker installation that has only been - // used with IPv4 and docker0 already is set up). In that case, we can - // perform the bridge init for IPv6 here, else we will error out below - // if --ipv6=true. - if len(addrsv6) == 0 && config.EnableIPv6 { - if err := setupIPv6Bridge(iface, config); err != nil { - return nil, err - } - } - } - - return b, nil -} -*/ - -/* -func createBridge(config *Configuration) (netlink.Addr, []netlink.Addr, error) { - // Formats an error return with default values. - fmtError := func(format string, params ...interface{}) (netlink.Addr, []netlink.Addr, error) { - return netlink.Addr{}, nil, fmt.Errorf(format, params...) - } - - // Elect a subnet for the bridge interface. - bridgeIPNet, err := electBridgeNetwork(config) - if err != nil { - return fmtError("Failed to elect bridge network: %v", err) - } - log.Debugf("Creating bridge interface %q with network %s", config.BridgeName, bridgeIPNet) - - // We attempt to create the bridge, and ignore the returned error if it is - // already existing. - iface, err := createBridgeInterface(config.BridgeName) - if err != nil && !os.IsExist(err) { - return netlink.Addr{}, nil, err - } - - // Configure bridge IPv4. - if err := netlink.AddrAdd(iface, &netlink.Addr{bridgeIPNet, ""}); err != nil { - return fmtError("Failed to add address %s to bridge: %v", bridgeIPNet, err) - } - - // Configure bridge IPv6. - if config.EnableIPv6 { - if err := setupIPv6Bridge(iface, config); err != nil { - return fmtError("Failed to setup bridge IPv6: %v", err) - } - } - - // Up the bridge interface. - if err := netlink.LinkSetUp(iface); err != nil { - return fmtError("Failed to up network bridge: %v", err) - } - - if config.FixedCIDRv6 != "" { - dest, network, err := net.ParseCIDR(config.FixedCIDRv6) - if err != nil { - return fmtError("Invalid bridge fixed CIDR IPv6 %q: %v", config.FixedCIDRv6, err) - } - - // Set route to global IPv6 subnet - log.Infof("Adding route to IPv6 network %q via device %q", dest, iface) - if err := netlink.RouteAdd(&netlink.Route{Dst: network, LinkIndex: iface.Attrs().Index}); err != nil { - return fmtError("Could not add route to IPv6 network %q via device %q", config.FixedCIDRv6, iface) - } - } - - return getInterfaceAddrByName(config.BridgeName) -} -*/ - type bridgeNetwork struct { Config Configuration } From 3125c1f7c78eb6aba8e38bb3e26a9ceb46858b04 Mon Sep 17 00:00:00 2001 From: Arnaud Porterie Date: Sun, 22 Feb 2015 21:42:34 -0800 Subject: [PATCH 6/6] WIP - Code moves Signed-off-by: Arnaud Porterie --- libnetwork/bridge/bridge.go | 12 --------- libnetwork/bridge/network.go | 15 ++++++++++++ libnetwork/bridge/utils.go | 47 ------------------------------------ 3 files changed, 15 insertions(+), 59 deletions(-) create mode 100644 libnetwork/bridge/network.go delete mode 100644 libnetwork/bridge/utils.go diff --git a/libnetwork/bridge/bridge.go b/libnetwork/bridge/bridge.go index 0723829c71..f9b9ce9d72 100644 --- a/libnetwork/bridge/bridge.go +++ b/libnetwork/bridge/bridge.go @@ -79,15 +79,3 @@ func Create(config *Configuration) (libnetwork.Network, error) { return &bridgeNetwork{*config}, nil } - -type bridgeNetwork struct { - Config Configuration -} - -func (b *bridgeNetwork) Type() string { - return NetworkType -} - -func (b *bridgeNetwork) Link(name string) ([]*libnetwork.Interface, error) { - return nil, nil -} diff --git a/libnetwork/bridge/network.go b/libnetwork/bridge/network.go new file mode 100644 index 0000000000..4e73ed5270 --- /dev/null +++ b/libnetwork/bridge/network.go @@ -0,0 +1,15 @@ +package bridge + +import "github.com/docker/libnetwork" + +type bridgeNetwork struct { + Config Configuration +} + +func (b *bridgeNetwork) Type() string { + return NetworkType +} + +func (b *bridgeNetwork) Link(name string) ([]*libnetwork.Interface, error) { + return nil, nil +} diff --git a/libnetwork/bridge/utils.go b/libnetwork/bridge/utils.go deleted file mode 100644 index b17dd63cf0..0000000000 --- a/libnetwork/bridge/utils.go +++ /dev/null @@ -1,47 +0,0 @@ -package bridge - -/* -func electBridgeNetwork(config *Configuration) (*net.IPNet, error) { - // Is a bridge IP is provided as part of the configuration, we only check - // its validity. - if config.AddressIPv4 != "" { - ip, network, err := net.ParseCIDR(config.AddressIPv4) - if err != nil { - return nil, err - } - network.IP = ip - return network, nil - } - - // No bridge IP was specified: we have to elect one ourselves from a set of - // predetermined networks. - for _, n := range bridgeNetworks { - // TODO CheckNameserverOverlaps - // TODO CheckRouteOverlaps - return n, nil - } - - return nil, fmt.Errorf("Couldn't find an address range for interface %q", config.BridgeName) -} - -func createBridgeInterface(name string) (netlink.Link, error) { - link := &netlink.Bridge{ - LinkAttrs: netlink.LinkAttrs{ - Name: name, - }, - } - - // Only set the bridge's MAC address if the kernel version is > 3.3, as it - // was not supported before that. - kv, err := kernel.GetKernelVersion() - if err == nil && (kv.Kernel >= 3 && kv.Major >= 3) { - link.Attrs().HardwareAddr = generateRandomMAC() - log.Debugf("Setting bridge mac address to %s", link.Attrs().HardwareAddr) - } - - if err := netlink.LinkAdd(link); err != nil { - return nil, err - } - return netlink.LinkByName(name) -} -*/