HONEYCOMB-58 - Routing Api
[honeycomb.git] / vpp-common / vpp-translate-utils / src / main / java / io / fd / honeycomb / translate / vpp / util / Ipv4Translator.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.fd.honeycomb.translate.vpp.util;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20
21 import com.google.common.net.InetAddresses;
22 import java.net.UnknownHostException;
23 import java.util.Arrays;
24 import javax.annotation.Nonnull;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
27
28 /**
29  * Trait providing logic for translation of ipv4-related data.
30  */
31 public interface Ipv4Translator extends ByteDataTranslator {
32
33     /**
34      * Make available also from static context.
35      */
36     Ipv4Translator INSTANCE = new Ipv4Translator() {};
37
38     /**
39      * Creates address array from address part of {@link Ipv4Prefix}
40      */
41     default byte[] ipv4AddressPrefixToArray(@Nonnull final Ipv4Prefix ipv4Prefix) {
42         checkNotNull(ipv4Prefix, "Cannot convert null prefix");
43
44         byte[] retval = new byte[4];
45         String[] address = ipv4Prefix.getValue().substring(0, ipv4Prefix.getValue().indexOf('/')).split("\\.");
46
47         for (int d = 0; d < 4; d++) {
48             retval[d] = (byte) (Short.parseShort(address[d]) & 0xff);
49         }
50         return retval;
51     }
52
53     /**
54      * Extracts {@link Ipv4Prefix} prefix
55      */
56     default byte extractPrefix(Ipv4Prefix data) {
57         checkNotNull(data, "Cannot extract from null");
58
59         return Byte.valueOf(data.getValue().substring(data.getValue().indexOf('/') + 1));
60     }
61
62     /**
63      * Converts byte array to {@link Ipv4Prefix} with specified prefixLength
64      */
65     default Ipv4Prefix arrayToIpv4Prefix(final byte[] address, byte prefixLength) {
66         Ipv4AddressNoZone addressPart = arrayToIpv4AddressNoZone(address);
67
68         return new Ipv4Prefix(addressPart.getValue().concat("/").concat(String.valueOf(prefixLength)));
69     }
70
71     /**
72      * Parse byte array returned by VPP representing an Ipv4 address. Vpp returns IP byte arrays in reversed order.
73      *
74      * @return Ipv4AddressNoZone containing string representation of IPv4 address constructed from submitted bytes. No
75      * change in order.
76      */
77     @Nonnull
78     default Ipv4AddressNoZone arrayToIpv4AddressNoZone(@Nonnull byte[] ip) {
79         // VPP sends ipv4 in a 16 byte array
80         if (ip.length == 16) {
81             ip = Arrays.copyOfRange(ip, 0, 4);
82         }
83         try {
84             // Not reversing the byte array here!! because the IP coming from VPP is in reversed byte order
85             // compared to byte order it was submitted
86             return new Ipv4AddressNoZone(InetAddresses.toAddrString(InetAddresses.fromLittleEndianByteArray(ip)));
87         } catch (UnknownHostException e) {
88             throw new IllegalArgumentException("Unable to parse ipv4", e);
89         }
90     }
91
92     /**
93      * Parse byte array returned by VPP representing an Ipv4 address. Vpp returns IP byte arrays in reversed order.
94      *
95      * @return Ipv4AddressNoZone containing string representation of IPv4 address constructed from submitted bytes. No
96      * change in order.
97      */
98     @Nonnull
99     default Ipv4AddressNoZone arrayToIpv4AddressNoZoneReversed(@Nonnull byte[] ip) {
100         // VPP sends ipv4 in a 16 byte array
101
102         if (ip.length == 16) {
103             ip = Arrays.copyOfRange(ip, 0, 4);
104         }
105
106         ip = reverseBytes(ip);
107
108         try {
109             // Not reversing the byte array here!! because the IP coming from VPP is in reversed byte order
110             // compared to byte order it was submitted
111             return new Ipv4AddressNoZone(InetAddresses.toAddrString(InetAddresses.fromLittleEndianByteArray(ip)));
112         } catch (UnknownHostException e) {
113             throw new IllegalArgumentException("Unable to parse ipv4", e);
114         }
115     }
116
117
118     /**
119      * Transform Ipv4 address to a byte array acceptable by VPP. VPP expects incoming byte array to be in the same order
120      * as the address.
121      *
122      * @return byte array with address bytes
123      */
124     default byte[] ipv4AddressNoZoneToArray(final Ipv4AddressNoZone ipv4Addr) {
125         return ipv4AddressNoZoneToArray(ipv4Addr.getValue());
126     }
127
128     default byte[] ipv4AddressNoZoneToArray(final String ipv4Addr) {
129         byte[] retval = new byte[4];
130         String[] dots = ipv4Addr.split("\\.");
131
132         for (int d = 0; d < 4; d++) {
133             retval[d] = (byte) (Short.parseShort(dots[d]) & 0xff);
134         }
135         return retval;
136     }
137 }