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