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.ovsdb.openstack.netvirt.translator;
11 import java.io.Serializable;
12 import java.math.BigInteger;
13 import java.net.InetAddress;
14 import java.net.Inet6Address;
15 import java.util.ArrayList;
16 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;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 @XmlAccessorType(XmlAccessType.NONE)
28 public class NeutronSubnetIPAllocationPool implements Serializable {
29 private static final Logger LOGGER = LoggerFactory
30 .getLogger(NeutronSubnetIPAllocationPool.class);
32 private static final long serialVersionUID = 1L;
34 private static final int BYTE_LENGTH = 8;
35 private static final int IPV4_DOTTED_QUADS = 4;
36 private static final int IPV4_DOTTED_QUAD_OFFSET = 3;
37 private static final int IPV4_DOTTED_QUAD_MASK = 255;
39 // See OpenStack Network API v2.0 Reference for description of
40 // annotated attributes
42 @XmlElement(name = "start")
45 @XmlElement(name = "end")
48 public NeutronSubnetIPAllocationPool() {
51 public NeutronSubnetIPAllocationPool(String lowAddress, String highAddress) {
52 poolStart = lowAddress;
53 poolEnd = highAddress;
56 public String getPoolStart() {
60 public void setPoolStart(String poolStart) {
61 this.poolStart = poolStart;
64 public String getPoolEnd() {
68 public void setPoolEnd(String poolEnd) {
69 this.poolEnd = poolEnd;
73 * This method determines if this allocation pool contains the
77 * IPv4 address in dotted decimal format
78 * @return a boolean on whether the pool contains the address or not
81 public boolean contains(String inputString) {
82 long inputIP = convert(inputString);
83 long startIP = convert(poolStart);
84 long endIP = convert(poolEnd);
85 return (inputIP >= startIP && inputIP <= endIP);
89 * This static method converts the supplied IPv4 address to a long
90 * integer for comparison
93 * IPv4 address in dotted decimal format
94 * @return high-endian representation of the IPv4 address as a long.
95 * This method will return 0 if the input is null.
98 static long convert(String inputString) {
100 if (inputString != null) {
101 String[] parts = inputString.split("\\.");
102 for (String part: parts) {
104 ans |= Integer.parseInt(part);
111 * This method determines if this allocation pool contains the
115 * IPv4 address in dotted decimal format
116 * @return a boolean on whether the pool contains the address or not
119 public boolean containsV6(String inputString) {
120 BigInteger inputIP = convertV6(inputString);
121 BigInteger startIP = convertV6(poolStart);
122 BigInteger endIP = convertV6(poolEnd);
123 return (inputIP.compareTo(startIP) >= 0 && inputIP.compareTo(endIP) <= 0);
127 * This static method converts the supplied IPv4 address to a long
128 * integer for comparison
131 * IPv6 address in dotted decimal format
132 * @return high-endian representation of the IPv4 address as a BigInteger.
133 * This method will return 0 if the input is null.
136 static BigInteger convertV6(String inputString) {
137 if (inputString == null) {
138 return BigInteger.ZERO;
141 return new BigInteger(InetAddress.getByName(inputString).getAddress());
142 } catch (Exception e) {
143 LOGGER.error("convertV6 error", e);
144 return BigInteger.ZERO;
149 * This static method converts the supplied high-ending long back
150 * into a dotted decimal representation of an IPv4 address
153 * high-endian representation of the IPv4 address as a long
154 * @return IPv4 address in dotted decimal format
156 static String longToIP(long input) {
159 String[] parts = new String[IPV4_DOTTED_QUADS];
160 for (part = 0; part < IPV4_DOTTED_QUADS; part++) {
161 parts[IPV4_DOTTED_QUAD_OFFSET-part] = String.valueOf(ipLong & IPV4_DOTTED_QUAD_MASK);
162 ipLong >>= BYTE_LENGTH;
164 return join(parts,".");
168 * This static method converts the supplied high-ending long back
169 * into a dotted decimal representation of an IPv4 address
172 * high-endian representation of the IPv4 address as a long
173 * @return IPv4 address in dotted decimal format
175 static String bigIntegerToIP(BigInteger b) {
177 return Inet6Address.getByAddress(b.toByteArray()).getHostAddress();
178 } catch (Exception e) {
179 LOGGER.error("bigIntegerToIP", e);
185 * helper routine used by longToIP
187 public static String join(String r[],String separator)
192 StringBuilder sb = new StringBuilder();
194 for(i = 0;i < r.length - 1;i++) {
196 sb.append(separator);
198 return sb.toString() + r[i];
202 * This method splits the current instance by removing the supplied
205 * If the parameter is either the low or high address,
206 * then that member is adjusted and a list containing just this instance
209 * If the parameter is in the middle of the pool, then
210 * create two new instances, one ranging from low to parameter-1
211 * the other ranging from parameter+1 to high
213 public List<NeutronSubnetIPAllocationPool> splitPool(String ipAddress) {
214 List<NeutronSubnetIPAllocationPool> ans = new ArrayList<>();
215 long gIP = NeutronSubnetIPAllocationPool.convert(ipAddress);
216 long sIP = NeutronSubnetIPAllocationPool.convert(poolStart);
217 long eIP = NeutronSubnetIPAllocationPool.convert(poolEnd);
219 NeutronSubnetIPAllocationPool p = new NeutronSubnetIPAllocationPool();
220 boolean poolStarted = false;
221 for (i = sIP; i <= eIP; i++) {
224 p.setPoolStart(poolStart);
228 p.setPoolStart(NeutronSubnetIPAllocationPool.longToIP(i+1));
233 p.setPoolEnd(poolEnd);
235 p.setPoolEnd(NeutronSubnetIPAllocationPool.longToIP(i-1));
239 if (i != sIP && i != eIP) {
242 p.setPoolStart(NeutronSubnetIPAllocationPool.longToIP(i));
246 p.setPoolEnd(NeutronSubnetIPAllocationPool.longToIP(i-1));
249 p = new NeutronSubnetIPAllocationPool();
251 p.setPoolStart(NeutronSubnetIPAllocationPool.longToIP(i+1));
260 public String toString() {
261 return "NeutronSubnetIPAllocationPool [" +
262 "start=" + poolStart +
263 ", end=" + poolEnd + "]";
267 * This method splits the current instance by removing the supplied
270 * If the parameter is either the low or high address,
271 * then that member is adjusted and a list containing just this instance
274 * If the parameter is in the middle of the pool, then
275 * create two new instances, one ranging from low to parameter-1
276 * the other ranging from parameter+1 to high
277 * If the pool is a single address, return null
279 public List<NeutronSubnetIPAllocationPool> splitPoolV6(String ipAddress) {
280 List<NeutronSubnetIPAllocationPool> ans = new ArrayList<>();
281 BigInteger gIP = NeutronSubnetIPAllocationPool.convertV6(ipAddress);
282 BigInteger sIP = NeutronSubnetIPAllocationPool.convertV6(poolStart);
283 BigInteger eIP = NeutronSubnetIPAllocationPool.convertV6(poolEnd);
284 if (gIP.compareTo(sIP) == 0 && gIP.compareTo(eIP) < 0) {
285 NeutronSubnetIPAllocationPool p = new NeutronSubnetIPAllocationPool();
286 p.setPoolStart(NeutronSubnetIPAllocationPool.bigIntegerToIP(sIP.add(BigInteger.ONE)));
287 p.setPoolEnd(poolEnd);
291 if (gIP.compareTo(eIP) == 0 && gIP.compareTo(sIP) > 0) {
292 NeutronSubnetIPAllocationPool p = new NeutronSubnetIPAllocationPool();
293 p.setPoolStart(poolStart);
294 p.setPoolEnd(NeutronSubnetIPAllocationPool.bigIntegerToIP(eIP.subtract(BigInteger.ONE)));
298 if (gIP.compareTo(eIP) < 0 && gIP.compareTo(sIP) > 0) {
299 NeutronSubnetIPAllocationPool p = new NeutronSubnetIPAllocationPool();
300 p.setPoolStart(poolStart);
301 p.setPoolEnd(NeutronSubnetIPAllocationPool.bigIntegerToIP(gIP.subtract(BigInteger.ONE)));
303 NeutronSubnetIPAllocationPool p2 = new NeutronSubnetIPAllocationPool();
304 p2.setPoolStart(NeutronSubnetIPAllocationPool.bigIntegerToIP(gIP.add(BigInteger.ONE)));
305 p2.setPoolEnd(poolEnd);