/*
- * Copyright (c) 2015 Brocade, Communications Systems, Inc
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2015 Cisco Systems, Inc., Brocade, Communications Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterators;
-import com.google.common.net.InetAddresses;
-import com.google.common.primitives.UnsignedBytes;
+import java.math.BigInteger;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IetfInetUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterators;
+import com.google.common.net.InetAddresses;
+import com.google.common.primitives.UnsignedBytes;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
/**
* Created by Martin Bobak <mbobak@cisco.com> on 5.3.2015.
* v6 routines added by Anton Ivanov on 14.6.2015
+ * Arbitrary masks by sai.marapareddy@gmail.com
*/
public final class IpConversionUtil {
+ private static final Logger LOG = LoggerFactory.getLogger(IpConversionUtil.class);
public static final String PREFIX_SEPARATOR = "/";
public static final Splitter PREFIX_SPLITTER = Splitter.on('/');
private static final int INADDR4SZ = 4;
private static final int INADDR6SZ = 16;
private static final int INT16SZ = 2;
+ private static final int IPV4_ADDRESS_LENGTH = 32;
+ private static final int IPV6_ADDRESS_LENGTH = 128;
+ private static final String DEFAULT_ARBITRARY_BIT_MASK = "255.255.255.255";
+
+ /*
+ * Prefix bytearray lookup table. We concatenate the prefixes
+ * to a single byte array and perform offset lookups to ensure
+ * the table is contiguous and save some space.
+ */
+ private static final byte[] PREFIX_BYTEARRAYS;
+ static {
+ final byte[] a = new byte[(INADDR6SZ * Byte.SIZE + 1) * INADDR6SZ];
+
+ int offset = 0;
+ for (int p = 0; p <= INADDR6SZ * Byte.SIZE; ++p) {
+ int prefix = p;
+ for (int i = 0; i < INADDR6SZ; ++i) {
+ a[offset++] = (byte) nextNibble(prefix);
+ prefix -= Byte.SIZE;
+ }
+ }
+
+ PREFIX_BYTEARRAYS = a;
+ }
private IpConversionUtil() {
throw new UnsupportedOperationException("This class should not be instantiated.");
public static Iterator<String> splitToParts(final Ipv4Address ipv4Address) {
/* Invalid (Ab)use of ip address as prefix!!! */
- return Iterators.forArray(ipv4Address.getValue(), "32");
+ return Iterators.forArray(ipv4Address.getValue(), String.valueOf(IPV4_ADDRESS_LENGTH));
}
public static Iterator<String> splitToParts(final Ipv6Prefix ipv6Prefix) {
public static Iterator<String> splitToParts(final Ipv6Address ipv6Address) {
/* Invalid (Ab)use of ip address as prefix!!! */
- return Iterators.forArray(ipv6Address.getValue(), "128");
+ return Iterators.forArray(ipv6Address.getValue(), String.valueOf(IPV6_ADDRESS_LENGTH));
}
/* This forest of functions has a purpose:
*/
public static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address){
- return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + 32);
+ return IetfInetUtil.INSTANCE.ipv4PrefixFor(ipv4Address);
}
public static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final String mask){
if (null != mask && !mask.isEmpty()) {
return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + mask);
} else {
- return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + "32");
+ return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH);
}
}
public static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final int intmask){
- return createPrefix(ipv4Address, String.valueOf(intmask));
+ return IetfInetUtil.INSTANCE.ipv4PrefixFor(ipv4Address, intmask);
}
public static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final byte [] bytemask){
- return createPrefix(ipv4Address, String.valueOf(countBits(bytemask)));
+ return IetfInetUtil.INSTANCE.ipv4PrefixFor(ipv4Address, countBits(bytemask));
+ }
+
+ public static DottedQuad createArbitraryBitMask(final byte [] bytemask) {
+ DottedQuad dottedQuad = new DottedQuad(DEFAULT_ARBITRARY_BIT_MASK);
+ try {
+ dottedQuad = new DottedQuad(InetAddress.getByAddress(bytemask).getHostAddress());
+ } catch (UnknownHostException e) {
+ LOG.error("Failed to create the dottedQuad notation for the given mask ", e);
+ }
+ return dottedQuad;
}
public static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address){
- return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + 128);
+ return IetfInetUtil.INSTANCE.ipv6PrefixFor(ipv6Address);
}
public static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final String mask){
* Note - there is no canonical form check here!!!
*/
if (Strings.isNullOrEmpty(mask)) {
- return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + "128");
+ return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + String.valueOf(IPV6_ADDRESS_LENGTH));
} else {
return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + mask);
}
}
public static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final int intmask){
- return createPrefix(ipv6Address, String.valueOf(intmask));
+ return IetfInetUtil.INSTANCE.ipv6PrefixFor(ipv6Address, intmask);
}
public static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final byte [] bytemask){
- /*
- * Ipv4Address has already validated the address part of the prefix,
- * It is mandated to comply to the same regexp as the address
- * There is absolutely no point rerunning additional checks vs this
- * Note - there is no canonical form check here!!!
- */
- return createPrefix(ipv6Address, String.valueOf(countBits(bytemask)));
+ return IetfInetUtil.INSTANCE.ipv6PrefixFor(ipv6Address, countBits(bytemask));
}
public static Integer extractPrefix(final Ipv4Prefix ipv4Prefix) {
- Iterator<String> addressParts = splitToParts(ipv4Prefix);
- addressParts.next();
- Integer retval = null;
- if (addressParts.hasNext()) {
- retval = Integer.parseInt(addressParts.next());
- }
- return retval;
+ return IetfInetUtil.INSTANCE.splitIpv4Prefix(ipv4Prefix).getValue();
}
public static Integer extractPrefix(final Ipv6Prefix ipv6Prefix) {
- Iterator<String> addressParts = splitToParts(ipv6Prefix);
- addressParts.next();
- Integer retval = null;
- if (addressParts.hasNext()) {
- retval = Integer.parseInt(addressParts.next());
- }
- return retval;
+ return IetfInetUtil.INSTANCE.splitIpv6Prefix(ipv6Prefix).getValue();
}
public static Integer extractPrefix(final Ipv4Address ipv4Prefix) {
- return 32;
+ return IPV4_ADDRESS_LENGTH;
}
public static Integer extractPrefix(final Ipv6Address ipv6Prefix) {
/**
* Print a v6 prefix in byte array + 1 notation
- *
* @param _binary_form - prefix, in byte [] form, last byte is netmask
+ * @return string of v6 prefix
+ * @throws UnknownHostException unknown host exception
*/
public static String byteArrayV6PrefixToString(final byte [] _binary_form) throws UnknownHostException {
/* NO DIY!!! - InetAddresses will actually print correct canonical
return sb.toString();
}
+ private static int ipv6PrefixByteArrayOffset(final int mask) {
+ if (mask < 0) {
+ return 0;
+ }
- /**
+ final int ret = mask * INADDR6SZ;
+ if (ret < PREFIX_BYTEARRAYS.length) {
+ return ret;
+ } else {
+ return PREFIX_BYTEARRAYS.length - INADDR6SZ;
+ }
+ }
+
+ /**
* Canonicalize a v6 prefix while in binary form
*
- * @param _prefix - prefix, in byte [] form
+ * @param prefix - prefix, in byte [] form
* @param mask - mask - number of bits
*/
- public static void canonicalizeIpv6Prefix(final byte [] _prefix, int mask) {
+ public static void canonicalizeIpv6Prefix(final byte [] prefix, final int mask) {
+ final int offset = ipv6PrefixByteArrayOffset(mask);
- for (int i=0; i < INADDR6SZ; i++) {
- _prefix[i] = (byte) (_prefix[i] & nextNibble(mask));
- mask = mask - 8;
+ for (int i = 0; i < INADDR6SZ; i++) {
+ prefix[i] &= PREFIX_BYTEARRAYS[offset + i];
}
}
- public static byte[] convertIpv6PrefixToByteArray(int prefix) {
- byte[] mask = new byte[16];
- for (int count = 0; count < 16; count++) {
- mask[count] = (byte) nextNibble(prefix);
- prefix = prefix - 8;
- }
- return mask;
+ public static byte[] convertIpv6PrefixToByteArray(final int prefix) {
+ final int offset = ipv6PrefixByteArrayOffset(prefix);
+
+ return Arrays.copyOfRange(PREFIX_BYTEARRAYS, offset, offset + INADDR6SZ);
}
public static Ipv6Address extractIpv6Address(final Ipv6Prefix ipv6Prefix) {
- Iterator<String> addressParts = PREFIX_SPLITTER.split(ipv6Prefix.getValue()).iterator();
- return new Ipv6Address(addressParts.next());
+ return IetfInetUtil.INSTANCE.ipv6AddressFrom(ipv6Prefix);
}
public static Integer extractIpv6Prefix(final Ipv6Prefix ipv6Prefix) {
- Iterator<String> addressParts = PREFIX_SPLITTER.split(ipv6Prefix.getValue()).iterator();
- addressParts.next();
-
- Integer prefix = null;
- if (addressParts.hasNext()) {
- prefix = Integer.parseInt(addressParts.next());
- }
- return prefix;
+ return IetfInetUtil.INSTANCE.splitIpv6Prefix(ipv6Prefix).getValue();
}
public static int countBits(final byte[] mask) {
}
return netmask;
}
+
+ public static final byte[] convertArbitraryMaskToByteArray(DottedQuad mask) {
+ String maskValue;
+ if (mask != null && mask.getValue() != null){
+ maskValue = mask.getValue();
+ }
+ else {
+ maskValue = DEFAULT_ARBITRARY_BIT_MASK;
+ }
+ InetAddress maskInIpFormat = null;
+ try {
+ maskInIpFormat = InetAddress.getByName(maskValue);
+ } catch (UnknownHostException e) {
+ LOG.error ("Failed to resolve the ip address of the mask",e);
+ }
+ byte[] bytes = maskInIpFormat.getAddress();
+ return bytes;
+ }
+
+ public static boolean isArbitraryBitMask(byte[] byteMask) {
+ if (byteMask == null) {
+ return false;
+ }
+ else {
+ ArrayList<Integer> integerMaskArrayList = new ArrayList<Integer>();
+ String maskInBits;
+ // converting byte array to bits
+ maskInBits = new BigInteger(1, byteMask).toString(2);
+ ArrayList<String> stringMaskArrayList = new ArrayList<String>(Arrays.asList(maskInBits.split("(?!^)")));
+ for(String string:stringMaskArrayList){
+ integerMaskArrayList.add(Integer.parseInt(string));
+ }
+ return checkArbitraryBitMask(integerMaskArrayList);
+ }
+ }
+
+ private static boolean checkArbitraryBitMask(ArrayList<Integer> arrayList) {
+ // checks 0*1* case - Leading zeros in arrayList are truncated
+ if(arrayList.size()>0 && arrayList.size()<32) {
+ return true;
+ }
+ //checks 1*0*1 case
+ else {
+ for(int i=0; i<arrayList.size()-1;i++) {
+ if(arrayList.get(i) ==0 && arrayList.get(i+1) == 1) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}