From: Robert Varga Date: Thu, 25 Feb 2016 20:42:44 +0000 (+0100) Subject: BUG-2825: introduce Ipv4 prefix parser for short bytes X-Git-Tag: release/boron~179 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=63d60122d4b07b243b1654f04dcd490f716012a0;hp=008fe5f4ec99745f5e52b9c196618e5d7941cdeb;p=mdsal.git BUG-2825: introduce Ipv4 prefix parser for short bytes BGP uses a short encoding schema, where they have only partial byte array. Add support for parsing such short byte arrays, padding the tail with zeros. Change-Id: Ib4ce202256d26b1cbee23e05320d8cef6f729257 Signed-off-by: Robert Varga --- diff --git a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/StringValueObjectFactory.java b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/StringValueObjectFactory.java index 8cf66c2512..0955681442 100644 --- a/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/StringValueObjectFactory.java +++ b/binding/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/StringValueObjectFactory.java @@ -41,9 +41,11 @@ public final class StringValueObjectFactory { private final MethodHandle constructor; private final MethodHandle setter; + private final T template; - private StringValueObjectFactory(final MethodHandle constructor, final MethodHandle setter) { - this.constructor = Preconditions.checkNotNull(constructor); + private StringValueObjectFactory(final T template, final MethodHandle constructor, final MethodHandle setter) { + this.template = Preconditions.checkNotNull(template); + this.constructor = constructor.bindTo(template); this.setter = Preconditions.checkNotNull(setter); } @@ -80,8 +82,8 @@ public final class StringValueObjectFactory { final StringValueObjectFactory ret; try { - ret = new StringValueObjectFactory<>( - LOOKUP.unreflectConstructor(copyConstructor).asType(CONSTRUCTOR_METHOD_TYPE).bindTo(template), + ret = new StringValueObjectFactory<>(template, + LOOKUP.unreflectConstructor(copyConstructor).asType(CONSTRUCTOR_METHOD_TYPE), LOOKUP.unreflectSetter(f).asType(SETTER_METHOD_TYPE)); } catch (IllegalAccessException e) { throw new IllegalStateException("Failed to instantiate method handles", e); @@ -123,4 +125,8 @@ public final class StringValueObjectFactory { throw Throwables.propagate(e); } } + + public T getTemplate() { + return template; + } } diff --git a/model/ietf/ietf-type-util/src/main/java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfInetUtil.java b/model/ietf/ietf-type-util/src/main/java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfInetUtil.java index 2b30e13033..65f9f27ba6 100644 --- a/model/ietf/ietf-type-util/src/main/java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfInetUtil.java +++ b/model/ietf/ietf-type-util/src/main/java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfInetUtil.java @@ -138,6 +138,24 @@ public abstract class AbstractIetfInetUtil { return prefix4Factory.newInstance(prefixStringV4(address, mask)); } + @Nonnull public final P4 ipv4PrefixForShort(@Nonnull final byte[] address, final int mask) { + if (mask == 0) { + // Easy case, reuse the template + return prefix4Factory.getTemplate(); + } + + return v4PrefixForShort(address, 0, (mask / Byte.SIZE) + ((mask % Byte.SIZE == 0) ? 0 : 1), mask); + } + + @Nonnull public final P4 ipv4PrefixForShort(@Nonnull final byte[] array, final int startOffset, final int mask) { + if (mask == 0) { + // Easy case, reuse the template + return prefix4Factory.getTemplate(); + } + + return v4PrefixForShort(array, startOffset, (mask / Byte.SIZE) + ((mask % Byte.SIZE == 0) ? 0 : 1), mask); + } + /** * Create a /32 Ipv4Prefix for an {@link Inet4Address} * @@ -261,6 +279,25 @@ public abstract class AbstractIetfInetUtil { return prefix6Factory.newInstance(addressStringV6(address) + '/' + mask); } + @Nonnull public final P6 ipv6PrefixForShort(@Nonnull final byte[] address, final int mask) { + return ipv6PrefixForShort(address, 0, mask); + } + + @Nonnull public final P6 ipv6PrefixForShort(@Nonnull final byte[] array, final int startOffset, final int mask) { + if (mask == 0) { + // Easy case, reuse the template + return prefix6Factory.getTemplate(); + } + + Preconditions.checkArgument(mask > 0 && mask <= 128, "Invalid mask %s", mask); + final int size = (mask / Byte.SIZE) + ((mask % Byte.SIZE == 0) ? 0 : 1); + + // Until we can instantiate an IPv6 address for a partial array, use a temporary buffer + byte[] tmp = new byte[INET6_LENGTH]; + System.arraycopy(array, startOffset, tmp, 0, size); + return ipv6PrefixFor(tmp, mask); + } + /** * Create a /128 Ipv6Prefix by interpreting input bytes as an IPv4 address. * @@ -372,4 +409,33 @@ public abstract class AbstractIetfInetUtil { sb.append(mask); return sb.toString(); } + + private P4 v4PrefixForShort(@Nonnull final byte[] array, final int startOffset, final int size, final int mask) { + if (startOffset == 0 && size == INET4_LENGTH && array.length == INET4_LENGTH) { + // Easy case, fall back to non-short + return ipv4PrefixFor(array, mask); + } + + final StringBuilder sb = new StringBuilder(18); + + // Add from address + sb.append(Byte.toUnsignedInt(array[startOffset])); + for (int i = 1; i < size; i++) { + sb.append('.'); + sb.append(Byte.toUnsignedInt(array[startOffset + i])); + } + + // Add zeros + for (int i = size; i < INET4_LENGTH; i++) { + sb.append('.'); + sb.append(0); + } + + // Add mask + Preconditions.checkArgument(mask > 0 && mask <= 32, "Invalid mask %s", mask); + sb.append('/'); + sb.append(mask); + + return prefix4Factory.newInstance(sb.toString()); + } }