前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >LLDP报文格式

LLDP报文格式

作者头像
全栈程序员站长
发布2022-09-01 14:15:25
3410
发布2022-09-01 14:15:25
举报
文章被收录于专栏:全栈程序员必看

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

前面已经知道了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.)报文格式如下:

LLDP报文格式
LLDP报文格式

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

LLDP报文格式
LLDP报文格式

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档