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 java.util.LinkedHashMap;
12 import java.util.List;
15 import com.google.common.collect.Iterables;
18 * Class that represents the LLDP frame objects
21 public class LLDP extends Packet {
22 private static final String CHASSISID = "ChassisId";
23 private static final String SYSTEMNAMEID = "SystemNameID";
24 private static final String PORTID = "PortId";
25 private static final String TTL = "TTL";
26 private static final int LLDPDefaultTlvs = 3;
27 private static LLDPTLV emptyTLV = new LLDPTLV().setLength((short) 0).setType((byte) 0);
28 public static final byte[] LLDPMulticastMac = { 1, (byte) 0x80, (byte) 0xc2, 0, 0, (byte) 0xe };
30 private Map<Byte, LLDPTLV> mandatoryTLVs;
31 private Map<Byte, LLDPTLV> optionalTLVs;
32 private Map<CustomTLVKey, LLDPTLV> customTLVs;
35 * Default constructor that creates the tlvList LinkedHashMap
43 * Constructor that creates the tlvList LinkedHashMap and sets the write access for the same
45 public LLDP(boolean writeAccess) {
51 mandatoryTLVs = new LinkedHashMap<>(LLDPDefaultTlvs);
52 optionalTLVs = new LinkedHashMap<>();
53 customTLVs = new LinkedHashMap<>();
58 * - description of the type of TLV
59 * @return byte - type of TLV
61 private byte getType(String typeDesc) {
62 if (typeDesc.equals(CHASSISID)) {
63 return LLDPTLV.TLVType.ChassisID.getValue();
64 } else if (typeDesc.equals(PORTID)) {
65 return LLDPTLV.TLVType.PortID.getValue();
66 } else if (typeDesc.equals(TTL)) {
67 return LLDPTLV.TLVType.TTL.getValue();
68 } else if (typeDesc.equals(SYSTEMNAMEID)) {
69 return LLDPTLV.TLVType.SystemName.getValue();
71 return LLDPTLV.TLVType.Unknown.getValue();
75 private LLDPTLV getFromTLVs(Byte type) {
77 tlv = mandatoryTLVs.get(type);
79 tlv = optionalTLVs.get(type);
84 private void putToTLVs(final Byte type, final LLDPTLV tlv) {
85 if (type == LLDPTLV.TLVType.ChassisID.getValue() || type == LLDPTLV.TLVType.PortID.getValue()
86 || type == LLDPTLV.TLVType.TTL.getValue()) {
87 mandatoryTLVs.put(type, tlv);
88 } else if (type != LLDPTLV.TLVType.Custom.getValue()) {
89 optionalTLVs.put(type, tlv);
95 * - description of the type of TLV
96 * @return LLDPTLV - full TLV
98 public LLDPTLV getTLV(String type) {
99 return getFromTLVs(getType(type));
102 public LLDPTLV getCustomTLV(CustomTLVKey key) {
103 return customTLVs.get(key);
108 * - description of the type of TLV
113 public void setTLV(String type, LLDPTLV tlv) {
114 putToTLVs(getType(type), tlv);
118 * @return the chassisId TLV
120 public LLDPTLV getChassisId() {
121 return getTLV(CHASSISID);
126 * - the chassisId to set
128 public LLDP setChassisId(LLDPTLV chassisId) {
129 setTLV(CHASSISID, chassisId);
134 * @return the SystemName TLV
136 public LLDPTLV getSystemNameId() {
137 return getTLV(SYSTEMNAMEID);
142 * - the chassisId to set
144 public LLDP setSystemNameId(LLDPTLV systemNameId) {
145 setTLV(SYSTEMNAMEID, systemNameId);
150 * @return LLDPTLV - the portId TLV
152 public LLDPTLV getPortId() {
153 return getTLV(PORTID);
158 * - the portId to set
161 public LLDP setPortId(LLDPTLV portId) {
162 setTLV(PORTID, portId);
167 * @return LLDPTLV - the ttl TLV
169 public LLDPTLV getTtl() {
178 public LLDP setTtl(LLDPTLV ttl) {
184 * @return the optionalTLVList
186 public Iterable<LLDPTLV> getOptionalTLVList() {
187 return optionalTLVs.values();
191 * @return the customTlvList
193 public Iterable<LLDPTLV> getCustomTlvList() {
194 return customTLVs.values();
198 * @param optionalTLVList
199 * the optionalTLVList to set
202 public LLDP setOptionalTLVList(List<LLDPTLV> optionalTLVList) {
203 for (LLDPTLV tlv : optionalTLVList) {
204 optionalTLVs.put(tlv.getType(), tlv);
210 * @param customTLVList
211 * the list of custom TLVs to set
214 public LLDP addCustomTLV(final LLDPTLV customTLV) {
215 CustomTLVKey key = new CustomTLVKey(LLDPTLV.extractCustomOUI(customTLV),
216 LLDPTLV.extractCustomSubtype(customTLV));
217 customTLVs.put(key, customTLV);
223 public Packet deserialize(byte[] data, int bitOffset, int size) throws PacketException {
224 int lldpOffset = bitOffset; // LLDP start
225 int lldpSize = size; // LLDP size
227 if (logger.isTraceEnabled()) {
228 logger.trace("LLDP: {} (offset {} bitsize {})", new Object[] { HexEncode.bytesToHexString(data),
229 lldpOffset, lldpSize });
232 * Deserialize the TLVs until we reach the end of the packet
234 while (lldpSize > 0) {
235 LLDPTLV tlv = new LLDPTLV();
236 tlv.deserialize(data, lldpOffset, lldpSize);
237 if (tlv.getType() == 0 && tlv.getLength() == 0) {
240 int tlvSize = tlv.getTLVSize(); // Size of current TLV in bits
241 lldpOffset += tlvSize;
243 if (tlv.getType() == LLDPTLV.TLVType.Custom.getValue()) {
246 this.putToTLVs(tlv.getType(), tlv);
253 public byte[] serialize() throws PacketException {
255 byte[] serializedBytes = new byte[getLLDPPacketLength()];
257 final Iterable<LLDPTLV> allTlvs = Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values());
258 for (LLDPTLV tlv : allTlvs) {
259 int numBits = tlv.getTLVSize();
261 BitBufferHelper.setBytes(serializedBytes, tlv.serialize(), startOffset, numBits);
262 } catch (BufferException e) {
263 throw new PacketException(e.getMessage());
265 startOffset += numBits;
267 // Now add the empty LLDPTLV at the end
269 BitBufferHelper.setBytes(serializedBytes, LLDP.emptyTLV.serialize(), startOffset,
270 LLDP.emptyTLV.getTLVSize());
271 } catch (BufferException e) {
272 throw new PacketException(e.getMessage());
275 if (logger.isTraceEnabled()) {
276 logger.trace("LLDP: serialized: {}", HexEncode.bytesToHexString(serializedBytes));
278 return serializedBytes;
282 * Returns the size of LLDP packet in bytes
284 * @return int - LLDP Packet size in bytes
286 private int getLLDPPacketLength() {
289 for (LLDPTLV lldptlv : Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values())) {
290 len += lldptlv.getTLVSize();
293 len += LLDP.emptyTLV.getTLVSize();
295 return len / NetUtils.NumBitsInAByte;