Blame README.md

Packit e9ba0d
lldpd: implementation of IEEE 802.1ab (LLDP)
Packit e9ba0d
============================================
Packit e9ba0d
Packit e9ba0d
[![Build Status](https://secure.travis-ci.org/vincentbernat/lldpd.png?branch=master)](http://travis-ci.org/vincentbernat/lldpd)
Packit e9ba0d
Packit e9ba0d
  http://vincentbernat.github.com/lldpd/
Packit e9ba0d
Packit e9ba0d
Features
Packit e9ba0d
--------
Packit e9ba0d
Packit e9ba0d
LLDP (Link Layer Discovery Protocol) is an industry standard protocol
Packit e9ba0d
designed to supplant proprietary Link-Layer protocols such as
Packit e9ba0d
Extreme's EDP (Extreme Discovery Protocol) and CDP (Cisco Discovery
Packit e9ba0d
Protocol). The goal of LLDP is to provide an inter-vendor compatible
Packit e9ba0d
mechanism to deliver Link-Layer notifications to adjacent network
Packit e9ba0d
devices.
Packit e9ba0d
Packit e9ba0d
lldpd implements both reception and sending. It also implements an
Packit e9ba0d
SNMP subagent for net-snmp to get local and remote LLDP
Packit e9ba0d
information. The LLDP-MIB is partially implemented but the most useful
Packit e9ba0d
tables are here. lldpd also partially implements LLDP-MED.
Packit e9ba0d
Packit e9ba0d
lldpd supports bridge, vlan and bonding.
Packit e9ba0d
Packit e9ba0d
The following OS are supported:
Packit e9ba0d
Packit e9ba0d
 * FreeBSD
Packit e9ba0d
 * GNU/Linux
Packit e9ba0d
 * macOS
Packit e9ba0d
 * NetBSD
Packit e9ba0d
 * OpenBSD
Packit e9ba0d
 * Solaris
Packit e9ba0d
Packit e9ba0d
Windows is not supported but you can use
Packit e9ba0d
[WinLLDPService](https://github.com/raspi/WinLLDPService/) as a
Packit e9ba0d
transmit-only agent.
Packit e9ba0d
Packit e9ba0d
Installation
Packit e9ba0d
------------
Packit e9ba0d
Packit e9ba0d
For general instructions [prefer the
Packit e9ba0d
website](http://vincentbernat.github.io/lldpd/installation.html),
Packit e9ba0d
including building from released tarballs.
Packit e9ba0d
Packit e9ba0d
To compile lldpd from Git, use the following commands:
Packit e9ba0d
Packit e9ba0d
    ./autogen.sh
Packit e9ba0d
    ./configure
Packit e9ba0d
    make
Packit e9ba0d
    sudo make install
Packit e9ba0d
Packit e9ba0d
lldpd uses privilege separation to increase its security. Two
Packit e9ba0d
processes, one running as root and doing minimal stuff and the other
Packit e9ba0d
running as an unprivileged user into a chroot doing most of the stuff,
Packit e9ba0d
are cooperating. You need to create a user called `_lldpd` in a group
Packit e9ba0d
`_lldpd` (this can be change with `./configure`). You also need to
Packit e9ba0d
create an empty directory `/usr/local/var/run/lldpd` (it needs to be
Packit e9ba0d
owned by root, not `_lldpd`!). If you get fuzzy timestamps from
Packit e9ba0d
syslog, copy `/etc/locatime` into the chroot.
Packit e9ba0d
Packit e9ba0d
`lldpcli` lets one query information collected through the command
Packit e9ba0d
line. If you don't want to run it as root, just install it setuid or
Packit e9ba0d
setgid `_lldpd`.
Packit e9ba0d
Packit e9ba0d
Installation (macOS)
Packit e9ba0d
-----------------------
Packit e9ba0d
Packit e9ba0d
The same procedure as above applies for macOS. However, there are
Packit e9ba0d
simpler alternatives:
Packit e9ba0d
Packit e9ba0d
 1. Use [Homebrew](https://brew.sh):
Packit e9ba0d
Packit e9ba0d
        brew install lldpd
Packit e9ba0d
        # Or, for the latest version:
Packit e9ba0d
        brew install https://raw.github.com/vincentbernat/lldpd/master/osx/lldpd.rb
Packit e9ba0d
Packit e9ba0d
 2. Build an macOS installer package which should work on the same
Packit e9ba0d
    version of macOS:
Packit e9ba0d
 
Packit e9ba0d
        mkdir build && cd build
Packit e9ba0d
        ../configure --prefix=/usr/local --localstatedir=/var --sysconfdir=/private/etc --with-embedded-libevent \
Packit e9ba0d
            --without-snmp
Packit e9ba0d
        make -C osx pkg
Packit e9ba0d
Packit e9ba0d
    If you want to compile for an older version of macOS, you need
Packit e9ba0d
    to find the right SDK and issues commands like those:
Packit e9ba0d
Packit e9ba0d
        SDK=/Developer/SDKs/MacOSX10.6.sdk
Packit e9ba0d
        mkdir build && cd build
Packit e9ba0d
        ../configure --prefix=/usr/local --localstatedir=/var --sysconfdir=/private/etc --with-embedded-libevent \
Packit e9ba0d
           --without-snmp \
Packit e9ba0d
           CFLAGS="-mmacosx-version-min=10.6 -isysroot $SDK" \
Packit e9ba0d
           LDFLAGS="-mmacosx-version-min=10.6 -isysroot $SDK"
Packit e9ba0d
        make -C osx pkg
Packit e9ba0d
Packit e9ba0d
    With recent SDK, you don't need to specify an alternate SDK. They
Packit e9ba0d
    are organized in a way that should enable compatibility with older
Packit e9ba0d
    versions of OSX:
Packit e9ba0d
Packit e9ba0d
        mkdir build && cd build
Packit e9ba0d
        ../configure --prefix=/usr/local --localstatedir=/var --sysconfdir=/private/etc --with-embedded-libevent \
Packit e9ba0d
           --without-snmp \
Packit e9ba0d
           CFLAGS="-mmacosx-version-min=10.9" \
Packit e9ba0d
           LDFLAGS="-mmacosx-version-min=10.9"
Packit e9ba0d
        make -C osx pkg
Packit e9ba0d
Packit e9ba0d
    You can check with `otool -l` that you got what you expected in
Packit e9ba0d
    term of supported versions.
Packit e9ba0d
Packit e9ba0d
If you don't follow the above procedures, you will have to create the
Packit e9ba0d
user/group `_lldpd`. Have a look at how this is done in
Packit e9ba0d
`osx/scripts/postinstall`.
Packit e9ba0d
Packit e9ba0d
Installation (Android)
Packit e9ba0d
----------------------
Packit e9ba0d
Packit e9ba0d
You need to download [Android NDK][]. Once unpacked, you can generate
Packit e9ba0d
a toolchain using the following command:
Packit e9ba0d
Packit e9ba0d
    ./build/tools/make-standalone-toolchain.sh \
Packit e9ba0d
        --platform=android-9 \
Packit e9ba0d
        --arch=arm \
Packit e9ba0d
        --install-dir=../android-toolchain
Packit e9ba0d
    export TOOLCHAIN=$PWD/../android-toolchain
Packit e9ba0d
Packit e9ba0d
Then, you can build `lldpd` with the following commands:
Packit e9ba0d
Packit e9ba0d
    mkdir build && cd build
Packit e9ba0d
    export PATH=$PATH:$TOOLCHAIN/bin
Packit e9ba0d
    ../configure \
Packit e9ba0d
        --host=arm-linux-androideabi \
Packit e9ba0d
        --with-sysroot=$TOOLCHAIN/sysroot
Packit e9ba0d
Packit e9ba0d
[Android NDK]: http://developer.android.com/tools/sdk/ndk/index.html
Packit e9ba0d
Packit e9ba0d
Usage
Packit e9ba0d
-----
Packit e9ba0d
Packit e9ba0d
lldpd also implements CDP (Cisco Discovery Protocol), FDP (Foundry
Packit e9ba0d
Discovery Protocol), SONMP (Nortel Discovery Protocol) and EDP
Packit e9ba0d
(Extreme Discovery Protocol). However, recent versions of IOS should
Packit e9ba0d
support LLDP and most Extreme stuff support LLDP. When a EDP, CDP or
Packit e9ba0d
SONMP frame is received on a given interface, lldpd starts sending
Packit e9ba0d
EDP, CDP, FDP or SONMP frame on this interface. Informations collected
Packit e9ba0d
through EDP/CDP/FDP/SONMP are integrated with other informations and
Packit e9ba0d
can be queried with `lldpcli` or through SNMP.
Packit e9ba0d
Packit e9ba0d
More information:
Packit e9ba0d
 * http://en.wikipedia.org/wiki/Link_Layer_Discovery_Protocol
Packit e9ba0d
 * http://standards.ieee.org/getieee802/download/802.1AB-2005.pdf
Packit e9ba0d
 * http://wiki.wireshark.org/LinkLayerDiscoveryProtocol
Packit e9ba0d
Packit e9ba0d
Compatibility with older kernels
Packit e9ba0d
--------------------------------
Packit e9ba0d
Packit e9ba0d
If you have a kernel older than Linux 2.6.39, you need to compile
Packit e9ba0d
lldpd with `--enable-oldies` to enable some compatibility functions:
Packit e9ba0d
otherwise, lldpd will only rely on Netlink to receive bridge, bond and
Packit e9ba0d
VLAN information.
Packit e9ba0d
Packit e9ba0d
For bonding, you need 2.6.24 (in previous version, PACKET_ORIGDEV
Packit e9ba0d
affected only non multicast packets). See:
Packit e9ba0d
Packit e9ba0d
 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=80feaacb8a6400a9540a961b6743c69a5896b937
Packit e9ba0d
 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=8032b46489e50ef8f3992159abd0349b5b8e476c
Packit e9ba0d
Packit e9ba0d
Otherwise, a packet received on a bond will be affected to all
Packit e9ba0d
interfaces of the bond. In this case, lldpd will affect a received
Packit e9ba0d
randomly to one of the interface (so a neighbor may be affected to the
Packit e9ba0d
wrong interface).
Packit e9ba0d
Packit e9ba0d
On 2.6.27, we are able to receive packets on real interface for enslaved
Packit e9ba0d
devices. This allows one to get neighbor information on active/backup
Packit e9ba0d
bonds. Without the 2.6.27, lldpd won't receive any information on
Packit e9ba0d
inactive slaves. Here are the patchs (thanks to Joe Eykholt):
Packit e9ba0d
Packit e9ba0d
 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=0d7a3681232f545c6a59f77e60f7667673ef0e93
Packit e9ba0d
 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=cc9bd5cebc0825e0fabc0186ab85806a0891104f
Packit e9ba0d
 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f982307f22db96201e41540295f24e8dcc10c78f
Packit e9ba0d
Packit e9ba0d
On FreeBSD, only a recent 9 kernel (9.1 or more recent) will allow to
Packit e9ba0d
send LLDP frames on enslaved devices. See this bug report for more
Packit e9ba0d
information:
Packit e9ba0d
Packit e9ba0d
 * http://www.freebsd.org/cgi/query-pr.cgi?pr=138620
Packit e9ba0d
Packit e9ba0d
Some devices (notably Cisco IOS) send frames tagged with the native
Packit e9ba0d
VLAN while they should send them untagged. If your network card does
Packit e9ba0d
not support accelerated VLAN, you will receive those frames as long as
Packit e9ba0d
the corresponding interface exists (see below). However, if your
Packit e9ba0d
network card handles VLAN encapsulation/decapsulation (check with
Packit e9ba0d
`ethtool -k`), you need a recent kernel to be able to receive those
Packit e9ba0d
frames without listening on all available VLAN. Starting from Linux
Packit e9ba0d
2.6.27, lldpd is able to capture VLAN frames when VLAN acceleration is
Packit e9ba0d
supported by the network card. Here is the patch:
Packit e9ba0d
Packit e9ba0d
 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bc1d0411b804ad190cdadabac48a10067f17b9e6
Packit e9ba0d
Packit e9ba0d
On some other versions, frames are sent on VLAN 1. If this is not the
Packit e9ba0d
native VLAN and if your network card support accelerated VLAN, you
Packit e9ba0d
need to subscribe to this VLAN as well. The Linux kernel does not
Packit e9ba0d
provide any interface for this. The easiest way is to create the VLAN
Packit e9ba0d
for each port:
Packit e9ba0d
Packit e9ba0d
    ip link add link eth0 name eth0.1 type vlan id 1
Packit e9ba0d
    ip link set up dev eth0.1
Packit e9ba0d
Packit e9ba0d
You can check both cases using tcpdump:
Packit e9ba0d
Packit e9ba0d
    tcpdump -epni eth0 ether host 01:80:c2:00:00:0e
Packit e9ba0d
    tcpdump -eni eth0 ether host 01:80:c2:00:00:0e
Packit e9ba0d
Packit e9ba0d
If the first command does not display received LLDP packets but the
Packit e9ba0d
second one does, LLDP packets are likely encapsulated into a VLAN:
Packit e9ba0d
Packit e9ba0d
    10:54:06.431154 f0:29:29:1d:7c:01 > 01:80:c2:00:00:0e, ethertype 802.1Q (0x8100), length 363: vlan 1, p 7, ethertype LLDP, LLDP, name SW-APP-D07.VTY, length 345
Packit e9ba0d
Packit e9ba0d
In this case, just create VLAN 1 will fix the situation. There are
Packit e9ba0d
other solutions:
Packit e9ba0d
Packit e9ba0d
 1. Disable VLAN acceleration on the receive side (`ethtool -K eth0
Packit e9ba0d
    rxvlan off`) but this may or may not work. Check if there are
Packit e9ba0d
    similar properties that could apply with `ethtool -k eth0`.
Packit e9ba0d
 2. Put the interface in promiscuous mode with `ip link set
Packit e9ba0d
    promisc on dev eth0`.
Packit e9ba0d
Packit e9ba0d
The last solution can be done directly by `lldpd` (on Linux only) by
Packit e9ba0d
using the option `configure system interface promiscuous`.
Packit e9ba0d
Packit e9ba0d
On modern networks, the performance impact should be nonexistent.
Packit e9ba0d
Packit e9ba0d
Development
Packit e9ba0d
-----------
Packit e9ba0d
Packit e9ba0d
During development, you may want to execute lldpd at its current
Packit e9ba0d
location instead of doing `make install`. The correct way to do this is
Packit e9ba0d
to issue the following command:
Packit e9ba0d
Packit e9ba0d
    sudo libtool execute src/daemon/lldpd -L $PWD/src/client/lldpcli -d
Packit e9ba0d
Packit e9ba0d
You can append any further arguments. If lldpd is unable to find
Packit e9ba0d
`lldpcli` it will start in an unconfigured mode and won't send or
Packit e9ba0d
accept LLDP frames.
Packit e9ba0d
Packit e9ba0d
You can use [afl](http://lcamtuf.coredump.cx/afl/) to test some
Packit e9ba0d
aspects of lldpd. To test frame decoding, you can do something like
Packit e9ba0d
that:
Packit e9ba0d
Packit e9ba0d
    export AFL_USE_ASAN=1 # only on 32bit arch
Packit e9ba0d
    ./configure CC=afl-gcc
Packit e9ba0d
    make clean check
Packit e9ba0d
    cd tests
Packit e9ba0d
    mkdir inputs
Packit e9ba0d
    mv *.pcap inputs
Packit e9ba0d
    afl-fuzz -i inputs -o outputs ./decode @@
Packit e9ba0d
Packit e9ba0d
There is a general test suite with `make check`. It's also possible to
Packit e9ba0d
run integration tests. They need [py.test](http://pytest.org/latest/)
Packit e9ba0d
and rely on Linux containers to be executed.
Packit e9ba0d
Packit e9ba0d
To enable code coverage, use:
Packit e9ba0d
Packit e9ba0d
    ../configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
Packit e9ba0d
                 --enable-sanitizers --enable-gcov --with-snmp \
Packit e9ba0d
                 CFLAGS="-O0 -g"
Packit e9ba0d
    make
Packit e9ba0d
    make check
Packit e9ba0d
    # maybe, run integration tests
Packit e9ba0d
    lcov --base-directory $PWD/src/lib \
Packit e9ba0d
         --directory src --capture --output-file gcov.info
Packit e9ba0d
    genhtml gcov.info --output-directory coverage
Packit e9ba0d
Packit e9ba0d
Embedding
Packit e9ba0d
---------
Packit e9ba0d
Packit e9ba0d
To embed lldpd into an existing system, there are two point of entries:
Packit e9ba0d
Packit e9ba0d
 1. If your system does not use standard Linux interface, you can
Packit e9ba0d
    support additional interfaces by implementing the appropriate
Packit e9ba0d
    `struct lldpd_ops`. You can look at
Packit e9ba0d
    `src/daemon/interfaces-linux.c` for examples. Also, have a look at
Packit e9ba0d
    `interfaces_update()` which is responsible for discovering and
Packit e9ba0d
    registering interfaces.
Packit e9ba0d
Packit e9ba0d
 2. `lldpcli` provides a convenient way to query `lldpd`. It also
Packit e9ba0d
    comes with various outputs, including XML which allows one to
Packit e9ba0d
    parse its output for integration and automation purpose. Another
Packit e9ba0d
    way is to use SNMP support. A third way is to write your own
Packit e9ba0d
    controller using `liblldpctl.so`. Its API is described in
Packit e9ba0d
    `src/lib/lldpctl.h`. The custom binary protocol between
Packit e9ba0d
    `liblldpctl.so` and `lldpd` is not stable. Therefore, the library
Packit e9ba0d
    should always be shipped with `lldpd`. On the other hand, programs
Packit e9ba0d
    using `liblldpctl.so` can rely on the classic ABI rules.
Packit e9ba0d
Packit e9ba0d
Troubleshooting
Packit e9ba0d
---------------
Packit e9ba0d
Packit e9ba0d
You can use `tcpdump` to look after the packets received and send by
Packit e9ba0d
`lldpd`. To look after LLDPU, use:
Packit e9ba0d
Packit e9ba0d
    tcpdump -s0 -vv -pni eth0 ether dst 01:80:c2:00:00:0e
Packit e9ba0d
Packit e9ba0d
Intel X710 cards may handle LLDP themselves, intercepting any incoming
Packit e9ba0d
packets. If you don't see anything through `tcpdump`, check if you
Packit e9ba0d
have such a card (with `lspci`) and stop the embedded LLDP daemon:
Packit e9ba0d
Packit e9ba0d
    for f in /sys/kernel/debug/i40e/*/command; do
Packit e9ba0d
        echo lldp stop > $f
Packit e9ba0d
    done
Packit e9ba0d
Packit e9ba0d
License
Packit e9ba0d
-------
Packit e9ba0d
Packit e9ba0d
lldpd is distributed under the ISC license:
Packit e9ba0d
Packit e9ba0d
 > Permission to use, copy, modify, and/or distribute this software for any
Packit e9ba0d
 > purpose with or without fee is hereby granted, provided that the above
Packit e9ba0d
 > copyright notice and this permission notice appear in all copies.
Packit e9ba0d
 >
Packit e9ba0d
 > THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
Packit e9ba0d
 > WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
Packit e9ba0d
 > MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Packit e9ba0d
 > ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Packit e9ba0d
 > WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
Packit e9ba0d
 > ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Packit e9ba0d
 > OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Packit e9ba0d
Packit e9ba0d
Also, `lldpcli` will be linked to GNU Readline (which is GPL licensed)
Packit e9ba0d
if available. To avoid this, use `--without-readline` as a configure
Packit e9ba0d
option.