Remove explicit default super-constructor calls
[controller.git] / opendaylight / commons / liblldp / src / main / java / org / opendaylight / controller / 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.controller.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
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 final 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 };
28
29     private Map<Byte, LLDPTLV> mandatoryTLVs;
30     private Map<Byte, LLDPTLV> optionalTLVs;
31     private Map<CustomTLVKey, LLDPTLV> customTLVs;
32
33     /**
34      * Default constructor that creates the tlvList LinkedHashMap
35      */
36     public LLDP() {
37         init();
38     }
39
40     /**
41      * Constructor that creates the tlvList LinkedHashMap and sets the write access for the same
42      */
43     public LLDP(final boolean writeAccess) {
44         super(writeAccess);
45         init();
46     }
47
48     private void init() {
49         mandatoryTLVs = new LinkedHashMap<>(LLDPDefaultTlvs);
50         optionalTLVs = new LinkedHashMap<>();
51         customTLVs = new LinkedHashMap<>();
52     }
53
54     /**
55      * @param String
56      *            - 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      * @param type
93      *            - description of the type of TLV
94      * @return LLDPTLV - full TLV
95      */
96     public LLDPTLV getTLV(final String type) {
97         return getFromTLVs(getType(type));
98     }
99
100     public LLDPTLV getCustomTLV(final CustomTLVKey key) {
101         return customTLVs.get(key);
102     }
103
104     /**
105      * @param type
106      *            - description of the type of TLV
107      * @param tlv
108      *            - tlv to set
109      */
110     public void setTLV(final String type, final LLDPTLV tlv) {
111         putToTLVs(getType(type), tlv);
112     }
113
114     /**
115      * @return the chassisId TLV
116      */
117     public LLDPTLV getChassisId() {
118         return getTLV(CHASSISID);
119     }
120
121     /**
122      * @param chassisId
123      *            - the chassisId to set
124      */
125     public LLDP setChassisId(final LLDPTLV chassisId) {
126         setTLV(CHASSISID, chassisId);
127         return this;
128     }
129
130     /**
131      * @return the SystemName TLV
132      */
133     public LLDPTLV getSystemNameId() {
134         return getTLV(SYSTEMNAMEID);
135     }
136
137     /**
138      * @param systemNameId
139      *            - the systemNameId to set
140      */
141     public LLDP setSystemNameId(final LLDPTLV systemNameId) {
142         setTLV(SYSTEMNAMEID, systemNameId);
143         return this;
144     }
145
146     /**
147      * @return LLDPTLV - the portId TLV
148      */
149     public LLDPTLV getPortId() {
150         return getTLV(PORTID);
151     }
152
153     /**
154      * @param portId
155      *            - the portId to set
156      * @return LLDP
157      */
158     public LLDP setPortId(final LLDPTLV portId) {
159         setTLV(PORTID, portId);
160         return this;
161     }
162
163     /**
164      * @return LLDPTLV - the ttl TLV
165      */
166     public LLDPTLV getTtl() {
167         return getTLV(TTL);
168     }
169
170     /**
171      * @param ttl
172      *            - the ttl to set
173      * @return LLDP
174      */
175     public LLDP setTtl(final LLDPTLV ttl) {
176         setTLV(TTL, ttl);
177         return this;
178     }
179
180     /**
181      * @return the optionalTLVList
182      */
183     public Iterable<LLDPTLV> getOptionalTLVList() {
184         return optionalTLVs.values();
185     }
186
187     /**
188      * @return the customTlvList
189      */
190     public Iterable<LLDPTLV> getCustomTlvList() {
191         return customTLVs.values();
192     }
193
194     /**
195      * @param optionalTLVList
196      *            the optionalTLVList to set
197      * @return LLDP
198      */
199     public LLDP setOptionalTLVList(final List<LLDPTLV> optionalTLVList) {
200         for (LLDPTLV tlv : optionalTLVList) {
201             optionalTLVs.put(tlv.getType(), tlv);
202         }
203         return this;
204     }
205
206     /**
207      * @param customTLV
208      *            the list of custom TLVs to set
209      * @return this LLDP
210      */
211     public LLDP addCustomTLV(final LLDPTLV customTLV) {
212         CustomTLVKey key = new CustomTLVKey(LLDPTLV.extractCustomOUI(customTLV),
213                 LLDPTLV.extractCustomSubtype(customTLV));
214         customTLVs.put(key, customTLV);
215
216         return this;
217     }
218
219     @Override
220     public Packet deserialize(final byte[] data, final int bitOffset, final int size) throws PacketException {
221         int lldpOffset = bitOffset; // LLDP start
222         int lldpSize = size; // LLDP size
223
224         if (LOG.isTraceEnabled()) {
225             LOG.trace("LLDP: {} (offset {} bitsize {})", new Object[] { HexEncode.bytesToHexString(data),
226                     lldpOffset, lldpSize });
227         }
228         /*
229          * Deserialize the TLVs until we reach the end of the packet
230          */
231         while (lldpSize > 0) {
232             LLDPTLV tlv = new LLDPTLV();
233             tlv.deserialize(data, lldpOffset, lldpSize);
234             if (tlv.getType() == 0 && tlv.getLength() == 0) {
235                 break;
236             }
237             int tlvSize = tlv.getTLVSize(); // Size of current TLV in bits
238             lldpOffset += tlvSize;
239             lldpSize -= tlvSize;
240             if (tlv.getType() == LLDPTLV.TLVType.Custom.getValue()) {
241                 addCustomTLV(tlv);
242             } else {
243                 this.putToTLVs(tlv.getType(), tlv);
244             }
245         }
246         return this;
247     }
248
249     @Override
250     public byte[] serialize() throws PacketException {
251         int startOffset = 0;
252         byte[] serializedBytes = new byte[getLLDPPacketLength()];
253
254         final Iterable<LLDPTLV> allTlvs = Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values());
255         for (LLDPTLV tlv : allTlvs) {
256             int numBits = tlv.getTLVSize();
257             try {
258                 BitBufferHelper.setBytes(serializedBytes, tlv.serialize(), startOffset, numBits);
259             } catch (final BufferException e) {
260                 throw new PacketException(e.getMessage());
261             }
262             startOffset += numBits;
263         }
264         // Now add the empty LLDPTLV at the end
265         try {
266             BitBufferHelper.setBytes(serializedBytes, LLDP.emptyTLV.serialize(), startOffset,
267                     LLDP.emptyTLV.getTLVSize());
268         } catch (final BufferException e) {
269             throw new PacketException(e.getMessage());
270         }
271
272         if (LOG.isTraceEnabled()) {
273             LOG.trace("LLDP: serialized: {}", HexEncode.bytesToHexString(serializedBytes));
274         }
275         return serializedBytes;
276     }
277
278     /**
279      * Returns the size of LLDP packet in bytes
280      *
281      * @return int - LLDP Packet size in bytes
282      */
283     private int getLLDPPacketLength() {
284         int len = 0;
285
286         for (LLDPTLV lldptlv : Iterables.concat(mandatoryTLVs.values(), optionalTLVs.values(), customTLVs.values())) {
287             len += lldptlv.getTLVSize();
288         }
289
290         len += LLDP.emptyTLV.getTLVSize();
291
292         return len / NetUtils.NumBitsInAByte;
293     }
294 }