--- /dev/null
+[∗] Waiting for commands.
+[∗] Execute command libtool execute src/daemon/lldpd -M 1 -L $PWD/src/client/lldpcli.
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface1, via: LLDP, RID: 1, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:b3:3c:2c:36
+ SysName: R2
+ SysDescr:
+ MgmtIP: 192.0.2.16
+ MgmtIP: 2001:db8::cafe:16
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Station, on
+ Port:
+ PortID: mac 50:54:b3:3c:2c:36
+ PortDescr: iface1
+ LLDP-MED:
+ Device Type: Media Endpoint (Class II)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+Interface: iface1, via: LLDP, RID: 2, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:07:79:57:69
+ SysName: R3
+ SysDescr:
+ MgmtIP: 192.0.2.17
+ MgmtIP: 2001:db8::cafe:17
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Tel, on
+ Capability: Station, on
+ Port:
+ PortID: mac 50:54:07:79:57:69
+ PortDescr: iface1
+ LLDP-MED:
+ Device Type: Communication Device Endpoint (Class III)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+Interface: iface2, via: LLDP, RID: 1, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:b3:3c:2c:36
+ SysName: R2
+ SysDescr:
+ MgmtIP: 192.0.2.16
+ MgmtIP: 2001:db8::cafe:16
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Station, on
+ Port:
+ PortID: mac 50:54:0e:ec:6e:77
+ PortDescr: iface2
+ LLDP-MED:
+ Device Type: Media Endpoint (Class II)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+Interface: iface3, via: LLDP, RID: 1, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:b3:3c:2c:36
+ SysName: R2
+ SysDescr:
+ MgmtIP: 192.0.2.16
+ MgmtIP: 2001:db8::cafe:16
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Station, on
+ Port:
+ PortID: mac 50:54:5e:ed:e2:df
+ PortDescr: iface3
+ LLDP-MED:
+ Device Type: Media Endpoint (Class II)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+Interface: iface4, via: LLDP, RID: 2, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:07:79:57:69
+ SysName: R3
+ SysDescr:
+ MgmtIP: 192.0.2.17
+ MgmtIP: 2001:db8::cafe:17
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Tel, on
+ Capability: Station, on
+ Port:
+ PortID: mac 50:54:30:01:78:dd
+ PortDescr: iface2
+ LLDP-MED:
+ Device Type: Communication Device Endpoint (Class III)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+Interface: iface5, via: LLDP, RID: 2, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:07:79:57:69
+ SysName: R3
+ SysDescr:
+ MgmtIP: 192.0.2.17
+ MgmtIP: 2001:db8::cafe:17
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Tel, on
+ Capability: Station, on
+ Port:
+ PortID: mac 50:54:ef:f4:f5:bf
+ PortDescr: iface3
+ LLDP-MED:
+ Device Type: Communication Device Endpoint (Class III)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail ports iface2.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface2, via: LLDP, RID: 1, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:b3:3c:2c:36
+ SysName: R2
+ SysDescr:
+ MgmtIP: 192.0.2.16
+ MgmtIP: 2001:db8::cafe:16
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Station, on
+ Port:
+ PortID: mac 50:54:0e:ec:6e:77
+ PortDescr: iface2
+ VLAN: 450 iface2.450
+ VLAN: 451 iface2.451
+ VLAN: 452 iface2.452
+ LLDP-MED:
+ Device Type: Media Endpoint (Class II)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail ports iface2.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface2, via: LLDP, RID: 1, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:b3:3c:2c:36
+ SysName: R2
+ SysDescr:
+ MgmtIP: 192.0.2.16
+ MgmtIP: 2001:db8::cafe:16
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Station, on
+ Port:
+ PortID: mac 50:54:0e:ec:6e:77
+ PortDescr: iface2
+ VLAN: 450 iface2.450
+ VLAN: 452 iface2.452
+ LLDP-MED:
+ Device Type: Media Endpoint (Class II)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail ports iface4.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface4, via: LLDP, RID: 2, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:07:79:57:69
+ SysName: R3
+ SysDescr:
+ MgmtIP: 192.0.2.17
+ MgmtIP: 2001:db8::cafe:17
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Tel, on
+ Capability: Station, off
+ Port:
+ PortID: mac 50:54:30:01:78:dd
+ PortDescr: iface2
+ Port is aggregated. PortAggregID: 6
+ LLDP-MED:
+ Device Type: Communication Device Endpoint (Class III)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail ports iface5.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface5, via: LLDP, RID: 2, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:07:79:57:69
+ SysName: R3
+ SysDescr:
+ MgmtIP: 192.0.2.17
+ MgmtIP: 2001:db8::cafe:17
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Tel, on
+ Capability: Station, off
+ Port:
+ PortID: mac 50:54:ef:f4:f5:bf
+ PortDescr: iface3
+ Port is aggregated. PortAggregID: 6
+ LLDP-MED:
+ Device Type: Communication Device Endpoint (Class III)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail ports iface4.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface4, via: LLDP, RID: 2, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:07:79:57:69
+ SysName: R3
+ SysDescr:
+ MgmtIP: 192.0.2.17
+ MgmtIP: 2001:db8::cafe:17
+ Capability: Bridge, off
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Tel, on
+ Capability: Station, off
+ Port:
+ PortID: mac 50:54:30:01:78:dd
+ PortDescr: iface2
+ Port is aggregated. PortAggregID: 6
+ VLAN: 453 bond0.453
+ LLDP-MED:
+ Device Type: Communication Device Endpoint (Class III)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail ports iface3.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface3, via: LLDP, RID: 1, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:b3:3c:2c:36
+ SysName: R2
+ SysDescr:
+ MgmtIP: 192.0.2.16
+ MgmtIP: 2001:db8::cafe:16
+ Capability: Bridge, on
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Station, off
+ Port:
+ PortID: mac 50:54:5e:ed:e2:df
+ PortDescr: iface3
+ LLDP-MED:
+ Device Type: Media Endpoint (Class II)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail ports iface2.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface2, via: LLDP, RID: 1, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:b3:3c:2c:36
+ SysName: R2
+ SysDescr:
+ MgmtIP: 192.0.2.16
+ MgmtIP: 2001:db8::cafe:16
+ Capability: Bridge, on
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Station, off
+ Port:
+ PortID: mac 50:54:0e:ec:6e:77
+ PortDescr: iface2
+ MDI Power: supported: yes, enabled: yes, pair control: yes
+ Device type: PSE
+ Power pairs: spare
+ Class: class 3
+ VLAN: 450 iface2.450
+ VLAN: 452 iface2.452
+ LLDP-MED:
+ Device Type: Media Endpoint (Class II)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ LLDP-MED Location Identification: Type: Coordinates, Geoid: WGS84
+ Latitude: 48.58666N
+ Longitude: 2.2013E
+ Altitude: m 117.46
+ LLDP-MED Location Identification: Type: ELIN
+ ECS ELIN: 911
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+ UnknownTLVs:
+ TLV: OUI: 33,44,55, SubType: 44, Len: 5 45,45,45,45,45
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
+[∗] Execute command libtool execute src/client/lldpcli show neighbor detail ports iface2.
+-------------------------------------------------------------------------------
+LLDP neighbors:
+-------------------------------------------------------------------------------
+Interface: iface2, via: LLDP, RID: 1, Time: 0 day
+ Chassis:
+ ChassisID: mac 50:54:b3:3c:2c:36
+ SysName: R2
+ SysDescr:
+ MgmtIP: 192.0.2.16
+ MgmtIP: 2001:db8::cafe:16
+ Capability: Bridge, on
+ Capability: Router, off
+ Capability: Wlan, off
+ Capability: Station, off
+ Port:
+ PortID: mac 50:54:0e:ec:6e:77
+ PortDescr: iface2
+ MDI Power: supported: yes, enabled: yes, pair control: yes
+ Device type: PSE
+ Power pairs: spare
+ Class: class 3
+ VLAN: 450 iface2.450
+ VLAN: 452 iface2.452
+ LLDP-MED:
+ Device Type: Media Endpoint (Class II)
+ Capability: Capabilities
+ Capability: Policy
+ Capability: Location
+ Capability: MDI/PSE
+ Capability: MDI/PD
+ Capability: Inventory
+ LLDP-MED Location Identification: Type: Coordinates, Geoid: WGS84
+ Latitude: 48.58666N
+ Longitude: 2.2013E
+ Altitude: m 117.46
+ LLDP-MED Location Identification: Type: ELIN
+ ECS ELIN: 911
+ Inventory:
+ Hardware Revision: pc-i440fx
+ Software Revision:
+ Firmware Revision:
+ Manufacturer: QEMU
+ Model: Standard PC (i440FX + PIIX, 1996
+ UnknownTLVs:
+ TLV: OUI: 33,44,55, SubType: 44, Len: 5 45,45,45,45,45
+-------------------------------------------------------------------------------
+[∗] End of command: 0.
--- /dev/null
+#!/bin/sh
+
+# Integration tests for lldpd. Those tests only run on Linux. They
+# spawn several VM and connect them together, then check lldpcli
+# results to see if everything is in order.
+
+# lldpd should be configure with:
+# ../configure --localstatedir=/var --sysconfdir=/etc --prefix=/usr CFLAGS="-O0 -g"
+
+LABNAME=lldpd
+
+set -e
+
+log_begin_msg () {
+ echo "[…] $1... "
+}
+log_ok_msg () {
+ echo "[✔] $1."
+}
+log_warn_msg () {
+ echo "[⚡] $1!"
+}
+log_error_msg () {
+ echo "[✘] $1!"
+ exit 1
+}
+log_info_msg () {
+ echo "[∗] $1."
+}
+
+check_kernel() {
+ log_begin_msg "Checking kernel version"
+ [ -f "$KERNEL" ] || log_error_msg "Unable to find kernel $KERNEL"
+ [ -r "$KERNEL" ] || log_error_msg "Kernel $KERNEL is not readable.\n Try \`setfacl -m u:$USER:r $KERNEL'"
+
+ # A recent version of `file` is able to extract the
+ # information. Since it is not widely available, let use some hack
+ # method.
+ VERSION=$(cat <<EOF |
+cat
+gunzip \\\037\\\213\\\010 xy
+unxz \\\3757zXZ\\\000 abcde
+bunzip2 BZh xy
+unlzma \\\135\\\0\\\0\\\0 xxx
+EOF
+ while read cmd sig1 sig2; do
+ case $sig1,$sig2 in
+ ,) poss="0:_" ;;
+ *) poss=$(tr "${sig1}\n${sig2}" "\n${sig2}=" < "$KERNEL" | grep -abo "^${sig2}" || true) ;;
+ esac
+ [ -n "$poss" ] || continue
+ for pos in $poss; do
+ pos=${pos%%:*}
+ tail -c+$pos "$KERNEL" | $cmd 2> /dev/null | strings -20 | \
+ grep ^Linux.version | head -1
+ done
+ done | head -1)
+
+ [ -n "$VERSION" ] || log_error_msg "Unable to determine version for $KERNEL"
+ VERSION="${VERSION#Linux version }"
+ VERSION="${VERSION%% *}"
+ log_ok_msg "Found kernel $VERSION"
+
+ log_begin_msg "Check kernel configuration"
+ CONFIG="$(dirname $KERNEL)/config-$VERSION"
+ [ -f "$CONFIG" ] || log_error_msg "Unable to find configuration file $CONFIG"
+ cat <<EOF | while read el; do
+9P_FS=[ym]
+NET_9P=[ym]
+NET_9P_VIRTIO=[ym]
+VIRTIO=[ym]
+VIRTIO_PCI=[ym]
+SERIAL_8250=y
+SERIAL_8250_CONSOLE=y
+TMPFS=y
+BLK_DEV_INITRD=y
+DEVTMPFS=[ym]
+EOF
+ grep -qx "CONFIG_$el" $CONFIG || log_error_msg "Kernel not configured with CONFIG_$el"
+ done
+
+ log_begin_msg "Search for modules"
+ for dir in "$(dirname $KERNEL)/lib/modules/$VERSION" "/lib/modules/$VERSION"; do
+ [ -d $dir ] || continue
+ MODULES="$dir"
+ break
+ done
+ if [ -z "$MODULES" ]; then
+ log_warn_msg "Unable to find module directory"
+ else
+ log_ok_msg "Modules are in $MODULES"
+ fi
+}
+
+check_dependencies() {
+ log_begin_msg "Checking if dependencies are present"
+ for exec in \
+ busybox \
+ qemu-system-x86_64 \
+ tmux vde_switch \
+ start-stop-daemon \
+ $DEPS; do
+ which $exec 2> /dev/null > /dev/null || log_error_msg "$exec is not installed"
+ done
+ log_ok_msg "All dependencies are met"
+}
+
+setup_tmp () {
+ TMP=$(mktemp -d)
+ trap "ret=$? ; cleanup" EXIT
+ log_info_msg "TMP is $TMP"
+}
+
+# Run our lab in tmux
+setup_screen() {
+ if [ -z "$TMUX" ] || [ x"$(tmux list-panes -F '#{session_name}')" != x"$LABNAME" ]; then
+ unset TMUX
+ exec tmux new-session -s "$LABNAME" -n main \
+ "env ROOT=$ROOT VERSION=$VERSION LINUX=$LINUX $PROGNAME $PROGARGS || read"
+ fi
+ sleep 1
+ tmux set-option -q prefix C-b
+ tmux set-option -q set-remain-on-exit on
+ tmux bind-key r respawn-window
+}
+
+# Setup a VDE switch
+setup_switch() {
+ nb=$1 ; shift
+ log_begin_msg "Setup switch $nb"
+ cat <<EOF > "$TMP/switch-$nb.conf"
+plugin/add /usr/lib/vde2/plugins/pdump.so
+pdump/filename $TMP/switch-$nb.pcap
+pdump/buffered 0
+pdump/active 1
+EOF
+ start-stop-daemon -b --no-close --make-pidfile --pidfile "$TMP/switch-$nb.pid" \
+ --start --startas $(which vde_switch) -- \
+ --sock "$TMP/switch-$nb.sock" --mgmt "$TMP/switch-management-$nb.sock" \
+ --rcfile "$TMP/switch-$nb.conf" --hub
+ # Management socket can be used with:
+ # socat - UNIX-CONNECT:"$TMP/switch-management-$nb.sock"
+ log_ok_msg "Switch $nb started"
+}
+
+setup_initrd () {
+ log_begin_msg "Build initrd"
+ DESTDIR=$TMP/initrd
+ mkdir -p $DESTDIR
+
+ # Copy busybox and eventually insmod
+ bins="busybox"
+ busybox --list | grep -qFx insmod || bins="$bins insmod"
+ for bin in $bins; do
+ install -D "$(which $bin)" ${DESTDIR}/bin/$bin
+ for x in $(ldd "$(which $bin)" 2> /dev/null | sed -e '
+ /\//!d;
+ /linux-gate/d;
+ /=>/ {s/.*=>[[:blank:]]*\([^[:blank:]]*\).*/\1/};
+ s/[[:blank:]]*\([^[:blank:]]*\) (.*)/\1/' 2>/dev/null); do
+ [ -f "${DESTDIR}/$x" ] || install -D "$x" "${DESTDIR}/$x"
+ done
+ done
+
+ # Configure busybox
+ for applet in $(${DESTDIR}/bin/busybox --list); do
+ ln -s busybox ${DESTDIR}/bin/${applet}
+ done
+
+ # Add modules
+ [ -z "$MODULES" ] || {
+ modules="9pnet_virtio 9p virtio_pci $UNION"
+ for mod in $modules; do
+ modprobe --all --set-version="${VERSION}" -d ${MODULES}/../../.. \
+ --ignore-install --quiet --show-depends $mod > /dev/null || {
+ log_warn_msg "Unable to find module $mod"
+ log_begin_msg "Continue building initrd"
+ }
+ modprobe --all --set-version="${VERSION}" -d ${MODULES}/../../.. \
+ --ignore-install --quiet --show-depends $mod |
+ while read prefix kmod options ; do
+ [ "${prefix}" = "insmod" ] || continue
+ grep -qFw "$kmod" ${DESTDIR}/modules 2> /dev/null || {
+ install -D "$kmod" "${DESTDIR}/${kmod}"
+ echo $prefix $kmod $options >> ${DESTDIR}/modules
+ }
+ done
+ done
+ }
+
+ # Copy this program
+ cp "$PROGNAME" ${DESTDIR}/init
+
+ # Create /tmp
+ mkdir ${DESTDIR}/tmp
+
+ # Build initrd
+ (cd "${DESTDIR}" && find . | cpio --quiet -R 0:0 -o -H newc | gzip > $TMP/initrd.gz)
+
+ log_ok_msg "initrd built in $TMP/initrd.gz"
+}
+
+random_mac () {
+ # But, not random in fact
+ name=$1
+ net=$2
+ mac=$(echo $name-$net | sha1sum | \
+ awk '{print "50:54:" substr($1,0,2) ":" substr($1, 2, 2) ":" substr($1, 4, 2) ":" substr($1, 6, 2)}')
+ echo $mac
+}
+
+start_vm () {
+ name=$1
+ shift
+
+ netargs=""
+ saveifs="$IFS"
+ IFS=,
+ for net in $NET; do
+ mac=$(random_mac $name $net)
+ netargs="$netargs -net nic,model=virtio,macaddr=$mac,vlan=$net"
+ netargs="$netargs -net vde,sock=$TMP/switch-$net.sock,vlan=$net"
+ done
+ IFS="$saveifs"
+
+ log_info_msg "Start VM $name"
+ # /root is mounted with version 9p2000.u to allow access to /dev,
+ # /sys and to mount new partitions over them. This is not the case
+ # for 9p2000.L.
+ cat <<EOF > "$TMP/vm-$name.exec"
+#!/bin/sh
+ echo
+ exec start-stop-daemon --make-pidfile --pidfile "$TMP/vm-$name.pid" \
+ --start --startas $(which qemu-system-x86_64) -- \
+ -enable-kvm \
+ -nodefconfig -nodefaults \
+ -display none \
+ -m ${MEM:-128M} \
+ \
+ -chardev stdio,id=charserial0,signal=off \
+ -device isa-serial,chardev=charserial0,id=serial0 \
+ -chardev socket,id=charserial1,path=$TMP/vm-$name-serial.pipe,server,nowait \
+ -device isa-serial,chardev=charserial1,id=serial1 \
+ \
+ -chardev socket,id=con0,path=$TMP/vm-$name-console.pipe,server,nowait \
+ -mon chardev=con0,mode=readline,default \
+ \
+ -fsdev local,security_model=passthrough,id=fsdev-root,path=${ROOT} \
+ -device virtio-9p-pci,id=fs-root,fsdev=fsdev-root,mount_tag=rootshare \
+ -fsdev local,security_model=none,id=fsdev-lab,path=${PWD} \
+ -device virtio-9p-pci,id=fs-lab,fsdev=fsdev-lab,mount_tag=labshare \
+ -fsdev local,security_model=none,id=fsdev-tmp,path=${TMP} \
+ -device virtio-9p-pci,id=fs-tmp,fsdev=fsdev-tmp,mount_tag=tmpshare \
+ -fsdev local,security_model=none,id=fsdev-modules,path=${MODULES}/..,readonly \
+ -device virtio-9p-pci,id=fs-modules,fsdev=fsdev-modules,mount_tag=moduleshare \
+ \
+ -gdb unix:$TMP/vm-$name-gdb.pipe,server,nowait \
+ -kernel $KERNEL \
+ -no-reboot \
+ -initrd $TMP/initrd.gz \
+ -append "uts=$name console=ttyS0 panic=1 TERM=$TERM quiet" \
+ $netargs \
+ $@
+EOF
+ log_info_msg "GDB server listening on $TMP/vm-$name-gdb.pipe"
+ log_info_msg "monitor listening on $TMP/vm-$name-console.pipe"
+ log_info_msg "ttyS1 listening on $TMP/vm-$name-serial.pipe"
+ chmod +x "$TMP/vm-$name.exec"
+ tmux new-window -n $name "$TMP/vm-$name.exec"
+ tmux select-window -t ":^"
+}
+
+display_help() {
+ cat <<EOF
+
+Some tmux commands (assuming default keybindings) :
+ C-b d - Detach the lab (resume with "tmux attach -t $LABNAME")
+ C-b w - Select a window
+ C-b n - Next window
+ C-b p - Previous window
+ C-b l - Last window
+ C-b ? - Get help
+
+EOF
+}
+
+run() {
+ r=$1
+ shift
+ log_info_msg "$r: execute $*"
+ printf "%s\n" "$*" > $TMP/${r}.command
+ n=0
+ while [ -f $TMP/${r}.command ]; do
+ sleep 1
+ n=$((n + 1))
+ [ $n -le 15 ] || {
+ log_error_msg "Timeout while executing command on $r"
+ }
+ done
+}
+
+process_commands() {
+ cd /mnt/lab
+ log_info_msg "Waiting for commands"
+ cmd=/tmp/lab/${uts}.command
+ set +e
+ while true; do
+ while [ ! -f $cmd ]; do
+ sleep 1
+ done
+ log_info_msg "Execute command $(head -1 $cmd)"
+ sh $cmd
+ log_info_msg "End of command: $?"
+ rm $cmd
+ done
+}
+
+start_tests() {
+ # Start lldpd on each VM
+ run R1 libtool execute src/daemon/lldpd -M 1 -L \$PWD/src/client/lldpcli
+ run R2 libtool execute src/daemon/lldpd -M 2 -L \$PWD/src/client/lldpcli
+ run R3 libtool execute src/daemon/lldpd -M 3 -L \$PWD/src/client/lldpcli
+ sleep 2
+ # Query neighbors
+ run R1 libtool execute src/client/lldpcli show neighbor detail
+ run R2 libtool execute src/client/lldpcli show neighbor detail
+ run R3 libtool execute src/client/lldpcli show neighbor detail
+ # Add some VLAN
+ run R2 ip link add link iface2 name iface2.450 type vlan id 450
+ run R2 ip link set up dev iface2.450
+ run R2 ip link add link iface2 name iface2.451 type vlan id 451
+ run R2 ip link set up dev iface2.451
+ run R2 ip link add link iface2 name iface2.452 type vlan id 452
+ run R2 ip link set up dev iface2.452
+ sleep 2
+ run R1 libtool execute src/client/lldpcli show neighbor detail ports iface2
+ # Remove one
+ run R2 ip link del iface2.451
+ sleep 2
+ run R1 libtool execute src/client/lldpcli show neighbor detail ports iface2
+ # Add a bond
+ run R3 ip link set down dev iface2
+ run R3 ip link set down dev iface3
+ run R3 ip link set iface2 master bond0
+ run R3 ip link set iface3 master bond0
+ run R3 ip link set up dev bond0
+ sleep 2
+ run R1 libtool execute src/client/lldpcli show neighbor detail ports iface4
+ run R1 libtool execute src/client/lldpcli show neighbor detail ports iface5
+ # Add a VLAN on top of bond
+ run R3 ip link add link bond0 name bond0.453 type vlan id 453
+ run R3 ip link set up dev bond0.453
+ sleep 2
+ run R1 libtool execute src/client/lldpcli show neighbor detail ports iface4
+ # Add a bridge
+ run R2 brctl addbr br0
+ run R2 brctl addif br0 iface3
+ run R2 ip link set up dev br0
+ sleep 2
+ run R1 libtool execute src/client/lldpcli show neighbor detail ports iface3
+ # Modify some TLV
+ conf="libtool execute src/client/lldpcli configure ports iface2"
+ run R2 $conf lldp custom-tlv oui 33,44,55 subtype 44 oui-info 45,45,45,45,45
+ run R2 $conf med location elin 911
+ run R2 $conf med location coordinate latitude 48.58667N longitude 2.2014E altitude 117.47 m datum WGS84
+ run R2 $conf med power pd source pse priority high value 5000
+ run R2 $conf dot3 power pse supported enabled paircontrol powerpairs spare class class-3
+ sleep 2
+ run R1 libtool execute src/client/lldpcli show neighbor detail ports iface2
+ # Configuration should stay when port go down and up
+ run R2 ip link set down dev iface2
+ sleep 2
+ run R2 ip link set up dev iface2
+ sleep 5
+ run R1 libtool execute src/client/lldpcli show neighbor detail ports iface2
+}
+
+cleanup() {
+ set +e
+ for pid in $TMP/*.pid; do
+ kill -15 -$(cat $pid) 2> /dev/null || true
+ done
+ sleep 1
+ for pid in $TMP/*.pid; do
+ kill -9 -$(cat $pid) 2> /dev/null || true
+ done
+ rm -rf $TMP
+ tmux kill-session -t $LABNAME
+}
+
+# FSM
+export STATE=${STATE:-BEGIN}
+case $$,$STATE in
+ 1,BEGIN)
+ # In initrd
+ log_info_msg "initrd started"
+ hostname ${uts}
+ export PATH=/usr/local/bin:/usr/bin:/bin:/sbin:/usr/local/sbin:/usr/sbin
+ export HOME=/root
+
+ [ ! -f /modules ] || {
+ log_info_msg "Loading modules"
+ . /modules
+ }
+
+ log_begin_msg "Setup root file system"
+ mount -n -t tmpfs tmpfs /tmp -o rw
+ mkdir /tmp/target
+ mkdir /tmp/target/ro
+ mkdir /tmp/target/overlay
+ mount -n -t 9p rootshare /tmp/target/overlay -o trans=virtio,version=9p2000.u,ro
+ mount -n -t proc proc /tmp/target/overlay/proc
+ mount -n -t sysfs sys /tmp/target/overlay/sys
+ log_ok_msg "Root file system setup"
+
+ log_begin_msg "Clean /tmp and /run"
+ for fs in /run /var/run /var/tmp /var/log /tmp /mnt; do
+ if [ -d /tmp/target/overlay$fs ] && [ ! -h /tmp/target/overlay$fs ]; then
+ mount -t tmpfs tmpfs /tmp/target/overlay$fs -o rw,nosuid,nodev
+ fi
+ done
+ log_ok_msg "/tmp, /run and others are clean"
+
+ log_begin_msg "Mount /lib/modules"
+ mount -t 9p moduleshare /tmp/target/overlay/lib/modules -o trans=virtio,version=9p2000.L,access=0,ro || \
+ log_error_msg "Unable to mount /lib/modules"
+ log_ok_msg "/root and /lib/modules mounted"
+
+ log_begin_msg "Mount /mnt/lab"
+ mkdir /tmp/target/overlay/mnt/lab
+ mount -t 9p labshare /tmp/target/overlay/mnt/lab -o trans=virtio,version=9p2000.L,access=any,rw || \
+ log_error_msg "Unable to mount /mnt/lab"
+ log_ok_msg "/mnt/lab mounted"
+
+ log_begin_msg "Mount /tmp/lab"
+ mkdir /tmp/target/overlay/tmp/lab
+ mount -t 9p tmpshare /tmp/target/overlay/tmp/lab -o trans=virtio,version=9p2000.L,access=any,rw || \
+ log_error_msg "Unable to mount /tmp/lab"
+ log_ok_msg "/tmp/lab mounted"
+
+ log_info_msg "Change root"
+ export STATE=CHROOTED
+ exec chroot /tmp/target/overlay /mnt/lab/integration-tests
+ ;;
+
+ 1,CHROOTED)
+ log_begin_msg "Starting udev"
+ udev_log=err
+ mount -n -o size=10M,mode=0755 -t devtmpfs devtmpfs /dev
+ udevadm info --cleanup-db
+ for udev in /lib/systemd/systemd-udevd /usr/lib/systemd/systemd-udevd $(command -v udevd 2> /dev/null); do
+ [ ! -x $udev ] || break
+ done
+ $udev --daemon
+ udevadm trigger --action=add
+ udevadm settle
+ log_ok_msg "udev started"
+
+ log_info_msg "Setup interfaces"
+ modprobe dummy 2>/dev/null || true
+ modprobe bonding 2>/dev/null || true
+ sleep 0.5 # Some interfaces may take some time to appear
+ # Rename all interfaces to "predictable" and "non-colliding"
+ # name. We don't have if we have eth* or ens* interfaces. Let
+ # take a totally different naming convention.
+ nb=1
+ for iface in $(echo /sys/bus/virtio/drivers/virtio_net/*/net/*); do
+ ip link set name iface$nb dev ${iface##*/}
+ nb=$((nb + 1))
+ done
+ for intf in /sys/class/net/*; do
+ intf=$(basename $intf)
+ ip a l dev $intf 2> /dev/null >/dev/null || continue
+ ip link set up dev $intf
+ done
+
+ log_info_msg "Setup IP addresses"
+ case $uts in
+ R1)
+ ip -4 addr add 192.0.2.15/24 dev iface1
+ ip -6 addr add 2001:db8::cafe:15/64 dev iface1
+ ;;
+ R2)
+ ip -4 addr add 192.0.2.16/24 dev iface1
+ ip -6 addr add 2001:db8::cafe:16/64 dev iface1
+ ;;
+ R3)
+ ip -4 addr add 192.0.2.17/24 dev iface1
+ ip -6 addr add 2001:db8::cafe:17/64 dev iface1
+ ;;
+ esac
+ process_commands 2>&1 | tee /mnt/lab/${uts}.output
+ ;;
+
+ *,BEGIN)
+ # Initial state
+ [ $(id -u) != 0 ] || {
+ log_error_msg "You should not run this as root"
+ exit 1
+ }
+ PROGNAME="$(readlink -f "$0")"
+ PROGARGS="$@"
+ ROOT="$(readlink -f "${ROOT:-/}")" # Root filesystem
+ KERNEL="$(readlink -f "${1:-/boot/vmlinuz-$(uname -r)}")" # Kernel
+ PATH="$PATH":/usr/local/sbin:/usr/sbin:/sbin
+ [ $# -lt 1 ] || shift
+
+ check_kernel
+ check_dependencies
+ setup_screen
+ setup_tmp
+ setup_initrd
+
+ setup_switch 1
+ setup_switch 2
+ setup_switch 3
+ setup_switch 4
+ setup_switch 5
+ sleep 0.3
+
+ NET=1,2,3,4,5 start_vm R1
+ NET=1,2,3 start_vm R2
+ NET=1,4,5 start_vm R3
+
+ display_help
+ start_tests
+
+ sed \
+ -e 's/^\(Interface:.*, Time: 0 day\).*/\1/' \
+ -e 's/^\( SysDescr:\).*/\1/' \
+ -e 's/^\( Hardware Revision: pc-i440fx\).*/\1/' \
+ -e 's/^\( Software Revision: \).*/\1/' \
+ -e 's/^\( Firmware Revision: \).*/\1/' \
+ R1.output > R1.output.redacted
+ diff -u ../tests/R1.expected R1.output.redacted || \
+ log_warn_msg "Unexpected differences"
+
+ log_info_msg "End of tests, press enter to exit."
+ read a
+ ;;
+esac
+
+# Local Variables:
+# mode: sh
+# indent-tabs-mode: nil
+# sh-basic-offset: 4
+# End: