WIP - Bridge refactoring
Signed-off-by: Arnaud Porterie <arnaud.porterie@docker.com>
This commit is contained in:
parent
1f3b1febc7
commit
796d58af9e
5 changed files with 83 additions and 50 deletions
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue