blob: 706a8b1aaa4de4c6fdb1dbdff92ac8ff29a69229 [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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
alshabib7911a052014-10-16 17:49:37 -070034 public static final String DEFAULT_DEVICE = "INVALID";
35 public static final String DEFAULT_NAME = "ONOS Discovery";
36
alshabib7911a052014-10-16 17:49:37 -070037
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080038 protected static final byte NAME_SUBTYPE = 1;
39 protected static final byte DEVICE_SUBTYPE = 2;
40 protected static final byte DOMAIN_SUBTYPE = 3;
41
42 private static final short NAME_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
43 private static final short DEVICE_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
44 private static final short DOMAIN_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
45
Jonathan Hart7838c512016-06-07 15:18:22 -070046 private final HashMap<Byte, LLDPOrganizationalTLV> opttlvs = Maps.newHashMap();
alshabib7911a052014-10-16 17:49:37 -070047
48 // TLV constants: type, size and subtype
49 // Organizationally specific TLV also have packet offset and contents of TLV
50 // header
51 private static final byte CHASSIS_TLV_TYPE = 1;
52 private static final byte CHASSIS_TLV_SIZE = 7;
53 private static final byte CHASSIS_TLV_SUBTYPE = 4;
54
55 private static final byte PORT_TLV_TYPE = 2;
56 private static final byte PORT_TLV_SIZE = 5;
57 private static final byte PORT_TLV_SUBTYPE = 2;
58
59 private static final byte TTL_TLV_TYPE = 3;
60
alshabib7911a052014-10-16 17:49:37 -070061 private final byte[] ttlValue = new byte[] {0, 0x78};
62
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080063 // Only needs to be accessed from LinkProbeFactory.
Ray Milkey88cc3432017-03-30 17:19:08 -070064 public ONOSLLDP(byte... subtype) {
alshabib7911a052014-10-16 17:49:37 -070065 super();
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080066 for (byte st : subtype) {
67 opttlvs.put(st, new LLDPOrganizationalTLV());
68 }
69 // guarantee the following (name and device) TLVs exist
70 opttlvs.putIfAbsent(NAME_SUBTYPE, new LLDPOrganizationalTLV());
71 opttlvs.putIfAbsent(DEVICE_SUBTYPE, new LLDPOrganizationalTLV());
alshabib7911a052014-10-16 17:49:37 -070072 setName(DEFAULT_NAME);
73 setDevice(DEFAULT_DEVICE);
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080074
Jonathan Hart7838c512016-06-07 15:18:22 -070075 setOptionalTLVList(Lists.newArrayList(opttlvs.values()));
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -080076 setTtl(new LLDPTLV().setType(TTL_TLV_TYPE)
alshabib7911a052014-10-16 17:49:37 -070077 .setLength((short) ttlValue.length)
78 .setValue(ttlValue));
alshabib7911a052014-10-16 17:49:37 -070079 }
80
81 private ONOSLLDP(LLDP lldp) {
82 this.portId = lldp.getPortId();
83 this.chassisId = lldp.getChassisId();
84 this.ttl = lldp.getTtl();
85 this.optionalTLVList = lldp.getOptionalTLVList();
86 }
87
88 public void setName(String name) {
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080089 LLDPOrganizationalTLV nametlv = opttlvs.get(NAME_SUBTYPE);
90 nametlv.setLength((short) (name.length() + NAME_LENGTH));
91 nametlv.setInfoString(name);
92 nametlv.setSubType(NAME_SUBTYPE);
Charles Chan928ff8b2017-05-04 12:22:54 -070093 nametlv.setOUI(MacAddress.ONOS.oui());
alshabib7911a052014-10-16 17:49:37 -070094 }
95
96 public void setDevice(String device) {
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080097 LLDPOrganizationalTLV devicetlv = opttlvs.get(DEVICE_SUBTYPE);
98 devicetlv.setInfoString(device);
99 devicetlv.setLength((short) (device.length() + DEVICE_LENGTH));
100 devicetlv.setSubType(DEVICE_SUBTYPE);
Charles Chan928ff8b2017-05-04 12:22:54 -0700101 devicetlv.setOUI(MacAddress.ONOS.oui());
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800102 }
103
104 public void setDomainInfo(String domainId) {
105 LLDPOrganizationalTLV domaintlv = opttlvs.get(DOMAIN_SUBTYPE);
106 if (domaintlv == null) {
107 // maybe warn people not to set this if remote probes aren't.
108 return;
109 }
110 domaintlv.setInfoString(domainId);
111 domaintlv.setLength((short) (domainId.length() + DOMAIN_LENGTH));
112 domaintlv.setSubType(DOMAIN_SUBTYPE);
Charles Chan928ff8b2017-05-04 12:22:54 -0700113 domaintlv.setOUI(MacAddress.ONOS.oui());
alshabib7911a052014-10-16 17:49:37 -0700114 }
115
116 public void setChassisId(final ChassisId chassisId) {
117 MacAddress chassisMac = MacAddress.valueOf(chassisId.value());
118 byte[] chassis = ArrayUtils.addAll(new byte[] {CHASSIS_TLV_SUBTYPE},
Yuta HIGUCHI3e848a82014-11-02 20:19:42 -0800119 chassisMac.toBytes());
alshabib7911a052014-10-16 17:49:37 -0700120
121 LLDPTLV chassisTLV = new LLDPTLV();
122 chassisTLV.setLength(CHASSIS_TLV_SIZE);
123 chassisTLV.setType(CHASSIS_TLV_TYPE);
124 chassisTLV.setValue(chassis);
125 this.setChassisId(chassisTLV);
126 }
127
128 public void setPortId(final int portNumber) {
129 byte[] port = ArrayUtils.addAll(new byte[] {PORT_TLV_SUBTYPE},
130 ByteBuffer.allocate(4).putInt(portNumber).array());
131
132 LLDPTLV portTLV = new LLDPTLV();
133 portTLV.setLength(PORT_TLV_SIZE);
134 portTLV.setType(PORT_TLV_TYPE);
135 portTLV.setValue(port);
136 this.setPortId(portTLV);
137 }
138
139 public LLDPOrganizationalTLV getNameTLV() {
140 for (LLDPTLV tlv : this.getOptionalTLVList()) {
141 if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
142 LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
143 if (orgTLV.getSubType() == NAME_SUBTYPE) {
144 return orgTLV;
145 }
146 }
147 }
148 return null;
149 }
150
151 public LLDPOrganizationalTLV getDeviceTLV() {
152 for (LLDPTLV tlv : this.getOptionalTLVList()) {
153 if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
154 LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
155 if (orgTLV.getSubType() == DEVICE_SUBTYPE) {
156 return orgTLV;
157 }
158 }
159 }
160 return null;
161 }
162
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800163 /**
164 * Gets the TLV associated with remote probing. This TLV will be null if
165 * remote probing is disabled.
166 *
167 * @return A TLV containing domain ID, or null.
168 */
169 public LLDPOrganizationalTLV getDomainTLV() {
170 for (LLDPTLV tlv : this.getOptionalTLVList()) {
171 if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
172 LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
173 if (orgTLV.getSubType() == DOMAIN_SUBTYPE) {
174 return orgTLV;
175 }
176 }
177 }
178 return null;
179 }
180
alshabib7911a052014-10-16 17:49:37 -0700181 public String getNameString() {
182 LLDPOrganizationalTLV tlv = getNameTLV();
183 if (tlv != null) {
Ray Milkey241b96a2014-11-17 13:08:20 -0800184 return new String(tlv.getInfoString(), StandardCharsets.UTF_8);
alshabib7911a052014-10-16 17:49:37 -0700185 }
186 return null;
187 }
188
189 public String getDeviceString() {
190 LLDPOrganizationalTLV tlv = getDeviceTLV();
191 if (tlv != null) {
Ray Milkey241b96a2014-11-17 13:08:20 -0800192 return new String(tlv.getInfoString(), StandardCharsets.UTF_8);
alshabib7911a052014-10-16 17:49:37 -0700193 }
194 return null;
195 }
196
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800197 public String getDomainString() {
198 LLDPOrganizationalTLV tlv = getDomainTLV();
199 if (tlv != null) {
200 return new String(tlv.getInfoString(), StandardCharsets.UTF_8);
201 }
202 return null;
203 }
204
alshabib7911a052014-10-16 17:49:37 -0700205 public Integer getPort() {
206 ByteBuffer portBB = ByteBuffer.wrap(this.getPortId().getValue());
207 portBB.position(1);
208 return portBB.getInt();
209 }
210
211 /**
212 * Given an ethernet packet, determines if this is an LLDP from
213 * ONOS and returns the device the LLDP came from.
214 * @param eth an ethernet packet
215 * @return a the lldp packet or null
216 */
217 public static ONOSLLDP parseONOSLLDP(Ethernet eth) {
218 if (eth.getEtherType() == Ethernet.TYPE_LLDP ||
219 eth.getEtherType() == Ethernet.TYPE_BSN) {
Jonathan Hart7838c512016-06-07 15:18:22 -0700220 ONOSLLDP onosLldp = new ONOSLLDP((LLDP) eth.getPayload());
alshabib7911a052014-10-16 17:49:37 -0700221 if (ONOSLLDP.DEFAULT_NAME.equals(onosLldp.getNameString())) {
222 return onosLldp;
223 }
224 }
225 return null;
226 }
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800227
228 /**
229 * Creates a link probe for link discovery/verification.
230 *
231 * @param deviceId The device ID as a String
232 * @param chassisId The chassis ID of the device
233 * @param portNum Port number of port to send probe out of
234 * @return ONOSLLDP probe message
235 */
236 public static ONOSLLDP onosLLDP(String deviceId, ChassisId chassisId, int portNum) {
237 ONOSLLDP probe = new ONOSLLDP(NAME_SUBTYPE, DEVICE_SUBTYPE);
238 probe.setPortId(portNum);
239 probe.setDevice(deviceId);
240 probe.setChassisId(chassisId);
241 return probe;
242 }
alshabib7911a052014-10-16 17:49:37 -0700243}