Allow bridge net driver to skip IPv4 configuration of bridge interface

Introduce "com.docker.network.bridge.inhibit_ipv4" option to the bridge
network driver. If set, this option will prevent docker from setting or
modifying Layer-3 (IP) configuration on the bridge interface in any way.

This option should allow connecting containers to pre-existing network
segments (with e.g., pre-existing default gateways) while simultaneously
preserving our ability to communicate with the host and/or configure the
properties of the host-side container virtual network interface (e.g.,
delay/loss/jitter via netem), which can not be done using macvlan.

Signed-off-by: Gabriel Somlo <gsomlo@gmail.com>
This commit is contained in:
Gabriel L. Somlo 2018-12-23 19:05:20 -05:00
parent f72e642339
commit 10027e8c01
4 changed files with 28 additions and 16 deletions

View File

@ -68,6 +68,7 @@ type networkConfiguration struct {
EnableIPv6 bool
EnableIPMasquerade bool
EnableICC bool
InhibitIPv4 bool
Mtu int
DefaultBindingIP net.IP
DefaultBridge bool
@ -243,6 +244,10 @@ func (c *networkConfiguration) fromLabels(labels map[string]string) error {
if c.EnableICC, err = strconv.ParseBool(value); err != nil {
return parseErr(label, value, err.Error())
}
case InhibitIPv4:
if c.InhibitIPv4, err = strconv.ParseBool(value); err != nil {
return parseErr(label, value, err.Error())
}
case DefaultBridge:
if c.DefaultBridge, err = strconv.ParseBool(value); err != nil {
return parseErr(label, value, err.Error())
@ -699,7 +704,7 @@ func (d *driver) createNetwork(config *networkConfiguration) (err error) {
// We ensure that the bridge has the expectedIPv4 and IPv6 addresses in
// the case of a previously existing device.
{bridgeAlreadyExists, setupVerifyAndReconcile},
{bridgeAlreadyExists && !config.InhibitIPv4, setupVerifyAndReconcile},
// Enable IPv6 Forwarding
{enableIPv6Forwarding, setupIPv6Forwarding},

View File

@ -137,6 +137,7 @@ func (ncfg *networkConfiguration) MarshalJSON() ([]byte, error) {
nMap["EnableIPv6"] = ncfg.EnableIPv6
nMap["EnableIPMasquerade"] = ncfg.EnableIPMasquerade
nMap["EnableICC"] = ncfg.EnableICC
nMap["InhibitIPv4"] = ncfg.InhibitIPv4
nMap["Mtu"] = ncfg.Mtu
nMap["Internal"] = ncfg.Internal
nMap["DefaultBridge"] = ncfg.DefaultBridge
@ -192,6 +193,7 @@ func (ncfg *networkConfiguration) UnmarshalJSON(b []byte) error {
ncfg.EnableIPv6 = nMap["EnableIPv6"].(bool)
ncfg.EnableIPMasquerade = nMap["EnableIPMasquerade"].(bool)
ncfg.EnableICC = nMap["EnableICC"].(bool)
ncfg.InhibitIPv4 = nMap["InhibitIPv4"].(bool)
ncfg.Mtu = int(nMap["Mtu"].(float64))
if v, ok := nMap["Internal"]; ok {
ncfg.Internal = v.(bool)

View File

@ -10,6 +10,9 @@ const (
// EnableICC label
EnableICC = "com.docker.network.bridge.enable_icc"
// InhibitIPv4 label
InhibitIPv4 = "com.docker.network.bridge.inhibit_ipv4"
// DefaultBindingIP label
DefaultBindingIP = "com.docker.network.bridge.host_binding_ipv4"

View File

@ -27,22 +27,24 @@ func selectIPv4Address(addresses []netlink.Addr, selector *net.IPNet) (netlink.A
}
func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
addrv4List, _, err := i.addresses()
if err != nil {
return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err)
}
addrv4, _ := selectIPv4Address(addrv4List, config.AddressIPv4)
if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) {
if addrv4.IPNet != nil {
if err := i.nlh.AddrDel(i.Link, &addrv4); err != nil {
return fmt.Errorf("failed to remove current ip address from bridge: %v", err)
}
if !config.InhibitIPv4 {
addrv4List, _, err := i.addresses()
if err != nil {
return fmt.Errorf("failed to retrieve bridge interface addresses: %v", err)
}
logrus.Debugf("Assigning address to bridge interface %s: %s", config.BridgeName, config.AddressIPv4)
if err := i.nlh.AddrAdd(i.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
return &IPv4AddrAddError{IP: config.AddressIPv4, Err: err}
addrv4, _ := selectIPv4Address(addrv4List, config.AddressIPv4)
if !types.CompareIPNet(addrv4.IPNet, config.AddressIPv4) {
if addrv4.IPNet != nil {
if err := i.nlh.AddrDel(i.Link, &addrv4); err != nil {
return fmt.Errorf("failed to remove current ip address from bridge: %v", err)
}
}
logrus.Debugf("Assigning address to bridge interface %s: %s", config.BridgeName, config.AddressIPv4)
if err := i.nlh.AddrAdd(i.Link, &netlink.Addr{IPNet: config.AddressIPv4}); err != nil {
return &IPv4AddrAddError{IP: config.AddressIPv4, Err: err}
}
}
}