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