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