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