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