首頁 > 後端開發 > Golang > golang怎麼實作LLDP協議

golang怎麼實作LLDP協議

PHPz
發布: 2023-04-18 09:24:41
原創
1028 人瀏覽過

LLDP (Link Layer Discovery Protocol) 是一種資料鏈路層協議,它允許設備在網路中發現相鄰設備並了解有關相鄰設備的資訊。在大型網路中,LLDP用於自動配置網路拓撲和連接資訊。 Go語言是一種高效能、可靠、並發且易於編寫的程式語言,因此可以使用Go語言實作LLDP協定。

在實作LLDP時,需要了解LLDP訊框的結構和標準。下面是LLDP訊框的結構:

LLDP結構
LLDP頭(7個位元組)
TLV Type(2個位元組) TLV Length(2個位元組) Value(0-507位元組)
. ..
TLV Type(2個位元組) TLV Length(2個位元組) Value(0-507位元組)
FCS(4個位元組)

在LLDP訊框中,頭部是由7個位元組組成:2個位元組的LLDP標頭(0x01 0x80), 4個位元組的MAC位址,表示發送方的MAC位址,以及1個位元組的TTL(Time To Live)。

在LLDP訊框中,包含多個TLV(Type-Length-Value)元素。每個TLV都由3個部分組成:類型(2個位元組)、長度(2個位元組)和值(0到507個位元組)。可以添加任意數量的TLV元素,但是必須以封裝結束標記(TLV End包)結尾。

值得注意的是,使用LLDP協定時,不需要啟用任何實體的認證機制,因此可能需要採取其他方法來確保接收到的資訊來自真實的裝置。

使用Go語言實作LLDP時,可以採用第三方函式庫進行實現,例如gopacket和lldp。這些程式庫提供了一些方法,可以簡化LLDP幀的建立和解析,並幫助執行與LLDP相對應的處理。以下是使用gopacket函式庫的範例:

package main

import (
    "bytes"
    "fmt"
    "net"
    "time"

    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
)

func main() {
    // 构造LLDP帧
    srcMac := net.HardwareAddr{0xa0, 0x36, 0x9f, 0x10, 0xca, 0x00} // 发送方的MAC地址
    dstMac, _ := net.ParseMAC("01:80:C2:00:00:0E")                  // 目标MAC地址
    eth := layers.Ethernet{
        SrcMAC:       srcMac,
        DstMAC:       dstMac,
        EthernetType: layers.EthernetTypeLLDP,
    }

    ttll := layers.TTL{LayerType: layers.LayerTypeTTL, TTL: 120} // TTL 120
    chassisID := layers.LLDPBasicTLV{
        Type: layers.LLDPBasicTLVTypeChassisID,
        Length: 7,
        Value: []byte{0x04, 0x24, 0x16, 0x12, 0x34, 0x56},
    } // 构造Chassis ID TLV
    portID := layers.LLDPBasicTLV{
        Type: layers.LLDPBasicTLVTypePortID,
        Length: 4,
        Value: []byte{0x01, 0x23, 0x45, 0x67},
    } // 构造Port ID TLV
    // 构造End TLV, 其中Value为空
    endOfLLDPDU := layers.LLDPBasicTLV{
        Type: layers.LLDPBasicTLVTypeEndOfLLDPDU,
        Length: 0,
        Value: []byte{},
    }
    lldp := layers.LLDPPacket{
        BaseLayer: layers.BaseLayer{},
        ChassisID: chassisID,
        PortID: portID,
        TTL: ttll,
    }
    lldp.TLVs = append(lldp.TLVs, endOfLLDPDU)

    // 确定网络接口,并构造数据包
    nic, _ := net.InterfaceByName("en0") // 获取本地网络接口, en0是Mac上的有线网络接口
    buffer := gopacket.NewSerializeBuffer()
    options := gopacket.SerializeOptions{}
    gopacket.SerializeLayers(buffer, options,
        &eth,
        &lldp,
    )
    outgoingPacket := buffer.Bytes()

    // 打开网络设备, 并将LLDP包写入device中
    handle, _ := net.ListenPacket("en0", "LLDP") // 打开套接字
    defer handle.Close()
    handle.WriteTo(outgoingPacket, nil, &net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) // 向目标MAC发送包
    fmt.Println("LLDP packet sent at", time.Now().Format(time.Stamp))
}
登入後複製

這裡使用了gopacket函式庫來建立LLDP幀,並使用Ethernet類型為LLDP的來源位址和目標位址。然後,使用LLDPPacket類型的結構體來建構資料包。 Chassis ID和Port ID TLV是基本的TLV類型,可以使用LLDPBasicTLV類型的結構體來建立它們。創建TLV後,將End TLV加入到包中。最後使用序列化選項序列化套件。該套件將被寫入網路介面。

在實際應用中,可以透過連接埠監聽和解析LLDP套件。以下是一個使用lldp函式庫的範例:

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/atikur-rabbi/lldp"
)

func main() {
    msgChan := make(chan lldp.Message)
    errorChan := make(chan error)

    // 监听网络接口
    go lldp.Listen("en0", msgChan, errorChan)

    // 在error通道上显示所有错误, 并打印收到的LLDP消息
    for {
        select {
        case e := <-errorChan:
            log.Println("error occured", e)
        case msg := <-msgChan:
            log.Printf("Received LLDP packet from %v: %v\n", msg.RemoteAddr, msg.Message)
        }
    }
}
登入後複製

在這個範例中,我們啟動一個非同步goroutine來監聽指定的網路介面(這裡是en0)。在收到LLDP訊息時,使用error通道列印錯誤,並透過msg通道列印收到的訊息。

總之,LLDP是一種非常有用的協議,可用於在網路中發現並了解相鄰設備的資訊。使用Go語言可以輕鬆實現LLDP協定。透過第三方函式庫的支持,我們可以更快地實現幀的建立和解析,並更好地處理與LLDP相對應的任務。

以上是golang怎麼實作LLDP協議的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板