summaryrefslogtreecommitdiffstats
path: root/vpp-common/vpp-translate-utils
diff options
context:
space:
mode:
Diffstat (limited to 'vpp-common/vpp-translate-utils')
-rw-r--r--vpp-common/vpp-translate-utils/pom.xml5
-rw-r--r--vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/TranslateUtils.java268
-rw-r--r--vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/cache/EntityDumpExecutor.java2
-rw-r--r--vpp-common/vpp-translate-utils/src/test/java/io/fd/honeycomb/translate/v3po/util/TranslateUtilsTest.java61
4 files changed, 336 insertions, 0 deletions
diff --git a/vpp-common/vpp-translate-utils/pom.xml b/vpp-common/vpp-translate-utils/pom.xml
index 32466c2e1..789338fcb 100644
--- a/vpp-common/vpp-translate-utils/pom.xml
+++ b/vpp-common/vpp-translate-utils/pom.xml
@@ -74,6 +74,11 @@
<artifactId>data-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.9</version>
+ </dependency>
<!-- Testing Dependencies -->
<dependency>
diff --git a/vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/TranslateUtils.java b/vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/TranslateUtils.java
index 0902064eb..95b07743f 100644
--- a/vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/TranslateUtils.java
+++ b/vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/TranslateUtils.java
@@ -17,6 +17,8 @@
package io.fd.honeycomb.translate.v3po.util;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Splitter;
import com.google.common.net.InetAddresses;
@@ -28,10 +30,21 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang3.StringUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.openvpp.jvpp.VppBaseCallException;
import org.openvpp.jvpp.dto.JVppReply;
@@ -102,6 +115,236 @@ public final class TranslateUtils {
}
}
+ public static final byte[] ipAddressToArray(IpAddress address) {
+ checkNotNull(address, "Cannot resolve null adddress");
+
+ if (isIpv6(address)) {
+ return ipv6AddressNoZoneToArray(new Ipv6AddressNoZone(address.getIpv6Address()));
+ } else {
+ return ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(address.getIpv4Address()));
+ }
+ }
+
+ /**
+ * Creates address array from address part of {@link Ipv4Prefix}
+ */
+ public static byte[] ipv4AddressPrefixToArray(@Nonnull final Ipv4Prefix ipv4Prefix) {
+ checkNotNull(ipv4Prefix, "Cannot convert null prefix");
+
+ byte[] retval = new byte[4];
+ String[] address = ipv4Prefix.getValue().substring(0, ipv4Prefix.getValue().indexOf('/')).split("\\.");
+
+ for (int d = 0; d < 4; d++) {
+ retval[d] = (byte) (Short.parseShort(address[d]) & 0xff);
+ }
+ return retval;
+ }
+
+ /**
+ * Converts {@link IpAddress} to array representing {@link Ipv4Address} or {@link Ipv6Address}
+ */
+ public static byte[] ipAddressToArray(boolean isIpv6, @Nonnull IpAddress address) {
+ checkNotNull(address, "Cannot convert null Address");
+
+ if (isIpv6) {
+ return ipv6AddressNoZoneToArray(new Ipv6AddressNoZone(address.getIpv6Address()));
+ } else {
+ return ipv4AddressNoZoneToArray(new Ipv4AddressNoZone(address.getIpv4Address()));
+ }
+ }
+
+ /**
+ * Converts array bytes to {@link IpAddress}
+ */
+ @Nonnull
+ public static IpAddress arrayToIpAddress(boolean isIpv6, byte[] ip) {
+ if (isIpv6) {
+ return new IpAddress(arrayToIpv6AddressNoZone(ip));
+ } else {
+ return new IpAddress(arrayToIpv4AddressNoZone(ip));
+ }
+ }
+
+ /**
+ * Extracts {@link Ipv4Prefix} prefix
+ */
+ public static byte extractPrefix(Ipv4Prefix data) {
+ checkNotNull(data, "Cannot extract from null");
+
+ return Byte.valueOf(data.getValue().substring(data.getValue().indexOf('/') + 1));
+ }
+
+ /**
+ * Converts byte array to {@link Ipv4Prefix} with specified prefixLength
+ */
+ public static Ipv4Prefix arrayToIpv4Prefix(final byte[] address, byte prefixLength) {
+ Ipv4AddressNoZone addressPart = arrayToIpv4AddressNoZone(address);
+
+ return new Ipv4Prefix(addressPart.getValue().concat("/").concat(String.valueOf(prefixLength)));
+ }
+
+ /**
+ * Transform Ipv6 address to a byte array acceptable by VPP. VPP expects incoming byte array to be in the same order
+ * as the address.
+ *
+ * @return byte array with address bytes
+ */
+ public static byte[] ipv6AddressNoZoneToArray(@Nonnull final Ipv6AddressNoZone ipv6Addr) {
+ byte[] retval = new byte[16];
+
+ //splits address and add ommited zeros for easier parsing
+ List<String> segments = Arrays.asList(ipv6Addr.getValue().split(":"))
+ .stream()
+ .map(segment -> StringUtils.repeat('0',4-segment.length())+segment)
+ .collect(Collectors.toList());
+
+ byte index = 0;
+ for (String segment : segments) {
+
+ String firstPart =segment.substring(0, 2);
+ String secondPart = segment.substring(2);
+
+ //first part should be ommited
+ if("00".equals(firstPart)){
+ index++;
+ }else{
+ retval[index++] = ((byte) Short.parseShort(firstPart, 16));
+ }
+
+ retval[index++] = ((byte) Short.parseShort(secondPart, 16));
+ }
+
+ return retval;
+ }
+
+ /**
+ * Creates address array from address part of {@link Ipv6Prefix}
+ */
+ public static byte[] ipv6AddressPrefixToArray(@Nonnull final Ipv6Prefix ipv4Prefix) {
+ checkNotNull(ipv4Prefix, "Cannot convert null prefix");
+
+ return ipv6AddressNoZoneToArray(new Ipv6AddressNoZone(
+ new Ipv6Address(ipv4Prefix.getValue().substring(0, ipv4Prefix.getValue().indexOf('/')))));
+ }
+
+ /**
+ * Extracts {@link Ipv6Prefix} prefix
+ */
+ public static byte extractPrefix(Ipv6Prefix data) {
+ checkNotNull(data, "Cannot extract from null");
+
+ return Byte.valueOf(data.getValue().substring(data.getValue().indexOf('/') + 1));
+ }
+
+ /**
+ * Converts byte array to {@link Ipv6Prefix} with specified prefixLength
+ */
+ public static Ipv6Prefix arrayToIpv6Prefix(final byte[] address, byte prefixLength) {
+ Ipv6AddressNoZone addressPart = arrayToIpv6AddressNoZone(address);
+
+ return new Ipv6Prefix(addressPart.getValue().concat("/").concat(String.valueOf(prefixLength)));
+ }
+
+ /**
+ * Parse byte array returned by VPP representing an Ipv6 address. Vpp returns IP byte arrays in reversed order.
+ *
+ * @return Ipv46ddressNoZone containing string representation of IPv6 address constructed from submitted bytes. No
+ * change in order.
+ */
+ @Nonnull
+ public static Ipv6AddressNoZone arrayToIpv6AddressNoZone(@Nonnull byte[] ip) {
+ checkArgument(ip.length == 16, "Illegal array length");
+
+ try {
+ return new Ipv6AddressNoZone(InetAddresses.toAddrString(InetAddresses.fromLittleEndianByteArray(ip)));
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException("Unable to parse ipv6", e);
+ }
+ }
+
+
+ /**
+ * Parse byte array returned by VPP representing an Ipv6 address. Vpp returns IP byte arrays in natural order.
+ *
+ * @return Ipv46ddressNoZone containing string representation of IPv6 address constructed from submitted bytes. No
+ * change in order.
+ */
+ @Nonnull
+ public static Ipv6AddressNoZone arrayToIpv6AddressNoZoneReversed(@Nonnull byte[] ip) {
+ checkArgument(ip.length == 16, "Illegal array length");
+
+ ip = reverseBytes(ip);
+
+ try {
+ return new Ipv6AddressNoZone(InetAddresses.toAddrString(InetAddresses.fromLittleEndianByteArray(ip)));
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException("Unable to parse ipv6", e);
+ }
+ }
+
+ /**
+ * Converts byte array to address string ,not separated with ":"
+ */
+ public static String byteArrayToMacUnseparated(byte[] address) {
+ checkArgument(address.length == 6, "Illegal array length");
+ return Hex.encodeHexString(address);
+ }
+
+ /**
+ * Converts byte array to address string ,separated with ":"
+ */
+ public static String byteArrayToMacSeparated(byte[] address) {
+ checkArgument(address.length == 6, "Illegal array length");
+
+ String unseparatedAddress = Hex.encodeHexString(address);
+ String separated = "";
+
+ for (int i = 0; i < unseparatedAddress.length(); i = i + 2) {
+ if (i == (unseparatedAddress.length() - 2)) {
+ separated = separated + unseparatedAddress.substring(0 + i, 2 + i);
+ } else {
+ separated = separated + unseparatedAddress.substring(0 + i, 2 + i) + ":";
+ }
+ }
+
+ return separated;
+ }
+
+ /**
+ * Converts MAC string to byte array
+ * */
+ public static byte[] macToByteArray(String mac){
+ checkNotNull(mac,"MAC cannot be null");
+
+ mac = mac.replace(":","");
+
+ try {
+ return Hex.decodeHex(mac.toCharArray());
+ } catch (DecoderException e) {
+ throw new IllegalArgumentException("Unable to convert mac",e);
+ }
+ }
+
+ /**
+ * Detects whether {@code IpAddress} is ipv6
+ */
+ public static boolean isIpv6(IpAddress address) {
+ checkNotNull(address, "Address cannot be null");
+
+ checkState(!(address.getIpv4Address() == null && address.getIpv6Address() == null), "Invalid address");
+ return address.getIpv6Address() != null;
+ }
+
+ /**
+ * Detects whether {@code IpPrefix} is ipv6
+ */
+ public static boolean isIpv6(IpPrefix address) {
+ checkNotNull(address, "Address cannot be null");
+ checkState(!(address.getIpv4Prefix() == null && address.getIpv6Prefix() == null), "Invalid address");
+ return address.getIpv6Prefix() != null;
+ }
+
+
/**
* Transform Ipv4 address to a byte array acceptable by VPP. VPP expects incoming byte array to be in the same order
* as the address.
@@ -144,6 +387,31 @@ public final class TranslateUtils {
}
/**
+ * Parse byte array returned by VPP representing an Ipv4 address. Vpp returns IP byte arrays in reversed order.
+ *
+ * @return Ipv4AddressNoZone containing string representation of IPv4 address constructed from submitted bytes. No
+ * change in order.
+ */
+ @Nonnull
+ public static Ipv4AddressNoZone arrayToIpv4AddressNoZoneReversed(@Nonnull byte[] ip) {
+ // VPP sends ipv4 in a 16 byte array
+
+ if (ip.length == 16) {
+ ip = Arrays.copyOfRange(ip, 0, 4);
+ }
+
+ ip = reverseBytes(ip);
+
+ try {
+ // Not reversing the byte array here!! because the IP coming from VPP is in reversed byte order
+ // compared to byte order it was submitted
+ return new Ipv4AddressNoZone(InetAddresses.toAddrString(InetAddresses.fromLittleEndianByteArray(ip)));
+ } catch (UnknownHostException e) {
+ throw new IllegalArgumentException("Unable to parse ipv4", e);
+ }
+ }
+
+ /**
* Return (interned) string from byte array while removing \u0000. Strings represented as fixed length byte[] from
* vpp contain \u0000.
*/
diff --git a/vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/cache/EntityDumpExecutor.java b/vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/cache/EntityDumpExecutor.java
index 8f3ae5596..5bc2a4b77 100644
--- a/vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/cache/EntityDumpExecutor.java
+++ b/vpp-common/vpp-translate-utils/src/main/java/io/fd/honeycomb/translate/v3po/util/cache/EntityDumpExecutor.java
@@ -26,6 +26,8 @@ import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
public interface EntityDumpExecutor<T, U> {
+ static Void NO_PARAMS = null;
+
/**
* Performs dump on {@link T} entity
*
diff --git a/vpp-common/vpp-translate-utils/src/test/java/io/fd/honeycomb/translate/v3po/util/TranslateUtilsTest.java b/vpp-common/vpp-translate-utils/src/test/java/io/fd/honeycomb/translate/v3po/util/TranslateUtilsTest.java
index d9cb52f3a..a55c3053a 100644
--- a/vpp-common/vpp-translate-utils/src/test/java/io/fd/honeycomb/translate/v3po/util/TranslateUtilsTest.java
+++ b/vpp-common/vpp-translate-utils/src/test/java/io/fd/honeycomb/translate/v3po/util/TranslateUtilsTest.java
@@ -15,6 +15,9 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.junit.Test;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -134,4 +137,62 @@ public class TranslateUtilsTest {
TranslateUtils.byteToBoolean((byte) 123);
}
+ @Test
+ public void testIpv6NoZone(){
+ final Ipv6AddressNoZone ipv6Addr = new Ipv6AddressNoZone("3ffe:1900:4545:3:200:f8ff:fe21:67cf");
+ byte[] bytes = TranslateUtils.ipv6AddressNoZoneToArray(ipv6Addr);
+ assertEquals((byte)63,bytes[0]);
+
+ bytes = reverseBytes(bytes);
+ final Ipv6AddressNoZone ivp6AddressNoZone = TranslateUtils.arrayToIpv6AddressNoZone(bytes);
+ assertEquals(ipv6Addr,ivp6AddressNoZone);
+ }
+
+ @Test
+ public void testByteArrayToMacUnseparated(){
+ byte[] address = TranslateUtils.parseMac("aa:bb:cc:dd:ee:ff");
+
+ String converted = TranslateUtils.byteArrayToMacUnseparated(address);
+
+ assertEquals("aabbccddeeff",converted);
+ }
+
+ @Test
+ public void testByteArrayToMacSeparated(){
+ byte[] address = TranslateUtils.parseMac("aa:bb:cc:dd:ee:ff");
+
+ String converted = TranslateUtils.byteArrayToMacSeparated(address);
+
+ assertEquals("aa:bb:cc:dd:ee:ff",converted);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testByteArrayToMacUnseparatedIllegal(){
+ TranslateUtils.byteArrayToMacUnseparated(new byte[]{54,26,87,32,14});
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testByteArrayToMacSeparatedIllegal() {
+ TranslateUtils.byteArrayToMacSeparated(new byte[]{54, 26, 87, 32, 14});
+ }
+
+ @Test
+ public void testIpv4AddressPrefixToArray() {
+ byte[] ip = TranslateUtils.ipv4AddressPrefixToArray(new Ipv4Prefix("192.168.2.1/24"));
+
+ assertEquals("1.2.168.192", TranslateUtils.arrayToIpv4AddressNoZone(ip).getValue());
+ }
+
+ @Test
+ public void testIpv6AddressPrefixToArray() {
+ byte[] ip = TranslateUtils.ipv6AddressPrefixToArray(new Ipv6Prefix("3ffe:1900:4545:3:200:f8ff:fe21:67cf/48"));
+
+ assertEquals("cf67:21fe:fff8:2:300:4545:19:fe3f", TranslateUtils.arrayToIpv6AddressNoZone(ip).getValue());
+ }
+
+ @Test
+ public void testExtractPrefix() {
+ assertEquals(24, TranslateUtils.extractPrefix(new Ipv4Prefix("192.168.2.1/24")));
+ assertEquals(48, TranslateUtils.extractPrefix(new Ipv6Prefix("3ffe:1900:4545:3:200:f8ff:fe21:67cf/48")));
+ }
} \ No newline at end of file