9b7efbb1e6f21676875cc4b6e2202ea14592d3ac
[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 java.util.ArrayList;
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 = 4;
26     private static LLDPTLV emptyTLV = new LLDPTLV().setLength((short) 0)
27             .setType((byte) 0);
28     public static final byte[] LLDPMulticastMac = { 1, (byte) 0x80,
29             (byte) 0xc2, 0, 0, (byte) 0xe };
30     private Map<Byte, LLDPTLV> tlvList;
31
32     /**
33      * Default constructor that creates the tlvList LinkedHashMap
34      */
35     public LLDP() {
36         super();
37         tlvList = new LinkedHashMap<Byte, LLDPTLV>(LLDPDefaultTlvs);
38     }
39
40     /**
41      * Constructor that creates the tlvList LinkedHashMap and sets the write
42      * access for the same
43      */
44     public LLDP(boolean writeAccess) {
45         super(writeAccess);
46         tlvList = new LinkedHashMap<Byte, LLDPTLV>(LLDPDefaultTlvs); // Mandatory
47                                                                      // TLVs
48     }
49
50     /**
51      * @param String
52      *            - description of the type of TLV
53      * @return byte - type of TLV
54      */
55     private byte getType(String typeDesc) {
56         if (typeDesc.equals(CHASSISID)) {
57             return LLDPTLV.TLVType.ChassisID.getValue();
58         } else if (typeDesc.equals(PORTID)) {
59             return LLDPTLV.TLVType.PortID.getValue();
60         } else if (typeDesc.equals(TTL)) {
61             return LLDPTLV.TLVType.TTL.getValue();
62         } else {
63             return LLDPTLV.TLVType.Unknown.getValue();
64         }
65     }
66
67     /**
68      * @param String
69      *            - description of the type of TLV
70      * @return LLDPTLV - full TLV
71      */
72     public LLDPTLV getTLV(String type) {
73         return tlvList.get(getType(type));
74     }
75
76     /**
77      * @param String
78      *            - description of the type of TLV
79      * @param LLDPTLV
80      *            - tlv to set
81      * @return void
82      */
83     public void setTLV(String type, LLDPTLV tlv) {
84         tlvList.put(getType(type), tlv);
85     }
86
87     /**
88      * @return the chassisId TLV
89      */
90     public LLDPTLV getChassisId() {
91         return getTLV(CHASSISID);
92     }
93
94     /**
95      * @param LLDPTLV
96      *            - the chassisId to set
97      */
98     public LLDP setChassisId(LLDPTLV chassisId) {
99         tlvList.put(getType(CHASSISID), chassisId);
100         return this;
101     }
102
103     /**
104      * @return the SystemName TLV
105      */
106     public LLDPTLV getSystemNameId() {
107         return getTLV(SYSTEMNAMEID);
108     }
109
110     /**
111      * @param LLDPTLV
112      *            - the chassisId to set
113      */
114     public LLDP setSystemNameId(LLDPTLV systemNameId) {
115         tlvList.put(getType(SYSTEMNAMEID), systemNameId);
116         return this;
117     }
118
119     /**
120      * @return LLDPTLV - the portId TLV
121      */
122     public LLDPTLV getPortId() {
123         return tlvList.get(getType(PORTID));
124     }
125
126     /**
127      * @param LLDPTLV
128      *            - the portId to set
129      * @return LLDP
130      */
131     public LLDP setPortId(LLDPTLV portId) {
132         tlvList.put(getType(PORTID), portId);
133         return this;
134     }
135
136     /**
137      * @return LLDPTLV - the ttl TLV
138      */
139     public LLDPTLV getTtl() {
140         return tlvList.get(getType(TTL));
141     }
142
143     /**
144      * @param LLDPTLV
145      *            - the ttl to set
146      * @return LLDP
147      */
148     public LLDP setTtl(LLDPTLV ttl) {
149         tlvList.put(getType(TTL), ttl);
150         return this;
151     }
152
153     /**
154      * @return the optionalTLVList
155      */
156     public List<LLDPTLV> getOptionalTLVList() {
157         List<LLDPTLV> list = new ArrayList<LLDPTLV>();
158         for (Map.Entry<Byte, LLDPTLV> entry : tlvList.entrySet()) {
159             byte type = entry.getKey();
160             if ((type == LLDPTLV.TLVType.ChassisID.getValue())
161                     || (type == LLDPTLV.TLVType.PortID.getValue())
162                     || (type == LLDPTLV.TLVType.TTL.getValue())) {
163                 continue;
164             } else {
165                 list.add(entry.getValue());
166             }
167         }
168         return list;
169     }
170
171     /**
172      * @param optionalTLVList
173      *            the optionalTLVList to set
174      * @return LLDP
175      */
176     public LLDP setOptionalTLVList(List<LLDPTLV> optionalTLVList) {
177         for (LLDPTLV tlv : optionalTLVList) {
178             tlvList.put(tlv.getType(), tlv);
179         }
180         return this;
181     }
182
183     @Override
184     public Packet deserialize(byte[] data, int bitOffset, int size)
185             throws PacketException {
186         int lldpOffset = bitOffset; // LLDP start
187         int lldpSize = size; // LLDP size
188
189         if (logger.isTraceEnabled()) {
190           logger.trace("LLDP: {} (offset {} bitsize {})", new Object[] {
191                   HexEncode.bytesToHexString(data), lldpOffset, lldpSize });
192         }
193         /*
194          * Deserialize the TLVs until we reach the end of the packet
195          */
196         while (lldpSize > 0) {
197             LLDPTLV tlv = new LLDPTLV();
198             tlv.deserialize(data, lldpOffset, lldpSize);
199             if (tlv.getType() == 0 && tlv.getLength() == 0) {
200                break;
201             }
202             int tlvSize = tlv.getTLVSize(); // Size of current TLV in bits
203             lldpOffset += tlvSize;
204             lldpSize -= tlvSize;
205             this.tlvList.put(tlv.getType(), tlv);
206         }
207         return this;
208     }
209
210     @Override
211     public byte[] serialize() throws PacketException {
212         int startOffset = 0;
213         byte[] serializedBytes = new byte[getLLDPPacketLength()];
214
215         for (Map.Entry<Byte, LLDPTLV> entry : tlvList.entrySet()) {
216             LLDPTLV tlv = entry.getValue();
217             int numBits = tlv.getTLVSize();
218             try {
219                 BitBufferHelper.setBytes(serializedBytes, tlv.serialize(),
220                         startOffset, numBits);
221             } catch (BufferException e) {
222                 throw new PacketException(e.getMessage());
223             }
224             startOffset += numBits;
225         }
226         // Now add the empty LLDPTLV at the end
227         try {
228             BitBufferHelper.setBytes(serializedBytes,
229                     LLDP.emptyTLV.serialize(), startOffset,
230                     LLDP.emptyTLV.getTLVSize());
231         } catch (BufferException e) {
232             throw new PacketException(e.getMessage());
233         }
234
235         if (logger.isTraceEnabled()) {
236           logger.trace("LLDP: serialized: {}",
237                   HexEncode.bytesToHexString(serializedBytes));
238         }
239         return serializedBytes;
240     }
241
242     /**
243      * Returns the size of LLDP packet in bytes
244      *
245      * @return int - LLDP Packet size in bytes
246      */
247     private int getLLDPPacketLength() {
248         int len = 0;
249         LLDPTLV tlv;
250
251         for (Map.Entry<Byte, LLDPTLV> entry : this.tlvList.entrySet()) {
252             tlv = entry.getValue();
253             len += tlv.getTLVSize();
254         }
255         len += LLDP.emptyTLV.getTLVSize();
256
257         return len / NetUtils.NumBitsInAByte;
258     }
259 }