blob: d94a7ba5286588011b28c93add0791ea004edeb6 [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska24c849c2014-10-27 09:53:05 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska24c849c2014-10-27 09:53:05 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska24c849c2014-10-27 09:53:05 -070015 */
alshabib7911a052014-10-16 17:49:37 -070016package org.onlab.packet;
17
18import com.google.common.collect.Lists;
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080019import com.google.common.collect.Maps;
alshabib7911a052014-10-16 17:49:37 -070020import org.apache.commons.lang.ArrayUtils;
21
22import java.nio.ByteBuffer;
Ray Milkey241b96a2014-11-17 13:08:20 -080023import java.nio.charset.StandardCharsets;
Jonathan Hart7838c512016-06-07 15:18:22 -070024import java.util.HashMap;
alshabib7911a052014-10-16 17:49:37 -070025
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080026import static org.onlab.packet.LLDPOrganizationalTLV.OUI_LENGTH;
27import static org.onlab.packet.LLDPOrganizationalTLV.SUBTYPE_LENGTH;
28
alshabib7911a052014-10-16 17:49:37 -070029/**
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080030 * ONOS LLDP containing organizational TLV for ONOS device discovery.
alshabib7911a052014-10-16 17:49:37 -070031 */
32public class ONOSLLDP extends LLDP {
Charles Chan928ff8b2017-05-04 12:22:54 -070033 /**
34 * ONOS OUI.
35 *
36 * @deprecated in Kingfisher. Use MacAddress.ONOS.oui() instead.
37 */
38 @Deprecated
alshabib7911a052014-10-16 17:49:37 -070039 public static final byte[] ONLAB_OUI = {(byte) 0xa4, 0x23, 0x05};
Charles Chan928ff8b2017-05-04 12:22:54 -070040
alshabib7911a052014-10-16 17:49:37 -070041 public static final String DEFAULT_DEVICE = "INVALID";
42 public static final String DEFAULT_NAME = "ONOS Discovery";
43
Charles Chan928ff8b2017-05-04 12:22:54 -070044 /**
45 * ONOS LLDP multicast MAC address.
46 *
47 * @deprecated in Kingfisher. Use MacAddress.ONOS_LLDP instead.
48 */
49 @Deprecated
Jonathan Hart7838c512016-06-07 15:18:22 -070050 public static final byte[] LLDP_ONLAB = {(byte) 0xa5, 0x23, 0x05, 0x00, 0x00, 0x01};
Charles Chan928ff8b2017-05-04 12:22:54 -070051
52 /**
53 * ONOS BDDP broadcast MAC address.
54 *
55 * @deprecated in Kingfisher. Use MacAddress.BROADCASAT instead.
56 */
57 @Deprecated
alshabib7911a052014-10-16 17:49:37 -070058 public static final byte[] BDDP_MULTICAST = {(byte) 0xff, (byte) 0xff,
59 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
60
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080061 protected static final byte NAME_SUBTYPE = 1;
62 protected static final byte DEVICE_SUBTYPE = 2;
63 protected static final byte DOMAIN_SUBTYPE = 3;
64
65 private static final short NAME_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
66 private static final short DEVICE_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
67 private static final short DOMAIN_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
68
Jonathan Hart7838c512016-06-07 15:18:22 -070069 private final HashMap<Byte, LLDPOrganizationalTLV> opttlvs = Maps.newHashMap();
alshabib7911a052014-10-16 17:49:37 -070070
71 // TLV constants: type, size and subtype
72 // Organizationally specific TLV also have packet offset and contents of TLV
73 // header
74 private static final byte CHASSIS_TLV_TYPE = 1;
75 private static final byte CHASSIS_TLV_SIZE = 7;
76 private static final byte CHASSIS_TLV_SUBTYPE = 4;
77
78 private static final byte PORT_TLV_TYPE = 2;
79 private static final byte PORT_TLV_SIZE = 5;
80 private static final byte PORT_TLV_SUBTYPE = 2;
81
82 private static final byte TTL_TLV_TYPE = 3;
83
alshabib7911a052014-10-16 17:49:37 -070084 private final byte[] ttlValue = new byte[] {0, 0x78};
85
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080086 // Only needs to be accessed from LinkProbeFactory.
Ray Milkey88cc3432017-03-30 17:19:08 -070087 public ONOSLLDP(byte... subtype) {
alshabib7911a052014-10-16 17:49:37 -070088 super();
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080089 for (byte st : subtype) {
90 opttlvs.put(st, new LLDPOrganizationalTLV());
91 }
92 // guarantee the following (name and device) TLVs exist
93 opttlvs.putIfAbsent(NAME_SUBTYPE, new LLDPOrganizationalTLV());
94 opttlvs.putIfAbsent(DEVICE_SUBTYPE, new LLDPOrganizationalTLV());
alshabib7911a052014-10-16 17:49:37 -070095 setName(DEFAULT_NAME);
96 setDevice(DEFAULT_DEVICE);
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080097
Jonathan Hart7838c512016-06-07 15:18:22 -070098 setOptionalTLVList(Lists.newArrayList(opttlvs.values()));
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -080099 setTtl(new LLDPTLV().setType(TTL_TLV_TYPE)
alshabib7911a052014-10-16 17:49:37 -0700100 .setLength((short) ttlValue.length)
101 .setValue(ttlValue));
alshabib7911a052014-10-16 17:49:37 -0700102 }
103
104 private ONOSLLDP(LLDP lldp) {
105 this.portId = lldp.getPortId();
106 this.chassisId = lldp.getChassisId();
107 this.ttl = lldp.getTtl();
108 this.optionalTLVList = lldp.getOptionalTLVList();
109 }
110
111 public void setName(String name) {
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800112 LLDPOrganizationalTLV nametlv = opttlvs.get(NAME_SUBTYPE);
113 nametlv.setLength((short) (name.length() + NAME_LENGTH));
114 nametlv.setInfoString(name);
115 nametlv.setSubType(NAME_SUBTYPE);
Charles Chan928ff8b2017-05-04 12:22:54 -0700116 nametlv.setOUI(MacAddress.ONOS.oui());
alshabib7911a052014-10-16 17:49:37 -0700117 }
118
119 public void setDevice(String device) {
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800120 LLDPOrganizationalTLV devicetlv = opttlvs.get(DEVICE_SUBTYPE);
121 devicetlv.setInfoString(device);
122 devicetlv.setLength((short) (device.length() + DEVICE_LENGTH));
123 devicetlv.setSubType(DEVICE_SUBTYPE);
Charles Chan928ff8b2017-05-04 12:22:54 -0700124 devicetlv.setOUI(MacAddress.ONOS.oui());
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800125 }
126
127 public void setDomainInfo(String domainId) {
128 LLDPOrganizationalTLV domaintlv = opttlvs.get(DOMAIN_SUBTYPE);
129 if (domaintlv == null) {
130 // maybe warn people not to set this if remote probes aren't.
131 return;
132 }
133 domaintlv.setInfoString(domainId);
134 domaintlv.setLength((short) (domainId.length() + DOMAIN_LENGTH));
135 domaintlv.setSubType(DOMAIN_SUBTYPE);
Charles Chan928ff8b2017-05-04 12:22:54 -0700136 domaintlv.setOUI(MacAddress.ONOS.oui());
alshabib7911a052014-10-16 17:49:37 -0700137 }
138
139 public void setChassisId(final ChassisId chassisId) {
140 MacAddress chassisMac = MacAddress.valueOf(chassisId.value());
141 byte[] chassis = ArrayUtils.addAll(new byte[] {CHASSIS_TLV_SUBTYPE},
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800142 chassisMac.toBytes());
alshabib7911a052014-10-16 17:49:37 -0700143
144 LLDPTLV chassisTLV = new LLDPTLV();
145 chassisTLV.setLength(CHASSIS_TLV_SIZE);
146 chassisTLV.setType(CHASSIS_TLV_TYPE);
147 chassisTLV.setValue(chassis);
148 this.setChassisId(chassisTLV);
149 }
150
151 public void setPortId(final int portNumber) {
152 byte[] port = ArrayUtils.addAll(new byte[] {PORT_TLV_SUBTYPE},
153 ByteBuffer.allocate(4).putInt(portNumber).array());
154
155 LLDPTLV portTLV = new LLDPTLV();
156 portTLV.setLength(PORT_TLV_SIZE);
157 portTLV.setType(PORT_TLV_TYPE);
158 portTLV.setValue(port);
159 this.setPortId(portTLV);
160 }
161
162 public LLDPOrganizationalTLV getNameTLV() {
163 for (LLDPTLV tlv : this.getOptionalTLVList()) {
164 if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
165 LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
166 if (orgTLV.getSubType() == NAME_SUBTYPE) {
167 return orgTLV;
168 }
169 }
170 }
171 return null;
172 }
173
174 public LLDPOrganizationalTLV getDeviceTLV() {
175 for (LLDPTLV tlv : this.getOptionalTLVList()) {
176 if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
177 LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
178 if (orgTLV.getSubType() == DEVICE_SUBTYPE) {
179 return orgTLV;
180 }
181 }
182 }
183 return null;
184 }
185
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800186 /**
187 * Gets the TLV associated with remote probing. This TLV will be null if
188 * remote probing is disabled.
189 *
190 * @return A TLV containing domain ID, or null.
191 */
192 public LLDPOrganizationalTLV getDomainTLV() {
193 for (LLDPTLV tlv : this.getOptionalTLVList()) {
194 if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
195 LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
196 if (orgTLV.getSubType() == DOMAIN_SUBTYPE) {
197 return orgTLV;
198 }
199 }
200 }
201 return null;
202 }
203
alshabib7911a052014-10-16 17:49:37 -0700204 public String getNameString() {
205 LLDPOrganizationalTLV tlv = getNameTLV();
206 if (tlv != null) {
Ray Milkey241b96a2014-11-17 13:08:20 -0800207 return new String(tlv.getInfoString(), StandardCharsets.UTF_8);
alshabib7911a052014-10-16 17:49:37 -0700208 }
209 return null;
210 }
211
212 public String getDeviceString() {
213 LLDPOrganizationalTLV tlv = getDeviceTLV();
214 if (tlv != null) {
Ray Milkey241b96a2014-11-17 13:08:20 -0800215 return new String(tlv.getInfoString(), StandardCharsets.UTF_8);
alshabib7911a052014-10-16 17:49:37 -0700216 }
217 return null;
218 }
219
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800220 public String getDomainString() {
221 LLDPOrganizationalTLV tlv = getDomainTLV();
222 if (tlv != null) {
223 return new String(tlv.getInfoString(), StandardCharsets.UTF_8);
224 }
225 return null;
226 }
227
alshabib7911a052014-10-16 17:49:37 -0700228 public Integer getPort() {
229 ByteBuffer portBB = ByteBuffer.wrap(this.getPortId().getValue());
230 portBB.position(1);
231 return portBB.getInt();
232 }
233
234 /**
235 * Given an ethernet packet, determines if this is an LLDP from
236 * ONOS and returns the device the LLDP came from.
237 * @param eth an ethernet packet
238 * @return a the lldp packet or null
239 */
240 public static ONOSLLDP parseONOSLLDP(Ethernet eth) {
241 if (eth.getEtherType() == Ethernet.TYPE_LLDP ||
242 eth.getEtherType() == Ethernet.TYPE_BSN) {
Jonathan Hart7838c512016-06-07 15:18:22 -0700243 ONOSLLDP onosLldp = new ONOSLLDP((LLDP) eth.getPayload());
alshabib7911a052014-10-16 17:49:37 -0700244 if (ONOSLLDP.DEFAULT_NAME.equals(onosLldp.getNameString())) {
245 return onosLldp;
246 }
247 }
248 return null;
249 }
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800250
251 /**
252 * Creates a link probe for link discovery/verification.
253 *
254 * @param deviceId The device ID as a String
255 * @param chassisId The chassis ID of the device
256 * @param portNum Port number of port to send probe out of
257 * @return ONOSLLDP probe message
258 */
259 public static ONOSLLDP onosLLDP(String deviceId, ChassisId chassisId, int portNum) {
260 ONOSLLDP probe = new ONOSLLDP(NAME_SUBTYPE, DEVICE_SUBTYPE);
261 probe.setPortId(portNum);
262 probe.setDevice(deviceId);
263 probe.setChassisId(chassisId);
264 return probe;
265 }
alshabib7911a052014-10-16 17:49:37 -0700266}