29b9d1cd52810f9e25e7231962ee74f6a00ee4e8
[bgpcep.git] / util / src / main / java / org / opendaylight / protocol / util / Ipv6Util.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.util;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.net.InetAddresses;
13 import io.netty.buffer.ByteBuf;
14 import io.netty.buffer.Unpooled;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.List;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
22
23 /**
24  * Util class for creating generated Ipv6Address.
25  */
26 public final class Ipv6Util {
27     public static final int IPV6_LENGTH = 16;
28     public static final int IPV6_BITS_LENGTH = 128;
29
30     static final int PREFIX_BYTE_LENGTH = IPV6_LENGTH + 1;
31
32     private static final Ipv6Prefix EMPTY_PREFIX = new Ipv6Prefix("::/0");
33
34     private Ipv6Util() {
35         // Hidden on purpose
36     }
37
38     /**
39      * Creates uncompressed IP Address.
40      *
41      * @param ip to be uncompressed
42      * @return Ipv6Address with same, but uncompressed, value
43      */
44     public static Ipv6AddressNoZone getFullForm(final Ipv6AddressNoZone ip) {
45         return new Ipv6AddressNoZone(InetAddresses.forString(ip.getValue()).getHostAddress());
46     }
47
48     /**
49      * Reads from ByteBuf buffer and converts bytes to Ipv6Address.
50      *
51      * @param buffer containing Ipv6 address, starting at reader index
52      * @return Ipv6Address
53      */
54     public static Ipv6AddressNoZone addressForByteBuf(final ByteBuf buffer) {
55         return IetfInetUtil.INSTANCE.ipv6AddressNoZoneFor(ByteArray.readBytes(buffer, IPV6_LENGTH));
56     }
57
58     /**
59      * From string ipAddress creates an InetAddress and puts it into ByteBuf.
60      * @param ipAddress Ipv6 address
61      * @return ByteBuf with filled in bytes from ipAddress
62      */
63     public static ByteBuf byteBufForAddress(final Ipv6AddressNoZone ipAddress) {
64         return Unpooled.wrappedBuffer(bytesForAddress(ipAddress));
65     }
66
67     /**
68      * Converts Ipv6Address to byte array.
69      *
70      * @param address Ipv6Address to be converted
71      * @return byte array
72      */
73     public static byte[] bytesForAddress(final Ipv6AddressNoZone address) {
74         return IetfInetUtil.INSTANCE.ipv6AddressNoZoneBytes(address);
75     }
76
77     /**
78      * Converts Ipv6Prefix to byte array. Prefix length at the end.
79      *
80      * @param prefix Ipv6Prefix to be converted
81      * @return byte array with prefix length at the end
82      */
83     public static byte[] bytesForPrefix(final Ipv6Prefix prefix) {
84         return IetfInetUtil.INSTANCE.ipv6PrefixToBytes(prefix);
85     }
86
87     /**
88      * Creates an Ipv6Prefix object from given byte array.
89      *
90      * @param bytes IPv6 address
91      * @param length prefix length
92      * @return Ipv6Prefix object
93      */
94     public static Ipv6Prefix prefixForBytes(final byte[] bytes, final int length) {
95         checkArgument(length <= bytes.length * Byte.SIZE);
96
97         final byte[] tmp;
98         if (bytes.length != IPV6_LENGTH) {
99             tmp = Arrays.copyOfRange(bytes, 0, IPV6_LENGTH);
100         } else {
101             tmp = bytes;
102         }
103
104         return IetfInetUtil.INSTANCE.ipv6PrefixFor(tmp, length);
105     }
106
107     /**
108      * Creates an Ipv6Prefix object from given ByteBuf. Prefix length is assumed to
109      * be in the left most byte of the buffer.
110      *
111      * @param buf IPv6 address
112      * @return Ipv6Prefix object
113      */
114     public static Ipv6Prefix prefixForByteBuf(final ByteBuf buf) {
115         final int prefixLength = buf.readUnsignedByte();
116         final int size = prefixLength / Byte.SIZE + (prefixLength % Byte.SIZE == 0 ? 0 : 1);
117         final int readable = buf.readableBytes();
118         checkArgument(size <= readable, "Illegal length of IP prefix: %s/%s", size, readable);
119
120         final byte[] bytes = new byte[IPV6_LENGTH];
121         buf.readBytes(bytes, 0, size);
122         return IetfInetUtil.INSTANCE.ipv6PrefixFor(bytes, prefixLength);
123     }
124
125     /**
126      * Creates a list of Ipv6 Prefixes from given byte array.
127      *
128      * @param bytes to be converted to List of Ipv6Prefixes.
129      * @return A List of Ipv6Prefixes
130      */
131     public static List<Ipv6Prefix> prefixListForBytes(final byte[] bytes) {
132         if (bytes.length == 0) {
133             return Collections.emptyList();
134         }
135         final List<Ipv6Prefix> list = new ArrayList<>();
136         int byteOffset = 0;
137         while (byteOffset < bytes.length) {
138             final int bitLength = Byte.toUnsignedInt(bytes[byteOffset]);
139             byteOffset += 1;
140             // if length == 0, default route will be added
141             if (bitLength == 0) {
142                 list.add(EMPTY_PREFIX);
143                 continue;
144             }
145             list.add(IetfInetUtil.INSTANCE.ipv6PrefixForShort(bytes, byteOffset, bitLength));
146             byteOffset += bitLength / Byte.SIZE;
147             if (bitLength % Byte.SIZE != 0) {
148                 byteOffset++;
149             }
150         }
151         return list;
152     }
153
154     /**
155      * Writes IPv6 address if not null, otherwise writes zeros to the
156      * <code>output</code> ByteBuf. ByteBuf's writerIndex is increased by 16.
157      *
158      * @param ipv6Address
159      *            IPv6 address to be written to the output.
160      * @param output
161      *            ByteBuf, where ipv6Address or zeros are written.
162      */
163     public static void writeIpv6Address(final Ipv6AddressNoZone ipv6Address, final ByteBuf output) {
164         if (ipv6Address != null) {
165             output.writeBytes(IetfInetUtil.INSTANCE.ipv6AddressNoZoneBytes(ipv6Address));
166         } else {
167             output.writeZero(IPV6_LENGTH);
168         }
169     }
170
171     /**
172      * Writes IPv6 prefix if not null, otherwise writes zeros to the
173      * <code>output</code> ByteBuf. ByteBuf's writerIndex is increased by 17.
174      *
175      * @param ipv6Prefix
176      *            IPv6 prefix to be written to the output. Prefix is written in
177      *            the last byte.
178      * @param output
179      *            ByteBuf, where ipv6Prefix or zeros are written.
180      */
181     public static void writeIpv6Prefix(final Ipv6Prefix ipv6Prefix, final ByteBuf output) {
182         if (ipv6Prefix != null) {
183             output.writeBytes(bytesForPrefix(ipv6Prefix));
184         } else {
185             output.writeZero(PREFIX_BYTE_LENGTH);
186         }
187     }
188
189     public static void writeMinimalPrefix(final Ipv6Prefix ipv6Prefix, final ByteBuf output) {
190         final byte[] bytes = IetfInetUtil.INSTANCE.ipv6PrefixToBytes(ipv6Prefix);
191         Ipv4Util.writeMinimalPrefix(output, bytes, bytes[IPV6_LENGTH]);
192     }
193 }