From aa3fb2c1271c948f9a3c5a4ab22ce146be13163e Mon Sep 17 00:00:00 2001 From: Jan Srnicek Date: Wed, 31 Aug 2016 07:46:41 +0200 Subject: HONEYCOMB-75 - Lisp implemetation Rebased on final minimal distro Change-Id: Ib71fc59e62dda4633f4f79c5c7417a4aaf02a177 Signed-off-by: Jan Srnicek Signed-off-by: Florin Coras Signed-off-by: Maros Marsalek --- .../translate/v3po/util/TranslateUtils.java | 268 +++++++++++++++++++++ .../v3po/util/cache/EntityDumpExecutor.java | 2 + 2 files changed, 270 insertions(+) (limited to 'vpp-common/vpp-translate-utils/src/main') 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 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. @@ -143,6 +386,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 { + static Void NO_PARAMS = null; + /** * Performs dump on {@link T} entity * -- cgit 1.2.3-korg