15681a1a6f9dc7bfdf3c3e5dd8551ebe8d9d5532
[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     @Nullable
51     public static Uri normalizeProtocolAgnosticPort(@Nullable final Uri port, final short protocolVersion) {
52         if (port == null) {
53             return null;
54         }
55
56         Uint32 portValue = InventoryDataServiceUtil
57                 .portNumberfromNodeConnectorId(OpenflowVersion.get(protocolVersion), port.getValue());
58
59         return portValue == null ? null : OpenflowPortsUtil.getProtocolAgnosticPortUri(protocolVersion, portValue);
60     }
61
62     /**
63      * Normalize Ipv6 address with prefix mask (ex. 1234:5678:9ABC::/76) and apply prefix mask to Ipv6 address.
64      *
65      * @param ipv6Prefix the Ipv6 prefix
66      * @return normalized Ipv6 prefix
67      */
68     @Nullable
69     public static Ipv6Prefix normalizeIpv6Prefix(@Nullable final Ipv6Prefix ipv6Prefix) {
70         if (ipv6Prefix == null) {
71             return null;
72         }
73
74         final byte[] address = IetfInetUtil.INSTANCE.ipv6AddressBytes(IpConversionUtil.extractIpv6Address(ipv6Prefix));
75         final byte[] mask =
76                 IpConversionUtil.convertIpv6PrefixToByteArray(IpConversionUtil.extractIpv6Prefix(ipv6Prefix));
77         return normalizeIpv6Address(address, mask);
78     }
79
80     /**
81      * Normalize Ipv6 address and arbitrary mask and apply arbitrary mask to Ipv6 address.
82      *
83      * @param ipv6Address the Ipv4 address
84      * @param ipv4Mask    the Ipv4 mask
85      * @return normalized Ipv6 prefix
86      */
87     @Nullable
88     public static Ipv6Prefix normalizeIpv6Arbitrary(@Nullable final Ipv6Address ipv6Address,
89                                                     @Nullable final Ipv6ArbitraryMask ipv4Mask) {
90         if (ipv6Address == null) {
91             return null;
92         }
93
94         final byte[] address = IetfInetUtil.INSTANCE.ipv6AddressBytes(ipv6Address);
95         final byte[] mask = IpConversionUtil.convertIpv6ArbitraryMaskToByteArray(ipv4Mask);
96         return normalizeIpv6Address(address, mask);
97     }
98
99     /**
100      * Normalize ipv 6 address without mask.
101      *
102      * @param ipv6Address the Ipv6 address
103      * @return normalized Ipv6 address
104      */
105     @Nullable
106     public static Ipv6Address normalizeIpv6AddressWithoutMask(@Nullable final Ipv6Address ipv6Address) {
107         final Ipv6Prefix ipv6Prefix = normalizeIpv6Arbitrary(ipv6Address, null);
108         return ipv6Prefix == null ? null : new Ipv6Address(ipv6Prefix.getValue().split(PREFIX_SEPARATOR)[0]);
109     }
110
111     /**
112      * Normalize Ipv4 address with prefix mask (ex. 192.168.0.1/24) and apply prefix mask to Ipv4 address.
113      *
114      * @param ipv4Prefix the Ipv4 prefix
115      * @return normalized Ipv4 prefix
116      */
117     @Nullable
118     public static Ipv4Prefix normalizeIpv4Prefix(@Nullable final Ipv4Prefix ipv4Prefix) {
119         if (ipv4Prefix == null) {
120             return null;
121         }
122
123         final byte[] address = IetfInetUtil.INSTANCE.ipv4AddressBytes(IpConversionUtil.extractIpv4Address(ipv4Prefix));
124         final byte[] mask =
125                 IpConversionUtil.convertArbitraryMaskToByteArray(IpConversionUtil.extractIpv4AddressMask(ipv4Prefix));
126         return normalizeIpv4Address(address, mask);
127     }
128
129     /**
130      * Normalize Ipv4 address and arbitrary mask and apply arbitrary mask to Ipv4 address.
131      *
132      * @param ipv4Address the Ipv4 address
133      * @param ipv4Mask    the Ipv4 mask
134      * @return normalized Ipv4 prefix
135      */
136     @Nullable
137     public static Ipv4Prefix normalizeIpv4Arbitrary(@Nullable final Ipv4Address ipv4Address,
138                                                     @Nullable final DottedQuad ipv4Mask) {
139         if (ipv4Address == null) {
140             return null;
141         }
142
143         final byte[] address = IetfInetUtil.INSTANCE.ipv4AddressBytes(ipv4Address);
144         final byte[] mask = IpConversionUtil.convertArbitraryMaskToByteArray(ipv4Mask);
145         return normalizeIpv4Address(address, mask);
146     }
147
148     /**
149      * Normalize Ipv4 address and arbitrary mask in byte array format and apply arbitrary mask to Ipv4 address.
150      *
151      * @param address Ipv4 address byte array
152      * @param mask    Ipv4 mask byte array
153      * @return normalized Ipv4 prefix
154      */
155     @Nullable
156     public static Ipv4Prefix normalizeIpv4Address(@Nullable final byte[] address, @Nullable final byte[] mask) {
157         final String addressPrefix = normalizeInetAddressWithMask(normalizeIpAddress(address, mask), mask);
158
159         if (addressPrefix == null) {
160             return null;
161         }
162
163         return new Ipv4Prefix(addressPrefix);
164     }
165
166
167     /**
168      * Normalize Ipv6 address and arbitrary mask in byte array format and apply arbitrary mask to Ipv6 address.
169      *
170      * @param address Ipv6 address byte array
171      * @param mask    Ipv6 mask byte array
172      * @return normalized Ipv6 prefix
173      */
174     @Nullable
175     public static Ipv6Prefix normalizeIpv6Address(@Nullable final byte[] address, @Nullable final byte[] mask) {
176         final String addressPrefix = normalizeInetAddressWithMask(normalizeIpAddress(address, mask), mask);
177
178         if (addressPrefix == null) {
179             return null;
180         }
181
182         return new Ipv6Prefix(addressPrefix);
183     }
184
185     /**
186      * Normalize generic IP address and arbitrary mask in byte array format and apply arbitrary mask to IP address.
187      *
188      * @param address address byte array
189      * @param mask    mask byte array
190      * @return normalized Inet address
191      */
192     @Nullable
193     public static InetAddress normalizeIpAddress(@Nullable final byte[] address, @Nullable final byte[] mask) {
194         if (address == null) {
195             return null;
196         }
197
198         final byte[] result = new byte[address.length];
199
200         for (int i = 0; i < address.length; i++) {
201             result[i] = mask != null ? (byte) (address[i] & mask[i]) : address[i];
202         }
203
204         try {
205             return InetAddress.getByAddress(result);
206         } catch (UnknownHostException e) {
207             LOG.warn("Failed to recognize the host while normalizing IP address from bytes ", e);
208             return null;
209         }
210     }
211
212     /**
213      * Convert arbitrary mask to prefix mask and append it to textual representation of Inet address.
214      *
215      * @param address the address
216      * @param mask    the mask
217      * @return the string
218      */
219     @Nullable
220     public static String normalizeInetAddressWithMask(@Nullable final InetAddress address,
221                                                       @Nullable final byte[] mask) {
222         if (address == null) {
223             return null;
224         }
225
226         return address.getHostAddress()
227                 + (mask == null ? "" : PREFIX_SEPARATOR + String.valueOf(IpConversionUtil.countBits(mask)));
228     }
229
230     /**
231      * Convert MAC address to it's lower case format.
232      *
233      * @param macAddress the MAC address
234      * @return normalized MAC address
235      */
236     @Nullable
237     public static MacAddress normalizeMacAddress(@Nullable final MacAddress macAddress) {
238         return macAddress == null ? null : new MacAddress(macAddress.getValue().toLowerCase(Locale.ROOT));
239     }
240
241     /**
242      * Convert MAC address mask to it's lower case format and if it is full F mask, return null.
243      *
244      * @param macAddress the MAC address
245      * @return normalized MAC address
246      */
247     @Nullable
248     public static MacAddress normalizeMacAddressMask(@Nullable final MacAddress macAddress) {
249         final MacAddress normalizedMacAddress = normalizeMacAddress(macAddress);
250
251         if (normalizedMacAddress == null) {
252             return null;
253         }
254
255         if (NO_ETH_MASK.equals(normalizedMacAddress.getValue())) {
256             return null;
257         }
258
259         return normalizedMacAddress;
260     }
261 }