From: Tony Tkacik Date: Tue, 5 May 2015 08:23:31 +0000 (+0000) Subject: Merge "BUG 2820 - LLDP refactor" X-Git-Tag: release/beryllium~613 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=dea515c8870769408b9bea29f555d6b71ff43211;hp=a54ec60368110d22794602343c934902f6833c65;p=controller.git Merge "BUG 2820 - LLDP refactor" --- diff --git a/opendaylight/commons/liblldp/pom.xml b/opendaylight/commons/liblldp/pom.xml index 01900b421b..9f4fc8d7e5 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)); } /**