/** * Create a pool of the given range (boundaries inclusive) which is completely free. The given subnet size is the network mask (thus * size) of the allocated subnets in this range. This constructor verifies that the whole range is "aligned" with subnets of this size * (i.e. there should not be a waste of space in the beginning or end which is smaller than one subnet of the given subnet size). * * @param range range from within to allocate * @param allocationSubnetSize size of the subnets that will be allocated * @return ipv6 address pool */ public static IPv6AddressPool fromRangeAndSubnet(final IPv6AddressRange range, final IPv6NetworkMask allocationSubnetSize) { // in the beginning, all is free return new IPv6AddressPool(range, allocationSubnetSize, new TreeSet<IPv6AddressRange>(Arrays.asList(range)), null); }
private void validateFreeRanges(IPv6AddressRange range, SortedSet<IPv6AddressRange> toValidate) { if (!toValidate.isEmpty() && !checkWithinBounds(range, toValidate)) throw new IllegalArgumentException("invalid free ranges: not all within bounds of overall range"); // TODO: some more validations would be useful. For example the free ranges should be defragmented and non overlapping etc }
/** * Private constructor to construct a pool with a given set of free ranges and a network which was just allocated. * * @param range range from within to allocate * @param allocationSubnetSize size of the subnets that will be allocated * @param freeRanges free ranges in the allocatable IP address range */ private IPv6AddressPool(final IPv6AddressRange range, final IPv6NetworkMask allocationSubnetSize, final SortedSet<IPv6AddressRange> freeRanges, final IPv6Network lastAllocated) { this.underlyingRange = range; this.allocationSubnetSize = allocationSubnetSize; this.freeRanges = Collections.unmodifiableSortedSet(freeRanges); this.lastAllocated = lastAllocated; validateFreeRanges(underlyingRange, freeRanges); validateRangeIsMultipleOfSubnetsOfGivenSize(underlyingRange, allocationSubnetSize); }
if (!contains(toDeAllocate)) final IPv6AddressRange freeRangeBeforeNetwork = findFreeRangeBefore(toDeAllocate); final IPv6AddressRange freeRangeAfterNetwork = findFreeRangeAfter(toDeAllocate); return new IPv6AddressPool(underlyingRange, allocationSubnetSize, newFreeRanges, getLastAllocated());
/** * Allocate the given subnet from the pool. * * @param toAllocate subnet to allocate from the pool * @return resulting pool */ public IPv6AddressPool allocate(IPv6Network toAllocate) { if (!contains(toAllocate)) throw new IllegalArgumentException( "can not allocate network which is not contained in the pool to allocate from [" + toAllocate + "]"); if (!this.allocationSubnetSize.equals(toAllocate.getNetmask())) throw new IllegalArgumentException( "can not allocate network with prefix length /" + toAllocate.getNetmask().asPrefixLength() + " from a pool configured to hand out subnets with prefix length /" + allocationSubnetSize); // go find the range that contains the requested subnet final IPv6AddressRange rangeToAllocateFrom = findFreeRangeContaining(toAllocate); if (rangeToAllocateFrom != null) { // found a range in which this subnet is free, allocate it return doAllocate(toAllocate, rangeToAllocateFrom); } else { // requested subnet not free return null; } }
/** * Allocate the first available subnet from the pool. * * @return resulting pool */ public IPv6AddressPool allocate() { if (!isExhausted()) { // get the first range of free subnets, and take the first subnet of that range final IPv6AddressRange firstFreeRange = freeRanges.first(); final IPv6Network allocated = IPv6Network.fromAddressAndMask(firstFreeRange.getFirst(), allocationSubnetSize); return doAllocate(allocated, firstFreeRange); } else { // exhausted return null; } }
if (!contains(toDeAllocate)) final IPv6AddressRange freeRangeBeforeNetwork = findFreeRangeBefore(toDeAllocate); final IPv6AddressRange freeRangeAfterNetwork = findFreeRangeAfter(toDeAllocate); return new IPv6AddressPool(underlyingRange, allocationSubnetSize, newFreeRanges, getLastAllocated());
/** * Allocate the given subnet from the pool. * * @param toAllocate subnet to allocate from the pool * @return resulting pool */ public IPv6AddressPool allocate(IPv6Network toAllocate) { if (!contains(toAllocate)) throw new IllegalArgumentException( "can not allocate network which is not contained in the pool to allocate from [" + toAllocate + "]"); if (!this.allocationSubnetSize.equals(toAllocate.getNetmask())) throw new IllegalArgumentException( "can not allocate network with prefix length /" + toAllocate.getNetmask().asPrefixLength() + " from a pool configured to hand out subnets with prefix length /" + allocationSubnetSize); // go find the range that contains the requested subnet final IPv6AddressRange rangeToAllocateFrom = findFreeRangeContaining(toAllocate); if (rangeToAllocateFrom != null) { // found a range in which this subnet is free, allocate it return doAllocate(toAllocate, rangeToAllocateFrom); } else { // requested subnet not free return null; } }
/** * Allocate the first available subnet from the pool. * * @return resulting pool */ public IPv6AddressPool allocate() { if (!isExhausted()) { // get the first range of free subnets, and take the first subnet of that range final IPv6AddressRange firstFreeRange = freeRanges.first(); final IPv6Network allocated = IPv6Network.fromAddressAndMask(firstFreeRange.getFirst(), allocationSubnetSize); return doAllocate(allocated, firstFreeRange); } else { // exhausted return null; } }
/** * Private constructor to construct a pool with a given set of free ranges and a network which was just allocated. * * @param range range from within to allocate * @param allocationSubnetSize size of the subnets that will be allocated * @param freeRanges free ranges in the allocatable IP address range */ private IPv6AddressPool(final IPv6AddressRange range, final IPv6NetworkMask allocationSubnetSize, final SortedSet<IPv6AddressRange> freeRanges, final IPv6Network lastAllocated) { this.underlyingRange = range; this.allocationSubnetSize = allocationSubnetSize; this.freeRanges = Collections.unmodifiableSortedSet(freeRanges); this.lastAllocated = lastAllocated; validateFreeRanges(underlyingRange, freeRanges); validateRangeIsMultipleOfSubnetsOfGivenSize(underlyingRange, allocationSubnetSize); }
/** * Create a pool of the given range (boundaries inclusive) which is completely free. The given subnet size is the network mask (thus * size) of the allocated subnets in this range. This constructor verifies that the whole range is "aligned" with subnets of this size * (i.e. there should not be a waste of space in the beginning or end which is smaller than one subnet of the given subnet size). * * @param range range from within to allocate * @param allocationSubnetSize size of the subnets that will be allocated * @return ipv6 address pool */ public static IPv6AddressPool fromRangeAndSubnet(final IPv6AddressRange range, final IPv6NetworkMask allocationSubnetSize) { // in the beginning, all is free return new IPv6AddressPool(range, allocationSubnetSize, new TreeSet<IPv6AddressRange>(Arrays.asList(range)), null); }
private void validateFreeRanges(IPv6AddressRange range, SortedSet<IPv6AddressRange> toValidate) { if (!toValidate.isEmpty() && !checkWithinBounds(range, toValidate)) throw new IllegalArgumentException("invalid free ranges: not all within bounds of overall range"); // TODO: some more validations would be useful. For example the free ranges should be defragmented and non overlapping etc }
/** * Private helper method to perform the allocation of a subnet within one of the free ranges. * * @param toAllocate subnet to allocate * @param rangeToAllocateFrom free range to allocate from * @return resulting pool */ private IPv6AddressPool doAllocate(final IPv6Network toAllocate, final IPv6AddressRange rangeToAllocateFrom) { assert freeRanges.contains(rangeToAllocateFrom); assert rangeToAllocateFrom.contains(toAllocate); final TreeSet<IPv6AddressRange> newFreeRanges = new TreeSet<IPv6AddressRange>(this.freeRanges); // remove range from free ranges newFreeRanges.remove(rangeToAllocateFrom); // from the range, remove the allocated subnet final List<IPv6AddressRange> newRanges = rangeToAllocateFrom.remove(toAllocate); // and add the resulting ranges as new free ranges newFreeRanges.addAll(newRanges); return new IPv6AddressPool(underlyingRange, allocationSubnetSize, newFreeRanges, toAllocate); }
/** * Private helper method to perform the allocation of a subnet within one of the free ranges. * * @param toAllocate subnet to allocate * @param rangeToAllocateFrom free range to allocate from * @return resulting pool */ private IPv6AddressPool doAllocate(final IPv6Network toAllocate, final IPv6AddressRange rangeToAllocateFrom) { assert freeRanges.contains(rangeToAllocateFrom); assert rangeToAllocateFrom.contains(toAllocate); final TreeSet<IPv6AddressRange> newFreeRanges = new TreeSet<IPv6AddressRange>(this.freeRanges); // remove range from free ranges newFreeRanges.remove(rangeToAllocateFrom); // from the range, remove the allocated subnet final List<IPv6AddressRange> newRanges = rangeToAllocateFrom.remove(toAllocate); // and add the resulting ranges as new free ranges newFreeRanges.addAll(newRanges); return new IPv6AddressPool(underlyingRange, allocationSubnetSize, newFreeRanges, toAllocate); }