mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Merge remote-tracking branch 'origin/219-default-bridge-2'
This commit is contained in:
		
						commit
						793c1ad990
					
				
					 6 changed files with 145 additions and 6 deletions
				
			
		| 
						 | 
					@ -135,6 +135,7 @@ type NetworkSettings struct {
 | 
				
			||||||
	IpAddress   string
 | 
						IpAddress   string
 | 
				
			||||||
	IpPrefixLen int
 | 
						IpPrefixLen int
 | 
				
			||||||
	Gateway     string
 | 
						Gateway     string
 | 
				
			||||||
 | 
						Bridge      string
 | 
				
			||||||
	PortMapping map[string]string
 | 
						PortMapping map[string]string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -491,6 +492,7 @@ func (container *Container) allocateNetwork() error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	container.network = iface
 | 
						container.network = iface
 | 
				
			||||||
 | 
						container.NetworkSettings.Bridge = container.runtime.networkManager.bridgeIface
 | 
				
			||||||
	container.NetworkSettings.IpAddress = iface.IPNet.IP.String()
 | 
						container.NetworkSettings.IpAddress = iface.IPNet.IP.String()
 | 
				
			||||||
	container.NetworkSettings.IpPrefixLen, _ = iface.IPNet.Mask.Size()
 | 
						container.NetworkSettings.IpPrefixLen, _ = iface.IPNet.Mask.Size()
 | 
				
			||||||
	container.NetworkSettings.Gateway = iface.Gateway.String()
 | 
						container.NetworkSettings.Gateway = iface.Gateway.String()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,13 @@ func main() {
 | 
				
			||||||
	// FIXME: Switch d and D ? (to be more sshd like)
 | 
						// FIXME: Switch d and D ? (to be more sshd like)
 | 
				
			||||||
	flDaemon := flag.Bool("d", false, "Daemon mode")
 | 
						flDaemon := flag.Bool("d", false, "Daemon mode")
 | 
				
			||||||
	flDebug := flag.Bool("D", false, "Debug mode")
 | 
						flDebug := flag.Bool("D", false, "Debug mode")
 | 
				
			||||||
 | 
						bridgeName := flag.String("br", "", "")
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
 | 
						if *bridgeName != "" {
 | 
				
			||||||
 | 
							docker.NetworkBridgeIface = *bridgeName
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							docker.NetworkBridgeIface = docker.DefaultNetworkBridge
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if *flDebug {
 | 
						if *flDebug {
 | 
				
			||||||
		os.Setenv("DEBUG", "1")
 | 
							os.Setenv("DEBUG", "1")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ lxc.utsname = {{.Id}}
 | 
				
			||||||
# network configuration
 | 
					# network configuration
 | 
				
			||||||
lxc.network.type = veth
 | 
					lxc.network.type = veth
 | 
				
			||||||
lxc.network.flags = up
 | 
					lxc.network.flags = up
 | 
				
			||||||
lxc.network.link = lxcbr0
 | 
					lxc.network.link = {{.NetworkSettings.Bridge}}
 | 
				
			||||||
lxc.network.name = eth0
 | 
					lxc.network.name = eth0
 | 
				
			||||||
lxc.network.mtu = 1500
 | 
					lxc.network.mtu = 1500
 | 
				
			||||||
lxc.network.ipv4 = {{.NetworkSettings.IpAddress}}/{{.NetworkSettings.IpPrefixLen}}
 | 
					lxc.network.ipv4 = {{.NetworkSettings.IpAddress}}/{{.NetworkSettings.IpPrefixLen}}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										101
									
								
								network.go
									
										
									
									
									
								
							
							
						
						
									
										101
									
								
								network.go
									
										
									
									
									
								
							| 
						 | 
					@ -12,10 +12,12 @@ import (
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var NetworkBridgeIface string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	networkBridgeIface = "lxcbr0"
 | 
						DefaultNetworkBridge = "lxcbr0"
 | 
				
			||||||
	portRangeStart     = 49153
 | 
						portRangeStart       = 49153
 | 
				
			||||||
	portRangeEnd       = 65535
 | 
						portRangeEnd         = 65535
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Calculates the first and last IP addresses in an IPNet
 | 
					// Calculates the first and last IP addresses in an IPNet
 | 
				
			||||||
| 
						 | 
					@ -29,6 +31,19 @@ func networkRange(network *net.IPNet) (net.IP, net.IP) {
 | 
				
			||||||
	return firstIP, lastIP
 | 
						return firstIP, lastIP
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Detects overlap between one IPNet and another
 | 
				
			||||||
 | 
					func networkOverlaps(netX *net.IPNet, netY *net.IPNet) bool {
 | 
				
			||||||
 | 
						firstIP, _ := networkRange(netX)
 | 
				
			||||||
 | 
						if netY.Contains(firstIP) {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						firstIP, _ = networkRange(netY)
 | 
				
			||||||
 | 
						if netX.Contains(firstIP) {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Converts a 4 bytes IP into a 32 bit integer
 | 
					// Converts a 4 bytes IP into a 32 bit integer
 | 
				
			||||||
func ipToInt(ip net.IP) int32 {
 | 
					func ipToInt(ip net.IP) int32 {
 | 
				
			||||||
	return int32(binary.BigEndian.Uint32(ip.To4()))
 | 
						return int32(binary.BigEndian.Uint32(ip.To4()))
 | 
				
			||||||
| 
						 | 
					@ -51,6 +66,19 @@ func networkSize(mask net.IPMask) int32 {
 | 
				
			||||||
	return int32(binary.BigEndian.Uint32(m)) + 1
 | 
						return int32(binary.BigEndian.Uint32(m)) + 1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Wrapper around the ip command
 | 
				
			||||||
 | 
					func ip(args ...string) (string, error) {
 | 
				
			||||||
 | 
						path, err := exec.LookPath("ip")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", fmt.Errorf("command not found: ip")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						output, err := exec.Command(path, args...).CombinedOutput()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", fmt.Errorf("ip failed: ip %v", strings.Join(args, " "))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return string(output), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Wrapper around the iptables command
 | 
					// Wrapper around the iptables command
 | 
				
			||||||
func iptables(args ...string) error {
 | 
					func iptables(args ...string) error {
 | 
				
			||||||
	path, err := exec.LookPath("iptables")
 | 
						path, err := exec.LookPath("iptables")
 | 
				
			||||||
| 
						 | 
					@ -63,6 +91,64 @@ func iptables(args ...string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkRouteOverlaps(dockerNetwork *net.IPNet) error {
 | 
				
			||||||
 | 
						output, err := ip("route")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						Debugf("Routes:\n\n%s", output)
 | 
				
			||||||
 | 
						for _, line := range strings.Split(output, "\n") {
 | 
				
			||||||
 | 
							if strings.Trim(line, "\r\n\t ") == "" || strings.Contains(line, "default") {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if _, network, err := net.ParseCIDR(strings.Split(line, " ")[0]); err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("Unexpected ip route output: %s (%s)", err, line)
 | 
				
			||||||
 | 
							} else if networkOverlaps(dockerNetwork, network) {
 | 
				
			||||||
 | 
								return fmt.Errorf("Network %s is already routed: '%s'", dockerNetwork.String(), line)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func CreateBridgeIface(ifaceName string) error {
 | 
				
			||||||
 | 
						addrs := []string{"172.16.42.1/24", "10.0.42.1/24", "192.168.42.1/24"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var ifaceAddr string
 | 
				
			||||||
 | 
						for _, addr := range addrs {
 | 
				
			||||||
 | 
							_, dockerNetwork, err := net.ParseCIDR(addr)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := checkRouteOverlaps(dockerNetwork); err == nil {
 | 
				
			||||||
 | 
								ifaceAddr = addr
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								Debugf("%s: %s", addr, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if ifaceAddr == "" {
 | 
				
			||||||
 | 
							return fmt.Errorf("Impossible to create a bridge. Please create a bridge manually and restart docker with -br <bridgeName>")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							Debugf("Creating bridge %s with network %s", ifaceName, ifaceAddr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if output, err := ip("link", "add", ifaceName, "type", "bridge"); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Error creating bridge: %s (output: %s)", err, output)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if output, err := ip("addr", "add", ifaceAddr, "dev", ifaceName); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Unable to add private network: %s (%s)", err, output)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if output, err := ip("link", "set", ifaceName, "up"); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Unable to start network bridge: %s (%s)", err, output)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := iptables("-t", "nat", "-A", "POSTROUTING", "-s", ifaceAddr,
 | 
				
			||||||
 | 
							"!", "-d", ifaceAddr, "-j", "MASQUERADE"); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("Unable to enable network bridge NAT: %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Return the IPv4 address of a network interface
 | 
					// Return the IPv4 address of a network interface
 | 
				
			||||||
func getIfaceAddr(name string) (net.Addr, error) {
 | 
					func getIfaceAddr(name string) (net.Addr, error) {
 | 
				
			||||||
	iface, err := net.InterfaceByName(name)
 | 
						iface, err := net.InterfaceByName(name)
 | 
				
			||||||
| 
						 | 
					@ -406,7 +492,14 @@ func (manager *NetworkManager) Allocate() (*NetworkInterface, error) {
 | 
				
			||||||
func newNetworkManager(bridgeIface string) (*NetworkManager, error) {
 | 
					func newNetworkManager(bridgeIface string) (*NetworkManager, error) {
 | 
				
			||||||
	addr, err := getIfaceAddr(bridgeIface)
 | 
						addr, err := getIfaceAddr(bridgeIface)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("Couldn't find bridge interface %s (%s).\nPlease create it with 'ip link add lxcbr0 type bridge; ip addr add ADDRESS/MASK dev lxcbr0'", bridgeIface, err)
 | 
							// If the iface is not found, try to create it
 | 
				
			||||||
 | 
							if err := CreateBridgeIface(bridgeIface); err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							addr, err = getIfaceAddr(bridgeIface)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	network := addr.(*net.IPNet)
 | 
						network := addr.(*net.IPNet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -253,3 +253,38 @@ func assertIPEquals(t *testing.T, ip1, ip2 net.IP) {
 | 
				
			||||||
		t.Fatalf("Expected IP %s, got %s", ip1, ip2)
 | 
							t.Fatalf("Expected IP %s, got %s", ip1, ip2)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func AssertOverlap(CIDRx string, CIDRy string, t *testing.T) {
 | 
				
			||||||
 | 
						_, netX, _ := net.ParseCIDR(CIDRx)
 | 
				
			||||||
 | 
						_, netY, _ := net.ParseCIDR(CIDRy)
 | 
				
			||||||
 | 
						if !networkOverlaps(netX, netY) {
 | 
				
			||||||
 | 
							t.Errorf("%v and %v should overlap", netX, netY)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func AssertNoOverlap(CIDRx string, CIDRy string, t *testing.T) {
 | 
				
			||||||
 | 
						_, netX, _ := net.ParseCIDR(CIDRx)
 | 
				
			||||||
 | 
						_, netY, _ := net.ParseCIDR(CIDRy)
 | 
				
			||||||
 | 
						if networkOverlaps(netX, netY) {
 | 
				
			||||||
 | 
							t.Errorf("%v and %v should not overlap", netX, netY)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNetworkOverlaps(t *testing.T) {
 | 
				
			||||||
 | 
						//netY starts at same IP and ends within netX
 | 
				
			||||||
 | 
						AssertOverlap("172.16.0.1/24", "172.16.0.1/25", t)
 | 
				
			||||||
 | 
						//netY starts within netX and ends at same IP
 | 
				
			||||||
 | 
						AssertOverlap("172.16.0.1/24", "172.16.0.128/25", t)
 | 
				
			||||||
 | 
						//netY starts and ends within netX
 | 
				
			||||||
 | 
						AssertOverlap("172.16.0.1/24", "172.16.0.64/25", t)
 | 
				
			||||||
 | 
						//netY starts at same IP and ends outside of netX
 | 
				
			||||||
 | 
						AssertOverlap("172.16.0.1/24", "172.16.0.1/23", t)
 | 
				
			||||||
 | 
						//netY starts before and ends at same IP of netX
 | 
				
			||||||
 | 
						AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
 | 
				
			||||||
 | 
						//netY starts before and ends outside of netX
 | 
				
			||||||
 | 
						AssertOverlap("172.16.1.1/24", "172.16.0.1/23", t)
 | 
				
			||||||
 | 
						//netY starts and ends before netX
 | 
				
			||||||
 | 
						AssertNoOverlap("172.16.1.1/25", "172.16.0.1/24", t)
 | 
				
			||||||
 | 
						//netX starts and ends before netY
 | 
				
			||||||
 | 
						AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -267,7 +267,10 @@ func NewRuntimeFromDirectory(root string) (*Runtime, error) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
 | 
							return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	netManager, err := newNetworkManager(networkBridgeIface)
 | 
						if NetworkBridgeIface == "" {
 | 
				
			||||||
 | 
							NetworkBridgeIface = DefaultNetworkBridge
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						netManager, err := newNetworkManager(NetworkBridgeIface)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue