2 * Copyright (c) 2014, 2017 Contextream, Inc. and others. All rights reserved.
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
8 package org.opendaylight.lispflowmapping.lisp.util;
10 import com.google.common.base.Preconditions;
11 import com.google.common.net.InetAddresses;
12 import java.net.Inet4Address;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.net.UnknownHostException;
16 import java.nio.ByteBuffer;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.Address;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.InstanceId;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ServicePath;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.source.dest.key.SourceDestKeyBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv4Binary;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv4PrefixBinary;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv6Binary;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv6PrefixBinary;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 public final class MaskUtil {
38 private static final Logger LOG = LoggerFactory.getLogger(MaskUtil.class);
39 public static final short IPV4_MAX_MASK = 32;
40 public static final short IPV6_MAX_MASK = 128;
42 // Utility class, should not be instantiated
46 public static boolean isMaskable(Address address) {
47 if (address instanceof Ipv4Prefix || address instanceof Ipv6Prefix
48 || address instanceof Ipv4PrefixBinary || address instanceof Ipv6PrefixBinary
49 || address instanceof SourceDestKey) {
51 } else if (address instanceof InstanceId) {
52 return isMaskable(((InstanceId)address).getInstanceId().getAddress());
57 public static boolean isMaskable(SimpleAddress address) {
58 if (address.getIpPrefix() != null) {
64 private static int slashPosition(final String prefix) {
65 final int slash = prefix.lastIndexOf('/');
66 Preconditions.checkArgument(slash >= 0, "Argument %s does not contain a slash", prefix);
70 public static String getPrefixAddress(final String prefix) {
71 return prefix.substring(0, slashPosition(prefix));
74 public static String getPrefixMask(final String prefix) {
75 return prefix.substring(slashPosition(prefix) + 1);
78 private static String[] splitPrefix(final String prefix) {
79 final int slash = slashPosition(prefix);
80 return new String[] { prefix.substring(0, slash), prefix.substring(slash + 1) };
83 public static Eid normalize(Eid eid, short mask) {
84 Address address = eid.getAddress();
86 if (address instanceof Ipv4PrefixBinary) {
87 byte[] addr = ((Ipv4PrefixBinary) address).getIpv4AddressBinary().getValue();
88 return LispAddressUtil.asIpv4PrefixBinaryEid(eid, normalizeByteArray(addr, mask), mask);
89 } else if (address instanceof Ipv6PrefixBinary) {
90 byte[] addr = ((Ipv6PrefixBinary) address).getIpv6AddressBinary().getValue();
91 return LispAddressUtil.asIpv6PrefixBinaryEid(eid, normalizeByteArray(addr, mask), mask);
92 } else if (address instanceof Ipv4Prefix) {
93 final String addr = getPrefixAddress(((Ipv4Prefix)address).getIpv4Prefix().getValue());
94 InetAddress normalized = normalizeIP(InetAddresses.forString(addr), mask);
95 return LispAddressUtil.asIpv4PrefixEid(eid, (Inet4Address)normalized, mask);
96 } else if (address instanceof Ipv6Prefix) {
97 final String addr = getPrefixAddress(((Ipv6Prefix)address).getIpv6Prefix().getValue());
98 InetAddress normalized = normalizeIP(InetAddresses.forString(addr), mask);
99 return LispAddressUtil.asIpv6PrefixEid(eid, (Inet6Address)normalized, mask);
100 } else if (address instanceof InstanceId) {
101 // TODO - not absolutely necessary, but should be implemented
104 } catch (UnknownHostException e) {
105 LOG.warn("Failed to normalize EID {} with mask {}, returning original EID", eid, mask, e);
110 public static Eid normalize(Eid eid) {
111 Address address = eid.getAddress();
113 if (address instanceof Ipv4PrefixBinary) {
114 byte[] addr = ((Ipv4PrefixBinary) address).getIpv4AddressBinary().getValue();
115 short mask = ((Ipv4PrefixBinary) address).getIpv4MaskLength().toJava();
116 return LispAddressUtil.asIpv4PrefixBinaryEid(eid, normalizeByteArray(addr, mask), mask);
117 } else if (address instanceof Ipv6PrefixBinary) {
118 byte[] addr = ((Ipv6PrefixBinary) address).getIpv6AddressBinary().getValue();
119 short mask = ((Ipv6PrefixBinary) address).getIpv6MaskLength().toJava();
120 return LispAddressUtil.asIpv6PrefixBinaryEid(eid, normalizeByteArray(addr, mask), mask);
121 } else if (address instanceof Ipv4Prefix) {
122 String[] v4prefix = splitPrefix(((Ipv4Prefix)address).getIpv4Prefix().getValue());
123 short mask = Short.parseShort(v4prefix[1]);
124 InetAddress normalized = normalizeIP(InetAddresses.forString(v4prefix[0]), mask);
125 return LispAddressUtil.asIpv4PrefixEid(eid, (Inet4Address) normalized, mask);
126 } else if (address instanceof Ipv6Prefix) {
127 String[] v6prefix = splitPrefix(((Ipv6Prefix)address).getIpv6Prefix().getValue());
128 short mask = Short.parseShort(v6prefix[1]);
129 InetAddress normalized = normalizeIP(InetAddresses.forString(v6prefix[0]), mask);
130 return LispAddressUtil.asIpv6PrefixEid(eid, (Inet6Address) normalized, mask);
131 } else if (address instanceof Ipv4) {
132 return LispAddressUtil.asIpv4PrefixEid(((Ipv4) address).getIpv4(), eid.getVirtualNetworkId());
133 } else if (address instanceof Ipv6) {
134 return LispAddressUtil.asIpv6PrefixEid(((Ipv6) address).getIpv6(), eid.getVirtualNetworkId());
135 } else if (address instanceof InstanceId) {
136 // TODO - not absolutely necessary, but should be implemented
138 } else if (address instanceof SourceDestKey) {
139 return normalizeSrcDst(eid);
140 } else if (address instanceof ServicePath) {
141 // Build new Service Path eid with service index set to 0
142 long spi = ((ServicePath) address).getServicePath().getServicePathId().getValue().toJava();
143 long vni = eid.getVirtualNetworkId() != null ? eid.getVirtualNetworkId().getValue().toJava() : -1;
144 return LispAddressUtil.asServicePathEid(vni, spi, (short)0);
146 } catch (UnknownHostException e) {
147 LOG.warn("Failed to normalize EID {}, returning original", eid, e);
152 private static Eid normalizeSrcDst(Eid eid) throws UnknownHostException {
153 final SimpleAddress normalizedSrc = normalizeSimpleAddress(
154 ((SourceDestKey) eid.getAddress()).getSourceDestKey().getSource());
155 final SimpleAddress normalizedDst = normalizeSimpleAddress(
156 ((SourceDestKey) eid.getAddress()).getSourceDestKey().getDest());
157 return LispAddressUtil.asSrcDstEid(new SourceDestKeyBuilder()
158 .setSource(normalizedSrc).setDest(normalizedDst).build(), eid.getVirtualNetworkId());
161 private static SimpleAddress normalizeSimpleAddress(SimpleAddress address) throws UnknownHostException {
162 if (address.getIpPrefix() == null) {
165 return new SimpleAddress(normalizeIpPrefix(address.getIpPrefix()));
168 private static IpPrefix normalizeIpPrefix(IpPrefix address) throws UnknownHostException {
169 String[] prefix = splitPrefix(address.stringValue());
170 short mask = Short.parseShort(prefix[1]);
172 InetAddress normalizedAddress = normalizeIP(InetAddresses.forString(prefix[0]), mask);
173 return IetfInetUtil.INSTANCE.ipPrefixFor(normalizedAddress.getAddress(), mask);
176 private static InetAddress normalizeIP(InetAddress address, int maskLength) throws UnknownHostException {
177 return InetAddress.getByAddress(normalizeByteArray(address.getAddress(), (short) maskLength));
180 public static byte[] normalizeByteArray(byte[] address, short maskLength) {
181 ByteBuffer byteRepresentation = ByteBuffer.wrap(address);
182 byte byteMask = (byte) 0xff;
183 int mask = maskLength;
184 for (int i = 0; i < byteRepresentation.array().length; i++) {
186 byteRepresentation.put(i, (byte) (byteMask & byteRepresentation.get(i)));
187 } else if (mask > 0) {
188 byteRepresentation.put(i, (byte) ((byte) (byteMask << (8 - mask)) & byteRepresentation.get(i)));
190 byteRepresentation.put(i, (byte) (0 & byteRepresentation.get(i)));
195 return byteRepresentation.array();
198 public static int getMaxMask(Address address) {
199 if (address instanceof Ipv4 || address instanceof Ipv4Prefix || address instanceof Ipv4Binary
200 || address instanceof Ipv4PrefixBinary) {
201 return IPV4_MAX_MASK;
202 } else if (address instanceof Ipv6 || address instanceof Ipv6Prefix || address instanceof Ipv4Binary
203 || address instanceof Ipv6PrefixBinary) {
204 return IPV6_MAX_MASK;
210 private static String getIpPrefixString(IpPrefix prefix) {
211 if (prefix.getIpv4Prefix() != null) {
212 return prefix.getIpv4Prefix().getValue();
213 } else if (prefix.getIpv6Prefix() != null) {
214 return prefix.getIpv6Prefix().getValue();
216 throw new IllegalArgumentException("Invalid prefix " + prefix);
220 public static short getMaskForIpPrefix(IpPrefix prefix) {
221 return Short.parseShort(getPrefixMask(getIpPrefixString(prefix)));
224 public static String getAddressStringForIpPrefix(IpPrefix prefix) {
225 return getPrefixAddress(getIpPrefixString(prefix));
228 public static String getAddressStringForIpv4Prefix(Ipv4Prefix prefix) {
229 return getPrefixAddress(prefix.getIpv4Prefix().getValue());
232 public static String getAddressStringForIpv6Prefix(Ipv6Prefix prefix) {
233 return getPrefixAddress(prefix.getIpv6Prefix().getValue());
236 public static short getMaskForAddress(SimpleAddress address) {
237 if (address.getIpPrefix() == null) {
240 return getMaskForIpPrefix(address.getIpPrefix());
243 public static short getMaskForAddress(Address address) {
244 if (address instanceof Ipv4) {
245 return IPV4_MAX_MASK;
246 } else if (address instanceof Ipv6) {
247 return IPV6_MAX_MASK;
248 } else if (address instanceof Ipv4Binary) {
249 return IPV4_MAX_MASK;
250 } else if (address instanceof Ipv6Binary) {
251 return IPV6_MAX_MASK;
252 } else if (address instanceof Ipv4Prefix) {
253 return Short.parseShort(getPrefixMask(((Ipv4Prefix) address).getIpv4Prefix().getValue()));
254 } else if (address instanceof Ipv6Prefix) {
255 return Short.parseShort(getPrefixMask(((Ipv6Prefix) address).getIpv6Prefix().getValue()));
256 } else if (address instanceof InstanceId) {
257 return getMaskForAddress(((InstanceId)address).getInstanceId().getAddress());
258 } else if (address instanceof Ipv4PrefixBinary) {
259 return ((Ipv4PrefixBinary) address).getIpv4MaskLength().toJava();
260 } else if (address instanceof Ipv6PrefixBinary) {
261 return ((Ipv6PrefixBinary) address).getIpv6MaskLength().toJava();