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