Fix to topology-lldp-discovery to allow for clean karaf feature
[controller.git] / opendaylight / commons / liblldp / src / main / java / org / opendaylight / controller / liblldp / LLDPTLV.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, 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
9 package org.opendaylight.controller.liblldp;
10
11 import java.io.UnsupportedEncodingException;
12 import java.nio.charset.Charset;
13 import java.util.Arrays;
14 import java.util.HashMap;
15 import java.util.LinkedHashMap;
16 import java.util.Map;
17
18 import org.apache.commons.lang3.tuple.MutablePair;
19 import org.apache.commons.lang3.tuple.Pair;
20
21 /**
22  * Class that represents the LLDPTLV objects
23  */
24
25 public class LLDPTLV extends Packet {
26     private static final String TYPE = "Type";
27     private static final String LENGTH = "Length";
28     private static final String VALUE = "Value";
29     private static final int LLDPTLVFields = 3;
30     public static final byte[] OFOUI = new byte[] { (byte) 0x00, (byte) 0x26,
31         (byte) 0xe1 }; // OpenFlow OUI
32     public static final byte[] customTlvSubType = new byte[] { 0 };
33     public static final int customTlvOffset = OFOUI.length
34             + customTlvSubType.length;
35     public static final byte chassisIDSubType[] = new byte[] { 4 }; // MAC address for the system
36     public static final byte portIDSubType[] = new byte[] { 7 }; // locally assigned
37
38     public enum TLVType {
39         Unknown((byte) 0), ChassisID((byte) 1), PortID((byte) 2), TTL((byte) 3), PortDesc(
40                 (byte) 4), SystemName((byte) 5), SystemDesc((byte) 6), Custom(
41                         (byte) 127);
42
43         private byte value;
44
45         private TLVType(byte value) {
46             this.value = value;
47         }
48
49         public byte getValue() {
50             return value;
51         }
52     }
53
54     private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
55         private static final long serialVersionUID = 1L;
56
57         {
58             put(TYPE, new MutablePair<Integer, Integer>(0, 7));
59             put(LENGTH, new MutablePair<Integer, Integer>(7, 9));
60             put(VALUE, new MutablePair<Integer, Integer>(16, 0));
61         }
62     };
63
64     protected Map<String, byte[]> fieldValues;
65
66     /**
67      * Default constructor that creates and sets the hash map values and sets
68      * the payload to null
69      */
70     public LLDPTLV() {
71         payload = null;
72         fieldValues = new HashMap<String, byte[]>(LLDPTLVFields);
73         hdrFieldCoordMap = fieldCoordinates;
74         hdrFieldsMap = fieldValues;
75     }
76
77     /**
78      * Constructor that writes the passed LLDPTLV values to the hdrFieldsMap
79      */
80     public LLDPTLV(LLDPTLV other) {
81         for (Map.Entry<String, byte[]> entry : other.hdrFieldsMap.entrySet()) {
82             this.hdrFieldsMap.put(entry.getKey(), entry.getValue());
83         }
84     }
85
86     /**
87      * @return int - the length of TLV
88      */
89     public int getLength() {
90         return (int) BitBufferHelper.toNumber(fieldValues.get(LENGTH),
91                 fieldCoordinates.get(LENGTH).getRight().intValue());
92     }
93
94     /**
95      * @return byte - the type of TLV
96      */
97     public byte getType() {
98         return BitBufferHelper.getByte(fieldValues.get(TYPE));
99     }
100
101     /**
102      * @return byte[] - the value field of TLV
103      */
104     public byte[] getValue() {
105         return fieldValues.get(VALUE);
106     }
107
108     /**
109      * @param byte - the type to set
110      * @return LLDPTLV
111      */
112     public LLDPTLV setType(byte type) {
113         byte[] lldpTLVtype = { type };
114         fieldValues.put(TYPE, lldpTLVtype);
115         return this;
116     }
117
118     /**
119      * @param short - the length to set
120      * @return LLDPTLV
121      */
122     public LLDPTLV setLength(short length) {
123         fieldValues.put(LENGTH, BitBufferHelper.toByteArray(length));
124         return this;
125     }
126
127     /**
128      * @param byte[] - the value to set
129      * @return LLDPTLV
130      */
131     public LLDPTLV setValue(byte[] value) {
132         fieldValues.put(VALUE, value);
133         return this;
134     }
135
136     @Override
137     public void setHeaderField(String headerField, byte[] readValue) {
138         hdrFieldsMap.put(headerField, readValue);
139     }
140
141     @Override
142     public int hashCode() {
143         final int prime = 31;
144         int result = super.hashCode();
145         result = prime * result
146                 + ((fieldValues == null) ? 0 : fieldValues.hashCode());
147         return result;
148     }
149
150     @Override
151     public boolean equals(Object obj) {
152         if (this == obj) {
153             return true;
154         }
155         if (!super.equals(obj)) {
156             return false;
157         }
158         if (getClass() != obj.getClass()) {
159             return false;
160         }
161         LLDPTLV other = (LLDPTLV) obj;
162         if (fieldValues == null) {
163             if (other.fieldValues != null) {
164                 return false;
165             }
166         } else if (!fieldValues.equals(other.fieldValues)) {
167             return false;
168         }
169         return true;
170     }
171
172     @Override
173     public int getfieldnumBits(String fieldName) {
174         if (fieldName.equals(VALUE)) {
175             return (NetUtils.NumBitsInAByte * BitBufferHelper.getShort(
176                     fieldValues.get(LENGTH), fieldCoordinates.get(LENGTH)
177                     .getRight().intValue()));
178         }
179         return fieldCoordinates.get(fieldName).getRight();
180     }
181
182     /**
183      * Returns the size in bits of the whole TLV
184      *
185      * @return int - size in bits of full TLV
186      */
187     public int getTLVSize() {
188         return (LLDPTLV.fieldCoordinates.get(TYPE).getRight() + // static
189                 LLDPTLV.fieldCoordinates.get(LENGTH).getRight() + // static
190                 getfieldnumBits(VALUE)); // variable
191     }
192
193     /**
194      * Creates the SystemName TLV value
195      *
196      * @param nodeId
197      *            node identifier string
198      * @return the SystemName TLV value in byte array
199      */
200     static public byte[] createSystemNameTLVValue(String nodeId) {
201         byte[] nid = nodeId.getBytes();
202         return nid;
203     }
204
205     /**
206      * Creates the ChassisID TLV value including the subtype and ChassisID
207      * string
208      *
209      * @param nodeId
210      *            node identifier string
211      * @return the ChassisID TLV value in byte array
212      */
213     static public byte[] createChassisIDTLVValue(String nodeId) {
214         byte[] nid = HexEncode.bytesFromHexString(nodeId);
215         byte[] cid = new byte[6];
216         int srcPos = 0, dstPos = 0;
217
218         if (nid.length > cid.length) {
219             srcPos = nid.length - cid.length;
220         } else {
221             dstPos = cid.length - nid.length;
222         }
223         System.arraycopy(nid, srcPos, cid, dstPos, cid.length);
224
225         byte[] cidValue = new byte[cid.length + chassisIDSubType.length];
226
227         System.arraycopy(chassisIDSubType, 0, cidValue, 0,
228                 chassisIDSubType.length);
229         System.arraycopy(cid, 0, cidValue, chassisIDSubType.length, cid.length);
230
231         return cidValue;
232     }
233
234     /**
235      * Creates the PortID TLV value including the subtype and PortID string
236      *
237      * @param portId
238      *            port identifier string
239      * @return the PortID TLV value in byte array
240      */
241     static public byte[] createPortIDTLVValue(String portId) {
242         byte[] pid = portId.getBytes(Charset.defaultCharset());
243         byte[] pidValue = new byte[pid.length + portIDSubType.length];
244
245         System.arraycopy(portIDSubType, 0, pidValue, 0, portIDSubType.length);
246         System.arraycopy(pid, 0, pidValue, portIDSubType.length, pid.length);
247
248         return pidValue;
249     }
250
251     /**
252      * Creates the custom TLV value including OUI, subtype and custom string
253      *
254      * @param portId
255      *            port identifier string
256      * @return the custom TLV value in byte array
257      */
258     static public byte[] createCustomTLVValue(String customString) {
259         byte[] customArray = customString.getBytes(Charset.defaultCharset());
260         byte[] customValue = new byte[customTlvOffset + customArray.length];
261
262         System.arraycopy(OFOUI, 0, customValue, 0, OFOUI.length);
263         System.arraycopy(customTlvSubType, 0, customValue, OFOUI.length,
264                 customTlvSubType.length);
265         System.arraycopy(customArray, 0, customValue, customTlvOffset,
266                 customArray.length);
267
268         return customValue;
269     }
270
271     /**
272      * Retrieves the string from TLV value and returns it in HexString format
273      *
274      * @param tlvValue
275      *            the TLV value
276      * @param tlvLen
277      *            the TLV length
278      * @return the HexString
279      */
280     static public String getHexStringValue(byte[] tlvValue, int tlvLen) {
281         byte[] cidBytes = new byte[tlvLen - chassisIDSubType.length];
282         System.arraycopy(tlvValue, chassisIDSubType.length, cidBytes, 0,
283                 cidBytes.length);
284         return HexEncode.bytesToHexStringFormat(cidBytes);
285     }
286
287     /**
288      * Retrieves the string from TLV value
289      *
290      * @param tlvValue
291      *            the TLV value
292      * @param tlvLen
293      *            the TLV length
294      * @return the string
295      */
296     static public String getStringValue(byte[] tlvValue, int tlvLen) {
297         byte[] pidSubType = new byte[portIDSubType.length];
298         byte[] pidBytes = new byte[tlvLen - portIDSubType.length];
299         System.arraycopy(tlvValue, 0, pidSubType, 0,
300                 pidSubType.length);
301         System.arraycopy(tlvValue, portIDSubType.length, pidBytes, 0,
302                 pidBytes.length);
303         if (pidSubType[0] == (byte) 0x3) {
304             return HexEncode.bytesToHexStringFormat(pidBytes);
305         } else {
306             return (new String(pidBytes, Charset.defaultCharset()));
307         }
308     }
309
310     /**
311      * Retrieves the custom string from the Custom TLV value which includes OUI,
312      * subtype and custom string
313      *
314      * @param customTlvValue
315      *            the custom TLV value
316      * @param customTlvLen
317      *            the custom TLV length
318      * @return the custom string
319      */
320     static public String getCustomString(byte[] customTlvValue, int customTlvLen) {
321         String customString = "";
322         byte[] vendor = new byte[3];
323         System.arraycopy(customTlvValue, 0, vendor, 0, vendor.length);
324         if (Arrays.equals(vendor, LLDPTLV.OFOUI)) {
325             int customArrayLength = customTlvLen - customTlvOffset;
326             byte[] customArray = new byte[customArrayLength];
327             System.arraycopy(customTlvValue, customTlvOffset, customArray, 0,
328                     customArrayLength);
329             try {
330                 customString = new String(customArray, "UTF-8");
331             } catch (UnsupportedEncodingException e) {
332             }
333         }
334
335         return customString;
336     }
337 }