2 * Copyright (c) 2015 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
8 package org.opendaylight.controller.liblldp;
10 import static org.junit.Assert.assertArrayEquals;
12 import java.util.ArrayList;
13 import java.util.List;
15 import org.apache.commons.lang3.ArrayUtils;
16 import org.junit.Assert;
17 import org.junit.Test;
18 import org.junit.internal.ArrayComparisonFailure;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
22 import com.google.common.primitives.Bytes;
25 * Test of {@link LLDP} serialization feature (TODO: and deserialization)
27 public class LLDPTest {
29 private static final Logger LOG = LoggerFactory.getLogger(LLDPTest.class);
31 private static final byte[] CHASSIS_ID_VALUE = "chassis".getBytes();
32 private static final short CHASSIS_ID_LENGTH = (short) CHASSIS_ID_VALUE.length;
34 private static final byte[] TTL_VALUE = new byte[] { (byte) 0, (byte) 100 };
35 private static final short TTL_LENGTH = (short) TTL_VALUE.length;
37 private static final byte[] PORT_VALUE = "dummy port id".getBytes();
38 private static final short PORT_LENGTH = (short) PORT_VALUE.length;
40 private static final byte[] SYSTEM_NAME_VALUE = "dummy system name".getBytes();
41 private static final short SYSTEM_NAME_LENGTH = (short) SYSTEM_NAME_VALUE.length;
43 private static final byte SYSTEM_CAPABILITIES_TLV = 8;
44 private static final byte[] SYSTEM_CAPABILITIES_VALUE = "dummy system capabilities".getBytes();
45 private static final short SYSTEM_CAPABILITIES_LENGTH = (short) SYSTEM_CAPABILITIES_VALUE.length;
47 private static final byte[] OUI = new byte[] { (byte) 0X11, (byte) 0X22, (byte) 0X33 };
49 private static final byte[] OUI_SUBTYPE_A = new byte[] { (byte) 0 };
50 private static final byte[] CUSTOM_SUBTYPE_A_VALUE = "first custom value A".getBytes();
51 private static final short CUSTOM_SUBTYPE_A_LENGTH = (short) (OUI.length + OUI_SUBTYPE_A.length + CUSTOM_SUBTYPE_A_VALUE.length);
53 private static final byte[] OUI_SUBTYPE_B = new byte[] { (byte) 1 };
54 private static final byte[] CUSTOM_SUBTYPE_B_VALUE = "second custom value B".getBytes();
55 private static final short CUSTOM_SUBTYPE_B_LENGTH = (short) (OUI.length + OUI_SUBTYPE_B.length + CUSTOM_SUBTYPE_B_VALUE.length);
58 * Tests whether serialization of LLDP packet is correct
60 * @see LLDP#serialize()
61 * @throws PacketException
64 public void testSerialize() throws PacketException {
65 LLDP lldpBuilder = new LLDP();
67 lldpBuilder.setChassisId(dummyTlv(LLDPTLV.TLVType.ChassisID.getValue(), CHASSIS_ID_LENGTH, CHASSIS_ID_VALUE));
68 lldpBuilder.setTtl(dummyTlv(LLDPTLV.TLVType.TTL.getValue(), TTL_LENGTH, TTL_VALUE));
69 lldpBuilder.setPortId(dummyTlv(LLDPTLV.TLVType.PortID.getValue(), PORT_LENGTH, PORT_VALUE));
70 lldpBuilder.setSystemNameId(dummyTlv(LLDPTLV.TLVType.SystemName.getValue(), SYSTEM_NAME_LENGTH,
73 // adding optional TLVs for which doesn't exist special set* methods in LLDP
74 final List<LLDPTLV> optionalTLVs = new ArrayList<>();
75 // System Capabilities TLV (type = 7)
76 optionalTLVs.add(dummyTlv(SYSTEM_CAPABILITIES_TLV, SYSTEM_CAPABILITIES_LENGTH, SYSTEM_CAPABILITIES_VALUE));
77 lldpBuilder.setOptionalTLVList(optionalTLVs);
79 // // adding custom TLVs
80 final List<LLDPTLV> customTLVs = new ArrayList<>();
81 customTLVs.add(dummyCustomTlv(LLDPTLV.TLVType.Custom.getValue(), OUI, OUI_SUBTYPE_A,
82 CUSTOM_SUBTYPE_A_LENGTH, CUSTOM_SUBTYPE_A_VALUE));
83 customTLVs.add(dummyCustomTlv(LLDPTLV.TLVType.Custom.getValue(), OUI, OUI_SUBTYPE_B,
84 CUSTOM_SUBTYPE_B_LENGTH, CUSTOM_SUBTYPE_B_VALUE));
85 lldpBuilder.setCustomTLVList(customTLVs);
87 byte[] serialized = lldpBuilder.serialize();
90 offset = checkTLV(serialized, offset, (byte) 0b00000010, "ChassisID", CHASSIS_ID_LENGTH, CHASSIS_ID_VALUE);
91 offset = checkTLV(serialized, offset, (byte) 0b00000110, "TTL", TTL_LENGTH, TTL_VALUE);
92 offset = checkTLV(serialized, offset, (byte) 0b00000100, "PortID", PORT_LENGTH, PORT_VALUE);
93 offset = checkTLV(serialized, offset, (byte) 0b00001010, "SystemName", SYSTEM_NAME_LENGTH,
95 offset = checkTLV(serialized, offset, (byte) 0b00010000, "System capabilities",
96 SYSTEM_CAPABILITIES_LENGTH, SYSTEM_CAPABILITIES_VALUE);
97 offset = checkTLV(serialized, offset, (byte) 0b11111110, "Custom subtype A",
98 CUSTOM_SUBTYPE_A_LENGTH, CUSTOM_SUBTYPE_A_VALUE, OUI[0], OUI[1], OUI[2],
100 offset = checkTLV(serialized, offset, (byte) 0b11111110, "Custom subtype B",
101 CUSTOM_SUBTYPE_B_LENGTH, CUSTOM_SUBTYPE_B_VALUE, OUI[0], OUI[1], OUI[2],
107 * Tests whether serialization of LLDP packet is correct
109 * @see LLDP#deserialize(byte[], int, int)
113 public void testDeserialize() throws Exception {
114 LLDP lldp = new LLDP();
115 byte[] bytesBeforeCustomA = new byte[] { 0x00, 0x26, (byte) 0xe1, OUI_SUBTYPE_A[0] };
116 byte[] bytesBeforeCustomB = new byte[] { 0x00, 0x26, (byte) 0xe1, OUI_SUBTYPE_B[0] };
118 byte[] rawLldpTlv = Bytes.concat(
119 awaitedBytes((byte) 0b00000010, CHASSIS_ID_LENGTH, CHASSIS_ID_VALUE, null),
120 awaitedBytes((byte) 0b00000110, TTL_LENGTH, TTL_VALUE, null),
121 awaitedBytes((byte) 0b00000100, PORT_LENGTH, PORT_VALUE, null),
122 awaitedBytes((byte) 0b00001010, SYSTEM_NAME_LENGTH, SYSTEM_NAME_VALUE, null),
123 awaitedBytes((byte) 0b00010010, SYSTEM_CAPABILITIES_LENGTH,
124 SYSTEM_CAPABILITIES_VALUE, null),
125 awaitedBytes((byte) 0b11111110, CUSTOM_SUBTYPE_A_LENGTH, CUSTOM_SUBTYPE_A_VALUE,
127 awaitedBytes((byte) 0b11111110, CUSTOM_SUBTYPE_B_LENGTH, CUSTOM_SUBTYPE_B_VALUE,
128 bytesBeforeCustomB));
130 lldp.deserialize(rawLldpTlv, 0, rawLldpTlv.length * NetUtils.NumBitsInAByte);
131 Assert.assertEquals("chassis", new String(lldp.getChassisId().getValue()));
132 Assert.assertArrayEquals(TTL_VALUE, lldp.getTtl().getValue());
133 Assert.assertEquals("dummy port id", new String(lldp.getPortId().getValue()));
134 Assert.assertEquals("dummy system name", new String(lldp.getSystemNameId().getValue()));
136 // optional items check
137 List<LLDPTLV> tlvOptionalList = lldp.getOptionalTLVList();
138 Assert.assertEquals(1, tlvOptionalList.size());
140 LLDPTLV itemOpt0 = tlvOptionalList.get(0);
141 Assert.assertEquals(9, itemOpt0.getType());
142 Assert.assertEquals("dummy system capabilities", new String(itemOpt0.getValue()));
144 // custom items check
145 List<LLDPTLV> tlvCustomList = lldp.getCustomTlvList();
146 Assert.assertEquals(2, tlvCustomList.size());
148 checkCustomTlv(tlvCustomList.get(0), "first custom value A");
149 checkCustomTlv(tlvCustomList.get(1), "second custom value B");
154 * @param expectedValue
156 private static void checkCustomTlv(LLDPTLV customItem, String expectedValue) {
157 Assert.assertEquals(127, customItem.getType());
158 LOG.debug("custom TLV1.length: {}", customItem.getLength());
159 Assert.assertEquals(expectedValue,
161 LLDPTLV.getCustomString(
162 customItem.getValue(),
163 customItem.getLength()))
167 private static int checkTLV(byte[] serializedData, int offset, byte typeTLVBits, String typeTLVName, short lengthTLV,
168 byte[] valueTLV, byte... bytesBeforeValue) throws ArrayComparisonFailure {
169 byte[] concreteTlvAwaited = awaitedBytes(typeTLVBits, lengthTLV, valueTLV, bytesBeforeValue);
170 int concreteTlvAwaitLength = concreteTlvAwaited.length;
171 assertArrayEquals("Serialization problem " + typeTLVName, concreteTlvAwaited,
172 ArrayUtils.subarray(serializedData, offset, offset + concreteTlvAwaitLength));
173 return offset + concreteTlvAwaitLength;
176 private static byte[] awaitedBytes(byte typeTLV, short length, byte[] value, byte[] bytesBeforeValue) {
177 byte[] awaited = ArrayUtils.EMPTY_BYTE_ARRAY;
179 // 0 - the less meaning byte (right), 1 most meaning byte (left)
180 byte lengthByte0 = (byte) length;
181 byte lengthByte1 = (byte) (length >> 8);
183 awaited = ArrayUtils.addAll(awaited, (byte) (typeTLV | lengthByte1), lengthByte0);
184 awaited = ArrayUtils.addAll(awaited, bytesBeforeValue);
185 awaited = ArrayUtils.addAll(awaited, value);
189 private static LLDPTLV dummyCustomTlv(final byte tlvType, byte[] oui, byte[] ouiSubtype, short customLength,
190 byte[] subtypeValue) {
191 byte[] fullCustomValue = new byte[0];
192 fullCustomValue = ArrayUtils.addAll(fullCustomValue, oui);
193 fullCustomValue = ArrayUtils.addAll(fullCustomValue, ouiSubtype);
194 fullCustomValue = ArrayUtils.addAll(fullCustomValue, subtypeValue);
195 return dummyTlv(tlvType, customLength, fullCustomValue);
198 private static LLDPTLV dummyTlv(final byte concreteTlv, final short concreteLength, final byte[] concreteValue) {
199 LLDPTLV tlv = new LLDPTLV();
200 tlv.setType(concreteTlv).setLength(concreteLength).setValue(concreteValue);