WIP - Bridge refactoring
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
This commit is contained in:
parent
76a8cbba11
commit
1f3b1febc7
10 changed files with 107 additions and 61 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
32
libnetwork/bridge/setup_ipv6.go
Normal file
32
libnetwork/bridge/setup_ipv6.go
Normal file
|
@ -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, ""})
|
||||
}
|
46
libnetwork/bridge/setup_verify.go
Normal file
46
libnetwork/bridge/setup_verify.go
Normal file
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue