Bernhard Bock

Get LLDP ports via tshark and Ansible

In order to check the cabling of a given set of compute servers, we needed to gather the switchports to which a set of NICs was connected. We wanted to have a nice CSV file for further processing.

The connected switchport is announced by the switch with a protocol called Link Layer Discovery Protocol (LLDP). On Linux, LLDP information is normally reported by lldpd, but it wasn’t available on those servers (neither was python3 😆)

As LLDP was enabled on the switches, though, we fell back to capturing the information via tshark.

#!/usr/bin/python2 -u
from __future__ import print_function
"""
Gather switchport information via tshark and LLDP

The script runs tshark over a hardcoded list of interfaces to capture
a LLDP packet with info about switch name and port ID.

The gathered info is printed on stdout in CSV format:
hostname;interface_name;switch_port_id;switch_name
Example:
overcloud-ovscompute-7;ens1f1;36241408;VV-LF-OFF-02
"""

import re
import socket
import subprocess

for interface in ["ens1f0", "ens1f1", "ens2f0", "ens2f1", "ens3f0", "ens3f1"]:
    print(socket.gethostname(), end=";")
    print(interface, end=";")
    tshark = subprocess.Popen(
        ["tshark", "-n", "-V", "-Q", "-c", "1", "-i", interface, "ether proto 0x88cc"],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    with tshark.stdout:
        for line in iter(tshark.stdout.readline, b""):
            match = re.search(br"Port Id: ([0-9]*)", line)
            if match:
                print(match.group(1), end=";")
            match = re.search(br"^    System Name = (.*)", line)
            if match:
                print(match.group(1), end="")
    tshark.wait()
    print()

The script was executed on all hosts and output was collected via Ansible:

---
# Gather switchport information via tshark and LLDP
# For the hardcoded list of ports taken into account, see the python script
# The gathered info is in output/switchports.csv

- name: get connected switchports
  hosts: '*'
  gather_facts: false
  tasks:
    - name: run script to capture switchport info via LLDP/tshark
      become: true
      script: ../scripts/linuxhost_get_connected_switchports.py
      changed_when: false
      register: portinfo_csv

    - name: write output to file
      delegate_to: localhost
      blockinfile:
        path: ../output/switchports.csv
        block: "{{ portinfo_csv.stdout }}"
        marker: ""
        create: true
        mode: 0644

— Mar 8, 2021