Add support for Service Path mapping records processing
[lispflowmapping.git] / mappingservice / lisp-proto / src / main / java / org / opendaylight / lispflowmapping / lisp / util / MaskUtil.java
1 /*
2  * Copyright (c) 2014 Contextream, Inc. 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.lispflowmapping.lisp.util;
9
10 import java.net.Inet4Address;
11 import java.net.Inet6Address;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.nio.ByteBuffer;
15
16 import org.apache.commons.lang3.exception.ExceptionUtils;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.SimpleAddress;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.Address;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.InstanceId;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ServicePath;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 public final class MaskUtil {
32     private static final Logger LOG = LoggerFactory.getLogger(MaskUtil.class);
33     private static final short IPV4_MAX_MASK = 32;
34     private static final short IPV6_MAX_MASK = 128;
35
36     // Utility class, should not be instantiated
37     private MaskUtil() {
38     }
39
40     public static boolean isMaskable(Address address) {
41         if (address instanceof Ipv4Prefix || address instanceof Ipv6Prefix || address instanceof SourceDestKey) {
42             return true;
43         } else if (address instanceof InstanceId) {
44             return isMaskable(((InstanceId)address).getInstanceId().getAddress());
45         }
46         return false;
47     }
48
49     public static boolean isMaskable(SimpleAddress address) {
50         if (address.getIpPrefix() != null) {
51             return true;
52         }
53         return false;
54     }
55
56     public static Eid normalize(Eid eid, short mask) {
57         Address address = eid.getAddress();
58         try {
59             if (address instanceof Ipv4Prefix) {
60                 String[] v4prefix = String.valueOf(((Ipv4Prefix)address).getIpv4Prefix().getValue()).split("/");
61                 InetAddress normalized = normalizeIP(Inet4Address.getByName(v4prefix[0]), mask);
62                 return LispAddressUtil.asIpv4PrefixEid(eid, (Inet4Address)normalized, mask);
63             } else if (address instanceof Ipv6Prefix) {
64                 String[] v6prefix = String.valueOf(((Ipv6Prefix)address).getIpv6Prefix().getValue()).split("/");
65                 InetAddress normalized = normalizeIP(Inet6Address.getByName(v6prefix[0]), mask);
66                 return LispAddressUtil.asIpv6PrefixEid(eid, (Inet6Address)normalized, mask);
67             } else if (address instanceof InstanceId) {
68                 // TODO - not absolutely necessary, but should be implemented
69                 return eid;
70             }
71         } catch (UnknownHostException e) {
72             LOG.trace("Failed to normalize eid {} with mask {}: {}", eid, mask, ExceptionUtils.getStackTrace(e));
73         }
74         return eid;
75     }
76
77     public static Eid normalize(Eid eid) {
78         Address address = eid.getAddress();
79         try {
80             if (address instanceof Ipv4Prefix) {
81                 String[] v4prefix = String.valueOf(((Ipv4Prefix)address).getIpv4Prefix().getValue()).split("/");
82                 short mask = Short.parseShort(v4prefix[1]);
83                 InetAddress normalized = normalizeIP(Inet4Address.getByName(v4prefix[0]), mask);
84                 return LispAddressUtil.asIpv4PrefixEid(eid, (Inet4Address)normalized, mask);
85             } else if (address instanceof Ipv6Prefix) {
86                 String[] v6prefix = String.valueOf(((Ipv6Prefix)address).getIpv6Prefix().getValue()).split("/");
87                 short mask = Short.parseShort(v6prefix[1]);
88                 InetAddress normalized = normalizeIP(Inet6Address.getByName(v6prefix[0]), mask);
89                 return LispAddressUtil.asIpv6PrefixEid(eid, (Inet6Address)normalized, mask);
90             } else if (address instanceof InstanceId) {
91                 // TODO - not absolutely necessary, but should be implemented
92                 return eid;
93             } else if (address instanceof ServicePath) {
94                 // Build new Service Path eid with service index set to 0
95                 long spi = ((ServicePath) address).getServicePath().getServicePathId().getValue();
96                 return LispAddressUtil.asServicePathEid(0, spi, (short)0);
97             }
98         } catch (UnknownHostException e) {
99             LOG.trace("Failed to normalize eid {}: {}", eid, ExceptionUtils.getStackTrace(e));
100         }
101         return eid;
102     }
103
104     private static InetAddress normalizeIP(InetAddress address, int maskLength) throws UnknownHostException {
105         ByteBuffer byteRepresentation = ByteBuffer.wrap(address.getAddress());
106         byte b = (byte) 0xff;
107         int mask = maskLength;
108         for (int i = 0; i < byteRepresentation.array().length; i++) {
109             if (mask >= 8) {
110                 byteRepresentation.put(i, (byte) (b & byteRepresentation.get(i)));
111             } else if (mask > 0) {
112                 byteRepresentation.put(i, (byte) ((byte) (b << (8 - mask)) & byteRepresentation.get(i)));
113             } else {
114                 byteRepresentation.put(i, (byte) (0 & byteRepresentation.get(i)));
115             }
116
117             mask -= 8;
118         }
119         return InetAddress.getByAddress(byteRepresentation.array());
120     }
121
122     public static int getMaxMask(Address address) {
123         if (address instanceof Ipv4 || address instanceof Ipv4Prefix) {
124             return IPV4_MAX_MASK;
125         } else if (address instanceof Ipv6 || address instanceof Ipv6Prefix) {
126             return IPV6_MAX_MASK;
127         } else {
128             return -1;
129         }
130     }
131
132     public static short getMaskForAddress(SimpleAddress address) {
133         if (address.getIpPrefix() == null) {
134             return -1;
135         }
136         return getMaskForIpPrefix(address.getIpPrefix());
137     }
138
139     public static short getMaskForIpPrefix(IpPrefix prefix) {
140         return Short.parseShort(String.valueOf(prefix.getValue()).split("/")[1]);
141     }
142
143     public static String getAddressStringForIpPrefix(IpPrefix prefix) {
144         return String.valueOf(prefix.getValue()).split("/")[0];
145     }
146
147     public static String getAddressStringForIpv4Prefix(Ipv4Prefix prefix) {
148         return String.valueOf(prefix.getIpv4Prefix().getValue()).split("/")[0];
149     }
150
151     public static String getAddressStringForIpv6Prefix(Ipv6Prefix prefix) {
152         return String.valueOf(prefix.getIpv6Prefix().getValue()).split("/")[0];
153     }
154
155     public static short getMaskForAddress(Address address) {
156         if (address instanceof Ipv4) {
157             return IPV4_MAX_MASK;
158         } else if (address instanceof Ipv6) {
159             return IPV6_MAX_MASK;
160         } else if (address instanceof Ipv4Prefix) {
161             String[] prefix = String.valueOf(((Ipv4Prefix)address).getIpv4Prefix().getValue()).split("/");  // TODO use something more efficient
162             return Short.parseShort(prefix[1]);
163         } else if (address instanceof Ipv6Prefix) {
164             String[] prefix = String.valueOf(((Ipv6Prefix)address).getIpv6Prefix().getValue()).split("/");  // TODO use something more efficient
165             return Short.parseShort(prefix[1]);
166         } else if (address instanceof InstanceId) {
167             return getMaskForAddress(((InstanceId)address).getInstanceId().getAddress());
168         }
169         return -1;
170     }
171 }