2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.liblldp;
11 import org.apache.commons.lang3.ArrayUtils;
12 import org.slf4j.LoggerFactory;
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;
21 import org.apache.commons.lang3.tuple.MutablePair;
22 import org.apache.commons.lang3.tuple.Pair;
25 * Class that represents the LLDPTLV objects
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;
35 public static final byte[] OFOUI = new byte[] { (byte) 0x00, (byte) 0x26,
38 /** Length of Organizationally defined subtype field of TLV in bytes */
39 private static final byte customTlvSubTypeLength = (byte)1;
41 /** OpenFlow subtype: nodeConnectorId of source */
42 public static final byte[] CUSTOM_TLV_SUB_TYPE_NODE_CONNECTOR_ID = new byte[] { 0 };
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 };
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
51 private static final Logger LOG = LoggerFactory.getLogger(LLDPTLV.class);
54 Unknown((byte) 0), ChassisID((byte) 1), PortID((byte) 2), TTL((byte) 3), PortDesc(
55 (byte) 4), SystemName((byte) 5), SystemDesc((byte) 6), Custom(
60 private TLVType(byte value) {
64 public byte getValue() {
69 private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
70 private static final long serialVersionUID = 1L;
73 put(TYPE, new MutablePair<Integer, Integer>(0, 7));
74 put(LENGTH, new MutablePair<Integer, Integer>(7, 9));
75 put(VALUE, new MutablePair<Integer, Integer>(16, 0));
79 protected Map<String, byte[]> fieldValues;
82 * Default constructor that creates and sets the hash map values and sets
87 fieldValues = new HashMap<String, byte[]>(LLDPTLVFields);
88 hdrFieldCoordMap = fieldCoordinates;
89 hdrFieldsMap = fieldValues;
93 * Constructor that writes the passed LLDPTLV values to the hdrFieldsMap
95 public LLDPTLV(LLDPTLV other) {
96 for (Map.Entry<String, byte[]> entry : other.hdrFieldsMap.entrySet()) {
97 this.hdrFieldsMap.put(entry.getKey(), entry.getValue());
102 * @return int - the length of TLV
104 public int getLength() {
105 return (int) BitBufferHelper.toNumber(fieldValues.get(LENGTH),
106 fieldCoordinates.get(LENGTH).getRight().intValue());
110 * @return byte - the type of TLV
112 public byte getType() {
113 return BitBufferHelper.getByte(fieldValues.get(TYPE));
117 * @return byte[] - the value field of TLV
119 public byte[] getValue() {
120 return fieldValues.get(VALUE);
124 * @param byte - the type to set
127 public LLDPTLV setType(byte type) {
128 byte[] lldpTLVtype = { type };
129 fieldValues.put(TYPE, lldpTLVtype);
134 * @param short - the length to set
137 public LLDPTLV setLength(short length) {
138 fieldValues.put(LENGTH, BitBufferHelper.toByteArray(length));
143 * @param byte[] - the value to set
146 public LLDPTLV setValue(byte[] value) {
147 fieldValues.put(VALUE, value);
152 public void setHeaderField(String headerField, byte[] readValue) {
153 hdrFieldsMap.put(headerField, readValue);
157 public int hashCode() {
158 final int prime = 31;
159 int result = super.hashCode();
160 result = prime * result
161 + ((fieldValues == null) ? 0 : fieldValues.hashCode());
166 public boolean equals(Object obj) {
170 if (!super.equals(obj)) {
173 if (getClass() != obj.getClass()) {
176 LLDPTLV other = (LLDPTLV) obj;
177 if (fieldValues == null) {
178 if (other.fieldValues != null) {
181 } else if (!fieldValues.equals(other.fieldValues)) {
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()));
194 return fieldCoordinates.get(fieldName).getRight();
198 * Returns the size in bits of the whole TLV
200 * @return int - size in bits of full TLV
202 public int getTLVSize() {
203 return (LLDPTLV.fieldCoordinates.get(TYPE).getRight() + // static
204 LLDPTLV.fieldCoordinates.get(LENGTH).getRight() + // static
205 getfieldnumBits(VALUE)); // variable
209 * Creates the SystemName TLV value
212 * node identifier string
213 * @return the SystemName TLV value in byte array
215 static public byte[] createSystemNameTLVValue(String nodeId) {
216 byte[] nid = nodeId.getBytes();
221 * Creates the ChassisID TLV value including the subtype and ChassisID
225 * node identifier string
226 * @return the ChassisID TLV value in byte array
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;
233 if (nid.length > cid.length) {
234 srcPos = nid.length - cid.length;
236 dstPos = cid.length - nid.length;
238 System.arraycopy(nid, srcPos, cid, dstPos, cid.length);
240 byte[] cidValue = new byte[cid.length + chassisIDSubType.length];
242 System.arraycopy(chassisIDSubType, 0, cidValue, 0,
243 chassisIDSubType.length);
244 System.arraycopy(cid, 0, cidValue, chassisIDSubType.length, cid.length);
250 * Creates the PortID TLV value including the subtype and PortID string
253 * port identifier string
254 * @return the PortID TLV value in byte array
256 static public byte[] createPortIDTLVValue(String portId) {
257 byte[] pid = portId.getBytes(Charset.defaultCharset());
258 byte[] pidValue = new byte[pid.length + portIDSubType.length];
260 System.arraycopy(portIDSubType, 0, pidValue, 0, portIDSubType.length);
261 System.arraycopy(pid, 0, pidValue, portIDSubType.length, pid.length);
267 * Creates the custom TLV value including OUI, subtype and custom string
270 * port identifier string
271 * @return the custom TLV value in byte array
272 * @see {@link #createCustomTLVValue(byte,String)}
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);
280 * Creates the custom TLV value including OUI, subtype and custom string
281 * @param subtype openflow subtype
283 * port identifier string
284 * @return the custom TLV value in byte array
286 static public byte[] createCustomTLVValue(byte[] subtype, byte[] customByteArray) {
287 byte[] customValue = new byte[customTlvOffset + customByteArray.length];
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);
298 * Retrieves the string from TLV value and returns it in HexString format
304 * @return the HexString
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,
310 return HexEncode.bytesToHexStringFormat(cidBytes);
314 * Retrieves the string from TLV value
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,
327 System.arraycopy(tlvValue, portIDSubType.length, pidBytes, 0,
329 if (pidSubType[0] == (byte) 0x3) {
330 return HexEncode.bytesToHexStringFormat(pidBytes);
332 return (new String(pidBytes, Charset.defaultCharset()));
337 * Retrieves the custom string from the Custom TLV value which includes OUI,
338 * subtype and custom string
340 * @param customTlvValue
341 * the custom TLV value
342 * @param customTlvLen
343 * the custom TLV length
344 * @return the custom string
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,
356 customString = new String(customArray, "UTF-8");
357 } catch (UnsupportedEncodingException e) {
364 public static int extractCustomOUI(final LLDPTLV lldptlv) {
365 byte[] value = lldptlv.getValue();
366 return BitBufferHelper.getInt(ArrayUtils.subarray(value, 0, 3));
369 public static byte extractCustomSubtype(final LLDPTLV lldptlv) {
370 byte[] value = lldptlv.getValue();
371 return BitBufferHelper.getByte(ArrayUtils.subarray(value, 3, 4));