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