Allow Address for getString()
[lispflowmapping.git] / mappingservice / lisp-proto / src / main / java / org / opendaylight / lispflowmapping / lisp / util / LispAddressStringifier.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc.  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 com.google.common.base.Preconditions;
11 import com.google.common.io.BaseEncoding;
12 import com.google.common.net.InetAddresses;
13 import java.net.Inet4Address;
14 import java.net.Inet6Address;
15 import java.net.UnknownHostException;
16 import java.util.List;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.LispAddress;
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.AfiList;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ApplicationData;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.AsNumber;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.DistinguishedName;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ExplicitLocatorPath;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.InstanceId;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv4Prefix;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Ipv6Prefix;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.KeyValueAddress;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.Mac;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.NoAddress;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.ServicePath;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.explicit.locator.path.Hop;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.explicit.locator.path.explicit.locator.path.Hop.LrsBits;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv4Binary;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv4PrefixBinary;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv6Binary;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv6PrefixBinary;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  * Utility class with static methods returning string representations of
47  * supported LISP address types, both for use in URLs and for user friendly
48  * output.
49  *
50  * @author Lorand Jakab
51  *
52  */
53 public class LispAddressStringifier {
54     protected static final Logger LOG = LoggerFactory.getLogger(LispAddressStringifier.class);
55
56     private static final String PREFIX_SEPARATOR = ":";
57
58     /*
59      * In the unlikely event that a AFI 0 address is used a key, we use a
60      * sequence number to ensure uniqueness
61      */
62     protected static int noAddrSeq = 0;
63
64     /*
65      * There are three possible destinations for rendering an address as a
66      * string:
67      *
68      *   * General user interaction, like log and CLI output, GUI
69      *     representation, etc.
70      *   * As a URI string that is the entry key in the MD-SAL datastore
71      *   * As a URL string that is the same as the URI string, except for
72      *     characters not accepted in URLs are percent encoded (e.g. '/' is
73      *     encoded as '%2f'
74      */
75     protected enum Destination {
76         USER,
77         URI,
78         URL;
79     }
80
81     public static String getString(LispAddress lispAddress) {
82         return getAddrString(Destination.USER, lispAddress);
83     }
84
85     public static String getString(Address address) {
86         return getAddrString(Destination.USER, address, null);
87     }
88
89     public static String getString(XtrId xtrId) {
90         return getXtrIdString(xtrId);
91     }
92
93     public static String getURIString(LispAddress lispAddress) {
94         return getAddrString(Destination.URI, lispAddress);
95     }
96
97     public static String getURIString(XtrId xtrId) {
98         return getXtrIdString(xtrId);
99     }
100
101     public static String getURLString(LispAddress lispAddress) {
102         return getAddrString(Destination.URL, lispAddress);
103     }
104
105     public static String getURLString(XtrId xtrId) {
106         return getXtrIdString(xtrId);
107     }
108
109     private static String getXtrIdString(XtrId xtrId) {
110         return BaseEncoding.base16().encode(xtrId.getValue());
111     }
112
113     private static String getAddrString(Destination dst, LispAddress lispAddress) {
114         Preconditions.checkNotNull(lispAddress, "lispAddress should not be null");
115         Address addr = lispAddress.getAddress();
116         Long vni = null;
117
118         if (lispAddress.getVirtualNetworkId() != null) {
119             vni = lispAddress.getVirtualNetworkId().getValue();
120         }
121
122         return getAddrString(dst, addr, vni);
123     }
124
125     private static String getAddrString(Destination dst, Address addr, Long virtualNetworkId) {
126         String prefix = "";
127         String vni = "";
128         String address = "";
129
130         if (virtualNetworkId != null) {
131             vni = "[" + virtualNetworkId + "] ";
132         }
133
134         if (addr instanceof Ipv4) {
135             prefix = "ipv4" + PREFIX_SEPARATOR;
136             address = getStringFromIpv4(dst, (Ipv4) addr);
137         } else if (addr instanceof Ipv4Binary) {
138             prefix = "ipv4" + PREFIX_SEPARATOR;
139             address = getStringFromIpv4Binary(dst, (Ipv4Binary) addr);
140         } else if (addr instanceof Ipv4Prefix) {
141             prefix = "ipv4" + PREFIX_SEPARATOR;
142             address = getStringFromIpv4Prefix(dst, (Ipv4Prefix) addr);
143         } else if (addr instanceof Ipv4PrefixBinary) {
144             prefix = "ipv4" + PREFIX_SEPARATOR;
145             address = getStringFromIpv4PrefixBinary(dst, (Ipv4PrefixBinary) addr);
146         } else if (addr instanceof Ipv6) {
147             prefix = "ipv6" + PREFIX_SEPARATOR;
148             address = getStringFromIpv6(dst, (Ipv6) addr);
149         } else if (addr instanceof Ipv6Binary) {
150             prefix = "ipv6" + PREFIX_SEPARATOR;
151             address = getStringFromIpv6Binary(dst, (Ipv6Binary) addr);
152         } else if (addr instanceof Ipv6Prefix) {
153             prefix = "ipv6" + PREFIX_SEPARATOR;
154             address = getStringFromIpv6Prefix(dst, (Ipv6Prefix) addr);
155         } else if (addr instanceof Ipv6PrefixBinary) {
156             prefix = "ipv6" + PREFIX_SEPARATOR;
157             address = getStringFromIpv6PrefixBinary(dst, (Ipv6PrefixBinary) addr);
158         } else if (addr instanceof Mac) {
159             prefix = "mac" + PREFIX_SEPARATOR;
160             address = getStringFromMac(dst, (Mac) addr);
161         } else if (addr instanceof InstanceId) {
162             SimpleAddress pa = ((InstanceId)addr).getInstanceId().getAddress();
163             // Instance ID is a separate parent hierarchy, so we use the simple address prefix
164             prefix = LispSimpleAddressStringifier.getURLPrefix(pa) + PREFIX_SEPARATOR;
165             address = getStringFromInstanceId(dst, (InstanceId) addr);
166         } else if (addr instanceof NoAddress) {
167             prefix = "no" + PREFIX_SEPARATOR;
168             address = getStringFromNoAddress(dst, (NoAddress) addr);
169         } else if (addr instanceof DistinguishedName) {
170             prefix = "dn" + PREFIX_SEPARATOR;
171             address = getStringFromDistinguishedName(dst, (DistinguishedName) addr);
172         } else if (addr instanceof AsNumber) {
173             prefix = "as" + PREFIX_SEPARATOR;
174             address = getStringFromAsNumber(dst, (AsNumber) addr);
175         } else if (addr instanceof AfiList) {
176             prefix = "list" + PREFIX_SEPARATOR;
177             address = getStringFromAfiList(dst, (AfiList) addr);
178         } else if (addr instanceof ApplicationData) {
179             prefix = "appdata" + PREFIX_SEPARATOR;
180             address = getStringFromApplicationData(dst, (ApplicationData) addr);
181         } else if (addr instanceof ExplicitLocatorPath) {
182             prefix = "elp" + PREFIX_SEPARATOR;
183             address = getStringFromExplicitLocatorPath(dst, (ExplicitLocatorPath) addr);
184         } else if (addr instanceof SourceDestKey) {
185             prefix = "srcdst" + PREFIX_SEPARATOR;
186             address = getStringFromSourceDestKey(dst, (SourceDestKey) addr);
187         } else if (addr instanceof KeyValueAddress) {
188             prefix = "kv" + PREFIX_SEPARATOR;
189             address = getStringFromKeyValueAddress(dst, (KeyValueAddress) addr);
190         } else if (addr instanceof ServicePath) {
191             prefix = "sp" + PREFIX_SEPARATOR;
192             address = getStringFromServicePath(dst, (ServicePath) addr);
193         } else {
194             return null;
195         }
196
197         if (dst == Destination.USER) {
198             return vni + address;
199         } else {
200             return prefix + address;
201         }
202
203     }
204
205     private static String getPrefixString(Destination dst, String prefix) {
206         if (dst == Destination.URL) {
207             return prefix.replace("/", "%2f");
208         } else {
209             return prefix;
210         }
211     }
212
213     protected static String getStringFromNoAddress(Destination dst, NoAddress addr) {
214         // AFI = 0
215         if (dst == Destination.USER) {
216             return "No Address Present";
217         } else {
218             return "" + noAddrSeq++;
219         }
220     }
221
222     protected static String getStringFromIpv4(Destination dst, Ipv4 addr) {
223         // AFI = 1; IPv4
224         return addr.getIpv4().getValue();
225     }
226
227     protected static String getStringFromIpv4Binary(Destination dst, Ipv4Binary addr) {
228         // AFI = 1; IPv4
229         try {
230             return InetAddresses.toAddrString(Inet4Address.getByAddress(addr.getIpv4Binary().getValue()));
231         } catch (UnknownHostException e) {
232             LOG.debug("Cannot convert binary IPv4 to string", e);
233         }
234         return null;
235     }
236
237     protected static String getStringFromIpv4Prefix(Destination dst, Ipv4Prefix addr) {
238         // AFI = 1; IPv4
239         String prefix = addr.getIpv4Prefix().getValue();
240         return getPrefixString(dst, prefix);
241     }
242
243     protected static String getStringFromIpv4PrefixBinary(Destination dst, Ipv4PrefixBinary addr) {
244         // AFI = 1; IPv4
245         try {
246             StringBuilder prefixBuilder = new StringBuilder(InetAddresses.toAddrString(
247                     Inet4Address.getByAddress(addr.getIpv4AddressBinary().getValue())));
248             prefixBuilder.append('/');
249             prefixBuilder.append(addr.getIpv4MaskLength().toString());
250             return getPrefixString(dst, prefixBuilder.toString());
251         } catch (UnknownHostException e) {
252             LOG.debug("Cannot convert binary IPv4 prefix to string", e);
253         }
254         return null;
255     }
256
257     protected static String getStringFromIpv6(Destination dst, Ipv6 addr) {
258         // AFI = 2; IPv6
259         return addr.getIpv6().getValue();
260     }
261
262     protected static String getStringFromIpv6Binary(Destination dst, Ipv6Binary addr) {
263         // AFI = 2; IPv6
264         try {
265             return InetAddresses.toAddrString(Inet6Address.getByAddress(addr.getIpv6Binary().getValue()));
266         } catch (UnknownHostException e) {
267             LOG.debug("Cannot convert binary IPv6 to string", e);
268         }
269         return null;
270     }
271
272     protected static String getStringFromIpv6Prefix(Destination dst, Ipv6Prefix addr) {
273         // AFI = 2; IPv6
274         return addr.getIpv6Prefix().getValue();
275     }
276
277     protected static String getStringFromIpv6PrefixBinary(Destination dst, Ipv6PrefixBinary addr) {
278         // AFI = 2; IPv5
279         try {
280             StringBuilder prefixBuilder = new StringBuilder(InetAddresses.toAddrString(
281                     Inet6Address.getByAddress(addr.getIpv6AddressBinary().getValue())));
282             prefixBuilder.append('/');
283             prefixBuilder.append(addr.getIpv6MaskLength().toString());
284             return getPrefixString(dst, prefixBuilder.toString());
285         } catch (UnknownHostException e) {
286             LOG.debug("Cannot convert binary IPv6 prefix to string", e);
287         }
288         return null;
289     }
290
291     protected static String getStringFromDistinguishedName(Destination dst, DistinguishedName addr) {
292         // AFI = 17; Distinguished Name
293         return addr.getDistinguishedName().getValue();
294     }
295
296     protected static String getStringFromAsNumber(Destination dst, AsNumber addr) {
297         // AFI = 18; Autonomous System Number
298         return "AS" + addr.getAsNumber().getValue();
299     }
300
301     protected static String getStringFromAfiList(Destination dst, AfiList addr) {
302         // AFI 16387, LCAF Type 1; Address List
303         // Example rendering:
304         //    {192.0.2.1,192.0.2.2,2001:db8::1}
305         List<SimpleAddress> addresses = addr.getAfiList().getAddressList();
306         StringBuilder sb = new StringBuilder("{");
307         boolean needComma = false;
308         for (SimpleAddress a : addresses) {
309             if (needComma) {
310                 sb.append(",");
311             }
312             sb.append(a.getValue());
313             needComma = true;
314         }
315         sb.append("}");
316         return sb.toString();
317     }
318
319     protected static String getStringFromInstanceId(Destination dst, InstanceId addr) {
320         // AFI = 16387, LCAF Type 2; Instance ID
321         // Example rendering:
322         //    [223] 192.0.2.0/24
323         SimpleAddress pa = addr.getInstanceId().getAddress();
324         if (dst == Destination.USER) {
325             return "[" + addr.getInstanceId().getIid().getValue() + "] "
326                     + LispSimpleAddressStringifier.getString(dst, pa);
327         } else {
328             return LispSimpleAddressStringifier.getString(dst, pa);
329         }
330     }
331
332     protected static String getStringFromApplicationData(Destination dst, ApplicationData addr) {
333         // AFI = 16387, LCAF Type 4; Application Data
334         // Example rendering:
335         //    192.0.2.1!128!17!80-81!6667-7000
336         return LispSimpleAddressStringifier.getString(dst, addr.getApplicationData().getAddress())
337                 + "!" + addr.getApplicationData().getIpTos()
338                 + "!" + addr.getApplicationData().getProtocol()
339                 + "!" + addr.getApplicationData().getLocalPortLow()
340                 + "-" + addr.getApplicationData().getLocalPortHigh()
341                 + "!" + addr.getApplicationData().getRemotePortLow()
342                 + "-" + addr.getApplicationData().getRemotePortHigh();
343     }
344
345     protected static String getStringFromExplicitLocatorPath(Destination dst, ExplicitLocatorPath addr) {
346         // AFI = 16387, LCAF Type 10, Explicit Locator Path
347         // Example rendering:
348         //    {192.0.2.1->192.0.2.2|lps->192.0.2.3}
349         List<Hop> hops = addr.getExplicitLocatorPath().getHop();
350         StringBuilder sb = new StringBuilder();
351         sb.append("{");
352         boolean needArrow = false;
353         for (Hop hop : hops) {
354             if (needArrow) {
355                 sb.append("->");
356             }
357             sb.append(LispSimpleAddressStringifier.getString(dst, hop.getAddress()));
358             LrsBits lrs = hop.getLrsBits();
359             if (lrs.isLookup() || lrs.isRlocProbe() || lrs.isStrict()) {
360                 sb.append("|");
361             }
362             if (lrs.isLookup()) {
363                 sb.append("l");
364             }
365             if (lrs.isRlocProbe()) {
366                 sb.append("p");
367             }
368             if (lrs.isStrict()) {
369                 sb.append("s");
370             }
371             needArrow = true;
372         }
373         sb.append("}");
374         return sb.toString();
375     }
376
377     protected static String getStringFromSourceDestKey(Destination dst, SourceDestKey addr) {
378         // AFI = 16387, LCAF Type 12, Source/Destination Key
379         // Example rendering:
380         //    192.0.2.1/32|192.0.2.2/32
381         return getPrefixString(dst, (new String(addr.getSourceDestKey().getSource().getValue()))
382                 + "|" + getPrefixString(dst, new String(addr.getSourceDestKey().getDest().getValue())));
383     }
384
385     protected static String getStringFromKeyValueAddress(Destination dst, KeyValueAddress addr) {
386         // AFI = 16387, LCAF Type 15, Key/Value Address Pair
387         // Example rendering:
388         //    192.0.2.1=>192.0.2.2
389         return getPrefixString(dst, new String(addr.getKeyValueAddress().getKey().getValue())
390                 + "=>" + getPrefixString(dst, new String(addr.getKeyValueAddress().getValue().getValue())));
391     }
392
393     protected static String getStringFromMac(Destination dst, Mac addr) {
394         // AFI = 16389; MAC
395         return addr.getMac().getValue();
396     }
397
398     protected static String getStringFromServicePath(Destination dst, ServicePath addr) {
399         // AFI = 16387; LCAF http://tools.ietf.org/html/draft-ermagan-lisp-nsh-00
400         // Example rendering:
401         //     42(3)
402         return getPrefixString(dst, new String(addr.getServicePath().getServicePathId().getValue() + "("
403                 + addr.getServicePath().getServiceIndex() + ")"));
404     }
405
406 }