Using LLDP on Linux


icon

Introduction

Link Layer Discovery Protocol (LLDP) is a layer 2 neighbor discovery protocol that allows devices to advertise device information to their directly connected peers/neighbors. It is best practice to enable LLDP globally to standardize network topology across all devices if you have a multi-vendor network.

Commonly used layer 2 discovery protocols are often vendor-proprietary, for instance, Cisco’s CDP, Foundry’s FDP, Extreme’s EDP and Nortel’s SONMP. This makes layer 2 discovery difficult in a heterogeneous environment. To counter this, IETF has introduced a standard vendor-neutral configuration exchange protocol -- the LLDP.

info

Using LLDP, device information such as chassis identification, port ID, port description, system name and description, device capability (as router, switch, hub…), IP/MAC address, etc., are transmitted to the neighboring devices. This information is also stored in local Management Information Databases (MIBs), and can be queried with the Simple Network Management Protocol (SNMP). The LLDP-enabled devices have an LLDP agent installed in them, which sends out advertisements from all physical interfaces either periodically or as changes occur.

Enabling LLDP on Linux

On Linux there are two solutions that can be used to provide LLDP support on your systems:

I personally like lldpd as you only need to install it and it will start working. Another benefit of lldpd is that it has multiple protocol support. lldpd supports CDP, FDP, EDP and SONMP. Unfortunately, lldpd is only available in Alpine Linux's community repositories. The main repositories only contain open-lldp. See this article for explanation of the Alpine Linux repositories.

Because I usually do not like to enable community repos, I had to figure out how to use open-lldp. I found an article which explains how to use open-lldp here.

Using open-lldp

Install and enable the agent:

apk add open-lldp
rc-update add lldpad
service lldpad start

Once running, you need to configure the agent. Currently I am using a start-up script, but the agent supports a configuration file in /etc/lldpad.conf. Note the config file is updated automatically by the lldpad agent when you change its configuration.

Configure things:

lldptool -L -i eth0 adminStatus
lldptool -i eth0 -T -V portDesc enableTx=yes
lldptool -i eth0 -T -V sysName  enableTx=yes
lldptool -i eth0 -T -V sysDesc enableTx=yes
lldptool -i eth0 -T -V sysCap enableTx=yes
lldptool -i eth0 -T -V mngAddr ipv4=192.168.42.66 enableTx=yes

To query neighbors:

# lldptool -t -n -i eth0

Chassis ID TLV
        MAC: 9c:8e:99:bd:b1:20
Port ID TLV
        Local: 12
Time to Live TLV
        120
Port Description TLV
        Port #12
System Name TLV
        switch1
System Description TLV
         HP ProCurve 1810G - 24 GE, P.2.12, eCos-2.0, CFE-2.1
System Capabilities TLV
        System capabilities:  Bridge
        Enabled capabilities: Bridge
Management Address TLV
        IPv4: 192.168.40.11
        Ifindex: 25
End of LLDPDU TLV

View from switch Web GUI:

screenshot

To get configured TLV values:

# lldptool -l -i ne0 adminStatus -c
adminStatus=rxtx
# lldptool -i ne0 -t -V portDesc -c
enableTx=yes
# lldptool -i ne0 -t -V mngAddr -c
ipv4=192.168.2.6
ipv6=
enableTx=yes

Using lldpd

Enable the community repo in /etc/apk/repositories

Install and enable the daemon:

apk add lldpd
rc-update add lldpd
service lldpd start

This is enough by default. If you want to enable additional protocols you must modify the file /etc/conf.d/lldpd and add the relevant options for additional protocol support:

  • -c : Enable the support of CDP protocol. (Cisco)
  • -e : Enable the support of EDP protocol. (Extreme)
  • -f : Enable the support of FDP protocol. (Foundry)
  • -s : Enable the support of SONMP protocol. (Nortel)

Query neighbors:

# lldpctl
-------------------------------------------------------------------------------
LLDP neighbors:
-------------------------------------------------------------------------------
Interface:    eth0, via: LLDP, RID: 1, Time: 0 day, 09:50:19
  Chassis:     
    ChassisID:    mac d4:01:c3:2f:cc:2e
    SysName:      swap4
    SysDescr:     MikroTik RouterOS 6.49.15 (stable) RBD52G-5HacD2HnD
    MgmtIP:       192.168.2.204
    MgmtIface:    4
    MgmtIP:       192.168.2.3
    MgmtIface:    4
    Capability:   Bridge, on
    Capability:   Router, on
    Capability:   Wlan, on
  Port:        
    PortID:       ifname bridge/ether2
    TTL:          120
-------------------------------------------------------------------------------

Hints and Tips

l2net

When I first tried this I did a mistake of creating a loop on my network, so STP disabled the port I was running LLDP. Weirdly enough, I would occasionally see neighbors on that port. So to troubleshoot, I was using tcpdump. These are some useful options:

  • -i nic : Select the interface
  • -v or -vv : more protocol decoding
  • -e : Show Ethernet Frame fields
  • ether proto 0x88cc : select LLDP frames (Protocol ID 0x88cc)

Also when configuring open-lldp, I would want to configure on the physical devices. I use this loop in bash:

for nic in $(ls -1 /sys/class/net/)
do
  [ ! -d /sys/class/net/"$nic"/device ] && continue
  if [ -f /sys/class/net/"$nic"/device/modalias ] ; then
    # Special rule to filter out xen backend interfaces
    grep -q xen-backend /sys/class/net/"$nic"/device/modalias && continue
  fi

  # CONFIG COMMANDS GO HERE
done

Normally, LLDP frames will not propagate through Linux bridges. This is the intended bridge behaviour. If you are for example using virtualization on your system and would like the VMs to see LLDP frames, you can force LLDP frames to be forwarded. See this article.

Enable LLDP forwarding:

echo 0x4000 > /sys/class/net/<bridge_name>/bridge/group_fwd_mask

This is a runtime change to make this more permanent, I do it from the Alpine Linux /etc/network/interfaces file:

# /etc/network/interfaces

auto br1
iface br1 inet dhcp
  bridge-ports eth0 eth1
  up echo 0x4000 > /sys/class/net/$IFACE/bridge/group_fwd_mask

On the other hand, on the MikroTik RouterOS switch I am using LLDP frames are passed through by default. So on the neighbors list I would see not just the switch but all the other devices on the other side of the switch. The switch has routing, bridging and switch capabilities. In RouterOS, bridging is done by software, while switching is done by a hardware chip on the device. Since obviously you would want to use switching when possible, you can add a switch rule to filter out LLDP frames:

/interface/ethernet/switch/rule> add switch=switch1 ports=ether3,ether4 mac-protocol=lldp copy-to-cpu=no redirect-to-cpu=yes mirror=no

This needs to be done in the CLI as the WebFIG UI won't let you select the LLDP protocol. See this. The redirect-to-cpu make sure the CPU gets incoming LLDP for book keeping but restricts forwarding.