diff --git a/libnetwork/drivers/overlay/ovmanager/ovmanager.go b/libnetwork/drivers/overlay/ovmanager/ovmanager.go index cd42a06226..54902929a5 100644 --- a/libnetwork/drivers/overlay/ovmanager/ovmanager.go +++ b/libnetwork/drivers/overlay/ovmanager/ovmanager.go @@ -18,9 +18,12 @@ import ( ) const ( - networkType = "overlay" + networkType = "overlay" + // The lowest VNI value to auto-assign. Windows does not support VXLAN IDs + // which overlap the range of 802.1Q VLAN IDs [0, 4095]. vxlanIDStart = 4096 - vxlanIDEnd = (1 << 24) - 1 + // The largest VNI value permitted by RFC 7348. + vxlanIDEnd = (1 << 24) - 1 ) type networkTable map[string]*network @@ -108,13 +111,22 @@ func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data, gwIP: ipd.Gateway, } - if len(vxlanIDList) > i { + if len(vxlanIDList) > i { // The VNI for this subnet was specified in the network options. s.vni = vxlanIDList[i] - } - - if err := n.obtainVxlanID(s); err != nil { - n.releaseVxlanID() - return nil, fmt.Errorf("could not obtain vxlan id for pool %s: %v", s.subnetIP, err) + err := d.vxlanIdm.GetSpecificID(uint64(s.vni)) // Mark VNI as in-use. + if err != nil { + // The VNI is already in use by another subnet/network. + n.releaseVxlanID() + return nil, fmt.Errorf("could not assign vxlan id %v to pool %s: %v", s.vni, s.subnetIP, err) + } + } else { + // Allocate an available VNI for the subnet, outside the range of 802.1Q VLAN IDs. + vni, err := d.vxlanIdm.GetIDInRange(vxlanIDStart, vxlanIDEnd, true) + if err != nil { + n.releaseVxlanID() + return nil, fmt.Errorf("could not obtain vxlan id for pool %s: %v", s.subnetIP, err) + } + s.vni = uint32(vni) } n.subnets = append(n.subnets, s) @@ -158,21 +170,6 @@ func (d *driver) NetworkFree(id string) error { return nil } -func (n *network) obtainVxlanID(s *subnet) error { - vni := uint64(s.vni) - if vni == 0 { - vni, err := n.driver.vxlanIdm.GetIDInRange(vxlanIDStart, vxlanIDEnd, true) - if err != nil { - return err - } - - s.vni = uint32(vni) - return nil - } - - return n.driver.vxlanIdm.GetSpecificID(vni) -} - func (n *network) releaseVxlanID() { for _, s := range n.subnets { n.driver.vxlanIdm.Release(uint64(s.vni))