From 2d82dd8cc1845228818c121070548d4784cc65b7 Mon Sep 17 00:00:00 2001 From: Jozef Gloncak Date: Tue, 17 Mar 2015 13:35:51 +0100 Subject: [PATCH] BUG 2820 - LLDP refactor LLDP class field changed from tlvList to mandatoryTLVs, optionalTLVs, customTLVs Added new create custom TLV value in order to hold security hint for LLDP topology discovery. Fixed guava bundle import Fixed apache-lang3 bundle import Change-Id: I5d0c6b9a9e29213d3f25aa99ff7edd5b30e6c7a8 Signed-off-by: Jozef Gloncak Signed-off-by: Michal Rehak (cherry picked from commit 26dfd63f953982f661e4e72f306c6a6b8e02cfd4) --- opendaylight/commons/liblldp/pom.xml | 1 + .../controller/liblldp/CustomTLVKey.java | 69 ++++++++++ .../opendaylight/controller/liblldp/LLDP.java | 130 +++++++++--------- .../controller/liblldp/LLDPTLV.java | 58 ++++++-- .../controller/liblldp/LLDPTest.java | 121 ++++++++++++---- 5 files changed, 275 insertions(+), 104 deletions(-) create mode 100644 opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/CustomTLVKey.java diff --git a/opendaylight/commons/liblldp/pom.xml b/opendaylight/commons/liblldp/pom.xml index 5e14c92ee7..286c68e677 100644 --- a/opendaylight/commons/liblldp/pom.xml +++ b/opendaylight/commons/liblldp/pom.xml @@ -27,6 +27,7 @@ org.slf4j slf4j-log4j12 + test com.google.guava diff --git a/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/CustomTLVKey.java b/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/CustomTLVKey.java new file mode 100644 index 0000000000..7bc631e5a6 --- /dev/null +++ b/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/CustomTLVKey.java @@ -0,0 +1,69 @@ +/** + * + */ +package org.opendaylight.controller.liblldp; + +public class CustomTLVKey { + + private int oui; + private byte subtype; + + /** + * @param oui + * @param subtype + */ + public CustomTLVKey(int oui, byte subtype) { + this.oui = oui; + this.subtype = subtype; + } + + /** + * @return the oui + */ + public int getOui() { + return oui; + } + /** + * @return the subtype + */ + public byte getSubtype() { + return subtype; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + oui; + result = prime * result + subtype; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null) { + return false; + } + + if (getClass() != obj.getClass()) { + return false; + } + + CustomTLVKey other = (CustomTLVKey) obj; + if (oui != other.oui) { + return false; + } + + if (subtype != other.subtype) { + return false; + } + + return true; + } + + +} diff --git a/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/LLDP.java b/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/LLDP.java index c7dc6915ad..85b2cbf82e 100644 --- a/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/LLDP.java +++ b/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/LLDP.java @@ -9,7 +9,6 @@ package org.opendaylight.controller.liblldp; import com.google.common.collect.Iterables; -import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -23,32 +22,34 @@ public class LLDP extends Packet { private static final String SYSTEMNAMEID = "SystemNameID"; private static final String PORTID = "PortId"; private static final String TTL = "TTL"; - private static final int LLDPDefaultTlvs = 4; - private static LLDPTLV emptyTLV = new LLDPTLV().setLength((short) 0) - .setType((byte) 0); - public static final byte[] LLDPMulticastMac = { 1, (byte) 0x80, - (byte) 0xc2, 0, 0, (byte) 0xe }; - private Map tlvList; + private static final int LLDPDefaultTlvs = 3; + private static LLDPTLV emptyTLV = new LLDPTLV().setLength((short) 0).setType((byte) 0); + public static final byte[] LLDPMulticastMac = { 1, (byte) 0x80, (byte) 0xc2, 0, 0, (byte) 0xe }; - private List customTlvList; + private Map mandatoryTLVs; + private Map optionalTLVs; + private Map customTLVs; /** * Default constructor that creates the tlvList LinkedHashMap */ public LLDP() { super(); - tlvList = new LinkedHashMap<>(LLDPDefaultTlvs); - customTlvList = new ArrayList<>(); + init(); } /** - * Constructor that creates the tlvList LinkedHashMap and sets the write - * access for the same + * Constructor that creates the tlvList LinkedHashMap and sets the write access for the same */ public LLDP(boolean writeAccess) { super(writeAccess); - tlvList = new LinkedHashMap(LLDPDefaultTlvs); // Mandatory - // TLVs + init(); + } + + private void init() { + mandatoryTLVs = new LinkedHashMap<>(LLDPDefaultTlvs); + optionalTLVs = new LinkedHashMap<>(); + customTLVs = new LinkedHashMap<>(); } /** @@ -70,13 +71,35 @@ public class LLDP extends Packet { } } + private LLDPTLV getFromTLVs(Byte type) { + LLDPTLV tlv = null; + tlv = mandatoryTLVs.get(type); + if (tlv == null) { + tlv = optionalTLVs.get(type); + } + return tlv; + } + + private void putToTLVs(final Byte type, final LLDPTLV tlv) { + if (type == LLDPTLV.TLVType.ChassisID.getValue() || type == LLDPTLV.TLVType.PortID.getValue() + || type == LLDPTLV.TLVType.TTL.getValue()) { + mandatoryTLVs.put(type, tlv); + } else if (type != LLDPTLV.TLVType.Custom.getValue()) { + optionalTLVs.put(type, tlv); + } + } + /** * @param String * - description of the type of TLV * @return LLDPTLV - full TLV */ public LLDPTLV getTLV(String type) { - return tlvList.get(getType(type)); + return getFromTLVs(getType(type)); + } + + public LLDPTLV getCustomTLV(CustomTLVKey key) { + return customTLVs.get(key); } /** @@ -87,7 +110,7 @@ public class LLDP extends Packet { * @return void */ public void setTLV(String type, LLDPTLV tlv) { - tlvList.put(getType(type), tlv); + putToTLVs(getType(type), tlv); } /** @@ -102,7 +125,7 @@ public class LLDP extends Packet { * - the chassisId to set */ public LLDP setChassisId(LLDPTLV chassisId) { - tlvList.put(getType(CHASSISID), chassisId); + setTLV(CHASSISID, chassisId); return this; } @@ -118,7 +141,7 @@ public class LLDP extends Packet { * - the chassisId to set */ public LLDP setSystemNameId(LLDPTLV systemNameId) { - tlvList.put(getType(SYSTEMNAMEID), systemNameId); + setTLV(SYSTEMNAMEID, systemNameId); return this; } @@ -126,7 +149,7 @@ public class LLDP extends Packet { * @return LLDPTLV - the portId TLV */ public LLDPTLV getPortId() { - return tlvList.get(getType(PORTID)); + return getTLV(PORTID); } /** @@ -135,7 +158,7 @@ public class LLDP extends Packet { * @return LLDP */ public LLDP setPortId(LLDPTLV portId) { - tlvList.put(getType(PORTID), portId); + setTLV(PORTID, portId); return this; } @@ -143,7 +166,7 @@ public class LLDP extends Packet { * @return LLDPTLV - the ttl TLV */ public LLDPTLV getTtl() { - return tlvList.get(getType(TTL)); + return getTLV(TTL); } /** @@ -152,34 +175,22 @@ public class LLDP extends Packet { * @return LLDP */ public LLDP setTtl(LLDPTLV ttl) { - tlvList.put(getType(TTL), ttl); + setTLV(TTL, ttl); return this; } /** * @return the optionalTLVList */ - public List getOptionalTLVList() { - List list = new ArrayList(); - for (Map.Entry entry : tlvList.entrySet()) { - byte type = entry.getKey(); - if ((type == LLDPTLV.TLVType.ChassisID.getValue()) - || (type == LLDPTLV.TLVType.PortID.getValue()) - || (type == LLDPTLV.TLVType.TTL.getValue()) - || (type == LLDPTLV.TLVType.SystemName.getValue())) { - continue; - } else { - list.add(entry.getValue()); - } - } - return list; + public Iterable getOptionalTLVList() { + return optionalTLVs.values(); } /** * @return the customTlvList */ - public List getCustomTlvList() { - return customTlvList; + public Iterable getCustomTlvList() { + return customTLVs.values(); } /** @@ -189,7 +200,7 @@ public class LLDP extends Packet { */ public LLDP setOptionalTLVList(List optionalTLVList) { for (LLDPTLV tlv : optionalTLVList) { - tlvList.put(tlv.getType(), tlv); + optionalTLVs.put(tlv.getType(), tlv); } return this; } @@ -199,20 +210,22 @@ public class LLDP extends Packet { * the list of custom TLVs to set * @return this LLDP */ - public LLDP setCustomTLVList(final List customTLVList) { - this.customTlvList = new ArrayList<>(customTLVList); + public LLDP addCustomTLV(final LLDPTLV customTLV) { + CustomTLVKey key = new CustomTLVKey(LLDPTLV.extractCustomOUI(customTLV), + LLDPTLV.extractCustomSubtype(customTLV)); + customTLVs.put(key, customTLV); + return this; } @Override - public Packet deserialize(byte[] data, int bitOffset, int size) - throws PacketException { + public Packet deserialize(byte[] data, int bitOffset, int size) throws PacketException { int lldpOffset = bitOffset; // LLDP start int lldpSize = size; // LLDP size if (logger.isTraceEnabled()) { - logger.trace("LLDP: {} (offset {} bitsize {})", new Object[] { - HexEncode.bytesToHexString(data), lldpOffset, lldpSize }); + logger.trace("LLDP: {} (offset {} bitsize {})", new Object[] { HexEncode.bytesToHexString(data), + lldpOffset, lldpSize }); } /* * Deserialize the TLVs until we reach the end of the packet @@ -221,15 +234,15 @@ public class LLDP extends Packet { LLDPTLV tlv = new LLDPTLV(); tlv.deserialize(data, lldpOffset, lldpSize); if (tlv.getType() == 0 && tlv.getLength() == 0) { - break; + break; } int tlvSize = tlv.getTLVSize(); // Size of current TLV in bits lldpOffset += tlvSize; lldpSize -= tlvSize; if (tlv.getType() == LLDPTLV.TLVType.Custom.getValue()) { - customTlvList.add(tlv); + addCustomTLV(tlv); } else { - this.tlvList.put(tlv.getType(), tlv); + this.putToTLVs(tlv.getType(), tlv); } } return this; @@ -240,12 +253,11 @@ public class LLDP extends Packet { int startOffset = 0; byte[] serializedBytes = new byte[getLLDPPacketLength()]; - final Iterable allTlvs = Iterables.concat(tlvList.values(), customTlvList); + final Iterable allTlvs = Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values()); for (LLDPTLV tlv : allTlvs) { int numBits = tlv.getTLVSize(); try { - BitBufferHelper.setBytes(serializedBytes, tlv.serialize(), - startOffset, numBits); + BitBufferHelper.setBytes(serializedBytes, tlv.serialize(), startOffset, numBits); } catch (BufferException e) { throw new PacketException(e.getMessage()); } @@ -253,16 +265,14 @@ public class LLDP extends Packet { } // Now add the empty LLDPTLV at the end try { - BitBufferHelper.setBytes(serializedBytes, - LLDP.emptyTLV.serialize(), startOffset, + BitBufferHelper.setBytes(serializedBytes, LLDP.emptyTLV.serialize(), startOffset, LLDP.emptyTLV.getTLVSize()); } catch (BufferException e) { throw new PacketException(e.getMessage()); } if (logger.isTraceEnabled()) { - logger.trace("LLDP: serialized: {}", - HexEncode.bytesToHexString(serializedBytes)); + logger.trace("LLDP: serialized: {}", HexEncode.bytesToHexString(serializedBytes)); } return serializedBytes; } @@ -274,15 +284,9 @@ public class LLDP extends Packet { */ private int getLLDPPacketLength() { int len = 0; - LLDPTLV tlv; - - for (Map.Entry entry : this.tlvList.entrySet()) { - tlv = entry.getValue(); - len += tlv.getTLVSize(); - } - for (LLDPTLV customTlv : this.customTlvList) { - len += customTlv.getTLVSize(); + for (LLDPTLV lldptlv : Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values())) { + len += lldptlv.getTLVSize(); } len += LLDP.emptyTLV.getTLVSize(); diff --git a/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/LLDPTLV.java b/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/LLDPTLV.java index 22bd4626d1..7b93d5f19c 100644 --- a/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/LLDPTLV.java +++ b/opendaylight/commons/liblldp/src/main/java/org/opendaylight/controller/liblldp/LLDPTLV.java @@ -8,13 +8,16 @@ package org.opendaylight.controller.liblldp; +import org.apache.commons.lang3.ArrayUtils; +import org.slf4j.LoggerFactory; + +import org.slf4j.Logger; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; - import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -27,14 +30,26 @@ public class LLDPTLV extends Packet { private static final String LENGTH = "Length"; private static final String VALUE = "Value"; private static final int LLDPTLVFields = 3; + + /** OpenFlow OUI */ public static final byte[] OFOUI = new byte[] { (byte) 0x00, (byte) 0x26, - (byte) 0xe1 }; // OpenFlow OUI - public static final byte[] customTlvSubType = new byte[] { 0 }; - public static final int customTlvOffset = OFOUI.length - + customTlvSubType.length; + (byte) 0xe1 }; + + /** Length of Organizationally defined subtype field of TLV in bytes */ + private static final byte customTlvSubTypeLength = (byte)1; + + /** OpenFlow subtype: nodeConnectorId of source */ + public static final byte[] CUSTOM_TLV_SUB_TYPE_NODE_CONNECTOR_ID = new byte[] { 0 }; + + /** OpenFlow subtype: custom sec = hash code of verification of origin of LLDP */ + public static final byte[] CUSTOM_TLV_SUB_TYPE_CUSTOM_SEC = new byte[] { 1 }; + + public static final int customTlvOffset = OFOUI.length + customTlvSubTypeLength; public static final byte chassisIDSubType[] = new byte[] { 4 }; // MAC address for the system public static final byte portIDSubType[] = new byte[] { 7 }; // locally assigned + private static final Logger LOG = LoggerFactory.getLogger(LLDPTLV.class); + public enum TLVType { Unknown((byte) 0), ChassisID((byte) 1), PortID((byte) 2), TTL((byte) 3), PortDesc( (byte) 4), SystemName((byte) 5), SystemDesc((byte) 6), Custom( @@ -254,16 +269,27 @@ public class LLDPTLV extends Packet { * @param portId * port identifier string * @return the custom TLV value in byte array + * @see {@link #createCustomTLVValue(byte,String)} */ static public byte[] createCustomTLVValue(String customString) { - byte[] customArray = customString.getBytes(Charset.defaultCharset()); - byte[] customValue = new byte[customTlvOffset + customArray.length]; + byte[] customByteArray = customString.getBytes(Charset.defaultCharset()); + return createCustomTLVValue(CUSTOM_TLV_SUB_TYPE_NODE_CONNECTOR_ID, customByteArray); + } + + /** + * Creates the custom TLV value including OUI, subtype and custom string + * @param subtype openflow subtype + * @param portId + * port identifier string + * @return the custom TLV value in byte array + */ + static public byte[] createCustomTLVValue(byte[] subtype, byte[] customByteArray) { + byte[] customValue = new byte[customTlvOffset + customByteArray.length]; System.arraycopy(OFOUI, 0, customValue, 0, OFOUI.length); - System.arraycopy(customTlvSubType, 0, customValue, OFOUI.length, - customTlvSubType.length); - System.arraycopy(customArray, 0, customValue, customTlvOffset, - customArray.length); + System.arraycopy(subtype, 0, customValue, OFOUI.length, 1); + System.arraycopy(customByteArray, 0, customValue, customTlvOffset, + customByteArray.length); return customValue; } @@ -334,4 +360,14 @@ public class LLDPTLV extends Packet { return customString; } + + public static int extractCustomOUI(final LLDPTLV lldptlv) { + byte[] value = lldptlv.getValue(); + return BitBufferHelper.getInt(ArrayUtils.subarray(value, 0, 3)); + } + + public static byte extractCustomSubtype(final LLDPTLV lldptlv) { + byte[] value = lldptlv.getValue(); + return BitBufferHelper.getByte(ArrayUtils.subarray(value, 3, 4)); + } } diff --git a/opendaylight/commons/liblldp/src/test/java/org/opendaylight/controller/liblldp/LLDPTest.java b/opendaylight/commons/liblldp/src/test/java/org/opendaylight/controller/liblldp/LLDPTest.java index 1a14e0b650..8bd700875a 100644 --- a/opendaylight/commons/liblldp/src/test/java/org/opendaylight/controller/liblldp/LLDPTest.java +++ b/opendaylight/commons/liblldp/src/test/java/org/opendaylight/controller/liblldp/LLDPTest.java @@ -8,7 +8,13 @@ package org.opendaylight.controller.liblldp; import static org.junit.Assert.assertArrayEquals; - +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import java.util.Iterator; import java.util.ArrayList; import java.util.List; @@ -44,7 +50,7 @@ public class LLDPTest { private static final byte[] SYSTEM_CAPABILITIES_VALUE = "dummy system capabilities".getBytes(); private static final short SYSTEM_CAPABILITIES_LENGTH = (short) SYSTEM_CAPABILITIES_VALUE.length; - private static final byte[] OUI = new byte[] { (byte) 0X11, (byte) 0X22, (byte) 0X33 }; + private static final byte[] OUI = LLDPTLV.OFOUI; private static final byte[] OUI_SUBTYPE_A = new byte[] { (byte) 0 }; private static final byte[] CUSTOM_SUBTYPE_A_VALUE = "first custom value A".getBytes(); @@ -54,6 +60,15 @@ public class LLDPTest { private static final byte[] CUSTOM_SUBTYPE_B_VALUE = "second custom value B".getBytes(); private static final short CUSTOM_SUBTYPE_B_LENGTH = (short) (OUI.length + OUI_SUBTYPE_B.length + CUSTOM_SUBTYPE_B_VALUE.length); + private static final byte[] BYTES_BEFORE_CUSTOM_A = new byte[] { 0x00, 0x26, (byte) 0xe1, OUI_SUBTYPE_A[0] }; + private static final byte[] BYTES_BEFORE_CUSTOM_B = new byte[] { 0x00, 0x26, (byte) 0xe1, OUI_SUBTYPE_B[0] }; + private LLDP lldpBuilder; + + @Before + public void setup() { + lldpBuilder = new LLDP(); + } + /** * Tests whether serialization of LLDP packet is correct * @@ -62,8 +77,6 @@ public class LLDPTest { */ @Test public void testSerialize() throws PacketException { - LLDP lldpBuilder = new LLDP(); - lldpBuilder.setChassisId(dummyTlv(LLDPTLV.TLVType.ChassisID.getValue(), CHASSIS_ID_LENGTH, CHASSIS_ID_VALUE)); lldpBuilder.setTtl(dummyTlv(LLDPTLV.TLVType.TTL.getValue(), TTL_LENGTH, TTL_VALUE)); lldpBuilder.setPortId(dummyTlv(LLDPTLV.TLVType.PortID.getValue(), PORT_LENGTH, PORT_VALUE)); @@ -76,13 +89,11 @@ public class LLDPTest { optionalTLVs.add(dummyTlv(SYSTEM_CAPABILITIES_TLV, SYSTEM_CAPABILITIES_LENGTH, SYSTEM_CAPABILITIES_VALUE)); lldpBuilder.setOptionalTLVList(optionalTLVs); - // // adding custom TLVs - final List customTLVs = new ArrayList<>(); - customTLVs.add(dummyCustomTlv(LLDPTLV.TLVType.Custom.getValue(), OUI, OUI_SUBTYPE_A, - CUSTOM_SUBTYPE_A_LENGTH, CUSTOM_SUBTYPE_A_VALUE)); - customTLVs.add(dummyCustomTlv(LLDPTLV.TLVType.Custom.getValue(), OUI, OUI_SUBTYPE_B, - CUSTOM_SUBTYPE_B_LENGTH, CUSTOM_SUBTYPE_B_VALUE)); - lldpBuilder.setCustomTLVList(customTLVs); + // adding custom TLVs + lldpBuilder.addCustomTLV(dummyCustomTlv(LLDPTLV.TLVType.Custom.getValue(), OUI, OUI_SUBTYPE_A, + CUSTOM_SUBTYPE_A_LENGTH, CUSTOM_SUBTYPE_A_VALUE)); + lldpBuilder.addCustomTLV(dummyCustomTlv(LLDPTLV.TLVType.Custom.getValue(), OUI, OUI_SUBTYPE_B, + CUSTOM_SUBTYPE_B_LENGTH, CUSTOM_SUBTYPE_B_VALUE)); byte[] serialized = lldpBuilder.serialize(); @@ -111,9 +122,6 @@ public class LLDPTest { */ @Test public void testDeserialize() throws Exception { - LLDP lldp = new LLDP(); - byte[] bytesBeforeCustomA = new byte[] { 0x00, 0x26, (byte) 0xe1, OUI_SUBTYPE_A[0] }; - byte[] bytesBeforeCustomB = new byte[] { 0x00, 0x26, (byte) 0xe1, OUI_SUBTYPE_B[0] }; byte[] rawLldpTlv = Bytes.concat( awaitedBytes((byte) 0b00000010, CHASSIS_ID_LENGTH, CHASSIS_ID_VALUE, null), @@ -123,30 +131,83 @@ public class LLDPTest { awaitedBytes((byte) 0b00010010, SYSTEM_CAPABILITIES_LENGTH, SYSTEM_CAPABILITIES_VALUE, null), awaitedBytes((byte) 0b11111110, CUSTOM_SUBTYPE_A_LENGTH, CUSTOM_SUBTYPE_A_VALUE, - bytesBeforeCustomA), + BYTES_BEFORE_CUSTOM_A), awaitedBytes((byte) 0b11111110, CUSTOM_SUBTYPE_B_LENGTH, CUSTOM_SUBTYPE_B_VALUE, - bytesBeforeCustomB)); + BYTES_BEFORE_CUSTOM_B)); - lldp.deserialize(rawLldpTlv, 0, rawLldpTlv.length * NetUtils.NumBitsInAByte); - Assert.assertEquals("chassis", new String(lldp.getChassisId().getValue())); - Assert.assertArrayEquals(TTL_VALUE, lldp.getTtl().getValue()); - Assert.assertEquals("dummy port id", new String(lldp.getPortId().getValue())); - Assert.assertEquals("dummy system name", new String(lldp.getSystemNameId().getValue())); + lldpBuilder.deserialize(rawLldpTlv, 0, rawLldpTlv.length * NetUtils.NumBitsInAByte); + Assert.assertEquals("chassis", new String(lldpBuilder.getChassisId().getValue())); + Assert.assertArrayEquals(TTL_VALUE, lldpBuilder.getTtl().getValue()); + Assert.assertEquals("dummy port id", new String(lldpBuilder.getPortId().getValue())); + Assert.assertEquals("dummy system name", new String(lldpBuilder.getSystemNameId().getValue())); // optional items check - List tlvOptionalList = lldp.getOptionalTLVList(); - Assert.assertEquals(1, tlvOptionalList.size()); + Iterator iteratorTlvOptional = lldpBuilder.getOptionalTLVList().iterator(); + + assertTrue(iteratorTlvOptional.hasNext()); + LLDPTLV item0 = iteratorTlvOptional.next(); + Assert.assertEquals(5, item0.getType()); + Assert.assertEquals("dummy system name", new String(item0.getValue())); + assertTrue(iteratorTlvOptional.hasNext()); - LLDPTLV itemOpt0 = tlvOptionalList.get(0); - Assert.assertEquals(9, itemOpt0.getType()); - Assert.assertEquals("dummy system capabilities", new String(itemOpt0.getValue())); + assertTrue(iteratorTlvOptional.hasNext()); + LLDPTLV item1 = iteratorTlvOptional.next(); + Assert.assertEquals(9, item1.getType()); + Assert.assertEquals("dummy system capabilities", new String(item1.getValue())); + assertFalse(iteratorTlvOptional.hasNext()); // custom items check - List tlvCustomList = lldp.getCustomTlvList(); - Assert.assertEquals(2, tlvCustomList.size()); + Iterable customTlvs = lldpBuilder.getCustomTlvList(); + Iterator iteratorLLDPTLV = customTlvs.iterator(); + assertEquals(true, iteratorLLDPTLV.hasNext()); + checkCustomTlv(iteratorLLDPTLV.next(), "first custom value A"); + assertEquals(true, iteratorLLDPTLV.hasNext()); + checkCustomTlv(iteratorLLDPTLV.next(), "second custom value B"); + assertEquals(false, iteratorLLDPTLV.hasNext()); + } - checkCustomTlv(tlvCustomList.get(0), "first custom value A"); - checkCustomTlv(tlvCustomList.get(1), "second custom value B"); + /** + * Test of {@link LLDP#addCustomTLV(LLDPTLV)} + * @throws PacketException + */ + @Test + public void testAddCustomTLV() throws PacketException { + byte[] customA = awaitedBytes((byte) 0b11111110, CUSTOM_SUBTYPE_A_LENGTH, CUSTOM_SUBTYPE_A_VALUE, + BYTES_BEFORE_CUSTOM_A); + byte[] customB = awaitedBytes((byte) 0b11111110, CUSTOM_SUBTYPE_B_LENGTH, CUSTOM_SUBTYPE_B_VALUE, + BYTES_BEFORE_CUSTOM_B); + + Packet lldptlvA = new LLDPTLV().deserialize(customA, 0, customA.length); + assertTrue(lldptlvA instanceof LLDPTLV); + Packet lldptlvB = new LLDPTLV().deserialize(customB, 0, customB.length); + assertTrue(lldptlvB instanceof LLDPTLV); + + lldpBuilder.addCustomTLV((LLDPTLV) lldptlvA); + lldpBuilder.addCustomTLV((LLDPTLV) lldptlvB); + + Iterator customTLVsIterator = lldpBuilder.getCustomTlvList().iterator(); + assertTrue(customTLVsIterator.hasNext()); + customTLVsIterator.next(); + assertTrue(customTLVsIterator.hasNext()); + customTLVsIterator.next(); + assertFalse(customTLVsIterator.hasNext()); + } + + @Test + public void testGetCustomTLV() throws PacketException { + int ouiInt = BitBufferHelper.getInt(OUI); + CustomTLVKey key = new CustomTLVKey(ouiInt, OUI_SUBTYPE_A[0]); + LLDPTLV customTLV = lldpBuilder.getCustomTLV(key); + assertNull(customTLV); + + byte[] customA = awaitedBytes((byte) 0b11111110, CUSTOM_SUBTYPE_A_LENGTH, CUSTOM_SUBTYPE_A_VALUE, + BYTES_BEFORE_CUSTOM_A); + lldpBuilder.deserialize(customA, 0, customA.length); + + customTLV = lldpBuilder.getCustomTLV(key); + assertNotNull(customTLV); + assertEquals(ouiInt, LLDPTLV.extractCustomOUI(customTLV)); + assertEquals(OUI_SUBTYPE_A[0], LLDPTLV.extractCustomSubtype(customTLV)); } /** -- 2.36.6