mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Phase-1 bridge driver changes to support IPAM
Signed-off-by: Madhu Venugopal <madhu@docker.com>
This commit is contained in:
parent
831e3401f3
commit
f2f536032b
13 changed files with 61 additions and 424 deletions
|
@ -35,6 +35,13 @@ const (
|
||||||
maxAllocatePortAttempts = 10
|
maxAllocatePortAttempts = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultGatewayV4AuxKey represents the default-gateway configured by the user
|
||||||
|
DefaultGatewayV4AuxKey = "DefaultGatewayIPv4"
|
||||||
|
// DefaultGatewayV6AuxKey represents the ipv6 default-gateway configured by the user
|
||||||
|
DefaultGatewayV6AuxKey = "DefaultGatewayIPv6"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ipAllocator *ipallocator.IPAllocator
|
ipAllocator *ipallocator.IPAllocator
|
||||||
)
|
)
|
||||||
|
@ -50,8 +57,6 @@ type configuration struct {
|
||||||
type networkConfiguration struct {
|
type networkConfiguration struct {
|
||||||
BridgeName string
|
BridgeName string
|
||||||
AddressIPv4 *net.IPNet
|
AddressIPv4 *net.IPNet
|
||||||
FixedCIDR *net.IPNet
|
|
||||||
FixedCIDRv6 *net.IPNet
|
|
||||||
EnableIPv6 bool
|
EnableIPv6 bool
|
||||||
EnableIPMasquerade bool
|
EnableIPMasquerade bool
|
||||||
EnableICC bool
|
EnableICC bool
|
||||||
|
@ -148,19 +153,6 @@ func (c *networkConfiguration) Validate() error {
|
||||||
|
|
||||||
// If bridge v4 subnet is specified
|
// If bridge v4 subnet is specified
|
||||||
if c.AddressIPv4 != nil {
|
if c.AddressIPv4 != nil {
|
||||||
// If Container restricted subnet is specified, it must be a subset of bridge subnet
|
|
||||||
if c.FixedCIDR != nil {
|
|
||||||
// Check Network address
|
|
||||||
if !c.AddressIPv4.Contains(c.FixedCIDR.IP) {
|
|
||||||
return &ErrInvalidContainerSubnet{}
|
|
||||||
}
|
|
||||||
// Check it is effectively a subset
|
|
||||||
brNetLen, _ := c.AddressIPv4.Mask.Size()
|
|
||||||
cnNetLen, _ := c.FixedCIDR.Mask.Size()
|
|
||||||
if brNetLen > cnNetLen {
|
|
||||||
return &ErrInvalidContainerSubnet{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If default gw is specified, it must be part of bridge subnet
|
// If default gw is specified, it must be part of bridge subnet
|
||||||
if c.DefaultGatewayIPv4 != nil {
|
if c.DefaultGatewayIPv4 != nil {
|
||||||
if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) {
|
if !c.AddressIPv4.Contains(c.DefaultGatewayIPv4) {
|
||||||
|
@ -169,13 +161,6 @@ func (c *networkConfiguration) Validate() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If default v6 gw is specified, FixedCIDRv6 must be specified and gw must belong to FixedCIDRv6 subnet
|
|
||||||
if c.EnableIPv6 && c.DefaultGatewayIPv6 != nil {
|
|
||||||
if c.FixedCIDRv6 == nil || !c.FixedCIDRv6.Contains(c.DefaultGatewayIPv6) {
|
|
||||||
return &ErrInvalidGateway{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,65 +244,6 @@ func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if i, ok := data["AddressIPv4"]; ok && i != nil {
|
|
||||||
if s, ok := i.(string); ok {
|
|
||||||
if ip, nw, e := net.ParseCIDR(s); e == nil {
|
|
||||||
nw.IP = ip
|
|
||||||
c.AddressIPv4 = nw
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("failed to parse AddressIPv4 value")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("invalid type for AddressIPv4 value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if i, ok := data["FixedCIDR"]; ok && i != nil {
|
|
||||||
if s, ok := i.(string); ok {
|
|
||||||
if ip, nw, e := net.ParseCIDR(s); e == nil {
|
|
||||||
nw.IP = ip
|
|
||||||
c.FixedCIDR = nw
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("failed to parse FixedCIDR value")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("invalid type for FixedCIDR value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if i, ok := data["FixedCIDRv6"]; ok && i != nil {
|
|
||||||
if s, ok := i.(string); ok {
|
|
||||||
if ip, nw, e := net.ParseCIDR(s); e == nil {
|
|
||||||
nw.IP = ip
|
|
||||||
c.FixedCIDRv6 = nw
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("failed to parse FixedCIDRv6 value")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("invalid type for FixedCIDRv6 value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if i, ok := data["DefaultGatewayIPv4"]; ok && i != nil {
|
|
||||||
if s, ok := i.(string); ok {
|
|
||||||
if c.DefaultGatewayIPv4 = net.ParseIP(s); c.DefaultGatewayIPv4 == nil {
|
|
||||||
return types.BadRequestErrorf("failed to parse DefaultGatewayIPv4 value")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("invalid type for DefaultGatewayIPv4 value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if i, ok := data["DefaultGatewayIPv6"]; ok && i != nil {
|
|
||||||
if s, ok := i.(string); ok {
|
|
||||||
if c.DefaultGatewayIPv6 = net.ParseIP(s); c.DefaultGatewayIPv6 == nil {
|
|
||||||
return types.BadRequestErrorf("failed to parse DefaultGatewayIPv6 value")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return types.BadRequestErrorf("invalid type for DefaultGatewayIPv6 value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if i, ok := data["DefaultBindingIP"]; ok && i != nil {
|
if i, ok := data["DefaultBindingIP"]; ok && i != nil {
|
||||||
if s, ok := i.(string); ok {
|
if s, ok := i.(string); ok {
|
||||||
if c.DefaultBindingIP = net.ParseIP(s); c.DefaultBindingIP == nil {
|
if c.DefaultBindingIP = net.ParseIP(s); c.DefaultBindingIP == nil {
|
||||||
|
@ -327,6 +253,7 @@ func (c *networkConfiguration) fromMap(data map[string]interface{}) error {
|
||||||
return types.BadRequestErrorf("invalid type for DefaultBindingIP value")
|
return types.BadRequestErrorf("invalid type for DefaultBindingIP value")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,6 +443,36 @@ func parseNetworkGenericOptions(data interface{}) (*networkConfiguration, error)
|
||||||
return config, err
|
return config, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *networkConfiguration) processIPAM(id string, ipamV4Data, ipamV6Data []driverapi.IPAMData) error {
|
||||||
|
if len(ipamV4Data) > 1 || len(ipamV6Data) > 1 {
|
||||||
|
return types.ForbiddenErrorf("bridge driver doesnt support multiple subnets")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ipamV4Data) == 0 {
|
||||||
|
return types.BadRequestErrorf("bridge network %s requires ipv4 configuration", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ipamV4Data[0].Gateway != nil {
|
||||||
|
c.AddressIPv4 = types.GetIPNetCopy(ipamV4Data[0].Gateway)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.EnableIPv6 && len(ipamV6Data) == 0 {
|
||||||
|
return types.BadRequestErrorf("bridge network %s requires ipv6 configuration", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
gw, ok := ipamV4Data[0].AuxAddresses[DefaultGatewayV4AuxKey]
|
||||||
|
if ok {
|
||||||
|
c.DefaultGatewayIPv4 = gw.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
gw, ok = ipamV4Data[0].AuxAddresses[DefaultGatewayV6AuxKey]
|
||||||
|
if ok {
|
||||||
|
c.DefaultGatewayIPv6 = gw.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseNetworkOptions(id string, option options.Generic) (*networkConfiguration, error) {
|
func parseNetworkOptions(id string, option options.Generic) (*networkConfiguration, error) {
|
||||||
var err error
|
var err error
|
||||||
config := &networkConfiguration{}
|
config := &networkConfiguration{}
|
||||||
|
@ -545,10 +502,6 @@ func parseNetworkOptions(id string, option options.Generic) (*networkConfigurati
|
||||||
|
|
||||||
// Returns the non link-local IPv6 subnet for the containers attached to this bridge if found, nil otherwise
|
// Returns the non link-local IPv6 subnet for the containers attached to this bridge if found, nil otherwise
|
||||||
func getV6Network(config *networkConfiguration, i *bridgeInterface) *net.IPNet {
|
func getV6Network(config *networkConfiguration, i *bridgeInterface) *net.IPNet {
|
||||||
if config.FixedCIDRv6 != nil {
|
|
||||||
return config.FixedCIDRv6
|
|
||||||
}
|
|
||||||
|
|
||||||
if i.bridgeIPv6 != nil && i.bridgeIPv6.IP != nil && !i.bridgeIPv6.IP.IsLinkLocalUnicast() {
|
if i.bridgeIPv6 != nil && i.bridgeIPv6.IP != nil && !i.bridgeIPv6.IP.IsLinkLocalUnicast() {
|
||||||
return i.bridgeIPv6
|
return i.bridgeIPv6
|
||||||
}
|
}
|
||||||
|
@ -587,6 +540,12 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = config.processIPAM(id, ipV4Data, ipV6Data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
networkList := d.getNetworks()
|
networkList := d.getNetworks()
|
||||||
for _, nw := range networkList {
|
for _, nw := range networkList {
|
||||||
nw.Lock()
|
nw.Lock()
|
||||||
|
@ -655,7 +614,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
|
||||||
bridgeSetup.queueStep(setupBridgeIPv4)
|
bridgeSetup.queueStep(setupBridgeIPv4)
|
||||||
|
|
||||||
enableIPv6Forwarding := false
|
enableIPv6Forwarding := false
|
||||||
if d.config.EnableIPForwarding && config.FixedCIDRv6 != nil {
|
if d.config.EnableIPForwarding {
|
||||||
enableIPv6Forwarding = true
|
enableIPv6Forwarding = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,14 +633,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
|
||||||
// the case of a previously existing device.
|
// the case of a previously existing device.
|
||||||
{bridgeAlreadyExists, setupVerifyAndReconcile},
|
{bridgeAlreadyExists, setupVerifyAndReconcile},
|
||||||
|
|
||||||
// Setup the bridge to allocate containers IPv4 addresses in the
|
|
||||||
// specified subnet.
|
|
||||||
{config.FixedCIDR != nil, setupFixedCIDRv4},
|
|
||||||
|
|
||||||
// Setup the bridge to allocate containers global IPv6 addresses in the
|
|
||||||
// specified subnet.
|
|
||||||
{config.FixedCIDRv6 != nil, setupFixedCIDRv6},
|
|
||||||
|
|
||||||
// Enable IPv6 Forwarding
|
// Enable IPv6 Forwarding
|
||||||
{enableIPv6Forwarding, setupIPv6Forwarding},
|
{enableIPv6Forwarding, setupIPv6Forwarding},
|
||||||
|
|
||||||
|
@ -712,8 +663,6 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, ipV4Dat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block bridge IP from being allocated.
|
|
||||||
bridgeSetup.queueStep(allocateBridgeIP)
|
|
||||||
// Apply the prepared list of steps, and abort at the first error.
|
// Apply the prepared list of steps, and abort at the first error.
|
||||||
bridgeSetup.queueStep(setupDeviceUp)
|
bridgeSetup.queueStep(setupDeviceUp)
|
||||||
if err = bridgeSetup.apply(); err != nil {
|
if err = bridgeSetup.apply(); err != nil {
|
||||||
|
@ -790,21 +739,7 @@ func (d *driver) DeleteNetwork(nid string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Programming
|
// Programming
|
||||||
err = netlink.LinkDel(n.bridge.Link)
|
return netlink.LinkDel(n.bridge.Link)
|
||||||
|
|
||||||
// Release ip addresses (ignore errors)
|
|
||||||
if config.FixedCIDR == nil || config.FixedCIDR.Contains(config.DefaultGatewayIPv4) {
|
|
||||||
if e := ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, n.bridge.gatewayIPv4); e != nil {
|
|
||||||
logrus.Warnf("Failed to release default gateway address %s: %v", n.bridge.gatewayIPv4.String(), e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if config.FixedCIDR == nil || config.FixedCIDR.Contains(n.bridge.bridgeIPv4.IP) {
|
|
||||||
if e := ipAllocator.ReleaseIP(n.bridge.bridgeIPv4, n.bridge.bridgeIPv4.IP); e != nil {
|
|
||||||
logrus.Warnf("Failed to release bridge IP %s: %v", n.bridge.bridgeIPv4.IP.String(), e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func addToBridge(ifaceName, bridgeName string) error {
|
func addToBridge(ifaceName, bridgeName string) error {
|
||||||
|
@ -996,12 +931,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// v4 address for the sandbox side pipe interface
|
ipv4Addr := ifInfo.Address()
|
||||||
ip4, err := ipAllocator.RequestIP(n.bridge.bridgeIPv4, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ipv4Addr := &net.IPNet{IP: ip4, Mask: n.bridge.bridgeIPv4.Mask}
|
|
||||||
|
|
||||||
// Down the interface before configuring mac address.
|
// Down the interface before configuring mac address.
|
||||||
if err = netlink.LinkSetDown(sbox); err != nil {
|
if err = netlink.LinkSetDown(sbox); err != nil {
|
||||||
|
@ -1009,7 +939,10 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
|
// Set the sbox's MAC. If specified, use the one configured by user, otherwise generate one based on IP.
|
||||||
mac := electMacAddress(epConfig, ip4)
|
mac := ifInfo.MacAddress()
|
||||||
|
if mac == nil {
|
||||||
|
mac = electMacAddress(epConfig, ipv4Addr.IP)
|
||||||
|
}
|
||||||
err = netlink.LinkSetHardwareAddr(sbox, mac)
|
err = netlink.LinkSetHardwareAddr(sbox, mac)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err)
|
return fmt.Errorf("could not set mac address for container interface %s: %v", containerIfName, err)
|
||||||
|
@ -1021,33 +954,7 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err)
|
return fmt.Errorf("could not set link up for host interface %s: %v", hostIfName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// v6 address for the sandbox side pipe interface
|
ipv6Addr = ifInfo.AddressIPv6()
|
||||||
ipv6Addr = &net.IPNet{}
|
|
||||||
if config.EnableIPv6 {
|
|
||||||
var ip6 net.IP
|
|
||||||
|
|
||||||
network := n.bridge.bridgeIPv6
|
|
||||||
if config.FixedCIDRv6 != nil {
|
|
||||||
network = config.FixedCIDRv6
|
|
||||||
}
|
|
||||||
|
|
||||||
ones, _ := network.Mask.Size()
|
|
||||||
if ones <= 80 {
|
|
||||||
ip6 = make(net.IP, len(network.IP))
|
|
||||||
copy(ip6, network.IP)
|
|
||||||
for i, h := range mac {
|
|
||||||
ip6[i+10] = h
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ip6, err := ipAllocator.RequestIP(network, ip6)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ipv6Addr = &net.IPNet{IP: ip6, Mask: network.Mask}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the sandbox side pipe interface
|
// Create the sandbox side pipe interface
|
||||||
endpoint.srcName = containerIfName
|
endpoint.srcName = containerIfName
|
||||||
endpoint.addr = ipv4Addr
|
endpoint.addr = ipv4Addr
|
||||||
|
@ -1062,16 +969,8 @@ func (d *driver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ifInfo.SetMacAddress(endpoint.macAddress)
|
if ifInfo.MacAddress() == nil {
|
||||||
if err != nil {
|
err = ifInfo.SetMacAddress(endpoint.macAddress)
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = ifInfo.SetIPAddress(ipv4Addr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if config.EnableIPv6 {
|
|
||||||
err = ifInfo.SetIPAddress(ipv6Addr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -1140,22 +1039,6 @@ func (d *driver) DeleteEndpoint(nid, eid string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Lock()
|
|
||||||
config := n.config
|
|
||||||
n.Unlock()
|
|
||||||
|
|
||||||
// Release the v6 address allocated to this endpoint's sandbox interface
|
|
||||||
if config.EnableIPv6 {
|
|
||||||
network := n.bridge.bridgeIPv6
|
|
||||||
if config.FixedCIDRv6 != nil {
|
|
||||||
network = config.FixedCIDRv6
|
|
||||||
}
|
|
||||||
err := ipAllocator.ReleaseIP(network, ep.addrv6.IP)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try removal of link. Discard error: link pair might have
|
// Try removal of link. Discard error: link pair might have
|
||||||
// already been deleted by sandbox delete. Make sure defer
|
// already been deleted by sandbox delete. Make sure defer
|
||||||
// does not see this error either.
|
// does not see this error either.
|
||||||
|
|
|
@ -36,11 +36,9 @@ func TestCreateFullOptions(t *testing.T) {
|
||||||
netConfig := &networkConfiguration{
|
netConfig := &networkConfiguration{
|
||||||
BridgeName: DefaultBridgeName,
|
BridgeName: DefaultBridgeName,
|
||||||
AddressIPv4: nw,
|
AddressIPv4: nw,
|
||||||
FixedCIDR: cnw,
|
|
||||||
DefaultGatewayIPv4: gw,
|
DefaultGatewayIPv4: gw,
|
||||||
EnableIPv6: true,
|
EnableIPv6: true,
|
||||||
}
|
}
|
||||||
_, netConfig.FixedCIDRv6, _ = net.ParseCIDR("2001:db8::/48")
|
|
||||||
genericOption := make(map[string]interface{})
|
genericOption := make(map[string]interface{})
|
||||||
genericOption[netlabel.GenericData] = config
|
genericOption[netlabel.GenericData] = config
|
||||||
|
|
||||||
|
@ -584,39 +582,6 @@ func TestValidateConfig(t *testing.T) {
|
||||||
// Bridge network
|
// Bridge network
|
||||||
_, network, _ := net.ParseCIDR("172.28.0.0/16")
|
_, network, _ := net.ParseCIDR("172.28.0.0/16")
|
||||||
|
|
||||||
// Test FixedCIDR
|
|
||||||
_, containerSubnet, _ := net.ParseCIDR("172.27.0.0/16")
|
|
||||||
c = networkConfiguration{
|
|
||||||
AddressIPv4: network,
|
|
||||||
FixedCIDR: containerSubnet,
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.Validate()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("Failed to detect invalid FixedCIDR network")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, containerSubnet, _ = net.ParseCIDR("172.28.0.0/16")
|
|
||||||
c.FixedCIDR = containerSubnet
|
|
||||||
err = c.Validate()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Unexpected validation error on FixedCIDR network")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, containerSubnet, _ = net.ParseCIDR("172.28.0.0/15")
|
|
||||||
c.FixedCIDR = containerSubnet
|
|
||||||
err = c.Validate()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("Failed to detect invalid FixedCIDR network")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, containerSubnet, _ = net.ParseCIDR("172.28.0.0/17")
|
|
||||||
c.FixedCIDR = containerSubnet
|
|
||||||
err = c.Validate()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Unexpected validation error on FixedCIDR network")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test v4 gw
|
// Test v4 gw
|
||||||
c.DefaultGatewayIPv4 = net.ParseIP("172.27.30.234")
|
c.DefaultGatewayIPv4 = net.ParseIP("172.27.30.234")
|
||||||
err = c.Validate()
|
err = c.Validate()
|
||||||
|
@ -634,7 +599,6 @@ func TestValidateConfig(t *testing.T) {
|
||||||
_, containerSubnet, _ = net.ParseCIDR("2001:1234:ae:b004::/64")
|
_, containerSubnet, _ = net.ParseCIDR("2001:1234:ae:b004::/64")
|
||||||
c = networkConfiguration{
|
c = networkConfiguration{
|
||||||
EnableIPv6: true,
|
EnableIPv6: true,
|
||||||
FixedCIDRv6: containerSubnet,
|
|
||||||
DefaultGatewayIPv6: net.ParseIP("2001:1234:ac:b004::bad:a55"),
|
DefaultGatewayIPv6: net.ParseIP("2001:1234:ac:b004::bad:a55"),
|
||||||
}
|
}
|
||||||
err = c.Validate()
|
err = c.Validate()
|
||||||
|
@ -647,12 +611,6 @@ func TestValidateConfig(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unexpected validation error on v6 default gateway")
|
t.Fatalf("Unexpected validation error on v6 default gateway")
|
||||||
}
|
}
|
||||||
|
|
||||||
c.FixedCIDRv6 = nil
|
|
||||||
err = c.Validate()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatalf("Failed to detect invalid v6 default gateway")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetDefaultGw(t *testing.T) {
|
func TestSetDefaultGw(t *testing.T) {
|
||||||
|
@ -683,7 +641,6 @@ func TestSetDefaultGw(t *testing.T) {
|
||||||
config := &networkConfiguration{
|
config := &networkConfiguration{
|
||||||
BridgeName: DefaultBridgeName,
|
BridgeName: DefaultBridgeName,
|
||||||
EnableIPv6: true,
|
EnableIPv6: true,
|
||||||
FixedCIDRv6: subnetv6,
|
|
||||||
DefaultGatewayIPv4: gw4,
|
DefaultGatewayIPv4: gw4,
|
||||||
DefaultGatewayIPv6: gw6,
|
DefaultGatewayIPv6: gw6,
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ const (
|
||||||
//Gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] )
|
//Gets the IP version in use ( [ipv4], [ipv6] or [ipv4 and ipv6] )
|
||||||
func getIPVersion(config *networkConfiguration) ipVersion {
|
func getIPVersion(config *networkConfiguration) ipVersion {
|
||||||
ipVersion := ipv4
|
ipVersion := ipv4
|
||||||
if config.FixedCIDRv6 != nil || config.EnableIPv6 {
|
if config.EnableIPv6 {
|
||||||
ipVersion |= ipv6
|
ipVersion |= ipv6
|
||||||
}
|
}
|
||||||
return ipVersion
|
return ipVersion
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package bridge
|
|
||||||
|
|
||||||
import (
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setupFixedCIDRv4(config *networkConfiguration, i *bridgeInterface) error {
|
|
||||||
addrv4, _, err := i.addresses()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Using IPv4 subnet: %v", config.FixedCIDR)
|
|
||||||
if err := ipAllocator.RegisterSubnet(addrv4.IPNet, config.FixedCIDR); err != nil {
|
|
||||||
return &FixedCIDRv4Error{Subnet: config.FixedCIDR, Net: addrv4.IPNet, Err: err}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
package bridge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/docker/libnetwork/testutils"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSetupFixedCIDRv4(t *testing.T) {
|
|
||||||
defer testutils.SetupTestOSContext(t)()
|
|
||||||
|
|
||||||
config := &networkConfiguration{
|
|
||||||
BridgeName: DefaultBridgeName,
|
|
||||||
AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(16, 32)},
|
|
||||||
FixedCIDR: &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)}}
|
|
||||||
br := &bridgeInterface{}
|
|
||||||
|
|
||||||
if err := setupDevice(config, br); err != nil {
|
|
||||||
t.Fatalf("Bridge creation failed: %v", err)
|
|
||||||
}
|
|
||||||
if err := setupBridgeIPv4(config, br); err != nil {
|
|
||||||
t.Fatalf("Assign IPv4 to bridge failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := setupFixedCIDRv4(config, br); err != nil {
|
|
||||||
t.Fatalf("Failed to setup bridge FixedCIDRv4: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ip, err := ipAllocator.RequestIP(config.FixedCIDR, nil); err != nil {
|
|
||||||
t.Fatalf("Failed to request IP to allocator: %v", err)
|
|
||||||
} else if expected := "192.168.2.1"; ip.String() != expected {
|
|
||||||
t.Fatalf("Expected allocated IP %s, got %s", expected, ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetupBadFixedCIDRv4(t *testing.T) {
|
|
||||||
defer testutils.SetupTestOSContext(t)()
|
|
||||||
|
|
||||||
config := &networkConfiguration{
|
|
||||||
BridgeName: DefaultBridgeName,
|
|
||||||
AddressIPv4: &net.IPNet{IP: net.ParseIP("192.168.1.1"), Mask: net.CIDRMask(24, 32)},
|
|
||||||
FixedCIDR: &net.IPNet{IP: net.ParseIP("192.168.2.0"), Mask: net.CIDRMask(24, 32)}}
|
|
||||||
br := &bridgeInterface{}
|
|
||||||
|
|
||||||
if err := setupDevice(config, br); err != nil {
|
|
||||||
t.Fatalf("Bridge creation failed: %v", err)
|
|
||||||
}
|
|
||||||
if err := setupBridgeIPv4(config, br); err != nil {
|
|
||||||
t.Fatalf("Assign IPv4 to bridge failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := setupFixedCIDRv4(config, br)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Setup bridge FixedCIDRv4 should have failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := err.(*FixedCIDRv4Error); !ok {
|
|
||||||
t.Fatalf("Did not fail with expected error. Actual error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package bridge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
log "github.com/Sirupsen/logrus"
|
|
||||||
"github.com/vishvananda/netlink"
|
|
||||||
)
|
|
||||||
|
|
||||||
func setupFixedCIDRv6(config *networkConfiguration, i *bridgeInterface) error {
|
|
||||||
log.Debugf("Using IPv6 subnet: %v", config.FixedCIDRv6)
|
|
||||||
if err := ipAllocator.RegisterSubnet(config.FixedCIDRv6, config.FixedCIDRv6); err != nil {
|
|
||||||
return &FixedCIDRv6Error{Net: config.FixedCIDRv6, Err: err}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setting route to global IPv6 subnet
|
|
||||||
log.Debugf("Adding route to IPv6 network %s via device %s", config.FixedCIDRv6.String(), config.BridgeName)
|
|
||||||
err := netlink.RouteAdd(&netlink.Route{
|
|
||||||
Scope: netlink.SCOPE_UNIVERSE,
|
|
||||||
LinkIndex: i.Link.Attrs().Index,
|
|
||||||
Dst: config.FixedCIDRv6,
|
|
||||||
})
|
|
||||||
if err != nil && !os.IsExist(err) {
|
|
||||||
log.Errorf("Could not add route to IPv6 network %s via device %s", config.FixedCIDRv6.String(), config.BridgeName)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
package bridge
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/docker/libnetwork/testutils"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSetupFixedCIDRv6(t *testing.T) {
|
|
||||||
defer testutils.SetupTestOSContext(t)()
|
|
||||||
|
|
||||||
config := &networkConfiguration{}
|
|
||||||
br := newInterface(config)
|
|
||||||
|
|
||||||
_, config.FixedCIDRv6, _ = net.ParseCIDR("2002:db8::/48")
|
|
||||||
if err := setupDevice(config, br); err != nil {
|
|
||||||
t.Fatalf("Bridge creation failed: %v", err)
|
|
||||||
}
|
|
||||||
if err := setupBridgeIPv4(config, br); err != nil {
|
|
||||||
t.Fatalf("Assign IPv4 to bridge failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := setupBridgeIPv6(config, br); err != nil {
|
|
||||||
t.Fatalf("Assign IPv4 to bridge failed: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := setupFixedCIDRv6(config, br); err != nil {
|
|
||||||
t.Fatalf("Failed to setup bridge FixedCIDRv6: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ip net.IP
|
|
||||||
if ip, err := ipAllocator.RequestIP(config.FixedCIDRv6, nil); err != nil {
|
|
||||||
t.Fatalf("Failed to request IP to allocator: %v", err)
|
|
||||||
} else if expected := "2002:db8::1"; ip.String() != expected {
|
|
||||||
t.Fatalf("Expected allocated IP %s, got %s", expected, ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := ipAllocator.ReleaseIP(config.FixedCIDRv6, ip); err != nil {
|
|
||||||
t.Fatalf("Failed to release IP from allocator: %v", err)
|
|
||||||
} else if _, err := ipAllocator.RequestIP(config.FixedCIDRv6, ip); err != nil {
|
|
||||||
t.Fatalf("Failed to request a released IP: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -74,18 +74,6 @@ func setupBridgeIPv4(config *networkConfiguration, i *bridgeInterface) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func allocateBridgeIP(config *networkConfiguration, i *bridgeInterface) error {
|
|
||||||
// Because of the way ipallocator manages the container address space,
|
|
||||||
// reserve bridge address only if it belongs to the container network
|
|
||||||
// (if defined), no need otherwise
|
|
||||||
if config.FixedCIDR == nil || config.FixedCIDR.Contains(i.bridgeIPv4.IP) {
|
|
||||||
if _, err := ipAllocator.RequestIP(i.bridgeIPv4, i.bridgeIPv4.IP); err != nil {
|
|
||||||
return fmt.Errorf("failed to reserve bridge IP %s: %v", i.bridgeIPv4.IP.String(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func electBridgeIPv4(config *networkConfiguration) (*net.IPNet, error) {
|
func electBridgeIPv4(config *networkConfiguration) (*net.IPNet, error) {
|
||||||
// Use the requested IPv4 CIDR when available.
|
// Use the requested IPv4 CIDR when available.
|
||||||
if config.AddressIPv4 != nil {
|
if config.AddressIPv4 != nil {
|
||||||
|
@ -117,15 +105,6 @@ func setupGatewayIPv4(config *networkConfiguration, i *bridgeInterface) error {
|
||||||
return &ErrInvalidGateway{}
|
return &ErrInvalidGateway{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Because of the way ipallocator manages the container address space,
|
|
||||||
// reserve default gw address only if it belongs to the container network
|
|
||||||
// (if defined), no need otherwise
|
|
||||||
if config.FixedCIDR == nil || config.FixedCIDR.Contains(config.DefaultGatewayIPv4) {
|
|
||||||
if _, err := ipAllocator.RequestIP(i.bridgeIPv4, config.DefaultGatewayIPv4); err != nil {
|
|
||||||
return fmt.Errorf("failed to reserve default gateway %s: %v", config.DefaultGatewayIPv4.String(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store requested default gateway
|
// Store requested default gateway
|
||||||
i.gatewayIPv4 = config.DefaultGatewayIPv4
|
i.gatewayIPv4 = config.DefaultGatewayIPv4
|
||||||
|
|
||||||
|
|
|
@ -61,19 +61,8 @@ func setupBridgeIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupGatewayIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
func setupGatewayIPv6(config *networkConfiguration, i *bridgeInterface) error {
|
||||||
if config.FixedCIDRv6 == nil {
|
|
||||||
return &ErrInvalidContainerSubnet{}
|
|
||||||
}
|
|
||||||
if !config.FixedCIDRv6.Contains(config.DefaultGatewayIPv6) {
|
|
||||||
return &ErrInvalidGateway{}
|
|
||||||
}
|
|
||||||
if _, err := ipAllocator.RequestIP(config.FixedCIDRv6, config.DefaultGatewayIPv6); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store requested default gateway
|
// Store requested default gateway
|
||||||
i.gatewayIPv6 = config.DefaultGatewayIPv6
|
i.gatewayIPv6 = config.DefaultGatewayIPv6
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,6 @@ func TestSetupGatewayIPv6(t *testing.T) {
|
||||||
|
|
||||||
config := &networkConfiguration{
|
config := &networkConfiguration{
|
||||||
BridgeName: DefaultBridgeName,
|
BridgeName: DefaultBridgeName,
|
||||||
FixedCIDRv6: nw,
|
|
||||||
DefaultGatewayIPv6: gw}
|
DefaultGatewayIPv6: gw}
|
||||||
|
|
||||||
br := &bridgeInterface{}
|
br := &bridgeInterface{}
|
||||||
|
|
|
@ -623,7 +623,7 @@ func (ep *endpoint) assignAddress() error {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
n := ep.getNetwork()
|
n := ep.getNetwork()
|
||||||
if n.Type() == "host" || n.Type() == "null" || n.Type() == "bridge" {
|
if n.Type() == "host" || n.Type() == "null" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ipam, err = n.getController().getIpamDriver(n.ipamType)
|
ipam, err = n.getController().getIpamDriver(n.ipamType)
|
||||||
|
@ -680,7 +680,7 @@ func (ep *endpoint) assignAddressVersion(ipVer int, ipam ipamapi.Ipam) error {
|
||||||
|
|
||||||
func (ep *endpoint) releaseAddress() {
|
func (ep *endpoint) releaseAddress() {
|
||||||
n := ep.getNetwork()
|
n := ep.getNetwork()
|
||||||
if n.Type() == "host" || n.Type() == "null" || n.Type() == "bridge" {
|
if n.Type() == "host" || n.Type() == "null" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ipam, err := n.getController().getIpamDriver(n.ipamType)
|
ipam, err := n.getController().getIpamDriver(n.ipamType)
|
||||||
|
|
|
@ -275,24 +275,12 @@ func TestBridge(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cidr, err := types.ParseCIDR("192.168.100.2/28")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cidrv6, err := types.ParseCIDR("fe90::1/96")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debug("Adding a bridge")
|
log.Debug("Adding a bridge")
|
||||||
|
|
||||||
netOption := options.Generic{
|
netOption := options.Generic{
|
||||||
netlabel.GenericData: options.Generic{
|
netlabel.GenericData: options.Generic{
|
||||||
"BridgeName": "testnetwork",
|
"BridgeName": "testnetwork",
|
||||||
"AddressIPv4": subnet,
|
"AddressIPv4": subnet,
|
||||||
"FixedCIDR": cidr,
|
|
||||||
"FixedCIDRv6": cidrv6,
|
|
||||||
"EnableIPv6": true,
|
"EnableIPv6": true,
|
||||||
"EnableICC": true,
|
"EnableICC": true,
|
||||||
"EnableIPMasquerade": true,
|
"EnableIPMasquerade": true,
|
||||||
|
@ -1661,16 +1649,10 @@ func TestEnableIPv6(t *testing.T) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
cidrv6, err := types.ParseCIDR("fe80::1/64")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
netOption := options.Generic{
|
netOption := options.Generic{
|
||||||
netlabel.EnableIPv6: true,
|
netlabel.EnableIPv6: true,
|
||||||
netlabel.GenericData: options.Generic{
|
netlabel.GenericData: options.Generic{
|
||||||
"BridgeName": "testnetwork",
|
"BridgeName": "testnetwork",
|
||||||
"FixedCIDRv6": cidrv6,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -796,7 +796,7 @@ func (n *network) getController() *controller {
|
||||||
|
|
||||||
func (n *network) ipamAllocate() error {
|
func (n *network) ipamAllocate() error {
|
||||||
// For now also exclude bridge from using new ipam
|
// For now also exclude bridge from using new ipam
|
||||||
if n.Type() == "host" || n.Type() == "null" || n.Type() == "bridge" {
|
if n.Type() == "host" || n.Type() == "null" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,8 +913,8 @@ func (n *network) ipamAllocateVersion(ipVer int, ipam ipamapi.Ipam) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *network) ipamRelease() {
|
func (n *network) ipamRelease() {
|
||||||
// For now also exclude bridge from using new ipam
|
// For now exclude host and null
|
||||||
if n.Type() == "host" || n.Type() == "null" || n.Type() == "bridge" {
|
if n.Type() == "host" || n.Type() == "null" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ipam, err := n.getController().getIpamDriver(n.ipamType)
|
ipam, err := n.getController().getIpamDriver(n.ipamType)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue