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.ArrayList;
12 import java.util.LinkedHashMap;
13 import java.util.List;
16 import com.google.common.collect.Iterables;
19 * Class that represents the LLDP frame objects
22 public class LLDP extends Packet {
23 private static final String CHASSISID = "ChassisId";
24 private static final String SYSTEMNAMEID = "SystemNameID";
25 private static final String PORTID = "PortId";
26 private static final String TTL = "TTL";
27 private static final int LLDPDefaultTlvs = 4;
28 private static LLDPTLV emptyTLV = new LLDPTLV().setLength((short) 0)
30 public static final byte[] LLDPMulticastMac = { 1, (byte) 0x80,
31 (byte) 0xc2, 0, 0, (byte) 0xe };
32 private Map<Byte, LLDPTLV> tlvList;
34 private List<LLDPTLV> customTlvList;
37 * Default constructor that creates the tlvList LinkedHashMap
41 tlvList = new LinkedHashMap<>(LLDPDefaultTlvs);
42 customTlvList = new ArrayList<>();
46 * Constructor that creates the tlvList LinkedHashMap and sets the write
49 public LLDP(boolean writeAccess) {
51 tlvList = new LinkedHashMap<Byte, LLDPTLV>(LLDPDefaultTlvs); // Mandatory
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();
76 * - description of the type of TLV
77 * @return LLDPTLV - full TLV
79 public LLDPTLV getTLV(String type) {
80 return tlvList.get(getType(type));
85 * - description of the type of TLV
90 public void setTLV(String type, LLDPTLV tlv) {
91 tlvList.put(getType(type), tlv);
95 * @return the chassisId TLV
97 public LLDPTLV getChassisId() {
98 return getTLV(CHASSISID);
103 * - the chassisId to set
105 public LLDP setChassisId(LLDPTLV chassisId) {
106 tlvList.put(getType(CHASSISID), chassisId);
111 * @return the SystemName TLV
113 public LLDPTLV getSystemNameId() {
114 return getTLV(SYSTEMNAMEID);
119 * - the chassisId to set
121 public LLDP setSystemNameId(LLDPTLV systemNameId) {
122 tlvList.put(getType(SYSTEMNAMEID), systemNameId);
127 * @return LLDPTLV - the portId TLV
129 public LLDPTLV getPortId() {
130 return tlvList.get(getType(PORTID));
135 * - the portId to set
138 public LLDP setPortId(LLDPTLV portId) {
139 tlvList.put(getType(PORTID), portId);
144 * @return LLDPTLV - the ttl TLV
146 public LLDPTLV getTtl() {
147 return tlvList.get(getType(TTL));
155 public LLDP setTtl(LLDPTLV ttl) {
156 tlvList.put(getType(TTL), ttl);
161 * @return the optionalTLVList
163 public List<LLDPTLV> getOptionalTLVList() {
164 List<LLDPTLV> list = new ArrayList<LLDPTLV>();
165 for (Map.Entry<Byte, LLDPTLV> entry : tlvList.entrySet()) {
166 byte type = entry.getKey();
167 if ((type == LLDPTLV.TLVType.ChassisID.getValue())
168 || (type == LLDPTLV.TLVType.PortID.getValue())
169 || (type == LLDPTLV.TLVType.TTL.getValue())
170 || (type == LLDPTLV.TLVType.SystemName.getValue())) {
173 list.add(entry.getValue());
180 * @return the customTlvList
182 public List<LLDPTLV> getCustomTlvList() {
183 return customTlvList;
187 * @param optionalTLVList
188 * the optionalTLVList to set
191 public LLDP setOptionalTLVList(List<LLDPTLV> optionalTLVList) {
192 for (LLDPTLV tlv : optionalTLVList) {
193 tlvList.put(tlv.getType(), tlv);
199 * @param customTLVList
200 * the list of custom TLVs to set
203 public LLDP setCustomTLVList(final List<LLDPTLV> customTLVList) {
204 this.customTlvList = new ArrayList<>(customTLVList);
209 public Packet deserialize(byte[] data, int bitOffset, int size)
210 throws PacketException {
211 int lldpOffset = bitOffset; // LLDP start
212 int lldpSize = size; // LLDP size
214 if (logger.isTraceEnabled()) {
215 logger.trace("LLDP: {} (offset {} bitsize {})", new Object[] {
216 HexEncode.bytesToHexString(data), lldpOffset, lldpSize });
219 * Deserialize the TLVs until we reach the end of the packet
221 while (lldpSize > 0) {
222 LLDPTLV tlv = new LLDPTLV();
223 tlv.deserialize(data, lldpOffset, lldpSize);
224 if (tlv.getType() == 0 && tlv.getLength() == 0) {
227 int tlvSize = tlv.getTLVSize(); // Size of current TLV in bits
228 lldpOffset += tlvSize;
230 if (tlv.getType() == LLDPTLV.TLVType.Custom.getValue()) {
231 customTlvList.add(tlv);
233 this.tlvList.put(tlv.getType(), tlv);
240 public byte[] serialize() throws PacketException {
242 byte[] serializedBytes = new byte[getLLDPPacketLength()];
244 final Iterable<LLDPTLV> allTlvs = Iterables.concat(tlvList.values(), customTlvList);
245 for (LLDPTLV tlv : allTlvs) {
246 int numBits = tlv.getTLVSize();
248 BitBufferHelper.setBytes(serializedBytes, tlv.serialize(),
249 startOffset, numBits);
250 } catch (BufferException e) {
251 throw new PacketException(e.getMessage());
253 startOffset += numBits;
255 // Now add the empty LLDPTLV at the end
257 BitBufferHelper.setBytes(serializedBytes,
258 LLDP.emptyTLV.serialize(), startOffset,
259 LLDP.emptyTLV.getTLVSize());
260 } catch (BufferException e) {
261 throw new PacketException(e.getMessage());
264 if (logger.isTraceEnabled()) {
265 logger.trace("LLDP: serialized: {}",
266 HexEncode.bytesToHexString(serializedBytes));
268 return serializedBytes;
272 * Returns the size of LLDP packet in bytes
274 * @return int - LLDP Packet size in bytes
276 private int getLLDPPacketLength() {
280 for (Map.Entry<Byte, LLDPTLV> entry : this.tlvList.entrySet()) {
281 tlv = entry.getValue();
282 len += tlv.getTLVSize();
285 for (LLDPTLV customTlv : this.customTlvList) {
286 len += customTlv.getTLVSize();
289 len += LLDP.emptyTLV.getTLVSize();
291 return len / NetUtils.NumBitsInAByte;