WIP - Bridge refactoring

Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
This commit is contained in:
Arnaud Porterie 2015-02-22 21:11:12 -08:00
parent 1f3b1febc7
commit 796d58af9e
5 changed files with 83 additions and 50 deletions

View File

@ -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 {

View File

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

View File

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

View File

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

View File

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