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