1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #9381 from lebauce/default-gateway

Proposal: Allow specifying a default gateway for bridge networking
This commit is contained in:
Arnaud Porterie 2015-04-20 15:50:35 -07:00
commit 9838242db1
5 changed files with 80 additions and 13 deletions

View file

@ -58,6 +58,8 @@ func (config *Config) InstallFlags() {
flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge") flag.StringVar(&config.Bridge.Iface, []string{"b", "-bridge"}, "", "Attach containers to a network bridge")
flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs") flag.StringVar(&config.Bridge.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs")
flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs") flag.StringVar(&config.Bridge.FixedCIDRv6, []string{"-fixed-cidr-v6"}, "", "IPv6 subnet for fixed IPs")
flag.StringVar(&config.Bridge.DefaultGatewayIPv4, []string{"-default-gateway"}, "", "Container default gateway IPv4 address")
flag.StringVar(&config.Bridge.DefaultGatewayIPv6, []string{"-default-gateway-v6"}, "", "Container default gateway IPv6 address")
flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication") flag.BoolVar(&config.Bridge.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use") flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Storage driver to use")
flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Exec driver to use") flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Exec driver to use")

View file

@ -77,8 +77,10 @@ var (
bridgeIface string bridgeIface string
bridgeIPv4Network *net.IPNet bridgeIPv4Network *net.IPNet
gatewayIPv4 net.IP
bridgeIPv6Addr net.IP bridgeIPv6Addr net.IP
globalIPv6Network *net.IPNet globalIPv6Network *net.IPNet
gatewayIPv6 net.IP
portMapper *portmapper.PortMapper portMapper *portmapper.PortMapper
once sync.Once once sync.Once
@ -103,6 +105,8 @@ type Config struct {
IP string IP string
FixedCIDR string FixedCIDR string
FixedCIDRv6 string FixedCIDRv6 string
DefaultGatewayIPv4 string
DefaultGatewayIPv6 string
InterContainerCommunication bool InterContainerCommunication bool
} }
@ -278,6 +282,12 @@ func InitDriver(config *Config) error {
} }
} }
if gateway, err := requestDefaultGateway(config.DefaultGatewayIPv4, bridgeIPv4Network); err != nil {
return err
} else {
gatewayIPv4 = gateway
}
if config.FixedCIDRv6 != "" { if config.FixedCIDRv6 != "" {
_, subnet, err := net.ParseCIDR(config.FixedCIDRv6) _, subnet, err := net.ParseCIDR(config.FixedCIDRv6)
if err != nil { if err != nil {
@ -289,6 +299,12 @@ func InitDriver(config *Config) error {
return err return err
} }
globalIPv6Network = subnet globalIPv6Network = subnet
if gateway, err := requestDefaultGateway(config.DefaultGatewayIPv6, globalIPv6Network); err != nil {
return err
} else {
gatewayIPv6 = gateway
}
} }
// Block BridgeIP in IP allocator // Block BridgeIP in IP allocator
@ -473,6 +489,24 @@ func setupIPv6Bridge(bridgeIPv6 string) error {
return nil return nil
} }
func requestDefaultGateway(requestedGateway string, network *net.IPNet) (gateway net.IP, err error) {
if requestedGateway != "" {
gateway = net.ParseIP(requestedGateway)
if gateway == nil {
return nil, fmt.Errorf("Bad parameter: invalid gateway ip %s", requestedGateway)
}
if !network.Contains(gateway) {
return nil, fmt.Errorf("Gateway ip %s must be part of the network %s", requestedGateway, network.String())
}
ipAllocator.RequestIP(network, gateway)
}
return gateway, nil
}
func createBridgeIface(name string) error { func createBridgeIface(name string) error {
kv, err := kernel.GetKernelVersion() kv, err := kernel.GetKernelVersion()
// Only set the bridge's mac address if the kernel version is > 3.3 // Only set the bridge's mac address if the kernel version is > 3.3
@ -526,6 +560,8 @@ func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Set
mac net.HardwareAddr mac net.HardwareAddr
err error err error
globalIPv6 net.IP globalIPv6 net.IP
defaultGWIPv4 net.IP
defaultGWIPv6 net.IP
) )
ip, err = ipAllocator.RequestIP(bridgeIPv4Network, net.ParseIP(requestedIP)) ip, err = ipAllocator.RequestIP(bridgeIPv4Network, net.ParseIP(requestedIP))
@ -560,6 +596,18 @@ func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Set
maskSize, _ := bridgeIPv4Network.Mask.Size() maskSize, _ := bridgeIPv4Network.Mask.Size()
if gatewayIPv4 != nil {
defaultGWIPv4 = gatewayIPv4
} else {
defaultGWIPv4 = bridgeIPv4Network.IP
}
if gatewayIPv6 != nil {
defaultGWIPv6 = gatewayIPv6
} else {
defaultGWIPv6 = bridgeIPv6Addr
}
// If linklocal IPv6 // If linklocal IPv6
localIPv6Net, err := linkLocalIPv6FromMac(mac.String()) localIPv6Net, err := linkLocalIPv6FromMac(mac.String())
if err != nil { if err != nil {
@ -569,7 +617,7 @@ func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Set
networkSettings := &network.Settings{ networkSettings := &network.Settings{
IPAddress: ip.String(), IPAddress: ip.String(),
Gateway: bridgeIPv4Network.IP.String(), Gateway: defaultGWIPv4.String(),
MacAddress: mac.String(), MacAddress: mac.String(),
Bridge: bridgeIface, Bridge: bridgeIface,
IPPrefixLen: maskSize, IPPrefixLen: maskSize,
@ -580,7 +628,7 @@ func Allocate(id, requestedMac, requestedIP, requestedIPv6 string) (*network.Set
networkSettings.GlobalIPv6Address = globalIPv6.String() networkSettings.GlobalIPv6Address = globalIPv6.String()
maskV6Size, _ := globalIPv6Network.Mask.Size() maskV6Size, _ := globalIPv6Network.Mask.Size()
networkSettings.GlobalIPv6PrefixLen = maskV6Size networkSettings.GlobalIPv6PrefixLen = maskV6Size
networkSettings.IPv6Gateway = bridgeIPv6Addr.String() networkSettings.IPv6Gateway = defaultGWIPv6.String()
} }
currentInterfaces.Set(id, &networkInterface{ currentInterfaces.Set(id, &networkInterface{

View file

@ -41,6 +41,12 @@ To see the man page for a command run **man docker <command>**.
**-d**, **--daemon**=*true*|*false* **-d**, **--daemon**=*true*|*false*
Enable daemon mode. Default is false. Enable daemon mode. Default is false.
**--default-gateway**=""
IPv4 address of the container default gateway; this address must be part of the bridge subnet (which is defined by \-b or \--bip)
**--default-gateway-v6**=""
IPv6 address of the container default gateway
**--dns**="" **--dns**=""
Force Docker to use specific DNS servers Force Docker to use specific DNS servers

View file

@ -56,6 +56,12 @@ server when it starts up, and cannot be changed once it is running:
* `--bip=CIDR` — see * `--bip=CIDR` — see
[Customizing docker0](#docker0) [Customizing docker0](#docker0)
* `--default-gateway=IP_ADDRESS` — see
[How Docker networks a container](#container-networking)
* `--default-gateway-v6=IP_ADDRESS` — see
[IPv6](#ipv6)
* `--fixed-cidr` — see * `--fixed-cidr` — see
[Customizing docker0](#docker0) [Customizing docker0](#docker0)
@ -499,7 +505,9 @@ want to configure `eth0` via Router Advertisements you should set:
![](/article-img/ipv6_basic_host_config.svg) ![](/article-img/ipv6_basic_host_config.svg)
Every new container will get an IPv6 address from the defined subnet. Further Every new container will get an IPv6 address from the defined subnet. Further
a default route will be added via the gateway `fe80::1` on `eth0`: a default route will be added on `eth0` in the container via the address
specified by the daemon option `--default-gateway-v6` if present, otherwise
via `fe80::1`:
docker run -it ubuntu bash -c "ip -6 addr show dev eth0; ip -6 route show" docker run -it ubuntu bash -c "ip -6 addr show dev eth0; ip -6 route show"
@ -865,12 +873,13 @@ The steps with which Docker configures a container are:
parameter or generate a random one. parameter or generate a random one.
5. Give the container's `eth0` a new IP address from within the 5. Give the container's `eth0` a new IP address from within the
bridge's range of network addresses, and set its default route to bridge's range of network addresses. The default route is set to the
the IP address that the Docker host owns on the bridge. The MAC IP address passed to the Docker daemon using the `--default-gateway`
address is generated from the IP address unless otherwise specified. option if specified, otherwise to the IP address that the Docker host
This prevents ARP cache invalidation problems, when a new container owns on the bridge. The MAC address is generated from the IP address
comes up with an IP used in the past by another container with another unless otherwise specified. This prevents ARP cache invalidation
MAC. problems, when a new container comes up with an IP used in the past by
another container with another MAC.
With these steps complete, the container now possesses an `eth0` With these steps complete, the container now possesses an `eth0`
(virtual) network card and will find itself able to communicate with (virtual) network card and will find itself able to communicate with

View file

@ -145,6 +145,8 @@ expect an integer, and they can only be specified once.
--bip="" Specify network bridge IP --bip="" Specify network bridge IP
-D, --debug=false Enable debug mode -D, --debug=false Enable debug mode
-d, --daemon=false Enable daemon mode -d, --daemon=false Enable daemon mode
--default-gateway="" Container default gateway IPv4 address
--default-gateway-v6="" Container default gateway IPv6 address
--dns=[] DNS server to use --dns=[] DNS server to use
--dns-search=[] DNS search domains to use --dns-search=[] DNS search domains to use
-e, --exec-driver="native" Exec driver to use -e, --exec-driver="native" Exec driver to use