Update MRI projects for Aluminium
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / util / AddressNormalizationUtil.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.openflowplugin.impl.util;
9
10 import java.net.InetAddress;
11 import java.net.UnknownHostException;
12 import java.util.Locale;
13 import org.eclipse.jdt.annotation.Nullable;
14 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
15 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.IpConversionUtil;
16 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
17 import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask;
27 import org.opendaylight.yangtools.yang.common.Uint32;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Utility class used for converting OpenFlow port numbers, Ipv4 and Ipv6 addresses to normalized format.
33  */
34 public final class AddressNormalizationUtil {
35     private static final Logger LOG = LoggerFactory.getLogger(AddressNormalizationUtil.class);
36
37     private static final String NO_ETH_MASK = "ff:ff:ff:ff:ff:ff";
38     private static final String PREFIX_SEPARATOR = "/";
39
40     private AddressNormalizationUtil() {
41     }
42
43     /**
44      * Extract port number from URI and convert it to OpenFlow specific textual representation.
45      *
46      * @param port            the OpenFlow port
47      * @param protocolVersion the OpenFLow protocol version
48      * @return normalized uri
49      */
50     public static @Nullable Uri normalizeProtocolAgnosticPort(@Nullable final Uri port, final short protocolVersion) {
51         if (port == null) {
52             return null;
53         }
54
55         Uint32 portValue = InventoryDataServiceUtil
56                 .portNumberfromNodeConnectorId(OpenflowVersion.get(protocolVersion), port.getValue());
57
58         return portValue == null ? null : OpenflowPortsUtil.getProtocolAgnosticPortUri(protocolVersion, portValue);
59     }
60
61     /**
62      * Normalize Ipv6 address with prefix mask (ex. 1234:5678:9ABC::/76) and apply prefix mask to Ipv6 address.
63      *
64      * @param ipv6Prefix the Ipv6 prefix
65      * @return normalized Ipv6 prefix
66      */
67     public static @Nullable Ipv6Prefix normalizeIpv6Prefix(@Nullable final Ipv6Prefix ipv6Prefix) {
68         if (ipv6Prefix == null) {
69             return null;
70         }
71
72         final byte[] address = IetfInetUtil.INSTANCE.ipv6AddressBytes(IpConversionUtil.extractIpv6Address(ipv6Prefix));
73         final byte[] mask =
74                 IpConversionUtil.convertIpv6PrefixToByteArray(IpConversionUtil.extractIpv6Prefix(ipv6Prefix));
75         return normalizeIpv6Address(address, mask);
76     }
77
78     /**
79      * Normalize Ipv6 address and arbitrary mask and apply arbitrary mask to Ipv6 address.
80      *
81      * @param ipv6Address the Ipv4 address
82      * @param ipv4Mask    the Ipv4 mask
83      * @return normalized Ipv6 prefix
84      */
85     public static @Nullable Ipv6Prefix normalizeIpv6Arbitrary(@Nullable final Ipv6Address ipv6Address,
86                                                               @Nullable final Ipv6ArbitraryMask ipv4Mask) {
87         if (ipv6Address == null) {
88             return null;
89         }
90
91         final byte[] address = IetfInetUtil.INSTANCE.ipv6AddressBytes(ipv6Address);
92         final byte[] mask = IpConversionUtil.convertIpv6ArbitraryMaskToByteArray(ipv4Mask);
93         return normalizeIpv6Address(address, mask);
94     }
95
96     /**
97      * Normalize ipv 6 address without mask.
98      *
99      * @param ipv6Address the Ipv6 address
100      * @return normalized Ipv6 address
101      */
102     public static @Nullable Ipv6Address normalizeIpv6AddressWithoutMask(@Nullable final Ipv6Address ipv6Address) {
103         final Ipv6Prefix ipv6Prefix = normalizeIpv6Arbitrary(ipv6Address, null);
104         return ipv6Prefix == null ? null : new Ipv6Address(ipv6Prefix.getValue().split(PREFIX_SEPARATOR)[0]);
105     }
106
107     /**
108      * Normalize Ipv4 address with prefix mask (ex. 192.168.0.1/24) and apply prefix mask to Ipv4 address.
109      *
110      * @param ipv4Prefix the Ipv4 prefix
111      * @return normalized Ipv4 prefix
112      */
113     public static @Nullable Ipv4Prefix normalizeIpv4Prefix(@Nullable final Ipv4Prefix ipv4Prefix) {
114         if (ipv4Prefix == null) {
115             return null;
116         }
117
118         final byte[] address = IetfInetUtil.INSTANCE.ipv4AddressBytes(IpConversionUtil.extractIpv4Address(ipv4Prefix));
119         final byte[] mask =
120                 IpConversionUtil.convertArbitraryMaskToByteArray(IpConversionUtil.extractIpv4AddressMask(ipv4Prefix));
121         return normalizeIpv4Address(address, mask);
122     }
123
124     /**
125      * Normalize Ipv4 address and arbitrary mask and apply arbitrary mask to Ipv4 address.
126      *
127      * @param ipv4Address the Ipv4 address
128      * @param ipv4Mask    the Ipv4 mask
129      * @return normalized Ipv4 prefix
130      */
131     public static @Nullable Ipv4Prefix normalizeIpv4Arbitrary(@Nullable final Ipv4Address ipv4Address,
132                                                               @Nullable final DottedQuad ipv4Mask) {
133         if (ipv4Address == null) {
134             return null;
135         }
136
137         final byte[] address = IetfInetUtil.INSTANCE.ipv4AddressBytes(ipv4Address);
138         final byte[] mask = IpConversionUtil.convertArbitraryMaskToByteArray(ipv4Mask);
139         return normalizeIpv4Address(address, mask);
140     }
141
142     /**
143      * Normalize Ipv4 address and arbitrary mask in byte array format and apply arbitrary mask to Ipv4 address.
144      *
145      * @param address Ipv4 address byte array
146      * @param mask    Ipv4 mask byte array
147      * @return normalized Ipv4 prefix
148      */
149     public static @Nullable Ipv4Prefix normalizeIpv4Address(final byte @Nullable [] address,
150                                                             final byte @Nullable [] mask) {
151         final String addressPrefix = normalizeInetAddressWithMask(normalizeIpAddress(address, mask), mask);
152
153         if (addressPrefix == null) {
154             return null;
155         }
156
157         return new Ipv4Prefix(addressPrefix);
158     }
159
160
161     /**
162      * Normalize Ipv6 address and arbitrary mask in byte array format and apply arbitrary mask to Ipv6 address.
163      *
164      * @param address Ipv6 address byte array
165      * @param mask    Ipv6 mask byte array
166      * @return normalized Ipv6 prefix
167      */
168     public static @Nullable Ipv6Prefix normalizeIpv6Address(final byte @Nullable [] address,
169                                                             final byte @Nullable [] mask) {
170         final String addressPrefix = normalizeInetAddressWithMask(normalizeIpAddress(address, mask), mask);
171
172         if (addressPrefix == null) {
173             return null;
174         }
175
176         return new Ipv6Prefix(addressPrefix);
177     }
178
179     /**
180      * Normalize generic IP address and arbitrary mask in byte array format and apply arbitrary mask to IP address.
181      *
182      * @param address address byte array
183      * @param mask    mask byte array
184      * @return normalized Inet address
185      */
186     public static @Nullable InetAddress normalizeIpAddress(final byte @Nullable [] address,
187                                                            final byte @Nullable [] mask) {
188         if (address == null) {
189             return null;
190         }
191
192         final byte[] result = new byte[address.length];
193
194         for (int i = 0; i < address.length; i++) {
195             result[i] = mask != null ? (byte) (address[i] & mask[i]) : address[i];
196         }
197
198         try {
199             return InetAddress.getByAddress(result);
200         } catch (UnknownHostException e) {
201             LOG.warn("Failed to recognize the host while normalizing IP address from bytes ", e);
202             return null;
203         }
204     }
205
206     /**
207      * Convert arbitrary mask to prefix mask and append it to textual representation of Inet address.
208      *
209      * @param address the address
210      * @param mask    the mask
211      * @return the string
212      */
213     public static @Nullable String normalizeInetAddressWithMask(final @Nullable InetAddress address,
214                                                                 final byte @Nullable [] mask) {
215         if (address == null) {
216             return null;
217         }
218
219         return address.getHostAddress()
220                 + (mask == null ? "" : PREFIX_SEPARATOR + String.valueOf(IpConversionUtil.countBits(mask)));
221     }
222
223     /**
224      * Convert MAC address to it's lower case format.
225      *
226      * @param macAddress the MAC address
227      * @return normalized MAC address
228      */
229     @Nullable
230     public static MacAddress normalizeMacAddress(@Nullable final MacAddress macAddress) {
231         return macAddress == null ? null : new MacAddress(macAddress.getValue().toLowerCase(Locale.ROOT));
232     }
233
234     /**
235      * Convert MAC address mask to it's lower case format and if it is full F mask, return null.
236      *
237      * @param macAddress the MAC address
238      * @return normalized MAC address
239      */
240     @Nullable
241     public static MacAddress normalizeMacAddressMask(@Nullable final MacAddress macAddress) {
242         final MacAddress normalizedMacAddress = normalizeMacAddress(macAddress);
243
244         if (normalizedMacAddress == null) {
245             return null;
246         }
247
248         if (NO_ETH_MASK.equals(normalizedMacAddress.getValue())) {
249             return null;
250         }
251
252         return normalizedMacAddress;
253     }
254 }