Fix checkstyle violations in liblldp
[openflowplugin.git] / libraries / liblldp / src / main / java / org / opendaylight / openflowplugin / libraries / liblldp / LLDP.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.libraries.liblldp;
10
11 import com.google.common.collect.Iterables;
12 import java.util.LinkedHashMap;
13 import java.util.List;
14 import java.util.Map;
15
16 /**
17  * Class that represents the LLDP frame objects.
18  */
19 public class LLDP extends Packet {
20     private static final String CHASSISID = "ChassisId";
21     private static final String SYSTEMNAMEID = "SystemNameID";
22     private static final String PORTID = "PortId";
23     private static final String TTL = "TTL";
24     private static final int LLDP_DEFAULT_TLVS = 3;
25     private static final LLDPTLV EMPTY_TLV = new LLDPTLV().setLength((short) 0).setType((byte) 0);
26     public static final byte[] LLDP_MULTICAST_MAC = { 1, (byte) 0x80, (byte) 0xc2, 0, 0, (byte) 0xe };
27
28     private Map<Byte, LLDPTLV> mandatoryTLVs;
29     private Map<Byte, LLDPTLV> optionalTLVs;
30     private Map<CustomTLVKey, LLDPTLV> customTLVs;
31
32     /**
33      * Default constructor that creates the tlvList LinkedHashMap.
34      */
35     public LLDP() {
36         init();
37     }
38
39     /**
40      * Constructor that creates the tlvList LinkedHashMap and sets the write access for the same.
41      */
42     public LLDP(final boolean writeAccess) {
43         super(writeAccess);
44         init();
45     }
46
47     private void init() {
48         mandatoryTLVs = new LinkedHashMap<>(LLDP_DEFAULT_TLVS);
49         optionalTLVs = new LinkedHashMap<>();
50         customTLVs = new LinkedHashMap<>();
51     }
52
53     /**
54      * Returns the TLV byte type.
55      *
56      * @param String description of the type of TLV
57      * @return byte type of TLV
58      */
59     private byte getType(final String typeDesc) {
60         if (typeDesc.equals(CHASSISID)) {
61             return LLDPTLV.TLVType.ChassisID.getValue();
62         } else if (typeDesc.equals(PORTID)) {
63             return LLDPTLV.TLVType.PortID.getValue();
64         } else if (typeDesc.equals(TTL)) {
65             return LLDPTLV.TLVType.TTL.getValue();
66         } else if (typeDesc.equals(SYSTEMNAMEID)) {
67             return LLDPTLV.TLVType.SystemName.getValue();
68         } else {
69             return LLDPTLV.TLVType.Unknown.getValue();
70         }
71     }
72
73     private LLDPTLV getFromTLVs(final Byte type) {
74         LLDPTLV tlv = null;
75         tlv = mandatoryTLVs.get(type);
76         if (tlv == null) {
77             tlv = optionalTLVs.get(type);
78         }
79         return tlv;
80     }
81
82     private void putToTLVs(final Byte type, final LLDPTLV tlv) {
83         if (type == LLDPTLV.TLVType.ChassisID.getValue() || type == LLDPTLV.TLVType.PortID.getValue()
84                 || type == LLDPTLV.TLVType.TTL.getValue()) {
85             mandatoryTLVs.put(type, tlv);
86         } else if (type != LLDPTLV.TLVType.Custom.getValue()) {
87             optionalTLVs.put(type, tlv);
88         }
89     }
90
91     /**
92      * Gets the full LLDPTLV.
93      *
94      * @param type description of the type of TLV
95      * @return LLDPTLV - full TLV
96      */
97     public LLDPTLV getTLV(final String type) {
98         return getFromTLVs(getType(type));
99     }
100
101     public LLDPTLV getCustomTLV(final CustomTLVKey key) {
102         return customTLVs.get(key);
103     }
104
105     /**
106      * Sets the LLDPTLV for a type.
107      *
108      * @param type description of the type of TLV
109      * @param tlv tlv to set
110      */
111     public void setTLV(final String type, final LLDPTLV tlv) {
112         putToTLVs(getType(type), tlv);
113     }
114
115     /**
116      * Returns the chassisId TLV.
117      */
118     public LLDPTLV getChassisId() {
119         return getTLV(CHASSISID);
120     }
121
122     public LLDP setChassisId(final LLDPTLV chassisId) {
123         setTLV(CHASSISID, chassisId);
124         return this;
125     }
126
127     /**
128      * Returns the SystemName TLV.
129      */
130     public LLDPTLV getSystemNameId() {
131         return getTLV(SYSTEMNAMEID);
132     }
133
134     public LLDP setSystemNameId(final LLDPTLV systemNameId) {
135         setTLV(SYSTEMNAMEID, systemNameId);
136         return this;
137     }
138
139     /**
140      * Returns the portId TLV.
141      */
142     public LLDPTLV getPortId() {
143         return getTLV(PORTID);
144     }
145
146     public LLDP setPortId(final LLDPTLV portId) {
147         setTLV(PORTID, portId);
148         return this;
149     }
150
151     /**
152      * Return the ttl TLV.
153      */
154     public LLDPTLV getTtl() {
155         return getTLV(TTL);
156     }
157
158     public LLDP setTtl(final LLDPTLV ttl) {
159         setTLV(TTL, ttl);
160         return this;
161     }
162
163     /**
164      * Returns the optionalTLVList.
165      */
166     public Iterable<LLDPTLV> getOptionalTLVList() {
167         return optionalTLVs.values();
168     }
169
170     /**
171      * Returns the customTlvList.
172      */
173     public Iterable<LLDPTLV> getCustomTlvList() {
174         return customTLVs.values();
175     }
176
177     public LLDP setOptionalTLVList(final List<LLDPTLV> optionalTLVList) {
178         for (LLDPTLV tlv : optionalTLVList) {
179             optionalTLVs.put(tlv.getType(), tlv);
180         }
181         return this;
182     }
183
184     public LLDP addCustomTLV(final LLDPTLV customTLV) {
185         CustomTLVKey key = new CustomTLVKey(LLDPTLV.extractCustomOUI(customTLV),
186                 LLDPTLV.extractCustomSubtype(customTLV));
187         customTLVs.put(key, customTLV);
188
189         return this;
190     }
191
192     @Override
193     public Packet deserialize(final byte[] data, final int bitOffset, final int size) throws PacketException {
194         int lldpOffset = bitOffset; // LLDP start
195         int lldpSize = size; // LLDP size
196
197         if (LOG.isTraceEnabled()) {
198             LOG.trace("LLDP: {} (offset {} bitsize {})", new Object[] { HexEncode.bytesToHexString(data),
199                 lldpOffset, lldpSize });
200         }
201         /*
202          * Deserialize the TLVs until we reach the end of the packet
203          */
204         while (lldpSize > 0) {
205             LLDPTLV tlv = new LLDPTLV();
206             tlv.deserialize(data, lldpOffset, lldpSize);
207             if (tlv.getType() == 0 && tlv.getLength() == 0) {
208                 break;
209             }
210             int tlvSize = tlv.getTLVSize(); // Size of current TLV in bits
211             lldpOffset += tlvSize;
212             lldpSize -= tlvSize;
213             if (tlv.getType() == LLDPTLV.TLVType.Custom.getValue()) {
214                 addCustomTLV(tlv);
215             } else {
216                 this.putToTLVs(tlv.getType(), tlv);
217             }
218         }
219         return this;
220     }
221
222     @Override
223     public byte[] serialize() throws PacketException {
224         int startOffset = 0;
225         byte[] serializedBytes = new byte[getLLDPPacketLength()];
226
227         final Iterable<LLDPTLV> allTlvs = Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(),
228                 customTLVs.values());
229         for (LLDPTLV tlv : allTlvs) {
230             int numBits = tlv.getTLVSize();
231             try {
232                 BitBufferHelper.setBytes(serializedBytes, tlv.serialize(), startOffset, numBits);
233             } catch (final BufferException e) {
234                 throw new PacketException("Error from setBytes", e);
235             }
236             startOffset += numBits;
237         }
238         // Now add the empty LLDPTLV at the end
239         try {
240             BitBufferHelper.setBytes(serializedBytes, LLDP.EMPTY_TLV.serialize(), startOffset,
241                     LLDP.EMPTY_TLV.getTLVSize());
242         } catch (final BufferException e) {
243             throw new PacketException("Error from setBytes", e);
244         }
245
246         if (LOG.isTraceEnabled()) {
247             LOG.trace("LLDP: serialized: {}", HexEncode.bytesToHexString(serializedBytes));
248         }
249         return serializedBytes;
250     }
251
252     /**
253      * Returns the size of LLDP packet in bytes.
254      *
255      * @return int - LLDP Packet size in bytes
256      */
257     private int getLLDPPacketLength() {
258         int len = 0;
259
260         for (LLDPTLV lldptlv : Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values())) {
261             len += lldptlv.getTLVSize();
262         }
263
264         len += LLDP.EMPTY_TLV.getTLVSize();
265
266         return len / NetUtils.NUM_BITS_IN_A_BYTE;
267     }
268 }