blob: e555f1fd3a40391d4e91f09d81f3ddc87c8567bc [file] [log] [blame]
/*
* Copyright 2014-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.onlab.packet;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onlab.packet.PacketUtils.*;
/**
* Representation of an LLDP Packet.
*/
public class LLDP extends BasePacket {
public static final byte CHASSIS_TLV_TYPE = 1;
public static final short CHASSIS_TLV_SIZE = 7;
public static final byte CHASSIS_TLV_SUBTYPE = 4;
public static final byte PORT_TLV_TYPE = 2;
public static final short PORT_TLV_SIZE = 5;
/**
* @deprecated since 1.15. Use the PORT_TLV_COMPONENT_SUBTYPE instead of PORT_TLV_SUBTYPE.
*/
@Deprecated
public static final byte PORT_TLV_SUBTYPE = 2;
public static final byte PORT_TLV_COMPONENT_SUBTYPE = PORT_TLV_SUBTYPE;
public static final byte PORT_TLV_INTERFACE_NAME_SUBTYPE = 5;
public static final byte TTL_TLV_TYPE = 3;
public static final short TTL_TLV_SIZE = 2;
protected LLDPTLV chassisId;
protected LLDPTLV portId;
protected LLDPTLV ttl;
protected List<LLDPTLV> optionalTLVList;
protected short ethType;
public LLDP() {
this.optionalTLVList = new LinkedList<>();
this.ethType = Ethernet.TYPE_LLDP;
}
/**
* @return the chassisId
*/
public LLDPTLV getChassisId() {
return this.chassisId;
}
/**
* @param chassis the chassisId to set
* @return this
*/
public LLDP setChassisId(final LLDPTLV chassis) {
this.chassisId = chassis;
return this;
}
/**
* @return the portId
*/
public LLDPTLV getPortId() {
return this.portId;
}
/**
* @param portId the portId to set
* @return this
*/
public LLDP setPortId(final LLDPTLV portId) {
this.portId = portId;
return this;
}
/**
* @return the ttl
*/
public LLDPTLV getTtl() {
return this.ttl;
}
/**
* @param ttl the ttl to set
* @return this
*/
public LLDP setTtl(final LLDPTLV ttl) {
this.ttl = ttl;
return this;
}
/**
* @return the optionalTLVList
*/
public List<LLDPTLV> getOptionalTLVList() {
return this.optionalTLVList;
}
/**
* @param optionalTLVList the optionalTLVList to set
* @return this
*/
public LLDP setOptionalTLVList(final List<LLDPTLV> optionalTLVList) {
this.optionalTLVList = optionalTLVList;
return this;
}
/**
* Adds additional TLV to optionalTLVList.
* @param lldptlv the optional TLV to be added
* @return this
*/
public LLDP addOptionalTLV(final LLDPTLV lldptlv) {
this.optionalTLVList.add(lldptlv);
return this;
}
@Override
public byte[] serialize() {
int length = 2 + this.chassisId.getLength() + 2
+ this.portId.getLength() + 2 + this.ttl.getLength() + 2;
for (final LLDPTLV tlv : this.optionalTLVList) {
length += 2 + tlv.getLength();
}
final byte[] data = new byte[length];
final ByteBuffer bb = ByteBuffer.wrap(data);
bb.put(this.chassisId.serialize());
bb.put(this.portId.serialize());
bb.put(this.ttl.serialize());
for (final LLDPTLV tlv : this.optionalTLVList) {
bb.put(tlv.serialize());
}
bb.putShort((short) 0); // End of LLDPDU
/*
* if (this.parent != null && this.parent instanceof Ethernet) {
* ((Ethernet) this.parent).setEtherType(this.ethType); }
*/
return data;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 883;
int result = super.hashCode();
result = prime * result
+ (this.chassisId == null ? 0 : this.chassisId.hashCode());
result = prime * result + this.optionalTLVList.hashCode();
result = prime * result
+ (this.portId == null ? 0 : this.portId.hashCode());
result = prime * result + (this.ttl == null ? 0 : this.ttl.hashCode());
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof LLDP)) {
return false;
}
final LLDP other = (LLDP) obj;
if (this.chassisId == null) {
if (other.chassisId != null) {
return false;
}
} else if (!this.chassisId.equals(other.chassisId)) {
return false;
}
if (!this.optionalTLVList.equals(other.optionalTLVList)) {
return false;
}
if (this.portId == null) {
if (other.portId != null) {
return false;
}
} else if (!this.portId.equals(other.portId)) {
return false;
}
if (this.ttl == null) {
if (other.ttl != null) {
return false;
}
} else if (!this.ttl.equals(other.ttl)) {
return false;
}
return true;
}
/**
* Deserializer function for LLDP packets.
*
* @return deserializer function
*/
public static Deserializer<LLDP> deserializer() {
return (data, offset, length) -> {
checkInput(data, offset, length, 0);
LLDP lldp = new LLDP();
int currentIndex = 0;
ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
LLDPTLV tlv;
do {
// Each new TLV must be a minimum of 2 bytes
// (containing the type and length fields).
currentIndex += 2;
checkHeaderLength(length, currentIndex);
tlv = new LLDPOrganizationalTLV().deserialize(bb);
// if there was a failure to deserialize stop processing TLVs
if (tlv == null) {
break;
}
switch (tlv.getType()) {
case 0x0:
// can throw this one away, it's just an end delimiter
break;
case 0x1:
lldp.chassisId = tlv;
break;
case 0x2:
lldp.portId = tlv;
break;
case 0x3:
lldp.ttl = tlv;
break;
default:
lldp.optionalTLVList.add(tlv);
break;
}
currentIndex += tlv.getLength();
} while (tlv.getType() != 0);
return lldp;
};
}
@Override
public String toString() {
return toStringHelper(getClass())
.add("chassisId", Arrays.toString(chassisId.getValue()))
.add("portId", Arrays.toString(portId.getValue()))
.add("ttl", Arrays.toString(ttl.getValue()))
.add("ethType", Short.toString(ethType))
.toString();
// TODO: need to handle optionalTLVList
}
}