/* * Copyright (c) 2016 Cisco and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.fd.hc2vpp.common.translate.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.net.InetAddresses; import io.fd.jvpp.core.types.Address; import io.fd.jvpp.core.types.AddressFamily; import io.fd.jvpp.core.types.AddressUnion; import io.fd.jvpp.core.types.Ip6Address; import io.fd.jvpp.core.types.Prefix; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil; 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.IpAddressNoZone; 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.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; /** * Trait providing logic for translation of ipv6-related data */ public interface Ipv6Translator extends ByteDataTranslator { /** * 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 */ default byte[] ipv6AddressNoZoneToArray(@Nonnull final Ipv6Address address) { return InetAddresses.forString(address.getValue()).getAddress(); } /** * Transform Ipv6 address to a Address acceptable by VPP. * * @param address {@link Ipv6Address} to be translated * @return Vpp {@link Address} from Ipv6 address */ default Address ipv6AddressToAddress(@Nonnull final Ipv6Address address) { Address addr = new Address(); addr.af = AddressFamily.ADDRESS_IP6; Ip6Address ip6Address = new Ip6Address(); ip6Address.ip6Address = ipv6AddressNoZoneToArray(address); addr.un = new AddressUnion(ip6Address); return addr; } /** * Creates address array from address part of {@link Ipv6Prefix} * * @return Ipv6 address as byte array */ default byte[] ipv6AddressPrefixToArray(@Nonnull final Ipv6Prefix ipv6Prefix) { checkNotNull(ipv6Prefix, "Cannot convert null prefix"); return ipv6AddressNoZoneToArray(new Ipv6AddressNoZone( new Ipv6Address(ipv6Prefix.getValue().substring(0, ipv6Prefix.getValue().indexOf('/'))))); } /** * Creates {@link io.fd.jvpp.nat.types.Ip6Address} from address part of {@link Ipv6Prefix} * * @return {@link io.fd.jvpp.nat.types.Ip6Address} */ default io.fd.jvpp.nat.types.Ip6Address ipv6AddressPrefixToNatIp6Address(@Nonnull final Ipv6Prefix ipv6Prefix) { checkNotNull(ipv6Prefix, "Cannot convert null prefix"); io.fd.jvpp.nat.types.Ip6Address ip6Address = new io.fd.jvpp.nat.types.Ip6Address(); ip6Address.ip6Address = ipv6AddressPrefixToArray(ipv6Prefix); return ip6Address; } /** * Transforms {@link Prefix} from {@link Ipv6Prefix} * @param ipv6Prefix prefix to be translated * @return Vpp {@link Prefix} from {@link Ipv6Prefix} */ default Prefix ipv6AddressPrefixToPrefix(@Nonnull final Ipv6Prefix ipv6Prefix) { checkNotNull(ipv6Prefix, "Cannot convert null prefix"); Prefix prefix = new Prefix(); prefix.address = new Address(); prefix.address.af = AddressFamily.ADDRESS_IP6; Ip6Address ip6Address = new Ip6Address(); ip6Address.ip6Address = ipv6AddressPrefixToArray(ipv6Prefix); prefix.address.un = new AddressUnion(ip6Address); prefix.addressLength = extractPrefix(ipv6Prefix); return prefix; } /** * Creates {@link io.fd.jvpp.nat.types.Ip6Prefix} from {@link Ipv6Prefix} * * @param ipv6Prefix prefix to be translated * @return Vpp {@link io.fd.jvpp.nat.types.Ip6Prefix} from {@link Ipv6Prefix} */ default io.fd.jvpp.nat.types.Ip6Prefix ipv6AddressPrefixToNatIp6Prefix(@Nonnull final Ipv6Prefix ipv6Prefix) { checkNotNull(ipv6Prefix, "Cannot convert null prefix"); io.fd.jvpp.nat.types.Ip6Prefix prefix = new io.fd.jvpp.nat.types.Ip6Prefix(); prefix.prefix = new io.fd.jvpp.nat.types.Ip6Address(); prefix.prefix.ip6Address = ipv6AddressPrefixToArray(ipv6Prefix); prefix.len = extractPrefix(ipv6Prefix); return prefix; } /** * Extracts {@link Ipv6Prefix} prefix */ default byte extractPrefix(Ipv6Prefix data) { checkNotNull(data, "Cannot extract from null"); return Integer.valueOf(data.getValue().substring(data.getValue().indexOf('/') + 1)).byteValue(); } /** * Converts byte array to {@link Ipv6Prefix} with specified prefixLength */ default Ipv6Prefix toIpv6Prefix(final byte[] address, int prefix) { return IetfInetUtil.INSTANCE.ipv6PrefixFor(address, prefix); } /** * Parse byte array returned by VPP representing an Ipv6 address. Expects array in non-reversed order * * @return Ipv6ddressNoZone containing string representation of IPv6 address constructed from submitted bytes. No * change in order. */ @Nonnull default Ipv6AddressNoZone arrayToIpv6AddressNoZone(@Nonnull byte[] ip) { checkArgument(ip.length == 16, "Illegal array length"); return new Ipv6AddressNoZone(IetfInetUtil.INSTANCE.ipv6AddressFor(ip)); } /** * Detects whether {@code IpAddress} is ipv6 */ default boolean isIpv6(@Nonnull final IpAddress address) { checkState(!(address.getIpv4Address() == null && address.getIpv6Address() == null), "Invalid address"); return address.getIpv6Address() != null; } /** * Detects whether {@code IpAddressZone} is ipv6 */ default boolean isIpv6(@Nonnull final IpAddressNoZone address) { checkState(!(address.getIpv4AddressNoZone() == null && address.getIpv6AddressNoZone() == null), "Invalid address"); return address.getIpv6AddressNoZone() != null; } /** * Detects whether {@code IpPrefix} is ipv6 */ default boolean isIpv6(@Nonnull final IpPrefix address) { checkState(!(address.getIpv4Prefix() == null && address.getIpv6Prefix() == null), "Invalid address"); return address.getIpv6Prefix() != null; } /** * Sets correct length of ip4 array in case vpp returns array of length greater than 4. * @param ip array to be truncated * @return ip array of length 4 */ default byte[] truncateIp4Array(final byte[] ip) { // 16, which causes problems for toIpv4Prefix final byte[] result = new byte[4]; System.arraycopy(ip, 0, result, 0, 4); return result; } }