Esempio n. 1
0
func (a *Allocator) getAddress(subnet *net.IPNet, bitmask *bitseq.Handle, prefAddress net.IP, ver ipVersion) (net.IP, error) {
	var (
		bytePos, bitPos int
		ordinal         int
		err             error
	)

	// Look for free IP, skip .0 and .255, they will be automatically reserved
	for {
		if bitmask.Unselected() <= 0 {
			return nil, ErrNoAvailableIPs
		}
		if prefAddress == nil {
			bytePos, bitPos, err = bitmask.GetFirstAvailable()
		} else {
			ordinal = ipToInt(getHostPortionIP(prefAddress, subnet))
			bytePos, bitPos, err = bitmask.CheckIfAvailable(ordinal)
		}
		if err != nil {
			return nil, ErrNoAvailableIPs
		}

		// Lock it
		if err = bitmask.PushReservation(bytePos, bitPos, false); err != nil {
			if _, ok := err.(types.RetryError); !ok {
				return nil, fmt.Errorf("internal failure while reserving the address: %s", err.Error())
			}
			continue
		}

		// Build IP ordinal
		ordinal = bitPos + bytePos*8

		// For v4, let reservation of .0 and .255 happen automatically
		if ver == v4 && !isValidIP(ordinal) {
			continue
		}
		break
	}

	// Convert IP ordinal for this subnet into IP address
	return generateAddress(ordinal, subnet), nil
}