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