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 com.google.common.collect.Iterables;
12 import java.util.LinkedHashMap;
13 import java.util.List;
17 * Class that represents the LLDP frame objects
20 public class LLDP extends Packet {
21 private static final String CHASSISID = "ChassisId";
22 private static final String SYSTEMNAMEID = "SystemNameID";
23 private static final String PORTID = "PortId";
24 private static final String TTL = "TTL";
25 private static final int LLDPDefaultTlvs = 3;
26 private static LLDPTLV emptyTLV = new LLDPTLV().setLength((short) 0).setType((byte) 0);
27 public static final byte[] LLDPMulticastMac = { 1, (byte) 0x80, (byte) 0xc2, 0, 0, (byte) 0xe };
29 private Map<Byte, LLDPTLV> mandatoryTLVs;
30 private Map<Byte, LLDPTLV> optionalTLVs;
31 private Map<CustomTLVKey, LLDPTLV> customTLVs;
34 * Default constructor that creates the tlvList LinkedHashMap
42 * Constructor that creates the tlvList LinkedHashMap and sets the write access for the same
44 public LLDP(boolean writeAccess) {
50 mandatoryTLVs = new LinkedHashMap<>(LLDPDefaultTlvs);
51 optionalTLVs = new LinkedHashMap<>();
52 customTLVs = new LinkedHashMap<>();
57 * - description of the type of TLV
58 * @return byte - type of TLV
60 private byte getType(String typeDesc) {
61 if (typeDesc.equals(CHASSISID)) {
62 return LLDPTLV.TLVType.ChassisID.getValue();
63 } else if (typeDesc.equals(PORTID)) {
64 return LLDPTLV.TLVType.PortID.getValue();
65 } else if (typeDesc.equals(TTL)) {
66 return LLDPTLV.TLVType.TTL.getValue();
67 } else if (typeDesc.equals(SYSTEMNAMEID)) {
68 return LLDPTLV.TLVType.SystemName.getValue();
70 return LLDPTLV.TLVType.Unknown.getValue();
74 private LLDPTLV getFromTLVs(Byte type) {
76 tlv = mandatoryTLVs.get(type);
78 tlv = optionalTLVs.get(type);
83 private void putToTLVs(final Byte type, final LLDPTLV tlv) {
84 if (type == LLDPTLV.TLVType.ChassisID.getValue() || type == LLDPTLV.TLVType.PortID.getValue()
85 || type == LLDPTLV.TLVType.TTL.getValue()) {
86 mandatoryTLVs.put(type, tlv);
87 } else if (type != LLDPTLV.TLVType.Custom.getValue()) {
88 optionalTLVs.put(type, tlv);
94 * - description of the type of TLV
95 * @return LLDPTLV - full TLV
97 public LLDPTLV getTLV(String type) {
98 return getFromTLVs(getType(type));
101 public LLDPTLV getCustomTLV(CustomTLVKey key) {
102 return customTLVs.get(key);
107 * - description of the type of TLV
112 public void setTLV(String type, LLDPTLV tlv) {
113 putToTLVs(getType(type), tlv);
117 * @return the chassisId TLV
119 public LLDPTLV getChassisId() {
120 return getTLV(CHASSISID);
125 * - the chassisId to set
127 public LLDP setChassisId(LLDPTLV chassisId) {
128 setTLV(CHASSISID, chassisId);
133 * @return the SystemName TLV
135 public LLDPTLV getSystemNameId() {
136 return getTLV(SYSTEMNAMEID);
141 * - the chassisId to set
143 public LLDP setSystemNameId(LLDPTLV systemNameId) {
144 setTLV(SYSTEMNAMEID, systemNameId);
149 * @return LLDPTLV - the portId TLV
151 public LLDPTLV getPortId() {
152 return getTLV(PORTID);
157 * - the portId to set
160 public LLDP setPortId(LLDPTLV portId) {
161 setTLV(PORTID, portId);
166 * @return LLDPTLV - the ttl TLV
168 public LLDPTLV getTtl() {
177 public LLDP setTtl(LLDPTLV ttl) {
183 * @return the optionalTLVList
185 public Iterable<LLDPTLV> getOptionalTLVList() {
186 return optionalTLVs.values();
190 * @return the customTlvList
192 public Iterable<LLDPTLV> getCustomTlvList() {
193 return customTLVs.values();
197 * @param optionalTLVList
198 * the optionalTLVList to set
201 public LLDP setOptionalTLVList(List<LLDPTLV> optionalTLVList) {
202 for (LLDPTLV tlv : optionalTLVList) {
203 optionalTLVs.put(tlv.getType(), tlv);
209 * @param customTLVList
210 * the list of custom TLVs to set
213 public LLDP addCustomTLV(final LLDPTLV customTLV) {
214 CustomTLVKey key = new CustomTLVKey(LLDPTLV.extractCustomOUI(customTLV),
215 LLDPTLV.extractCustomSubtype(customTLV));
216 customTLVs.put(key, customTLV);
222 public Packet deserialize(byte[] data, int bitOffset, int size) throws PacketException {
223 int lldpOffset = bitOffset; // LLDP start
224 int lldpSize = size; // LLDP size
226 if (logger.isTraceEnabled()) {
227 logger.trace("LLDP: {} (offset {} bitsize {})", new Object[] { HexEncode.bytesToHexString(data),
228 lldpOffset, lldpSize });
231 * Deserialize the TLVs until we reach the end of the packet
233 while (lldpSize > 0) {
234 LLDPTLV tlv = new LLDPTLV();
235 tlv.deserialize(data, lldpOffset, lldpSize);
236 if (tlv.getType() == 0 && tlv.getLength() == 0) {
239 int tlvSize = tlv.getTLVSize(); // Size of current TLV in bits
240 lldpOffset += tlvSize;
242 if (tlv.getType() == LLDPTLV.TLVType.Custom.getValue()) {
245 this.putToTLVs(tlv.getType(), tlv);
252 public byte[] serialize() throws PacketException {
254 byte[] serializedBytes = new byte[getLLDPPacketLength()];
256 final Iterable<LLDPTLV> allTlvs = Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values());
257 for (LLDPTLV tlv : allTlvs) {
258 int numBits = tlv.getTLVSize();
260 BitBufferHelper.setBytes(serializedBytes, tlv.serialize(), startOffset, numBits);
261 } catch (BufferException e) {
262 throw new PacketException(e.getMessage());
264 startOffset += numBits;
266 // Now add the empty LLDPTLV at the end
268 BitBufferHelper.setBytes(serializedBytes, LLDP.emptyTLV.serialize(), startOffset,
269 LLDP.emptyTLV.getTLVSize());
270 } catch (BufferException e) {
271 throw new PacketException(e.getMessage());
274 if (logger.isTraceEnabled()) {
275 logger.trace("LLDP: serialized: {}", HexEncode.bytesToHexString(serializedBytes));
277 return serializedBytes;
281 * Returns the size of LLDP packet in bytes
283 * @return int - LLDP Packet size in bytes
285 private int getLLDPPacketLength() {
288 for (LLDPTLV lldptlv : Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values())) {
289 len += lldptlv.getTLVSize();
292 len += LLDP.emptyTLV.getTLVSize();
294 return len / NetUtils.NumBitsInAByte;