2 * Copyright (c) 2013, 2015 IBM Corporation and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.neutron.spi;
11 import com.google.common.net.InetAddresses;
12 import java.io.Serializable;
13 import java.math.BigInteger;
14 import java.net.Inet6Address;
15 import java.net.UnknownHostException;
16 import java.util.ArrayList;
17 import java.util.List;
18 import javax.xml.bind.annotation.XmlAccessType;
19 import javax.xml.bind.annotation.XmlAccessorType;
20 import javax.xml.bind.annotation.XmlElement;
21 import javax.xml.bind.annotation.XmlRootElement;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 @XmlAccessorType(XmlAccessType.NONE)
27 public final class NeutronSubnetIpAllocationPool implements Serializable {
28 private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnetIpAllocationPool.class);
30 private static final long serialVersionUID = 1L;
32 private static final int BYTE_LENGTH = 8;
33 private static final int IPV4_DOTTED_QUADS = 4;
34 private static final int IPV4_DOTTED_QUAD_OFFSET = 3;
35 private static final int IPV4_DOTTED_QUAD_MASK = 255;
37 // See OpenStack Network API v2.0 Reference for description of
38 // annotated attributes
40 @XmlElement(name = "start")
43 @XmlElement(name = "end")
46 public NeutronSubnetIpAllocationPool() {
49 public NeutronSubnetIpAllocationPool(String lowAddress, String highAddress) {
50 poolStart = lowAddress;
51 poolEnd = highAddress;
54 public String getPoolStart() {
58 public void setPoolStart(String poolStart) {
59 this.poolStart = poolStart;
62 public String getPoolEnd() {
66 public void setPoolEnd(String poolEnd) {
67 this.poolEnd = poolEnd;
71 * This method determines if this allocation pool contains the
75 * IPv4 address in dotted decimal format
76 * @return a boolean on whether the pool contains the address or not
79 public boolean contains(String inputString) {
80 long inputIp = convert(inputString);
81 long startIp = convert(poolStart);
82 long endIp = convert(poolEnd);
83 return inputIp >= startIp && inputIp <= endIp;
87 * This static method converts the supplied IPv4 address to a long
88 * integer for comparison.
91 * IPv4 address in dotted decimal format
92 * @return high-endian representation of the IPv4 address as a long.
93 * This method will return 0 if the input is null.
96 static long convert(String inputString) {
98 if (inputString != null) {
99 String[] parts = inputString.split("\\.");
100 for (String part : parts) {
102 ans |= Integer.parseInt(part);
109 * This method determines if this allocation pool contains the
110 * input IPv4 address.
113 * IPv4 address in dotted decimal format
114 * @return a boolean on whether the pool contains the address or not
117 public boolean containsV6(String inputString) {
118 BigInteger inputIp = convertV6(inputString);
119 BigInteger startIp = convertV6(poolStart);
120 BigInteger endIp = convertV6(poolEnd);
121 return inputIp.compareTo(startIp) >= 0 && inputIp.compareTo(endIp) <= 0;
125 * This static method converts the supplied IPv4 address to a long
126 * integer for comparison.
129 * IPv6 address in dotted decimal format
130 * @return high-endian representation of the IPv4 address as a BigInteger.
131 * This method will return 0 if the input is null.
134 static BigInteger convertV6(String inputString) {
135 if (inputString == null) {
136 return BigInteger.ZERO;
138 return new BigInteger(((Inet6Address) InetAddresses.forString(inputString)).getAddress());
142 * This static method converts the supplied high-ending long back
143 * into a dotted decimal representation of an IPv4 address.
146 * high-endian representation of the IPv4 address as a long
147 * @return IPv4 address in dotted decimal format
149 static String longToIp(long input) {
152 String[] parts = new String[IPV4_DOTTED_QUADS];
153 for (part = 0; part < IPV4_DOTTED_QUADS; part++) {
154 parts[IPV4_DOTTED_QUAD_OFFSET - part] = String.valueOf(ipLong & IPV4_DOTTED_QUAD_MASK);
155 ipLong >>= BYTE_LENGTH;
157 return join(parts, ".");
161 * This static method converts the supplied high-ending long back
162 * into a dotted decimal representation of an IPv4 address.
165 * high-endian representation of the IPv4 address as a long
166 * @return IPv4 address in dotted decimal format
168 static String bigIntegerToIp(BigInteger ipv4BigInteger) {
170 return Inet6Address.getByAddress(ipv4BigInteger.toByteArray()).getHostAddress();
171 } catch (UnknownHostException e) {
172 LOG.error("bigIntegerToIp", e);
178 * helper routine used by longToIp
180 public static String join(String[] strings, String separator) {
181 if (strings.length == 0) {
184 StringBuilder sb = new StringBuilder();
186 for (index = 0; index < strings.length - 1; index++) {
187 sb.append(strings[index]);
188 sb.append(separator);
190 return sb.toString() + strings[index];
194 * This method splits the current instance by removing the supplied
197 * If the parameter is either the low or high address,
198 * then that member is adjusted and a list containing just this instance
201 * If the parameter is in the middle of the pool, then
202 * create two new instances, one ranging from low to parameter-1
203 * the other ranging from parameter+1 to high
205 public List<NeutronSubnetIpAllocationPool> splitPool(String ipAddress) {
206 List<NeutronSubnetIpAllocationPool> ans = new ArrayList<>();
207 long givenIp = NeutronSubnetIpAllocationPool.convert(ipAddress);
208 long startIp = NeutronSubnetIpAllocationPool.convert(poolStart);
209 long endIp = NeutronSubnetIpAllocationPool.convert(poolEnd);
211 NeutronSubnetIpAllocationPool pool = new NeutronSubnetIpAllocationPool();
212 boolean poolStarted = false;
213 for (ipaddr = startIp; ipaddr <= endIp; ipaddr++) {
214 if (ipaddr == startIp) {
215 if (ipaddr != givenIp) {
216 pool.setPoolStart(poolStart);
220 pool.setPoolStart(NeutronSubnetIpAllocationPool.longToIp(ipaddr + 1));
223 if (ipaddr == endIp) {
224 if (ipaddr != givenIp) {
225 pool.setPoolEnd(poolEnd);
227 pool.setPoolEnd(NeutronSubnetIpAllocationPool.longToIp(ipaddr - 1));
231 if (ipaddr != startIp && ipaddr != endIp) {
232 if (ipaddr != givenIp) {
234 pool.setPoolStart(NeutronSubnetIpAllocationPool.longToIp(ipaddr));
238 pool.setPoolEnd(NeutronSubnetIpAllocationPool.longToIp(ipaddr - 1));
240 pool = new NeutronSubnetIpAllocationPool();
242 pool.setPoolStart(NeutronSubnetIpAllocationPool.longToIp(ipaddr + 1));
251 public String toString() {
252 return "NeutronSubnetIpAllocationPool [" + "start=" + poolStart + ", end=" + poolEnd + "]";
256 * This method splits the current instance by removing the supplied
259 * If the parameter is either the low or high address,
260 * then that member is adjusted and a list containing just this instance
263 * If the parameter is in the middle of the pool, then
264 * create two new instances, one ranging from low to parameter-1
265 * the other ranging from parameter+1 to high
266 * If the pool is a single address, return null
268 public List<NeutronSubnetIpAllocationPool> splitPoolV6(String ipAddress) {
269 List<NeutronSubnetIpAllocationPool> ans = new ArrayList<>();
270 BigInteger givenIp = NeutronSubnetIpAllocationPool.convertV6(ipAddress);
271 BigInteger startIp = NeutronSubnetIpAllocationPool.convertV6(poolStart);
272 BigInteger endIp = NeutronSubnetIpAllocationPool.convertV6(poolEnd);
273 if (givenIp.compareTo(startIp) == 0 && givenIp.compareTo(endIp) < 0) {
274 NeutronSubnetIpAllocationPool pool = new NeutronSubnetIpAllocationPool();
275 pool.setPoolStart(NeutronSubnetIpAllocationPool.bigIntegerToIp(startIp.add(BigInteger.ONE)));
276 pool.setPoolEnd(poolEnd);
280 if (givenIp.compareTo(endIp) == 0 && givenIp.compareTo(startIp) > 0) {
281 NeutronSubnetIpAllocationPool pool = new NeutronSubnetIpAllocationPool();
282 pool.setPoolStart(poolStart);
283 pool.setPoolEnd(NeutronSubnetIpAllocationPool.bigIntegerToIp(endIp.subtract(BigInteger.ONE)));
287 if (givenIp.compareTo(endIp) < 0 && givenIp.compareTo(startIp) > 0) {
288 NeutronSubnetIpAllocationPool pool = new NeutronSubnetIpAllocationPool();
289 pool.setPoolStart(poolStart);
290 pool.setPoolEnd(NeutronSubnetIpAllocationPool.bigIntegerToIp(givenIp.subtract(BigInteger.ONE)));
292 NeutronSubnetIpAllocationPool p2 = new NeutronSubnetIpAllocationPool();
293 p2.setPoolStart(NeutronSubnetIpAllocationPool.bigIntegerToIp(givenIp.add(BigInteger.ONE)));
294 p2.setPoolEnd(poolEnd);