LLDP报文格式

2022-09-01 14:15:25 浏览数 (2)

大家好,又见面了,我是你们的朋友全栈君。

前面已经知道了Floodlight Controller是通过从SW发送LLDP帧来获得链路信息的,链路层发现协议(L2)是通过在本地网络中广播LLDP报文来通告自己的设备信息,从而服务于拓扑计算,(wikipedia:LLDP information is sent by devices from each of their interfaces at a fixed interval, in the form of an Ethernet frame. Each frame contains one LLDP Data Unit (LLDPDU). Each LLDPDU is a sequence of type-length-value (TLV) structures.)报文格式如下:

type-length-value 的设计很常见(比如netlink中attribute也是这种格式),这里的TLV结构是:

此时再看代码就很容易理解:

public class LLDPTLV {

protected byte type ;

protected short length ;

protected byte [] value ;

public byte getType() {

return type ;

}

public LLDPTLV setType( byte type) {

this . type = type;

return this ;

}

public short getLength() {

return length ;

}

public LLDPTLV setLength( short length) {

this . length = length;

return this ;

}

public byte [] getValue() {

return value ;

}

public LLDPTLV setValue( byte [] value) {

this . value = value;

return this ;

}

// serialization – Turn data into a stream of bytes

public byte [] serialize() {

// type = 7 bits

// info string length 9 bits, each value == byte

// info string

short scratch = ( short ) (((0x7f & this . type ) << 9) | (0x1ff & this . length ));

// 7 9 = 2B

byte [] data = new byte [2 this . length ];

ByteBuffer bb = ByteBuffer. wrap(data);

bb.putShort(scratch);

if ( this . value != null )

bb.put( this . value );

return data;

}

// deserialization – Turn a stream of bytes back into a copy of the original

// object.

public LLDPTLV deserialize(ByteBuffer bb) {

short sscratch;

sscratch = bb.getShort();

this . type = ( byte ) ((sscratch >> 9) & 0x7f);

this . length = ( short ) (sscratch & 0x1ff);

if ( this . length > 0) {

this . value = new byte [ this . length ];

// if there is an underrun just toss the TLV

if (bb.remaining() < this . length )

return null ;

bb.get( this . value );

}

return this ;

}

}


public class LLDP extends BasePacket {

protected LLDPTLV chassisId ;

protected LLDPTLV portId ;

protected LLDPTLV ttl ;

protected List<LLDPTLV> optionalTLVList ;

protected short ethType ;

//上述几个字段都是LLDP协议规定的

public LLDP() {

this . optionalTLVList = new ArrayList<LLDPTLV>();

this . ethType = Ethernet. TYPE_LLDP ; // 0x88cc

}

public LLDPTLV getChassisId() {

return chassisId ;

}

public LLDP setChassisId(LLDPTLV chassisId) {

this . chassisId = chassisId;

return this ;

}

public LLDPTLV getPortId() {

return portId ;

}

public LLDP setPortId(LLDPTLV portId) {

this . portId = portId;

return this ;

}

public LLDPTLV getTtl() {

return ttl ;

}

public LLDP setTtl(LLDPTLV ttl) {

this . ttl = ttl;

return this ;

}

public List<LLDPTLV> getOptionalTLVList() {

return optionalTLVList ;

}

public LLDP setOptionalTLVList(List<LLDPTLV> optionalTLVList) {

this . optionalTLVList = optionalTLVList;

return this ;

}

@Override

public byte [] serialize() {

int length = 2 this . chassisId .getLength() 2

this . portId .getLength() 2 this . ttl .getLength() 2;

for (LLDPTLV tlv : this . optionalTLVList ) {

length = 2 tlv.getLength();

}

byte [] data = new byte [length];

ByteBuffer bb = ByteBuffer. wrap(data);

bb.put( this . chassisId .serialize());

bb.put( this . portId .serialize());

bb.put( this . ttl .serialize());

for (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( ethType );

return data;

}

@Override

public IPacket deserialize( byte [] data, int offset, int length) {

ByteBuffer bb = ByteBuffer. wrap(data, offset, length);

LLDPTLV tlv;

do {

tlv = new LLDPTLV().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, its just an end delimiter

break ;

case 0x1:

this . chassisId = tlv;

break ;

case 0x2:

this . portId = tlv;

break ;

case 0x3:

this . ttl = tlv;

break ;

default :

this . optionalTLVList .add(tlv);

break ;

}

} while (tlv.getType() != 0 && bb.hasRemaining());

return this ;

}

}

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/140278.html原文链接:https://javaforall.cn

0 人点赞