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