Update imports to reference new YANG revisions
[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.opendaylight.lfm.lisp.proto.rev151105.LcafSegmentAddress;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.LcafSourceDestAddress;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.LispAFIAddress;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.LispIpv4Address;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.LispIpv6Address;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lcafsegmentaddress.AddressBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lcafsegmentaddress.Address;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lcafsourcedestaddress.DstAddress;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lcafsourcedestaddress.DstAddressBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lcafsourcedestaddress.SrcAddress;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lcafsourcedestaddress.SrcAddressBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.LispAddressContainer;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.LispAddressContainerBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.Ipv4;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.Ipv4Builder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.Ipv6;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.Ipv6Builder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.LcafSegment;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.LcafSegmentBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.LcafSourceDest;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.LcafSourceDestBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.ipv4.Ipv4Address;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.ipv4.Ipv4AddressBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.ipv6.Ipv6Address;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.ipv6.Ipv6AddressBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.lcafsegment.LcafSegmentAddr;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.lcafsegment.LcafSegmentAddrBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.lcafsourcedest.LcafSourceDestAddr;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.lispaddress.lispaddresscontainer.address.lcafsourcedest.LcafSourceDestAddrBuilder;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 public class MaskUtil {
50     private static final Logger LOG = LoggerFactory.getLogger(MaskUtil.class);
51     public static boolean isMaskable(LispAFIAddress address) {
52         if (address instanceof Ipv4Address || address instanceof Ipv6Address || address instanceof LcafSegmentAddr) {
53             return true;
54         }
55         return false;
56     }
57
58     public static boolean isMaskable(LispAddressContainer address) {
59         if (address.getAddress() instanceof Ipv4  || address.getAddress() instanceof Ipv6) {
60             return true;
61         } else if (address.getAddress() instanceof LcafSegment) {
62             return isMaskable(LispAFIConvertor.toAFIfromPrimitive(((LcafSegment) address.getAddress())
63                     .getLcafSegmentAddr().getAddress().getPrimitiveAddress()));
64         } else if (address.getAddress() instanceof LcafSourceDestAddress) {
65             LcafSourceDestAddr sd = ((LcafSourceDest) address.getAddress()).getLcafSourceDestAddr();
66             return isMaskable(LispAFIConvertor.toAFIfromPrimitive(sd.getSrcAddress().getPrimitiveAddress()))
67                     && isMaskable(LispAFIConvertor.toAFIfromPrimitive(sd.getDstAddress().getPrimitiveAddress()));
68         }
69         return false;
70     }
71
72     public static LispAFIAddress normalize(LispAFIAddress address, short mask) {
73         try {
74             if (address instanceof Ipv4Address) {
75                 return LispAFIConvertor.asIPAfiAddress(normalizeIP(
76                         Inet4Address.getByName(((Ipv4Address) address).getIpv4Address().getValue()),
77                         mask).getHostAddress());
78             } else if (address instanceof Ipv6Address) {
79                 return LispAFIConvertor.asIPv6AfiAddress(normalizeIP(
80                         Inet6Address.getByName(((Ipv6Address) address).getIpv6Address().getValue()),
81                         mask).getHostAddress());
82             } else if (address instanceof LcafSegmentAddr) {
83                 LcafSegmentAddr segAddr = (LcafSegmentAddr) address;
84                 LispAFIAddress afiAddr = LispAFIConvertor
85                         .toAFIfromPrimitive(segAddr.getAddress().getPrimitiveAddress());
86                 Address normalizedAddr = new AddressBuilder().setPrimitiveAddress(
87                         LispAFIConvertor.toPrimitive(normalize(afiAddr, mask))).build();
88                 return new LcafSegmentAddrBuilder(segAddr).setAddress(normalizedAddr).build();
89             }
90         } catch (UnknownHostException e) {
91             LOG.trace("Failed to normalize " + address + ": " + ExceptionUtils.getStackTrace(e));
92         }
93         return address;
94     }
95
96     public static LispAFIAddress normalize(LispAFIAddress address) {
97         if (address instanceof Ipv4Address) {
98             return normalize(address, ((Ipv4Address) address).getMask());
99         } else if (address instanceof Ipv6Address) {
100             return normalize(address, ((Ipv6Address) address).getMask());
101         } else if (address instanceof LcafSegmentAddr) {
102             LcafSegmentAddr segAddr = (LcafSegmentAddr) address;
103             LispAFIAddress afiAddr = LispAFIConvertor.toAFIfromPrimitive(segAddr.getAddress().getPrimitiveAddress());
104             short mask = getMaskForAfiAddress(afiAddr);
105             if (mask == 0) {
106                 return address;
107             }
108             Address normalizedAddr = new AddressBuilder().setPrimitiveAddress(
109                     LispAFIConvertor.toPrimitive(normalize(afiAddr, mask))).build();
110             return new LcafSegmentAddrBuilder(segAddr).setAddress(normalizedAddr).build();
111         }
112         return address;
113     }
114
115     public static LispAddressContainer normalize(LispAddressContainer address, short mask) {
116         try {
117             if (address.getAddress() instanceof Ipv4) {
118                 return LispAFIConvertor.asIPv4Prefix(normalizeIP(
119                         Inet4Address.getByName(((Ipv4) address.getAddress()).getIpv4Address().getIpv4Address().getValue()),
120                         mask).getHostAddress(), mask);
121             } else if (address.getAddress() instanceof Ipv6) {
122                 return LispAFIConvertor.asIPv6Prefix(normalizeIP(
123                         Inet6Address.getByName(((Ipv6) address.getAddress()).getIpv6Address().getIpv6Address().getValue()),
124                         mask).getHostAddress(), mask);
125             } else if (address.getAddress() instanceof LcafSegment) {
126                 LcafSegmentAddress segAddr = ((LcafSegment) address.getAddress()).getLcafSegmentAddr();
127                 LispAFIAddress afiAddr = LispAFIConvertor
128                         .toAFIfromPrimitive(segAddr.getAddress().getPrimitiveAddress());
129                 Address normalizedAddr = new AddressBuilder().setPrimitiveAddress(
130                         LispAFIConvertor.toPrimitive(normalize(afiAddr, mask))).build();
131                 return new LispAddressContainerBuilder().setAddress(
132                         new LcafSegmentBuilder().setLcafSegmentAddr(
133                                 new LcafSegmentAddrBuilder(segAddr).setAddress(normalizedAddr).build()).build())
134                         .build();
135             }
136         } catch (UnknownHostException e) {
137             LOG.trace("Failed to normalize " + address + ": " + ExceptionUtils.getStackTrace(e));
138         }
139         return address;
140     }
141
142     public static LispAddressContainer normalize(LispAddressContainer address) {
143         if (address.getAddress() instanceof Ipv4) {
144             return normalize(address, ((Ipv4)address.getAddress()).getIpv4Address().getMask());
145         } else if (address.getAddress() instanceof Ipv6) {
146             return normalize(address, ((Ipv6)address.getAddress()).getIpv6Address().getMask());
147         } else if (address.getAddress() instanceof LcafSegment) {
148             LcafSegmentAddress segAddr = ((LcafSegment) address.getAddress()).getLcafSegmentAddr();
149             LispAFIAddress afiAddr = LispAFIConvertor
150                     .toAFIfromPrimitive(segAddr.getAddress().getPrimitiveAddress());
151             short mask = getMaskForAfiAddress(afiAddr);
152             if (mask == 0) {
153                 return address;
154             }
155             Address normalizedAddr = new AddressBuilder().setPrimitiveAddress(
156                     LispAFIConvertor.toPrimitive(normalize(afiAddr, mask))).build();
157             return new LispAddressContainerBuilder().setAddress(
158                     new LcafSegmentBuilder().setLcafSegmentAddr(
159                             new LcafSegmentAddrBuilder(segAddr).setAddress(normalizedAddr).build()).build())
160                     .build();
161         }
162         return address;
163     }
164
165     private static InetAddress normalizeIP(InetAddress address, int mask) throws UnknownHostException {
166         ByteBuffer byteRepresentation = ByteBuffer.wrap(address.getAddress());
167         byte b = (byte) 0xff;
168         for (int i = 0; i < byteRepresentation.array().length; i++) {
169             if (mask >= 8)
170                 byteRepresentation.put(i, (byte) (b & byteRepresentation.get(i)));
171
172             else if (mask > 0) {
173                 byteRepresentation.put(i, (byte) ((byte) (b << (8 - mask)) & byteRepresentation.get(i)));
174             } else {
175                 byteRepresentation.put(i, (byte) (0 & byteRepresentation.get(i)));
176             }
177
178             mask -= 8;
179         }
180         return InetAddress.getByAddress(byteRepresentation.array());
181     }
182
183     public static String normalizeIPString(String addr, int mask) {
184         short afi = getIpAfiForString(addr);
185         try {
186             if (afi == 1) {
187                 return normalizeIP(Inet4Address.getByName(addr), mask).getHostAddress();
188             } else if (afi == 2) {
189                 return normalizeIP(Inet6Address.getByName(addr), mask).getHostAddress();
190             } else {
191                 LOG.debug("The string {} is not a valid IP address!", addr);
192                 return null;
193             }
194         } catch (Exception e){
195             LOG.trace("Failed to normalize " + addr + ": " + ExceptionUtils.getStackTrace(e));
196         }
197         return null;
198     }
199
200     public static int getMaxMask(LispAFIAddress address) {
201         if (address instanceof Ipv4Address) {
202             return 32;
203         }
204         if (address instanceof Ipv6Address) {
205             return 128;
206         }
207         return -1;
208     }
209
210     public static byte getMaxMaskForAfi(int afi) {
211         if (afi == 1) {
212             return (byte) 32;
213         } else if (afi == 2) {
214             return (byte) 128;
215         } else {
216             return (byte) -1;
217         }
218     }
219
220     private static short getMaskForAfiAddress(LispAFIAddress addr) {
221         if (addr instanceof Ipv4Address) {
222             Short res = ((Ipv4Address) addr).getMask();
223             return (res != null) ? res.shortValue() : 32;
224         } else if (addr instanceof Ipv6Address) {
225             Short res = ((Ipv6Address) addr).getMask();
226             return (res != null) ? res.shortValue() : 128;
227         } else {
228             return 0;
229         }
230     }
231
232     public static short getMaskForAddress(LispAddressContainer addr) {
233         if (addr.getAddress() instanceof Ipv4) {
234             Short res = ((Ipv4)addr.getAddress()).getIpv4Address().getMask();
235             return (res != null) ? res.shortValue() : 32;
236         } else if (addr.getAddress() instanceof Ipv6) {
237             Short res = ((Ipv6)addr.getAddress()).getIpv6Address().getMask();
238             return (res != null) ? res.shortValue() : 128;
239         } else if (addr.getAddress() instanceof LcafSegment) {
240             return getMaskForAfiAddress(LispAFIConvertor.toAFIfromPrimitive((((LcafSegment) addr.getAddress())
241                     .getLcafSegmentAddr()).getAddress().getPrimitiveAddress()));
242         }
243         return 0;
244     }
245
246     private static short getIpAfiForString(String addr) {
247         if(addr.matches("([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])") == true){
248             return 1;
249         }
250         else if(addr.matches("([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)\\:([0-9a-f]+)") == true){
251             return 2;
252         }
253         return -1;
254     }
255
256     public static LispAddressContainer setMask(LispAddressContainer addr, int mask) {
257         if (addr.getAddress() instanceof Ipv4) {
258             return new LispAddressContainerBuilder().setAddress(
259                     new Ipv4Builder().setIpv4Address(
260                             new Ipv4AddressBuilder(((Ipv4) addr.getAddress()).getIpv4Address()).setMask((short) mask)
261                                     .build()).build()).build();
262
263         } else if (addr.getAddress() instanceof Ipv6) {
264             return new LispAddressContainerBuilder().setAddress(
265                     new Ipv6Builder().setIpv6Address(
266                             new Ipv6AddressBuilder(((Ipv6) addr.getAddress()).getIpv6Address()).setMask((short) mask)
267                                     .build()).build()).build();
268         } else if (addr.getAddress() instanceof LcafSegment) {
269             setMask(LispAFIConvertor.toAFIfromPrimitive(((LcafSegment) addr.getAddress()).getLcafSegmentAddr()
270                     .getAddress().getPrimitiveAddress()), mask);
271         }
272         return addr;
273     }
274
275     public static LispAFIAddress setMask(LispAFIAddress addr, int mask) {
276         if (addr instanceof LispIpv4Address) {
277             return new Ipv4AddressBuilder().setIpv4Address(((LispIpv4Address) addr).getIpv4Address())
278                     .setAfi(addr.getAfi()).setMask((short)mask).build();
279         } else if (addr instanceof LispIpv6Address) {
280             return new Ipv6AddressBuilder().setIpv6Address(((LispIpv6Address) addr).getIpv6Address())
281                     .setAfi(addr.getAfi()).setMask((short)mask).build();
282         } else if (addr instanceof LcafSegmentAddress) {
283             LispAFIAddress afiAddr = LispAFIConvertor.toAFIfromPrimitive(((LcafSegmentAddress) addr).getAddress()
284                     .getPrimitiveAddress());
285             afiAddr = setMask(afiAddr, mask);
286             return new LcafSegmentAddrBuilder((LcafSegmentAddress) addr).setAddress(
287                     new AddressBuilder().setPrimitiveAddress(LispAFIConvertor.toPrimitive(afiAddr)).build()).build();
288         }
289         return addr;
290     }
291
292     public static LispAFIAddress setMaskSourceDest(LispAFIAddress addr, int srcMask, int dstMask) {
293         DstAddress dst = LcafSourceDestHelper.getDstAddress(addr);
294         LispAFIAddress dstAfi = LispAFIConvertor.toAFIfromPrimitive(dst.getPrimitiveAddress());
295         DstAddress newDst = new DstAddressBuilder(dst).setPrimitiveAddress(LispAFIConvertor.toPrimitive(setMask(dstAfi, dstMask))).build();
296         SrcAddress src = LcafSourceDestHelper.getSrcAddress(addr);
297         LispAFIAddress srcAfi = LispAFIConvertor.toAFIfromPrimitive(src.getPrimitiveAddress());
298         SrcAddress newSrc = new SrcAddressBuilder(src).setPrimitiveAddress(LispAFIConvertor.toPrimitive(setMask(srcAfi, srcMask))).build();
299         return new LcafSourceDestAddrBuilder((LcafSourceDestAddress)addr).setDstAddress(newDst).setSrcAddress(newSrc).build();
300     }
301
302     public static LispAddressContainer setMaskSourceDest(LispAddressContainer addr, int srcMask, int dstMask) {
303         return new LispAddressContainerBuilder().setAddress(
304                 new LcafSourceDestBuilder((LcafSourceDest) addr.getAddress()).setLcafSourceDestAddr(
305                         (LcafSourceDestAddr) setMaskSourceDest(
306                                 ((LcafSourceDest) addr.getAddress()).getLcafSourceDestAddr(), srcMask, dstMask))
307                         .build()).build();
308     }
309
310     /**
311      * RFC6830 defines masks and EIDs as separate fields of larger, encompassing blocks of LISP messages. However within
312      * LispFlowMapping masks are internal fields of EIDs. The fixMask methods should be used in deserializers and RPC
313      * handlers to ensure that masks for EIDs reflect accordingly the mask field values carried in LISP messages or RPC
314      * input objects respectively.
315      */
316     public static LispAFIAddress fixMask(LispAFIAddress addr, short mask) {
317         if (addr instanceof LispIpv4Address || addr instanceof LispIpv6Address || addr instanceof LcafSegmentAddress) {
318            return MaskUtil.setMask(addr, mask);
319         } else if (addr instanceof LcafSourceDestAddress) {
320            return MaskUtil.setMaskSourceDest(addr, LcafSourceDestHelper.getSrcMask(addr),
321                     LcafSourceDestHelper.getDstMask(addr));
322         }
323         return addr;
324     }
325
326     public static LispAddressContainer fixMask(LispAddressContainer addr, short mask) {
327         if (addr.getAddress() instanceof Ipv4 || addr.getAddress() instanceof Ipv6
328                 || addr.getAddress() instanceof LcafSegment) {
329             return MaskUtil.setMask(addr, mask);
330         } else if (addr.getAddress() instanceof LcafSourceDest) {
331             return MaskUtil.setMaskSourceDest(addr, LcafSourceDestHelper.getSrcMask(addr),
332                     LcafSourceDestHelper.getDstMask(addr));
333         }
334         return addr;
335     }
336 }