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