LLDP使用技术报告
背景
链路层发现协议(Link Layer Discovery Protocol,LLDP)是一种网络协议,主要用于在以太网网络中发现相邻设备并与其交换信息。LLDP是一种开放的标准,由IEEE 802.1AB定义,能够跨多个厂商的设备进行互操作。它的主要功能是帮助网络管理员识别网络拓扑结构,便于管理和故障排除。
LLDP在网络设备之间周期性地发送和接收LLDP数据单元(LLDPDU),这些数据单元包含设备的配置信息和能力。每个LLDPDU由多个TLV(Type-Length-Value)字段组成,每个字段包含特定类型的信息。
最常用的字段
LLDPDU中的常用TLV字段包括:
- Chassis ID TLV:识别设备底盘的唯一标识符,通常是设备的MAC地址。
- Port ID TLV:标识发送LLDPDU的端口,可以是端口的MAC地址或端口号。
- Time to Live (TTL) TLV:指定LLDP信息的生存时间,单位为秒。
- Port Description TLV:描述端口的信息,如端口名称或类型。
- System Name TLV:设备的主机名。
- System Description TLV:设备的详细描述,包括制造商、型号和操作系统版本等信息。
- System Capabilities TLV:设备的功能和当前启用的功能,如交换机、路由器等。
- Management Address TLV:设备的管理地址,可以是IPv4或IPv6地址。
Chassis Subtype 的字段
Chassis Subtype TLV 包含以下几个字段:
- TLV 类型(Type):表示这是一个 Chassis Subtype TLV。
- TLV 长度(Length):表示该 TLV 的总长度。
- 子类型(Subtype):指定 Chassis Subtype 的类型,常见的子类型包括:
- 1:MAC 地址:表示使用设备的 MAC 地址作为标识。
- 2:网络地址:使用网络地址(如 IP 地址)作为标识。
- 3:主机名:使用设备的主机名作为标识。
- 4:UUID:使用通用唯一标识符(UUID)作为标识。
- 5:描述:使用一个描述性字符串作为标识。
- 子类型值(Subtype Value):具体的标识值,根据子类型不同,这个值也不同。例如,如果子类型是 MAC 地址,那么子类型值就是一个具体的 MAC 地址。
使用示例
假设我们有一台设备,其 MAC 地址为 00:1A:2B:3C:4D:5E
。它将使用 Chassis Subtype TLV 来广播它的 MAC 地址。
TLV 结构:
- Type: 1 (Chassis Subtype)
- Length: 7
- Subtype: 1 (MAC Address)
- Subtype Value: 00:1A:2B:3C:4D:5E
自定义字段
除了标准的TLV字段外,LLDP还允许使用自定义TLV字段。这些字段可以携带特定的厂商信息或特定应用的配置信息。定义自定义TLV字段时,需要确保Type值在特定范围内,以避免与标准字段冲突。
实验设备
实验设备包括一台PC和一台嵌入式Linux设备。在本次实验中,我们将演示如何在PC端使用Python Qt实现设备发现功能,并在嵌入式Linux设备上使用C语言发送设备信息。
PC端代码 (Python Qt)
import sys
import threading
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QTextEdit
from scapy.all import *
from scapy.layers.l2 import Ether
# Define LLDP layer
class LLDPDU(Packet):
name = "LLDPDU"
fields_desc = [
ByteField("type", 0),
ByteField("length", 0),
StrLenField("value", "", length_from=lambda pkt:pkt.length)
]
class SnifferThread(QObject):
packet_received = pyqtSignal(str)
def start_sniffing(self):
thread = threading.Thread(target=self.sniff_packets)
thread.daemon = True
thread.start()
def sniff_packets(self):
print("Starting packet sniffing...")
sniff(filter="ether proto 0x88cc", prn=self.process_packet, store=0)
print("Packet sniffing stopped.")
def process_packet(self, packet):
if packet.haslayer(Ether