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)) }