Home  >  Article  >  Backend Development  >  How to implement LLDP protocol in golang

How to implement LLDP protocol in golang

PHPz
PHPzOriginal
2023-04-18 09:07:23965browse

LLDP (Link Layer Discovery Protocol) is a data link layer protocol that allows devices to discover and learn information about neighboring devices in a network. In large networks, LLDP is used to automatically configure network topology and connection information. Go language is a high-performance, reliable, concurrent and easy-to-write programming language, so the LLDP protocol can be implemented using Go language.

When implementing LLDP, you need to understand the structure and standards of the LLDP frame. The following is the structure of the LLDP frame:

##TLV Type (2 bytes) TLV Length (2 bytes) Value (0-507 bytes) FCS (4 bytes)
LLDP structure
LLDP header (7 bytes )
TLV Type (2 bytes) TLV Length (2 bytes) Value (0-507 bytes)
. ..
In an LLDP frame, the header is composed of 7 bytes: 2 bytes of LLDP header (0x01 0x80), 4-byte MAC address, indicating the sender's MAC address, and 1-byte TTL (Time To Live).

In the LLDP frame, multiple TLV (Type-Length-Value) elements are included. Each TLV consists of 3 parts: type (2 bytes), length (2 bytes), and value (0 to 507 bytes). Any number of TLV elements can be added, but they must end with an encapsulation end tag (TLV End package).

It is worth noting that when using the LLDP protocol, there is no need to enable the authentication mechanism of any entity, so other methods may need to be taken to ensure that the information received comes from a real device.

When using Go language to implement LLDP, you can use third-party libraries for implementation, such as gopacket and lldp. These libraries provide methods that simplify the creation and parsing of LLDP frames and help perform processing corresponding to LLDP. The following is an example of using the gopacket library:

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))
}
The gopacket library is used here to create an LLDP frame, and the source and destination addresses of the Ethernet type are LLDP. Then, use the LLDPPacket type structure to construct the data packet. Chassis ID and Port ID TLVs are basic TLV types, and they can be created using structures of type LLDPBasicTLV. After creating the TLV, add the End TLV to the package. Finally serialize the package using serialization options. The packet will be written to the network interface.

In actual applications, LLDP packets can be monitored and parsed through the port. The following is an example using the lldp library:

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)
        }
    }
}
In this example, we start an asynchronous goroutine to listen on the specified network interface (here en0). When receiving an LLDP message, use the error channel to print the error, and print the received message through the msg channel.

In short, LLDP is a very useful protocol that can be used to discover and understand information about neighboring devices in the network. The LLDP protocol can be easily implemented using the Go language. With the support of third-party libraries, we can achieve faster frame creation and parsing and better handle tasks corresponding to LLDP.

The above is the detailed content of How to implement LLDP protocol in golang. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn