[Falcon] link discovery -
- Support for TLV containing cluster fingerprint info
- Config for enabling extra TLV at device level
- Refactored ONOSLLDP constructor for ease of use
Change-Id: I93abe6c0ed8b7e37c80af5920649272faad8856e
diff --git a/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java b/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
index 4d5d58b..78a6ad3 100644
--- a/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
+++ b/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
@@ -15,14 +15,21 @@
*/
package org.onlab.packet;
+import java.util.HashMap;
+
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
import org.apache.commons.lang.ArrayUtils;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
+import static org.onlab.packet.LLDPOrganizationalTLV.OUI_LENGTH;
+import static org.onlab.packet.LLDPOrganizationalTLV.SUBTYPE_LENGTH;
+
/**
- * ONOS LLDP containing organizational TLV for ONOS device dicovery.
+ * ONOS LLDP containing organizational TLV for ONOS device discovery.
*/
public class ONOSLLDP extends LLDP {
@@ -37,12 +44,16 @@
public static final byte[] BDDP_MULTICAST = {(byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
- private static final byte NAME_SUBTYPE = 1;
- private static final byte DEVICE_SUBTYPE = 2;
- private static final short NAME_LENGTH = 4; //1 for subtype + 3 for OUI
- private static final short DEVICE_LENGTH = 4; //1 for subtype + 3 for OUI
- private final LLDPOrganizationalTLV nameTLV = new LLDPOrganizationalTLV();
- private final LLDPOrganizationalTLV deviceTLV = new LLDPOrganizationalTLV();
+ protected static final byte NAME_SUBTYPE = 1;
+ protected static final byte DEVICE_SUBTYPE = 2;
+ protected static final byte DOMAIN_SUBTYPE = 3;
+
+ private static final short NAME_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
+ private static final short DEVICE_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
+ private static final short DOMAIN_LENGTH = OUI_LENGTH + SUBTYPE_LENGTH;
+
+ private final HashMap<Byte, LLDPOrganizationalTLV> opttlvs =
+ Maps.<Byte, LLDPOrganizationalTLV>newHashMap();
// TLV constants: type, size and subtype
// Organizationally specific TLV also have packet offset and contents of TLV
@@ -57,18 +68,24 @@
private static final byte TTL_TLV_TYPE = 3;
-
private final byte[] ttlValue = new byte[] {0, 0x78};
- public ONOSLLDP() {
+ // Only needs to be accessed from LinkProbeFactory.
+ protected ONOSLLDP(byte ... subtype) {
super();
+ for (byte st : subtype) {
+ opttlvs.put(st, new LLDPOrganizationalTLV());
+ }
+ // guarantee the following (name and device) TLVs exist
+ opttlvs.putIfAbsent(NAME_SUBTYPE, new LLDPOrganizationalTLV());
+ opttlvs.putIfAbsent(DEVICE_SUBTYPE, new LLDPOrganizationalTLV());
setName(DEFAULT_NAME);
setDevice(DEFAULT_DEVICE);
- setOptionalTLVList(Lists.<LLDPTLV>newArrayList(nameTLV, deviceTLV));
+
+ setOptionalTLVList(Lists.<LLDPTLV>newArrayList(opttlvs.values()));
setTtl(new LLDPTLV().setType(TTL_TLV_TYPE)
.setLength((short) ttlValue.length)
.setValue(ttlValue));
-
}
private ONOSLLDP(LLDP lldp) {
@@ -79,17 +96,31 @@
}
public void setName(String name) {
- nameTLV.setLength((short) (name.length() + NAME_LENGTH));
- nameTLV.setInfoString(name);
- nameTLV.setSubType(NAME_SUBTYPE);
- nameTLV.setOUI(ONLAB_OUI);
+ LLDPOrganizationalTLV nametlv = opttlvs.get(NAME_SUBTYPE);
+ nametlv.setLength((short) (name.length() + NAME_LENGTH));
+ nametlv.setInfoString(name);
+ nametlv.setSubType(NAME_SUBTYPE);
+ nametlv.setOUI(ONLAB_OUI);
}
public void setDevice(String device) {
- deviceTLV.setInfoString(device);
- deviceTLV.setLength((short) (device.length() + DEVICE_LENGTH));
- deviceTLV.setSubType(DEVICE_SUBTYPE);
- deviceTLV.setOUI(ONLAB_OUI);
+ LLDPOrganizationalTLV devicetlv = opttlvs.get(DEVICE_SUBTYPE);
+ devicetlv.setInfoString(device);
+ devicetlv.setLength((short) (device.length() + DEVICE_LENGTH));
+ devicetlv.setSubType(DEVICE_SUBTYPE);
+ devicetlv.setOUI(ONLAB_OUI);
+ }
+
+ public void setDomainInfo(String domainId) {
+ LLDPOrganizationalTLV domaintlv = opttlvs.get(DOMAIN_SUBTYPE);
+ if (domaintlv == null) {
+ // maybe warn people not to set this if remote probes aren't.
+ return;
+ }
+ domaintlv.setInfoString(domainId);
+ domaintlv.setLength((short) (domainId.length() + DOMAIN_LENGTH));
+ domaintlv.setSubType(DOMAIN_SUBTYPE);
+ domaintlv.setOUI(ONLAB_OUI);
}
public void setChassisId(final ChassisId chassisId) {
@@ -139,6 +170,24 @@
return null;
}
+ /**
+ * Gets the TLV associated with remote probing. This TLV will be null if
+ * remote probing is disabled.
+ *
+ * @return A TLV containing domain ID, or null.
+ */
+ public LLDPOrganizationalTLV getDomainTLV() {
+ for (LLDPTLV tlv : this.getOptionalTLVList()) {
+ if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
+ LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
+ if (orgTLV.getSubType() == DOMAIN_SUBTYPE) {
+ return orgTLV;
+ }
+ }
+ }
+ return null;
+ }
+
public String getNameString() {
LLDPOrganizationalTLV tlv = getNameTLV();
if (tlv != null) {
@@ -155,6 +204,14 @@
return null;
}
+ public String getDomainString() {
+ LLDPOrganizationalTLV tlv = getDomainTLV();
+ if (tlv != null) {
+ return new String(tlv.getInfoString(), StandardCharsets.UTF_8);
+ }
+ return null;
+ }
+
public Integer getPort() {
ByteBuffer portBB = ByteBuffer.wrap(this.getPortId().getValue());
portBB.position(1);
@@ -177,4 +234,40 @@
}
return null;
}
+
+ /**
+ * Creates a link probe for link discovery/verification.
+ *
+ * @param deviceId The device ID as a String
+ * @param chassisId The chassis ID of the device
+ * @param portNum Port number of port to send probe out of
+ * @return ONOSLLDP probe message
+ */
+ public static ONOSLLDP onosLLDP(String deviceId, ChassisId chassisId, int portNum) {
+ ONOSLLDP probe = new ONOSLLDP(NAME_SUBTYPE, DEVICE_SUBTYPE);
+ probe.setPortId(portNum);
+ probe.setDevice(deviceId);
+ probe.setChassisId(chassisId);
+ return probe;
+ }
+
+ /**
+ * Creates a link probe carrying a fingerprint unique to the ONOS cluster managing
+ * link discovery/verification.
+ *
+ * @param deviceId The device ID as a String
+ * @param chassisId The chassis ID of the device
+ * @param portNum Port number of port to send probe out of
+ * @param domainId The cluster's fingerprint
+ * @return ONOSLLDP probe message
+ */
+ public static ONOSLLDP fingerprintedLLDP(
+ String deviceId, ChassisId chassisId, int portNum, String domainId) {
+ ONOSLLDP probe = new ONOSLLDP(NAME_SUBTYPE, DEVICE_SUBTYPE, DOMAIN_SUBTYPE);
+ probe.setPortId(portNum);
+ probe.setDevice(deviceId);
+ probe.setChassisId(chassisId);
+ probe.setDomainInfo(domainId);
+ return probe;
+ }
}