From 31e7d6b12988494c0b512c925a80757368389c8d Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Wed, 17 Jun 2015 10:50:08 -0700 Subject: [PATCH] rebased to upstream v1.0.1-23-g986eb2e --- lldpad-0.9.46-123-g48a5f38.patch | 45882 ---------------- lldpad.spec | 38 +- ...22_cmds-retrieve-vsi-paramenter-data.patch | 106 + ...port-for-OUI-infrastructure-in-vdp22.patch | 172 + ...Cisco-specific-OUI-extensions-to-VDP.patch | 650 + ...k-timeout-handler-to-set-the-right-t.patch | 33 + ...VDP-Changes-in-OUI-infra-for-get-tlv.patch | 333 + ...isco-OUI-handlers-to-support-get-tlv.patch | 283 + ...VDP-Add-vdptool-man-page-to-Makefile.patch | 27 + ...int-compile-errors-in-32-bit-systems.patch | 45 + ...dp-automake-fixes-for-dist-distcheck.patch | 130 + ...led-test-tool-building-for-distcheck.patch | 26 + open-lldp-v1.0.1-19-nltest-build-error.patch | 40 + ...p-v1.0.1-2-VDP-vdptool-first-version.patch | 1671 + ...ake-fix-drop-prefix-on-vdptool_LDADD.patch | 34 + ...ix-DCBX-event-generation-from-lldpad.patch | 141 + ...mory-leak-for-modify-VSI-support-for.patch | 223 + ....1-23-lldp-make-TTL-TLV-configurable.patch | 312 + open-lldp-v1.0.1-24-fix-build-warnings.patch | 59 + ...-cases-Some-test-cases-to-test-the-n.patch | 2722 + ...ake-the-interface-to-VDP22-in-lldpad.patch | 593 + ...ort-for-get-tlv-in-vdptool-and-VDP22.patch | 1194 + ...DP22-for-correct-error-code-status-t.patch | 894 + ...port-for-OUI-infrastructure-in-VDP22.patch | 158 + ...rt-for-OUI-infrastructure-in-vdptool.patch | 355 + ...port-for-OUI-infrastructure-in-vdp22.patch | 524 + sources | 2 +- 27 files changed, 10758 insertions(+), 45889 deletions(-) delete mode 100644 lldpad-0.9.46-123-g48a5f38.patch create mode 100644 open-lldp-v1.0.1-1-VDP-vdp22_cmds-retrieve-vsi-paramenter-data.patch create mode 100644 open-lldp-v1.0.1-10-VDP-Support-for-OUI-infrastructure-in-vdp22.patch create mode 100644 open-lldp-v1.0.1-11-VDP-Support-for-Cisco-specific-OUI-extensions-to-VDP.patch create mode 100644 open-lldp-v1.0.1-12-VDP22-Fix-the-ack-timeout-handler-to-set-the-right-t.patch create mode 100644 open-lldp-v1.0.1-13-VDP-Changes-in-OUI-infra-for-get-tlv.patch create mode 100644 open-lldp-v1.0.1-14-VDP-Changes-in-Cisco-OUI-handlers-to-support-get-tlv.patch create mode 100644 open-lldp-v1.0.1-15-VDP-Add-vdptool-man-page-to-Makefile.patch create mode 100644 open-lldp-v1.0.1-16-VDP-Fixed-DBG-print-compile-errors-in-32-bit-systems.patch create mode 100644 open-lldp-v1.0.1-17-lldp-automake-fixes-for-dist-distcheck.patch create mode 100644 open-lldp-v1.0.1-18-enabled-test-tool-building-for-distcheck.patch create mode 100644 open-lldp-v1.0.1-19-nltest-build-error.patch create mode 100644 open-lldp-v1.0.1-2-VDP-vdptool-first-version.patch create mode 100644 open-lldp-v1.0.1-20-lldp-automake-fix-drop-prefix-on-vdptool_LDADD.patch create mode 100644 open-lldp-v1.0.1-21-lldpad-Fix-DCBX-event-generation-from-lldpad.patch create mode 100644 open-lldp-v1.0.1-22-vdp-Fixed-the-memory-leak-for-modify-VSI-support-for.patch create mode 100644 open-lldp-v1.0.1-23-lldp-make-TTL-TLV-configurable.patch create mode 100644 open-lldp-v1.0.1-24-fix-build-warnings.patch create mode 100644 open-lldp-v1.0.1-3-VDP-vdptool-test-cases-Some-test-cases-to-test-the-n.patch create mode 100644 open-lldp-v1.0.1-4-VDP-Changes-to-make-the-interface-to-VDP22-in-lldpad.patch create mode 100644 open-lldp-v1.0.1-5-VDP-Support-for-get-tlv-in-vdptool-and-VDP22.patch create mode 100644 open-lldp-v1.0.1-6-VDP-Support-in-VDP22-for-correct-error-code-status-t.patch create mode 100644 open-lldp-v1.0.1-7-VDP-Support-for-OUI-infrastructure-in-VDP22.patch create mode 100644 open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch create mode 100644 open-lldp-v1.0.1-9-VDP-Support-for-OUI-infrastructure-in-vdp22.patch diff --git a/lldpad-0.9.46-123-g48a5f38.patch b/lldpad-0.9.46-123-g48a5f38.patch deleted file mode 100644 index c2d8fdd..0000000 --- a/lldpad-0.9.46-123-g48a5f38.patch +++ /dev/null @@ -1,45882 +0,0 @@ -v0.9.46-123-g48a5f38 ---- -48a5f38 Move to libnl3 -fa42d01 lldpad: print verbose error messages -cb1ae28 lldpad: do not use absolute pathname for sys/queue.h -d3706f0 Interop issues with Juniper QFX3500 switch & firmware managed dcbx -8f78907 clif.c use correct include file -d36de79 vdp22_cmds scan vdp22 module for configuration -4ace840 liblldp_clif docuementation update clif_vsi and clif_vsiwait -844ddd9 clif and vdp22_clif_cmd send correct tlvid -1c52e87 vdp22 client command interface definition -990044c vdp22 add missing information for client -9064813 vdp22 bridge mode simulation fix for commit 61b69da -272c4f4 veth-setup.sh create veth0 with fixed mac address -c5cf1d3 crtl_iface remove trailing blanks and newlines -3b8cb17 gitignore add new files -ce66e20 Disambiguate TX/RX sum error messages -b8f7583 Add missing newlines in dcb_protocol.c log messages -4f6e8cb Add missing newlines in dcb_rule_chk.c log messages -61b69da ecp22 : Do not send end tlv. -3ef96bc lldp: Fix some spelling errors -8f877b3 Fixed automake error -da964f8 vdp22 test remove obsolete file -522ae1b evb/evb22 test cases -abe2bc7 evb/evb22 make sure one protocol only -ed02ef9 vdp22: Restore vsi profile after link down/up event -5cf5850 Fix the build with recent autotools -9b71e95 vdp22 add test suite -745b8f2 vdp22 bridge mode error simulation fix -9cfda55 vdp handle dis-assoc comand without profile -3bc8b0d evb22 test case 26 -66f229b lldpad: Fixes for the flag values in VDP responses -c8f94ee vdp22 check for evb22.enabletx value -22af9bc trivial: upper-case some enum values -04c7179 vethsetup shell script for qbg22 testing -cc573cf evb22 add test case 25 -ca36254 qbg22sim fix typo in comment -808a677 ecp22 protocol test suite -f997f75 evb22 protocol test suite -95b45b2 qbg22sim fix ecp22 ethertype value -3fc974d liblldp_clif add documentation for new functions -6ea9f8a vdp22 reduce delay before executing vdp22 -727eafa lldpad: fix ECP 2.2 ethertype and allow VDP to support VEB mode -9294969 lldptool update for EVB22 -bc3ebd8 vdptest use liblldp_clif library for vdp22 test cases -f676ad2 clif support for sending vdp22 commands to lldpad -9ae3138 clif add clif_pending_wait function -e7e80bc vdp22 call back to client support -2827f1a vdp22 support for command messages from attached client -f32d041 vdp22 add support for command line interface -155576c vdp22 add vdp22_info function -87cd148 vdp22 set vlanid to include qos -81b43e5 vdp22 define protocol subtype -87cfde3 evb22 fix define values -f5cd6eb crtl_iface minor fixes -bf92b65 lldp_rtnl remove mynla_xxx functions -ee8b4d2 vdpnl remove mynla_xxx functions -796ec98 vdpnl rename vsiid_fmt to vsi_idfmt -4d44957 lldpad: stop dcbx from overwriting adminstatus -354fd12 vdp22 support variable number of VLAN/QoS returns -a3e642c vdp22 make function vdp22_local2str static -5d6b8f3 COPYING: Update FSF address -82bc127 dcbnl.h: Update FSF address -027931b Do not install systemd files as executable -cd7f197 lldpad: do not set rx state from TX initialization -09f7b9f vdptest: add additional notes to man page -106f9c0 vdpnl: initialize vdpnl_mac to prevent segfault -bbd83e0 vdp22-bridge support for error generation -2bddc48 vdpnl add support for new netlink message format -2534205 vdp22 add support for KEEP bit and KEEP state transition -346a427 vdp22 remove default error status on VSI end -c070198 vdp22 returned changed filter information from switch -326fcd2 vdp22 remove pcp and ps from structure definition -1c96e28 vdp22 support tracing for manager id -3c9f390 vdp set size of filter data list to zero -e9d8430 rtnl netlink message construction support -e026e9f liblldp_clif function clif_getpid fix wrong buffer length -c901b23 vdpnl regression support of multiple VSIs broken -6efa72c vdptest add support for IEEE 802.1 Qbg ratified standard -4794c01 vdp22 introduce new header files for common defines -345492b lldp: lldptool evb example man page typo fix -b79bf42 vdp22 protocol support for bridge state machine -3c9f82a vdp22 include bridge resource allocation code -915a2f8 vdp22 add bridge resource allocation code -49a522f Fixup definition of dcbx_get_arg_handlers -180f5df lldpad: Option '-t' to omit timestamps in messages -c321645 lldp: Do not print 'l2_packet_receive - recvfrom' when network is down -bc0c53f lldpad: Fixup pid file handling -90c8224 lldpad: remove check_cfg_file() -d8a997f lldpad: systemd integration -88f02e8 nltest: use correct format for pfc messages -eeff6d4 vdp22 protocol support for station state machine -0f5f66f EVB and VDP are only supported on the nearest customer bridge agent. This patch adds code to fail set commands from lldptool gracefully with a string that users might understand. -1a3cb98 lldpad: refactor VDP cmd interpretor with vdp_cmdok -42f731c vdptest print wrong values in trace -091c203 qbg_utils increase buffer to store uuid -d1b9702 vdpnl add trace statement on filter information -c4da57d vdpnl pretty indentation -edbfec0 vdpnl determine filter information format from netlink msg -bc1a19c vdpnl remove blank after colon in trace -0762554 vdptest man page minor fixes -3c93fd7 lldpad: check for existence of device before allowing set -11cea1c lldptool: update bridge scope long form options -e4d564d lldptool: man page fixes for MED and DCBX TLVs -1beda0b ecp22 ecp22_data_from_evb function rename -7060df3 vdp22 get role from evb22 protocol -b4a1407 vdp22 add VSI format identifier -0313734 lldpad: correct IEEE DCBX capabilities check -8a44162 lldpad: do not require active TLVs to configure attributes -cc83dce vdptest fix and clearify documentation -66ebbb5 lldp: Simplify set_lldp_agent_admin() to fix RHEL 6.4 compiler error -76e794c lldpad: Avoid accessing removed port structure -67ca45d qbg22 rename header files lldp_qbg22 to qbg22 -5fcf657 qbg22 rename header files lldp_vdp22 -d544f05 qbg22 rename source files lldp_vdp22 -1017dbd qbg rename source and header files lldp_qbg_utils -7d4c77c qbg rename source and header files lldp_vdp -99ded5b lldp move files lldp_evb22*.c to parent directory -92bdc90 qbg rename source and header file lldp_ecp -859fab6 qbg22 rename source and header file lldp_ecp22 -5994fa7 vdp22 add timeout calcuation -60c35b7 vdp22 add more support for vdp22 protocol -201e6fe vdp22 add netlink support for filter format field -3375ff9 vdp22 add vsi22 profile data structure -c0fe8bc lldpad: Primarily identify netdevs by ifindex - -diff --git a/.gitignore b/.gitignore -index 9289e11..c2ac5d7 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -1,3 +1,5 @@ -+*/.dirstamp -+compile - parse_cli.c - *.o - *.lo -diff --git a/COPYING b/COPYING -index 5f297e5..87eef25 100644 ---- a/COPYING -+++ b/COPYING -@@ -8,7 +8,7 @@ GNU General Public License - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. --59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - Everyone is permitted to copy and distribute verbatim copies of this license - document, but changing it is not allowed. -diff --git a/Makefile.am b/Makefile.am -index 893fa45..4889d32 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -16,8 +16,8 @@ ACLOCAL_AMFLAGS = -I m4 - parse_cli.o: CFLAGS+=-U_FORTIFY_SOURCE -Wno-error - - ## system requires a shared libconfig --AM_CFLAGS = -Wall -Werror -Wextra -Wformat=2 $(LIBCONFIG_CFLAGS) --AM_LDFLAGS = $(LIBCONFIG_LIBS) -+AM_CFLAGS = -Wall -Werror -Wextra -Wformat=2 $(LIBCONFIG_CFLAGS) $(LIBNL_CFLAGS) -+AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS) - - ## header files to be installed, for programs using the client interface to lldpad - lldpad_includedir= ${includedir}/lldpad -@@ -27,7 +27,7 @@ include/clif.h include/lldp_dcbx_cmds.h \ - include/lldpad.h include/lldp_mand_cmds.h \ - include/clif_msgs.h include/lldp_basman_cmds.h include/lldp_8023_cmds.h \ - include/lldp_med_cmds.h include/lldp_util.h \ --include/lldp_evb_cmds.h include/lldp_vdp_cmds.h include/lldp_8021qaz_cmds.h \ -+include/lldp_evb_cmds.h include/qbg_vdp_cmds.h include/lldp_8021qaz_cmds.h \ - include/clif_sock.h include/linux/dcbnl.h \ - include/linux/netlink.h include/linux/rtnetlink.h \ - include/lldpad_status.h -@@ -40,7 +40,7 @@ include/lldpad_shm.h include/event_iface.h include/messages.h \ - include/parse_cli.h include/version.h include/lldptool_cli.h include/list.h \ - include/lldp_mand_clif.h include/lldp_basman_clif.h include/lldp_med_clif.h \ - include/lldp_8023_clif.h include/lldp_dcbx_clif.h include/lldp_evb_clif.h \ --include/lldp_evb22_clif.h include/lldp_vdp_clif.h include/lldp_vdpnl.h \ -+include/lldp_evb22_clif.h include/qbg_vdp_clif.h include/qbg_vdpnl.h \ - include/lldp_8021qaz_clif.h \ - include/lldp_orgspec_clif.h include/lldp_cisco_clif.h \ - include/lldptool.h include/lldp_rtnl.h include/dcbtool.h include/lldp_dcbx_cfg.h -@@ -56,19 +56,20 @@ lldp_dcbx.c include/lldp_dcbx.h tlv_dcbx.c include/tlv_dcbx.h \ - lldp_dcbx_cfg.c include/lldp_dcbx_cfg.h lldp_util.c \ - lldp_mand.c include/lldp_mand.h \ - lldp_mand_cmds.c lldp_basman_cmds.c lldp_8023_cmds.c lldp_med_cmds.c \ --lldp_evb_cmds.c lldp_evb.c include/lldp_evb.h lldp_vdp_cmds.c \ --include/lldp_vdp_cmds.h \ --include/lldp_ecp.h include/lldp_qbg_utils.h lldp_ecp.c lldp_qbg_utils.c \ --lldp_vdp.c include/lldp_vdp.h \ -+lldp_evb_cmds.c lldp_evb.c include/lldp_evb.h qbg/vdp_cmds.c \ -+include/qbg_vdp_cmds.h \ -+include/qbg_ecp.h include/qbg_utils.h qbg/ecp.c qbg_utils.c \ -+qbg/vdp.c include/qbg_vdp.h \ - lldp_tlv.c include/lldp_tlv.h \ - lldp_basman.c include/lldp_basman.h \ - lldp_med.c include/lldp_med.h \ - lldp_8023.c include/lldp_8023.h \ - lldp_8021qaz.c include/lldp_8021qaz.h \ - lldp_8021qaz_cmds.c include/lldp_8021qaz_cmds.h \ --include/lldp_evb22.h qbg/lldp_evb22.c qbg/lldp_evb22_cmds.c \ --include/lldp_qbg22.h include/lldp_ecp22.h qbg/lldp_ecp22.c \ --include/lldp_vdp22.h qbg/lldp_vdp22.c qbg/lldp_vdpnl.c -+include/lldp_evb22.h lldp_evb22.c lldp_evb22_cmds.c \ -+include/qbg22.h include/qbg_ecp22.h qbg/ecp22.c \ -+include/qbg_vdp22.h qbg/vdp22.c qbg/vdpnl.c qbg/vdp22sm.c qbg/vdp22br.c \ -+include/qbg_vdp22def.h qbg/vdp22_cmds.c qbg/vdp_ascii.c - - lib_LTLIBRARIES = liblldp_clif.la - liblldp_clif_la_LDFLAGS = -version-info 1:0:0 -@@ -83,11 +84,11 @@ dcbtool_LDFLAGS = -ldl -llldp_clif - lldptool_SOURCES = lldptool.c lldptool_cmds.c lldp_rtnl.c \ - lldp_mand_clif.c lldp_basman_clif.c lldp_med_clif.c \ - lldp_8023_clif.c lldp_dcbx_clif.c lldp_util.c \ -- lldp_8021qaz_clif.c lldp_evb_clif.c lldp_vdp_clif.c \ -- lldp_orgspec_clif.c lldp_cisco_clif.c qbg/lldp_evb22_clif.c \ -+ lldp_8021qaz_clif.c lldp_evb_clif.c qbg/vdp_clif.c \ -+ lldp_orgspec_clif.c lldp_cisco_clif.c lldp_evb22_clif.c \ - weak_readline.c $(lldpad_include_HEADERS) $(noinst_HEADERS) - lldptool_LDADD = ${srcdir}/liblldp_clif.la --lldptool_LDFLAGS = -ldl -llldp_clif -+lldptool_LDFLAGS = -ldl -llldp_clif $(LIBNL_LIBS) - - if BUILD_DEBUG - nltest_SOURCES = test/nltest.c test/nltest.h -@@ -120,25 +121,21 @@ pkgconfig_DATA = lldpad.pc liblldp_clif.pc - ## put a spec file and documentation in the distribution archive - dist_noinst_DATA = lldpad.spec README COPYING ChangeLog - --## lldpad.init is listed here because it gets installed from install-data-local --dist_noinst_SCRIPTS = lldpad.init -- - ## special hooks to handle the init script --install-data-local: lldpad.init -- $(MKDIR_P) $(DESTDIR)/etc/init.d -- $(INSTALL_SCRIPT) lldpad.init $(DESTDIR)/etc/init.d/lldpad -+install-data-local: lldpad.service lldpad.socket -+ $(MKDIR_P) $(DESTDIR)/usr/lib/systemd/system -+ $(INSTALL_DATA) lldpad.service $(DESTDIR)/usr/lib/systemd/system/lldpad.service -+ $(INSTALL_DATA) lldpad.socket $(DESTDIR)/usr/lib/systemd/system/lldpad.socket - - BASH_COMPLETION_DIR=/etc/bash_completion.d/ - - install-data-hook: -- /sbin/chkconfig --add lldpad || true - ## provide support for bash completion - $(MKDIR_P) $(DESTDIR)/$(BASH_COMPLETION_DIR) -- $(INSTALL_SCRIPT) ${srcdir}/contrib/bash_completion/* $(DESTDIR)/$(BASH_COMPLETION_DIR) -+ $(INSTALL_DATA) ${srcdir}/contrib/bash_completion/* $(DESTDIR)/$(BASH_COMPLETION_DIR) - - uninstall-local: -- /sbin/chkconfig --del lldpad || true -- rm -f '$(DESTDIR)/etc/init.d/lldpad' -+ rm -f '$(DESTDIR)/usr/lib/systemd/system/lldpad.*' - rm -f '$(includedir)/dcbd/clif_cmds.h' - rm -f '$(includedir)/dcbd' - -diff --git a/clif.c b/clif.c -index 2984e8e..cad6f75 100644 ---- a/clif.c -+++ b/clif.c -@@ -1,6 +1,6 @@ - /******************************************************************************* - -- LLDP Agent Daemon (LLDPAD) Software -+ LLDP Agent Daemon (LLDPAD) Software - Copyright(c) 2007-2010 Intel Corporation. - - Substantially modified from: -@@ -179,7 +179,7 @@ static int clif_attach_helper(struct clif *clif, char *tlvs_hex, int attach) - return -1; - sprintf(buf, "D"); - } -- -+ - ret = clif_request(clif, buf, strlen(buf), rbuf, &len, NULL); - free(buf); - if (ret < 0) -@@ -215,11 +215,11 @@ int clif_recv(struct clif *clif, char *reply, size_t *reply_len) - } - - --int clif_pending(struct clif *clif) -+int clif_pending_wait(struct clif *clif, int waittime) - { - struct timeval tv; - fd_set rfds; -- tv.tv_sec = 0; -+ tv.tv_sec = waittime; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_SET(clif->s, &rfds); -@@ -227,6 +227,10 @@ int clif_pending(struct clif *clif) - return FD_ISSET(clif->s, &rfds); - } - -+int clif_pending(struct clif *clif) -+{ -+ return clif_pending_wait(clif, 0); -+} - - int clif_get_fd(struct clif *clif) - { -@@ -240,7 +244,7 @@ pid_t clif_getpid(void) - { - struct clif *clif_conn; - char buf[MAX_CLIF_MSGBUF]; -- size_t len; -+ size_t len = sizeof(buf); - char *ppong; - int ret; - pid_t lldpad = 0; /* LLDPAD process identifier */ -@@ -275,3 +279,155 @@ out: - clif_close(clif_conn); - return lldpad; - } -+ -+/* -+ * Command line interface for vdp22 module. -+ * Includes for lldptool like access to lldpad -+ */ -+#include -+#include -+#include -+#include "include/qbg22.h" -+#include "include/qbg_vdp22_clif.h" /* Defines op_XXXX */ -+#include /* Needed by agent.h */ -+#include "lldp/agent.h" /* Nearest customer bridge define */ -+ -+/* -+ * Send a command via clif_xxx to lldpad. -+ * Return negavite numbers when a send/reply error occurs. -+ * Lldpad returns cmd_success for success and cmd_xxx for failure. -+ */ -+static int tool_send(struct clif *connp, char *cmd, size_t cmd_len, -+ char *reply, size_t *reply_len, int *lldpad_rc) -+{ -+ int rc; -+ -+ *lldpad_rc = 0; -+ rc = clif_request(connp, cmd, cmd_len, reply, reply_len, NULL); -+ if (!rc) { -+ if (1 != sscanf(reply, "R%02x", lldpad_rc)) -+ rc = -3; -+ } -+ return rc; -+} -+ -+/* -+ * Prepend the lldpad fan out information in front of the command. -+ * We use the vsi parameter. -+ */ -+static int hdr_set(char *ifname, char *s, size_t sz, unsigned int tlvid, -+ char *cmd, size_t cmd_len) -+{ -+ int rc; -+ -+ /* All command messages begin this way */ -+ rc = snprintf(s, sz, "%c%08x%c%1x%02x%08x%02zx%s%02x%08x03vsi%04zx%s", -+ MOD_CMD, LLDP_MOD_VDP22, CMD_REQUEST, CLIF_MSG_VERSION, -+ cmd_settlv, op_arg | op_argval | op_config, -+ strlen(ifname), ifname, NEAREST_CUSTOMER_BRIDGE, tlvid, -+ cmd_len, cmd); -+ return (rc < 0 || rc > (int)sz) ? -EFBIG : 0; -+} -+ -+/* -+ * Remove all whitespace and nonprintable characters from string. -+ */ -+static void kill_white(char *s) -+{ -+ char *cp = s; -+ -+ for (; *s != '\0'; ++s) { -+ if (isspace(*s)) -+ continue; -+ if (isprint(*s)) -+ *cp++ = *s; -+ } -+ *cp = '\0'; -+} -+ -+/* -+ * Send a VSI command to the vdp22 module and expect a reply. The reply can be -+ * an aknowledgement (error code 0) or an error code != 0 which means the -+ * command contained an error and was not accepted. -+ */ -+int clif_vsi(struct clif *connp, char *ifname, unsigned int tlvid, -+ char *cmd, char *reply, size_t *reply_len) -+{ -+ int rc, resp; -+ char cmd2[MAX_CLIF_MSGBUF]; -+ -+ kill_white(cmd); -+ rc = hdr_set(ifname, cmd2, sizeof(cmd2), tlvid, cmd, strlen(cmd)); -+ if (rc) -+ return rc; -+ rc = tool_send(connp, cmd2, strlen(cmd2), reply, reply_len, &resp); -+ if (!rc) -+ rc = resp; -+ return rc; -+} -+ -+/* -+ * Test if this is an event message from vdp22 module. -+ */ -+static bool test_evt(char *msg, size_t *msg_len) -+{ -+ bool is_evt = true; -+ unsigned int module; -+ -+ if (*msg_len < 12 || msg[MSG_TYPE] != MOD_CMD -+ || msg[MOD_MSG_TYPE] != EVENT_MSG -+ || sscanf(&msg[MSG_TYPE + 1], "%08x", &module) != 1 -+ || module != LLDP_MOD_VDP22) -+ is_evt = false; -+ return is_evt; -+} -+ -+/* -+ * Wait for an event message from lldpad module. After checking for the correct -+ * event message, the header of the event message is removed. -+ * -+ * Returns -+ * <0 on error or time out. -+ * =0 number of bytes on successful message reception (in reply_len parameter). -+ */ -+#define EVTHEADER 12 /* # of bytes in event message as hdr */ -+int clif_vsievt(struct clif *clif, char *reply, size_t *reply_len, int wait) -+{ -+ if (clif == NULL || wait < 0) -+ return -EINVAL; -+ if (clif_pending_wait(clif, wait)) { -+ if (clif_recv(clif, reply, reply_len) == 0) { -+ if (test_evt(reply, reply_len)) { -+ *reply_len -= EVTHEADER; -+ memmove(reply, reply + EVTHEADER, *reply_len); -+ reply[*reply_len] = '\0'; -+ return 0; -+ } else -+ return -EBADF; -+ } else -+ return -EIO; -+ } -+ return -EAGAIN; -+} -+/* -+ * Send a VSI command to the vdp22 mode and expect a reply. The reply can -+ * an aknowledgement (error code 0) or an error code != 0 which means the -+ * command contained an error and was not accepted. -+ * -+ * Wait for the event message from lldpad to return the VSI association data -+ * from the switch -+ */ -+int clif_vsiwait(struct clif *connp, char *ifname, unsigned int tlvid, -+ char *cmd, char *reply, size_t *reply_len, int wait) -+{ -+ int rc; -+ size_t reply_len2 = *reply_len; -+ -+ rc = clif_vsi(connp, ifname, tlvid, cmd, reply, reply_len); -+ if (!rc) { -+ rc = clif_vsievt(connp, reply, &reply_len2, wait); -+ if (!rc) -+ *reply_len = reply_len2; -+ } -+ return rc; -+} -diff --git a/config.c b/config.c -index 7229b91..5fc6f58 100644 ---- a/config.c -+++ b/config.c -@@ -102,6 +102,7 @@ void destroy_cfg(void) - void scan_port(UNUSED void *eloop_data, UNUSED void *user_ctx) - { - struct port *port; -+ struct port *next; - struct if_nameindex *nameidx, *p; - - LLDPAD_INFO("%s: NLMSG dropped, scan ports.\n", __func__); -@@ -121,24 +122,20 @@ void scan_port(UNUSED void *eloop_data, UNUSED void *user_ctx) - * comes back online we should receive a RTM_NEWLINK event and can - * readd it there. - */ -- port = porthead; -- while (port != NULL) { -+ for (port = porthead; port; port = next) { - int found = 0; -- struct port *del; -- p = nameidx; -- while (p->if_index != 0) { -- if (!strncmp(p->if_name, port->ifname, -- MAX_DEVICE_NAME_LEN)) { -+ -+ for (p = nameidx; p->if_index; ++p) { -+ if ((int)p->if_index == port->ifindex) { - /* Good device exists continue port walk */ - found = 1; -+ memcpy(port->ifname, p->if_name, IFNAMSIZ); - break; - } -- p++; - } -- del = port; -- port = port->next; -+ next = port->next; - if (!found) -- remove_port(del->ifname); -+ remove_port(port->ifname); - } - - /* Walk port list looking for devices that should have been added -@@ -149,43 +146,42 @@ void scan_port(UNUSED void *eloop_data, UNUSED void *user_ctx) - * This is required because we currently do not know if we missed - * IF_OPER_UP, IF_OPER_DOWN or IF_OPER_DORMANT. - */ -- p = nameidx; -- while (p->if_index != 0) { -+ for (p = nameidx; p->if_index; ++p) { - struct lldp_module *np; - const struct lldp_mod_ops *ops; - char *ifname = p->if_name; - struct lldp_agent *agent; - -- if (!is_valid_lldp_device(ifname)) { -- p++; -+ if (!is_valid_lldp_device(ifname)) -+ continue; -+ -+ port = port_find_by_ifindex(p->if_index); -+ if (!port) { -+ port = add_port(p->if_index, p->if_name); - continue; - } - -- port = port_find_by_name(p->if_name); -- if (!port) -- port = add_port(p->if_name); -- -- if (port && check_link_status(ifname)) { -+ memcpy(port->ifname, ifname, IFNAMSIZ); -+ if (check_link_status(ifname)) { - set_port_oper_delay(ifname); - oper_add_device(ifname); -- } else if (port) { -- LIST_FOREACH(agent, &port->agent_head, entry) { -- LLDPAD_DBG("%s: calling ifdown for agent %p.\n", -- __func__, agent); -- LIST_FOREACH(np, &lldp_head, lldp) { -- ops = np->ops; -- if (ops->lldp_mod_ifdown) -- ops->lldp_mod_ifdown(ifname, -- agent); -- } -+ continue; -+ } -+ LIST_FOREACH(agent, &port->agent_head, entry) { -+ LLDPAD_DBG("%s: calling ifdown for agent %p.\n", -+ __func__, agent); -+ LIST_FOREACH(np, &lldp_head, lldp) { -+ ops = np->ops; -+ if (ops->lldp_mod_ifdown) -+ ops->lldp_mod_ifdown(ifname, agent); - } -- set_lldp_port_enable(ifname, 0); - } -- p++; -+ set_lldp_port_enable(ifname, 0); - } - - if_freenameindex(nameidx); - return; -+ - error_out: - eloop_register_timeout(INI_TIMER, 0, scan_port, NULL, NULL); - return; -@@ -265,7 +261,7 @@ static bool check_int(int int_setting) - - static bool check_priority(int priority_setting) - { -- if (priority_setting < dcb_none || priority_setting >= dcb_invalid) -+ if (priority_setting < DCB_NONE || priority_setting >= DCB_INVALID) - return false; - else - return true; -@@ -361,36 +357,34 @@ void init_ports(void) - return; - } - -- p = nameidx; -- while (p->if_index != 0) { -+ for (p = nameidx; p->if_index; ++p) { - int valid = is_valid_lldp_device(p->if_name); - -- if (!valid) { -- p++; -+ if (!valid) - continue; -- } - -- port = add_port(p->if_name); -- -- if (port == NULL) { -+ port = add_port(p->if_index, p->if_name); -+ if (!port) { - LLDPAD_ERR("%s: Error adding device %s\n", - __func__, p->if_name); -- } else if (check_link_status(p->if_name)) { -- lldp_add_agent(p->if_name, NEAREST_BRIDGE); -- lldp_add_agent(p->if_name, NEAREST_NONTPMR_BRIDGE); -- lldp_add_agent(p->if_name, NEAREST_CUSTOMER_BRIDGE); -+ continue; -+ } -+ if (!check_link_status(p->if_name)) -+ continue; - -- LIST_FOREACH(agent, &port->agent_head, entry) { -- LLDPAD_DBG("%s: calling ifup for agent %p.\n", -- __func__, agent); -- LIST_FOREACH(np, &lldp_head, lldp) { -- if (np->ops->lldp_mod_ifup) -- np->ops->lldp_mod_ifup(p->if_name, agent); -- } -+ lldp_add_agent(p->if_name, NEAREST_BRIDGE); -+ lldp_add_agent(p->if_name, NEAREST_NONTPMR_BRIDGE); -+ lldp_add_agent(p->if_name, NEAREST_CUSTOMER_BRIDGE); -+ -+ LIST_FOREACH(agent, &port->agent_head, entry) { -+ LLDPAD_DBG("%s: calling ifup for agent %p.\n", -+ __func__, agent); -+ LIST_FOREACH(np, &lldp_head, lldp) { -+ if (np->ops->lldp_mod_ifup) -+ np->ops->lldp_mod_ifup(p->if_name, agent); - } -- set_lldp_port_enable(p->if_name, 1); - } -- p++; -+ set_lldp_port_enable(p->if_name, 1); - } - - if_freenameindex(nameidx); -diff --git a/configure.ac b/configure.ac -index 119ab58..8d65d26 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1,5 +1,5 @@ - AC_INIT([lldpad], [0.9.46], [lldp-devel@open-lldp.org]) --AM_INIT_AUTOMAKE([-Wall -Werror foreign]) -+AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) - - m4_pattern_allow([AM_PROG_AR]) - AM_PROG_AR -@@ -13,6 +13,7 @@ fi - AM_CONDITIONAL([BUILD_DEBUG], [test "$enable_debug" = "yes"]) - - AC_PROG_CC -+AM_PROG_CC_C_O - AC_PROG_CXX - AC_PROG_LEX - AC_PROG_LIBTOOL -@@ -25,12 +26,12 @@ then - fi - - PKG_CHECK_MODULES([LIBCONFIG], [libconfig >= 1.3.2]) --PKG_CHECK_MODULES([LIBNL], [libnl-1 >= 1.1]) -+PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.2]) - - AC_SUBST(LIBNL_CFLAGS) - AC_SUBST(LIBNL_LIBS) - --AC_CHECK_LIB(nl, rtnl_link_get_by_name) -+AC_CHECK_LIB(nl3, rtnl_link_get_by_name) - - AC_CHECK_FUNCS([alarm]) - AC_CHECK_FUNCS([gettimeofday]) -diff --git a/ctrl_iface.c b/ctrl_iface.c -index e02f036..e4fd0b7 100644 ---- a/ctrl_iface.c -+++ b/ctrl_iface.c -@@ -1,6 +1,6 @@ - /******************************************************************************* - -- LLDP Agent Daemon (LLDPAD) Software -+ LLDP Agent Daemon (LLDPAD) Software - Copyright(c) 2007-2010 Intel Corporation. - - Substantially modified from: -@@ -73,7 +73,7 @@ struct clif_cmds { - socklen_t fromlen, - char *ibuf, int ilen, - char *rbuf, int rlen); --}; -+}; - - static const struct clif_cmds cmd_tbl[] = { - { DCB_CMD, clif_iface_module }, -@@ -117,7 +117,6 @@ int clif_iface_module(struct clif_data *clifd, - } - - mod = find_module_by_id(&lldp_head, module_id); -- - if (mod && mod->ops && mod->ops->client_cmd) - return (mod->ops->client_cmd)(clifd, from, fromlen, - cmd_start, cmd_len, rbuf+strlen(rbuf), rlen); -@@ -156,17 +155,14 @@ int clif_iface_attach(struct clif_data *clifd, - char *tlv, *str, *tokenize; - const char *delim = ","; - int i, tlv_count = 0; -- u8 *ptr; - - dst = malloc(sizeof(*dst)); - if (dst == NULL) -- return 1; -+ return cmd_failed; - memset(dst, 0, sizeof(*dst)); - memcpy(&dst->addr, from, sizeof(struct sockaddr_un)); - dst->addrlen = fromlen; - dst->debug_level = MSG_INFO; -- dst->next = clifd->ctrl_dst; -- clifd->ctrl_dst = dst; - - /* - * There are two cases here one, the user provided -@@ -175,7 +171,6 @@ int clif_iface_attach(struct clif_data *clifd, - * user sent a comma seperated string of tlv module - * ids it expects events from - */ -- - /* set default string to DCBX Events */ - if (ibuf[1] == '\0') { - u32 hex = LLDP_MOD_DCBX; -@@ -197,7 +192,7 @@ int clif_iface_attach(struct clif_data *clifd, - tokenize = strtok(NULL, delim); - tlv_count++; - } while (tokenize); -- -+ - dst->tlv_types = malloc(sizeof(u32) * tlv_count); - if (!dst->tlv_types) - goto err_types; -@@ -206,8 +201,11 @@ int clif_iface_attach(struct clif_data *clifd, - /* Populate tlv_types from comma separated string */ - tokenize = strtok(str, delim); - for (i=0; tokenize; i++) { -- ptr = (u8*)&dst->tlv_types[i]; -- hexstr2bin(tokenize, ptr, 4); -+ char *myend; -+ -+ dst->tlv_types[i] = strtol(tokenize, &myend, 16); -+ if (*myend) /* No hexnumber for module id */ -+ goto err_types; - tokenize = strtok(NULL, delim); - } - -@@ -215,13 +213,17 @@ int clif_iface_attach(struct clif_data *clifd, - dst->tlv_types[i] = ~0; - free(tlv); - -+ /* Insert new node at beginning */ -+ dst->next = clifd->ctrl_dst; -+ clifd->ctrl_dst = dst; - LLDPAD_DBG("CTRL_IFACE monitor attached\n"); - snprintf(rbuf, rlen, "%c", ATTACH_CMD); - -- return 0; -+ return cmd_success; - err_types: - free(tlv); - err_tlv: -+ free(dst); - LLDPAD_DBG("CTRL_IFACE monitor attach error\n"); - snprintf(rbuf, rlen, "%c", ATTACH_CMD); - -@@ -278,7 +280,7 @@ int clif_iface_level(struct clif_data *clifd, - level = ibuf+1; - snprintf(rbuf, rlen, "%c", LEVEL_CMD); - -- LLDPAD_DBG("CTRL_IFACE LEVEL %s", level); -+ LLDPAD_DBG("CTRL_IFACE LEVEL %s\n", level); - - dst = clifd->ctrl_dst; - while (dst) { -@@ -326,7 +328,7 @@ static void process_clif_cmd( struct clif_data *cd, - rsize - strlen(rbuf) - 1); - - /* update status and compute final length */ -- rbuf[CLIF_STAT_OFF] = hexlist[(status & 0x0f1) >> 4]; -+ rbuf[CLIF_STAT_OFF] = hexlist[(status & 0xf0) >> 4]; - rbuf[CLIF_STAT_OFF+1] = hexlist[status & 0x0f]; - *rlen = strlen(rbuf); - } -@@ -371,14 +373,14 @@ static void ctrl_iface_receive(int sock, void *eloop_ctx, - cred = (struct ucred *)CMSG_DATA(cmsg); - - if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { -- LLDPAD_INFO("%s: No sender credentials, ignoring", -+ LLDPAD_INFO("%s: No sender credentials, ignoring\n", - __FUNCTION__); - sprintf(buf,"R%02x", cmd_bad_params); - sendto(sock, buf, 3, 0, (struct sockaddr *) &from, fromlen); - return; - } - if (cred->uid != 0) { -- LLDPAD_INFO("%s: sender uid=%i, ignoring", -+ LLDPAD_INFO("%s: sender uid=%i, ignoring\n", - __FUNCTION__, cred->uid); - sprintf(buf,"R%02x", cmd_no_access); - sendto(sock, buf, 3, 0, (struct sockaddr *) &from, -@@ -411,6 +413,42 @@ int ctrl_iface_register(struct clif_data *clifd) - clifd, NULL); - } - -+int ctrl_iface_systemd_socket() -+{ -+ char *env, *ptr; -+ unsigned int p, l; -+ -+ env = getenv("LISTEN_PID"); -+ if (!env) -+ return -1; -+ -+ p = strtoul(env, &ptr, 10); -+ if (ptr && ptr == env) { -+ LLDPAD_DBG("Invalid value '%s' for LISTEN_PID\n", env); -+ return -1; -+ } -+ if ((pid_t)p != getpid()) { -+ LLDPAD_DBG("Invalid PID '%d' from LISTEN_PID\n", p); -+ return -1; -+ } -+ env = getenv("LISTEN_FDS"); -+ if (!env) { -+ LLDPAD_DBG("LISTEN_FDS is not set\n"); -+ return -1; -+ } -+ l = strtoul(env, &ptr, 10); -+ if (ptr && ptr == env) { -+ LLDPAD_INFO("Invalid value '%s' for LISTEN_FDS\n", env); -+ return -1; -+ } -+ if (l != 1) { -+ LLDPAD_INFO("LISTEN_FDS specified %d fds\n", l); -+ return -1; -+ } -+ /* systemd returns fds with an offset of '3' */ -+ return 3; -+} -+ - int ctrl_iface_init(struct clif_data *clifd) - { - struct sockaddr_un addr; -@@ -421,9 +459,14 @@ int ctrl_iface_init(struct clif_data *clifd) - clifd->ctrl_sock = -1; - clifd->ctrl_dst = NULL; - -+ s = ctrl_iface_systemd_socket(); -+ if (s != -1) { -+ LLDPAD_INFO("using fd %d from systemd\n", s); -+ goto out; -+ } - s = socket(AF_LOCAL, SOCK_DGRAM, 0); - if (s < 0) { -- perror("socket(AF_LOCAL)"); -+ LLDPAD_WARN("failed to create CLI socket: %m\n"); - goto fail; - } - /* enable receiving of the sender credentials */ -@@ -436,7 +479,10 @@ int ctrl_iface_init(struct clif_data *clifd) - "%s", LLDP_CLIF_SOCK); - addrlen = sizeof(sa_family_t) + strlen(addr.sun_path + 1) + 1; - if (bind(s, (struct sockaddr *) &addr, addrlen) < 0) { -- perror("bind(AF_LOCAL)"); -+ if (errno == EADDRINUSE) -+ LLDPAD_WARN("another lldpad instance is running\n"); -+ else -+ LLDPAD_WARN("failed to bind CLI socket address: %m"); - goto fail; - } - /* enable receiving of the sender credentials */ -@@ -444,6 +490,7 @@ int ctrl_iface_init(struct clif_data *clifd) - &feature_on, sizeof(feature_on)); - - LLDPAD_INFO("bound ctrl iface to %s\n", &addr.sun_path[1]); -+out: - clifd->ctrl_sock = s; - - return 0; -@@ -481,7 +528,7 @@ int is_ctrl_listening(struct ctrl_dst *dst, u32 type) - u32 term = ~0; - u32 all = 0; - u32 dcbx = LLDP_MOD_DCBX; -- -+ - if (!dst) - return 0; - -@@ -530,8 +577,7 @@ void ctrl_iface_send(struct clif_data *clifd, int level, u32 moduleid, - next = dst->next; - send = 0; - /* Does dst receive these event messages? */ -- send = is_ctrl_listening(dst, moduleid); -- -+ send = is_ctrl_listening(dst, moduleid); - /* Yes */ - if (send && level >= dst->debug_level) { - msg.msg_name = &dst->addr; -diff --git a/dcb_protocol.c b/dcb_protocol.c -index 1e110a6..61b504d 100644 ---- a/dcb_protocol.c -+++ b/dcb_protocol.c -@@ -45,7 +45,7 @@ - #include "linux/dcbnl.h" - - static void handle_opermode_true(char *device_name); --u8 gdcbx_subtype = dcbx_subtype2; -+u8 gdcbx_subtype = DCBX_SUBTYPE2; - - int set_configuration(char *device_name, u32 EventFlag); - -@@ -1213,7 +1213,7 @@ int dcbx_remove_adapter(char *device_name) - LLDPAD_DBG("remove_adapter: oper llink not found\n"); - } - -- lldpad_shm_set_dcbx(device_name, dcbx_subtype0); -+ lldpad_shm_set_dcbx(device_name, DCBX_SUBTYPE0); - return true; - } - -@@ -1343,7 +1343,7 @@ bool add_pg_defaults() - pg_data.tx.up[index].pgid = (u8)(index); - pg_data.tx.up[index].bwgid = (u8)index; - pg_data.tx.up[index].percent_of_pg_cap = BW_PERCENT; -- pg_data.tx.up[index].strict_priority = dcb_none; -+ pg_data.tx.up[index].strict_priority = DCB_NONE; - } - temp = rmndr; - for (index=0; index < MAX_BANDWIDTH_GROUPS; index++) { -@@ -1357,7 +1357,7 @@ bool add_pg_defaults() - pg_data.rx.up[index].pgid = (u8)(index); - pg_data.rx.up[index].bwgid = (u8)index; - pg_data.rx.up[index].percent_of_pg_cap = BW_PERCENT; -- pg_data.rx.up[index].strict_priority = dcb_none; -+ pg_data.rx.up[index].strict_priority = DCB_NONE; - } - - snprintf(sTmp, MAX_DESCRIPTION_LEN, DEF_CFG_STORE); -@@ -1391,7 +1391,7 @@ bool add_pfc_defaults() - pfc_data.protocol.Advertise = 1; - - for (index=0; index < MAX_TRAFFIC_CLASSES; index++) -- pfc_data.admin[index] = pfc_disabled; -+ pfc_data.admin[index] = PFC_DISABLED; - - snprintf(sTmp, MAX_DESCRIPTION_LEN, DEF_CFG_STORE); - /* Create pfc default data store for the device. */ -@@ -1599,9 +1599,9 @@ cmd_status put_pg(char *device_name, pg_attribs *pg_data, pfc_attribs *pfc_data) - feature_protocol_attribs *dStore = &(it->second->protocol); - - if (dStore->Enable && !(pg_data->protocol.Enable)) -- LLDPAD_INFO("%s PG disabled", device_name); -+ LLDPAD_INFO("%s PG disabled\n", device_name); - else if (!(dStore->Enable) && pg_data->protocol.Enable) -- LLDPAD_INFO("%s PG enabled", device_name); -+ LLDPAD_INFO("%s PG enabled\n", device_name); - - dStore->Advertise_prev = dStore->Advertise; - dStore->Advertise = pg_data->protocol.Advertise; -@@ -1611,7 +1611,7 @@ cmd_status put_pg(char *device_name, pg_attribs *pg_data, pfc_attribs *pfc_data) - - memcpy(&(it->second->rx), &(pg_data->rx), sizeof(pg_data->rx)); - memcpy(&(it->second->tx), &(pg_data->tx), sizeof(pg_data->tx)); -- if (it->second->protocol.dcbx_st == dcbx_subtype2) -+ if (it->second->protocol.dcbx_st == DCBX_SUBTYPE2) - it->second->num_tcs = pg_data->num_tcs; - - DCB_SET_FLAGS(EventFlag, DCB_LOCAL_CHANGE_PG); -@@ -1653,7 +1653,7 @@ cmd_status put_peer_pg(char *device_name, pg_attribs *peer_pg_data) - goto Exit; - } - -- if (peer_pg_data->protocol.dcbx_st == dcbx_subtype2) -+ if (peer_pg_data->protocol.dcbx_st == DCBX_SUBTYPE2) - rebalance_uppcts(peer_pg_data); - - /* detect config change */ -@@ -1677,7 +1677,7 @@ cmd_status put_peer_pg(char *device_name, pg_attribs *peer_pg_data) - sizeof(peer_pg_data->rx)); - memcpy(&(peer_it->second->tx), &(peer_pg_data->tx), - sizeof(peer_pg_data->tx)); -- if (peer_it->second->protocol.dcbx_st == dcbx_subtype2) -+ if (peer_it->second->protocol.dcbx_st == DCBX_SUBTYPE2) - peer_it->second->num_tcs = peer_pg_data->num_tcs; - Exit: - return result; -@@ -1765,9 +1765,9 @@ cmd_status put_pfc(char *device_name, pfc_attribs *pfc_data) - feature_protocol_attribs *dStore = &(it->second->protocol); - - if (dStore->Enable && !(pfc_data->protocol.Enable)) -- LLDPAD_INFO("%s PFC disabled", device_name); -+ LLDPAD_INFO("%s PFC disabled\n", device_name); - else if (!(dStore->Enable) && pfc_data->protocol.Enable) -- LLDPAD_INFO("%s PFC enabled", device_name); -+ LLDPAD_INFO("%s PFC enabled\n", device_name); - - dStore->Advertise_prev = dStore->Advertise; - dStore->Advertise = pfc_data->protocol.Advertise; -@@ -1777,7 +1777,7 @@ cmd_status put_pfc(char *device_name, pfc_attribs *pfc_data) - - memcpy(it->second->admin, pfc_data->admin, - sizeof(pfc_data->admin)); -- if (it->second->protocol.dcbx_st == dcbx_subtype2) -+ if (it->second->protocol.dcbx_st == DCBX_SUBTYPE2) - it->second->num_tcs = pfc_data->num_tcs; - - /* Run the protocol */ -@@ -1835,7 +1835,7 @@ cmd_status put_peer_pfc(char *device_name, pfc_attribs *peer_pfc_data) - - memcpy(peer_it->second->admin, &peer_pfc_data->admin, - sizeof(peer_pfc_data->admin)); -- if (peer_it->second->protocol.dcbx_st == dcbx_subtype2) -+ if (peer_it->second->protocol.dcbx_st == DCBX_SUBTYPE2) - peer_it->second->num_tcs = peer_pfc_data->num_tcs; - Exit: - return result; -@@ -1934,9 +1934,9 @@ cmd_status put_app(char *device_name, u32 subtype, app_attribs *app_data) - - feature_protocol_attribs *dStore = &(it->second->protocol); - if (dStore->Enable && !(app_data->protocol.Enable)) -- LLDPAD_INFO("%s APP disabled", device_name); -+ LLDPAD_INFO("%s APP disabled\n", device_name); - else if (!(dStore->Enable) && app_data->protocol.Enable) -- LLDPAD_INFO("%s APP enabled", device_name); -+ LLDPAD_INFO("%s APP enabled\n", device_name); - dStore->Advertise_prev = dStore->Advertise; - dStore->Advertise = app_data->protocol.Advertise; - dStore->Enable = app_data->protocol.Enable; -@@ -2040,9 +2040,9 @@ cmd_status put_llink(char *device_name, u32 subtype, llink_attribs *llink_data) - } - feature_protocol_attribs *dStore = &(it->second->protocol); - if (dStore->Enable && !(llink_data->protocol.Enable)) -- LLDPAD_INFO("%s LLINK disabled", device_name); -+ LLDPAD_INFO("%s LLINK disabled\n", device_name); - else if (!(dStore->Enable) && llink_data->protocol.Enable) -- LLDPAD_INFO("%s LLINK enabled", device_name); -+ LLDPAD_INFO("%s LLINK enabled\n", device_name); - dStore->Advertise_prev = dStore->Advertise; - dStore->Advertise = llink_data->protocol.Advertise; - dStore->Enable = llink_data->protocol.Enable; -@@ -2575,7 +2575,7 @@ bool LocalPeerCompatible(char *device_name, u32 EventFlag, u32 Subtype) - ppg = Peer->second; - - match = true; -- if (ppg->protocol.dcbx_st == dcbx_subtype1) { -+ if (ppg->protocol.dcbx_st == DCBX_SUBTYPE1) { - for (i = 0; i < MAX_USER_PRIORITIES; i++) { - if (lpg->tx.up[i].bwgid != - ppg->tx.up[i].bwgid) -@@ -3180,7 +3180,7 @@ cmd_status run_feature_protocol(char *device_name, u32 EventFlag, u32 Subtype) - goto ErrBadVersion; - } - -- if (feat_prot->dcbx_st == dcbx_subtype2) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE2) { - /* Handle Peer expiration */ - if (peer_ctrl_prot->second->RxDCBTLVState == - DCB_PEER_EXPIRED) { -@@ -3210,7 +3210,7 @@ cmd_status run_feature_protocol(char *device_name, u32 EventFlag, u32 Subtype) - feat_prot->Syncd, __LINE__); - feat_prot->Oper_version = - feat_prot->Max_version; -- if (feat_prot->dcbx_st == dcbx_subtype2) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE2) { - feat_prot->Error = true; - } else { - feat_prot->Error = false; -@@ -3295,7 +3295,7 @@ cmd_status run_feature_protocol(char *device_name, u32 EventFlag, u32 Subtype) - feat_prot->Error_Flag = FEAT_ERR_NONE; - Err = feat_prot->Error; - /* Set_configuration to driver. */ -- if (feat_prot->dcbx_st == dcbx_subtype2) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE2) { - feat_prot->Syncd = !(feat_prot->Error); - feat_prot->Error = false; - if (set_configuration(device_name, -@@ -3323,7 +3323,7 @@ cmd_status run_feature_protocol(char *device_name, u32 EventFlag, u32 Subtype) - feat_prot->Error_Flag = FEAT_ERR_NONE; - Err = feat_prot->Error; - -- if (feat_prot->dcbx_st == dcbx_subtype2) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE2) { - feat_prot->OperMode = - !(peer_feat_prot->Error); - if (feat_prot->OperMode) { -@@ -3375,7 +3375,7 @@ cmd_status run_feature_protocol(char *device_name, u32 EventFlag, u32 Subtype) - Err = feat_prot->Error; - - /* Set_configuration to driver. */ -- if (feat_prot->dcbx_st == dcbx_subtype2) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE2) { - feat_prot->OperMode = - !peer_feat_prot->Error; - feat_prot->Syncd = !(feat_prot->Error); -@@ -3412,7 +3412,7 @@ cmd_status run_feature_protocol(char *device_name, u32 EventFlag, u32 Subtype) - Err = feat_prot->Error; - /* Set_configuration to driver. */ - -- if (feat_prot->dcbx_st == dcbx_subtype2) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE2) { - feat_prot->OperMode = - !peer_feat_prot->Error; - feat_prot->Syncd = !(feat_prot->Error); -@@ -3442,7 +3442,7 @@ cmd_status run_feature_protocol(char *device_name, u32 EventFlag, u32 Subtype) - Err = feat_prot->Error; - - /* Set default configuration */ -- if (feat_prot->dcbx_st == dcbx_subtype2) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE2) { - feat_prot->Syncd = feat_prot->Error; - feat_prot->Error = true; - if (set_configuration(device_name, -@@ -3464,7 +3464,7 @@ ErrProt: - if (peer_feat_prot->Error) - feat_prot->Error_Flag |= FEAT_ERR_PEER; - -- if (feat_prot->dcbx_st == dcbx_subtype1) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE1) { - if (feat_prot->Error || peer_feat_prot->Error){ - LLDPAD_DBG(" ## FEATURE ERROR: " - "%d, %d (Error_Flag 0x%x" -@@ -3483,7 +3483,7 @@ ErrProt: - } - if (ErrorChanged) { - LLDPAD_DBG(" ErrorChanged \n"); -- if (feat_prot->dcbx_st == dcbx_subtype1) { -+ if (feat_prot->dcbx_st == DCBX_SUBTYPE1) { - feat_prot->Syncd = false; - LLDPAD_DBG(" Set Syncd to %u [%u]\n", - feat_prot->Syncd, __LINE__); -@@ -3509,10 +3509,10 @@ OperChange: - if (feat_prot->OperMode != old_pg_opmode) { - pg_events = pg_events | EVENT_OPERMODE; - if (feat_prot->OperMode) { -- LLDPAD_INFO("%s PG oper mode true", -+ LLDPAD_INFO("%s PG oper mode true\n", - device_name); - } else { -- LLDPAD_INFO("%s PG oper mode false", -+ LLDPAD_INFO("%s PG oper mode false\n", - device_name); - } - } -@@ -3534,10 +3534,10 @@ OperChange: - if (feat_prot->OperMode != old_pfc_opmode) { - pfc_events = pfc_events | EVENT_OPERMODE; - if (feat_prot->OperMode) { -- LLDPAD_INFO("%s PFC oper mode true", -+ LLDPAD_INFO("%s PFC oper mode true\n", - device_name); - } else { -- LLDPAD_INFO("%s PFC oper mode false", -+ LLDPAD_INFO("%s PFC oper mode false\n", - device_name); - } - } -@@ -3563,10 +3563,10 @@ OperChange: - if (feat_prot->OperMode != old_app_opmode) { - app_events = app_events | EVENT_OPERMODE; - if (feat_prot->OperMode) { -- LLDPAD_INFO("%s APP oper mode true", -+ LLDPAD_INFO("%s APP oper mode true\n", - device_name); - } else { -- LLDPAD_INFO("%s APP oper mode false", -+ LLDPAD_INFO("%s APP oper mode false\n", - device_name); - } - } -@@ -3836,7 +3836,7 @@ cmd_status run_control_protocol(char *device_name, u32 EventFlag) - return cmd_device_not_found; - } - if (pg_dstore.protocol.dcbx_st == -- dcbx_subtype2) { -+ DCBX_SUBTYPE2) { - return cmd_success; - } else { - /* Send the updated DCB TLV */ -diff --git a/dcb_rule_chk.c b/dcb_rule_chk.c -index ee644f6..bd6d2f2 100644 ---- a/dcb_rule_chk.c -+++ b/dcb_rule_chk.c -@@ -144,9 +144,9 @@ static int dcb_fixup_pg(struct pg_attribs *fixpg, struct pfc_attribs *fixpfc) - if (!entry) - continue; - -- if (entry->strict_priority == dcb_link) -+ if (entry->strict_priority == DCB_LINK) - strict++; -- else if (fixpfc && fixpfc->admin[j] == pfc_enabled) -+ else if (fixpfc && fixpfc->admin[j] == PFC_ENABLED) - pfc++; - else - be++; -@@ -188,11 +188,11 @@ static int dcb_fixup_pg(struct pg_attribs *fixpg, struct pfc_attribs *fixpfc) - continue; - - if (pgid < 0) { -- if (entry->strict_priority == dcb_link) { -+ if (entry->strict_priority == DCB_LINK) { - pgid = cbe + cpfc + strict; - strict++; - } else if (fixpfc && -- fixpfc->admin[j] == pfc_enabled) { -+ fixpfc->admin[j] == PFC_ENABLED) { - pgid = cbe + pfc; - pfc++; - } else { -@@ -252,7 +252,7 @@ static int dcb_fixup_pg(struct pg_attribs *fixpg, struct pfc_attribs *fixpfc) - for (i = 0; i < MAX_USER_PRIORITIES; i++) { - fixpg->tx.up[i].bwgid = i; - -- if (fixpg->tx.up[i].strict_priority == dcb_link) { -+ if (fixpg->tx.up[i].strict_priority == DCB_LINK) { - fixpg->tx.up[i].percent_of_pg_cap = 0; - fixpg->rx.up[i].percent_of_pg_cap = 0; - } else { -@@ -314,7 +314,7 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - - /* Internally in the pg_attribs structure, a link strict PGID is - * maintained as a PGID value (0-7) with a corresponding -- * strict_priority field value of 'dcb_link'. Only one link strict -+ * strict_priority field value of 'DCB_LINK'. Only one link strict - * PGID is allowed. - */ - link_strict_pgid = LINK_STRICT_PGID; -@@ -323,7 +323,7 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - tx_bw = tx_bw + pg->tx.pg_percent[i]; - - /* check for >1 link strict PGID */ -- if (pg->tx.up[i].strict_priority == dcb_link) { -+ if (pg->tx.up[i].strict_priority == DCB_LINK) { - if (link_strict_pgid == LINK_STRICT_PGID) { - link_strict_pgid = pg->tx.up[i].pgid; - } else if (pg->tx.up[i].pgid != link_strict_pgid) { -@@ -343,7 +343,7 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - */ - for (i = 0; i < MAX_BW_GROUP; i++) { - if ((tx_bw != 0) || (pg->tx.up[i].strict_priority != -- dcb_link)) { -+ DCB_LINK)) { - LLDPAD_INFO("Invalid tx total BWG %d\n", - (int)tx_bw); - return cmd_bad_params; -@@ -356,7 +356,7 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - rx_bw = rx_bw + pg->rx.pg_percent[i]; - - /* check for >1 link strict PGID */ -- if (pg->rx.up[i].strict_priority == dcb_link) { -+ if (pg->rx.up[i].strict_priority == DCB_LINK) { - if (link_strict_pgid == LINK_STRICT_PGID) { - link_strict_pgid = pg->rx.up[i].pgid; - } else if (pg->rx.up[i].pgid != link_strict_pgid) { -@@ -376,7 +376,7 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - */ - for (i = 0; i < MAX_BW_GROUP; i++) { - if ((rx_bw != 0) || (pg->rx.up[i].strict_priority != -- dcb_link)) { -+ DCB_LINK)) { - LLDPAD_INFO("Invalid RX total BWG %d\n", - (int)rx_bw); - return cmd_bad_params; -@@ -403,7 +403,7 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - (int)tx_bw_id); - return cmd_bad_params; - } -- if (pg->tx.up[i].strict_priority == dcb_link) { -+ if (pg->tx.up[i].strict_priority == DCB_LINK) { - tx_link_strict[tx_bw_id] = true; - /* Link strict should have zero bandwidth */ - if (tx_bw){ -@@ -412,7 +412,7 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - return cmd_bad_params; - } - } else if (!tx_bw) { -- LLDPAD_INFO("Zero BW on non LSP tc %i", i); -+ LLDPAD_INFO("Zero BW on non LSP tc %i\n", i); - /* Non link strict should have non zero bandwidth*/ - return cmd_bad_params; - } -@@ -422,10 +422,10 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - rx_bw_id = (u8)(pg->rx.up[i].bwgid); - - if (rx_bw_id >= MAX_BW_GROUP) { -- LLDPAD_INFO("Invalid RX BW %i", rx_bw_id); -+ LLDPAD_INFO("Invalid RX BW %i\n", rx_bw_id); - return cmd_bad_params; - } -- if (pg->rx.up[i].strict_priority == dcb_link) { -+ if (pg->rx.up[i].strict_priority == DCB_LINK) { - rx_link_strict[rx_bw_id] = true; - /* Link strict class should have zero bandwidth */ - if (rx_bw){ -@@ -434,7 +434,7 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - return cmd_bad_params; - } - } else if (!rx_bw) { -- LLDPAD_INFO("Zero BW on no LSP tc %i", i); -+ LLDPAD_INFO("Zero BW on no LSP tc %i\n", i); - /* Non link strict class should have non-zero bw */ - return cmd_bad_params; /* DCB_RX_ERR_TC_BW_ZERO; */ - } -@@ -451,13 +451,13 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - */ - if (tx_link_strict[i]) { - if (tx_bw_sum[i] && pg->tx.pg_percent[i]) { -- LLDPAD_INFO("Non-zero LSP BW %d %d\n", -+ LLDPAD_INFO("Non-zero TX LSP BW %d %d\n", - i, (int)tx_bw_sum[i]); - /* Link strict group should have zero bw */ - return cmd_bad_params; - } - } else if (tx_bw_sum[i] != BW_PERCENT && tx_bw_sum[i] != 0) { -- LLDPAD_INFO("Invalid BW sum on BWG %i %i", -+ LLDPAD_INFO("Invalid TX BW sum on BWG %i %i\n", - i, (int)tx_bw_sum[i]); - return cmd_bad_params; - } -@@ -470,13 +470,13 @@ dcb_check_config (full_dcb_attrib_ptrs *attribs) - */ - if (rx_link_strict[i]) { - if (rx_bw_sum[i] && pg->rx.pg_percent[i]) { -- LLDPAD_INFO("Non-zero BW on LSP tc " -- "%u %u\n", i, rx_bw_sum[i]); -+ LLDPAD_INFO("Non-zero RX LSP BW %d %d\n", -+ i, (int)rx_bw_sum[i]); - /* Link strict group should have zero bw */ - return cmd_bad_params; - } - } else if (rx_bw_sum[i] != BW_PERCENT && rx_bw_sum[i] != 0) { -- LLDPAD_INFO("Invalid BW sum on BWG %i %i", -+ LLDPAD_INFO("Invalid RX BW sum on BWG %i %i\n", - i, (int)rx_bw_sum[i]); - return cmd_bad_params; - } -@@ -517,7 +517,7 @@ void rebalance_uppcts(pg_attribs *pg) - for (i = 0; i < MAX_USER_PRIORITIES; i++) { - if (pg->tx.up[i].bwgid == bwgid) { - uplist[num_found++] = (u8)i; -- if (pg->tx.up[i].strict_priority == dcb_link) { -+ if (pg->tx.up[i].strict_priority == DCB_LINK) { - link_strict = true; - pg->tx.up[i].percent_of_pg_cap = 0; - pg->rx.up[i].percent_of_pg_cap = 0; -@@ -535,8 +535,8 @@ void rebalance_uppcts(pg_attribs *pg) - } - pg->tx.up[uplist[i]].percent_of_pg_cap = (u8)value; - pg->rx.up[uplist[i]].percent_of_pg_cap = (u8)value; -- pg->tx.up[uplist[i]].strict_priority = dcb_none; -- pg->rx.up[uplist[i]].strict_priority = dcb_none; -+ pg->tx.up[uplist[i]].strict_priority = DCB_NONE; -+ pg->rx.up[uplist[i]].strict_priority = DCB_NONE; - } - } - } -diff --git a/dcbtool_cmds.c b/dcbtool_cmds.c -index b36c522..a5cd0fe 100644 ---- a/dcbtool_cmds.c -+++ b/dcbtool_cmds.c -@@ -465,7 +465,7 @@ void print_dcb_cmd_response(char *buf, int status) - int version; - int dcb_cmd; - int feature; -- int dcbx_st = dcbx_subtype1; -+ int dcbx_st = DCBX_SUBTYPE1; - int subtype = 0; - int plen = 0; - int doff; -@@ -634,16 +634,16 @@ void print_dcb_cmd_response(char *buf, int status) - case FEATURE_DCBX: - printf("DCBX Version:\t"); - switch (*(buf+doff+DCBX_VERSION) ^ '0') { -- case dcbx_subtype1: -+ case DCBX_SUBTYPE1: - printf("CIN\n"); - break; -- case dcbx_subtype2: -+ case DCBX_SUBTYPE2: - printf("CEE\n"); - break; -- case dcbx_force_subtype1: -+ case DCBX_FORCE_SUBTYPE1: - printf("FORCED CIN\n"); - break; -- case dcbx_force_subtype2: -+ case DCBX_FORCE_SUBTYPE2: - printf("FORCED CEE\n"); - break; - default: -@@ -680,7 +680,7 @@ void print_dcb_cmd_response(char *buf, int status) - printf("\n"); - - if ((dcb_cmd != CMD_GET_PEER) || -- (dcb_cmd == CMD_GET_PEER && dcbx_st == dcbx_subtype1)) { -+ (dcb_cmd == CMD_GET_PEER && dcbx_st == DCBX_SUBTYPE1)) { - printf("uppct: \t"); - for (i=0; iifname, MAX_DEVICE_NAME_LEN)) -+ ifindex = get_ifidx(device_name); -+ for (port = porthead; port; port = port->next) -+ if (ifindex == port->ifindex) - break; -- port = port->next; -- } - - if (!port) { -- newport = add_port(device_name); -- -- if (newport == NULL) { -+ newport = add_port(ifindex, device_name); -+ if (!newport) { - LLDPAD_INFO("%s: Error adding device %s\n", -- __func__, device_name); -+ __func__, device_name); - return -EINVAL; - } - -@@ -232,6 +230,7 @@ static void event_if_decode_nlmsg(int route_type, void *data, int len) - struct rtattr *rta; - char device_name[IFNAMSIZ]; - struct lldp_agent *agent; -+ int ifindex; - int attrlen; - int valid; - int link_status = IF_OPER_UNKNOWN; -@@ -241,13 +240,13 @@ static void event_if_decode_nlmsg(int route_type, void *data, int len) - case RTM_DELLINK: - case RTM_SETLINK: - case RTM_GETLINK: -+ ifindex = ((struct ifinfomsg *)data)->ifi_index; - LLDPAD_DBG(" IFINFOMSG\n"); - LLDPAD_DBG(" ifi_family = 0x%02x\n", - ((struct ifinfomsg *)data)->ifi_family); - LLDPAD_DBG(" ifi_type = 0x%x\n", - ((struct ifinfomsg *)data)->ifi_type); -- LLDPAD_DBG(" ifi_index = %i\n", -- ((struct ifinfomsg *)data)->ifi_index); -+ LLDPAD_DBG(" ifi_index = %i\n", ifindex); - LLDPAD_DBG(" ifi_flags = 0x%04x\n", - ((struct ifinfomsg *)data)->ifi_flags); - LLDPAD_DBG(" ifi_change = 0x%04x\n", -@@ -274,7 +273,7 @@ static void event_if_decode_nlmsg(int route_type, void *data, int len) - if (!valid) - break; - -- struct port *port = port_find_by_name(device_name); -+ struct port *port = port_find_by_ifindex(ifindex); - if (!port) - break; - -diff --git a/include/clif.h b/include/clif.h -index fa19149..648eedf 100644 ---- a/include/clif.h -+++ b/include/clif.h -@@ -152,8 +152,12 @@ int clif_recv(struct clif *clif, char *reply, size_t *reply_len); - * message available to be received with clif_recv(). clif_pending() is - * only used for event messages, i.e., clif_attach() must have been used to - * register the client interface as an event monitor. -+ * -+ * clif_pending_wait - Same as clif_pending, but allows the specification -+ * of maximum wait time in seconds. - */ - int clif_pending(struct clif *clif); -+int clif_pending_wait(struct clif *clif, int waittime); - - - /** -@@ -180,4 +184,70 @@ int clif_get_fd(struct clif *clif); - * its PID. Extract the PID and return it to the caller. - */ - pid_t clif_getpid(void); -+ -+/** -+ * clif_vsi - Send a VDP22 association command to the running lldpad process -+ * @clif: Control interface data from clif_open() -+ * @ifname: Name of the interface to apply the VSI command -+ * @tlvid: Number of tlv identifier -+ * @cmd: Buffer containing the VSI command -+ * @reply: Buffer for the reply data -+ * @reply_len: Length of the reply buffer -+ * Returns: cmd_success when VSI command was accepted and cmd_failure if not. -+ * -+ * This commands sends an VSI association command encoded as ascii string -+ * to the lldpad VPD22 module. The module decodes the ascii string and checks -+ * for consistency. Any white space in the ascii string is removed. The -+ * format of the ascii string is explained in the man page. -+ * -+ * If the command is invalid cmd_failure is returned. -+ * Other cmd_success is returned. In this case the command was accepted and -+ * sent to the switch. The switch may still deny the request. The switch -+ * response is sent via an event message. -+ * -+ * Note: This command can only be sent when the clif_attach() functions has -+ * been called with successful return code. -+ */ -+int clif_vsi(struct clif *clif, char *ifname, unsigned int tlvid, char *cmd, -+ char *reply, size_t *reply_len); -+ -+/** -+ * clif_vsievt - Wait for event message from lldpad after clif_vsi() -+ * @clif: Control interface data from clif_open() -+ * @reply: Buffer for the reply data -+ * @reply_len: Length of the reply buffer -+ * @waittime: Maximum number of seconds to wait for event message -+ * Returns: -+ * 0: on success (a message was received and reply_len contains the number -+ * of bytes of the message) -+ * -EINVAL: Invalid parameters, for example negative wait time. -+ * -EAGAIN: No message received. -+ * -EIO: Message pending but receive function failed. -+ * -EBADF: Message received but was no event message. -+ * -+ * This function waits up to waittime seconds for an event message from -+ * lldpad. An event message is expected when the clif_vsi() successfully -+ * submitted an VSI command. The event message contains the reply from the -+ * switch. The event message is in acsii and the format is explained in the -+ * man page. -+ */ -+int clif_vsievt(struct clif *clif, char *reply, size_t *reply_len, int waitime); -+ -+/** -+ * clif_vsiwait - Send VSI command and wait for event message. -+ * @clif: Control interface data from clif_open() -+ * @ifname: Name of the interface to apply the VSI command -+ * @tlvid: Number of tlv identifier -+ * @cmd: Buffer containing the VSI command -+ * @reply: Buffer for the reply data -+ * @reply_len: Length of the reply buffer -+ * @waittime: Maximum number of seconds to wait for event message -+ * Returns: see clif_vsi() and clif_vsievt(). -+ * -+ * This function is a combination of clif_vsi() and clif_vsievt(). It sends -+ * the vsi command and on successful reception of the VSI command calls -+ * clif_vsievt() to receive the response. -+ */ -+int clif_vsiwait(struct clif *clif, char *ifname, unsigned int tlvid, -+ char *cmd, char *reply, size_t *reply_len, int waittime); - #endif /* CLIF_H */ -diff --git a/include/dcb_types.h b/include/dcb_types.h -index 34d88d6..23cf264 100644 ---- a/include/dcb_types.h -+++ b/include/dcb_types.h -@@ -41,11 +41,11 @@ - - /* DCBX subtypes */ - typedef enum { -- dcbx_subtype0 = 0, /* auto IEEE */ -- dcbx_subtype1 = 1, /* CIN */ -- dcbx_subtype2 = 2, /* CEE */ -- dcbx_force_subtype1 = 5,/* FORCE CIN */ -- dcbx_force_subtype2 = 6,/* FORCE CEE */ -+ DCBX_SUBTYPE0 = 0, /* auto IEEE */ -+ DCBX_SUBTYPE1 = 1, /* CIN */ -+ DCBX_SUBTYPE2 = 2, /* CEE */ -+ DCBX_FORCE_SUBTYPE1 = 5,/* FORCE CIN */ -+ DCBX_FORCE_SUBTYPE2 = 6,/* FORCE CEE */ - } dcbx_subtype; - - -@@ -54,9 +54,9 @@ typedef enum { - - /* PFC configuration */ - typedef enum { -- pfc_disabled = 0x000, -- pfc_enabled, -- pfc_invalid, -+ PFC_DISABLED = 0x000, -+ PFC_ENABLED, -+ PFC_INVALID, - } pfc_type; - - /* Peer DCB TLV States */ -@@ -70,10 +70,10 @@ typedef enum { - typedef pfc_type dcb_pfc_type; - - typedef enum { -- dcb_none = 0x0000, -- dcb_group, -- dcb_link, -- dcb_invalid, -+ DCB_NONE = 0x0000, -+ DCB_GROUP, -+ DCB_LINK, -+ DCB_INVALID, - } dcb_strict_priority_type; - - typedef pfc_type dcb_pfc_list_type[MAX_USER_PRIORITIES]; -diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h -index 66a6723..503bad3 100644 ---- a/include/linux/dcbnl.h -+++ b/include/linux/dcbnl.h -@@ -11,8 +11,8 @@ - * more details. - * - * You should have received a copy of the GNU General Public License along with -- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple -- * Place - Suite 330, Boston, MA 02111-1307 USA. -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Author: Lucy Liu - */ -diff --git a/include/lldp_8021qaz.h b/include/lldp_8021qaz.h -index 461cca2..55353b8 100644 ---- a/include/lldp_8021qaz.h -+++ b/include/lldp_8021qaz.h -@@ -238,5 +238,6 @@ inline int ieee8021qaz_clif_cmd(void *data, struct sockaddr_un *from, - socklen_t fromlen, char *ibuf, int ilen, - char *rbuf); - int ieee8021qaz_check_operstate(void); -+int get_dcbx_hw(const char *ifname, __u8 *dcbx); - - #endif /* _LLDP_8021QAZ_H */ -diff --git a/include/lldp_dcbx_cmds.h b/include/lldp_dcbx_cmds.h -index 9e9603d..39661e7 100644 ---- a/include/lldp_dcbx_cmds.h -+++ b/include/lldp_dcbx_cmds.h -@@ -31,7 +31,7 @@ - #include - #include "clif_msgs.h" - --struct arg_handlers *dcbx_get_arg_handlers(); -+struct arg_handlers *dcbx_get_arg_handlers(void); - void dont_advertise_dcbx_all(char *ifname, bool ad); - - #define CLIF_RSP_MSG_OFF 0 -diff --git a/include/lldp_ecp.h b/include/lldp_ecp.h -deleted file mode 100644 -index aa388c6..0000000 ---- a/include/lldp_ecp.h -+++ /dev/null -@@ -1,106 +0,0 @@ --/******************************************************************************* -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Jens Osterkamp -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --#ifndef LLDP_ECP_H --#define LLDP_ECP_H -- --#include -- --#include "lldp_mod.h" --#include "lldp_vdp.h" -- --#define ECP_SUBTYPE 0x0 -- --#define ECP_MAX_RETRIES 3 --#define ECP_SEQUENCE_NR_START 0x0 -- --#define MSECS 1000 --#define SECS (1000 * MSECS) -- --#define ECP_ACK_TIMER_DEFAULT (500 * MSECS) /* 500 ms */ --#define ECP_LOCALCHANGE_TIMEOUT (1 * MSECS) /* 1 ms */ -- --#define ECP_ACK_TIMER_STOPPED (-1) -- --typedef enum { -- ECP_REQUEST = 0, -- ECP_ACK --} ecp_mode; -- --struct ecp_buffer { /* ECP payload buffer */ -- u8 frame[ETH_FRAME_LEN]; /* Payload buffer */ -- u16 frame_len; /* # of bytes of valid data */ -- u8 state; /* Buffer state */ -- u8 localChange; /* Status changed */ -- u8 rcvFrame; /* True if new frame received */ --}; -- --struct ecp { -- struct l2_packet_data *l2; -- int sequence; -- int retries; -- int ackReceived; -- int ackTimer; -- u16 lastSequence; -- u16 seqECPDU; -- struct ecp_buffer rx; /* Receive buffer */ -- struct ecp_buffer tx; /* Transmit buffer */ -- struct agentstats stats; -- char ifname[IFNAMSIZ]; /* Interface name */ --}; -- --struct ecp_hdr { -- u8 oui[3]; -- u8 pad1; -- u16 subtype; -- u8 mode; -- u16 seqnr; --} __attribute__ ((__packed__)); -- --enum { -- ECP_TX_INIT_TRANSMIT, -- ECP_TX_TRANSMIT_ECPDU, -- ECP_TX_WAIT_FOR_ACK, -- ECP_TX_REQUEST_PDU --}; -- --enum { -- ECP_RX_IDLE, -- ECP_RX_INIT_RECEIVE, -- ECP_RX_RECEIVE_WAIT, -- ECP_RX_RECEIVE_ECPDU, -- ECP_RX_SEND_ACK, -- ECP_RX_RESEND_ACK, --}; -- --struct vdp_data; -- --void ecp_somethingChangedLocal(struct vdp_data *, bool); --void ecp_rx_send_ack_frame(struct vdp_data *); -- --int ecp_init(char *); --int ecp_deinit(char *); --#endif /* _ECP_H */ -diff --git a/include/lldp_ecp22.h b/include/lldp_ecp22.h -deleted file mode 100644 -index 50a1b44..0000000 ---- a/include/lldp_ecp22.h -+++ /dev/null -@@ -1,172 +0,0 @@ --/******************************************************************************* -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2013 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --#ifndef LLDP_ECP22_H --#define LLDP_ECP22_H -- --#include -- --#include "lldp_mod.h" --#include "lldp_qbg22.h" -- --enum { /* ECP Receive states */ -- ECP22_RX_BEGIN, -- ECP22_RX_WAIT, -- ECP22_RX_WAIT2, -- ECP22_RX_FIRST, -- ECP22_RX_REC_ECPDU, -- ECP22_RX_NEW_ECPDU, -- ECP22_RX_SEND_ACK --}; --enum { /* ECP Transmit states */ -- ECP22_TX_BEGIN, -- ECP22_TX_INIT, -- ECP22_TX_TXMIT_ECPDU, -- ECP22_TX_WAIT_FORREQ, -- ECP22_TX_WAIT_ONDATA, -- ECP22_TX_ERROR --}; -- --enum { -- ECP22_REQUEST = 0, -- ECP22_ACK --} ecp22_mode; -- --struct ecp22_hdr { /* ECP22 header */ -- u16 ver_op_sub; /* ECP22 version, operation, subtype */ -- u16 seqno; /* ECP22 sequence number */ --} __attribute__ ((__packed__)); -- --/* -- * Define maximum ECP protocol payload length. Leave room for END TLV. -- */ --#define ECP22_MAXPAYLOAD_LEN (ETH_DATA_LEN - sizeof(struct ecp22_hdr) - 2) -- --struct ecp22_buffer { /* ECP payload buffer */ -- unsigned char frame[ETH_FRAME_LEN]; /* Payload buffer */ -- unsigned short frame_len; /* # of bytes of valid data */ -- unsigned char state; /* Buffer state machine */ -- unsigned char ecpdu_received; /* True when packet received */ -- unsigned char ack_received; /* True when packet acknowledged */ -- unsigned char retries; /* # of retries */ -- unsigned short last_seqno; /* Seqno last acknowledged packet */ -- unsigned short seqno; /* Seqno this packet */ -- unsigned long errors; /* # of transmit errors */ --}; -- --struct ecp22_payload_node { /* ECP Payload node */ -- struct packed_tlv *ptlv; /* Pointer to packed TLV to send */ -- unsigned short subtype; /* ECP subtype*/ -- unsigned char mac[ETH_ALEN]; /* Destination MAC address */ -- LIST_ENTRY(ecp22_payload_node) node; --}; -- --/* -- * ECP22 payload data -- */ --typedef LIST_HEAD(ecp22_list, ecp22_payload_node) ecp22_list; -- --struct ecp22_usedlist { /* List of valid ecp_payload_nodes */ -- ecp22_list head; /* ECP payload data free list */ -- struct ecp22_payload_node *last; /* Ptr to last entry in list */ --}; -- --struct ecp22_freelist { /* List of free ecp_payload_nodes */ -- ecp22_list head; /* ECP payload data free list */ -- u16 freecnt; /* # of nodes on freelist */ --}; -- --enum { -- ecp22_maxpayload = 64 --}; -- --struct ecp22 { /* ECP protocol data per interface */ -- struct l2_packet_data *l2; -- char ifname[IFNAMSIZ]; /* Interface name */ -- LIST_ENTRY(ecp22) node; /* Successor */ -- struct ecp22_buffer rx; /* Receive buffer */ -- struct ecp22_buffer tx; /* Transmit buffer */ -- struct agentstats stats; -- struct ecp22_usedlist inuse; /* List of payload data */ -- struct ecp22_freelist isfree; /* List of free payload nodes */ -- unsigned char max_retries; /* Max # of retries (via EVB) */ -- unsigned char max_rte; /* Wait time for ack (via EVB) */ --}; -- --struct ecp22_user_data { /* ECP module data per interface */ -- LIST_HEAD(ecp_head, ecp22) head; --}; -- --/* -- * Function prototypes -- */ --struct lldp_module *ecp22_register(void); --void ecp22_unregister(struct lldp_module *); --void ecp22_stop(char *); --void ecp22_start(char *); -- --/* -- * Functions to set and read ecp header operations field. -- */ --static inline void ecp22_hdr_set_op(struct ecp22_hdr *p, unsigned int op) --{ -- p->ver_op_sub &= 0xf3ff; -- p->ver_op_sub |= (op & 0x3) << 10; --} -- --static inline unsigned int ecp22_hdr_read_op(struct ecp22_hdr *p) --{ -- return (p->ver_op_sub >> 10) & 3; --} -- --/* -- * Functions to set and read ecp header subtype field. -- */ --static inline void ecp22_hdr_set_subtype(struct ecp22_hdr *p, unsigned int sub) --{ -- p->ver_op_sub &= 0xfc00; -- p->ver_op_sub |= sub & 0x3ff; --} -- --static inline unsigned int ecp22_hdr_read_subtype(struct ecp22_hdr *p) --{ -- return p->ver_op_sub & 0x3ff; --} -- --/* -- * Functions to set and read ecp header version field. -- */ --static inline void ecp22_hdr_set_version(struct ecp22_hdr *p, unsigned int ver) --{ -- p->ver_op_sub &= 0xfff; -- p->ver_op_sub |= (ver & 0xf) << 12; --} -- --static inline unsigned int ecp22_hdr_read_version(struct ecp22_hdr *p) --{ -- return (p->ver_op_sub >> 12) & 0xf; --} -- --#endif -diff --git a/include/lldp_evb22.h b/include/lldp_evb22.h -index c5255dc..36fcc13 100644 ---- a/include/lldp_evb22.h -+++ b/include/lldp_evb22.h -@@ -27,7 +27,7 @@ - #define _LLDP_EVB22_H - - #include "lldp_mod.h" --#include "lldp_qbg22.h" -+#include "qbg22.h" - - #define LLDP_MOD_EVB22_SUBTYPE 0xd - #define LLDP_MOD_EVB22_OUI { 0x00, 0x80, 0xc2, LLDP_MOD_EVB22_SUBTYPE } -@@ -38,9 +38,9 @@ enum { /* EVB bit definitions defines */ - EVB_RRCTR = 0x1, /* Bridge reflective relay control */ - EVB_SGID = 0x8, /* Station group ID */ - EVB_RRREQ = 0x4, /* Station reflective relay request */ -- EVB_RRSTAT_YES = 0x2, /* Station reflective relay status TRUE */ -+ EVB_RRSTAT_YES = 0x1, /* Station reflective relay status TRUE */ - EVB_RRSTAT_NO = 0x0, /* Station reflective relay status NO */ -- EVB_RRSTAT_DONT = 0x1, /* Station reflective relay status unknown */ -+ EVB_RRSTAT_DONT = 0x3, /* Station reflective relay status unknown */ - EVB_ROL = 0x20, /* Remote or local indicator */ - EVB_BRIDGE = 0x1, /* EVB Bridge */ - EVB_STATION = 0x2 /* EVB Station */ -diff --git a/include/lldp_qbg22.h b/include/lldp_qbg22.h -deleted file mode 100644 -index 1007bd9..0000000 ---- a/include/lldp_qbg22.h -+++ /dev/null -@@ -1,87 +0,0 @@ --/******************************************************************************* -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2013 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --/* -- * Define IEEE 802.1Qbg module identification numbers and module interface -- * structures which are exchanged between all the qbg modules. -- * -- * Messages are sent from: -- * EVB --> ECP: Max number of retries (R) and retransmit timeout (RTE). -- * -- * EVB --> VDP: Max number of Reinit-keep-Alive (RKA) Resource wait delay (RWD) -- * and groupid support. -- * -- * VDP --> ECP: VSI Information as payload -- * ECP --> VDP: VSI Information as payload -- * -- * This is used in the module notify call back function. -- */ -- --#ifndef LLDP_QBG22_H --#define LLDP_QBG22_H -- --/* -- * Modules Identifications -- */ --#define LLDP_MOD_EVB22 0x80c2 --#define LLDP_MOD_ECP22 0x80c3 --#define LLDP_MOD_VDP22 0x80c4 -- -- --enum { /* Identify data type in union below */ -- EVB22_TO_ECP22 = 1, /* Data from EVB to ECP */ -- EVB22_TO_VDP22 = 2, /* Data from EVB to VDP */ -- ECP22_TO_ULP = 3, /* Data from ECP to VDP, etc */ -- VDP22_TO_ECP22 = 4, /* Data from VDP to ECP */ -- /* ECP22 subtypes */ -- ECP22_VDP = 1, /* VDP protocol */ -- ECP22_PECSP = 2 /* Port extender control and status protocol */ --}; -- --struct evb22_to_ecp22 { /* Notification from EVB to ECP */ -- unsigned char max_retry;/* Max number of retries */ -- unsigned char max_rte; /* Max number of acknowledgement wait */ --}; -- --struct evb22_to_vdp22 { /* Notification from EVB to VDP */ -- unsigned char max_rwd; /* Max number of resource wait delay */ -- unsigned char max_rka; /* Max number of reinit keep alive */ -- unsigned char gpid; /* Support group ids in VDP */ --}; -- --struct ecp22_to_ulp { /* Notification from ECP to VDP, etc */ -- unsigned short len; /* Size of bytestream */ -- void *data; /* Pointer to data */ --}; -- --struct qbg22_imm { /* Intermodule message data structure */ -- int data_type; /* Identifies union data */ -- union { /* Overlay possible data */ -- struct evb22_to_ecp22 a; -- struct evb22_to_vdp22 b; -- struct ecp22_to_ulp c; -- } u; --}; --#endif -diff --git a/include/lldp_qbg_utils.h b/include/lldp_qbg_utils.h -deleted file mode 100644 -index 9f465c4..0000000 ---- a/include/lldp_qbg_utils.h -+++ /dev/null -@@ -1,43 +0,0 @@ --/******************************************************************************* -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2010, 2013 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --/* -- * Header file for small utility functions called throught qbg modules. -- */ -- --#ifndef LLDP_QBG_UTILS_H --#define LLDP_QBG_UTILS_H -- --void hexdump_frame(const char *, char *, const unsigned char *, size_t); --int modules_notify(int, int, char *, void *); -- --/* -- * Required buffer space to display a UUID. -- * VDP_UUID_STRLEN = strlen("fa9b7fff-b0a0-4893-abcd-beef4ff18f8f") -- */ --#define VDP_UUID_STRLEN 36 -- --int vdp_uuid2str(const u8 *, char *, size_t); --#endif -diff --git a/include/lldp_rtnl.h b/include/lldp_rtnl.h -index 76425e6..c21236d 100644 ---- a/include/lldp_rtnl.h -+++ b/include/lldp_rtnl.h -@@ -31,19 +31,8 @@ - #define IFNAMSIZ 16 - #endif - --#include "include/linux/netlink.h" -- --/* -- * Helper functions to construct a netlink message. -- */ --void mynla_nest_end(struct nlmsghdr *, struct nlattr *); --struct nlattr *mynla_nest_start(struct nlmsghdr *, int); --void mynla_put(struct nlmsghdr *, int, size_t, void *); --void mynla_put_u16(struct nlmsghdr *, int, __u16); --void mynla_put_u32(struct nlmsghdr *, int, __u32); -- - int get_operstate(char *ifname); - int set_operstate(char *ifname, __u8 operstate); --int set_linkmode(const char *ifname, __u8 linkmode); -+int set_linkmode(int ifindex, const char *ifname, __u8 linkmode); - - #endif -diff --git a/include/lldp_util.h b/include/lldp_util.h -index ee9e6e6..5767d4e 100644 ---- a/include/lldp_util.h -+++ b/include/lldp_util.h -@@ -142,6 +142,7 @@ int is_autoneg_supported(const char *ifname); - int get_mtu(const char *); - int get_mfs(const char *); - int get_ifflags(const char *); -+int get_ifname(int ifindex, char *ifname); - int get_maucaps(const char *); - int get_mautype(const char *); - int get_ifpflags(const char *); -diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h -deleted file mode 100644 -index 1e2908b..0000000 ---- a/include/lldp_vdp.h -+++ /dev/null -@@ -1,170 +0,0 @@ --/******************************************************************************* -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Jens Osterkamp -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --#ifndef _LLDP_VDP_H --#define _LLDP_VDP_H -- --#include "lldp_mod.h" --#include "lldp_ecp.h" -- --#define LLDP_MOD_VDP (OUI_IEEE_8021Qbg + 1) -- --#define VDP_MODE_PREASSOCIATE 0x0 --#define VDP_MODE_PREASSOCIATE_WITH_RR 0x1 --#define VDP_MODE_ASSOCIATE 0x2 --#define VDP_MODE_DEASSOCIATE 0x3 -- --#define VDP_RESPONSE_SUCCESS 0x0 --#define VDP_RESPONSE_INVALID_FORMAT 0x1 --#define VDP_RESPONSE_INSUFF_RESOURCES 0x2 --#define VDP_RESPONSE_UNUSED_VTID 0x3 --#define VDP_RESPONSE_VTID_VIOLATION 0x4 --#define VDP_RESPONSE_VTID_VER_VIOLATION 0x5 --#define VDP_RESPONSE_OUT_OF_SYNC 0x6 --#define VDP_RESPONSE_UNKNOWN 0xfe --#define VDP_RESPONSE_NO_RESPONSE 0xff -- --extern const char * const vsi_states[]; -- --#define VDP_FILTER_INFO_FORMAT_VID 0x1 --#define VDP_FILTER_INFO_FORMAT_MACVID 0x2 --#define VDP_FILTER_INFO_FORMAT_GROUPVID 0x3 --#define VDP_FILTER_INFO_FORMAT_GROUPMACVID 0x4 -- --#define VDP_TIMER_GRANULARITY (100 * MSECS) /* 100 ms */ --#define VDP_KEEPALIVE_TIMER_DEFAULT (10 * SECS) /* 10s */ --#define VDP_ACK_TIMER_DEFAULT (2 * ECP_ACK_TIMER_DEFAULT * ECP_MAX_RETRIES) --#define VDP_KEEPALIVE_TIMER_STOPPED (-1) --#define VDP_ACK_TIMER_STOPPED (-1) --#define VDP_LOCALCHANGE_TIMEOUT (1 * MSECS) /* 1 ms */ -- --#define VDP_ROLE_STATION 0 --#define VDP_ROLE_BRIDGE 1 -- --enum { -- VSI_UNASSOCIATED = 0, -- VSI_ASSOC_PROCESSING, -- VSI_ASSOCIATED, -- VSI_PREASSOC_PROCESSING, -- VSI_PREASSOCIATED, -- VSI_DEASSOC_PROCESSING, -- VSI_EXIT, --}; -- --struct mac_vlan_p { -- u8 mac[6]; -- u16 vlan; --} __attribute__ ((__packed__)); -- --struct mac_vlan { /* MAC,VLAN entry anchored by profiles */ -- u8 mac[6]; -- u16 vlan; -- u8 qos; /* QOS field */ -- pid_t req_pid; /* PID of requester for this profile */ -- u32 req_seq; /* Seq # of requester for this profile */ -- LIST_ENTRY(mac_vlan) entry; --}; -- --struct tlv_info_vdp { /* VSI information in packet format */ -- u8 oui[3]; -- u8 sub; -- u8 mode; -- u8 response; -- u8 mgrid; -- u8 id[3]; -- u8 version; -- u8 instance[16]; -- u8 format; -- u16 entries; --} __attribute__ ((__packed__)); -- --struct vsi_profile { -- int mode; /* VSI profile association command */ -- int response; /* Response from switch */ -- u8 no_nlmsg; /* Don't send netlink msg on VSI_EXIT */ -- u8 mgrid; /* Profile mgr id */ -- int id; /* Profile id */ -- u8 version; /* Profile id version number */ -- u8 instance[16]; /* Profile UUID */ -- u8 format; /* Format of MAC,VLAN list */ -- u16 entries; /* Number of MAC,VLAN entries in macvid_head */ -- LIST_HEAD(macvid_head, mac_vlan) macvid_head; -- struct port *port; -- int ackTimer; /* VDP ACK timer interval */ -- int ackReceived; /* VDP ACK received for this profile */ -- int keepaliveTimer; /* VDP keepalive timer interval */ -- int state; /* State of VDP state machine for profile */ -- int seqnr; /* Seqnr of ECP packet this profile was sent */ -- bool localChange; /* True when state needs change */ -- bool remoteChange; /* True when switch caused profile change */ -- bool txmit; /* Profile transmitted */ -- LIST_ENTRY(vsi_profile) profile; --}; -- --struct vdp_data { -- char ifname[IFNAMSIZ]; -- u8 enabletx; -- u8 vdpbit_on; /* Enable VDP Protocol */ -- struct ecp ecp; -- struct unpacked_tlv *vdp; -- int role; -- int keepaliveTimer; -- int ackTimer; -- int nroftimers; -- LIST_HEAD(profile_head, vsi_profile) profile_head; -- LIST_ENTRY(vdp_data) entry; --}; -- --struct vdp_user_data { -- LIST_HEAD(vdp_head, vdp_data) head; --}; -- --struct lldp_module *vdp_register(void); --void vdp_unregister(struct lldp_module *); --struct vdp_data *vdp_data(char *); --struct packed_tlv *vdp_gettlv(struct vdp_data *, struct vsi_profile *); --void vdp_vsi_sm_station(struct vsi_profile *); --struct vsi_profile *vdp_add_profile(struct vdp_data *, struct vsi_profile *); --int vdp_remove_profile(struct vsi_profile *); --void vdp_somethingChangedLocal(struct vsi_profile *, bool); --void vdp_update(char *, u8); --void vdp_ifup(char *, struct lldp_agent *); --void vdp_ifdown(char *, struct lldp_agent *); -- --void vdp_ack_profiles(struct vdp_data *, int); --void vdp_advance_sm(struct vdp_data *); --int vdp_indicate(struct vdp_data *, struct unpacked_tlv *); --int vdp_vsis_pending(struct vdp_data *); --int vdp_vsis(char *); --const char *vdp_response2str(int); --void vdp_trace_profile(struct vsi_profile *); --struct vsi_profile *vdp_alloc_profile(void); --void vdp_delete_profile(struct vsi_profile *); --struct vsi_profile *vdp_find_profile(struct vdp_data *, struct vsi_profile *); -- --#define MAC_ADDR_STRLEN 18 -- --#endif /* _LLDP_VDP_H */ -diff --git a/include/lldp_vdp22.h b/include/lldp_vdp22.h -deleted file mode 100644 -index c29b7fe..0000000 ---- a/include/lldp_vdp22.h -+++ /dev/null -@@ -1,62 +0,0 @@ --/******************************************************************************* -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2013 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --/* -- * External interface definition for the ratified standard VDP protocol. -- */ --#ifndef LLDP_VDP22_H --#define LLDP_VDP22_H -- --#include --#include -- --#include "lldp_mod.h" -- --struct vsi22_profile { -- LIST_ENTRY(vsi22_profile) prof22_entry; --}; -- --struct vdp22 { /* Per interface VSI/VDP data */ -- char ifname[IFNAMSIZ]; /* Interface name */ -- unsigned char max_rwd; /* Max number of resource wait delay */ -- unsigned char max_rka; /* Max number of reinit keep alive */ -- unsigned char gpid; /* Supports group ids in VDP */ -- unsigned short input_len; /* Length of input data from ECP */ -- unsigned char input[ETH_DATA_LEN]; /* Input data from ECP */ -- LIST_HEAD(profile22_head, vsi22_profile) prof22_head; -- LIST_ENTRY(vdp22) entry; --}; -- --struct vdp22_user_data { /* Head for all VDP data */ -- LIST_HEAD(vdp22_head, vdp22) head; --}; -- --struct lldp_module *vdp22_register(void); --void vdp22_unregister(struct lldp_module *); --void vdp22_start(const char *); --void vdp22_stop(char *); --int vdp22_query(const char *); -- --#endif -diff --git a/include/lldp_vdp_clif.h b/include/lldp_vdp_clif.h -deleted file mode 100644 -index ab51426..0000000 ---- a/include/lldp_vdp_clif.h -+++ /dev/null -@@ -1,32 +0,0 @@ --/******************************************************************************* -- -- Implementation of VDP according to IEEE 802.1Qbg -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Jens Osterkamp -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --#ifndef _LLDP_VDP_CLIF_H --#define _LLDP_VDP_CLIF_H -- --struct lldp_module *vdp_cli_register(void); -- --#endif -diff --git a/include/lldp_vdp_cmds.h b/include/lldp_vdp_cmds.h -deleted file mode 100644 -index ec0d575..0000000 ---- a/include/lldp_vdp_cmds.h -+++ /dev/null -@@ -1,48 +0,0 @@ --/******************************************************************************* -- -- implementation of VDP according to IEEE 802.1Qbg -- (c) Copyright IBM Corp. 2010 -- -- Author(s): Jens Osterkamp -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --#ifndef _LLDP_VDP_CMDS_H --#define _LLDP_VDP_CMDS_H -- --struct arg_handlers *vdp_get_arg_handlers(); --int vdp_clif_cmd(char *, int, char *, int); -- --enum { -- MODE = 0, -- MGRID, -- TYPEID, -- TYPEIDVERSION, -- INSTANCEID, -- FORMAT, --}; -- --#define VAL_STATION "station" --#define VAL_BRIDGE "bridge" --#define ARG_VDP_MODE "mode" --#define ARG_VDP_ROLE "role" --#define VDP_PREFIX "vdp" --#define VDP_BUF_SIZE 256 -- --#endif -diff --git a/include/lldp_vdpnl.h b/include/lldp_vdpnl.h -deleted file mode 100644 -index d6fdca6..0000000 ---- a/include/lldp_vdpnl.h -+++ /dev/null -@@ -1,64 +0,0 @@ --/******************************************************************************* -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2013 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --/* -- * Definition of the VSI data structure received via netlink interface -- */ --#ifndef LLDP_VDPNL_H --#define LLDP_VDPNL_H -- --#include --#include -- --#define MAX_PAYLOAD 4096 /* Maximum Payload Size */ -- --struct vdpnl_mac { /* MAC-VLAN pair */ -- unsigned short vlan; /* Vlan identifier */ -- unsigned char mac[ETH_ALEN]; /* Mac address */ -- unsigned char qos; /* Quality of service */ --}; -- --struct vdpnl_vsi { /* Data structure for VSI data via netlink */ -- char ifname[IFNAMSIZ]; /* Interface name */ -- int ifindex; /* Index number */ -- unsigned char request; /* VSI request mode */ -- unsigned short response; /* VSI response code */ -- unsigned char vsi_mgrid; -- unsigned char vsi_typeversion; -- unsigned char vsi_uuid[PORT_UUID_MAX]; -- unsigned long vsi_typeid; -- unsigned long req_seq; -- pid_t req_pid; -- int macsz; /* Entries in mac-vlan pair list */ -- struct vdpnl_mac *maclist; /* List of MAC-VLAN pairs */ --}; -- --int vdpnl_recv(unsigned char *, size_t); --int vdpnl_send(struct vdpnl_vsi *); --int vdp_request(struct vdpnl_vsi *); --int vdp22_request(struct vdpnl_vsi *); --int vdp_status(int, struct vdpnl_vsi *); --int event_trigger(struct nlmsghdr *, pid_t); --#endif -diff --git a/include/lldpad_status.h b/include/lldpad_status.h -index 163b5fb..df6e0f7 100644 ---- a/include/lldpad_status.h -+++ b/include/lldpad_status.h -@@ -44,6 +44,7 @@ typedef enum { - cmd_not_capable, - cmd_not_applicable, - cmd_no_access, -+ cmd_agent_not_supported, - } cmd_status; - - #endif /* LLDPAD_STATUS_H */ -diff --git a/include/messages.h b/include/messages.h -index 21e7f1e..d52bdac 100644 ---- a/include/messages.h -+++ b/include/messages.h -@@ -31,6 +31,7 @@ - - extern bool daemonize; - extern int loglvl; -+extern int omit_tstamp; - - void log_message(int loglvl, const char *pFormat, ...) - __attribute__((__format__(__printf__, 2, 3))); -diff --git a/include/qbg22.h b/include/qbg22.h -new file mode 100644 -index 0000000..eb3eb4d ---- /dev/null -+++ b/include/qbg22.h -@@ -0,0 +1,91 @@ -+/******************************************************************************* -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+/* -+ * Define IEEE 802.1Qbg module identification numbers and module interface -+ * structures which are exchanged between all the qbg modules. -+ * -+ * Messages are sent from: -+ * EVB --> ECP: Max number of retries (R) and retransmit timeout (RTE). -+ * -+ * EVB --> VDP: Max number of Reinit-keep-Alive (RKA) Resource wait delay (RWD) -+ * and groupid support. -+ * -+ * VDP --> ECP: VSI Information as payload -+ * ECP --> VDP: VSI Information as payload -+ * -+ * This is used in the module notify call back function. -+ */ -+ -+#ifndef LLDP_QBG22_H -+#define LLDP_QBG22_H -+ -+/* -+ * Modules Identifications -+ */ -+#define LLDP_MOD_EVB22 0x80c2 -+#define LLDP_MOD_ECP22 0x80c3 -+#define LLDP_MOD_VDP22 0x80c4 -+#define LLDP_MOD_VDP22_SUBTYPE 0 -+ -+ -+enum { /* Identify data type in union below */ -+ EVB22_TO_ECP22 = 1, /* Data from EVB to ECP */ -+ EVB22_TO_VDP22 = 2, /* Data from EVB to VDP */ -+ ECP22_TO_ULP = 3, /* Data from ECP to VDP, etc */ -+ VDP22_TO_ECP22 = 4, /* Data from VDP to ECP */ -+ /* ECP22 subtypes */ -+ ECP22_VDP = 1, /* VDP protocol */ -+ ECP22_PECSP = 2 /* Port extender control and status protocol */ -+}; -+ -+struct evb22_to_ecp22 { /* Notification from EVB to ECP */ -+ unsigned char max_retry;/* Max number of retries */ -+ unsigned char max_rte; /* Max number of acknowledgement wait */ -+}; -+ -+struct evb22_to_vdp22 { /* Notification from EVB to VDP */ -+ unsigned char max_retry;/* Max number of retries */ -+ unsigned char max_rte; /* Max number of acknowledgement wait */ -+ unsigned char max_rwd; /* Max number of resource wait delay */ -+ unsigned char max_rka; /* Max number of reinit keep alive */ -+ unsigned char gpid; /* Support group ids in VDP */ -+ unsigned char evbon; /* EVB TLV transmits enabled */ -+}; -+ -+struct ecp22_to_ulp { /* Notification from ECP to VDP, etc */ -+ unsigned short len; /* Size of bytestream */ -+ void *data; /* Pointer to data */ -+}; -+ -+struct qbg22_imm { /* Intermodule message data structure */ -+ int data_type; /* Identifies union data */ -+ union { /* Overlay possible data */ -+ struct evb22_to_ecp22 a; -+ struct evb22_to_vdp22 b; -+ struct ecp22_to_ulp c; -+ } u; -+}; -+#endif -diff --git a/include/qbg_ecp.h b/include/qbg_ecp.h -new file mode 100644 -index 0000000..a67385b ---- /dev/null -+++ b/include/qbg_ecp.h -@@ -0,0 +1,106 @@ -+/******************************************************************************* -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Jens Osterkamp -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+#ifndef QBG_ECP_H -+#define QBG_ECP_H -+ -+#include -+ -+#include "lldp_mod.h" -+#include "qbg_vdp.h" -+ -+#define ECP_SUBTYPE 0x0 -+ -+#define ECP_MAX_RETRIES 3 -+#define ECP_SEQUENCE_NR_START 0x0 -+ -+#define MSECS 1000 -+#define SECS (1000 * MSECS) -+ -+#define ECP_ACK_TIMER_DEFAULT (500 * MSECS) /* 500 ms */ -+#define ECP_LOCALCHANGE_TIMEOUT (1 * MSECS) /* 1 ms */ -+ -+#define ECP_ACK_TIMER_STOPPED (-1) -+ -+typedef enum { -+ ECP_REQUEST = 0, -+ ECP_ACK -+} ecp_mode; -+ -+struct ecp_buffer { /* ECP payload buffer */ -+ u8 frame[ETH_FRAME_LEN]; /* Payload buffer */ -+ u16 frame_len; /* # of bytes of valid data */ -+ u8 state; /* Buffer state */ -+ u8 localChange; /* Status changed */ -+ u8 rcvFrame; /* True if new frame received */ -+}; -+ -+struct ecp { -+ struct l2_packet_data *l2; -+ int sequence; -+ int retries; -+ int ackReceived; -+ int ackTimer; -+ u16 lastSequence; -+ u16 seqECPDU; -+ struct ecp_buffer rx; /* Receive buffer */ -+ struct ecp_buffer tx; /* Transmit buffer */ -+ struct agentstats stats; -+ char ifname[IFNAMSIZ]; /* Interface name */ -+}; -+ -+struct ecp_hdr { -+ u8 oui[3]; -+ u8 pad1; -+ u16 subtype; -+ u8 mode; -+ u16 seqnr; -+} __attribute__ ((__packed__)); -+ -+enum { -+ ECP_TX_INIT_TRANSMIT, -+ ECP_TX_TRANSMIT_ECPDU, -+ ECP_TX_WAIT_FOR_ACK, -+ ECP_TX_REQUEST_PDU -+}; -+ -+enum { -+ ECP_RX_IDLE, -+ ECP_RX_INIT_RECEIVE, -+ ECP_RX_RECEIVE_WAIT, -+ ECP_RX_RECEIVE_ECPDU, -+ ECP_RX_SEND_ACK, -+ ECP_RX_RESEND_ACK, -+}; -+ -+struct vdp_data; -+ -+void ecp_somethingChangedLocal(struct vdp_data *, bool); -+void ecp_rx_send_ack_frame(struct vdp_data *); -+ -+int ecp_init(char *); -+int ecp_deinit(char *); -+#endif /* _ECP_H */ -diff --git a/include/qbg_ecp22.h b/include/qbg_ecp22.h -new file mode 100644 -index 0000000..567f6df ---- /dev/null -+++ b/include/qbg_ecp22.h -@@ -0,0 +1,172 @@ -+/******************************************************************************* -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+#ifndef QBG_ECP22_H -+#define QBG_ECP22_H -+ -+#include -+ -+#include "lldp_mod.h" -+#include "qbg22.h" -+ -+enum { /* ECP Receive states */ -+ ECP22_RX_BEGIN, -+ ECP22_RX_WAIT, -+ ECP22_RX_WAIT2, -+ ECP22_RX_FIRST, -+ ECP22_RX_REC_ECPDU, -+ ECP22_RX_NEW_ECPDU, -+ ECP22_RX_SEND_ACK -+}; -+enum { /* ECP Transmit states */ -+ ECP22_TX_BEGIN, -+ ECP22_TX_INIT, -+ ECP22_TX_TXMIT_ECPDU, -+ ECP22_TX_WAIT_FORREQ, -+ ECP22_TX_WAIT_ONDATA, -+ ECP22_TX_ERROR -+}; -+ -+enum { -+ ECP22_REQUEST = 0, -+ ECP22_ACK -+} ecp22_mode; -+ -+struct ecp22_hdr { /* ECP22 header */ -+ u16 ver_op_sub; /* ECP22 version, operation, subtype */ -+ u16 seqno; /* ECP22 sequence number */ -+} __attribute__ ((__packed__)); -+ -+/* -+ * Define maximum ECP protocol payload length. Leave room for END TLV. -+ */ -+#define ECP22_MAXPAYLOAD_LEN (ETH_DATA_LEN - sizeof(struct ecp22_hdr) - 2) -+ -+struct ecp22_buffer { /* ECP payload buffer */ -+ unsigned char frame[ETH_FRAME_LEN]; /* Payload buffer */ -+ unsigned short frame_len; /* # of bytes of valid data */ -+ unsigned char state; /* Buffer state machine */ -+ unsigned char ecpdu_received; /* True when packet received */ -+ unsigned char ack_received; /* True when packet acknowledged */ -+ unsigned char retries; /* # of retries */ -+ unsigned short last_seqno; /* Seqno last acknowledged packet */ -+ unsigned short seqno; /* Seqno this packet */ -+ unsigned long errors; /* # of transmit errors */ -+}; -+ -+struct ecp22_payload_node { /* ECP Payload node */ -+ struct packed_tlv *ptlv; /* Pointer to packed TLV to send */ -+ unsigned short subtype; /* ECP subtype*/ -+ unsigned char mac[ETH_ALEN]; /* Destination MAC address */ -+ LIST_ENTRY(ecp22_payload_node) node; -+}; -+ -+/* -+ * ECP22 payload data -+ */ -+typedef LIST_HEAD(ecp22_list, ecp22_payload_node) ecp22_list; -+ -+struct ecp22_usedlist { /* List of valid ecp_payload_nodes */ -+ ecp22_list head; /* ECP payload data free list */ -+ struct ecp22_payload_node *last; /* Ptr to last entry in list */ -+}; -+ -+struct ecp22_freelist { /* List of free ecp_payload_nodes */ -+ ecp22_list head; /* ECP payload data free list */ -+ u16 freecnt; /* # of nodes on freelist */ -+}; -+ -+enum { -+ ecp22_maxpayload = 64 -+}; -+ -+struct ecp22 { /* ECP protocol data per interface */ -+ struct l2_packet_data *l2; -+ char ifname[IFNAMSIZ]; /* Interface name */ -+ LIST_ENTRY(ecp22) node; /* Successor */ -+ struct ecp22_buffer rx; /* Receive buffer */ -+ struct ecp22_buffer tx; /* Transmit buffer */ -+ struct agentstats stats; -+ struct ecp22_usedlist inuse; /* List of payload data */ -+ struct ecp22_freelist isfree; /* List of free payload nodes */ -+ unsigned char max_retries; /* Max # of retries (via EVB) */ -+ unsigned char max_rte; /* Wait time for ack (via EVB) */ -+}; -+ -+struct ecp22_user_data { /* ECP module data per interface */ -+ LIST_HEAD(ecp_head, ecp22) head; -+}; -+ -+/* -+ * Function prototypes -+ */ -+struct lldp_module *ecp22_register(void); -+void ecp22_unregister(struct lldp_module *); -+void ecp22_stop(char *); -+void ecp22_start(char *); -+ -+/* -+ * Functions to set and read ecp header operations field. -+ */ -+static inline void ecp22_hdr_set_op(struct ecp22_hdr *p, unsigned int op) -+{ -+ p->ver_op_sub &= 0xf3ff; -+ p->ver_op_sub |= (op & 0x3) << 10; -+} -+ -+static inline unsigned int ecp22_hdr_read_op(struct ecp22_hdr *p) -+{ -+ return (p->ver_op_sub >> 10) & 3; -+} -+ -+/* -+ * Functions to set and read ecp header subtype field. -+ */ -+static inline void ecp22_hdr_set_subtype(struct ecp22_hdr *p, unsigned int sub) -+{ -+ p->ver_op_sub &= 0xfc00; -+ p->ver_op_sub |= sub & 0x3ff; -+} -+ -+static inline unsigned int ecp22_hdr_read_subtype(struct ecp22_hdr *p) -+{ -+ return p->ver_op_sub & 0x3ff; -+} -+ -+/* -+ * Functions to set and read ecp header version field. -+ */ -+static inline void ecp22_hdr_set_version(struct ecp22_hdr *p, unsigned int ver) -+{ -+ p->ver_op_sub &= 0xfff; -+ p->ver_op_sub |= (ver & 0xf) << 12; -+} -+ -+static inline unsigned int ecp22_hdr_read_version(struct ecp22_hdr *p) -+{ -+ return (p->ver_op_sub >> 12) & 0xf; -+} -+ -+#endif -diff --git a/include/qbg_utils.h b/include/qbg_utils.h -new file mode 100644 -index 0000000..6033556 ---- /dev/null -+++ b/include/qbg_utils.h -@@ -0,0 +1,45 @@ -+/******************************************************************************* -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2010, 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+/* -+ * Header file for small utility functions called throught qbg modules. -+ */ -+ -+#ifndef QBG_UTILS_H -+#define QBG_UTILS_H -+ -+void hexdump_frame(const char *, char *, const unsigned char *, size_t); -+int modules_notify(int, int, char *, void *); -+ -+/* -+ * Required buffer space to display a VSI ID (as UUID or other formats). -+ * VDP_UUID_STRLEN = strlen("fa9b7fff-b0a0-4893-abcd-beef4ff18f8f") -+ * or strlen("fa9b:7fff:b0a0:4893:abcd:beef:4ff1:8f8f") -+ */ -+#define VDP_UUID_STRLEN 40 -+ -+/* Convert VSI IDs to strings */ -+int vdp_uuid2str(const unsigned char *, char *, size_t); -+#endif -diff --git a/include/qbg_vdp.h b/include/qbg_vdp.h -new file mode 100644 -index 0000000..e7de693 ---- /dev/null -+++ b/include/qbg_vdp.h -@@ -0,0 +1,170 @@ -+/******************************************************************************* -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Jens Osterkamp -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+#ifndef QBG_VDP_H -+#define QBG_VDP_H -+ -+#include "lldp_mod.h" -+#include "qbg_ecp.h" -+ -+#define LLDP_MOD_VDP (OUI_IEEE_8021Qbg + 1) -+ -+#define VDP_MODE_PREASSOCIATE 0x0 -+#define VDP_MODE_PREASSOCIATE_WITH_RR 0x1 -+#define VDP_MODE_ASSOCIATE 0x2 -+#define VDP_MODE_DEASSOCIATE 0x3 -+ -+#define VDP_RESPONSE_SUCCESS 0x0 -+#define VDP_RESPONSE_INVALID_FORMAT 0x1 -+#define VDP_RESPONSE_INSUFF_RESOURCES 0x2 -+#define VDP_RESPONSE_UNUSED_VTID 0x3 -+#define VDP_RESPONSE_VTID_VIOLATION 0x4 -+#define VDP_RESPONSE_VTID_VER_VIOLATION 0x5 -+#define VDP_RESPONSE_OUT_OF_SYNC 0x6 -+#define VDP_RESPONSE_UNKNOWN 0xfe -+#define VDP_RESPONSE_NO_RESPONSE 0xff -+ -+extern const char * const vsi_states[]; -+ -+#define VDP_FILTER_INFO_FORMAT_VID 0x1 -+#define VDP_FILTER_INFO_FORMAT_MACVID 0x2 -+#define VDP_FILTER_INFO_FORMAT_GROUPVID 0x3 -+#define VDP_FILTER_INFO_FORMAT_GROUPMACVID 0x4 -+ -+#define VDP_TIMER_GRANULARITY (100 * MSECS) /* 100 ms */ -+#define VDP_KEEPALIVE_TIMER_DEFAULT (10 * SECS) /* 10s */ -+#define VDP_ACK_TIMER_DEFAULT (2 * ECP_ACK_TIMER_DEFAULT * ECP_MAX_RETRIES) -+#define VDP_KEEPALIVE_TIMER_STOPPED (-1) -+#define VDP_ACK_TIMER_STOPPED (-1) -+#define VDP_LOCALCHANGE_TIMEOUT (1 * MSECS) /* 1 ms */ -+ -+#define VDP_ROLE_STATION 0 -+#define VDP_ROLE_BRIDGE 1 -+ -+enum { -+ VSI_UNASSOCIATED = 0, -+ VSI_ASSOC_PROCESSING, -+ VSI_ASSOCIATED, -+ VSI_PREASSOC_PROCESSING, -+ VSI_PREASSOCIATED, -+ VSI_DEASSOC_PROCESSING, -+ VSI_EXIT, -+}; -+ -+struct mac_vlan_p { -+ u8 mac[6]; -+ u16 vlan; -+} __attribute__ ((__packed__)); -+ -+struct mac_vlan { /* MAC,VLAN entry anchored by profiles */ -+ u8 mac[6]; -+ u16 vlan; -+ u8 qos; /* QOS field */ -+ pid_t req_pid; /* PID of requester for this profile */ -+ u32 req_seq; /* Seq # of requester for this profile */ -+ LIST_ENTRY(mac_vlan) entry; -+}; -+ -+struct tlv_info_vdp { /* VSI information in packet format */ -+ u8 oui[3]; -+ u8 sub; -+ u8 mode; -+ u8 response; -+ u8 mgrid; -+ u8 id[3]; -+ u8 version; -+ u8 instance[16]; -+ u8 format; -+ u16 entries; -+} __attribute__ ((__packed__)); -+ -+struct vsi_profile { -+ int mode; /* VSI profile association command */ -+ int response; /* Response from switch */ -+ u8 no_nlmsg; /* Don't send netlink msg on VSI_EXIT */ -+ u8 mgrid; /* Profile mgr id */ -+ int id; /* Profile id */ -+ u8 version; /* Profile id version number */ -+ u8 instance[16]; /* Profile UUID */ -+ u8 format; /* Format of MAC,VLAN list */ -+ u16 entries; /* Number of MAC,VLAN entries in macvid_head */ -+ LIST_HEAD(macvid_head, mac_vlan) macvid_head; -+ struct port *port; -+ int ackTimer; /* VDP ACK timer interval */ -+ int ackReceived; /* VDP ACK received for this profile */ -+ int keepaliveTimer; /* VDP keepalive timer interval */ -+ int state; /* State of VDP state machine for profile */ -+ int seqnr; /* Seqnr of ECP packet this profile was sent */ -+ bool localChange; /* True when state needs change */ -+ bool remoteChange; /* True when switch caused profile change */ -+ bool txmit; /* Profile transmitted */ -+ LIST_ENTRY(vsi_profile) profile; -+}; -+ -+struct vdp_data { -+ char ifname[IFNAMSIZ]; -+ u8 enabletx; -+ u8 vdpbit_on; /* Enable VDP Protocol */ -+ struct ecp ecp; -+ struct unpacked_tlv *vdp; -+ int role; -+ int keepaliveTimer; -+ int ackTimer; -+ int nroftimers; -+ LIST_HEAD(profile_head, vsi_profile) profile_head; -+ LIST_ENTRY(vdp_data) entry; -+}; -+ -+struct vdp_user_data { -+ LIST_HEAD(vdp_head, vdp_data) head; -+}; -+ -+struct lldp_module *vdp_register(void); -+void vdp_unregister(struct lldp_module *); -+struct vdp_data *vdp_data(char *); -+struct packed_tlv *vdp_gettlv(struct vdp_data *, struct vsi_profile *); -+void vdp_vsi_sm_station(struct vsi_profile *); -+struct vsi_profile *vdp_add_profile(struct vdp_data *, struct vsi_profile *); -+int vdp_remove_profile(struct vsi_profile *); -+void vdp_somethingChangedLocal(struct vsi_profile *, bool); -+void vdp_update(char *, u8); -+void vdp_ifup(char *, struct lldp_agent *); -+void vdp_ifdown(char *, struct lldp_agent *); -+ -+void vdp_ack_profiles(struct vdp_data *, int); -+void vdp_advance_sm(struct vdp_data *); -+int vdp_indicate(struct vdp_data *, struct unpacked_tlv *); -+int vdp_vsis_pending(struct vdp_data *); -+int vdp_vsis(char *); -+const char *vdp_response2str(int); -+void vdp_trace_profile(struct vsi_profile *); -+struct vsi_profile *vdp_alloc_profile(void); -+void vdp_delete_profile(struct vsi_profile *); -+struct vsi_profile *vdp_find_profile(struct vdp_data *, struct vsi_profile *); -+ -+#define MAC_ADDR_STRLEN 18 -+ -+#endif /* _LLDP_VDP_H */ -diff --git a/include/qbg_vdp22.h b/include/qbg_vdp22.h -new file mode 100644 -index 0000000..b345602 ---- /dev/null -+++ b/include/qbg_vdp22.h -@@ -0,0 +1,210 @@ -+/******************************************************************************* -+ -+ Implementation of VDP protocol for IEEE 802.1 Qbg Ratified Standard -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+#ifndef QBG_VDP22_H -+#define QBG_VDP22_H -+ -+/* -+ * Defintion of VDP22 data structures: -+ * For IEEE 802.1Qbg ratified standard the Virtual Station Information (VSI) -+ * in the VDP22 protocol is maintained as a queue with one entry per interface -+ * supporting VDP22. -+ * Each interface is the anchor for a list of active VSI manager identifiers. -+ * All VSIs with the same -+ * - manager-id -+ * - type-id and type version -+ * - VSI format type and VSI id -+ * - filter info format -+ * are grouped into one entry. This means if two VSIs differ only in the -+ * filter info format (for example), two seperate VSI list elements will be -+ * allocated and queued in the VSI queue of that interface name. -+ * -+ * Each VSI node maintains the VDP22 state machine for that association. -+ * -+ * Supported operations: -+ * - Find a VSI entry given the search criterias: -+ * manager-id, type-id, type-version, VSI-format, VSI-ID and filter-info -+ * (data and format). -+ * - Add new filter data to a matching VSI entry (and filter not already -+ * active). -+ * - Remove filter data from a matching VSI entry. -+ * - Add a new VSI node when no VSI match is found. -+ * - Remove a VSI node when no filter entry is active anymore. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+enum vdp22_role { /* State for VDP22 bridge processing */ -+ VDP22_BRIDGE = 1, /* Bridge role */ -+ VDP22_STATION /* State role */ -+}; -+ -+enum vdp22_cmdresp { /* VDP22 Protocol command responses */ -+ VDP22_RESP_SUCCESS = 0, /* Success */ -+ VDP22_RESP_INVALID_FORMAT = 1, -+ VDP22_RESP_NO_RESOURCES = 2, -+ VDP22_RESP_NO_VSIMGR = 3, /* No contact to VSI manager */ -+ VDP22_RESP_OTHER = 4, /* Other reasons */ -+ VDP22_RESP_NOADDR = 5, /* Invalid VID, MAC, GROUP etc */ -+ VDP22_RESP_DEASSOC = 252, /* Deassoc response */ -+ VDP22_RESP_TIMEOUT = 253, /* Timeout response */ -+ VDP22_RESP_KEEP = 254, /* Keep response */ -+ VDP22_RESP_NONE = 255 /* No response returned so far */ -+}; -+ -+enum { -+ VDP22_MGRIDSZ = 16, /* Size of manager identifier */ -+ VDP22_IDSZ = 16 /* Size of vsi identifier */ -+}; -+ -+struct vsi_origin { /* Originator of VSI request */ -+ pid_t req_pid; /* PID of requester for VSI */ -+ unsigned long req_seq; /* Seq # of requester for VSI */ -+}; -+ -+/* -+ * Generic filter data. Some field are unused, this depends -+ * on the filter info format value (see enum above). -+ */ -+struct fid22 { /* Filter data: GROUP,MAC,VLAN entry */ -+ unsigned long grpid; /* Group identifier */ -+ unsigned char mac[ETH_ALEN]; /* MAC address */ -+ unsigned short vlan; /* VLAN idenfier */ -+ struct vsi_origin requestor; -+}; -+ -+/* -+ * VSI information. One node per matching entry (same mgrid, type_id, type_ver, -+ * id_fmt, id and fif). Filter data can be added and removed. -+ */ -+enum vsi22_flags { /* Flags (or'ed in) */ -+ VDP22_BUSY = 1, /* This node is under work */ -+ VDP22_DELETE_ME = 2, /* Deallocate this node */ -+ VDP22_RETURN_VID = 4, /* Return wildcard vlan id */ -+ VDP22_NOTIFY = 8, /* Send netlink message to requestor */ -+ VDP22_NLCMD = 16 /* Netlink command pending */ -+}; -+ -+struct vdp22smi { /* Data structure for VDP22 state machine */ -+ int state; /* State of VDP state machine for VSI */ -+ bool kato; /* VSI KA ACK timeout hit for this VSI */ -+ bool ackreceived; /* VSI ACK received for this VSI */ -+ bool acktimeout; /* VSI ACK timeout hit for this VSI */ -+ bool localchg; /* True when state needs change */ -+ bool deassoc; /* True when deassoc received from switch */ -+ bool txmit; /* True when packed TLV transmitted */ -+ bool resp_ok; /* True when acked TLV received and match ok */ -+ int txmit_error; /* != 0 error code from transmit via ECP */ -+}; -+ -+struct vsi22 { -+ LIST_ENTRY(vsi22) node; /* Node element */ -+ unsigned char mgrid[VDP22_MGRIDSZ]; /* Manager identifier */ -+ unsigned char cc_vsi_mode; /* currently confirmed VSI mode */ -+ unsigned char vsi_mode; /* VSI mode: ASSOC, PREASSOC, etc */ -+ unsigned char resp_vsi_mode; /* Responsed VSI mode: ASSOC, etc */ -+ unsigned char status; /* Status, Request/Response */ -+ unsigned char hints; /* Indicate migration/suspend */ -+ unsigned long type_id; /* Type identifier */ -+ unsigned char type_ver; /* Type version */ -+ unsigned char vsi_fmt; /* Format of VSI identifier */ -+ unsigned char vsi[VDP22_IDSZ]; /* VSI identifier */ -+ unsigned char fif; /* Filter info format */ -+ unsigned short no_fdata; /* Entries in filter data */ -+ struct fid22 *fdata; /* Filter data variable length */ -+ struct vdp22 *vdp; /* Back pointer to VDP head */ -+ unsigned long flags; /* Flags, see above */ -+ struct vdp22smi smi; /* State machine information */ -+}; -+ -+struct vdp22 { /* Per interface VSI/VDP data */ -+ LIST_ENTRY(vdp22) node; /* Node element */ -+ char ifname[IFNAMSIZ + 1]; /* Interface name */ -+ unsigned char ecp_retries; /* # of ECP module retries */ -+ unsigned char ecp_rte; /* ECP module retry timeout exponent */ -+ unsigned char vdp_rwd; /* Resource wait delay exponent */ -+ unsigned char vdp_rka; /* Reinit keep alive exponent */ -+ unsigned char gpid; /* Supports group ids in VDP */ -+ unsigned char myrole; /* Station or bridge role */ -+ unsigned char evbon; /* True on EVB22 txmit enabled */ -+ unsigned char br_down; /* True when bridge down */ -+ unsigned short input_len; /* Length of input data from ECP */ -+ unsigned char input[ETH_DATA_LEN]; /* Input data from ECP */ -+ LIST_HEAD(vsi22_head, vsi22) vsi22_que; /* Active VSIs */ -+}; -+ -+struct vdp22_user_data { /* Head for all VDP data */ -+ LIST_HEAD(vdp22_head, vdp22) head; -+}; -+ -+struct lldp_module *vdp22_register(void); -+void vdp22_unregister(struct lldp_module *); -+void vdp22_start(const char *, int); -+void vdp22_showvsi(struct vsi22 *p); -+void vdp22_stop(char *); -+int vdp22_from_ecp22(struct vdp22 *); -+int vdp22_query(const char *); -+int vdp22_addreq(struct vsi22 *, struct vdp22 *); -+int vdp22_nlback(struct vsi22 *); -+int vdp22_clntback(struct vsi22 *); -+struct vsi22 *vdp22_copy_vsi(struct vsi22 *); -+void vdp22_listdel_vsi(struct vsi22 *); -+int vdp22br_resources(struct vsi22 *, int *); -+int vdp22_info(const char *); -+void vdp22_stop_timers(struct vsi22 *); -+int vdp22_start_localchange_timer(struct vsi22 *); -+ -+/* -+ * Functions to get and set vlan identifier and qos. -+ */ -+static inline unsigned short vdp22_get_ps(unsigned short x) -+{ -+ return (x >> 15) & 0x1; -+} -+ -+static inline unsigned short vdp22_get_qos(unsigned short x) -+{ -+ return (x >> 12) & 0xf; -+} -+ -+static inline unsigned short vdp22_set_qos(unsigned short x) -+{ -+ return (x & 0xf) << 12; -+} -+ -+static inline unsigned short vdp22_get_vlanid(unsigned short x) -+{ -+ return x & 0xfff; -+} -+ -+static inline unsigned short vdp22_set_vlanid(unsigned short x) -+{ -+ return (x & 0xfff); -+} -+#endif -diff --git a/include/qbg_vdp22_clif.h b/include/qbg_vdp22_clif.h -new file mode 100644 -index 0000000..20330b8 ---- /dev/null -+++ b/include/qbg_vdp22_clif.h -@@ -0,0 +1,55 @@ -+/******************************************************************************* -+ -+ Implementation of VDP 22 (ratified standard) according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2014 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+/* -+ * Client command interface for vdp22 module. -+ */ -+ -+#ifndef QBG_VDP22_CLIF_H -+#define QBG_VDP22_CLIF_H -+typedef enum { -+ cmd_getstats, -+ cmd_gettlv, -+ cmd_settlv, -+ cmd_get_lldp, -+ cmd_set_lldp, -+ cmd_quit, -+ cmd_license, -+ cmd_version, -+ cmd_help, -+ cmd_ping, -+ cmd_nop -+} vdp22_cmd; -+ -+typedef enum { -+ op_local = 0x1, -+ op_neighbor = 0x2, -+ op_arg = 0x4, -+ op_argval = 0x8, -+ op_config = 0x10, -+ op_delete = 0x20, -+ op_key = 0x40 -+} vdp22_op; -+#endif -diff --git a/include/qbg_vdp22_cmds.h b/include/qbg_vdp22_cmds.h -new file mode 100644 -index 0000000..8cfd32a ---- /dev/null -+++ b/include/qbg_vdp22_cmds.h -@@ -0,0 +1,40 @@ -+/******************************************************************************* -+ -+ Implementation of VDP 22 (ratified standard) according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2014 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+/* -+ * Command interface for vdp22 module. -+ */ -+ -+#ifndef QBG_VDP22_CMDS_H -+#define QBG_VDP22_CMDS_H -+ -+struct arg_handlers *vdp22_arg_handlers(); -+int vdp22_clif_cmd(void *, struct sockaddr_un *, socklen_t, char *, int, char *, -+ int); -+#define VAL_STATION "station" -+#define VAL_BRIDGE "bridge" -+#define ARG_VDP22_VSI "vsi" -+ -+#endif -diff --git a/include/qbg_vdp22def.h b/include/qbg_vdp22def.h -new file mode 100644 -index 0000000..52f4502 ---- /dev/null -+++ b/include/qbg_vdp22def.h -@@ -0,0 +1,75 @@ -+/******************************************************************************* -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+/* -+ * External interface definition for the ratified standard VDP protocol. -+ */ -+#ifndef QBG_VDP22DEF_H -+#define QBG_VDP22DEF_H -+ -+/* -+ * Define VDP22 filter formats. -+ */ -+enum vdp22_ffmt { /* Format of filter information */ -+ VDP22_FFMT_VID = 1, /* Vlan Identifier */ -+ VDP22_FFMT_MACVID, /* MAC address and Vlan Identifier */ -+ VDP22_FFMT_GROUPVID, /* Group and Vlan Identifier */ -+ VDP22_FFMT_GROUPMACVID /* Group, MAC and Vlan Identifier */ -+}; -+ -+/* -+ * Define VDP22 VSI Profile modes. -+ */ -+enum vdp22_modes { -+ VDP22_ENDTLV = 0, -+ VDP22_PREASSOC = 1, -+ VDP22_PREASSOC_WITH_RR, -+ VDP22_ASSOC, -+ VDP22_DEASSOC, -+ VDP22_MGRID, -+ VDP22_OUI = 0x7f -+}; -+ -+/* -+ * Define VDP22 VSI identifier format -+ */ -+enum vdp22_vsiid_fmt { -+ VDP22_ID_IP4 = 1, /* VSI ID is IPv4 address */ -+ VDP22_ID_IP6, /* VSI ID is IPv6 address */ -+ VDP22_ID_MAC, /* VSI ID is IEEE 802 MAC address */ -+ VDP22_ID_LOCAL, /* VSI ID is locally defined */ -+ VDP22_ID_UUID /* VSI ID is RFC4122 UUID */ -+}; -+ -+ -+/* -+ * Define VDP22 Migiration hints -+ */ -+enum vdp22_migration_hints { -+ VDP22_MIGTO = 16, /* M-bit migrate to hint */ -+ VDP22_MIGFROM = 32 /* S-bit migrate from hint */ -+}; -+ -+#endif -diff --git a/include/qbg_vdp_clif.h b/include/qbg_vdp_clif.h -new file mode 100644 -index 0000000..e4f9f78 ---- /dev/null -+++ b/include/qbg_vdp_clif.h -@@ -0,0 +1,32 @@ -+/******************************************************************************* -+ -+ Implementation of VDP according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Jens Osterkamp -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+#ifndef QBG_VDP_CLIF_H -+#define QBG_VDP_CLIF_H -+ -+struct lldp_module *vdp_cli_register(void); -+ -+#endif -diff --git a/include/qbg_vdp_cmds.h b/include/qbg_vdp_cmds.h -new file mode 100644 -index 0000000..2bbcb1c ---- /dev/null -+++ b/include/qbg_vdp_cmds.h -@@ -0,0 +1,48 @@ -+/******************************************************************************* -+ -+ implementation of VDP according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2010 -+ -+ Author(s): Jens Osterkamp -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+#ifndef QBG_VDP_CMDS_H -+#define QBG_VDP_CMDS_H -+ -+struct arg_handlers *vdp_get_arg_handlers(); -+int vdp_clif_cmd(char *, int, char *, int); -+ -+enum { -+ MODE = 0, -+ MGRID, -+ TYPEID, -+ TYPEIDVERSION, -+ INSTANCEID, -+ FORMAT, -+}; -+ -+#define VAL_STATION "station" -+#define VAL_BRIDGE "bridge" -+#define ARG_VDP_MODE "mode" -+#define ARG_VDP_ROLE "role" -+#define VDP_PREFIX "vdp" -+#define VDP_BUF_SIZE 256 -+ -+#endif -diff --git a/include/qbg_vdpnl.h b/include/qbg_vdpnl.h -new file mode 100644 -index 0000000..7b26bc7 ---- /dev/null -+++ b/include/qbg_vdpnl.h -@@ -0,0 +1,81 @@ -+/******************************************************************************* -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+/* -+ * Definition of the VSI data structure received via netlink interface -+ */ -+#ifndef QBG_VDPNL_H -+#define QBG_VDPNL_H -+ -+#include -+#include -+ -+#define MAX_PAYLOAD 4096 /* Maximum Payload Size */ -+ -+enum { -+ vdpnl_nlf1 = 1, /* Netlink message format 1 (draft 0.2) */ -+ vdpnl_nlf2 /* Netlink message format 2 (ratified) */ -+}; -+ -+struct vdpnl_mac { /* MAC-VLAN pair */ -+ unsigned short vlan; /* Vlan identifier */ -+ unsigned char mac[ETH_ALEN]; /* Mac address */ -+ unsigned char qos; /* Quality of service */ -+ unsigned char changed; /* Vlan changed by switch */ -+ unsigned long gpid; /* Group identifer */ -+}; -+ -+struct vdpnl_vsi { /* Data structure for VSI data via netlink */ -+ char ifname[IFNAMSIZ + 1]; /* Interface name */ -+ int ifindex; /* Index number */ -+ int vf; /* Virtual function number */ -+ unsigned char hints; /* VSI request mode migrition hints */ -+ unsigned char request; /* VSI request mode */ -+ unsigned short response; /* VSI response code */ -+ unsigned char vsi_mgrid; -+ unsigned char vsi_typeversion; -+ unsigned char vsi_idfmt; -+ unsigned char vsi_uuid[PORT_UUID_MAX]; -+ unsigned char vsi_mgrid2[PORT_UUID_MAX]; -+ unsigned char nl_version; /* Netlink message format version */ -+ unsigned long vsi_typeid; -+ unsigned long req_seq; -+ pid_t req_pid; -+ unsigned char filter_fmt; /* Filter format type */ -+ int macsz; /* Entries in mac-vlan pair list */ -+ struct vdpnl_mac *maclist; /* List of MAC-VLAN pairs */ -+}; -+ -+int vdpnl_recv(unsigned char *, size_t); -+int vdpnl_send(struct vdpnl_vsi *); -+int vdp_request(struct vdpnl_vsi *); -+int vdp22_request(struct vdpnl_vsi *, int); -+int vdp_status(int, struct vdpnl_vsi *); -+int vdp22_status(int, struct vdpnl_vsi *, int); -+int event_trigger(struct nlmsghdr *, pid_t); -+int vdp_str2vdpnl(char *, struct vdpnl_vsi *, char *); -+int vdp_vdpnl2str(struct vdpnl_vsi *, char *, size_t); -+int vdp22_sendevent(struct vdpnl_vsi *); -+#endif -diff --git a/lldp/agent.c b/lldp/agent.c -index 2e85aa5..4bc5394 100644 ---- a/lldp/agent.c -+++ b/lldp/agent.c -@@ -51,12 +51,10 @@ static const char *agent_sections[AGENT_MAX] = { - struct lldp_agent * - lldp_agent_find_by_type(const char *ifname, enum agent_type type) - { -- struct port *port; -+ struct port *port = port_find_by_ifindex(get_ifidx(ifname)); - struct lldp_agent *agent; - -- port = port_find_by_name(ifname); -- -- if (port == NULL) -+ if (!port) - return NULL; - - LIST_FOREACH(agent, &port->agent_head, entry) { -@@ -109,12 +107,10 @@ void lldp_init_agent(struct port *port, struct lldp_agent *agent, int type) - int lldp_add_agent(const char *ifname, enum agent_type type) - { - int count; -- struct port *port; -+ struct port *port = port_find_by_ifindex(get_ifidx(ifname)); - struct lldp_agent *agent, *newagent; - -- port = port_find_by_name(ifname); -- -- if (port == NULL) -+ if (!port) - return -1; - - /* check if lldp_agents for this if already exist */ -@@ -123,17 +119,15 @@ int lldp_add_agent(const char *ifname, enum agent_type type) - count++; - if (agent->type != type) - continue; -- else -- return -1; -+ return -1; - } - - /* if not, create one and initialize it */ -- LLDPAD_DBG("%s(%i): creating new agent for port %s.\n", __func__, -- __LINE__, ifname); -- newagent = (struct lldp_agent *)malloc(sizeof(struct lldp_agent)); -- if (newagent == NULL) { -- LLDPAD_DBG("%s(%i): creation of new agent failed !.\n", -- __func__, __LINE__); -+ LLDPAD_DBG("%s: creating new agent for port %s.\n", __func__, -+ ifname); -+ newagent = malloc(sizeof(*newagent)); -+ if (!newagent) { -+ LLDPAD_DBG("%s: creation of new agent failed !.\n", __func__); - return -1; - } - -diff --git a/lldp/l2_packet.h b/lldp/l2_packet.h -index 737ae54..b82b894 100644 ---- a/lldp/l2_packet.h -+++ b/lldp/l2_packet.h -@@ -40,7 +40,7 @@ - #define ETH_P_LLDP 0x88cc - - #define ETH_P_ECP 0x88b7 /* Draft 0.2 */ --#define ETH_P_ECP22 0x8890 /* Ratified standard */ -+#define ETH_P_ECP22 0x8940 /* Ratified standard */ - - #ifndef ETH_MIN_DATA_LEN - #define ETH_MIN_DATA_LEN (ETH_ZLEN - ETH_HLEN) -diff --git a/lldp/l2_packet_linux.c b/lldp/l2_packet_linux.c -index a5fe8bf..08f1e55 100644 ---- a/lldp/l2_packet_linux.c -+++ b/lldp/l2_packet_linux.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include "eloop.h" - #include "ports.h" - #include "messages.h" -@@ -144,8 +145,9 @@ static void l2_packet_receive(int sock, void *eloop_ctx, UNUSED void *sock_ctx) - &fromlen); - - if (res < 0) { -- LLDPAD_INFO("receive ERROR = %d\n", res); -- perror("l2_packet_receive - recvfrom"); -+ LLDPAD_INFO("receive if %s ERROR = %d\n", l2->ifname, errno); -+ if (errno != ENETDOWN) -+ perror("l2_packet_receive - recvfrom"); - return; - } - -diff --git a/lldp/ports.c b/lldp/ports.c -index 0652ce8..3bd6a2a 100644 ---- a/lldp/ports.c -+++ b/lldp/ports.c -@@ -124,56 +124,43 @@ int get_lldp_agent_admin(const char *ifname, int type) - - void set_lldp_agent_admin(const char *ifname, int type, int admin) - { -- struct port *port = NULL; -+ struct port *port; - struct lldp_agent *agent; -- int all = 0; -- int tmp; -+ int ifindex = get_ifidx(ifname); - -- all = !strlen(ifname); -+ if (!ifindex) -+ return; - -- port = porthead; -- while (port != NULL) { -- if (all || !strncmp(ifname, port->ifname, IFNAMSIZ)) { -- /* don't change a port which has an explicit setting -- * on a global setting change -- */ -- if (all && (!get_config_setting(port->ifname, -- type, -- ARG_ADMINSTATUS, -- (void *)&tmp, -- CONFIG_TYPE_INT))) { -- port = port->next; -- continue; -- } -+ for (port = porthead; port; port = port->next) { -+ if (ifindex == port->ifindex) -+ break; -+ } - -- agent = lldp_agent_find_by_type(port->ifname, type); -- if (!agent) { -- port = port->next; -- continue; -- } -+ if (!port) -+ return; - -- if (agent->adminStatus != admin) { -- agent->adminStatus = admin; -- somethingChangedLocal(ifname, type); -- run_tx_sm(port, agent); -- run_rx_sm(port, agent); -- } -+ agent = lldp_agent_find_by_type(port->ifname, type); -+ if (!agent) -+ return; - -- if (!all) -- break; -- } -- port = port->next; -+ /* Set ifname with ifindex reported ifname */ -+ if (strncmp(port->ifname, ifname, IFNAMSIZ) != 0) -+ memcpy(port->ifname, ifname, IFNAMSIZ); -+ -+ if (agent->adminStatus != admin) { -+ agent->adminStatus = admin; -+ somethingChangedLocal(port->ifname, type); -+ run_tx_sm(port, agent); -+ run_rx_sm(port, agent); - } - } - - void set_lldp_port_enable(const char *ifname, int enable) - { -- struct port *port = NULL; -+ struct port *port = port_find_by_ifindex(get_ifidx(ifname)); - struct lldp_agent *agent = NULL; - -- port = port_find_by_name(ifname); -- -- if (port == NULL) -+ if (!port) - return; - - port->portEnabled = (u8)enable; -@@ -192,9 +179,9 @@ void set_lldp_port_enable(const char *ifname, int enable) - - void set_port_oper_delay(const char *ifname) - { -- struct port *port = port_find_by_name(ifname); -+ struct port *port = port_find_by_ifindex(get_ifidx(ifname)); - -- if (port == NULL) -+ if (!port) - return; - - port->dormantDelay = DORMANT_DELAY; -@@ -204,11 +191,9 @@ void set_port_oper_delay(const char *ifname) - - int set_port_hw_resetting(const char *ifname, int resetting) - { -- struct port *port = NULL; -+ struct port *port = port_find_by_ifindex(get_ifidx(ifname)); - -- port = port_find_by_name(ifname); -- -- if (port == NULL) -+ if (!port) - return -1; - - port->hw_resetting = (u8)resetting; -@@ -218,22 +203,18 @@ int set_port_hw_resetting(const char *ifname, int resetting) - - int get_port_hw_resetting(const char *ifname) - { -- struct port *port = NULL; -- -- port = port_find_by_name(ifname); -+ struct port *port = port_find_by_ifindex(get_ifidx(ifname)); - - if (port) - return port->hw_resetting; -- else -- return 0; -+ -+ return 0; - } - - int reinit_port(const char *ifname) - { -+ struct port *port = port_find_by_ifindex(get_ifidx(ifname)); - struct lldp_agent *agent; -- struct port *port; -- -- port = port_find_by_name(ifname); - - if (!port) - return -1; -@@ -268,29 +249,23 @@ int reinit_port(const char *ifname) - return 0; - } - --struct port *add_port(const char *ifname) -+struct port *add_port(int ifindex, const char *ifname) - { - struct port *newport; - -- newport = porthead; -- while (newport != NULL) { -- if (!strncmp(ifname, newport->ifname, IFNAMSIZ)) -- return 0; -- newport = newport->next; -- } -+ for (newport = porthead; newport; newport = newport->next) -+ if (ifindex == newport->ifindex) -+ return NULL; - -- newport = (struct port *)malloc(sizeof(struct port)); -- if (newport == NULL) { -+ newport = malloc(sizeof(*newport)); -+ if (!newport) { - LLDPAD_DBG("new port malloc failed\n"); - goto fail; - } -- memset(newport,0,sizeof(struct port)); -+ memset(newport, 0, sizeof(*newport)); -+ newport->ifindex = ifindex; - newport->next = NULL; -- newport->ifname = strdup(ifname); -- if (newport->ifname == NULL) { -- LLDPAD_DBG("new port name malloc failed\n"); -- goto fail; -- } -+ strncpy(newport->ifname, ifname, IFNAMSIZ); - - newport->bond_master = is_bond(ifname); - /* Initialize relevant port variables */ -@@ -318,16 +293,14 @@ struct port *add_port(const char *ifname) - return newport; - - fail: -- if(newport) { -- if(newport->ifname) -- free(newport->ifname); -+ if (newport) - free(newport); -- } - return NULL; - } - --int remove_port(char *ifname) -+int remove_port(const char *ifname) - { -+ int ifindex = get_ifidx(ifname); - struct port *port; /* Pointer to port to remove */ - struct port *parent = NULL; /* Pointer to previous on port stack */ - struct lldp_agent *agent; -@@ -348,7 +321,7 @@ int remove_port(char *ifname) - LLDPAD_DBG("In %s: Found port %s\n", __func__, port->ifname); - - /* Set linkmode to off */ -- set_linkmode(ifname, 0); -+ set_linkmode(ifindex, port->ifname, 0); - - /* Close down the socket */ - l2_packet_deinit(port->l2); -@@ -394,9 +367,6 @@ int remove_port(char *ifname) - else - return -1; - -- if (port->ifname) -- free(port->ifname); -- - free(port); - - return 0; -diff --git a/lldp/ports.h b/lldp/ports.h -index 2aa15c9..21280e0 100644 ---- a/lldp/ports.h -+++ b/lldp/ports.h -@@ -76,7 +76,8 @@ enum portEnableStatus { - - /* lldp port specific structure */ - struct port { -- char *ifname; -+ struct port *next; -+ int ifindex; - u8 hw_resetting; - u8 portEnabled; - u8 prevPortEnabled; -@@ -87,8 +88,7 @@ struct port { - - LIST_HEAD(agent_head, lldp_agent) agent_head; - struct l2_packet_data *l2; -- -- struct port *next; -+ char ifname[IFNAMSIZ]; - }; - - extern struct port *porthead; -@@ -96,8 +96,8 @@ extern struct port *porthead; - #ifdef __cplusplus - extern "C" { - #endif --struct port *add_port(const char *); --int remove_port(char *); -+struct port *add_port(int ifindex, const char *); -+int remove_port(const char *); - #ifdef __cplusplus - } - #endif -@@ -118,15 +118,13 @@ void set_port_oper_delay(const char *ifname); - int reinit_port(const char *ifname); - void set_agent_oper_delay(const char *ifname, int type); - --static inline struct port *port_find_by_name(const char *ifname) -+static inline struct port *port_find_by_ifindex(int ifindex) - { - struct port *port = porthead; - -- while (port) { -- if (!strncmp(ifname, port->ifname, IFNAMSIZ)) -+ for (port = porthead; port; port = port->next) -+ if (ifindex == port->ifindex) - return port; -- port = port->next; -- } - return NULL; - } - -diff --git a/lldp/tx.c b/lldp/tx.c -index 67933a7..69c1a1a 100644 ---- a/lldp/tx.c -+++ b/lldp/tx.c -@@ -118,8 +118,6 @@ void txInitializeLLDP(struct lldp_agent *agent) - } - - agent->tx.state = TX_LLDP_INITIALIZE; -- agent->rx.state = LLDP_WAIT_PORT_OPERATIONAL; -- - agent->tx.localChange = false; - agent->stats.statsFramesOutTotal = 0; - agent->timers.reinitDelay = REINIT_DELAY; -diff --git a/lldp_8021qaz.c b/lldp_8021qaz.c -index b3da01b..094676d 100644 ---- a/lldp_8021qaz.c -+++ b/lldp_8021qaz.c -@@ -419,12 +419,12 @@ inline void set_prio_map(u32 *prio_map, u8 prio, int tc) - * - * Returns 0 on success, error value otherwise. - */ --static int get_dcbx_hw(const char *ifname, __u8 *dcbx) -+int get_dcbx_hw(const char *ifname, __u8 *dcbx) - { - int err = 0; - struct nlattr *attr; - struct sockaddr_nl dest_addr; -- static struct nl_handle *nlhandle; -+ static struct nl_sock *nlsocket; - struct nl_msg *nlm = NULL; - unsigned char *msg = NULL; - struct nlmsghdr *hdr; -@@ -434,28 +434,28 @@ static int get_dcbx_hw(const char *ifname, __u8 *dcbx) - .dcb_pad = 0 - }; - -- if (!nlhandle) { -- nlhandle = nl_handle_alloc(); -- if (!nlhandle) { -- LLDPAD_WARN("%s: %s: nl_handle_alloc failed, %s\n", -- __func__, ifname, nl_geterror()); -+ if (!nlsocket) { -+ nlsocket = nl_socket_alloc(); -+ if (!nlsocket) { -+ LLDPAD_WARN("%s: %s: nl_socket_alloc failed\n", -+ __func__, ifname); - err = -ENOMEM; - goto out; - } -- nl_socket_set_local_port(nlhandle, 0); -+ nl_socket_set_local_port(nlsocket, 0); - } - -- err = nl_connect(nlhandle, NETLINK_ROUTE); -+ err = nl_connect(nlsocket, NETLINK_ROUTE); - if (err < 0) { - LLDPAD_WARN("%s: %s nlconnect failed abort get ieee, %s\n", -- __func__, ifname, nl_geterror()); -+ __func__, ifname, nl_geterror(err)); - goto out; - } - - nlm = nlmsg_alloc_simple(RTM_GETDCB, NLM_F_REQUEST); - if (!nlm) { -- LLDPAD_WARN("%s: %s nlmsg_alloc failed abort get ieee, %s\n", -- __func__, ifname, nl_geterror()); -+ LLDPAD_WARN("%s: %s nlmsg_alloc failed abort get ieee\n", -+ __func__, ifname); - err = -ENOMEM; - goto out; - } -@@ -472,14 +472,14 @@ static int get_dcbx_hw(const char *ifname, __u8 *dcbx) - if (err < 0) - goto out; - -- err = nl_send_auto_complete(nlhandle, nlm); -+ err = nl_send_auto_complete(nlsocket, nlm); - if (err <= 0) { - LLDPAD_WARN("%s: %s 802.1Qaz get app attributes failed\n", - __func__, ifname); - goto out; - } - -- err = nl_recv(nlhandle, &dest_addr, &msg, NULL); -+ err = nl_recv(nlsocket, &dest_addr, &msg, NULL); - if (err <= 0) { - LLDPAD_WARN("%s: %s: nl_recv returned %d\n", __func__, ifname, - err); -@@ -492,6 +492,7 @@ static int get_dcbx_hw(const char *ifname, __u8 *dcbx) - if (!attr) { - LLDPAD_DBG("%s: %s: nlmsg_find_attr failed, no GDCBX support\n", - __func__, ifname); -+ err = -EOPNOTSUPP; - goto out; - } - -@@ -499,8 +500,8 @@ static int get_dcbx_hw(const char *ifname, __u8 *dcbx) - out: - nlmsg_free(nlm); - free(msg); -- if (nlhandle) -- nl_close(nlhandle); -+ if (nlsocket) -+ nl_close(nlsocket); - return err; - } - -@@ -524,7 +525,7 @@ void ieee8021qaz_ifup(char *ifname, struct lldp_agent *agent) - struct ieee_ets *ets = NULL; - struct ieee_pfc *pfc = NULL; - struct app_prio *data = NULL; -- int err; -+ int err, no_set_status; - - if (agent->type != NEAREST_BRIDGE) - return; -@@ -537,12 +538,19 @@ void ieee8021qaz_ifup(char *ifname, struct lldp_agent *agent) - if (err < 0) - return; - -+ /* If admin has explicitly enabled Rx/Tx, don't override it */ -+ no_set_status = get_config_setting(ifname, agent->type, ARG_ADMINSTATUS, -+ &adminstatus, CONFIG_TYPE_INT); -+ - /* If hardware is not DCBX IEEE compliant or it is managed - * by an LLD agent most likely a firmware agent abort - */ -- if (!(dcbx & DCB_CAP_DCBX_VER_IEEE) || -- (dcbx & DCB_CAP_DCBX_LLD_MANAGED)) -+ if (dcbx & DCB_CAP_DCBX_LLD_MANAGED) { -+ if (no_set_status) -+ set_lldp_agent_admin(ifname, agent->type, -+ (adminstatus & enabledRxOnly)); - return; -+ } - - /* If 802.1Qaz is already configured no need to continue */ - tlvs = ieee8021qaz_data(ifname); -@@ -552,17 +560,11 @@ void ieee8021qaz_ifup(char *ifname, struct lldp_agent *agent) - /* if there is no persistent adminStatus setting then set to enabledRx - * but do not persist that as a setting. - */ -- if (get_config_setting(ifname, agent->type, ARG_ADMINSTATUS, -- &adminstatus, CONFIG_TYPE_INT)) -+ if (no_set_status) - set_lldp_agent_admin(ifname, agent->type, enabledRxOnly); - - /* lookup port data */ -- port = porthead; -- while (port != NULL) { -- if (!strncmp(ifname, port->ifname, MAX_DEVICE_NAME_LEN)) -- break; -- port = port->next; -- } -+ port = port_find_by_ifindex(get_ifidx(ifname)); - - /* - * Check if link down and/or tlvs exist for current port. -@@ -633,8 +635,10 @@ initialized: - /* Query hardware and set maximum number of TCs with hardware values */ - len = get_ieee_hw(ifname, &ets, &pfc, &data, &cnt); - if (len > 0) { -- tlvs->ets->cfgl->max_tcs = ets->ets_cap; -- tlvs->pfc->local.pfc_cap = pfc->pfc_cap; -+ if (ets) -+ tlvs->ets->cfgl->max_tcs = ets->ets_cap; -+ if (pfc) -+ tlvs->pfc->local.pfc_cap = pfc->pfc_cap; - - free(ets); - free(pfc); -@@ -644,7 +648,7 @@ initialized: - /* if the dcbx field is filled in by the dcbx query then the - * kernel is supports IEEE mode, so make IEEE DCBX active by default. - */ -- if (!dcbx || (dcbx_get_legacy_version(ifname) & ~MASK_DCBX_FORCE)) { -+ if (dcbx_get_legacy_version(ifname) & ~MASK_DCBX_FORCE) { - tlvs->active = false; - } else { - tlvs->active = true; -@@ -786,7 +790,7 @@ static int get_ieee_hw(const char *ifname, struct ieee_ets **ets, - int rem; - int itr = 0; - struct sockaddr_nl dest_addr; -- static struct nl_handle *nlhandle; -+ struct nl_sock *nlsocket = NULL; - struct nl_msg *nlm; - unsigned char *msg = NULL; - struct nlmsghdr *hdr; -@@ -797,20 +801,19 @@ static int get_ieee_hw(const char *ifname, struct ieee_ets **ets, - .dcb_pad = 0 - }; - -- if (!nlhandle) { -- nlhandle = nl_handle_alloc(); -- if (!nlhandle) { -- LLDPAD_WARN("%s: %s: nl_handle_alloc failed, %s\n", -- __func__, ifname, nl_geterror()); -- *cnt = 0; -- return -ENOMEM; -- } -- nl_socket_set_local_port(nlhandle, 0); -+ nlsocket = nl_socket_alloc(); -+ if (!nlsocket) { -+ LLDPAD_WARN("%s: %s: nl_handle_alloc failed\n", -+ __func__, ifname); -+ *cnt = 0; -+ return -ENOMEM; - } -+ nl_socket_set_local_port(nlsocket, 0); - -- if (nl_connect(nlhandle, NETLINK_ROUTE) < 0) { -+ err = nl_connect(nlsocket, NETLINK_ROUTE); -+ if (err < 0) { - LLDPAD_WARN("%s: %s nlconnect failed abort get ieee, %s\n", -- __func__, ifname, nl_geterror()); -+ __func__, ifname, nl_geterror(err)); - goto out1; - } - -@@ -832,14 +835,14 @@ static int get_ieee_hw(const char *ifname, struct ieee_ets **ets, - if (err < 0) - goto out; - -- err = nl_send_auto_complete(nlhandle, nlm); -+ err = nl_send_auto_complete(nlsocket, nlm); - if (err <= 0) { - LLDPAD_WARN("%s: %s 802.1Qaz get app attributes failed\n", - __func__, ifname); - goto out; - } - -- err = nl_recv(nlhandle, &dest_addr, &msg, NULL); -+ err = nl_recv(nlsocket, &dest_addr, &msg, NULL); - if (err <= 0) { - LLDPAD_WARN("%s: %s: nl_recv returned %d\n", __func__, ifname, - err); -@@ -936,7 +939,8 @@ static int get_ieee_hw(const char *ifname, struct ieee_ets **ets, - out: - nlmsg_free(nlm); - free(msg); -- nl_close(nlhandle); -+ nl_close(nlsocket); -+ nl_socket_free(nlsocket); - out1: - *cnt = itr; - return err; -@@ -947,7 +951,7 @@ static int del_ieee_hw(const char *ifname, struct dcb_app *app_data) - int err = 0; - struct nlattr *ieee, *app; - struct sockaddr_nl dest_addr; -- static struct nl_handle *nlhandle; -+ struct nl_sock *nlsocket; - struct nl_msg *nlm; - struct dcbmsg d = { - .dcb_family = AF_UNSPEC, -@@ -955,19 +959,18 @@ static int del_ieee_hw(const char *ifname, struct dcb_app *app_data) - .dcb_pad = 0 - }; - -- if (!nlhandle) { -- nlhandle = nl_handle_alloc(); -- if (!nlhandle) { -- LLDPAD_WARN("%s: %s: nl_handle_alloc failed, %s\n", -- __func__, ifname, nl_geterror()); -- return -ENOMEM; -- } -- nl_socket_set_local_port(nlhandle, 0); -+ nlsocket = nl_socket_alloc(); -+ if (!nlsocket) { -+ LLDPAD_WARN("%s: %s: nl_handle_alloc failed\n", -+ __func__, ifname); -+ return -ENOMEM; - } -+ nl_socket_set_local_port(nlsocket, 0); - -- if (nl_connect(nlhandle, NETLINK_ROUTE) < 0) { -+ err = nl_connect(nlsocket, NETLINK_ROUTE); -+ if (err < 0) { - LLDPAD_WARN("%s: %s nlconnect failed abort hardware set, %s\n", -- __func__, ifname, nl_geterror()); -+ __func__, ifname, nl_geterror(err)); - err = -EIO; - goto out1; - } -@@ -1009,7 +1012,7 @@ static int del_ieee_hw(const char *ifname, struct dcb_app *app_data) - nla_nest_end(nlm, app); - } - nla_nest_end(nlm, ieee); -- err = nl_send_auto_complete(nlhandle, nlm); -+ err = nl_send_auto_complete(nlsocket, nlm); - if (err <= 0) - LLDPAD_WARN("%s: %s 802.1Qaz set attributes failed\n", - __func__, ifname); -@@ -1017,7 +1020,8 @@ static int del_ieee_hw(const char *ifname, struct dcb_app *app_data) - out: - nlmsg_free(nlm); - out2: -- nl_close(nlhandle); -+ nl_close(nlsocket); -+ nl_socket_free(nlsocket); - out1: - return err; - -@@ -1030,7 +1034,7 @@ static int set_ieee_hw(const char *ifname, struct ieee_ets *ets_data, - int err = 0; - struct nlattr *ieee, *app; - struct sockaddr_nl dest_addr; -- static struct nl_handle *nlhandle; -+ struct nl_sock *nlsocket; - struct nl_msg *nlm; - struct dcbmsg d = { - .dcb_family = AF_UNSPEC, -@@ -1038,15 +1042,13 @@ static int set_ieee_hw(const char *ifname, struct ieee_ets *ets_data, - .dcb_pad = 0 - }; - -- if (!nlhandle) { -- nlhandle = nl_handle_alloc(); -- if (!nlhandle) { -- LLDPAD_WARN("%s: %s: nl_handle_alloc failed, %s\n", -- __func__, ifname, nl_geterror()); -- return -ENOMEM; -- } -- nl_socket_set_local_port(nlhandle, 0); -+ nlsocket = nl_socket_alloc(); -+ if (!nlsocket) { -+ LLDPAD_WARN("%s: %s: nl_handle_alloc failed\n", -+ __func__, ifname); -+ return -ENOMEM; - } -+ nl_socket_set_local_port(nlsocket, 0); - - if (!ets_data && !pfc_data && !app_data) { - err = 0; -@@ -1060,9 +1062,10 @@ static int set_ieee_hw(const char *ifname, struct ieee_ets *ets_data, - print_pfc(pfc_data); - #endif - -- if (nl_connect(nlhandle, NETLINK_ROUTE) < 0) { -+ err = nl_connect(nlsocket, NETLINK_ROUTE); -+ if (err < 0) { - LLDPAD_WARN("%s: %s nlconnect failed abort hardware set, %s\n", -- __func__, ifname, nl_geterror()); -+ __func__, ifname, nl_geterror(err)); - err = -EIO; - goto out1; - } -@@ -1118,7 +1121,7 @@ static int set_ieee_hw(const char *ifname, struct ieee_ets *ets_data, - nla_nest_end(nlm, app); - } - nla_nest_end(nlm, ieee); -- err = nl_send_auto_complete(nlhandle, nlm); -+ err = nl_send_auto_complete(nlsocket, nlm); - if (err <= 0) - LLDPAD_WARN("%s: %s 802.1Qaz set attributes failed\n", - __func__, ifname); -@@ -1126,7 +1129,8 @@ static int set_ieee_hw(const char *ifname, struct ieee_ets *ets_data, - out: - nlmsg_free(nlm); - out2: -- nl_close(nlhandle); -+ nl_close(nlsocket); -+ nl_socket_free(nlsocket); - out1: - return err; - } -@@ -2146,29 +2150,18 @@ void ieee8021qaz_unregister(struct lldp_module *mod) - */ - void ieee8021qaz_ifdown(char *device_name, struct lldp_agent *agent) - { -- struct port *port = NULL; - struct ieee8021qaz_tlvs *tlvs; - - if (agent->type != NEAREST_BRIDGE) - return; - -- port = porthead; -- while (port != NULL) { -- if (!strncmp(device_name, port->ifname, MAX_DEVICE_NAME_LEN)) -- break; -- port = port->next; -- } -- - tlvs = ieee8021qaz_data(device_name); -- - if (!tlvs) - return; - -- if (tlvs) { -- ieee8021qaz_free_rx(tlvs->rx); -- free(tlvs->rx); -- tlvs->rx = NULL; -- } -+ ieee8021qaz_free_rx(tlvs->rx); -+ free(tlvs->rx); -+ tlvs->rx = NULL; - } - - /* -diff --git a/lldp_8021qaz_cmds.c b/lldp_8021qaz_cmds.c -index 1414a78..c2c270f 100644 ---- a/lldp_8021qaz_cmds.c -+++ b/lldp_8021qaz_cmds.c -@@ -132,7 +132,6 @@ static int - get_arg_dcbx_mode(struct cmd *cmd, char *args, UNUSED char *arg_value, - char *obuf, int obuf_len) - { -- struct ieee8021qaz_tlvs *tlvs; - char buf[250] = ""; - - if (cmd->cmd != cmd_gettlv) -@@ -147,18 +146,14 @@ get_arg_dcbx_mode(struct cmd *cmd, char *args, UNUSED char *arg_value, - return cmd_not_applicable; - } - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- - switch (lldpad_shm_get_dcbx(cmd->ifname)) { -- case dcbx_subtype0: -+ case DCBX_SUBTYPE0: - snprintf(buf, sizeof(buf), "auto"); - break; -- case dcbx_subtype1: -+ case DCBX_SUBTYPE1: - snprintf(buf, sizeof(buf), "CIN"); - break; -- case dcbx_subtype2: -+ case DCBX_SUBTYPE2: - snprintf(buf, sizeof(buf), "CEE"); - break; - default: -@@ -173,11 +168,32 @@ get_arg_dcbx_mode(struct cmd *cmd, char *args, UNUSED char *arg_value, - return cmd_success; - } - -+#define MAX_DCBX_HW_RETRIES 5 -+ -+static bool is_dcbx_hw(const char *ifname) -+{ -+ __u8 dcbx = 0; -+ int err, tries = 0; -+ -+query_retry: -+ err = get_dcbx_hw(ifname, &dcbx); -+ -+ if (err == -ENOMEM && tries < MAX_DCBX_HW_RETRIES) { -+ tries++; -+ goto query_retry; -+ } -+ -+ if (err < 0 || -+ !(dcbx & DCB_CAP_DCBX_VER_IEEE) || -+ dcbx & DCB_CAP_DCBX_LLD_MANAGED) -+ return false; -+ -+ return true; -+} -+ - static int set_arg_dcbx_mode(struct cmd *cmd, UNUSED char *args, - char *arg_value, char *obuf, int obuf_len) - { -- struct ieee8021qaz_tlvs *tlvs; -- - if (cmd->cmd != cmd_settlv) - return cmd_invalid; - -@@ -190,14 +206,14 @@ static int set_arg_dcbx_mode(struct cmd *cmd, UNUSED char *args, - return cmd_not_applicable; - } - -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; -+ - if (strcmp(arg_value, "reset")) - return cmd_invalid; - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; - -- lldpad_shm_set_dcbx(cmd->ifname, dcbx_subtype0); -+ lldpad_shm_set_dcbx(cmd->ifname, DCBX_SUBTYPE0); - snprintf(obuf, obuf_len, "mode = %s\n", arg_value); - - return cmd_success; -@@ -214,8 +230,8 @@ test_arg_dcbx_mode(UNUSED struct cmd *cmd, UNUSED char *args, - static int get_arg_willing(struct cmd *cmd, char *args, - UNUSED char *arg_value, char *obuf, int obuf_len) - { -- int willing = 0; -- struct ieee8021qaz_tlvs *tlvs; -+ char arg_path[256]; -+ int willing, err; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; -@@ -230,26 +246,20 @@ static int get_arg_willing(struct cmd *cmd, char *args, - return cmd_not_applicable; - } - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- switch (cmd->tlvid) { -- case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: -- willing = tlvs->ets->cfgl->willing; -- break; -- case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_PFC: -- willing = tlvs->pfc->local.willing; -- break; -- } -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, -+ cmd->tlvid, args); -+ err = get_config_setting(cmd->ifname, cmd->type, arg_path, &willing, -+ CONFIG_TYPE_INT); - -- if (willing) -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int) strlen(args), args, -- (unsigned int) strlen(VAL_YES), VAL_YES); -+ if (err) -+ snprintf(obuf, obuf_len, "%02x%s%04d", -+ (unsigned int) strlen(args), args, 0); - else - snprintf(obuf, obuf_len, "%02x%s%04x%s", - (unsigned int) strlen(args), args, -- (unsigned int) strlen(VAL_NO), VAL_NO); -+ willing ? (unsigned int)strlen(VAL_YES) : -+ (unsigned int)strlen(VAL_NO), -+ willing ? VAL_YES : VAL_NO); - - return cmd_success; - } -@@ -264,8 +274,6 @@ static int _set_arg_willing(struct cmd *cmd, char *args, - if (cmd->cmd != cmd_settlv) - return cmd_invalid; - -- -- - /* To remain backward compatible and make it easier - * for everyone use to {0|1} notation we still support - * this but also support english variants as well -@@ -297,20 +305,23 @@ static int _set_arg_willing(struct cmd *cmd, char *args, - return cmd_not_applicable; - } - -- if (test) -+ -+ if (test) { -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; - return cmd_success; -+ } - - tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- -- switch (cmd->tlvid) { -- case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: -- tlvs->ets->cfgl->willing = !!willing; -- break; -- case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_PFC: -- tlvs->pfc->local.willing = !!willing; -- break; -+ if (tlvs) { -+ switch (cmd->tlvid) { -+ case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: -+ tlvs->ets->cfgl->willing = !!willing; -+ break; -+ case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_PFC: -+ tlvs->pfc->local.willing = !!willing; -+ break; -+ } - } - - snprintf(obuf, obuf_len, "willing = %s\n", -@@ -340,7 +351,9 @@ static int test_arg_willing(struct cmd *cmd, char *args, - static int get_arg_numtc(struct cmd *cmd, char *args, - UNUSED char *arg_value, char *obuf, int obuf_len) - { -- struct ieee8021qaz_tlvs *tlvs; -+ char arg_path[256]; -+ int max_tcs = 0; -+ int err = 0; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; -@@ -356,12 +369,18 @@ static int get_arg_numtc(struct cmd *cmd, char *args, - return cmd_not_applicable; - } - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; - -- snprintf(obuf, obuf_len, "%02x%s%04x%i", -- (unsigned int) strlen(args), args, 1, tlvs->ets->cfgl->max_tcs); -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, -+ cmd->tlvid, args); -+ err = get_config_setting(cmd->ifname, cmd->type, -+ arg_path, &max_tcs, CONFIG_TYPE_INT); -+ -+ if (!err) -+ snprintf(obuf, obuf_len, "%02x%s%04x%i", -+ (unsigned int) strlen(args), args, 1, max_tcs); -+ else -+ snprintf(obuf, obuf_len, "%02x%s%04d", -+ (unsigned int) strlen(args), args, 0); - - return cmd_success; - } -@@ -377,10 +396,9 @@ static int get_arg_up2tc(struct cmd *cmd, char *args, - UNUSED char *arg_value, - char *obuf, UNUSED int obuf_len) - { -- struct ieee8021qaz_tlvs *tlvs; -- char buf[250] = ""; -- u32 *pmap = NULL; -- int i; -+ char arg_path[256] = ""; -+ const char *buf = ""; -+ int err; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; -@@ -395,33 +413,18 @@ static int get_arg_up2tc(struct cmd *cmd, char *args, - return cmd_not_applicable; - } - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- switch (cmd->tlvid) { -- case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: -- pmap = &tlvs->ets->cfgl->prio_map; -- break; -- case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSREC: -- pmap = &tlvs->ets->recl->prio_map; -- break; -- } -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, -+ cmd->tlvid, args); -+ err = get_config_setting(cmd->ifname, cmd->type, -+ arg_path, &buf, CONFIG_TYPE_STRING); - -- for (i = 0; i < 8; i++) { -- char cat[5]; -- -- if (i) -- snprintf(cat, sizeof(cat), ",%i:%i", i, -- get_prio_map(*pmap, i)); -- else -- snprintf(cat, sizeof(cat), "%i:%i", i, -- get_prio_map(*pmap, i)); -- strncat(buf, cat, sizeof(buf) - strlen(buf) - 1); -- } -- -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int) strlen(args), args, -- (unsigned int) strlen(buf), buf); -+ if (!err) -+ snprintf(obuf, obuf_len, "%02x%s%04x%s", -+ (unsigned int) strlen(args), args, -+ (unsigned int) strlen(buf), buf); -+ else -+ snprintf(obuf, obuf_len, "%02x%s%04d", -+ (unsigned int) strlen(args), args, 0); - - return cmd_success; - } -@@ -433,35 +436,33 @@ _set_arg_up2tc(struct cmd *cmd, char *args, const char *arg_value, - struct ieee8021qaz_tlvs *tlvs; - char arg_path[256]; - char *toked_maps, *parse; -- u32 *pmap; -- u32 save_pmap; -- u8 max; -- int i, err = cmd_success; -+ u32 *pmap = NULL; -+ u8 max = MAX_TCS; -+ int err = cmd_success; - - if (cmd->cmd != cmd_settlv) - return cmd_invalid; - -+ tlvs = ieee8021qaz_data(cmd->ifname); -+ - switch (cmd->tlvid) { - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- pmap = &tlvs->ets->cfgl->prio_map; -- max = tlvs->ets->cfgl->max_tcs; -+ if (tlvs) { -+ pmap = &tlvs->ets->cfgl->prio_map; -+ max = tlvs->ets->cfgl->max_tcs; -+ } - break; - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSREC: -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- pmap = &tlvs->ets->recl->prio_map; -- max = MAX_TCS; -+ if (tlvs) { -+ pmap = &tlvs->ets->recl->prio_map; -+ max = MAX_TCS; -+ } - break; - case INVALID_TLVID: - return cmd_invalid; - default: - return cmd_not_applicable; - } -- save_pmap = *pmap; - - parse = strdup(arg_value); - if (!parse) -@@ -526,29 +527,25 @@ _set_arg_up2tc(struct cmd *cmd, char *args, const char *arg_value, - } - - mask = ~(0xffffffff & (0xF << (4 * (7-prio)))); -- *pmap &= mask; -- *pmap |= tc << (4 * (7-prio)); -+ if (pmap && !test) { -+ *pmap &= mask; -+ *pmap |= tc << (4 * (7-prio)); -+ } - toked_maps = strtok(NULL, ","); - } -- } else { -+ } else if (pmap && !test) { - *pmap = 0; - } - - if (test) { -- *pmap = save_pmap; -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; - free(parse); - return cmd_success; - } - - /* Build output buffer */ -- strncat(obuf, "up2tc = ", obuf_len - strlen(obuf) - 1); -- for (i = 0; i < 8; i++) { -- char cat[5]; -- -- snprintf(cat, sizeof(cat), "%i:%i ", i, get_prio_map(*pmap, i)); -- strncat(obuf, cat, obuf_len - strlen(obuf) - 1); -- } -- strncat(obuf, "\n", obuf_len - strlen(obuf) - 1); -+ snprintf(obuf, obuf_len, "up2tc = %s\n", arg_value); - - /* Update configuration file with new attribute */ - snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, -@@ -576,26 +573,17 @@ static int test_arg_up2tc(struct cmd *cmd, char *args, - static int get_arg_tcbw(struct cmd *cmd, char *args, - UNUSED char *arg_value, char *obuf, UNUSED int obuf_len) - { -- struct ieee8021qaz_tlvs *tlvs; -- char buf[250] = ""; -- int i; -- u8 *bmap; -+ char arg_path[250] = ""; -+ const char *buf = ""; -+ int err; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; - - switch (cmd->tlvid) { - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- bmap = tlvs->ets->cfgl->tc_bw; - break; - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSREC: -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- bmap = tlvs->ets->recl->tc_bw; - break; - case INVALID_TLVID: - return cmd_invalid; -@@ -603,17 +591,18 @@ static int get_arg_tcbw(struct cmd *cmd, char *args, - return cmd_not_applicable; - } - -- for (i = 0; i < 8; i++) { -- char cat[6]; -- if (i) -- snprintf(cat, sizeof(cat), ",%i", bmap[i]); -- else -- snprintf(cat, sizeof(cat), "%i", bmap[i]); -- strncat(buf, cat, sizeof(buf) - strlen(buf) - 1); -- } -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, -+ cmd->tlvid, args); -+ err = get_config_setting(cmd->ifname, cmd->type, arg_path, &buf, -+ CONFIG_TYPE_STRING); - -- snprintf(obuf, obuf_len, "%02x%s%04x%s", (unsigned int) strlen(args), -- args, (unsigned int) strlen(buf), buf); -+ if (!err) -+ snprintf(obuf, obuf_len, "%02x%s%04x%s", -+ (unsigned int) strlen(args), args, -+ (unsigned int) strlen(buf), buf); -+ else -+ snprintf(obuf, obuf_len, "%02x%s%04d", -+ (unsigned int) strlen(args), args, 0); - - return cmd_success; - } -@@ -626,7 +615,7 @@ _set_arg_tcbw(struct cmd *cmd, char *args, const char *arg_value, - char arg_path[256]; - char *toked_bw, *parse; - int i, err = cmd_success; -- u8 *tcbw, percent[8] = {0}, total = 0; -+ u8 *tcbw = NULL, percent[8] = {0}, total = 0; - - if (cmd->cmd != cmd_settlv) - return cmd_invalid; -@@ -634,15 +623,13 @@ _set_arg_tcbw(struct cmd *cmd, char *args, const char *arg_value, - switch (cmd->tlvid) { - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: - tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- tcbw = tlvs->ets->cfgl->tc_bw; -+ if (tlvs) -+ tcbw = tlvs->ets->cfgl->tc_bw; - break; - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSREC: - tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- tcbw = tlvs->ets->recl->tc_bw; -+ if (tlvs) -+ tcbw = tlvs->ets->recl->tc_bw; - break; - case INVALID_TLVID: - return cmd_invalid; -@@ -668,9 +655,11 @@ _set_arg_tcbw(struct cmd *cmd, char *args, const char *arg_value, - err = cmd_invalid; - goto invalid; - } else if (test) { -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; - free(parse); - return cmd_success; -- } else { -+ } else if (tcbw) { - memcpy(tcbw, percent, sizeof(*tcbw) * MAX_TCS); - } - -@@ -708,26 +697,17 @@ static int test_arg_tcbw(struct cmd *cmd, char *args, - static int get_arg_tsa(struct cmd *cmd, char *args, UNUSED char *arg_value, - char *obuf, UNUSED int obuf_len) - { -- struct ieee8021qaz_tlvs *tlvs; -- char buf[250] = ""; -- int i; -- u8 *tsa; -+ const char *buf = ""; -+ char arg_path[250] = ""; -+ int err; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; - - switch (cmd->tlvid) { - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- tsa = tlvs->ets->cfgl->tsa_map; - break; - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSREC: -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- tsa = tlvs->ets->recl->tsa_map; - break; - case INVALID_TLVID: - return cmd_invalid; -@@ -735,40 +715,18 @@ static int get_arg_tsa(struct cmd *cmd, char *args, UNUSED char *arg_value, - return cmd_not_applicable; - } - -- for (i = 0; i < 8; i++) { -- char cnt[4]; -- int space_left; -- -- if (i) -- snprintf(cnt, sizeof(cnt), ",%i:", i); -- else -- snprintf(cnt, sizeof(cnt), "%i:", i); -- strncat(buf, cnt, sizeof(buf) - strlen(buf) - 1); -- -- space_left = sizeof(buf) - strlen(buf) - 1; -- switch (tsa[i]) { -- case IEEE8021Q_TSA_STRICT: -- strncat(buf, "strict", space_left); -- break; -- case IEEE8021Q_TSA_CBSHAPER: -- strncat(buf, "cb_shaper", space_left); -- break; -- case IEEE8021Q_TSA_ETS: -- strncat(buf, "ets", space_left); -- break; -- case IEEE8021Q_TSA_VENDOR: -- strncat(buf, "vendor", space_left); -- break; -- default: -- strncat(buf, "unknown", space_left); -- break; -- } -- } -- -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int) strlen(args), args, -- (unsigned int) strlen(buf), buf); -- -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -+ TLVID_PREFIX, cmd->tlvid, args); -+ err = get_config_setting(cmd->ifname, cmd->type, arg_path, &buf, -+ CONFIG_TYPE_STRING); -+ -+ if (!err) -+ snprintf(obuf, obuf_len, "%02x%s%04x%s", -+ (unsigned int) strlen(args), args, -+ (unsigned int) strlen(buf), buf); -+ else -+ snprintf(obuf, obuf_len, "%02x%s%04d", -+ (unsigned int) strlen(args), args, 0); - - return cmd_success; - } -@@ -781,7 +739,7 @@ _set_arg_tsa(struct cmd *cmd, char *args, const char *arg_value, - char arg_path[256]; - char *toked_maps, *parse; - int i, err = cmd_success; -- u8 *tsa; -+ u8 *tsa = NULL; - - if (cmd->cmd != cmd_settlv) - return cmd_invalid; -@@ -789,15 +747,13 @@ _set_arg_tsa(struct cmd *cmd, char *args, const char *arg_value, - switch (cmd->tlvid) { - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSCFG: - tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- tsa = tlvs->ets->cfgl->tsa_map; -+ if (tlvs) -+ tsa = tlvs->ets->cfgl->tsa_map; - break; - case (OUI_IEEE_8021 << 8) | LLDP_8021QAZ_ETSREC: - tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- tsa = tlvs->ets->recl->tsa_map; -+ if (tlvs) -+ tsa = tlvs->ets->recl->tsa_map; - break; - case INVALID_TLVID: - return cmd_invalid; -@@ -840,15 +796,17 @@ _set_arg_tsa(struct cmd *cmd, char *args, const char *arg_value, - goto invalid; - } - -- if (!test) -+ if (!test && tsa) - tsa[tc] = type; - toked_maps = strtok(NULL, ","); - } -- } else if (!test) { -+ } else if (!test && tsa) { - memset(tsa, 0, MAX_TCS); - } - - if (test) { -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; - free(parse); - return cmd_success; - } -@@ -862,22 +820,24 @@ _set_arg_tsa(struct cmd *cmd, char *args, const char *arg_value, - strncat(obuf, cnt, obuf_len - strlen(obuf) - 1); - - space_left = obuf_len - strlen(obuf) - 1; -- switch (tsa[i]) { -- case IEEE8021Q_TSA_STRICT: -- strncat(obuf, "strict ", space_left); -- break; -- case IEEE8021Q_TSA_CBSHAPER: -- strncat(obuf, "cb_shaper ", space_left); -- break; -- case IEEE8021Q_TSA_ETS: -- strncat(obuf, "ets ", space_left); -- break; -- case IEEE8021Q_TSA_VENDOR: -- strncat(obuf, "vendor ", space_left); -- break; -- default: -- strncat(obuf, "unknown ", space_left); -- break; -+ if (tsa) { -+ switch (tsa[i]) { -+ case IEEE8021Q_TSA_STRICT: -+ strncat(obuf, "strict ", space_left); -+ break; -+ case IEEE8021Q_TSA_CBSHAPER: -+ strncat(obuf, "cb_shaper ", space_left); -+ break; -+ case IEEE8021Q_TSA_ETS: -+ strncat(obuf, "ets ", space_left); -+ break; -+ case IEEE8021Q_TSA_VENDOR: -+ strncat(obuf, "vendor ", space_left); -+ break; -+ default: -+ strncat(obuf, "unknown ", space_left); -+ break; -+ } - } - } - strncat(obuf, "\n", obuf_len - strlen(obuf) - 1); -@@ -907,11 +867,8 @@ static int test_arg_tsa(struct cmd *cmd, char *args, char *arg_value, - static int get_arg_enabled(struct cmd *cmd, char *args, UNUSED char *arg_value, - char *obuf, UNUSED int obuf_len) - { -- struct ieee8021qaz_tlvs *tlvs; -- char buf[20] = ""; -- int i; -- bool first; -- u8 pfc; -+ char arg_path[256]; -+ int err, pfc; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; -@@ -925,33 +882,17 @@ static int get_arg_enabled(struct cmd *cmd, char *args, UNUSED char *arg_value, - return cmd_not_applicable; - } - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- -- pfc = tlvs->pfc->local.pfc_enable; -- -- first = true; -- for (i = 0; i < 8; i++) { -- if (pfc & (1 << i)) { -- char val[3]; -- -- if (first) { -- snprintf(val, sizeof(val), "%i", i); -- first = false; -- } else { -- snprintf(val, sizeof(val), ",%i", i); -- } -- strncat(buf, val, sizeof(buf) - strlen(buf) - 1); -- } -- } -- -- if (first) -- strncpy(buf, "none", sizeof(buf)); -- -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int) strlen(args), args, -- (unsigned int) strlen(buf), buf); -+ snprintf(arg_path, sizeof(arg_path), -+ "%s%08x.%s", TLVID_PREFIX, cmd->tlvid, args); -+ err = get_config_setting(cmd->ifname, cmd->type, arg_path, &pfc, -+ CONFIG_TYPE_INT); -+ -+ if (!err) -+ snprintf(obuf, obuf_len, "%02x%s%04x%i", -+ (unsigned int) strlen(args), args, 2, pfc); -+ else -+ snprintf(obuf, obuf_len, "%02x%s%04d", -+ (unsigned int) strlen(args), args, 0); - - - return cmd_success; -@@ -979,10 +920,6 @@ static int _set_arg_enabled(struct cmd *cmd, char *args, - return cmd_not_applicable; - } - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- - parse = strdup(arg_value); - if (!parse) - return cmd_failed; -@@ -1014,6 +951,8 @@ static int _set_arg_enabled(struct cmd *cmd, char *args, - } - - if (test) { -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; - free(parse); - return cmd_success; - } -@@ -1040,7 +979,10 @@ static int _set_arg_enabled(struct cmd *cmd, char *args, - "%s%08x.%s", TLVID_PREFIX, cmd->tlvid, args); - set_config_setting(cmd->ifname, cmd->type, arg_path, &mask, - CONFIG_TYPE_INT); -- tlvs->pfc->local.pfc_enable = mask; -+ -+ tlvs = ieee8021qaz_data(cmd->ifname); -+ if (tlvs) -+ tlvs->pfc->local.pfc_enable = mask; - somethingChangedLocal(cmd->ifname, cmd->type); - invalid: - free(parse); -@@ -1062,7 +1004,9 @@ static int test_arg_enabled(struct cmd *cmd, char *args, - static int get_arg_delay(struct cmd *cmd, char *args, - UNUSED char *arg_value, char *obuf, int obuf_len) - { -- struct ieee8021qaz_tlvs *tlvs; -+ unsigned int delay; -+ char arg_path[256]; -+ int err; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; -@@ -1076,13 +1020,17 @@ static int get_arg_delay(struct cmd *cmd, char *args, - return cmd_not_applicable; - } - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -+ snprintf(arg_path, sizeof(arg_path), -+ "%s%08x.%s", TLVID_PREFIX, cmd->tlvid, args); -+ err = get_config_setting(cmd->ifname, cmd->type, arg_path, &delay, -+ CONFIG_TYPE_INT); - -- snprintf(obuf, obuf_len, "%02x%s%04x%02x", -- (unsigned int) strlen(args), args, 2, -- tlvs->pfc->local.delay); -+ if (!err) -+ snprintf(obuf, obuf_len, "%02x%s%04x%02x", -+ (unsigned int) strlen(args), args, 2, delay); -+ else -+ snprintf(obuf, obuf_len, "%02x%s%04d", -+ (unsigned int) strlen(args), args, 0); - - return cmd_success; - } -@@ -1106,14 +1054,15 @@ static int _set_arg_delay(struct cmd *cmd, char *args, - return cmd_not_applicable; - } - -- tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -- -- if (test) -+ if (test) { -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; - return cmd_success; -+ } - -- tlvs->pfc->local.delay = delay; -+ tlvs = ieee8021qaz_data(cmd->ifname); -+ if (tlvs) -+ tlvs->pfc->local.delay = delay; - - snprintf(obuf, obuf_len, "delay = %i\n", delay); - -@@ -1140,13 +1089,38 @@ static int test_arg_delay(struct cmd *cmd, char *args, - return _set_arg_delay(cmd, args, arg_value, obuf, obuf_len, true); - } - -+static void arg_app_strncat_hw(char *new_app, int hw) -+{ -+ switch (hw) { -+ case IEEE_APP_SET: -+ strncat(new_app, "hw (pending set)\n", -+ sizeof(new_app) - strlen(new_app) - 2); -+ break; -+ case IEEE_APP_DEL: -+ strncat(new_app, "hw (pending delete)\n", -+ sizeof(new_app) - strlen(new_app) - 2); -+ break; -+ case IEEE_APP_DONE: -+ strncat(new_app, "hw (set)\n", -+ sizeof(new_app) - strlen(new_app) - 2); -+ break; -+ default: -+ strncat(new_app, " hw (unknown)\n", -+ sizeof(new_app) - strlen(new_app) - 2); -+ break; -+ } -+} -+ - static int get_arg_app(struct cmd *cmd, char *args, UNUSED char *arg_value, - char *obuf, int obuf_len) - { - struct ieee8021qaz_tlvs *tlvs; -- int i = 0; - struct app_obj *np; - char app_buf[2048] = "(prio,sel,proto)\n"; -+ char new_app[80] = ""; -+ const char *app; -+ u8 prio, sel; -+ int proto, hw = -1, i; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; -@@ -1161,55 +1135,93 @@ static int get_arg_app(struct cmd *cmd, char *args, UNUSED char *arg_value, - } - - tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; -+ for (i = 0; i < MAX_APP_ENTRIES; i++) { -+ char arg_path[256]; -+ char *parse, *app_tuple; -+ int err; - -- LIST_FOREACH(np, &tlvs->app_head, entry) { -- char new_app[80]; -- char state[15]; -- struct dcb_app *dcb_app = &np->app; -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s%i", -+ TLVID_PREFIX, TLVID_8021(LLDP_8021QAZ_APP), -+ ARG_APP, i); -+ errno = 0; -+ err = get_config_setting(cmd->ifname, cmd->type, arg_path, -+ &app, CONFIG_TYPE_STRING); -+ if (err) -+ continue; - -- switch (np->hw) { -- case IEEE_APP_SET: -- strcpy(state, "pending set"); -+ /* Parse cfg file input, bounds checking done on set app cmd */ -+ parse = strdup(app); -+ if (!parse) - break; -- case IEEE_APP_DEL: -- strcpy(state, "pending delete"); -+ app_tuple = strtok(parse, ","); -+ if (!app_tuple) - break; -- case IEEE_APP_DONE: -- strcpy(state, "set"); -+ prio = atoi(app_tuple); -+ app_tuple = strtok(NULL, ","); -+ if (!app_tuple) - break; -- default: -- strcpy(state, "unknown"); -+ sel = atoi(app_tuple); -+ -+ app_tuple = strtok(NULL, ","); -+ if (!app_tuple) - break; -- } - -- if (dcb_app->selector == 1) { -+ /* APP Data can be in hex or integer form */ -+ errno = 0; -+ proto = (int) strtol(app_tuple, NULL, 0); -+ if (sel == 1) { - snprintf(new_app, sizeof(new_app), -- "%i:(%i,%i,0x%04x) %s (%s)\n", i, -- dcb_app->priority, -- dcb_app->selector, -- dcb_app->protocol, -- np->peer ? "peer" : "local", -- state); -+ "%i:(%i,%i,0x%04x) local ", i, -+ prio, sel, proto); - } else { - snprintf(new_app, sizeof(new_app), -- "%i:(%i,%i,%i) %s hw (%s)\n", i, -- dcb_app->priority, -- dcb_app->selector, -- dcb_app->protocol, -- np->peer ? "peer" : "local", -- state); -+ "%i:(%i,%i,%i) local ", i, -+ prio, sel, proto); - } -+ -+ if (tlvs) { -+ LIST_FOREACH(np, &tlvs->app_head, entry) { -+ if (np->app.selector == sel && -+ np->app.protocol == proto && -+ np->app.priority == prio && -+ !np->peer) -+ hw = np->hw; -+ } -+ } -+ -+ arg_app_strncat_hw(new_app, hw); - strncat(app_buf, new_app, sizeof(app_buf) - strlen(app_buf) - 2); -- i++; -+ } -+ -+ if (tlvs) { -+ LIST_FOREACH(np, &tlvs->app_head, entry) { -+ if (!np->peer) -+ continue; -+ -+ if (np->app.selector == 1) { -+ snprintf(new_app, sizeof(new_app), -+ "%i:(%i,%i,0x%04x) peer ", i, -+ np->app.priority, -+ np->app.selector, -+ np->app.protocol); -+ } else { -+ snprintf(new_app, sizeof(new_app), -+ "%i:(%i,%i,%i) peer ", i, -+ np->app.priority, -+ np->app.selector, -+ np->app.protocol); -+ } -+ -+ arg_app_strncat_hw(new_app, np->hw); -+ strncat(app_buf, new_app, -+ sizeof(app_buf) - strlen(app_buf) - 2); -+ } - } - - snprintf(obuf, obuf_len, "%02x%s%04x%s", - (unsigned int) strlen(args), args, - (unsigned int) strlen(app_buf), app_buf); - -- - return cmd_success; - } - -@@ -1242,8 +1254,6 @@ static int _set_arg_app(struct cmd *cmd, char *args, char *arg_value, - } - - tlvs = ieee8021qaz_data(cmd->ifname); -- if (!tlvs) -- return cmd_device_not_found; - - parse = strdup(arg_value); - if (!parse) -@@ -1298,8 +1308,11 @@ static int _set_arg_app(struct cmd *cmd, char *args, char *arg_value, - - free(parse); - -- if (test) -+ if (test) { -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; - return cmd_success; -+ } - - snprintf(new_argval, sizeof(new_argval), - "%1u,%1u,%5u", (u8) prio, (u8) sel, (u16)pid); -@@ -1341,6 +1354,9 @@ static int _set_arg_app(struct cmd *cmd, char *args, char *arg_value, - return cmd_failed; - - /* Build app noting we verified prio, sel, and pid inputs */ -+ if (!tlvs) -+ goto write_app_config; -+ - ieee8021qaz_mod_app(&tlvs->app_head, 0, (u8) prio, (u8) sel, (u16) pid, - (cmd->ops & op_delete) ? op_delete : 0); - ieee8021qaz_app_sethw(cmd->ifname, &tlvs->app_head); -@@ -1348,45 +1364,28 @@ static int _set_arg_app(struct cmd *cmd, char *args, char *arg_value, - i = 0; - LIST_FOREACH(np, &tlvs->app_head, entry) { - char new_app[80]; -- char state[15]; -- struct dcb_app *dcb_app = &np->app; - -- switch (np->hw) { -- case IEEE_APP_SET: -- strcpy(state, "pending set"); -- break; -- case IEEE_APP_DEL: -- strcpy(state, "pending delete"); -- break; -- case IEEE_APP_DONE: -- strcpy(state, "set"); -- break; -- default: -- strcpy(state, "unknown"); -- break; -- } -- -- if (dcb_app->selector == 1) { -+ if (np->app.selector == 1) { - snprintf(new_app, sizeof(new_app), -- "%i:(%i,%i,0x%04x) %s (%s)\n", i, -- dcb_app->priority, -- dcb_app->selector, -- dcb_app->protocol, -- np->peer ? "peer" : "local", -- state); -+ "%i:(%i,%i,0x%04x) %s ", i, -+ np->app.priority, -+ np->app.selector, -+ np->app.protocol, -+ np->peer ? "peer" : "local"); - } else { - snprintf(new_app, sizeof(new_app), -- "%i:(%i,%i,%i) %s (%s)\n", i, -- dcb_app->priority, -- dcb_app->selector, -- dcb_app->protocol, -- np->peer ? "peer" : "local", -- state); -+ "%i:(%i,%i,%i) %s ", i, -+ np->app.priority, -+ np->app.selector, -+ np->app.protocol, -+ np->peer ? "peer" : "local"); - } -+ arg_app_strncat_hw(new_app, np->hw); - strncat(obuf, new_app, obuf_len - strlen(obuf) - 2); - i++; - } - -+write_app_config: - somethingChangedLocal(cmd->ifname, cmd->type); - - if (cmd->ops & op_delete) -@@ -1434,7 +1433,7 @@ get_arg_tlvtxenable(struct cmd *cmd, char *arg, UNUSED char *argvalue, - snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", - TLVID_PREFIX, cmd->tlvid, arg); - -- if (!is_tlv_txdisabled(cmd->ifname, cmd->type, cmd->tlvid)) -+ if (is_tlv_txenabled(cmd->ifname, cmd->type, cmd->tlvid)) - value = true; - else - value = false; -@@ -1500,8 +1499,11 @@ static int _set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, - err = get_config_setting(cmd->ifname, cmd->type, arg_path, - &curr, CONFIG_TYPE_BOOL); - -- if (test) -+ if (test) { -+ if (!is_dcbx_hw(cmd->ifname)) -+ return cmd_not_capable; - return cmd_success; -+ } - - snprintf(obuf, obuf_len, "enabled = %s\n", value ? "yes" : "no"); - -diff --git a/lldp_8023.c b/lldp_8023.c -index e8e3f31..eea4bc7 100644 ---- a/lldp_8023.c -+++ b/lldp_8023.c -@@ -320,40 +320,32 @@ static void ieee8023_free_tlv(struct ieee8023_data *bd) - } - } - --static int ieee8023_bld_tlv(struct ieee8023_data *bd, -- struct lldp_agent *agent) -+static int ieee8023_bld_tlv(struct ieee8023_data *bd, struct lldp_agent *agent) - { -- int rc = 0; -- -- if (!port_find_by_name(bd->ifname)) { -- rc = EEXIST; -- goto out_err; -- } -+ if (!port_find_by_ifindex(get_ifidx(bd->ifname))) -+ return -EEXIST; - - if (ieee8023_bld_maccfg_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:ieee8023_bld_macfg_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return 0; - } - if (ieee8023_bld_powvmdi_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:ieee8023_bld_powvmdi_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return 0; - } - if (ieee8023_bld_linkagg_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:ieee8023_bld_linkagg_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return 0; - } - if (ieee8023_bld_maxfs_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:ieee8023_bld_maxfs_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return 0; - } -- rc = 0; -- --out_err: -- return rc; -+ return 0; - } - - static void ieee8023_free_data(struct ieee8023_user_data *ud) -diff --git a/lldp_basman.c b/lldp_basman.c -index 4916e19..824dd9a 100644 ---- a/lldp_basman.c -+++ b/lldp_basman.c -@@ -541,42 +541,35 @@ static void basman_free_tlv(struct basman_data *bd) - /* build unpacked tlvs */ - static int basman_bld_tlv(struct basman_data *bd, struct lldp_agent *agent) - { -- int rc = EPERM; -- -- if (!port_find_by_name(bd->ifname)) { -- rc = EEXIST; -- goto out_err; -- } -+ if (!port_find_by_ifindex(get_ifidx(bd->ifname))) -+ return -EEXIST; - - if (basman_bld_portdesc_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:basman_bld_portdesc_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return -EPERM; - } - if (basman_bld_sysname_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:basman_bld_sysname_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return -EPERM; - } - if (basman_bld_sysdesc_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:basman_bld_sysdesc_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return -EPERM; - } - if (basman_bld_syscaps_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:basman_bld_syscaps_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return -EPERM; - } - if (basman_bld_manaddr_tlv(bd, agent)) { - LLDPAD_DBG("%s:%s:basman_bld_manaddr_tlv() failed\n", -- __func__, bd->ifname); -- goto out_err; -+ __func__, bd->ifname); -+ return -EPERM; - } -- rc = 0; -- --out_err: -- return rc; -+ return 0; - } - - static void basman_free_data(struct basman_user_data *bud) -diff --git a/lldp_dcbx.c b/lldp_dcbx.c -index e9f41a8..9999e33 100644 ---- a/lldp_dcbx.c -+++ b/lldp_dcbx.c -@@ -210,7 +210,7 @@ int dcbx_bld_tlv(struct port *newport, struct lldp_agent *agent) - goto fail_add; - } - -- if (tlvs->dcbx_st == dcbx_subtype2) { -+ if (tlvs->dcbx_st == DCBX_SUBTYPE2) { - tlvs->pg2 = bld_dcbx2_pg_tlv(tlvs, &success); - if (!success) { - LLDPAD_INFO("bld_dcbx2_pg_tlv: failed\n"); -@@ -224,7 +224,7 @@ int dcbx_bld_tlv(struct port *newport, struct lldp_agent *agent) - } - } - -- if (tlvs->dcbx_st == dcbx_subtype2) { -+ if (tlvs->dcbx_st == DCBX_SUBTYPE2) { - tlvs->pfc2 = bld_dcbx2_pfc_tlv(tlvs, &success); - if (!success) { - LLDPAD_INFO("bld_dcbx2_pfc_tlv: failed\n"); -@@ -238,7 +238,7 @@ int dcbx_bld_tlv(struct port *newport, struct lldp_agent *agent) - } - } - -- if (tlvs->dcbx_st == dcbx_subtype2) { -+ if (tlvs->dcbx_st == DCBX_SUBTYPE2) { - tlvs->app2 = bld_dcbx2_app_tlv(tlvs, &success); - if (!success) { - LLDPAD_INFO("bld_dcbx2_app_tlv: failed\n"); -@@ -259,7 +259,7 @@ int dcbx_bld_tlv(struct port *newport, struct lldp_agent *agent) - goto fail_add; - } - -- if (tlvs->dcbx_st == dcbx_subtype2) { -+ if (tlvs->dcbx_st == DCBX_SUBTYPE2) { - tlvs->dcbx2 = bld_dcbx2_tlv(tlvs); - if (tlvs->dcbx2 == NULL) { - LLDPAD_INFO("add_port: bld_dcbx2_tlv failed\n"); -@@ -364,7 +364,7 @@ struct packed_tlv* dcbx_gettlv(struct port *port, struct lldp_agent *agent) - dcbx_free_tlv(tlvs); - - dcbx_bld_tlv(port, agent); -- if (tlvs->dcbx_st == dcbx_subtype2) { -+ if (tlvs->dcbx_st == DCBX_SUBTYPE2) { - /* Load Type127 - dcbx subtype 2*/ - if (tlv_ok(tlvs->dcbx2)) - ptlv = pack_tlv(tlvs->dcbx2); -@@ -484,7 +484,8 @@ void dcbx_unregister(struct lldp_module *mod) - - void dcbx_ifup(char *ifname, struct lldp_agent *agent) - { -- struct port *port = NULL; -+ int ifindex, ret; -+ struct port *port; - struct dcbx_tlvs *tlvs; - struct dcbd_user_data *dud; - struct dcbx_manifest *manifest; -@@ -501,14 +502,15 @@ void dcbx_ifup(char *ifname, struct lldp_agent *agent) - if (agent->type != NEAREST_BRIDGE) - return; - -- port = port_find_by_name(ifname); -+ ifindex = get_ifidx(ifname); -+ port = port_find_by_ifindex(ifindex); - - dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX); - tlvs = dcbx_data(ifname); - - if (!port) - return; -- else if (tlvs) -+ if (tlvs) - goto initialized; - - /* Abort initialization on hardware that does not support -@@ -529,14 +531,12 @@ void dcbx_ifup(char *ifname, struct lldp_agent *agent) - if (dcb_support.dcbx && !(dcb_support.dcbx & DCB_CAP_DCBX_HOST)) - return; - -- /* if no adminStatus setting or wrong setting for adminStatus, -- * then set adminStatus to enabledRxTx. -- */ -- if (get_config_setting(ifname, agent->type, ARG_ADMINSTATUS, -- &adminstatus, CONFIG_TYPE_INT) || -- adminstatus == enabledTxOnly || -- adminstatus == enabledRxOnly) { -- -+ /* if no adminStatus setting default to enabled for DCBX */ -+ ret = get_config_setting(ifname, agent->type, -+ ARG_ADMINSTATUS, -+ &adminstatus, -+ CONFIG_TYPE_INT); -+ if (ret != cmd_success) { - /* set enableTx to true if it is not already set */ - snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, - (OUI_CEE_DCBX << 8) | 1, ARG_TLVTXENABLE); -@@ -634,7 +634,6 @@ initialized: - - void dcbx_ifdown(char *device_name, struct lldp_agent *agent) - { -- struct port *port = NULL; - struct dcbx_tlvs *tlvs; - - if (agent->type != NEAREST_BRIDGE) -@@ -644,30 +643,19 @@ void dcbx_ifdown(char *device_name, struct lldp_agent *agent) - if (is_bond(device_name)) - return; - -- port = porthead; -- while (port != NULL) { -- if (!strncmp(device_name, port->ifname, MAX_DEVICE_NAME_LEN)) -- break; -- port = port->next; -- } -- - tlvs = dcbx_data(device_name); -- - if (!tlvs) - return; - - /* remove dcb port */ -- if (check_port_dcb_mode(device_name)) { -+ if (check_port_dcb_mode(device_name)) - dcbx_remove_adapter(device_name); -- } - -- if (tlvs) { -- LIST_REMOVE(tlvs, entry); -- dcbx_free_tlv(tlvs); -- dcbx_free_manifest(tlvs->manifest); -- free(tlvs->manifest); -- free(tlvs); -- } -+ LIST_REMOVE(tlvs, entry); -+ dcbx_free_tlv(tlvs); -+ dcbx_free_manifest(tlvs->manifest); -+ free(tlvs->manifest); -+ free(tlvs); - } - - void clear_dcbx_manifest(struct dcbx_tlvs *dcbx) -@@ -745,12 +733,12 @@ int dcbx_rchange(struct port *port, struct lldp_agent *agent, struct unpacked_tl - if ((memcmp(tlv->info, &oui, DCB_OUI_LEN) != 0)) - return SUBTYPE_INVALID; - -- if ((tlv->info[DCB_OUI_LEN] == dcbx_subtype2) -+ if ((tlv->info[DCB_OUI_LEN] == DCBX_SUBTYPE2) - && (agent->lldpdu & RCVD_LLDP_DCBX2_TLV)) { - LLDPAD_INFO("Received duplicate DCBX2 TLVs\n"); - return TLV_ERR; - } -- if ((tlv->info[DCB_OUI_LEN] == dcbx_subtype1) -+ if ((tlv->info[DCB_OUI_LEN] == DCBX_SUBTYPE1) - && (agent->lldpdu & RCVD_LLDP_DCBX1_TLV)) { - LLDPAD_INFO("Received duplicate DCBX1 TLVs\n"); - return TLV_ERR; -@@ -760,14 +748,14 @@ int dcbx_rchange(struct port *port, struct lldp_agent *agent, struct unpacked_tl - * the currently configured legacy dcbx mode. - * However, capture if any legacy DCBX TLVs are recieved. - */ -- if (tlv->info[DCB_OUI_LEN] == dcbx_subtype2) { -- if (dcbx->dcbx_st == dcbx_subtype2) -+ if (tlv->info[DCB_OUI_LEN] == DCBX_SUBTYPE2) { -+ if (dcbx->dcbx_st == DCBX_SUBTYPE2) - dcbx->manifest->dcbx2 = tlv; - agent->lldpdu |= RCVD_LLDP_DCBX2_TLV; - dcbx->rxed_tlvs = true; - return TLV_OK; -- } else if (tlv->info[DCB_OUI_LEN] == dcbx_subtype1) { -- if (dcbx->dcbx_st == dcbx_subtype1) -+ } else if (tlv->info[DCB_OUI_LEN] == DCBX_SUBTYPE1) { -+ if (dcbx->dcbx_st == DCBX_SUBTYPE1) - dcbx->manifest->dcbx1 = tlv; - agent->lldpdu |= RCVD_LLDP_DCBX1_TLV; - dcbx->rxed_tlvs = true; -@@ -783,10 +771,10 @@ int dcbx_rchange(struct port *port, struct lldp_agent *agent, struct unpacked_tl - - if (!dcbx->active && !ieee8021qaz_tlvs_rxed(dcbx->ifname) && - dcbx->rxed_tlvs && (not_present || enabled)) { -- if (dcbx->dcbx_st == dcbx_subtype2) -+ if (dcbx->dcbx_st == DCBX_SUBTYPE2) - LLDPAD_DBG("CEE DCBX %s going ACTIVE\n", - dcbx->ifname); -- else if (dcbx->dcbx_st == dcbx_subtype1) -+ else if (dcbx->dcbx_st == DCBX_SUBTYPE1) - LLDPAD_DBG("CIN DCBX %s going ACTIVE\n", - dcbx->ifname); - set_dcbx_mode(port->ifname, -diff --git a/lldp_dcbx_cfg.c b/lldp_dcbx_cfg.c -index 0dc23ea..f44c653 100644 ---- a/lldp_dcbx_cfg.c -+++ b/lldp_dcbx_cfg.c -@@ -320,7 +320,7 @@ int dcbx_default_cfg_file(void) - - tmp_setting = config_setting_add(dcbx_setting, "dcbx_version", - CONFIG_TYPE_INT); -- if (!tmp_setting || !config_setting_set_int(tmp_setting, dcbx_subtype2)) -+ if (!tmp_setting || !config_setting_set_int(tmp_setting, DCBX_SUBTYPE2)) - goto error; - - config_write_file(&lldpad_cfg, cfg_file_name); -@@ -1104,10 +1104,10 @@ int get_dcbx_version(int *result) - - if (get_int_config(dcbx_setting, "dcbx_version", TYPE_INT, result)) { - switch (*result) { -- case dcbx_subtype1: -- case dcbx_subtype2: -- case dcbx_force_subtype1: -- case dcbx_force_subtype2: -+ case DCBX_SUBTYPE1: -+ case DCBX_SUBTYPE2: -+ case DCBX_FORCE_SUBTYPE1: -+ case DCBX_FORCE_SUBTYPE2: - rval = 1; - break; - default: -diff --git a/lldp_dcbx_cmds.c b/lldp_dcbx_cmds.c -index 1ce4d4c..7fdf6c4 100644 ---- a/lldp_dcbx_cmds.c -+++ b/lldp_dcbx_cmds.c -@@ -229,7 +229,7 @@ static int test_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, - return _set_arg_tlvtxenable(cmd, arg, argvalue, obuf, obuf_len, true); - } - --struct arg_handlers *dcbx_get_arg_handlers() -+struct arg_handlers *dcbx_get_arg_handlers(void) - { - return &arg_handlers[0]; - } -@@ -298,10 +298,10 @@ static cmd_status set_dcbx_config(char *ibuf, int ilen) - if (ilen == DCBX_CFG_OFF + CFG_DCBX_DLEN) { - version = (*(ibuf+off+DCBX_VERSION)) ^ '0'; - switch (version) { -- case dcbx_subtype1: -- case dcbx_subtype2: -- case dcbx_force_subtype1: -- case dcbx_force_subtype2: -+ case DCBX_SUBTYPE1: -+ case DCBX_SUBTYPE2: -+ case DCBX_FORCE_SUBTYPE1: -+ case DCBX_FORCE_SUBTYPE2: - rval = save_dcbx_version(version); - break; - default: -@@ -533,7 +533,7 @@ static int handle_dcbx_cmd(u8 cmd, u8 feature, char *ibuf, int ilen, char *rbuf) - return status; - } - --int dcbx_clif_cmd(void *data, -+int dcbx_clif_cmd(UNUSED void *data, - UNUSED struct sockaddr_un *from, - UNUSED socklen_t fromlen, - char *ibuf, int ilen, -@@ -549,10 +549,8 @@ int dcbx_clif_cmd(void *data, - pfc_attribs pfc_data; - app_attribs app_data; - llink_attribs llink_data; -- struct port *port; - struct dcbx_tlvs *dcbx; -- -- data = (struct clif_data *) data; -+ int dcb_enable; - - if (hexstr2bin(ibuf+DCB_CMD_OFF, &cmd, sizeof(cmd)) || - hexstr2bin(ibuf+DCB_FEATURE_OFF, &feature, sizeof(feature))) -@@ -586,17 +584,13 @@ int dcbx_clif_cmd(void *data, - memcpy(port_id, ibuf+DCB_PORT_OFF, plen); - port_id[plen] = '\0'; - -- /* Confirm port is a lldpad managed port */ -- port = port_find_by_name(port_id); -- if (!port) -- return cmd_device_not_found; -- -- dcbx = dcbx_data(port->ifname); -- if (!dcbx) -- return cmd_device_not_found; -+ if (get_hw_state(port_id, &dcb_enable) < 0) -+ return cmd_not_capable; - -+ dcbx = dcbx_data(port_id); - /* OPER and PEER cmd not applicable while in IEEE-DCBX modes */ -- if (dcbx->active == 0 && (cmd == CMD_GET_PEER || cmd == CMD_GET_OPER)) -+ if ((!dcbx || dcbx->active == 0) && -+ (cmd == CMD_GET_PEER || cmd == CMD_GET_OPER)) - return cmd_not_applicable; - - switch(feature) { -@@ -789,7 +783,7 @@ static cmd_status get_pg_data(pg_attribs *pg_data, int cmd, char *port_id, - for (i = 0; i < MAX_BANDWIDTH_GROUPS; i++) - sprintf(rbuf+PG_PG_PCNT(i), "%02x", pg_data->tx.pg_percent[i]); - for (i = 0; i < MAX_USER_PRIORITIES; i++) { -- if (pg_data->tx.up[i].strict_priority == dcb_link) -+ if (pg_data->tx.up[i].strict_priority == DCB_LINK) - value = LINK_STRICT_PGID; - else - value = pg_data->tx.up[i].pgid; -@@ -797,27 +791,27 @@ static cmd_status get_pg_data(pg_attribs *pg_data, int cmd, char *port_id, - } - for (i = 0; i < MAX_USER_PRIORITIES; i++) { - if ((cmd != CMD_GET_PEER) || -- (cmd == CMD_GET_PEER && dcbx_st == dcbx_subtype1)) -+ (cmd == CMD_GET_PEER && dcbx_st == DCBX_SUBTYPE1)) - sprintf(rbuf+PG_UP_PCNT(i), "%02x", - pg_data->tx.up[i].percent_of_pg_cap); -- else if (cmd == CMD_GET_PEER && dcbx_st == dcbx_subtype2) -+ else if (cmd == CMD_GET_PEER && dcbx_st == DCBX_SUBTYPE2) - sprintf(rbuf+PG_UP_PCNT(i), "%c%c", - CLIF_NOT_SUPPLIED, CLIF_NOT_SUPPLIED); - } - for (i = 0; i < MAX_USER_PRIORITIES; i++) { - if ((cmd != CMD_GET_PEER) || -- (cmd == CMD_GET_PEER && dcbx_st == dcbx_subtype1)) { -- if (pg_data->tx.up[i].strict_priority == dcb_link) -- value = dcb_none; -+ (cmd == CMD_GET_PEER && dcbx_st == DCBX_SUBTYPE1)) { -+ if (pg_data->tx.up[i].strict_priority == DCB_LINK) -+ value = DCB_NONE; - else - value = pg_data->tx.up[i].strict_priority; - sprintf(rbuf+PG_UP_STRICT(i), "%1x", value); -- } else if (cmd == CMD_GET_PEER && dcbx_st == dcbx_subtype2) { -+ } else if (cmd == CMD_GET_PEER && dcbx_st == DCBX_SUBTYPE2) { - sprintf(rbuf+PG_UP_STRICT(i), "%c", CLIF_NOT_SUPPLIED); - } - } - -- if ((cmd == CMD_GET_PEER && dcbx_st == dcbx_subtype1) || -+ if ((cmd == CMD_GET_PEER && dcbx_st == DCBX_SUBTYPE1) || - (cmd == CMD_GET_OPER)) - sprintf(rbuf+PG_UP_NUM_TC, "%c", CLIF_NOT_SUPPLIED); - else -@@ -858,7 +852,7 @@ static int get_pfc_data(pfc_attribs *pfc_data, int cmd, char *port_id, - sprintf(rbuf+PFC_UP(i), "%1x", pfc_data->admin[i]); - } - -- if ((cmd == CMD_GET_PEER && dcbx_st == dcbx_subtype1) || -+ if ((cmd == CMD_GET_PEER && dcbx_st == DCBX_SUBTYPE1) || - (cmd == CMD_GET_OPER)) - sprintf(rbuf+PFC_NUM_TC, "%c", CLIF_NOT_SUPPLIED); - else -@@ -978,7 +972,7 @@ static int set_pg_config(pg_attribs *pg_data, char *port_id, char *ibuf, - flag = *(ibuf+off+PG_UP_PGID(i)); - if (flag == CLIF_NOT_SUPPLIED) { - if (pg_data->tx.up[i].strict_priority == -- dcb_link) -+ DCB_LINK) - flag = LINK_STRICT_PGID; - else - flag = pg_data->tx.up[i].pgid; -@@ -1021,8 +1015,8 @@ static int set_pg_config(pg_attribs *pg_data, char *port_id, char *ibuf, - pg_data->tx.up[i].strict_priority |= flag; - pg_data->rx.up[i].strict_priority |= flag; - } else { -- pg_data->tx.up[i].strict_priority &= ~dcb_group; -- pg_data->rx.up[i].strict_priority &= ~dcb_group; -+ pg_data->tx.up[i].strict_priority &= ~DCB_GROUP; -+ pg_data->rx.up[i].strict_priority &= ~DCB_GROUP; - } - } - -@@ -1040,14 +1034,14 @@ static int set_pg_config(pg_attribs *pg_data, char *port_id, char *ibuf, - for (i = 0; i < MAX_USER_PRIORITIES; i++) { - if (pg_data->tx.up[i].pgid == LINK_STRICT_PGID || - (!used[pg_data->tx.up[i].pgid] && -- pg_data->tx.up[i].strict_priority & dcb_link)) { -+ pg_data->tx.up[i].strict_priority & DCB_LINK)) { - pg_data->tx.up[i].pgid = flag; - pg_data->rx.up[i].pgid = flag; -- pg_data->tx.up[i].strict_priority = dcb_link; -- pg_data->rx.up[i].strict_priority = dcb_link; -+ pg_data->tx.up[i].strict_priority = DCB_LINK; -+ pg_data->rx.up[i].strict_priority = DCB_LINK; - } else { -- pg_data->tx.up[i].strict_priority &= ~dcb_link; -- pg_data->rx.up[i].strict_priority &= ~dcb_link; -+ pg_data->tx.up[i].strict_priority &= ~DCB_LINK; -+ pg_data->rx.up[i].strict_priority &= ~DCB_LINK; - } - } - } else if (ilen != off) { -@@ -1104,9 +1098,9 @@ static int set_pfc_config(pfc_attribs *pfc_data, char *port_id, char *ibuf, - if (flag == CLIF_NOT_SUPPLIED) - continue; - if (flag) -- pfc_data->admin[i] = pfc_enabled; -+ pfc_data->admin[i] = PFC_ENABLED; - else -- pfc_data->admin[i] = pfc_disabled; -+ pfc_data->admin[i] = PFC_DISABLED; - } - } else if (ilen != off) { - /* at least needs to include the protocol settings */ -diff --git a/lldp_dcbx_nl.c b/lldp_dcbx_nl.c -index 33cf257..7a2dad2 100644 ---- a/lldp_dcbx_nl.c -+++ b/lldp_dcbx_nl.c -@@ -39,6 +39,7 @@ - #include "linux/rtnetlink.h" - #include "linux/dcbnl.h" - #include "lldp.h" -+#include "lldp_util.h" - #include "dcb_types.h" - #include "dcb_protocol.h" - #include "dcb_driver_interface.h" -@@ -641,9 +642,10 @@ int get_hw_state(char *ifname, int *dcb_state) - - int set_hw_state(char *ifname, int dcb_state) - { -- int err = 0; -+ int err; -+ int ifindex = get_ifidx(ifname); - -- err = set_linkmode(ifname, dcb_state); -+ err = set_linkmode(ifindex, ifname, dcb_state); - - if (err) - LLDPAD_DBG("ERROR %s: set_linkmode dcbstate %i\n", -@@ -751,9 +753,9 @@ int set_hw_pfc(char *ifname, dcb_pfc_list_type pfc_data, - - for (i = 0; i < MAX_TRAFFIC_CLASSES; i++) { - if (pfc_temp[i]) -- pfc[i] = pfc_enabled; -+ pfc[i] = PFC_ENABLED; - else -- pfc[i] = pfc_disabled; -+ pfc[i] = PFC_DISABLED; - } - - rval = set_pfc_cfg(ifname, &pfc[0]); -diff --git a/lldp_ecp.c b/lldp_ecp.c -deleted file mode 100644 -index 8e92253..0000000 ---- a/lldp_ecp.c -+++ /dev/null -@@ -1,1093 +0,0 @@ --/****************************************************************************** -- -- Implementation of ECP according to 802.1Qbg -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Jens Osterkamp -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include -- --#include "eloop.h" --#include "lldp.h" --#include "lldp_evb.h" --#include "lldp_qbg_utils.h" --#include "lldp_vdp.h" --#include "messages.h" --#include "config.h" --#include "lldp/l2_packet.h" -- --#include "lldp_tlv.h" -- --static void ecp_tx_run_sm(struct vdp_data *); --static void ecp_rx_run_sm(struct vdp_data *); -- --/* ecp_localchange_handler - triggers the processing of a local change -- * @eloop_data: data structure of event loop -- * @user_ctx: user context, vdp_data here -- * -- * no return value -- * -- * called from ecp_somethingchangedlocal when a change is pending. Calls -- * the ECP tx station state machine. A oneshot handler. This detour is taken -- * to not having to call the ecp code from the vdp state machine. Instead, we -- * return to the event loop, giving other code a chance to do work. -- */ --static void ecp_localchange_handler(UNUSED void *eloop_data, void *user_ctx) --{ -- struct vdp_data *vd; -- -- vd = (struct vdp_data *) user_ctx; -- if (vd->ecp.tx.localChange) { -- LLDPAD_DBG("%s:%s ecp.tx.localChange %i\n", -- __func__, vd->ecp.ifname, vd->ecp.tx.localChange); -- ecp_tx_run_sm(vd); -- } --} -- --/* ecp_start_localchange_timer - starts the ECP localchange timer -- * @vd: vdp_data for the interface -- * -- * returns 0 on success, -1 on error -- * -- * starts the ECP localchange timer when a localchange has been signaled from -- * the VDP state machine. -- */ --static int ecp_start_localchange_timer(struct vdp_data *vd) --{ -- return eloop_register_timeout(0, ECP_LOCALCHANGE_TIMEOUT, -- ecp_localchange_handler, -- NULL, (void *) vd); --} -- --/* ecp_stop_localchange_timer - stop the ECP localchange timer -- * @vd: vdp_data for the interface -- * -- * returns the number of removed handlers -- * -- * stops the ECP localchange timer. Used e.g. when the host interface goes down. -- */ --static int ecp_stop_localchange_timer(struct vdp_data *vd) --{ -- LLDPAD_DBG("%s:%s stopping ecp localchange timer\n", __func__, -- vd->ecp.ifname); -- return eloop_cancel_timeout(ecp_localchange_handler, NULL, (void *) vd); --} -- --/* ecp_ackTimer_expired - checks for expired ack timer -- * @vd: vdp_data for interface -- * -- * returns true or false -- * -- * returns true if ack timer has expired, false otherwise. -- */ --static bool ecp_ackTimer_expired(struct vdp_data *vd) --{ -- return (vd->ecp.ackTimer == 0); --} -- --/* ecp_ack_timeout_handler - handles the ack timer expiry -- * @eloop_data: data structure of event loop -- * @user_ctx: user context, vdp_data here -- * -- * no return value -- * -- * called when the ECP timer has expired. Calls the ECP station state machine. -- */ --static void ecp_ack_timeout_handler(UNUSED void *eloop_data, void *user_ctx) --{ -- struct vdp_data *vd; -- -- vd = (struct vdp_data *) user_ctx; -- if (vd->ecp.ackTimer > 0) -- vd->ecp.ackTimer -= ECP_ACK_TIMER_DEFAULT; -- -- if (ecp_ackTimer_expired(vd) == true) { -- LLDPAD_DBG("%s:%s ecp_ackTimer_expired (%i)\n", -- __func__, vd->ecp.ifname, vd->ecp.ackTimer); -- ecp_tx_run_sm(vd); -- } else { -- LLDPAD_DBG("%s:%s BUG! handler called but" -- "vdp->ecp.ackTimer not expired (%i)\n", -- __func__, vd->ecp.ifname, vd->ecp.ackTimer); -- } --} -- --/* ecp_start_ack_timer - starts the ECP ack timer -- * @vd: vdp_data for the interface -- * -- * returns 0 on success, -1 on error -- * -- * starts the ECP ack timer when a frame has been sent out. -- */ --static int ecp_start_ack_timer(struct vdp_data *vd) --{ -- return eloop_register_timeout(0, ECP_ACK_TIMER_DEFAULT, -- ecp_ack_timeout_handler, -- NULL, (void *) vd); --} -- --/* ecp_stop_ack_timer - stop the ECP ack timer -- * @vd: vdp_data for the interface -- * -- * returns the number of removed handlers -- * -- * stops the ECP ack timer. Used e.g. when the host interface goes down. -- */ --static int ecp_stop_ack_timer(struct vdp_data *vd) --{ -- LLDPAD_DBG("%s:%s stopping ecp ack timer\n", __func__, vd->ecp.ifname); -- return eloop_cancel_timeout(ecp_ack_timeout_handler, NULL, (void *) vd); --} -- --/* ecp_tx_stop_ackTimer - stop the ECP ack timer -- * @vd: currently used port -- * -- * returns the number of removed handlers -- * -- * stops the ECP ack timer. used when a ack frame for the port has been -- * received. -- */ --static void ecp_tx_stop_ackTimer(struct vdp_data *vd) --{ -- vd->ecp.ackTimer = ECP_ACK_TIMER_STOPPED; -- LLDPAD_DBG("%s:%s stopped ecp ack timer\n", __func__, vd->ecp.ifname); -- ecp_stop_ack_timer(vd); --} -- --int ecp_deinit(char *ifname) --{ -- struct vdp_data *vd; -- -- LLDPAD_DBG("%s:%s stopping ECP\n", __func__, ifname); -- vd = vdp_data(ifname); -- if (!vd) { -- LLDPAD_ERR("%s:%s unable to find vd\n", __func__, ifname); -- return -1; -- } -- -- ecp_stop_ack_timer(vd); -- ecp_stop_localchange_timer(vd); -- ecp_tx_stop_ackTimer(vd); -- return 0; --} -- --static const char *ecp_tx_states[] = { -- "ECP_TX_INIT_TRANSMIT", -- "ECP_TX_TRANSMIT_ECPDU", -- "ECP_TX_WAIT_FOR_ACK", -- "ECP_TX_REQUEST_PDU" --}; -- --/* ecp_somethingChangedLocal - set flag if port has changed -- * @vd: port to set the flag for -- * @mode: mode to set the flag to -- * -- * no return value -- * -- * set the localChange flag with a mode to indicate a port has changed. -- * used to signal an ecpdu needs to be sent out. -- */ -- --void ecp_somethingChangedLocal(struct vdp_data *vd, bool flag) --{ -- if (!vd) -- return; -- -- LLDPAD_DBG("%s:%s vd->ecp.tx.localChange to %s\n", __func__, -- vd->ecp.ifname, (flag == true) ? "true" : "false"); -- vd->ecp.tx.localChange = flag; -- ecp_start_localchange_timer(vd); --} -- --/* -- * Append some data at the end of the transmit data buffer. Make sure the -- * End TLV always fits into the buffer. -- */ --static u8 end_tlv[2] = { 0x0, 0x0 }; /* END TLV */ -- --static int ecp_append(u8 *buffer, u32 *pos, void *data, u32 len) --{ -- if (*pos + len > ETH_FRAME_LEN - sizeof end_tlv) -- return 0; -- memcpy(buffer + *pos, data, len); -- *pos += len; -- return 1; --} -- --/* ecp_build_ECPDU - create an ecp protocol data unit -- * @vd: currently used port -- * -- * returns true on success, false on failure -- * -- * creates the frame header with the ports mac address, the ecp header with REQ -- * plus a list of packed TLVs created from the profiles on this -- * port. -- */ --static bool ecp_build_ECPDU(struct vdp_data *vd) --{ -- struct l2_ethhdr eth; -- struct ecp_hdr ecp_hdr; -- u8 own_addr[ETH_ALEN]; -- u32 fb_offset = 0; -- struct packed_tlv *ptlv = NULL; -- struct vsi_profile *p; -- int rc; -- -- /* TODO: use LLDP group MAC addresses to support -- * S-channels/multichannel -- */ -- memcpy(eth.h_dest, nearest_bridge, ETH_ALEN); -- l2_packet_get_own_src_addr(vd->ecp.l2,(u8 *)&own_addr); -- memcpy(eth.h_source, &own_addr, ETH_ALEN); -- eth.h_proto = htons(ETH_P_ECP); -- memset(vd->ecp.tx.frame, 0, sizeof vd->ecp.tx.frame); -- ecp_append(vd->ecp.tx.frame, &fb_offset, (void *)ð, sizeof eth); -- -- ecp_hdr.oui[0] = 0x0; -- ecp_hdr.oui[1] = 0x1b; -- ecp_hdr.oui[2] = 0x3f; -- ecp_hdr.pad1 = 0x0; -- ecp_hdr.subtype = ECP_SUBTYPE; -- ecp_hdr.mode = ECP_REQUEST; -- -- vd->ecp.lastSequence++; -- ecp_hdr.seqnr = htons(vd->ecp.lastSequence); -- ecp_append(vd->ecp.tx.frame, &fb_offset, (void *)&ecp_hdr, -- sizeof ecp_hdr); -- -- /* create packed_tlvs for all profiles on this interface */ -- LIST_FOREACH(p, &vd->profile_head, profile) { -- -- if (!p->localChange) { -- LLDPAD_DBG("%s:%s skipping unchanged profile\n", -- __func__, vd->ecp.ifname); -- continue; -- } -- -- ptlv = vdp_gettlv(vd, p); -- -- if (!ptlv) { -- LLDPAD_DBG("%s:%s ptlv not created\n", __func__, -- vd->ecp.ifname); -- continue; -- } -- -- rc = ecp_append(vd->ecp.tx.frame, &fb_offset, ptlv->tlv, -- ptlv->size); -- ptlv = free_pkd_tlv(ptlv); -- if (rc) -- p->seqnr = vd->ecp.lastSequence; -- else -- break; -- } -- ecp_append(vd->ecp.tx.frame, &fb_offset, end_tlv, sizeof end_tlv); -- vd->ecp.tx.frame_len = MAX(fb_offset, (unsigned)ETH_ZLEN); -- return true; --} -- --/* ecp_tx_Initialize - initializes the ecp tx state machine -- * @vd: currently used port -- * -- * no return value -- * -- * initializes some variables for the ecp tx state machine. -- */ --static void ecp_tx_Initialize(struct vdp_data *vd) --{ -- memset(vd->ecp.tx.frame, 0, sizeof vd->ecp.tx.frame); -- ecp_somethingChangedLocal(vd, true); -- vd->ecp.lastSequence = ECP_SEQUENCE_NR_START; -- vd->ecp.stats.statsFramesOutTotal = 0; -- vd->ecp.ackTimer = ECP_ACK_TIMER_STOPPED; -- vd->ecp.retries = 0; --} -- --/* ecp_txFrame - transmit ecp frame -- * @vd: currently used port -- * -- * returns the number of characters sent on success, -1 on failure -- * -- * sends out the frame stored in the frame structure using l2_packet_send. -- */ --static u8 ecp_txFrame(struct vdp_data *vd) --{ -- int status = 0; -- -- status = l2_packet_send(vd->ecp.l2, (u8 *)&nearest_bridge, -- htons(ETH_P_ECP), vd->ecp.tx.frame, vd->ecp.tx.frame_len); -- vd->ecp.stats.statsFramesOutTotal++; -- vd->ecp.tx.frame_len = 0; -- return status; --} -- --/* ecp_tx_create_frame - create ecp frame -- * @vd: currently used port -- * -- * no return value -- */ --static void ecp_tx_create_frame(struct vdp_data *vd) --{ -- /* send REQs */ -- if (vd->ecp.tx.localChange) { -- int ret; -- -- LLDPAD_DBG("%s:%s sending REQs\n", __func__, vd->ecp.ifname); -- ret = ecp_build_ECPDU(vd); -- -- /* ECPDU construction succesful, send out frame */ -- if (ret == true) { -- hexdump_frame(vd->ecp.ifname, "frame-out", -- vd->ecp.tx.frame, vd->ecp.tx.frame_len); -- ecp_txFrame(vd); -- } -- } -- -- ecp_somethingChangedLocal(vd, false); --} -- --/* ecp_tx_start_ackTimer - starts the ECP ack timer -- * @vd: vdp_data to process -- * -- * returns 0 on success, -1 on error -- * -- * starts the ack timer when a frame has been sent out. -- */ --static void ecp_tx_start_ackTimer(struct vdp_data *vd) --{ -- vd->ecp.ackTimer = ECP_ACK_TIMER_DEFAULT; -- LLDPAD_DBG("%s-%s: starting ecp ack timer\n", __func__, vd->ifname); -- ecp_start_ack_timer(vd); --} -- --/* ecp_tx_change_state - changes the ecp tx sm state -- * @vd: currently used port -- * @newstate: new state for the sm -- * -- * no return value -- * -- * checks state transistion for consistency and finally changes the state of -- * the profile. -- */ --static void ecp_tx_change_state(struct vdp_data *vd, u8 newstate) --{ -- switch(newstate) { -- case ECP_TX_INIT_TRANSMIT: -- break; -- case ECP_TX_TRANSMIT_ECPDU: -- assert((vd->ecp.tx.state == ECP_TX_INIT_TRANSMIT) || -- (vd->ecp.tx.state == ECP_TX_WAIT_FOR_ACK) || -- (vd->ecp.tx.state == ECP_TX_REQUEST_PDU)); -- break; -- case ECP_TX_WAIT_FOR_ACK: -- assert(vd->ecp.tx.state == ECP_TX_TRANSMIT_ECPDU); -- break; -- case ECP_TX_REQUEST_PDU: -- assert(vd->ecp.tx.state == ECP_TX_WAIT_FOR_ACK); -- break; -- default: -- LLDPAD_ERR("%s: LLDP TX state machine invalid state %d\n", -- vd->ifname, newstate); -- } -- LLDPAD_DBG("%s-%s: state change %s -> %s\n", __func__, -- vd->ifname, ecp_tx_states[vd->ecp.tx.state], -- ecp_tx_states[newstate]); -- vd->ecp.tx.state = newstate; -- return; --} -- --/* ecp_set_tx_state - sets the ecp tx sm state -- * @vd: currently used port -- * -- * returns true or false -- * -- * switches the state machine to the next state depending on the input -- * variables. returns true or false depending on wether the state machine -- * can be run again with the new state or can stop at the current state. -- */ --static bool ecp_set_tx_state(struct vdp_data *vd) --{ -- struct port *port = port_find_by_name(vd->ifname); -- -- if (!port) { -- LLDPAD_ERR("%s: port not found\n", __func__); -- return 0; -- } -- -- if ((port->portEnabled == false) && (port->prevPortEnabled == true)) { -- LLDPAD_ERR("set_tx_state: port was disabled\n"); -- ecp_tx_change_state(vd, ECP_TX_INIT_TRANSMIT); -- } -- port->prevPortEnabled = port->portEnabled; -- -- switch (vd->ecp.tx.state) { -- case ECP_TX_INIT_TRANSMIT: -- if (port->portEnabled && (vd->enabletx == true) -- && vd->ecp.tx.localChange) { -- ecp_tx_change_state(vd, ECP_TX_TRANSMIT_ECPDU); -- return true; -- } -- return false; -- case ECP_TX_TRANSMIT_ECPDU: -- if (vd->enabletx == false) { -- ecp_tx_change_state(vd, ECP_TX_INIT_TRANSMIT); -- return true; -- } -- ecp_tx_change_state(vd, ECP_TX_WAIT_FOR_ACK); -- return false; -- case ECP_TX_WAIT_FOR_ACK: -- if (ecp_ackTimer_expired(vd)) { -- vd->ecp.retries++; -- if (vd->ecp.retries < ECP_MAX_RETRIES) { -- ecp_somethingChangedLocal(vd, true); -- ecp_tx_change_state(vd, ECP_TX_TRANSMIT_ECPDU); -- return true; -- } -- if (vd->ecp.retries == ECP_MAX_RETRIES) { -- LLDPAD_DBG("%s-%s: retries expired\n", -- __func__, vd->ifname); -- ecp_tx_stop_ackTimer(vd); -- ecp_tx_change_state(vd, ECP_TX_REQUEST_PDU); -- return true; -- } -- } -- if (vd->ecp.ackReceived && -- vd->ecp.seqECPDU == vd->ecp.lastSequence) { -- vd->ecp.ackReceived = false; -- if (vdp_vsis_pending(vd)) { -- LLDPAD_DBG("%s-%s: still work pending\n", -- __func__, vd->ifname); -- ecp_somethingChangedLocal(vd, true); -- } -- ecp_tx_change_state(vd, ECP_TX_REQUEST_PDU); -- return true; -- } -- return false; -- case ECP_TX_REQUEST_PDU: -- if (vd->ecp.tx.localChange) { -- ecp_tx_change_state(vd, ECP_TX_TRANSMIT_ECPDU); -- return true; -- } -- return false; -- default: -- LLDPAD_ERR("%s: LLDP TX state machine in invalid state %d\n", -- vd->ifname, vd->ecp.tx.state); -- return false; -- } --} -- --/* ecp_tx_run_sm - state machine for ecp tx -- * @vd: currently used vdp_data -- * -- * no return value -- * -- * runs the state machine for ecp tx. -- */ --void ecp_tx_run_sm(struct vdp_data *vd) --{ -- do { -- LLDPAD_DBG("%s-%s: ecp_tx - %s\n", __func__, -- vd->ifname, ecp_tx_states[vd->ecp.tx.state]); -- -- switch(vd->ecp.tx.state) { -- case ECP_TX_INIT_TRANSMIT: -- ecp_tx_Initialize(vd); -- break; -- case ECP_TX_TRANSMIT_ECPDU: -- ecp_tx_create_frame(vd); -- ecp_tx_start_ackTimer(vd); -- ecp_somethingChangedLocal(vd, false); -- break; -- case ECP_TX_WAIT_FOR_ACK: -- if (vd->ecp.ackReceived) { -- LLDPAD_DBG("%s-%s: ECP_TX_WAIT_FOR_ACK " -- "ackReceived seqECPDU %#x " -- "lastSequence %#x\n", __func__, -- vd->ifname, vd->ecp.seqECPDU, -- vd->ecp.lastSequence); -- ecp_somethingChangedLocal(vd, false); -- ecp_tx_stop_ackTimer(vd); -- } -- break; -- case ECP_TX_REQUEST_PDU: -- vd->ecp.retries = 0; -- LLDPAD_DBG("%s-%s: ECP_TX_REQUEST_PDU lastSeq %#x\n", -- __func__, vd->ifname, vd->ecp.lastSequence); -- break; -- default: -- LLDPAD_ERR("%s: LLDP TX state machine in invalid state %d\n", -- vd->ifname, vd->ecp.tx.state); -- } -- } while (ecp_set_tx_state(vd) == true); --} -- --static const char *ecp_rx_states[] = { -- "ECP_RX_IDLE", -- "ECP_RX_INIT_RECEIVE", -- "ECP_RX_RECEIVE_WAIT", -- "ECP_RX_RECEIVE_ECPDU", -- "ECP_RX_SEND_ACK", -- "ECP_RX_RESEND_ACK", --}; -- --/* ecp_rx_Initialize - initializes the ecp rx state machine -- * @vd: vd for the state machine -- * -- * no return value -- * -- * initialize some variables, get rid of old frame if necessary -- */ --static void ecp_rx_Initialize(struct vdp_data *vd) --{ -- vd->ecp.rx.rcvFrame = false; -- vd->ecp.ackReceived = false; -- vd->ecp.rx.frame_len = 0; --} -- --/* ecp_rx_SendAckFrame - send ack frame -- * @vd: port used by ecp -- * -- * currently always returns 0 -- * -- * copies current received frame over to frame out, fills in address of this -- * port and set mode field to ACK. used by ecp_rx_send_ack_frame. -- */ --static int ecp_rx_SendAckFrame(struct vdp_data *vd) --{ -- u16 tlv_offset = 0; -- struct ecp_hdr *ecp_hdr; -- struct l2_ethhdr *hdr; -- u8 own_addr[ETH_ALEN]; -- -- LLDPAD_DBG("%s:%s acking frame\n", __func__, vd->ecp.ifname); -- /* copy over to transmit buffer */ -- memcpy(vd->ecp.tx.frame, vd->ecp.rx.frame, vd->ecp.rx.frame_len); -- vd->ecp.tx.frame_len = vd->ecp.rx.frame_len; -- -- /* use my own addr to send ACK */ -- hdr = (struct l2_ethhdr *)vd->ecp.tx.frame; -- l2_packet_get_own_src_addr(vd->ecp.l2,(u8 *)&own_addr); -- memcpy(hdr->h_source, &own_addr, ETH_ALEN); -- -- tlv_offset = sizeof(struct l2_ethhdr); -- ecp_hdr = (struct ecp_hdr *)&vd->ecp.tx.frame[tlv_offset]; -- ecp_hdr->mode = ECP_ACK; -- -- tlv_offset = sizeof(struct l2_ethhdr) + sizeof(struct ecp_hdr); -- LLDPAD_DBG("%s:%s zeroing out rest of ack frame from %i to %i\n", -- __func__, vd->ecp.ifname, tlv_offset, vd->ecp.rx.frame_len); -- memset(&vd->ecp.tx.frame[tlv_offset], 0, -- vd->ecp.rx.frame_len - tlv_offset); -- return 0; --} -- --/* ecp_rx_send_ack_frame - send out ack frame for received frame -- * @vd: vd for the state machine -- * -- * no return value -- * -- * creates an ack frame for a just received frame, prints the about to be -- * sent frame and finally transmits it. -- */ --void ecp_rx_send_ack_frame(struct vdp_data *vd) --{ -- ecp_rx_SendAckFrame(vd); -- hexdump_frame(vd->ecp.ifname, "frame-ack", vd->ecp.tx.frame, -- vd->ecp.tx.frame_len); -- ecp_txFrame(vd); --} -- --/* ecp_rx_ReceiveFrame - receive ecp frame -- * @ctx: rx callback context, struct vd * in this case -- * @ifindex: index of interface -- * @buf: buffer which contains the frame just received -- * @len: size of buffer (frame) -- * -- * no return value -- * -- * creates a local copy of the buffer and checks the header. keeps some -- * statistics about ecp frames. Checks if it is a request or an ack frame -- * and branches to ecp rx or ecp tx state machine. -- */ --static void ecp_rx_ReceiveFrame(void *ctx, UNUSED int ifindex, const u8 *buf, -- size_t len) --{ -- struct vdp_data *vd; -- struct port *port; -- u8 frame_error = 0; -- u16 tlv_offset; -- struct l2_ethhdr *hdr; -- struct l2_ethhdr example_hdr,*ex; -- struct ecp_hdr *ecp_hdr; -- -- if (!ctx) { -- LLDPAD_WARN("%s: no ctx - can't process frame\n", __func__); -- return; -- } -- -- vd = (struct vdp_data *)ctx; -- port = port_find_by_name(vd->ifname); -- if (port == NULL) -- return; -- -- LLDPAD_DBG("%s:%s received packet with size %i\n", __func__, -- vd->ecp.ifname, (int)len); -- if (vd->enabletx == false) -- return; -- -- if (vd->ecp.rx.frame_len == len && -- (memcmp(buf, vd->ecp.rx.frame, len) == 0)) { -- vd->ecp.stats.statsFramesInTotal++; -- return; -- } -- -- memset(vd->ecp.rx.frame, 0, len); -- memcpy(vd->ecp.rx.frame, buf, len); -- -- vd->ecp.rx.frame_len = (u16)len; -- ex = &example_hdr; -- memcpy(ex->h_dest, nearest_bridge, ETH_ALEN); -- ex->h_proto = htons(ETH_P_ECP); -- hdr = (struct l2_ethhdr *)vd->ecp.rx.frame; -- -- if ((memcmp(hdr->h_dest, ex->h_dest, ETH_ALEN) != 0)) { -- LLDPAD_ERR("%s:%s ERROR multicast address error in incoming frame." -- " Dropping frame.\n", __func__, vd->ecp.ifname); -- frame_error++; -- return; -- } -- -- if (hdr->h_proto != example_hdr.h_proto) { -- LLDPAD_ERR("%s:%s ERROR ethertype %#x not ECP ethertype", -- __func__, vd->ecp.ifname, htons(hdr->h_proto)); -- frame_error++; -- return; -- } -- -- if (!frame_error) { -- vd->ecp.stats.statsFramesInTotal++; -- vd->ecp.rx.rcvFrame = true; -- } -- -- tlv_offset = sizeof(struct l2_ethhdr); -- ecp_hdr = (struct ecp_hdr *)&vd->ecp.rx.frame[tlv_offset]; -- vd->ecp.seqECPDU = ntohs(ecp_hdr->seqnr); -- hexdump_frame(vd->ecp.ifname, "frame-in", vd->ecp.rx.frame, -- vd->ecp.rx.frame_len); -- -- switch(ecp_hdr->mode) { -- case ECP_REQUEST: -- LLDPAD_DBG("%s:%s received REQ frame\n", __func__, -- vd->ecp.ifname); -- vd->ecp.ackReceived = false; -- ecp_rx_run_sm(vd); -- break; -- case ECP_ACK: -- LLDPAD_DBG("%s:%s received ACK frame\n", __func__, -- vd->ecp.ifname); -- vd->ecp.ackReceived = true; -- vdp_ack_profiles(vd, vd->ecp.seqECPDU); -- ecp_tx_run_sm(vd); -- vd->ecp.ackReceived = false; -- break; -- default: -- LLDPAD_ERR("%s:%s ERROR: unknown mode %i\n", __func__, -- vd->ecp.ifname, ecp_hdr->mode); -- return; -- } -- --} -- --/* ecp_rx_change_state - changes the ecp rx sm state -- * @vd: currently used port -- * @newstate: new state for the sm -- * -- * no return value -- * -- * checks state transistion for consistency and finally changes the state of -- * the profile. -- */ --static void ecp_rx_change_state(struct vdp_data *vd, u8 newstate) --{ -- switch(newstate) { -- case ECP_RX_IDLE: -- break; -- case ECP_RX_INIT_RECEIVE: -- break; -- case ECP_RX_RECEIVE_WAIT: -- assert((vd->ecp.rx.state == ECP_RX_INIT_RECEIVE) || -- (vd->ecp.rx.state == ECP_RX_IDLE) || -- (vd->ecp.rx.state == ECP_RX_SEND_ACK) || -- (vd->ecp.rx.state == ECP_RX_RESEND_ACK)); -- break; -- case ECP_RX_RECEIVE_ECPDU: -- assert(vd->ecp.rx.state == ECP_RX_RECEIVE_WAIT); -- break; -- case ECP_RX_SEND_ACK: -- assert(vd->ecp.rx.state == ECP_RX_RECEIVE_ECPDU); -- break; -- case ECP_RX_RESEND_ACK: -- assert(vd->ecp.rx.state == ECP_RX_RECEIVE_ECPDU); -- break; -- default: -- LLDPAD_ERR("%s:%s LLDP RX state machine invalid state %d\n", -- __func__, vd->ecp.ifname, newstate); -- } -- -- LLDPAD_DBG("%s:%s state change %s -> %s\n", __func__, -- vd->ecp.ifname, ecp_rx_states[vd->ecp.rx.state], -- ecp_rx_states[newstate]); -- -- vd->ecp.rx.state = newstate; --} -- --/* ecp_init - initialize ecp module -- * @ifname: interface for which the module is initialized -- * -- * returns 0 on success, -1 on error -- * -- * finds the port to the interface name, sets up the receive handle for -- * incoming ecp frames and initializes the ecp rx and tx state machines. -- * should usually be called when a successful exchange of EVB TLVs has been -- * made and ECP and VDP protocols are supported by both sides. -- */ --int ecp_init(char *ifname) --{ -- struct vdp_data *vd; -- -- LLDPAD_DBG("%s:%s starting ECP\n", __func__, ifname); -- vd = vdp_data(ifname); -- if (!vd) { -- LLDPAD_ERR("%s:%s unable to find vd\n", __func__, ifname); -- return -1; -- } -- -- if (!vd->ecp.l2) -- vd->ecp.l2 = l2_packet_init(vd->ifname, NULL, ETH_P_ECP, -- ecp_rx_ReceiveFrame, vd, 1); -- -- if (!vd->ecp.l2) { -- LLDPAD_ERR("%s:%s failed to access layer 2 access ETH_P_ECP\n", -- __func__, ifname); -- return -1; -- } -- strncpy(vd->ecp.ifname, ifname, sizeof vd->ecp.ifname); -- ecp_rx_change_state(vd, ECP_RX_IDLE); -- ecp_rx_run_sm(vd); -- ecp_somethingChangedLocal(vd, true); -- return 0; --} -- --/* ecp_rx_validate_frame - validates received frame -- * @vd: vdp_data used by ecp -- * -- * no return value -- * -- * checks wether received frame has correct subtype and mode -- */ -- --static void ecp_rx_validate_frame(struct vdp_data *vd) --{ -- u16 tlv_offset = 0; -- struct ecp_hdr *ecp_hdr; -- -- LLDPAD_DBG("%s:%s validating frame\n", __func__, vd->ecp.ifname); -- tlv_offset = sizeof(struct l2_ethhdr); -- ecp_hdr = (struct ecp_hdr *)&vd->ecp.rx.frame[tlv_offset]; -- LLDPAD_DBG("%s:%s ecp packet with subtype %#x mode %#x seq %#04x\n", -- __func__, vd->ecp.ifname, ecp_hdr->subtype, ecp_hdr->mode, -- ntohs(ecp_hdr->seqnr)); -- -- if (ecp_hdr->subtype != ECP_SUBTYPE) { -- LLDPAD_ERR("%s:%s ERROR: unknown subtype\n", __func__, -- vd->ecp.ifname); -- return; -- } -- -- if ((ecp_hdr->oui[0] != 0x0) || (ecp_hdr->oui[1] != 0x1b) || -- (ecp_hdr->oui[2] != 0x3f)) { -- LLDPAD_ERR("%s:%s ERROR: incorrect OUI 0x%02x%02x%02x\n", -- __func__, vd->ecp.ifname, ecp_hdr->oui[0], -- ecp_hdr->oui[1], ecp_hdr->oui[2]); -- return; -- } -- -- switch(ecp_hdr->mode) { -- case ECP_REQUEST: -- break; -- case ECP_ACK: -- break; -- default: -- LLDPAD_ERR("%s:%s ERROR: unknown mode %i\n", __func__, -- vd->ecp.ifname, ecp_hdr->mode); -- return; -- } -- -- /* FIXME: also done in ecp_rx_ReceiveFrame, -- * are both necessary ? */ -- vd->ecp.seqECPDU = ntohs(ecp_hdr->seqnr); --} -- --/* ecp_rx_ProcessFrame - process received ecp frames -- * @vd: currently used port -- * -- * no return value -- * -- * walks through the packed vsi tlvs in an ecp frame, extracts them -- * and passes them to the VDP ULP with vdp_indicate. -- */ --static void ecp_rx_ProcessFrame(struct vdp_data *vd) --{ -- u16 tlv_cnt = 0; -- u8 tlv_type = 0; -- u16 tlv_length = 0; -- u16 tlv_offset = 0; -- u16 *tlv_head_ptr = NULL; -- u8 frame_error = 0; -- bool tlv_stored = false; -- struct ecp_hdr *ecp_hdr; -- int vdp_called; -- -- LLDPAD_DBG("%s:%s processing frame\n", __func__, vd->ecp.ifname); -- tlv_offset = sizeof(struct l2_ethhdr); -- -- ecp_hdr = (struct ecp_hdr *)&vd->ecp.rx.frame[tlv_offset]; -- LLDPAD_DBG("%s:%s ecp packet with subtype %#x mode %#x seq %#04x\n", -- __func__, vd->ifname, ecp_hdr->subtype, -- ecp_hdr->mode, ntohs(ecp_hdr->seqnr)); -- if (ecp_hdr->mode == ECP_ACK) -- return; -- -- /* processing of VSI_TLVs starts here */ -- tlv_offset += sizeof(struct ecp_hdr); -- vdp_called = 0; -- do { -- tlv_cnt++; -- -- if (tlv_offset > vd->ecp.rx.frame_len) { -- LLDPAD_ERR("%s:%s ERROR: Frame overrun! tlv_offset %i" -- " frame_len %i cnt %i\n", __func__, -- vd->ecp.ifname, tlv_offset, -- vd->ecp.rx.frame_len, tlv_cnt); -- frame_error++; -- goto out; -- } -- -- if (tlv_offset + 2 > vd->ecp.rx.frame_len) { -- LLDPAD_DBG("%s:%s tlv EOF problem size=%d offset=%d\n", -- __func__, vd->ecp.ifname, -- vd->ecp.rx.frame_len, tlv_offset); -- frame_error++; -- goto out; -- } -- -- tlv_head_ptr = (u16 *)&vd->ecp.rx.frame[tlv_offset]; -- tlv_length = htons(*tlv_head_ptr) & 0x01FF; -- tlv_type = (u8)(htons(*tlv_head_ptr) >> 9); -- -- u16 tmp_offset = tlv_offset + tlv_length; -- if (tmp_offset > vd->ecp.rx.frame_len) { -- LLDPAD_ERR("%s:%s ERROR: Frame overflow: offset=%d " -- "rx.size=%d\n", __func__, vd->ecp.ifname, -- tmp_offset, vd->ecp.rx.frame_len); -- frame_error++; -- goto out; -- } -- -- u8 *info = (u8 *)&vd->ecp.rx.frame[tlv_offset + -- sizeof(*tlv_head_ptr)]; -- -- struct unpacked_tlv *tlv = create_tlv(); -- -- if (!tlv) { -- LLDPAD_DBG("%s:%s failed malloc for incoming TLV\n", -- __func__, vd->ecp.ifname); -- goto out; -- } -- -- if ((tlv_length == 0) && (tlv->type != TYPE_0)) { -- LLDPAD_DBG("%s:%s tlv_length == 0\n", __func__, -- vd->ecp.ifname); -- free_unpkd_tlv(tlv); -- goto out; -- } -- -- tlv->type = tlv_type; -- tlv->length = tlv_length; -- tlv->info = (u8 *)malloc(tlv_length); -- if (tlv->info) { -- memset(tlv->info,0, tlv_length); -- memcpy(tlv->info, info, tlv_length); -- } else { -- LLDPAD_DBG("%s:%s failed malloc for incoming TLV info\n", -- __func__, vd->ecp.ifname); -- free_unpkd_tlv(tlv); -- goto out; -- } -- -- /* Validate the TLV */ -- tlv_offset += sizeof(*tlv_head_ptr) + tlv_length; -- -- if (tlv->type == TYPE_127) { /* private TLV */ -- /* give VSI TLV to VDP */ -- if (!vdp_indicate(vd, tlv)) { -- tlv_stored = true; -- ++vdp_called; -- } else { -- /* TODO -- * put it in a list and try again later until -- * timer and retries have expired -- */ -- tlv_stored = false; -- } -- } -- -- if ((tlv->type != TYPE_0) && !tlv_stored) { -- LLDPAD_DBG("%s:%s TLV (%u) was not stored (%p)\n", -- __func__, vd->ecp.ifname, tlv->type, tlv); -- tlv = free_unpkd_tlv(tlv); -- vd->ecp.stats.statsTLVsUnrecognizedTotal++; -- } -- tlv = NULL; -- tlv_stored = false; -- } while (tlv_offset < vd->ecp.rx.frame_len); --out: -- if (frame_error) { -- vd->ecp.stats.statsFramesDiscardedTotal++; -- vd->ecp.stats.statsFramesInErrorsTotal++; -- } -- if (vdp_called) -- vdp_advance_sm(vd); --} -- --/* ecp_set_rx_state - sets the ecp rx sm state -- * @vd: currently used port -- * -- * returns true or false -- * -- * switches the state machine to the next state depending on the input -- * variables. returns true or false depending on wether the state machine -- * can be run again with the new state or can stop at the current state. -- */ --static bool ecp_set_rx_state(struct vdp_data *vd) --{ -- struct port *port = port_find_by_name(vd->ifname); -- -- if (!port) -- return false; -- -- if (port->portEnabled == false) -- ecp_rx_change_state(vd, ECP_RX_IDLE); -- -- switch(vd->ecp.rx.state) { -- case ECP_RX_IDLE: -- if (port->portEnabled == true) { -- ecp_rx_change_state(vd, ECP_RX_INIT_RECEIVE); -- return true; -- } -- return false; -- case ECP_RX_INIT_RECEIVE: -- if (vd->enabletx == true) { -- ecp_rx_change_state(vd, ECP_RX_RECEIVE_WAIT); -- return true; -- } -- return false; -- case ECP_RX_RECEIVE_WAIT: -- if (vd->enabletx == false) { -- ecp_rx_change_state(vd, ECP_RX_IDLE); -- return true; -- } -- if (vd->ecp.rx.rcvFrame == true) { -- ecp_rx_change_state(vd, ECP_RX_RECEIVE_ECPDU); -- return true; -- } -- return false; -- case ECP_RX_RECEIVE_ECPDU: -- if (vd->ecp.seqECPDU == vd->ecp.lastSequence) { -- LLDPAD_DBG("%s:%s seqECPDU %x, lastSequence %x\n", -- __func__, vd->ecp.ifname, vd->ecp.seqECPDU, -- vd->ecp.lastSequence); -- ecp_rx_change_state(vd, ECP_RX_RESEND_ACK); -- return true; -- } -- if (vd->ecp.seqECPDU != vd->ecp.lastSequence) { -- ecp_rx_change_state(vd, ECP_RX_RESEND_ACK); -- return true; -- } -- return false; -- case ECP_RX_SEND_ACK: -- case ECP_RX_RESEND_ACK: -- ecp_rx_change_state(vd, ECP_RX_RECEIVE_WAIT); -- return false; -- default: -- LLDPAD_DBG("%s:%s ECP RX state machine in invalid state %d\n", -- __func__, vd->ecp.ifname, vd->ecp.rx.state); -- return false; -- } --} -- --/* ecp_rx_run_sm - state machine for ecp rx -- * @vd: currently used port -- * -- * no return value -- * -- * runs the state machine for ecp rx. -- */ --static void ecp_rx_run_sm(struct vdp_data *vd) --{ -- ecp_set_rx_state(vd); -- do { -- LLDPAD_DBG("%s:%s ecp_rx - %s\n", __func__, vd->ecp.ifname, -- ecp_rx_states[vd->ecp.tx.state]); -- -- switch(vd->ecp.rx.state) { -- case ECP_RX_IDLE: -- break; -- case ECP_RX_INIT_RECEIVE: -- ecp_rx_Initialize(vd); -- break; -- case ECP_RX_RECEIVE_WAIT: -- break; -- case ECP_RX_RECEIVE_ECPDU: -- vd->ecp.rx.rcvFrame = false; -- ecp_rx_validate_frame(vd); -- break; -- case ECP_RX_SEND_ACK: -- ecp_rx_ProcessFrame(vd); -- break; -- case ECP_RX_RESEND_ACK: -- ecp_rx_ProcessFrame(vd); -- if (!vd->ecp.ackReceived) { -- ecp_rx_send_ack_frame(vd); -- } -- break; -- default: -- LLDPAD_DBG("%s:%s ECP RX state machine in invalid state %d\n", -- __func__, vd->ecp.ifname, vd->ecp.rx.state); -- } -- } while (ecp_set_rx_state(vd) == true); --} -diff --git a/lldp_evb.c b/lldp_evb.c -index c5c52bb..4b3752e 100644 ---- a/lldp_evb.c -+++ b/lldp_evb.c -@@ -32,7 +32,7 @@ - #include "lldp_tlv.h" - #include "lldp_evb.h" - #include "lldp_evb_cmds.h" --#include "lldp_vdp.h" -+#include "qbg_vdp.h" - #include "messages.h" - #include "config.h" - -diff --git a/lldp_evb22.c b/lldp_evb22.c -new file mode 100644 -index 0000000..85c6abc ---- /dev/null -+++ b/lldp_evb22.c -@@ -0,0 +1,565 @@ -+/****************************************************************************** -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2012 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+#define _GNU_SOURCE -+#include -+#include -+ -+#include "lldp.h" -+#include "lldp_tlv.h" -+#include "lldp_evb22.h" -+#include "qbg_ecp22.h" -+#include "qbg_vdp22.h" -+#include "qbg_utils.h" -+#include "lldp_evb_cmds.h" -+#include "messages.h" -+#include "config.h" -+ -+extern struct lldp_head lldp_head; -+ -+struct evb22_data *evb22_data(char *ifname, enum agent_type type) -+{ -+ struct evb22_user_data *ud; -+ struct evb22_data *ed = NULL; -+ -+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB22); -+ if (ud) { -+ LIST_FOREACH(ed, &ud->head, entry) { -+ if (!strncmp(ifname, ed->ifname, IFNAMSIZ) && -+ (type == ed->agenttype)) -+ break; -+ } -+ } -+ return ed; -+} -+ -+static void evb22_format_tlv(char *buf, size_t len, struct evb22_tlv *tlv) -+{ -+ int comma = 0; -+ char bridge_txt[32], station_txt[32]; -+ -+ memset(bridge_txt, 0, sizeof bridge_txt); -+ if (evb_ex_bgid(tlv->bridge_s)) { -+ strcat(bridge_txt, "bgid"); -+ comma = 1; -+ } -+ if (evb_ex_rrcap(tlv->bridge_s)) { -+ if (comma) -+ strcat(bridge_txt, ","); -+ strcat(bridge_txt, "rrcap"); -+ comma = 1; -+ } -+ if (evb_ex_rrctr(tlv->bridge_s)) { -+ if (comma) -+ strcat(bridge_txt, ","); -+ strcat(bridge_txt, "rrctr"); -+ } -+ -+ comma = 0; -+ memset(station_txt, 0, sizeof station_txt); -+ if (evb_ex_sgid(tlv->station_s)) { -+ strcat(station_txt, "sgid"); -+ comma = 1; -+ } -+ if (evb_ex_rrreq(tlv->station_s)) { -+ if (comma) -+ strcat(station_txt, ","); -+ strcat(station_txt, "rrreq"); -+ comma = 1; -+ } -+ if (evb_ex_rrstat(tlv->station_s)) { -+ if (comma) -+ strcat(station_txt, ","); -+ strcat(station_txt, "rrstat"); -+ } -+ snprintf(buf, len, "bridge:%s(%#02x) station:%s(%#02x) " -+ "retries:%d rte:%d mode:%d r/l:%d rwd:%d " -+ "r/l:%d rka:%d", bridge_txt, tlv->bridge_s, -+ station_txt, tlv->station_s, -+ evb_ex_retries(tlv->r_rte), evb_ex_rte(tlv->r_rte), -+ evb_ex_evbmode(tlv->evb_mode), evb_ex_rol(tlv->evb_mode), -+ evb_ex_rwd(tlv->evb_mode), -+ evb_ex_rol(tlv->rl_rka), evb_ex_rka(tlv->rl_rka)); -+} -+ -+static void evb22_print_tlvinfo(char *ifname, struct evb22_tlv *tlv) -+{ -+ char buf[256]; -+ -+ evb22_format_tlv(buf, sizeof buf, tlv); -+ LLDPAD_DBG("%s evb %s\n", ifname, buf); -+} -+ -+static void evb22_dump_tlv(char *ifname, struct unpacked_tlv *tlv) -+{ -+ int i, left = 0; -+ char buffer[256]; -+ -+ for (i = 0; i < tlv->length; i++) { -+ int c; -+ -+ c = snprintf(buffer + left, -+ sizeof buffer - left, -+ "%02x ", tlv->info[i]); -+ -+ if (c < 0 || (c >= (int)sizeof buffer - left)) -+ break; -+ else -+ left += c; -+ } -+ -+ LLDPAD_DBG("%s:%s type %i length %i info %s\n", -+ __func__, ifname, tlv->type, tlv->length, buffer); -+} -+ -+static void common_tlv(struct evb22_data *ed) -+{ -+ struct evb22_tlv *recv = &ed->last; -+ struct evb22_tlv *mine = &ed->policy; -+ u8 val; -+ -+ /* Set retries and rte value */ -+ val = evb_ex_retries(recv->r_rte); -+ if (evb_ex_retries(mine->r_rte) > val) -+ val = evb_ex_retries(mine->r_rte); -+ ed->out.r_rte = evb_set_retries(val); -+ val = evb_ex_rte(recv->r_rte); -+ if (evb_ex_rte(mine->r_rte) > val) -+ val = evb_ex_rte(mine->r_rte); -+ ed->out.r_rte |= evb_set_rte(val); -+ -+ /* Set evbmode */ -+ ed->out.evb_mode = evb_set_evbmode(evb_ex_evbmode(mine->evb_mode)); -+ val = evb_ex_rwd(recv->evb_mode); -+ if (evb_ex_rwd(mine->evb_mode) > val) -+ val = evb_ex_rwd(mine->evb_mode); -+ else -+ ed->out.evb_mode |= evb_set_rol(1); -+ ed->out.evb_mode |= evb_set_rwd(val); -+ -+ /* Set rka */ -+ ed->out.rl_rka = 0; -+ val = evb_ex_rka(recv->rl_rka); -+ if (evb_ex_rka(mine->rl_rka) > val) -+ val = evb_ex_rka(mine->rl_rka); -+ else -+ ed->out.rl_rka = evb_set_rol(1); -+ ed->out.rl_rka |= evb_set_rka(val); -+} -+ -+/* -+ * Fill the EVB DU for LLDP transmition. Sender is bridge. -+ */ -+static void bridge_tlv(struct evb22_data *ed) -+{ -+ struct evb22_tlv *recv = &ed->last; -+ struct evb22_tlv *mine = &ed->policy; -+ -+ /* Copy my last station status */ -+ ed->out.station_s = recv->station_s; -+ -+ /* Set bridge status */ -+ ed->out.bridge_s = mine->bridge_s; -+ if (evb_ex_rrreq(recv->station_s) && evb_ex_rrcap(mine->bridge_s)) -+ ed->out.bridge_s |= evb_set_rrctr(1); -+ common_tlv(ed); -+} -+ -+/* -+ * Fill the EVB DU for LLDP transmition. Sender is station. -+ */ -+static void station_tlv(struct evb22_data *ed) -+{ -+ struct evb22_tlv *recv = &ed->last; -+ struct evb22_tlv *mine = &ed->policy; -+ u8 val; -+ -+ /* Copy my last bridge status */ -+ ed->out.bridge_s = recv->bridge_s; -+ -+ /* -+ * Set station status, 2nd byte of OUI is 0x80. If 0x00 -+ * nothing received from bridge. -+ */ -+ if (recv->oui[1] == 0) -+ val = EVB_RRSTAT_DONT; -+ else if (evb_ex_rrctr(recv->bridge_s)) -+ val = EVB_RRSTAT_YES; -+ else -+ val = EVB_RRSTAT_NO; -+ ed->out.station_s = evb_maskoff_rrstat(mine->station_s) -+ | evb_set_rrstat(val); -+ common_tlv(ed); -+} -+ -+/* -+ * Checks values received in TLV and takes over some values. -+ * Sets the new suggestion in member tie to be send out to switch. -+ * -+ * Also notify depending modules about the new values. -+ */ -+static void evb22_update_tlv(struct evb22_data *ed) -+{ -+ struct qbg22_imm qbg; -+ -+ if (evb_ex_evbmode(ed->policy.evb_mode) == EVB_STATION) -+ station_tlv(ed); -+ else -+ bridge_tlv(ed); -+ -+ qbg.data_type = EVB22_TO_ECP22; -+ qbg.u.a.max_rte = evb_ex_rte(ed->out.r_rte); -+ qbg.u.a.max_retry = evb_ex_retries(ed->out.r_rte); -+ modules_notify(LLDP_MOD_ECP22, LLDP_MOD_EVB22, ed->ifname, &qbg); -+ -+ qbg.data_type = EVB22_TO_VDP22; -+ qbg.u.b.max_rka = evb_ex_rka(ed->out.rl_rka); -+ qbg.u.b.max_rwd = evb_ex_rwd(ed->out.evb_mode); -+ qbg.u.b.max_rte = evb_ex_rte(ed->out.r_rte); -+ qbg.u.b.max_retry = evb_ex_retries(ed->out.r_rte); -+ /* Support group identifiers when advertised by both sides */ -+ qbg.u.b.gpid = evb_ex_bgid(ed->out.bridge_s) -+ && evb_ex_sgid(ed->out.station_s); -+ qbg.u.b.evbon = ed->txmit; -+ modules_notify(LLDP_MOD_VDP22, LLDP_MOD_EVB22, ed->ifname, &qbg); -+} -+ -+/* -+ * Build the packed EVB TLV. -+ * Returns a pointer to the packed tlv or 0 on failure. -+ */ -+static struct packed_tlv *evb22_build_tlv(struct evb22_data *ed) -+{ -+ struct packed_tlv *ptlv = 0; -+ u8 infobuf[sizeof(struct evb22_tlv)]; -+ struct unpacked_tlv tlv = { -+ .type = ORG_SPECIFIC_TLV, -+ .length = sizeof(struct evb22_tlv), -+ .info = infobuf -+ }; -+ -+ evb22_update_tlv(ed); -+ memcpy(tlv.info, &ed->out, tlv.length); -+ ptlv = pack_tlv(&tlv); -+ if (ptlv) { -+ LLDPAD_DBG("%s:%s TLV about to be sent out:\n", __func__, -+ ed->ifname); -+ evb22_dump_tlv(ed->ifname, &tlv); -+ } else -+ LLDPAD_DBG("%s:%s failed to pack EVB TLV\n", __func__, -+ ed->ifname); -+ return ptlv; -+} -+ -+/* -+ * Function call to build and return module specific packed EVB TLV. -+ * Returned packed_tlv is free'ed by caller of this function. -+ */ -+static struct packed_tlv *evb22_gettlv(struct port *port, -+ struct lldp_agent *agent) -+{ -+ struct evb22_data *ed; -+ -+ if (agent->type != NEAREST_CUSTOMER_BRIDGE) -+ return 0; -+ ed = evb22_data(port->ifname, agent->type); -+ if (!ed) { -+ LLDPAD_ERR("%s:%s agent %d failed\n", __func__, port->ifname, -+ agent->type); -+ return 0; -+ } -+ return (ed->txmit) ? evb22_build_tlv(ed) : 0; -+} -+ -+/* -+ * evb_rchange: process received EVB TLV LLDPDU -+ * -+ * TLV not consumed on error -+ */ -+static int evb22_rchange(struct port *port, struct lldp_agent *agent, -+ struct unpacked_tlv *tlv) -+{ -+ struct evb22_data *ed; -+ u8 oui_subtype[OUI_SUB_SIZE] = LLDP_MOD_EVB22_OUI; -+ -+ if (agent->type != NEAREST_CUSTOMER_BRIDGE) -+ return 0; -+ ed = evb22_data(port->ifname, agent->type); -+ -+ if (!ed) -+ return SUBTYPE_INVALID; -+ -+ if (tlv->type == TYPE_127) { -+ /* check for length */ -+ if (tlv->length < OUI_SUB_SIZE) -+ return TLV_ERR; -+ -+ /* check for oui */ -+ if (memcmp(tlv->info, &oui_subtype, OUI_SUB_SIZE)) -+ return SUBTYPE_INVALID; -+ -+ /* disable rx if tx has been disabled by administrator */ -+ if (!ed->txmit) { -+ LLDPAD_WARN("%s:%s agent %d EVB Config disabled\n", -+ __func__, ed->ifname, agent->type); -+ return TLV_OK; -+ } -+ -+ LLDPAD_DBG("%s:%s agent %d received tlv:\n", __func__, -+ port->ifname, agent->type); -+ evb22_dump_tlv(ed->ifname, tlv); -+ memcpy(&ed->last, tlv->info, tlv->length); -+ evb22_print_tlvinfo(ed->ifname, &ed->last); -+ -+ evb22_update_tlv(ed); -+ somethingChangedLocal(ed->ifname, agent->type); -+ -+ LLDPAD_DBG("%s:%s agent %d new tlv:\n", __func__, port->ifname, -+ agent->type); -+ evb22_print_tlvinfo(ed->ifname, &ed->out); -+ /* TODO vdp_update(port->ifname, ed->tie.ccap); */ -+ } -+ return TLV_OK; -+} -+ -+/* -+ * Stop all modules which depend on EVB capabilities. -+ */ -+static void evb22_stop_modules(char *ifname) -+{ -+ LLDPAD_DBG("%s:%s STOP\n", __func__, ifname); -+ ecp22_stop(ifname); -+ vdp22_stop(ifname); -+} -+ -+static void evb22_ifdown(char *ifname, struct lldp_agent *agent) -+{ -+ struct evb22_data *ed; -+ -+ if (agent->type != NEAREST_CUSTOMER_BRIDGE) -+ return; -+ LLDPAD_DBG("%s:%s agent %d called\n", __func__, ifname, agent->type); -+ -+ ed = evb22_data(ifname, agent->type); -+ if (!ed) { -+ LLDPAD_DBG("%s:%s agent %d does not exist.\n", __func__, -+ ifname, agent->type); -+ return; -+ } -+ if (ed->vdp_start) -+ evb22_stop_modules(ifname); -+ LIST_REMOVE(ed, entry); -+ free(ed); -+ LLDPAD_INFO("%s:%s agent %d removed\n", __func__, ifname, agent->type); -+} -+ -+/* -+ * Fill up evb structure with reasonable info from the configuration file. -+ */ -+static void evb22_init_tlv(struct evb22_data *ed, struct lldp_agent *agent) -+{ -+ u8 mode; -+ -+ memset(&ed->last, 0, sizeof ed->last); -+ memset(&ed->out, 0, sizeof ed->out); -+ memset(&ed->policy, 0, sizeof ed->policy); -+ -+ ed->txmit = evb22_conf_enabletx(ed->ifname, agent->type); -+ if (!ed->txmit) -+ LLDPAD_DBG("%s:%s agent %d EVB tx is currently disabled\n", -+ __func__, ed->ifname, agent->type); -+ -+ hton24(ed->policy.oui, LLDP_MOD_EVB22); -+ ed->policy.sub = LLDP_MOD_EVB22_SUBTYPE; -+ hton24(ed->out.oui, LLDP_MOD_EVB22); -+ ed->out.sub = LLDP_MOD_EVB22_SUBTYPE; -+ -+ mode = evb22_conf_evbmode(ed->ifname, agent->type); -+ ed->policy.evb_mode = evb_set_rol(0) -+ | evb_set_rwd(evb22_conf_rwd(ed->ifname, agent->type)) -+ | evb_set_evbmode(mode); -+ if (mode == EVB_STATION) { -+ mode = evb22_conf_rrreq(ed->ifname, agent->type); -+ ed->policy.station_s = evb_set_rrstat(EVB_RRSTAT_DONT) -+ | evb_set_sgid(evb22_conf_gid(ed->ifname, agent->type)) -+ | evb_set_rrreq(mode); -+ ed->policy.bridge_s = 0; -+ } else { -+ mode = evb22_conf_rrcap(ed->ifname, agent->type); -+ ed->policy.bridge_s = evb_set_rrcap(mode) -+ | evb_set_bgid(evb22_conf_gid(ed->ifname, agent->type)); -+ ed->policy.station_s = 0; -+ } -+ ed->policy.r_rte = -+ evb_set_retries(evb22_conf_retries(ed->ifname, agent->type)) -+ | evb_set_rte(evb22_conf_rte(ed->ifname, agent->type)); -+ ed->policy.rl_rka = evb_set_rol(0) -+ | evb_set_rka(evb22_conf_rka(ed->ifname, agent->type)); -+} -+ -+static void evb22_ifup(char *ifname, struct lldp_agent *agent) -+{ -+ struct evb22_data *ed; -+ struct evb22_user_data *ud; -+ -+ if (agent->type != NEAREST_CUSTOMER_BRIDGE) -+ return; -+ LLDPAD_DBG("%s:%s agent %d called\n", __func__, ifname, agent->type); -+ if (is_tlv_txenabled(ifname, agent->type, -+ TLVID(OUI_IEEE_8021Qbg, LLDP_EVB_SUBTYPE))) { -+ LLDPAD_ERR("%s:%s evb draft 0.2 protocol already enabled\n", -+ __func__, ifname); -+ return; -+ } -+ -+ ed = evb22_data(ifname, agent->type); -+ if (ed) { -+ LLDPAD_DBG("%s:%s agent %d already exists\n", __func__, ifname, -+ agent->type); -+ return; -+ } -+ -+ /* not found, alloc/init per-port tlv data */ -+ ed = (struct evb22_data *) calloc(1, sizeof *ed); -+ if (!ed) { -+ LLDPAD_ERR("%s:%s agent %d malloc %zu failed\n", -+ __func__, ifname, agent->type, sizeof *ed); -+ return; -+ } -+ strncpy(ed->ifname, ifname, IFNAMSIZ); -+ ed->agenttype = agent->type; -+ evb22_init_tlv(ed, agent); -+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB22); -+ LIST_INSERT_HEAD(&ud->head, ed, entry); -+ LLDPAD_DBG("%s:%s agent %d added\n", __func__, ifname, agent->type); -+} -+ -+/* -+ * Start all modules which depend on EVB capabilities: ECP, VDP, CDCP. -+ */ -+static void evb22_start_modules(char *ifname, int role) -+{ -+ LLDPAD_DBG("%s:%s START role:%d\n", __func__, ifname, role); -+ ecp22_start(ifname); -+ vdp22_start(ifname, role); -+} -+ -+/* -+ * Check for stable interfaces. When an interface goes up the carrier might -+ * come and go during a start up time. Define a window during which the port -+ * is considered unstable for EVB/VDP protocols. -+ * -+ * Use the dormantDelay counter of the port to determine a stable interface. -+ */ -+static int evb22_timer(struct port *port, struct lldp_agent *agent) -+{ -+ struct evb22_data *ed; -+ -+ if (agent->type != NEAREST_CUSTOMER_BRIDGE) -+ return 0; -+ ed = evb22_data(port->ifname, agent->type); -+ if (!ed) -+ return 0; -+ if (!ed->vdp_start) { -+ ed->vdp_start = true; -+ evb22_start_modules(port->ifname, -+ evb_ex_evbmode(ed->policy.evb_mode)); -+ } -+ return 0; -+} -+ -+static u8 evb22_mibdelete(struct port *port, struct lldp_agent *agent) -+{ -+ struct evb22_data *ed; -+ -+ ed = evb22_data(port->ifname, agent->type); -+ if (ed && (agent->type == ed->agenttype)) { -+ memset(&ed->last, 0, sizeof ed->last); -+ /* TODO vdp_update(port->ifname, 0); */ -+ } -+ return 0; -+} -+ -+/* -+ * Remove all interface/agent specific evb data. -+ */ -+static void evb22_free_data(struct evb22_user_data *ud) -+{ -+ struct evb22_data *ed; -+ -+ if (ud) { -+ while (!LIST_EMPTY(&ud->head)) { -+ ed = LIST_FIRST(&ud->head); -+ LIST_REMOVE(ed, entry); -+ free(ed); -+ } -+ } -+} -+ -+void evb22_unregister(struct lldp_module *mod) -+{ -+ if (mod->data) { -+ evb22_free_data((struct evb22_user_data *) mod->data); -+ free(mod->data); -+ } -+ free(mod); -+ LLDPAD_DBG("%s:done\n", __func__); -+} -+ -+static const struct lldp_mod_ops evb22_ops = { -+ .lldp_mod_gettlv = evb22_gettlv, -+ .lldp_mod_rchange = evb22_rchange, -+ .lldp_mod_mibdelete = evb22_mibdelete, -+ .timer = evb22_timer, -+ .lldp_mod_ifdown = evb22_ifdown, -+ .lldp_mod_ifup = evb22_ifup, -+ .lldp_mod_register = evb22_register, -+ .lldp_mod_unregister = evb22_unregister, -+ .get_arg_handler = evb22_get_arg_handlers -+}; -+ -+struct lldp_module *evb22_register(void) -+{ -+ struct lldp_module *mod; -+ struct evb22_user_data *ud; -+ -+ mod = calloc(1, sizeof *mod); -+ if (!mod) { -+ LLDPAD_ERR("%s: failed to malloc module data\n", __func__); -+ return NULL; -+ } -+ ud = calloc(1, sizeof *ud); -+ if (!ud) { -+ free(mod); -+ LLDPAD_ERR("%s failed to malloc module user data\n", __func__); -+ return NULL; -+ } -+ LIST_INIT(&ud->head); -+ mod->id = LLDP_MOD_EVB22; -+ mod->ops = &evb22_ops; -+ mod->data = ud; -+ LLDPAD_DBG("%s:done\n", __func__); -+ return mod; -+} -diff --git a/lldp_evb22_clif.c b/lldp_evb22_clif.c -new file mode 100644 -index 0000000..336273f ---- /dev/null -+++ b/lldp_evb22_clif.c -@@ -0,0 +1,201 @@ -+/****************************************************************************** -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+#include -+#include -+ -+#include "lldp_tlv.h" -+#include "clif_msgs.h" -+#include "lldp_mod.h" -+#include "lldptool.h" -+#include "lldp.h" -+#include "lldp_evb22.h" -+#include "lldp_evb22_clif.h" -+ -+static void show_tlv(char *buf, size_t len, struct evb22_tlv *tlv) -+{ -+ int comma = 0; -+ char bridge_txt[32], station_txt[32]; -+ -+ memset(bridge_txt, 0, sizeof bridge_txt); -+ if (evb_ex_bgid(tlv->bridge_s)) { -+ strcat(bridge_txt, "bgid"); -+ comma = 1; -+ } -+ if (evb_ex_rrcap(tlv->bridge_s)) { -+ if (comma) -+ strcat(bridge_txt, ","); -+ strcat(bridge_txt, "rrcap"); -+ comma = 1; -+ } -+ if (evb_ex_rrctr(tlv->bridge_s)) { -+ if (comma) -+ strcat(bridge_txt, ","); -+ strcat(bridge_txt, "rrctr"); -+ } -+ -+ comma = 0; -+ memset(station_txt, 0, sizeof station_txt); -+ if (evb_ex_sgid(tlv->station_s)) { -+ strcat(station_txt, "sgid"); -+ comma = 1; -+ } -+ if (evb_ex_rrreq(tlv->station_s)) { -+ if (comma) -+ strcat(station_txt, ","); -+ strcat(station_txt, "rrreq"); -+ comma = 1; -+ } -+ if (evb_ex_rrstat(tlv->station_s)) { -+ if (comma) -+ strcat(station_txt, ","); -+ strcat(station_txt, "rrstat"); -+ } -+ -+ snprintf(buf, len, "bridge:%s(%#02x)\n" -+ "\tstation:%s(%#02x)\n" -+ "\tretries:%d rte:%d\n" -+ "\tmode:%s r/l:%d rwd:%d\n" -+ "\tr/l:%d rka:%d\n", -+ bridge_txt, tlv->bridge_s, -+ station_txt, tlv->station_s, -+ evb_ex_retries(tlv->r_rte), evb_ex_rte(tlv->r_rte), -+ evb_ex_evbmode(tlv->evb_mode) == EVB_STATION ? -+ "station" : "bridge", -+ evb_ex_rol(tlv->evb_mode), -+ evb_ex_rwd(tlv->evb_mode), -+ evb_ex_rol(tlv->rl_rka), evb_ex_rka(tlv->rl_rka)); -+} -+ -+static void evb22_print_cfg_tlv(u16 len, char *info) -+{ -+ struct evb22_tlv tlv; -+ char buf[256]; -+ -+ if (len != 5) { -+ printf("Bad evbcfg TLV: %s\n", info); -+ return; -+ } -+ memset(&tlv, 0, sizeof tlv); -+ memset(buf, 0, sizeof buf); -+ hexstr2bin(&info[0], &tlv.bridge_s, sizeof tlv.bridge_s); -+ hexstr2bin(&info[2], &tlv.station_s, sizeof tlv.station_s); -+ hexstr2bin(&info[4], &tlv.r_rte, sizeof tlv.r_rte); -+ hexstr2bin(&info[6], &tlv.evb_mode, sizeof tlv.evb_mode); -+ hexstr2bin(&info[8], &tlv.rl_rka, sizeof tlv.rl_rka); -+ show_tlv(buf, sizeof buf, &tlv); -+ printf("%s", buf); -+} -+ -+static struct type_name_info evb22_tlv_names[] = { -+ { -+ .type = TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE), -+ .name = "EVB Configuration TLV", -+ .key = "evb", -+ .print_info = evb22_print_cfg_tlv -+ }, -+ { -+ .type = INVALID_TLVID -+ } -+}; -+ -+static int evb22_print_help() -+{ -+ struct type_name_info *tn = &evb22_tlv_names[0]; -+ -+ while (tn->type != INVALID_TLVID) { -+ if (tn->key && strlen(tn->key) && tn->name) { -+ printf(" %s", tn->key); -+ if (strlen(tn->key)+3 < 8) -+ printf("\t"); -+ printf("\t: %s\n", tn->name); -+ } -+ tn++; -+ } -+ -+ return 0; -+} -+ -+static void evb22_cli_unregister(struct lldp_module *mod) -+{ -+ free(mod); -+} -+ -+/* return 1: if it printed the TLV -+ * 0: if it did not -+ */ -+static int evb22_print_tlv(u32 tlvid, u16 len, char *info) -+{ -+ struct type_name_info *tn = &evb22_tlv_names[0]; -+ -+ while (tn->type != INVALID_TLVID) { -+ if (tlvid == tn->type) { -+ printf("%s\n", tn->name); -+ if (tn->print_info) { -+ printf("\t"); -+ tn->print_info(len-4, info); -+ } -+ return 1; -+ } -+ tn++; -+ } -+ -+ return 0; -+} -+ -+static u32 evb22_lookup_tlv_name(char *tlvid_str) -+{ -+ struct type_name_info *tn = &evb22_tlv_names[0]; -+ -+ while (tn->type != INVALID_TLVID) { -+ if (!strcasecmp(tn->key, tlvid_str)) -+ return tn->type; -+ tn++; -+ } -+ return INVALID_TLVID; -+} -+ -+static const struct lldp_mod_ops evb22_ops_clif = { -+ .lldp_mod_register = evb22_cli_register, -+ .lldp_mod_unregister = evb22_cli_unregister, -+ .print_tlv = evb22_print_tlv, -+ .lookup_tlv_name = evb22_lookup_tlv_name, -+ .print_help = evb22_print_help -+}; -+ -+struct lldp_module *evb22_cli_register(void) -+{ -+ struct lldp_module *mod; -+ -+ mod = calloc(1, sizeof(*mod)); -+ if (!mod) { -+ fprintf(stderr, "%s failed to malloc module data\n", __func__); -+ return NULL; -+ } -+ mod->id = LLDP_MOD_EVB22; -+ mod->ops = &evb22_ops_clif; -+ -+ return mod; -+} -diff --git a/lldp_evb22_cmds.c b/lldp_evb22_cmds.c -new file mode 100644 -index 0000000..cebfeb2 ---- /dev/null -+++ b/lldp_evb22_cmds.c -@@ -0,0 +1,750 @@ -+/****************************************************************************** -+ -+ Implementation of EVB TLVs for LLDP -+ (c) Copyright IBM Corp. 2012 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+#include -+ -+#include "lldp.h" -+#include "lldp_evb22.h" -+#include "lldp_tlv.h" -+#include "lldp_mand_clif.h" -+#include "config.h" -+#include "clif_msgs.h" -+#include "messages.h" -+ -+/* -+ * Defines for configuration file name tags. -+ */ -+#define EVB_BUF_SIZE 256 -+#define EVB_CONF_MODE "evbmode" -+#define EVB_CONF_RRREQ "evbrrreq" -+#define EVB_CONF_RRCAP "evbrrcap" -+#define EVB_CONF_GPID "evbgpid" -+#define EVB_CONF_RETRIES "ecpretries" -+#define EVB_CONF_RTE "ecprte" -+#define EVB_CONF_RWD "vdprwd" -+#define EVB_CONF_RKA "vdprka" -+#define EVB_CONF_BRIDGE "bridge" -+#define EVB_CONF_STATION "station" -+ -+/* -+ * Read EVB specific data from the configuration file. -+ */ -+static const char *evb22_conf_string(char *ifname, enum agent_type type, -+ char *ext, int def) -+{ -+ char arg_path[EVB_BUF_SIZE]; -+ const char *param = NULL; -+ -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -+ TLVID_PREFIX, TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE), -+ ext); -+ if (get_cfg(ifname, type, arg_path, ¶m, CONFIG_TYPE_STRING)) -+ LLDPAD_INFO("%s:%s agent %d loading EVB policy for %s" -+ " failed, using default (%d)\n", __func__, -+ ifname, type, ext, def); -+ return param; -+} -+ -+static int evb22_conf_int(char *ifname, enum agent_type type, -+ char *ext, int def, int cfgtype) -+{ -+ char arg_path[EVB_BUF_SIZE]; -+ int param; -+ -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -+ TLVID_PREFIX, TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE), -+ ext); -+ if (get_cfg(ifname, type, arg_path, ¶m, cfgtype)) { -+ LLDPAD_INFO("%s:%s agent %d loading EVB policy for %s" -+ " failed, using default (%d)\n", __func__, -+ ifname, type, ext, def); -+ return def; -+ } -+ return param; -+} -+ -+/* -+ * Read EXP parameter. Defaults to 8 --> 10 * 2 ^ 8 = 2560us > 2ms. -+ */ -+static int exponent(char *ifname, enum agent_type type, char *txt, int def) -+{ -+ int value; -+ -+ value = evb22_conf_int(ifname, type, txt, def, CONFIG_TYPE_INT); -+ if (value > 31) { -+ LLDPAD_DBG("%s:%s agent %d invalid %s %d\n", __func__, -+ ifname, type, txt, value); -+ value = def; -+ } -+ LLDPAD_DBG("%s:%s agent %d policy %s %d\n", __func__, -+ ifname, type, txt, value); -+ return value; -+} -+ -+/* -+ * Read retransmission exponent parameter. -+ */ -+int evb22_conf_rte(char *ifname, enum agent_type type) -+{ -+ return exponent(ifname, type, EVB_CONF_RTE, 8); -+} -+ -+/* -+ * Read reinit keep alive parameter. Same as RTE. -+ */ -+int evb22_conf_rka(char *ifname, enum agent_type type) -+{ -+ return exponent(ifname, type, EVB_CONF_RKA, 20); -+} -+ -+/* -+ * Read resource wait delay parameter. Same as RTE. -+ */ -+int evb22_conf_rwd(char *ifname, enum agent_type type) -+{ -+ return exponent(ifname, type, EVB_CONF_RWD, 20); -+} -+ -+/* -+ * Read max retries parameter. Defaults to 3. -+ */ -+int evb22_conf_retries(char *ifname, enum agent_type type) -+{ -+ int value; -+ -+ value = evb22_conf_int(ifname, type, EVB_CONF_RETRIES, 3, -+ CONFIG_TYPE_INT); -+ if (value > 7) { -+ LLDPAD_DBG("%s:%s agent %d invalid %s %d\n", __func__, -+ ifname, type, EVB_CONF_RETRIES, value); -+ value = 3; -+ } -+ LLDPAD_DBG("%s:%s agent %d policy %s %d\n", __func__, -+ ifname, type, EVB_CONF_RETRIES, value); -+ return value; -+} -+ -+/* -+ * Read station group id parameter. Defaults to false. -+ */ -+int evb22_conf_gid(char *ifname, enum agent_type type) -+{ -+ int value; -+ -+ value = evb22_conf_int(ifname, type, EVB_CONF_GPID, false, -+ CONFIG_TYPE_BOOL); -+ LLDPAD_DBG("%s:%s agent %d policy %s %s\n", __func__, -+ ifname, type, EVB_CONF_GPID, value ? "true" : "false"); -+ return value; -+} -+ -+/* -+ * Read reflective-relay bridge capability parameter. Defaults to false. -+ */ -+int evb22_conf_rrcap(char *ifname, enum agent_type type) -+{ -+ int value; -+ -+ value = evb22_conf_int(ifname, type, EVB_CONF_RRCAP, false, -+ CONFIG_TYPE_BOOL); -+ LLDPAD_DBG("%s:%s agent %d policy %s %s\n", __func__, -+ ifname, type, EVB_CONF_RRCAP, value ? "true" : "false"); -+ return value; -+} -+ -+/* -+ * Read reflective-relay station request parameter. Defaults to false. -+ */ -+int evb22_conf_rrreq(char *ifname, enum agent_type type) -+{ -+ int value; -+ -+ value = evb22_conf_int(ifname, type, EVB_CONF_RRREQ, false, -+ CONFIG_TYPE_BOOL); -+ LLDPAD_DBG("%s:%s agent %d policy %s %s\n", __func__, -+ ifname, type, EVB_CONF_RRREQ, value ? "true" : "false"); -+ return value; -+} -+ -+/* -+ * Read station/bridge role from configuration file. Defaults to station -+ */ -+int evb22_conf_evbmode(char *ifname, enum agent_type type) -+{ -+ int mode = EVB_STATION; -+ const char *value; -+ -+ value = evb22_conf_string(ifname, type, EVB_CONF_MODE, mode); -+ if (value) { -+ if (!strcasecmp(value, EVB_CONF_BRIDGE)) -+ mode = EVB_BRIDGE; -+ else if (strcasecmp(value, EVB_CONF_STATION)) { -+ LLDPAD_ERR("%s:%s agent %d invalid evbmode %s\n", -+ __func__, ifname, type, value); -+ value = EVB_CONF_STATION; -+ } -+ } else -+ value = EVB_CONF_STATION; -+ LLDPAD_DBG("%s:%s agent %d policy %s %s(%#x)\n", __func__, -+ ifname, type, EVB_CONF_MODE, value, mode); -+ return mode; -+} -+ -+/* -+ * Read transmit status from configuration file. -+ */ -+int evb22_conf_enabletx(char *ifname, enum agent_type type) -+{ -+ return is_tlv_txenabled(ifname, type, -+ TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE)); -+} -+ -+static int evb22_cmdok(struct cmd *cmd, cmd_status expected) -+{ -+ if (cmd->cmd != expected) -+ return cmd_invalid; -+ switch (cmd->tlvid) { -+ case TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE): -+ return cmd_success; -+ case INVALID_TLVID: -+ return cmd_invalid; -+ default: -+ return cmd_not_applicable; -+ } -+} -+ -+static int get_arg_evbmode(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ struct evb22_data *ed; -+ char *s; -+ cmd_status good_cmd = evb22_cmdok(cmd, cmd_gettlv); -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ ed = evb22_data((char *) &cmd->ifname, cmd->type); -+ if (!ed) -+ return cmd_invalid; -+ if (evb_ex_evbmode(ed->policy.evb_mode) == EVB_STATION) -+ s = EVB_CONF_STATION; -+ else -+ s = EVB_CONF_BRIDGE; -+ snprintf(obuf, obuf_len, "%02x%s%04x%s", -+ (unsigned int)strlen(arg), arg, (unsigned int)strlen(s), s); -+ return cmd_success; -+} -+ -+static int set2_arg_evbmode(struct cmd *cmd, char *arg, const char *argvalue, -+ bool test) -+{ -+ char arg_path[EVB_BUF_SIZE]; -+ struct evb22_data *ed; -+ cmd_status good_cmd = evb22_cmdok(cmd, cmd_settlv); -+ u8 mode; -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ if (strcasecmp(argvalue, EVB_CONF_BRIDGE) -+ && strcasecmp(argvalue, EVB_CONF_STATION)) -+ return cmd_bad_params; -+ ed = evb22_data((char *) &cmd->ifname, cmd->type); -+ if (!ed) -+ return cmd_invalid; -+ if (test) -+ return cmd_success; -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -+ TLVID_PREFIX, cmd->tlvid, arg); -+ -+ if (set_cfg(cmd->ifname, cmd->type, arg_path, &argvalue, -+ CONFIG_TYPE_STRING)) { -+ LLDPAD_ERR("%s: error saving EVB mode (%s)\n", ed->ifname, -+ argvalue); -+ return cmd_failed; -+ } -+ mode = strcasecmp(argvalue, EVB_CONF_BRIDGE) ? EVB_STATION : EVB_BRIDGE; -+ ed->policy.evb_mode = evb_maskoff_evbmode(ed->policy.evb_mode) | -+ evb_set_evbmode(mode); -+ LLDPAD_INFO("%s: changed EVB mode (%s)\n", ed->ifname, argvalue); -+ return cmd_success; -+} -+ -+static int set_arg_evbmode(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return set2_arg_evbmode(cmd, arg, argvalue, false); -+} -+ -+static int test_arg_evbmode(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return set2_arg_evbmode(cmd, arg, argvalue, true); -+} -+ -+static int get_txmit(struct evb22_data *ed) -+{ -+ return ed->txmit; -+} -+ -+static void set_txmit(struct evb22_data *ed, int value) -+{ -+ ed->txmit = value; -+} -+ -+static int get_gpid(struct evb22_data *ed) -+{ -+ int mode = evb_ex_evbmode(ed->policy.evb_mode); -+ -+ if (mode == EVB_STATION && evb_ex_sgid(ed->policy.station_s)) -+ return 1; -+ if (mode == EVB_BRIDGE && evb_ex_bgid(ed->policy.bridge_s)) -+ return 1; -+ return 0; -+} -+ -+static void set_gpid(struct evb22_data *ed, int value) -+{ -+ if (evb_ex_evbmode(ed->policy.evb_mode) == EVB_STATION) -+ ed->policy.station_s = evb_maskoff_sgid(ed->policy.station_s) -+ | evb_set_sgid(value); -+ else -+ ed->policy.bridge_s = evb_maskoff_bgid(ed->policy.bridge_s) -+ | evb_set_bgid(value); -+} -+ -+static void set_rrcap(struct evb22_data *ed, int value) -+{ -+ ed->policy.bridge_s = evb_maskoff_rrcap(ed->policy.bridge_s) -+ | evb_set_rrcap(value); -+} -+ -+static int get_rrcap(struct evb22_data *ed) -+{ -+ return evb_ex_rrcap(ed->policy.bridge_s); -+} -+ -+static void set_rrreq(struct evb22_data *ed, int value) -+{ -+ ed->policy.station_s = evb_maskoff_rrreq(ed->policy.station_s) -+ | evb_set_rrreq(value); -+} -+ -+static int get_rrreq(struct evb22_data *ed) -+{ -+ return evb_ex_rrreq(ed->policy.station_s); -+} -+ -+/* -+ * Read a boolean value from the command line argument and apply the new -+ * value to parameter. -+ */ -+static int scan_bool(struct cmd *cmd, char *arg, char *argvalue, bool test, -+ void (*fct)(struct evb22_data *, int)) -+{ -+ int value; -+ char arg_path[EVB_BUF_SIZE]; -+ struct evb22_data *ed; -+ cmd_status good_cmd = evb22_cmdok(cmd, cmd_settlv); -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ if (!strcasecmp(argvalue, VAL_YES)) -+ value = 1; -+ else if (!strcasecmp(argvalue, VAL_NO)) -+ value = 0; -+ else -+ return cmd_bad_params; -+ ed = evb22_data((char *) &cmd->ifname, cmd->type); -+ if (!ed) -+ return cmd_invalid; -+ if (test) -+ return cmd_success; -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -+ TLVID_PREFIX, cmd->tlvid, arg); -+ if (set_cfg(cmd->ifname, cmd->type, arg_path, &value, -+ CONFIG_TYPE_BOOL)){ -+ LLDPAD_ERR("%s: error saving EVB enabletx (%s)\n", ed->ifname, -+ argvalue); -+ return cmd_failed; -+ } -+ LLDPAD_INFO("%s: changed EVB %s (%s)\n", ed->ifname, arg, argvalue); -+ (*fct)(ed, value); -+ somethingChangedLocal(cmd->ifname, cmd->type); -+ return cmd_success; -+} -+ -+static int show_bool(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len, -+ int (*fct)(struct evb22_data *)) -+{ -+ struct evb22_data *ed; -+ char *s; -+ cmd_status good_cmd = evb22_cmdok(cmd, cmd_gettlv); -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ ed = evb22_data((char *) &cmd->ifname, cmd->type); -+ if (!ed) -+ return cmd_invalid; -+ if ((*fct)(ed)) -+ s = VAL_YES; -+ else -+ s = VAL_NO; -+ snprintf(obuf, obuf_len, "%02x%s%04x%s", -+ (unsigned int)strlen(arg), arg, (unsigned int)strlen(s), s); -+ return cmd_success; -+} -+ -+static int get_arg_tlvtxenable(struct cmd *cmd, char *arg, -+ UNUSED char *argvalue, char *obuf, int obuf_len) -+{ -+ return show_bool(cmd, arg, argvalue, obuf, obuf_len, get_txmit); -+} -+ -+static int set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_bool(cmd, arg, argvalue, false, set_txmit); -+} -+ -+static int test_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ /* -+ * Make sure either evb draft 0.2 or evb ratified standard is -+ * running at the same time but not both. -+ */ -+ if (!strcasecmp(argvalue, VAL_YES) -+ && is_tlv_txenabled(cmd->ifname, cmd->type, -+ TLVID(OUI_IEEE_8021Qbg, -+ LLDP_EVB_SUBTYPE))) { -+ LLDPAD_ERR("%s:%s evb draft 0.2 protocol already enabled\n", -+ __func__, cmd->ifname); -+ return cmd_failed; -+ } -+ return scan_bool(cmd, arg, argvalue, true, 0); -+} -+ -+static int get_arg_gpid(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ return show_bool(cmd, arg, argvalue, obuf, obuf_len, get_gpid); -+} -+ -+static int set_arg_gpid(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_bool(cmd, arg, argvalue, false, set_gpid); -+} -+ -+static int test_arg_gpid(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_bool(cmd, arg, argvalue, true, 0); -+} -+ -+static int get_arg_rrcap(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ return show_bool(cmd, arg, argvalue, obuf, obuf_len, get_rrcap); -+} -+ -+static int set_arg_rrcap(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_bool(cmd, arg, argvalue, false, set_rrcap); -+} -+ -+static int test_arg_rrcap(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_bool(cmd, arg, argvalue, true, 0); -+} -+ -+static int get_arg_rrreq(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ return show_bool(cmd, arg, argvalue, obuf, obuf_len, get_rrreq); -+} -+ -+static int set_arg_rrreq(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_bool(cmd, arg, argvalue, false, set_rrreq); -+} -+ -+static int test_arg_rrreq(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_bool(cmd, arg, argvalue, true, 0); -+} -+ -+ -+static void set_retries(struct evb22_data *ed, int value) -+{ -+ ed->policy.r_rte = evb_maskoff_retries(ed->policy.r_rte) -+ | evb_set_retries(value); -+} -+ -+static int get_retries(struct evb22_data *ed) -+{ -+ return evb_ex_retries(ed->policy.r_rte); -+} -+ -+static void set_rte(struct evb22_data *ed, int value) -+{ -+ ed->policy.r_rte = evb_maskoff_rte(ed->policy.r_rte) -+ | evb_set_rte(value); -+} -+ -+static int get_rte(struct evb22_data *ed) -+{ -+ return evb_ex_rte(ed->policy.r_rte); -+} -+ -+static void set_rwd(struct evb22_data *ed, int value) -+{ -+ ed->policy.evb_mode = evb_maskoff_rwd(ed->policy.evb_mode) -+ | evb_set_rwd(value); -+} -+ -+static int get_rwd(struct evb22_data *ed) -+{ -+ return evb_ex_rwd(ed->policy.evb_mode); -+} -+ -+static void set_rka(struct evb22_data *ed, int value) -+{ -+ ed->policy.rl_rka = evb_maskoff_rka(ed->policy.rl_rka) -+ | evb_set_rka(value); -+} -+ -+static int get_rka(struct evb22_data *ed) -+{ -+ return evb_ex_rka(ed->policy.rl_rka); -+} -+ -+static int scan_31bit(struct cmd *cmd, char *arg, const char *argvalue, -+ bool test, void (*fct)(struct evb22_data *, int), -+ int limit) -+{ -+ char arg_path[EVB_BUF_SIZE]; -+ struct evb22_data *ed; -+ int value; -+ char *endp; -+ cmd_status good_cmd = evb22_cmdok(cmd, cmd_settlv); -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ value = strtoul(argvalue, &endp, 0); -+ if (*endp != '\0' || value > limit) -+ return cmd_bad_params; -+ ed = evb22_data((char *) &cmd->ifname, cmd->type); -+ if (!ed) -+ return cmd_invalid; -+ if (test) -+ return cmd_success; -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -+ TLVID_PREFIX, cmd->tlvid, arg); -+ if (set_cfg(ed->ifname, cmd->type, arg_path, &value, -+ CONFIG_TYPE_INT)){ -+ LLDPAD_ERR("%s: error saving EVB %s (%d)\n", ed->ifname, arg, -+ value); -+ return cmd_failed; -+ } -+ LLDPAD_INFO("%s: changed EVB %s (%s)\n", ed->ifname, arg, argvalue); -+ (*fct)(ed, value); -+ somethingChangedLocal(cmd->ifname, cmd->type); -+ return cmd_success; -+} -+ -+static int show_31bit(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len, -+ int (*fct)(struct evb22_data *)) -+{ -+ struct evb22_data *ed; -+ char s[EVB_BUF_SIZE]; -+ cmd_status good_cmd = evb22_cmdok(cmd, cmd_gettlv); -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ ed = evb22_data((char *) &cmd->ifname, cmd->type); -+ if (!ed) -+ return cmd_invalid; -+ if (sprintf(s, "%i", (*fct)(ed)) <= 0) -+ return cmd_invalid; -+ snprintf(obuf, obuf_len, "%02x%s%04x%s", -+ (unsigned int)strlen(arg), arg, (unsigned int)strlen(s), s); -+ return cmd_success; -+} -+ -+static int get_arg_retries(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ return show_31bit(cmd, arg, argvalue, obuf, obuf_len, get_retries); -+} -+ -+static int set_arg_retries(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_31bit(cmd, arg, argvalue, false, set_retries, 7); -+} -+ -+static int test_arg_retries(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_31bit(cmd, arg, argvalue, true, 0, 7); -+} -+ -+static int get_arg_rte(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ return show_31bit(cmd, arg, argvalue, obuf, obuf_len, get_rte); -+} -+ -+static int set_arg_rte(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_31bit(cmd, arg, argvalue, false, set_rte, 31); -+} -+ -+static int test_arg_rte(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_31bit(cmd, arg, argvalue, true, 0, 31); -+} -+ -+static int get_arg_rwd(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ return show_31bit(cmd, arg, argvalue, obuf, obuf_len, get_rwd); -+} -+ -+static int set_arg_rwd(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_31bit(cmd, arg, argvalue, false, set_rwd, 31); -+} -+ -+static int test_arg_rwd(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_31bit(cmd, arg, argvalue, true, 0, 31); -+} -+ -+static int get_arg_rka(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ return show_31bit(cmd, arg, argvalue, obuf, obuf_len, get_rka); -+} -+ -+static int set_arg_rka(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_31bit(cmd, arg, argvalue, false, set_rka, 31); -+} -+ -+static int test_arg_rka(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return scan_31bit(cmd, arg, argvalue, true, 0, 31); -+} -+ -+static struct arg_handlers arg_handlers[] = { -+ { -+ .arg = EVB_CONF_RKA, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_rka, -+ .handle_set = set_arg_rka, -+ .handle_test = test_arg_rka -+ }, -+ { -+ .arg = EVB_CONF_RWD, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_rwd, -+ .handle_set = set_arg_rwd, -+ .handle_test = test_arg_rwd -+ }, -+ { -+ .arg = EVB_CONF_RTE, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_rte, -+ .handle_set = set_arg_rte, -+ .handle_test = test_arg_rte -+ }, -+ { -+ .arg = EVB_CONF_RETRIES, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_retries, -+ .handle_set = set_arg_retries, -+ .handle_test = test_arg_retries -+ }, -+ { -+ .arg = EVB_CONF_RRREQ, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_rrreq, -+ .handle_set = set_arg_rrreq, -+ .handle_test = test_arg_rrreq -+ }, -+ { -+ .arg = EVB_CONF_RRCAP, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_rrcap, -+ .handle_set = set_arg_rrcap, -+ .handle_test = test_arg_rrcap -+ }, -+ { -+ .arg = EVB_CONF_GPID, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_gpid, -+ .handle_set = set_arg_gpid, -+ .handle_test = test_arg_gpid -+ }, -+ { -+ .arg = EVB_CONF_MODE, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_evbmode, -+ .handle_set = set_arg_evbmode, -+ .handle_test = test_arg_evbmode -+ }, -+ { -+ .arg = ARG_TLVTXENABLE, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_tlvtxenable, -+ .handle_set = set_arg_tlvtxenable, -+ .handle_test = test_arg_tlvtxenable -+ }, -+ { -+ .arg = 0 -+ } -+}; -+ -+struct arg_handlers *evb22_get_arg_handlers() -+{ -+ return &arg_handlers[0]; -+} -diff --git a/lldp_evb_cmds.c b/lldp_evb_cmds.c -index 923d56d..eec4f33 100644 ---- a/lldp_evb_cmds.c -+++ b/lldp_evb_cmds.c -@@ -32,7 +32,7 @@ - - #include "lldp.h" - #include "lldp_evb.h" --#include "lldp_vdp.h" -+#include "qbg_vdp.h" - #include "lldp_tlv.h" - #include "lldp_mand_clif.h" - #include "config.h" -@@ -167,8 +167,12 @@ static int evb_cmdok(struct cmd *cmd, cmd_status expected) - { - if (cmd->cmd != expected) - return cmd_invalid; -+ - switch (cmd->tlvid) { - case TLVID_8021Qbg(LLDP_EVB_SUBTYPE): -+ if (cmd->type != NEAREST_CUSTOMER_BRIDGE) -+ return cmd_agent_not_supported; -+ - return cmd_success; - case INVALID_TLVID: - return cmd_invalid; -@@ -181,17 +185,19 @@ static int - get_arg_tlvtxenable(struct cmd *cmd, char *arg, UNUSED char *argvalue, - char *obuf, int obuf_len) - { -- struct evb_data *ed; -- char *s; - cmd_status good_cmd = evb_cmdok(cmd, cmd_gettlv); -+ char *s, arg_path[EVB_BUF_SIZE]; -+ int value; - - if (good_cmd != cmd_success) - return good_cmd; - -- ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (ed->txmit) -+ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -+ TLVID_PREFIX, cmd->tlvid, arg); -+ if (get_cfg(cmd->ifname, cmd->type, arg_path, &value, CONFIG_TYPE_BOOL)) -+ value = false; -+ -+ if (value) - s = VAL_YES; - else - s = VAL_NO; -@@ -221,10 +227,11 @@ static int _set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, - return cmd_bad_params; - - ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (vdp_vsis(ed->ifname)) -- return cmd_failed; -+ if (ed) { -+ if (vdp_vsis(ed->ifname)) -+ return cmd_failed; -+ } -+ - if (test) - return cmd_success; - -@@ -233,12 +240,14 @@ static int _set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, - - if (set_cfg(cmd->ifname, cmd->type, arg_path, &value, - CONFIG_TYPE_BOOL)){ -- LLDPAD_ERR("%s: error saving EVB enabletx (%s)\n", ed->ifname, -+ LLDPAD_ERR("%s: error saving EVB enabletx (%s)\n", cmd->ifname, - argvalue); - return cmd_failed; - } -- ed->txmit = value; -- LLDPAD_INFO("%s: changed EVB enabletx (%s)\n", ed->ifname, argvalue); -+ if (ed) -+ ed->txmit = value; -+ -+ LLDPAD_INFO("%s: changed EVB enabletx (%s)\n", cmd->ifname, argvalue); - somethingChangedLocal(cmd->ifname, cmd->type); - - return cmd_success; -@@ -253,26 +262,37 @@ static int set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, - static int test_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, - UNUSED char *obuf, UNUSED int obuf_len) - { -+ /* -+ * Make sure either evb draft 0.2 or evb ratified standard is -+ * running at the same time but not both. -+ */ -+ if (!strcasecmp(argvalue, VAL_YES) -+ && is_tlv_txenabled(cmd->ifname, cmd->type, -+ TLVID(OUI_IEEE_8021Qbg22, -+ LLDP_EVB22_SUBTYPE))) { -+ LLDPAD_ERR("%s:%s evb protocol already enabled\n", -+ __func__, cmd->ifname); -+ return cmd_failed; -+ } - return _set_arg_tlvtxenable(cmd, arg, argvalue, true); - } - - static int get_arg_fmode(struct cmd *cmd, char *arg, UNUSED char *argvalue, - char *obuf, int obuf_len) - { -- char *s; -- struct evb_data *ed; - cmd_status good_cmd = evb_cmdok(cmd, cmd_gettlv); -+ char *s; -+ u8 mode; - - if (good_cmd != cmd_success) - return good_cmd; - -- ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (ed->policy.smode & LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY) -+ mode = evb_conf_fmode(cmd->ifname, cmd->type); -+ if (mode & LLDP_EVB_CAPABILITY_FORWARD_REFLECTIVE_RELAY) - s = VAL_EVB_FMODE_REFLECTIVE_RELAY; - else - s = VAL_EVB_FMODE_BRIDGE; -+ - snprintf(obuf, obuf_len, "%02x%s%04x%s", - (unsigned int)strlen(arg), arg, (unsigned int)strlen(s), s); - return cmd_success; -@@ -296,25 +316,28 @@ static int _set_arg_fmode(struct cmd *cmd, const char *argvalue, bool test) - return cmd_bad_params; - - ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (vdp_vsis(ed->ifname)) -- return cmd_failed; -+ if (ed) { -+ if (vdp_vsis(ed->ifname)) -+ return cmd_failed; -+ } -+ - if (test) - return cmd_success; - - snprintf(arg_path, sizeof(arg_path), "%s%08x.fmode", - TLVID_PREFIX, cmd->tlvid); - -- if (set_cfg(ed->ifname, cmd->type, arg_path, &argvalue, -+ if (set_cfg(cmd->ifname, cmd->type, arg_path, &argvalue, - CONFIG_TYPE_STRING)) { - LLDPAD_ERR("%s: saving EVB forwarding mode failed\n", -- ed->ifname); -+ cmd->ifname); - return cmd_failed; - } - -- ed->policy.smode = smode; -- LLDPAD_INFO("%s: changed EVB forwarding mode (%s)\n", ed->ifname, -+ if (ed) -+ ed->policy.smode = smode; -+ -+ LLDPAD_INFO("%s: changed EVB forwarding mode (%s)\n", cmd->ifname, - argvalue); - somethingChangedLocal(cmd->ifname, cmd->type); - return cmd_success; -@@ -338,27 +361,25 @@ get_arg_capabilities(struct cmd *cmd, char *arg, UNUSED char *argvalue, - { - int comma = 0; - char t[EVB_BUF_SIZE]; -- struct evb_data *ed; -+ u8 scap; - cmd_status good_cmd = evb_cmdok(cmd, cmd_gettlv); - - if (good_cmd != cmd_success) - return good_cmd; -- ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; - -+ scap = evb_conf_capa(cmd->ifname, cmd->type); - memset(t, 0, sizeof t); -- if (ed->policy.scap & LLDP_EVB_CAPABILITY_PROTOCOL_RTE) { -+ if (scap & LLDP_EVB_CAPABILITY_PROTOCOL_RTE) { - strcat(t, VAL_EVB_CAPA_RTE); - comma = 1; - } -- if (ed->policy.scap & LLDP_EVB_CAPABILITY_PROTOCOL_ECP) { -+ if (scap & LLDP_EVB_CAPABILITY_PROTOCOL_ECP) { - if (comma) - strcat(t, " "); - strcat(t, VAL_EVB_CAPA_ECP); - comma = 1; - } -- if (ed->policy.scap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP) { -+ if (scap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP) { - if (comma) - strcat(t, " "); - strcat(t, VAL_EVB_CAPA_VDP); -@@ -415,25 +436,25 @@ _set_arg_capabilities(struct cmd *cmd, const char *argvalue, bool test) - return cmd_bad_params; - - ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (vdp_vsis(ed->ifname)) -- return cmd_failed; -+ if (ed) -+ if (vdp_vsis(ed->ifname)) -+ return cmd_failed; - if (test) - return cmd_success; - - snprintf(arg_path, sizeof(arg_path), "%s%08x.capabilities", - TLVID_PREFIX, cmd->tlvid); - -- if (set_cfg(ed->ifname, cmd->type, arg_path, &argvalue, -+ if (set_cfg(cmd->ifname, cmd->type, arg_path, &argvalue, - CONFIG_TYPE_STRING)) { - LLDPAD_ERR("%s: saving EVB capabilities (%#x) failed\n", -- ed->ifname, scap); -+ cmd->ifname, scap); - return cmd_failed; - } - -- ed->policy.scap = scap; -- LLDPAD_INFO("%s: changed EVB capabilities (%#x)\n", ed->ifname, scap); -+ if (ed) -+ ed->policy.scap = scap; -+ LLDPAD_INFO("%s: changed EVB capabilities (%#x)\n", cmd->ifname, scap); - somethingChangedLocal(cmd->ifname, cmd->type); - - return cmd_success; -@@ -457,17 +478,15 @@ static int get_arg_rte(struct cmd *cmd, char *arg, UNUSED char *argvalue, - char *obuf, int obuf_len) - { - char s[EVB_BUF_SIZE]; -- struct evb_data *ed; -+ u8 rte; - cmd_status good_cmd = evb_cmdok(cmd, cmd_gettlv); - - if (good_cmd != cmd_success) - return good_cmd; - -- ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -+ rte = evb_conf_rte(cmd->ifname, cmd->type); - -- if (sprintf(s, "%i", ed->policy.rte) <= 0) -+ if (sprintf(s, "%i", rte) <= 0) - return cmd_invalid; - - snprintf(obuf, obuf_len, "%02x%s%04x%s", -@@ -491,24 +510,24 @@ static int _set_arg_rte(struct cmd *cmd, const char *argvalue, bool test) - return cmd_bad_params; - - ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (vdp_vsis(ed->ifname)) -- return cmd_failed; -+ if (ed) -+ if (vdp_vsis(ed->ifname)) -+ return cmd_failed; - if (test) - return cmd_success; - - snprintf(arg_path, sizeof(arg_path), "%s%08x.rte", TLVID_PREFIX, - cmd->tlvid); -- if (set_cfg(ed->ifname, cmd->type, arg_path, &argvalue, -+ if (set_cfg(cmd->ifname, cmd->type, arg_path, &argvalue, - CONFIG_TYPE_STRING)){ -- LLDPAD_ERR("%s: error saving EVB rte (%d)\n", ed->ifname, -+ LLDPAD_ERR("%s: error saving EVB rte (%d)\n", cmd->ifname, - value); - return cmd_failed; - } - -- ed->policy.rte = value; -- LLDPAD_INFO("%s: changed EVB rte (%#x)\n", ed->ifname, value); -+ if (ed) -+ ed->policy.rte = value; -+ LLDPAD_INFO("%s: changed EVB rte (%#x)\n", cmd->ifname, value); - somethingChangedLocal(cmd->ifname, cmd->type); - - return cmd_success; -@@ -530,16 +549,15 @@ static int get_arg_vsis(struct cmd *cmd, char *arg, UNUSED char *argvalue, - char *obuf, int obuf_len) - { - char s[EVB_BUF_SIZE]; -- struct evb_data *ed; -+ u16 svsi; - cmd_status good_cmd = evb_cmdok(cmd, cmd_gettlv); - - if (good_cmd != cmd_success) - return good_cmd; - -- ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (sprintf(s, "%04i", ed->policy.svsi) <= 0) -+ svsi = evb_conf_vsis(cmd->ifname, cmd->type); -+ -+ if (sprintf(s, "%04i", svsi) <= 0) - return cmd_invalid; - snprintf(obuf, obuf_len, "%02x%s%04x%s", - (unsigned int)strlen(arg), arg, (unsigned int)strlen(s), s); -@@ -561,24 +579,24 @@ static int _set_arg_vsis(struct cmd *cmd, const char *argvalue, bool test) - return cmd_bad_params; - - ed = evb_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (vdp_vsis(ed->ifname)) -- return cmd_failed; -+ if (ed) -+ if (vdp_vsis(ed->ifname)) -+ return cmd_failed; - if (test) - return cmd_success; - - snprintf(arg_path, sizeof(arg_path), "%s%08x.vsis", TLVID_PREFIX, - cmd->tlvid); -- if (set_cfg(ed->ifname, cmd->type, arg_path, &argvalue, -+ if (set_cfg(cmd->ifname, cmd->type, arg_path, &argvalue, - CONFIG_TYPE_STRING)){ -- LLDPAD_ERR("%s: error saving EVB vsi (%d)\n", ed->ifname, -+ LLDPAD_ERR("%s: error saving EVB vsi (%d)\n", cmd->ifname, - value); - return cmd_failed; - } - -- ed->policy.svsi = htons(value); -- LLDPAD_INFO("%s: changed EVB vsis (%#x)\n", ed->ifname, value); -+ if (ed) -+ ed->policy.svsi = htons(value); -+ LLDPAD_INFO("%s: changed EVB vsis (%#x)\n", cmd->ifname, value); - somethingChangedLocal(cmd->ifname, cmd->type); - - return cmd_success; -diff --git a/lldp_mand.c b/lldp_mand.c -index 943070f..b269d3f 100644 ---- a/lldp_mand.c -+++ b/lldp_mand.c -@@ -464,8 +464,9 @@ out_err: - static int mand_bld_tlv(struct mand_data *md, struct lldp_agent *agent) - { - int rc = EPERM; -+ int ifindex = get_ifidx(md->ifname); - -- if (!port_find_by_name(md->ifname)) { -+ if (!port_find_by_ifindex(ifindex)) { - rc = EEXIST; - goto out_err; - } -@@ -655,13 +656,13 @@ void mand_unregister(struct lldp_module *mod) - struct mand_data *md; - - nameidx = if_nameindex(); -- if (nameidx == NULL) { -+ if (!nameidx) { - LLDPAD_DBG("error calling if_nameindex()\n"); - return; - } - - for (p = nameidx; p->if_index != 0; p++) { -- port = port_find_by_name(p->if_name); -+ port = port_find_by_ifindex(p->if_index); - if (!port) - continue; - -diff --git a/lldp_mand_cmds.c b/lldp_mand_cmds.c -index aedb8dc..532337b 100644 ---- a/lldp_mand_cmds.c -+++ b/lldp_mand_cmds.c -@@ -78,17 +78,12 @@ static struct arg_handlers arg_handlers[] = { - static int get_mand_subtype(struct cmd *cmd, char *arg, UNUSED char *argvalue, - char *obuf, int obuf_len) - { -- struct mand_data *md; - int subtype; - char *string, arg_path[256]; - - if (cmd->cmd != cmd_gettlv) - return cmd_invalid; - -- md = mand_data(cmd->ifname, cmd->type); -- if (!md) -- return cmd_device_not_found; -- - switch (cmd->tlvid) { - case CHASSIS_ID_TLV: - snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -@@ -183,8 +178,6 @@ static int _set_mand_subtype(struct cmd *cmd, char *arg, char *argvalue, - return cmd_invalid; - - md = mand_data(cmd->ifname, cmd->type); -- if (!md) -- return cmd_device_not_found; - - switch (cmd->tlvid) { - case CHASSIS_ID_TLV: -@@ -261,9 +254,11 @@ static int _set_mand_subtype(struct cmd *cmd, char *arg, char *argvalue, - if (test) - return cmd_success; - -- md->read_shm = 1; -- md->rebuild_chassis = 1; -- md->rebuild_portid = 1; -+ if (md) { -+ md->read_shm = 1; -+ md->rebuild_chassis = 1; -+ md->rebuild_portid = 1; -+ } - - snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, - cmd->tlvid, arg); -@@ -570,6 +565,10 @@ int get_tlvs(struct cmd *cmd, char *rbuf, int rlen) - u16 type, len; - int res; - -+ /* VDP 0.2 protocol for nearest customer bridge only */ -+ if (cmd->tlvid == (OUI_IEEE_8021Qbg << 8) -+ && cmd->type != NEAREST_CUSTOMER_BRIDGE) -+ return cmd_agent_not_supported; - if (cmd->ops & op_local) { - res = get_local_tlvs(cmd->ifname, cmd->type, &tlvs[0], &size); - if (res) -@@ -652,7 +651,6 @@ int mand_clif_cmd(UNUSED void *data, - char *rbuf, int rlen) - { - struct cmd cmd; -- struct port *port; - u8 len, version; - int ioff, roff; - int rstatus = cmd_invalid; -@@ -727,9 +725,8 @@ int mand_clif_cmd(UNUSED void *data, - (unsigned int)strlen(cmd.ifname), cmd.ifname); - roff = strlen(rbuf); - -- /* Confirm port is a lldpad managed port */ -- port = port_find_by_name(cmd.ifname); -- if (!port) { -+ /* Confirm port is a valid LLDP port */ -+ if (!get_ifidx(cmd.ifname) || !is_valid_lldp_device(cmd.ifname)) { - free(argvals); - free(args); - return cmd_device_not_found; -diff --git a/lldp_med.c b/lldp_med.c -index db83eaf..77ec20d 100644 ---- a/lldp_med.c -+++ b/lldp_med.c -@@ -686,39 +686,32 @@ out_err: - * @md: the med data struct - * - * Returns 0 for success or error code for failure -- * - */ --static int med_bld_tlv(struct med_data *md, -- struct lldp_agent *agent) -+static int med_bld_tlv(struct med_data *md, struct lldp_agent *agent) - { -- int rc = EPERM; -- -- if (!port_find_by_name(md->ifname)) { -- rc = EEXIST; -- goto out_err; -- } -+ if (!port_find_by_ifindex(get_ifidx(md->ifname))) -+ return -EEXIST; - - /* no build if not enabled */ - if (!is_tlv_txenabled(md->ifname, agent->type, - TLVID_MED(LLDP_MED_RESERVED))) { - LLDPAD_DBG("%s:%s:LLDP-MED is not enabled\n", -- __func__, md->ifname); -- rc = 0; -- goto out_err; -+ __func__, md->ifname); -+ return 0; - } - - /* no build if enabled no devtype is given */ - if (!LLDP_MED_DEVTYPE_DEFINED(get_med_devtype(md->ifname, agent->type))) { - LLDPAD_DBG("%s:%s:LLDP-MED devtype is not defined\n", -- __func__, md->ifname); -- goto out_err; -+ __func__, md->ifname); -+ return -EPERM; - } - - /* MED Cap is always mandatory for MED */ - if (med_bld_medcaps_tlv(md, agent)) { - LLDPAD_DBG("%s:%s:MED Capabilities TLV is mandatory!\n", -- __func__, md->ifname); -- goto out_err; -+ __func__, md->ifname); -+ return -EPERM; - } - - /* MAC PHY TLV is mandatory for MED */ -@@ -726,8 +719,7 @@ static int med_bld_tlv(struct med_data *md, - TLVID_8023(LLDP_8023_MACPHY_CONFIG_STATUS))) { - LLDPAD_DBG("%s:%s MAC PHY Config is mandatory for MED\n", - __func__, md->ifname); -- rc = ENOTTY; -- goto out_err; -+ return -ENOTTY; - } - - /* Build optional and conditional ones based on device type: -@@ -757,32 +749,28 @@ static int med_bld_tlv(struct med_data *md, - * - Extended Power-via-MDI: mandatory only for - * 802.3.af PSE - * - Inventory: optional -- * - */ - if (med_bld_netpoli_tlv(md, agent)) { - LLDPAD_DBG("%s:%s:med_bld_netpoli_tlv() failed\n", -- __func__, md->ifname); -- goto out_err; -+ __func__, md->ifname); -+ return -EPERM; - } - if (med_bld_locid_tlv(md, agent)) { - LLDPAD_DBG("%s:%s:med_bld_locid_tlv() failed\n", -- __func__, md->ifname); -- goto out_err; -+ __func__, md->ifname); -+ return -EPERM; - } - if (med_bld_powvmdi_tlv(md, agent)) { - LLDPAD_DBG("%s:%s:med_bld_powvmdi_tlv() failed\n", -- __func__, md->ifname); -- goto out_err; -+ __func__, md->ifname); -+ return -EPERM; - } - if (med_bld_inventory_tlv(md, agent)) { - LLDPAD_DBG("%s:%s:med_bld_inventory_tlv() failed\n", -- __func__, md->ifname); -- goto out_err; -+ __func__, md->ifname); -+ return -EPERM; - } -- rc = 0; -- --out_err: -- return rc; -+ return 0; - } - - /* -diff --git a/lldp_qbg_utils.c b/lldp_qbg_utils.c -deleted file mode 100644 -index 04491de..0000000 ---- a/lldp_qbg_utils.c -+++ /dev/null -@@ -1,95 +0,0 @@ --/****************************************************************************** -- -- Implementation of ECP according to 802.1Qbg -- (c) Copyright IBM Corp. 2010, 2013 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --/* -- * This file contains common support utilities for the ECP protocols. -- */ -- --#include --#include -- --#include "lldp.h" --#include "lldp_mod.h" --#include "messages.h" --#include "lldp_qbg_utils.h" -- --extern int loglvl; /* Global lldpad log level */ --extern struct lldp_head lldp_head; -- --/* -- * hexdump_frame - print raw evb/ecp/vdp frame -- */ --void hexdump_frame(const char *ifname, char *txt, const unsigned char *buf, -- size_t len) --{ -- size_t i; -- int left = 0; -- char buffer[ETH_FRAME_LEN * 3]; -- -- /* Only collect data when the loglvl ensures data printout */ -- if (LOG_DEBUG < loglvl) -- return; -- for (i = 0; i < len; i++) { -- int c; -- c = snprintf(buffer + left, sizeof buffer - left, "%02x%c", -- buf[i], !((i + 1) % 16) ? '\n' : ' '); -- if (c > 0 && (c < (int)sizeof buffer - left)) -- left += c; -- } -- LLDPAD_DBG("%s:%s %s\n%s\n", __func__, ifname, txt, buffer); --} -- --/* -- * Function to advertise changed variables to other modules. -- * -- * Parameters are interface name, target module id and data. -- * When sending the data, the module call back function contains the -- * module id of the sender. -- * -- * Return 0 when no addressee found or addressess found but addressee was -- * unable to handle data. -- */ --int modules_notify(int id, int sender_id, char *ifname, void *data) --{ -- struct lldp_module *mp = find_module_by_id(&lldp_head, id); -- int rc = 0; -- -- if (mp && mp->ops->lldp_mod_notify) -- rc = mp->ops->lldp_mod_notify(sender_id, ifname, data); -- LLDPAD_DBG("%s:%s target-id:%#x rc:%d\n", __func__, ifname, id, rc); -- return rc; --} -- --int vdp_uuid2str(const u8 *p, char *dst, size_t size) --{ -- if (dst && size > VDP_UUID_STRLEN) { -- snprintf(dst, size, "%02x%02x%02x%02x-%02x%02x-%02x%02x" -- "-%02x%02x-%02x%02x%02x%02x%02x%02x", -- p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], -- p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); -- return 0; -- } -- return -1; --} -diff --git a/lldp_rtnl.c b/lldp_rtnl.c -index 0c57e62..33b4d19 100644 ---- a/lldp_rtnl.c -+++ b/lldp_rtnl.c -@@ -46,45 +46,6 @@ - - #define NLMSG_SIZE 1024 - --/* -- * Helper functions to construct a netlink message. -- * The functions assume the nlmsghdr.nlmsg_len is set correctly. -- */ --void mynla_nest_end(struct nlmsghdr *nlh, struct nlattr *start) --{ -- start->nla_type |= NLA_F_NESTED; -- start->nla_len = (void *)nlh + nlh->nlmsg_len - (void *)start; --} -- --struct nlattr *mynla_nest_start(struct nlmsghdr *nlh, int type) --{ -- struct nlattr *ap = (struct nlattr *)((void *)nlh + nlh->nlmsg_len); -- -- ap->nla_type = type; -- nlh->nlmsg_len += NLA_HDRLEN; -- return ap; --} -- --void mynla_put(struct nlmsghdr *nlh, int type, size_t len, void *data) --{ -- struct nlattr *ap = (struct nlattr *)((void *)nlh + nlh->nlmsg_len); -- -- ap->nla_type = type; -- ap->nla_len = NLA_HDRLEN + len; -- memcpy(ap + 1, data, len); -- nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(len); --} -- --void mynla_put_u16(struct nlmsghdr *nlh, int type, __u16 data) --{ -- mynla_put(nlh, type, sizeof data, &data); --} -- --void mynla_put_u32(struct nlmsghdr *nlh, int type, __u32 data) --{ -- mynla_put(nlh, type, sizeof data, &data); --} -- - typedef int rtnl_handler(struct nlmsghdr *nh, void *arg); - - /** -@@ -173,7 +134,7 @@ static ssize_t rtnl_send_linkmode(int s, int ifindex, - return send(s, &req, req.nh.nlmsg_len, 0); - } - --static int rtnl_set_linkmode(int ifindex, const char *ifname, __u8 linkmode) -+int set_linkmode(int ifindex, const char *ifname, __u8 linkmode) - { - int s; - int rc; -@@ -301,11 +262,6 @@ int get_operstate(char *ifname) - return operstate; - } - --int set_linkmode(const char *ifname, __u8 linkmode) --{ -- return rtnl_set_linkmode(0, ifname, linkmode); --} -- - int get_perm_hwaddr(const char *ifname, u8 *buf_perm, u8 *buf_san) - { - int s; -diff --git a/lldp_util.c b/lldp_util.c -index 4a1cc4a..754b0cd 100644 ---- a/lldp_util.c -+++ b/lldp_util.c -@@ -308,9 +308,17 @@ int get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr) - return 1; - } - -+/* -+ * Return true if the mac address is valid (non-zero and no hardware -+ * broadcast address) -+ */ - int is_valid_mac(const u8 *mac) - { -- return !!(mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]); -+ if (0 == (mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5])) -+ return 0; -+ if (0xff == (mac[0] & mac[1] & mac[2] & mac[3] & mac[4] & mac[5])) -+ return 0; -+ return 1; - } - - int read_int(const char *path) -@@ -349,6 +357,25 @@ int get_ifflags(const char *ifname) - return flags; - } - -+int get_ifname(int ifindex, char *ifname) -+{ -+ int fd; -+ int rc; -+ struct ifreq ifr; -+ -+ memset(&ifr, 0, sizeof(ifr)); -+ fd = get_ioctl_socket(); -+ if (fd < 0) -+ return -1; -+ -+ ifr.ifr_ifindex = ifindex; -+ rc = ioctl(fd, SIOCGIFNAME, &ifr); -+ if (rc >= 0) -+ memcpy(ifname, ifr.ifr_name, IFNAMSIZ); -+ -+ return rc; -+} -+ - int get_ifpflags(const char *ifname) - { - int fd; -@@ -1185,7 +1212,7 @@ int get_arg_val_list(char *ibuf, int ilen, int *ioff, - *ioff += arglen; - *(arglens+i) = arglen; - -- if (ilen - *ioff > 2 * (int)sizeof(argvalue_len)) { -+ if (ilen - *ioff >= 2 * (int)sizeof(argvalue_len)) { - hexstr2bin(ibuf+*ioff, (u8 *)&argvalue_len, - sizeof(argvalue_len)); - argvalue_len = ntohs(argvalue_len); -diff --git a/lldp_vdp.c b/lldp_vdp.c -deleted file mode 100644 -index 57133d1..0000000 ---- a/lldp_vdp.c -+++ /dev/null -@@ -1,1916 +0,0 @@ --/****************************************************************************** -- -- Implementation of VDP according to IEEE 802.1Qbg -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Jens Osterkamp -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include "lldp.h" --#include "lldp_vdp.h" --#include "lldp_vdpnl.h" --#include "eloop.h" --#include "lldp_evb.h" --#include "messages.h" --#include "config.h" --#include "lldp_tlv.h" --#include "lldp_vdp_cmds.h" --#include "lldp_qbg_utils.h" --#include "lldp_mand_clif.h" -- --/* Define Module id. Must match with value in lldp_vdp_clif.c */ --#define LLDP_MOD_VDP02 ((LLDP_MOD_VDP << 8) | LLDP_VDP_SUBTYPE) -- --static const char * const vsi_responses[] = { -- [VDP_RESPONSE_SUCCESS] = "success", -- [VDP_RESPONSE_INVALID_FORMAT] = "invalid format", -- [VDP_RESPONSE_INSUFF_RESOURCES] = "insufficient resources", -- [VDP_RESPONSE_UNUSED_VTID] = "unused VTID", -- [VDP_RESPONSE_VTID_VIOLATION] = "VTID violation", -- [VDP_RESPONSE_VTID_VER_VIOLATION] = "VTID version violation", -- [VDP_RESPONSE_OUT_OF_SYNC] = "out of sync", -- [VDP_RESPONSE_UNKNOWN] = "unknown response", -- [VDP_RESPONSE_NO_RESPONSE] = "no response", --}; -- --const char * const vsi_states[] = { -- [VSI_UNASSOCIATED] = "VSI_UNASSOCIATED", -- [VSI_ASSOC_PROCESSING] = "VSI_ASSOC_PROCESSING", -- [VSI_ASSOCIATED] = "VSI_ASSOCIATED", -- [VSI_PREASSOC_PROCESSING] = "VSI_PREASSOC_PROCESSING", -- [VSI_PREASSOCIATED] = "VSI_PREASSOCIATED", -- [VSI_DEASSOC_PROCESSING] = "VSI_DEASSOC_PROCESSING", -- [VSI_EXIT] = "VSI_EXIT", --}; -- --int vdp_start_localchange_timer(struct vsi_profile *p); --int vdp_remove_profile(struct vsi_profile *profile); --int vdp_trigger(struct vsi_profile *profile); -- --void vdp_trace_profile(struct vsi_profile *p) --{ -- char instance[VDP_UUID_STRLEN + 2]; -- struct mac_vlan *mac_vlan; -- -- vdp_uuid2str(p->instance, instance, sizeof(instance)); -- -- LLDPAD_DBG("profile:%p mode:%d response:%d state:%d (%s) no_nlmsg:%d" -- " txmit:%i" -- " mgrid:%d id:%d(%#x) version:%d %s format:%d entries:%d\n", -- p, p->mode, p->response, p->state, vsi_states[p->state], -- p->no_nlmsg, p->txmit, -- p->mgrid, p->id, p->id, p->version, instance, p->format, -- p->entries); -- LIST_FOREACH(mac_vlan, &p->macvid_head, entry) { -- char macbuf[MAC_ADDR_STRLEN + 1]; -- -- mac2str(mac_vlan->mac, macbuf, MAC_ADDR_STRLEN); -- LLDPAD_DBG("profile:%p mac:%s vlan:%d qos:%d pid:%d seq:%d\n", -- p, macbuf, mac_vlan->vlan, mac_vlan->qos, -- mac_vlan->req_pid, mac_vlan->req_seq); -- } --} -- --struct vsi_profile *vdp_alloc_profile() --{ -- struct vsi_profile *prof; -- -- prof = calloc(1, sizeof *prof); -- if (prof) -- LIST_INIT(&prof->macvid_head); -- return prof; --} -- --/* -- * vdp_remove_macvlan - remove all mac/vlan pairs in the profile -- * @profile: profile to remove -- * -- * Remove all allocated pairs on the profile. -- */ --static void vdp_remove_macvlan(struct vsi_profile *profile) --{ -- struct mac_vlan *p; -- -- while ((p = LIST_FIRST(&profile->macvid_head))) { -- LIST_REMOVE(p, entry); -- free(p); -- } --} -- --void vdp_delete_profile(struct vsi_profile *prof) --{ -- vdp_remove_macvlan(prof); -- free(prof); --} -- --/* vdp_profile_equal - checks for equality of 2 profiles -- * @p1: profile 1 -- * @p2: profile 2 -- * -- * returns true if equal, false if not -- * -- * compares mgrid, id, version, instance 2 vsi profiles to find -- * out if they are equal. -- */ --static bool vdp_profile_equal(struct vsi_profile *p1, struct vsi_profile *p2) --{ -- if (p1->mgrid != p2->mgrid) -- return false; -- -- if (p1->id != p2->id) -- return false; -- -- if (p1->version != p2->version) -- return false; -- -- if (memcmp(p1->instance, p2->instance, 16)) -- return false; -- -- return true; --} -- --/* -- * vdp_find_profile - Find a profile in the list of profiles already allocated -- * -- * Returns pointer to already allocated profile in list, 0 if not. -- */ -- --struct vsi_profile *vdp_find_profile(struct vdp_data *vd, -- struct vsi_profile *thisone) --{ -- struct vsi_profile *p; -- -- LIST_FOREACH(p, &vd->profile_head, profile) { -- if (vdp_profile_equal(p, thisone)) -- return p; -- } -- return 0; --} -- --/* vdp_data - searches vdp_data in the list of modules for this port -- * @ifname: interface name to search for -- * -- * returns vdp_data on success, NULL on error -- * -- * searches the list of user_data for the VDP module user_data. -- */ --struct vdp_data *vdp_data(char *ifname) --{ -- struct vdp_user_data *ud; -- struct vdp_data *vd = NULL; -- -- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP02); -- if (ud) { -- LIST_FOREACH(vd, &ud->head, entry) { -- if (!strncmp(ifname, vd->ifname, IFNAMSIZ)) -- return vd; -- } -- } -- return NULL; --} -- --/* vdp_free_tlv - free tlv in vdp_data -- * @vd: vdp_data -- * -- * no return value -- * -- * frees up tlv in vdp_data. used in vdp_free_data. -- */ --static void vdp_free_tlv(struct vdp_data *vd) --{ -- if (vd) { -- FREE_UNPKD_TLV(vd, vdp); -- } --} -- --/* vdp_free_data - frees up vdp data -- * @ud: user data structure -- * -- * no return value -- * -- * removes vd_structure from the user_data list. frees up tlv in vdp_data. -- * used in vdp_unregister. -- */ --static void vdp_free_data(struct vdp_user_data *ud) --{ -- struct vdp_data *vd; -- if (ud) { -- while (!LIST_EMPTY(&ud->head)) { -- vd = LIST_FIRST(&ud->head); -- LIST_REMOVE(vd, entry); -- vdp_free_tlv(vd); -- free(vd); -- } -- } --} -- --/* vdp_response2str - map response to string -- * @response: response received -- * -- * no return value -- * -- * maps VDP response received for a profile to human readable string for -- * printing. -- */ --const char *vdp_response2str(int response) --{ -- if ((response >= VDP_RESPONSE_SUCCESS) && -- (response <= VDP_RESPONSE_OUT_OF_SYNC)) -- return vsi_responses[response]; -- -- if (response == VDP_RESPONSE_NO_RESPONSE) -- return vsi_responses[VDP_RESPONSE_NO_RESPONSE]; -- -- return vsi_responses[VDP_RESPONSE_UNKNOWN]; --} -- --/* vdp_ack_profiles - clear ackReceived for all profiles with seqnr -- * @vd: vd for the interface -- * @seqnr: seqnr the ack has been received with -- * -- * no return value -- * -- * clear the ackReceived for all profiles which have been sent out with -- * the seqnr that we now have received the ecp ack for. -- */ --void vdp_ack_profiles(struct vdp_data *vd, int seqnr) --{ -- struct vsi_profile *p; -- -- LIST_FOREACH(p, &vd->profile_head, profile) { -- if (p->seqnr == seqnr) { -- p->ackReceived = false; -- p->txmit = true; -- } -- } -- --} -- --/* vdp_vsis - find out number of VSIs for this interface -- * @ifname: interfac name -- * -- * returns the number of VSIs -- * -- * walk through the list of VSIs and return the count. -- */ --int vdp_vsis(char *ifname) --{ -- struct vdp_data *vd; -- struct vsi_profile *p; -- int count = 0; -- -- vd = vdp_data(ifname); -- -- if (!vd) -- return 0; -- -- LIST_FOREACH(p, &vd->profile_head, profile) { -- count++; -- } -- -- return count; --} -- --/* vdp_vsis_pending - check for pending VSIs -- * @vd: vdp data for the interface -- * -- * returns the number of VSIs found -- * -- * walk through the list of VSIs and return the count. -- */ --int vdp_vsis_pending(struct vdp_data *vd) --{ -- struct vsi_profile *p; -- int count = 0; -- -- LIST_FOREACH(p, &vd->profile_head, profile) { -- if (p->localChange && (p->txmit == false)) -- count++; -- } -- -- return count; --} -- --/* vdp_somethingChangedLocal - set flag if profile has changed -- * @profile: profile to set the flag for -- * @flag: set the flag to true or false -- * -- * no return value -- * -- * set the localChange flag with a mode to indicate a profile has changed. -- * used next time when a ecpdu with profiles is sent out. -- */ --void vdp_somethingChangedLocal(struct vsi_profile *profile, bool flag) --{ -- LLDPAD_DBG("%s: setting profile->localChange to %s\n", -- __func__, (flag == true) ? "true" : "false"); -- -- profile->localChange = flag; -- -- if (flag == true) -- vdp_start_localchange_timer(profile); --} -- --/* vdp_keepaliveTimer_expired - checks for expired ack timer -- * @profile: profile to be checked -- * -- * returns true or false -- * -- * returns value of profile->keepaliveTimerExpired, true if ack timer has -- * expired, * false otherwise. -- */ --static bool vdp_keepaliveTimer_expired(struct vsi_profile *profile) --{ -- return (profile->keepaliveTimer == 0); --} -- --/* vdp_ackTimer_expired - checks for expired ack timer -- * @profile: profile to be checked -- * -- * returns true or false -- * -- * returns value of profile->ackTimerExpired, true if ack timer has expired, -- * false otherwise. -- */ --static bool vdp_ackTimer_expired(struct vsi_profile *profile) --{ -- return (profile->ackTimer == 0); --} -- --/* vdp_localchange_handler - triggers in case of vdp_ack or on vdp -- * localchange -- * @eloop_data: data structure of event loop -- * @user_ctx: user context, vdp_data here -- * -- * no return value -- * -- * called from vdp_somethingchangedlocal or vdp_ack_profiles when a change is -- * pending. Calls the VDP station state machine. This detour is taken -- * to not having to call the vdp code from the ecp state machine. Instead, we -- * return to the event loop, giving other code a chance to do work. -- */ --void vdp_localchange_handler(UNUSED void *eloop_data, void *user_ctx) --{ -- struct vsi_profile *p; -- -- p = (struct vsi_profile *) user_ctx; -- -- if ((p->ackReceived) || (p->localChange)) { -- LLDPAD_DBG("%s: p->localChange %i p->ackReceived %i\n", -- __func__, p->localChange, p->ackReceived); -- vdp_vsi_sm_station(p); -- } --} -- --/* -- * vdp_stop - cancel the VDP localchange timer -- * -- * returns 0 on success, -1 on error -- * -- * cancels the VPP localchange timer when a profile has been deleted. -- */ --int vdp_stop_localchange_timer(struct vsi_profile *p) --{ -- return eloop_cancel_timeout(vdp_localchange_handler, NULL, (void *) p); --} -- --/* vdp_start_localchange_timer - starts the VDP localchange timer -- * @vd: vdp_data for the interface -- * -- * returns 0 on success, -1 on error -- * -- * starts the VPP localchange timer when a localchange has been signaled from -- * the VDP state machine. -- */ --int vdp_start_localchange_timer(struct vsi_profile *p) --{ -- unsigned int usecs; -- -- usecs = VDP_LOCALCHANGE_TIMEOUT; -- -- return eloop_register_timeout(0, usecs, vdp_localchange_handler, NULL, -- (void *) p); --} -- --/* vdp_ack_timeout_handler - handles the ack timer expiry -- * @eloop_data: data structure of event loop -- * @user_ctx: user context, vdp_data here -- * -- * no return value -- * -- * called when the VDP ack timer for a profile has expired. -- * Calls the VDP station state machine for the profile. -- */ --void vdp_ack_timeout_handler(UNUSED void *eloop_data, void *user_ctx) --{ -- struct vsi_profile *p = (struct vsi_profile *) user_ctx; -- -- if (p->ackTimer > 0) -- p->ackTimer -= VDP_ACK_TIMER_DEFAULT; -- -- if (vdp_ackTimer_expired(p)) { -- LLDPAD_DBG("%s: profile %#02x vdp_ackTimer_expired %i" -- " p->ackReceived %i\n", __func__, p->instance[15], -- vdp_ackTimer_expired(p), p->ackReceived); -- vdp_vsi_sm_station(p); -- } --} -- --/* vdp_start_ack_timer - starts the VDP profile ack timer -- * @profile: vsi_profile -- * -- * returns 0 on success, -1 on error -- * -- * starts the VDP profile ack timer when a profile has been handed to ecp for -- * transmission. -- */ --static int vdp_start_ackTimer(struct vsi_profile *profile) --{ -- unsigned int usecs; -- -- usecs = VDP_ACK_TIMER_DEFAULT; -- -- profile->ackTimer = VDP_ACK_TIMER_DEFAULT; -- -- LLDPAD_DBG("%s: %s starting ack timer for %#02x (%i)\n", -- __func__, profile->port->ifname, -- profile->instance[15], profile->ackTimer); -- -- return eloop_register_timeout(0, usecs, vdp_ack_timeout_handler, NULL, -- (void *)profile); --} -- --/* vdp_stop_ackTimer - stops the VDP profile ack timer -- * @vd: vdp_data for the interface -- * -- * returns the number of removed handlers -- * -- * stops the VDP tck imer. Used e.g. when the host interface goes down. -- */ --static int vdp_stop_ackTimer(struct vsi_profile *profile) --{ -- LLDPAD_DBG("%s: %s stopping ack timer for %#02x (%i)\n", __func__, -- profile->port->ifname, profile->instance[15], -- profile->ackTimer); -- -- return eloop_cancel_timeout(vdp_ack_timeout_handler, NULL, -- (void *)profile); --} -- --/* vdp_keepalive_timeout_handler - handles the keepalive timer expiry -- * @eloop_data: data structure of event loop -- * @user_ctx: user context, vdp_data here -- * -- * no return value -- * -- * called when the VDP keepalive timer for a profile has expired. -- * Calls the VDP station state machine for the profile. -- */ --void vdp_keepalive_timeout_handler(UNUSED void *eloop_data, void *user_ctx) --{ -- struct vsi_profile *p = (struct vsi_profile *) user_ctx; -- -- if (p->keepaliveTimer > 0) -- p->keepaliveTimer -= VDP_KEEPALIVE_TIMER_DEFAULT; -- -- if (vdp_keepaliveTimer_expired(p)) { -- LLDPAD_DBG("%s: profile %#02x vdp_keepaliveTimer_expired %i" -- " p->ackReceived %i p->ackReceived %i\n", __func__, -- p->instance[15], vdp_keepaliveTimer_expired(p), -- p->ackReceived, p->ackReceived); -- vdp_vsi_sm_station(p); -- } --} -- --/* vdp_start_keepalive_timer - starts the VDP profile keepalive timer -- * @vd: vdp_data for the interface -- * -- * returns 0 on success, -1 on error -- * -- * starts the VDP profile keepalive timer when a profile has been handed to -- * ecp for transmission. -- */ --static int vdp_start_keepaliveTimer(struct vsi_profile *profile) --{ -- unsigned int usecs; -- -- usecs = VDP_KEEPALIVE_TIMER_DEFAULT; -- -- profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT; -- -- LLDPAD_DBG("%s: %s starting keepalive timer for %#02x (%i)\n", -- __func__, profile->port->ifname, profile->instance[15], -- profile->keepaliveTimer); -- -- return eloop_register_timeout(0, usecs, vdp_keepalive_timeout_handler, -- NULL, (void *) profile); --} -- --/* vdp_stop_keepalive_timer - stops the VDP profile keepalive timer -- * @vd: vdp_data for the interface -- * -- * returns the number of removed handlers -- * -- * stops the VDP tck imer. Used e.g. when the host interface goes down. -- */ --static int vdp_stop_keepaliveTimer(struct vsi_profile *profile) --{ -- profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_STOPPED; -- -- LLDPAD_DBG("%s: %s stopping keepalive timer for %#02x (%i)\n", -- __func__, profile->port->ifname, -- profile->instance[15], profile->keepaliveTimer); -- -- return eloop_cancel_timeout(vdp_keepalive_timeout_handler, NULL, -- (void *) profile); --} -- --static bool vdp_vsi_negative_response(struct vsi_profile *profile) --{ -- if ((profile->response > 0) && (profile->response < 255)) -- return true; -- else -- return false; --} -- --/* vdp_vsi_change_station_state - changes the VDP station sm state -- * @profile: profile to process -- * @newstate: new state for the sm -- * -- * no return value -- * -- * actually changes the state of the profile -- */ --void vdp_vsi_change_station_state(struct vsi_profile *profile, u8 newstate) --{ -- switch(newstate) { -- case VSI_UNASSOCIATED: -- break; -- case VSI_ASSOC_PROCESSING: -- assert((profile->state == VSI_PREASSOCIATED) || -- (profile->state == VSI_ASSOCIATED) || -- (profile->state == VSI_UNASSOCIATED)); -- break; -- case VSI_ASSOCIATED: -- assert((profile->state == VSI_ASSOC_PROCESSING) || -- (profile->state == VSI_ASSOCIATED)); -- break; -- case VSI_PREASSOC_PROCESSING: -- assert((profile->state == VSI_PREASSOCIATED) || -- (profile->state == VSI_ASSOCIATED) || -- (profile->state == VSI_UNASSOCIATED)); -- break; -- case VSI_PREASSOCIATED: -- assert((profile->state == VSI_PREASSOC_PROCESSING) || -- (profile->state == VSI_PREASSOCIATED)); -- break; -- case VSI_DEASSOC_PROCESSING: -- assert((profile->state == VSI_PREASSOCIATED) || -- (profile->state == VSI_UNASSOCIATED) || -- (profile->state == VSI_ASSOCIATED)); -- break; -- case VSI_EXIT: -- assert((profile->state == VSI_ASSOC_PROCESSING) || -- (profile->state == VSI_PREASSOC_PROCESSING) || -- (profile->state == VSI_DEASSOC_PROCESSING) || -- (profile->state == VSI_PREASSOCIATED) || -- (profile->state == VSI_ASSOCIATED)); -- break; -- default: -- LLDPAD_ERR("ERROR: The VDP station State Machine is broken\n"); -- break; -- } -- -- LLDPAD_DBG("%s: %s state change %s -> %s\n", __func__, -- profile->port->ifname, vsi_states[profile->state], -- vsi_states[newstate]); -- -- profile->state = newstate; --} -- --/* vdp_vsi_set_station_state - sets the vdp sm station state -- * @profile: profile to process -- * -- * returns true or false -- * -- * switches the state machine to the next state depending on the input -- * variables. returns true or false depending on wether the state machine -- * can be run again with the new state or can stop at the current state. -- */ --static bool vdp_vsi_set_station_state(struct vsi_profile *profile) --{ -- switch(profile->state) { -- case VSI_UNASSOCIATED: -- if ((profile->mode == VDP_MODE_PREASSOCIATE) || -- (profile->mode == VDP_MODE_PREASSOCIATE_WITH_RR)) { -- vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING); -- vdp_somethingChangedLocal(profile, true); -- return true; -- } else if (profile->mode == VDP_MODE_ASSOCIATE) { -- vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING); -- vdp_somethingChangedLocal(profile, true); -- return true; -- } else if (profile->mode == VDP_MODE_DEASSOCIATE) { -- vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING); -- vdp_somethingChangedLocal(profile, true); -- return true; -- } -- return false; -- case VSI_ASSOC_PROCESSING: -- if (profile->ackReceived) { -- if (profile->response == 0) -- vdp_vsi_change_station_state(profile, VSI_ASSOCIATED); -- else -- vdp_vsi_change_station_state(profile, VSI_EXIT); -- return true; -- } else if (!profile->ackReceived && vdp_ackTimer_expired(profile)) { -- vdp_vsi_change_station_state(profile, VSI_EXIT); -- return true; -- } -- return false; -- case VSI_ASSOCIATED: -- if (profile->mode == VDP_MODE_PREASSOCIATE) { -- vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING); -- return true; -- } else if (profile->mode == VDP_MODE_DEASSOCIATE) { -- vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING); -- return true; -- } else if (vdp_vsi_negative_response(profile)) { -- vdp_vsi_change_station_state(profile, VSI_EXIT); -- return true; -- } else if (vdp_keepaliveTimer_expired(profile)) { -- vdp_stop_keepaliveTimer(profile); -- vdp_somethingChangedLocal(profile, true); -- vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING); -- return true; -- } -- return false; -- case VSI_PREASSOC_PROCESSING: -- LLDPAD_DBG("%s: profile->ackReceived %i, vdp_ackTimer %i\n", -- __func__, profile->ackReceived, profile->ackTimer); -- if (profile->ackReceived) { -- if (profile->response == 0) -- vdp_vsi_change_station_state(profile, VSI_PREASSOCIATED); -- else -- vdp_vsi_change_station_state(profile, VSI_EXIT); -- return true; -- } else if (!profile->ackReceived && vdp_ackTimer_expired(profile)) { -- vdp_vsi_change_station_state(profile, VSI_EXIT); -- return true; -- } -- return false; -- case VSI_PREASSOCIATED: -- if (profile->mode == VDP_MODE_ASSOCIATE) { -- vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING); -- return true; -- } else if (profile->mode == VDP_MODE_DEASSOCIATE) { -- vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING); -- return true; -- } else if (vdp_keepaliveTimer_expired(profile)) { -- vdp_stop_keepaliveTimer(profile); -- vdp_somethingChangedLocal(profile, true); -- vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING); -- return true; -- } -- return false; -- case VSI_DEASSOC_PROCESSING: -- if ((profile->ackReceived) || vdp_ackTimer_expired(profile) || -- profile->remoteChange) { -- vdp_vsi_change_station_state(profile, VSI_EXIT); -- return true; -- } -- return false; -- case VSI_EXIT: -- return false; -- default: -- LLDPAD_ERR("%s: VSI state machine in invalid state %d\n", -- profile->port->ifname, profile->state); -- return false; -- } --} -- --/* vdp_vsi_sm_station - state machine for vdp station role -- * @profile: profile for which the state is processed -- * -- * no return value -- * -- * runs the state machine for the station role of VDP. -- */ --void vdp_vsi_sm_station(struct vsi_profile *profile) --{ -- struct vdp_data *vd = vdp_data(profile->port->ifname); -- int bye = 0; -- -- vdp_vsi_set_station_state(profile); -- do { -- LLDPAD_DBG("%s: %s station for %#02x - %s\n", -- __func__, profile->port->ifname, -- profile->instance[15], vsi_states[profile->state]); -- -- switch(profile->state) { -- case VSI_UNASSOCIATED: -- break; -- case VSI_ASSOC_PROCESSING: -- vdp_stop_keepaliveTimer(profile); -- profile->response = VDP_RESPONSE_NO_RESPONSE; -- if (profile->localChange) { -- ecp_somethingChangedLocal(vd, true); -- profile->ackReceived = false; -- vdp_start_ackTimer(profile); -- } -- break; -- case VSI_ASSOCIATED: -- profile->ackReceived = false; -- vdp_somethingChangedLocal(profile, false); -- vdp_stop_ackTimer(profile); -- vdp_start_keepaliveTimer(profile); -- break; -- case VSI_PREASSOC_PROCESSING: -- vdp_stop_keepaliveTimer(profile); -- profile->response = VDP_RESPONSE_NO_RESPONSE; -- if (profile->localChange) { -- profile->ackReceived = false; -- ecp_somethingChangedLocal(vd, true); -- vdp_start_ackTimer(profile); -- } -- break; -- case VSI_PREASSOCIATED: -- profile->ackReceived = false; -- vdp_somethingChangedLocal(profile, false); -- vdp_stop_ackTimer(profile); -- vdp_start_keepaliveTimer(profile); -- break; -- case VSI_DEASSOC_PROCESSING: -- profile->ackReceived = false; -- vdp_stop_keepaliveTimer(profile); -- profile->response = VDP_RESPONSE_NO_RESPONSE; -- if (profile->localChange) { -- profile->ackReceived = false; -- ecp_somethingChangedLocal(vd, true); -- vdp_start_ackTimer(profile); -- } -- break; -- case VSI_EXIT: -- if (profile->no_nlmsg && !profile->ackReceived && -- vdp_ackTimer_expired(profile)) -- bye = 1; -- vdp_stop_ackTimer(profile); -- vdp_stop_keepaliveTimer(profile); -- vdp_stop_localchange_timer(profile); -- if (bye) -- vdp_remove_profile(profile); -- else -- vdp_trigger(profile); -- break; -- default: -- LLDPAD_ERR("%s: ERROR VSI state machine in invalid state %d\n", -- vd->ifname, profile->state); -- } -- } while (vdp_vsi_set_station_state(profile) == true); -- --} -- --/* vdp_advance_sm - advance state machine after update from switch -- * -- * no return value -- */ --void vdp_advance_sm(struct vdp_data *vd) --{ -- struct vsi_profile *p; -- -- LIST_FOREACH(p, &vd->profile_head, profile) { -- LLDPAD_DBG("%s: %s station for %#02x - %s ackReceived %i\n", -- __func__, p->port->ifname, -- p->instance[15], vsi_states[p->state], -- p->ackReceived); -- if (p->ackReceived) { -- vdp_vsi_sm_station(p); -- p->ackReceived = false; -- } -- } --} -- --/* vdp_vsi_change_bridge_state - changes the VDP bridge sm state -- * @profile: profile to process -- * @newstate: new state for the sm -- * -- * no return value -- * -- * actually changes the state of the profile -- */ --static void vdp_vsi_change_bridge_state(struct vsi_profile *profile, -- u8 newstate) --{ -- switch(newstate) { -- case VSI_UNASSOCIATED: -- break; -- case VSI_ASSOC_PROCESSING: -- assert((profile->state == VSI_UNASSOCIATED) || -- (profile->state == VSI_PREASSOCIATED) || -- (profile->state == VSI_ASSOCIATED)); -- break; -- case VSI_ASSOCIATED: -- assert(profile->state == VSI_ASSOC_PROCESSING); -- break; -- case VSI_PREASSOC_PROCESSING: -- assert((profile->state == VSI_UNASSOCIATED) || -- (profile->state == VSI_PREASSOCIATED) || -- (profile->state == VSI_ASSOCIATED)); -- break; -- case VSI_PREASSOCIATED: -- assert(profile->state == VSI_PREASSOC_PROCESSING); -- break; -- case VSI_DEASSOC_PROCESSING: -- assert((profile->state == VSI_UNASSOCIATED) || -- (profile->state == VSI_PREASSOCIATED) || -- (profile->state == VSI_ASSOCIATED)); -- break; -- case VSI_EXIT: -- assert((profile->state == VSI_DEASSOC_PROCESSING) || -- (profile->state == VSI_PREASSOC_PROCESSING) || -- (profile->state == VSI_ASSOC_PROCESSING)); -- break; -- default: -- LLDPAD_ERR("ERROR: The VDP bridge State Machine is broken\n"); -- break; -- } -- profile->state = newstate; --} -- --/* vdp_vsi_set_bridge_state - sets the vdp sm bridge state -- * @profile: profile to process -- * -- * returns true or false -- * -- * switches the state machine to the next state depending on the input -- * variables. returns true or false depending on wether the state machine -- * can be run again with the new state or can stop at the current state. -- */ --static bool vdp_vsi_set_bridge_state(struct vsi_profile *profile) --{ -- switch(profile->state) { -- case VSI_UNASSOCIATED: -- if ((profile->mode == VDP_MODE_DEASSOCIATE)) /* || (INACTIVE)) */ { -- vdp_vsi_change_bridge_state(profile, VSI_DEASSOC_PROCESSING); -- return true; -- } else if (profile->mode == VDP_MODE_ASSOCIATE) { -- vdp_vsi_change_bridge_state(profile, VSI_ASSOC_PROCESSING); -- return true; -- } else if (profile->mode == VDP_MODE_PREASSOCIATE) { -- vdp_vsi_change_bridge_state(profile, VSI_PREASSOC_PROCESSING); -- return true; -- } -- return false; -- case VSI_ASSOC_PROCESSING: -- /* TODO: handle error case -- if (!vsiError) || -- (vsiError && vsiState == Assoc) { -- */ -- if (profile->mode == VDP_MODE_ASSOCIATE) { -- vdp_vsi_change_bridge_state(profile, VSI_ASSOCIATED); -- return true; -- } -- return false; -- case VSI_ASSOCIATED: -- if (profile->mode == VDP_MODE_ASSOCIATE) /* || ( INACTIVE )*/ { -- vdp_vsi_change_bridge_state(profile, VSI_DEASSOC_PROCESSING); -- return true; -- } else if (profile->mode == VDP_MODE_PREASSOCIATE) { -- vdp_vsi_change_bridge_state(profile, VSI_PREASSOC_PROCESSING); -- return true; -- } else if (profile->mode == VDP_MODE_ASSOCIATE) { -- vdp_vsi_change_bridge_state(profile, VSI_ASSOC_PROCESSING); -- return true; -- } -- return false; -- case VSI_PREASSOC_PROCESSING: -- if (profile->response != VDP_RESPONSE_SUCCESS) { -- vdp_vsi_change_bridge_state(profile, VSI_EXIT); -- return true; -- } -- vdp_vsi_change_bridge_state(profile, VSI_PREASSOCIATED); -- return false; -- case VSI_PREASSOCIATED: -- if (profile->mode == VDP_MODE_ASSOCIATE) { -- vdp_vsi_change_bridge_state(profile, VSI_ASSOC_PROCESSING); -- return true; -- } else if (profile->mode == VDP_MODE_DEASSOCIATE ) { -- vdp_vsi_change_bridge_state(profile, VSI_DEASSOC_PROCESSING); -- return true; -- } else if (profile->mode == VDP_MODE_PREASSOCIATE ) { -- vdp_vsi_change_bridge_state(profile, VSI_PREASSOC_PROCESSING); -- return true; -- } -- return false; -- case VSI_DEASSOC_PROCESSING: -- vdp_vsi_change_bridge_state(profile, VSI_EXIT); -- return false; -- case VSI_EXIT: -- return false; -- default: -- LLDPAD_ERR("%s: ERROR VSI state machine (bridge) in invalid state %d\n", -- profile->port->ifname, profile->state); -- return false; -- } --} -- --/* vdp_vsi_sm_bridge - state machine for vdp bridge role -- * @profile: profile for which the state is processed -- * -- * no return value -- * -- * runs the state machine for the bridge role of VDP. -- */ --static void vdp_vsi_sm_bridge(struct vsi_profile *profile) --{ -- struct vdp_data *vd = vdp_data(profile->port->ifname); -- -- vdp_vsi_set_bridge_state(profile); -- do { -- LLDPAD_DBG("%s: %s bridge - %s\n", __func__, -- profile->port->ifname, vsi_states[profile->state]); -- switch(profile->state) { -- case VSI_UNASSOCIATED: -- break; -- case VSI_ASSOC_PROCESSING: -- /* TODO: vsiError = ProcRxandSetCfg(remoteTLV, localtlv, vsistate); -- * if (vsiError) -- * txTLV(Assoc NACK) -- * else -- * txTLV(Assoc ACK) -- */ -- break; -- case VSI_ASSOCIATED: -- break; -- case VSI_PREASSOC_PROCESSING: -- /* TODO: vsiError = ProcRxandSetCfg(remoteTLV, localtlv, vsistate); -- * if (vsiError) -- * txTLV(PreAssoc NACK) -- * else -- * txTLV(PreAssoc ACK) -- */ -- /* for now, we always succeed */ -- profile->response = VDP_RESPONSE_SUCCESS; -- ecp_rx_send_ack_frame(vd); -- break; -- case VSI_PREASSOCIATED: -- LLDPAD_DBG("%s: %s\n", __func__, profile->port->ifname); -- break; -- case VSI_DEASSOC_PROCESSING: -- /* TODO: txTLV(DeAssoc ACK) */ -- break; -- case VSI_EXIT: -- vdp_remove_profile(profile); -- break; -- default: -- LLDPAD_ERR("%s: ERROR VSI state machine in invalid state %d\n", -- vd->ifname, profile->state); -- } -- } while (vdp_vsi_set_bridge_state(profile) == true); -- --} -- --/* -- * vdp_validate_tlv - validates vsi tlvs -- * @vdp: decoded vsi tlv -- * -- * Returns 0 on success, 1 on error -- * -- * checks the contents of an already decoded vsi tlv for inconsistencies -- */ --static int vdp_validate_tlv(struct tlv_info_vdp *vdp, struct unpacked_tlv *tlv) --{ -- int pairs = (tlv->length - sizeof *vdp) / sizeof(struct mac_vlan_p); -- -- if (ntoh24(vdp->oui) != OUI_IEEE_8021Qbg) { -- LLDPAD_DBG("vdp->oui %#06x\n", ntoh24(vdp->oui)); -- goto out_err; -- } -- -- if (vdp->sub != LLDP_VDP_SUBTYPE) { -- LLDPAD_DBG("vdp->sub %#02x\n", vdp->sub); -- goto out_err; -- } -- -- if (vdp->mode > VDP_MODE_DEASSOCIATE) { -- LLDPAD_DBG("unknown mode %#02x in vsi tlv\n", vdp->mode); -- goto out_err; -- } -- -- if (vdp->response > VDP_RESPONSE_OUT_OF_SYNC) { -- LLDPAD_DBG("unknown response %#02x\n", vdp->response); -- goto out_err; -- } -- -- if (vdp->format != VDP_FILTER_INFO_FORMAT_MACVID) { -- LLDPAD_DBG("unknown format %#02x in vsi tlv\n", vdp->format); -- goto out_err; -- } -- -- if (ntohs(vdp->entries) < 1) { -- LLDPAD_DBG("invalid # of entries %#02x in vsi tlv\n", -- ntohs(vdp->entries)); -- goto out_err; -- } -- -- /* Check for number of entries of MAC,VLAN pairs */ -- if (ntohs(vdp->entries) != pairs) { -- LLDPAD_DBG("mismatching # of entries %#x/%#x in vsi tlv\n", -- ntohs(vdp->entries), pairs); -- goto out_err; -- } -- return 0; -- --out_err: -- return 1; --} -- --/* -- * Create a VSI profile structure from switch response. -- */ --static void make_profile(struct vsi_profile *new, struct tlv_info_vdp *vdp, -- struct unpacked_tlv *tlv) --{ -- int i; -- u8 *pos = tlv->info + sizeof *vdp; -- -- new->mode = vdp->mode; -- new->response = vdp->response; -- new->mgrid = vdp->mgrid; -- new->id = ntoh24(vdp->id); -- new->version = vdp->version; -- memcpy(&new->instance, &vdp->instance, sizeof new->instance); -- new->format = vdp->format; -- new->entries = ntohs(vdp->entries); -- LLDPAD_DBG("%s: MAC/VLAN filter info format %u, # of entries %u\n", -- __func__, new->format, new->entries); -- -- /* Add MAC,VLAN to list */ -- for (i = 0; i < new->entries; ++i) { -- struct mac_vlan *mac_vlan = calloc(1, sizeof(struct mac_vlan)); -- u16 vlan; -- char macbuf[MAC_ADDR_STRLEN + 1]; -- -- if (!mac_vlan) { -- new->entries = i; -- return; -- } -- memcpy(&mac_vlan->mac, pos, ETH_ALEN); -- pos += ETH_ALEN; -- mac2str(mac_vlan->mac, macbuf, MAC_ADDR_STRLEN); -- memcpy(&vlan, pos, 2); -- pos += 2; -- mac_vlan->vlan = ntohs(vlan); -- LLDPAD_DBG("%s: mac %s vlan %d\n", __func__, macbuf, -- mac_vlan->vlan); -- LIST_INSERT_HEAD(&new->macvid_head, mac_vlan, entry); -- } --} -- --/* -- * vdp_indicate - receive VSI TLVs from ECP -- * @port: the port on which the tlv was received -- * @tlv: the unpacked tlv to receive -- * -- * Returns 0 on success -- * -- * receives a vsi tlv and creates a profile. Take appropriate action -- * depending on the role of the (receive) port -- */ --int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv) --{ -- struct tlv_info_vdp vdp; -- struct vsi_profile *p, *profile; -- struct port *port = port_find_by_name(vd->ifname); -- -- LLDPAD_DBG("%s: indicating vdp of length %u (%zu) for %s\n", -- __func__, tlv->length, sizeof(struct tlv_info_vdp), -- vd->ifname); -- -- if (!port) { -- LLDPAD_ERR("%s: port not found for %s\n", __func__, -- vd->ifname); -- goto out_err; -- } -- -- memset(&vdp, 0, sizeof vdp); -- /* copy only vdp header w/o list of mac/vlan/groupid pairs */ -- memcpy(&vdp, tlv->info, sizeof vdp); -- -- if (vdp_validate_tlv(&vdp, tlv)) { -- LLDPAD_ERR("%s: invalid TLV received\n", __func__); -- goto out_err; -- } -- -- profile = vdp_alloc_profile(); -- -- if (!profile) { -- LLDPAD_ERR("%s: unable to allocate profile\n", __func__); -- goto out_err; -- } -- make_profile(profile, &vdp, tlv); -- -- profile->port = port; -- -- if (vd->role == VDP_ROLE_STATION) { -- /* do we have the profile already ? */ -- p = vdp_find_profile(vd, profile); -- -- if (p) { -- LLDPAD_DBG("%s: station profile found localChange %i " -- "ackReceived %i no_nlmsg:%d\n", -- __func__, p->localChange, p->ackReceived, -- p->no_nlmsg); -- -- if (profile->mode == VDP_MODE_DEASSOCIATE && -- (p->response == VDP_RESPONSE_NO_RESPONSE || -- p->response == VDP_RESPONSE_SUCCESS) && -- p->mode == VDP_MODE_PREASSOCIATE) { -- LLDPAD_DBG("%s: ignore dis-associate request " -- "in pre-association\n", __func__); -- vdp_delete_profile(profile); -- return 0; -- } -- -- p->ackReceived = true; -- p->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT; -- if (profile->mode != p->mode) { -- p->mode = profile->mode; -- p->remoteChange = true; -- if (profile->mode == VDP_MODE_DEASSOCIATE) -- p->no_nlmsg = 0; -- } else -- p->remoteChange = false; -- p->response = profile->response; -- LLDPAD_DBG("%s: remoteChange %i no_nlmsg %d mode %d\n", -- __func__, p->remoteChange, p->no_nlmsg, -- p->mode); -- if (vdp_vsi_negative_response(p)) -- p->mode = VDP_MODE_DEASSOCIATE; -- -- LLDPAD_DBG("%s: profile response: %s (%i) " -- "for profile %#02x at state %s\n", -- __func__, -- vdp_response2str(p->response), -- p->response, p->instance[15], -- vsi_states[p->state]); -- } else { -- LLDPAD_DBG("%s: station profile not found\n", __func__); -- } -- vdp_delete_profile(profile); -- } -- -- if (vd->role == VDP_ROLE_BRIDGE) { -- /* do we have the profile already ? */ -- p = vdp_find_profile(vd, profile); -- -- if (p) { -- LLDPAD_DBG("%s: bridge profile found\n", __func__); -- vdp_delete_profile(profile); -- } else { -- LLDPAD_DBG("%s: bridge profile not found\n", __func__); -- /* put it in the list */ -- profile->state = VSI_UNASSOCIATED; -- LIST_INSERT_HEAD(&vd->profile_head, profile, profile); -- } -- -- vdp_vsi_sm_bridge(profile); -- } -- -- return 0; -- --out_err: -- return 1; -- --} -- --/* -- * vdp_bld_vsi_tlv - build the VDP VSI TLV -- * @vd: vdp_data structure for this port -- * @profile: profile the vsi tlv is created from -- * -- * Returns 0 on success, ENOMEM otherwise -- * -- * creates a vdp structure from an existing profile -- */ --static int vdp_bld_vsi_tlv(struct vdp_data *vd, struct vsi_profile *profile) --{ -- struct mac_vlan *mv; -- struct mac_vlan_p *mv_p; -- struct tlv_info_vdp *vdp; -- int rc = 0; -- struct unpacked_tlv *tlv = NULL; -- int size = sizeof(struct tlv_info_vdp) + -- profile->entries * sizeof(struct mac_vlan_p); -- -- vdp = malloc(size); -- -- if (!vdp) { -- LLDPAD_DBG("%s: unable to allocate memory for VDP TLV\n", -- __func__); -- rc = ENOMEM; -- goto out_err; -- } -- -- memset(vdp, 0, size); -- -- hton24(vdp->oui, OUI_IEEE_8021Qbg); -- vdp->sub = LLDP_VDP_SUBTYPE; -- vdp->mode = profile->mode; -- vdp->response = 0; -- vdp->mgrid = profile->mgrid; -- hton24(vdp->id, profile->id); -- vdp->version = profile->version; -- memcpy(&vdp->instance, &profile->instance, 16); -- vdp->format = VDP_FILTER_INFO_FORMAT_MACVID; -- vdp->entries = htons(profile->entries); -- -- mv_p = (struct mac_vlan_p *)(vdp + 1); -- -- LIST_FOREACH(mv, &profile->macvid_head, entry) { -- memcpy(mv_p->mac, mv->mac, MAC_ADDR_LEN); -- mv_p->vlan = htons(mv->vlan); -- mv_p++; -- } -- -- tlv = create_tlv(); -- if (!tlv) { -- rc = ENOMEM; -- goto out_free; -- } -- -- tlv->type = ORG_SPECIFIC_TLV; -- tlv->length = size; -- tlv->info = (u8 *)malloc(tlv->length); -- if(!tlv->info) { -- free(tlv); -- tlv = NULL; -- rc = ENOMEM; -- goto out_free; -- } -- -- FREE_UNPKD_TLV(vd, vdp); -- -- memcpy(tlv->info, vdp, tlv->length); -- -- vd->vdp = tlv; -- --out_free: -- free(vdp); -- --out_err: -- return rc; -- --} -- --/* vdp_bld_tlv - builds a tlv from a profile -- * @vd: vdp_data structure for this port -- * @profile: profile the vsi tlv is created from -- * -- * returns 0 on success, != 0 on error -- * -- * wrapper function around vdp_bld_vsi_tlv. adds some checks and calls -- * vdp_bld_vsi_tlv. --*/ -- --static int vdp_bld_tlv(struct vdp_data *vd, struct vsi_profile *profile) --{ -- int rc = 0; -- -- if (!port_find_by_name(vd->ifname)) { -- rc = EEXIST; -- goto out_err; -- } -- -- if (vdp_bld_vsi_tlv(vd, profile)) { -- LLDPAD_ERR("%s: %s vdp_bld_vsi_tlv() failed\n", -- __func__, vd->ifname); -- rc = EINVAL; -- goto out_err; -- } -- --out_err: -- return rc; --} -- --/* vdp_gettlv - get the tlv for a profile -- * @port: the port on which the tlv was received -- * @profile: profile the vsi tlv is created from -- * -- * returns 0 on success -- * -- * this is the interface function called from ecp_build_ECPDU. It returns the -- * packed tlv for a profile. -- */ --struct packed_tlv *vdp_gettlv(struct vdp_data *vd, struct vsi_profile *profile) --{ -- int size; -- struct packed_tlv *ptlv = NULL; -- -- /* frees the unpacked_tlv in vdp_data -- * also done in vdp_bld_vsi_tlv */ -- vdp_free_tlv(vd); -- -- if (vdp_bld_tlv(vd, profile)) { -- LLDPAD_ERR("%s: %s vdp_bld_tlv failed\n", -- __func__, vd->ifname); -- goto out_err; -- } -- -- size = TLVSIZE(vd->vdp); -- -- if (!size) { -- LLDPAD_ERR("%s: size %i of unpacked_tlv not correct\n", -- __func__, size); -- goto out_err; -- } -- -- ptlv = create_ptlv(); -- if (!ptlv) -- goto out_err; -- -- ptlv->tlv = malloc(size); -- if (!ptlv->tlv) -- goto out_free; -- -- ptlv->size = 0; -- PACK_TLV_AFTER(vd->vdp, ptlv, size, out_free); -- -- return ptlv; -- --out_free: -- ptlv = free_pkd_tlv(ptlv); --out_err: -- LLDPAD_ERR("%s: %s failed\n", __func__, vd->ifname); -- return NULL; --} -- --/* vdp_macvlan_equal - checks for equality of 2 mac/vlan pairs -- * @mv1: mac/vlan pair 1 -- * @mv2: mac/vlan pair 2 -- * -- * returns true if equal, false if not -- * -- * compares mac address and vlan if they are equal. -- */ --bool vdp_macvlan_equal(struct mac_vlan *mv1, struct mac_vlan *mv2) --{ -- if (memcmp(mv1->mac, mv2->mac, MAC_ADDR_LEN)) -- return false; -- -- if (mv1->vlan != mv2->vlan) -- return false; -- -- return true; --} -- --/* -- * Check if the current profile already has this entry. If so take over -- * PID and other fields. If not add this MAC,VLAN to our list. -- * -- * Returns 1 it the entry already exist, 0 if not. -- */ --static int have_macvlan(struct vsi_profile *p1, struct mac_vlan *new) --{ -- struct mac_vlan *mv1; -- -- LIST_FOREACH(mv1, &p1->macvid_head, entry) -- if (vdp_macvlan_equal(mv1, new) == true) { -- mv1->req_pid = new->req_pid; -- mv1->req_seq = new->req_seq; -- mv1->qos = new->qos; -- return 1; -- } -- LIST_INSERT_HEAD(&p1->macvid_head, new, entry); -- p1->entries++; -- return 0; --} -- --/* vdp_takeover_macvlans - take over macvlan pairs from p2 into p1 -- * @p1: profile 1 -- * @p2: profile 2 -- * -- * returns number of mac/vlan pairs taken over -- * -- * loops over all mac/vlan pairs in profile 2 and looks for them in profile 1. -- * If the mac/vlan pair does not yet exist in profile 1, it adds the new pair to -- * the list in profile 1. -- */ --void vdp_takeover_macvlans(struct vsi_profile *p1, struct vsi_profile *p2) --{ -- struct mac_vlan *mv2; -- int count = 0; -- -- LLDPAD_DBG("%s: taking over mac/vlan pairs\n", __func__); -- -- while ((mv2 = LIST_FIRST(&p2->macvid_head))) { -- LIST_REMOVE(mv2, entry); -- p2->entries--; -- if (have_macvlan(p1, mv2)) -- free(mv2); -- else -- count++; -- } -- -- LLDPAD_DBG("%s: %u mac/vlan pairs taken over\n", __func__, count); --} -- --/* vdp_add_profile - adds a profile to a per port list -- * @profile: profile to add -- * -- * returns the profile that has been found or added, NULL otherwise. -- * -- * main interface function which adds a profile to a list kept on a per-port -- * basis. Checks if the profile is already in the list, adds it if necessary. -- */ --struct vsi_profile *vdp_add_profile(struct vdp_data *vd, -- struct vsi_profile *profile) --{ -- struct vsi_profile *p; -- -- LLDPAD_DBG("%s: adding vdp profile for %s\n", __func__, -- profile->port->ifname); -- vdp_trace_profile(profile); -- -- /* -- * Search this profile. If found check, -- * if the MAC/VLAN pair already exists. If not, add it. -- */ -- p = vdp_find_profile(vd, profile); -- if (p) { -- LLDPAD_DBG("%s: profile already exists\n", __func__); -- -- vdp_takeover_macvlans(p, profile); -- -- if (p->mode != profile->mode) { -- LLDPAD_DBG("%s: new mode %i\n", -- __func__, profile->mode); -- p->mode = profile->mode; -- p->response = VDP_RESPONSE_NO_RESPONSE; -- } -- profile = p; -- } else { -- -- profile->response = VDP_RESPONSE_NO_RESPONSE; -- -- LIST_INSERT_HEAD(&vd->profile_head, profile, profile); -- } -- -- vdp_somethingChangedLocal(profile, true); -- -- return profile; --} -- --/* vdp_remove_profile - remove a profile from a per port list -- * @profile: profile to remove -- * -- * returns 0 if removal was successful, -1 if removal failed -- * -- * function used in the state machines to remove a profile from a list kept on -- * a per-port basis. Checks if the profile is in the list, removes it if there. -- */ --int vdp_remove_profile(struct vsi_profile *profile) --{ -- struct vsi_profile *p; -- struct vdp_data *vd; -- -- LLDPAD_DBG("%s: removing vdp profile on %s\n", __func__, -- profile->port->ifname); -- vdp_trace_profile(profile); -- -- vd = vdp_data(profile->port->ifname); -- if (!vd) { -- LLDPAD_ERR("%s: could not find vdp_data for %s\n", __func__, -- profile->port->ifname); -- return -1; -- } -- /* Check if profile exists. If yes, remove it. */ -- p = vdp_find_profile(vd, profile); -- if (p) { -- LIST_REMOVE(p, profile); -- vdp_delete_profile(p); -- return 0; -- } -- return -1; /* Not found */ --} -- --/* vdp_ifdown - tear down vdp structures for a interface -- * @ifname: name of the interface -- * -- * no return value -- * -- * interface function to lldpad. tears down vdp specific structures if -- * interface "ifname" goes down. -- */ --void vdp_ifdown(char *ifname, UNUSED struct lldp_agent *agent) --{ -- struct vdp_data *vd; -- struct vsi_profile *p; -- -- LLDPAD_DBG("%s: called on interface %s\n", __func__, ifname); -- -- vd = vdp_data(ifname); -- if (!vd) -- goto out_err; -- -- if (ecp_deinit(ifname)) -- goto out_err; -- -- LIST_FOREACH(p, &vd->profile_head, profile) { -- if (p->ackTimer > 0) -- vdp_stop_ackTimer(p); -- if (p->keepaliveTimer > 0) -- vdp_stop_keepaliveTimer(p); -- } -- -- LLDPAD_INFO("%s: %s vdp data removed\n", __func__, ifname); -- return; --out_err: -- LLDPAD_INFO("%s: %s vdp data remove failed\n", __func__, ifname); -- -- return; --} -- --/* vdp_ifup - build up vdp structures for a interface -- * @ifname: name of the interface -- * -- * no return value -- * -- * interface function to lldpad. builds up vdp specific structures if -- * interface "ifname" goes up. -- */ --void vdp_ifup(char *ifname, struct lldp_agent *agent) --{ -- char *role; -- char config_path[16]; -- struct vdp_data *vd; -- struct vdp_user_data *ud; -- struct vsi_profile *p; -- int enabletx = false; -- -- LLDPAD_DBG("%s: %s agent:%d start VDP\n", -- __func__, ifname, agent->type); -- -- snprintf(config_path, sizeof(config_path), "%s.%s", -- VDP_PREFIX, ARG_TLVTXENABLE); -- -- if (get_config_setting(ifname, agent->type, config_path, -- (void *)&enabletx, CONFIG_TYPE_BOOL)) -- enabletx = false; -- -- if (enabletx == false) { -- LLDPAD_DBG("%s: %s not enabled for VDP\n", __func__, ifname); -- return; -- } -- -- vd = vdp_data(ifname); -- if (vd) { -- vd->enabletx = enabletx; -- -- LLDPAD_WARN("%s: %s vdp data already exists\n", -- __func__, ifname); -- goto out_start_again; -- } -- -- /* not found, alloc/init per-port module data */ -- vd = (struct vdp_data *) calloc(1, sizeof(struct vdp_data)); -- if (!vd) { -- LLDPAD_ERR("%s: %s malloc %zu failed\n", -- __func__, ifname, sizeof(*vd)); -- goto out_err; -- } -- strncpy(vd->ifname, ifname, IFNAMSIZ); -- -- vd->role = VDP_ROLE_STATION; -- vd->enabletx = enabletx; -- -- if (!get_cfg(ifname, NEAREST_BRIDGE, "vdp.role", (void *)&role, -- CONFIG_TYPE_STRING)) { -- if (!strcasecmp(role, VAL_BRIDGE)) { -- vd->role = VDP_ROLE_BRIDGE; -- } -- } -- -- LLDPAD_DBG("%s: configured for %s mode\n", ifname, -- (vd->role ==VDP_ROLE_BRIDGE) ? "bridge" : "station"); -- -- LIST_INIT(&vd->profile_head); -- -- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP02); -- LIST_INSERT_HEAD(&ud->head, vd, entry); -- --out_start_again: -- if (ecp_init(ifname)) { -- LLDPAD_ERR("%s: %s unable to init ecp\n", __func__, ifname); -- vdp_ifdown(ifname, agent); -- goto out_err; -- } -- -- vd->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT; -- vd->ackTimer = VDP_ACK_TIMER_DEFAULT; -- -- LLDPAD_DBG("%s: %s starting vdp timer (%i)\n", __func__, -- vd->ifname, vd->nroftimers); -- -- LIST_FOREACH(p, &vd->profile_head, profile) { -- if (p->ackTimer > 0) { -- vdp_somethingChangedLocal(p, true); -- vdp_start_ackTimer(p); -- } -- if (p->keepaliveTimer > 0) -- vdp_start_keepaliveTimer(p); -- } -- -- LLDPAD_DBG("%s: %s agent:%d vdp added\n", __func__, ifname, -- agent->type); -- return; -- --out_err: -- LLDPAD_ERR("%s: %s agent:%d vdp adding failed\n", -- __func__, ifname, agent->type); --} -- --static int vdp_client_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, -- UNUSED socklen_t fromlen, char *ibuf, int ilen, -- char *rbuf, int rlen) --{ -- return vdp_clif_cmd(ibuf, ilen, rbuf, rlen); --} -- --static const struct lldp_mod_ops vdp_ops = { -- .lldp_mod_register = vdp_register, -- .lldp_mod_unregister = vdp_unregister, -- .get_arg_handler = vdp_get_arg_handlers, -- .client_cmd = vdp_client_cmd --}; -- --/* vdp_register - register vdp module to lldpad -- * @none -- * -- * returns lldp_module struct on success, NULL on error -- * -- * allocates a module structure with vdp module information and returns it -- * to lldpad. -- */ --struct lldp_module *vdp_register(void) --{ -- struct lldp_module *mod; -- struct vdp_user_data *ud; -- -- mod = malloc(sizeof(*mod)); -- if (!mod) { -- LLDPAD_ERR("%s: failed to start - vdp data\n", __func__); -- return NULL; -- } -- ud = malloc(sizeof(struct vdp_user_data)); -- if (!ud) { -- free(mod); -- LLDPAD_ERR("%s: failed to start - vdp user data\n", __func__); -- return NULL; -- } -- LIST_INIT(&ud->head); -- mod->id = LLDP_MOD_VDP02; -- mod->ops = &vdp_ops; -- mod->data = ud; -- LLDPAD_DBG("%s: done\n", __func__); -- return mod; --} -- --/* vdp_unregister - unregister vdp module from lldpad -- * @none -- * -- * no return value -- * -- * frees vdp module structure. -- */ --void vdp_unregister(struct lldp_module *mod) --{ -- if (mod->data) { -- vdp_free_data((struct vdp_user_data *) mod->data); -- free(mod->data); -- } -- free(mod); -- LLDPAD_DBG("%s: done\n", __func__); --} -- --void vdp_update(char *ifname, u8 ccap) --{ -- struct vdp_data *vdp = vdp_data(ifname); -- -- if (vdp) { -- vdp->vdpbit_on = ccap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP; -- LLDPAD_DBG("%s:%s vdpbit_on %d\n", __func__, ifname, -- vdp->vdpbit_on); -- } --} -- --/* -- * Handle a VSI request from buddy. -- */ --int vdp_request(struct vdpnl_vsi *vsi) --{ -- struct vdp_data *vd; -- struct vsi_profile *profile, *p; -- struct port *port = port_find_by_name(vsi->ifname); -- struct mac_vlan *mac_vlan; -- int ret = 0; -- -- vd = vdp_data(vsi->ifname); -- if (!vd) { -- LLDPAD_ERR("%s: %s has not yet been configured\n", __func__, -- vsi->ifname); -- return -ENXIO; -- } -- if (!vd->vdpbit_on) { -- LLDPAD_ERR("%s: %s has VDP disabled\n", __func__, vsi->ifname); -- return -ENXIO; -- } -- -- if (!port) { -- LLDPAD_ERR("%s: %s can not find port\n", __func__, vsi->ifname); -- return -ENODEV; -- } -- /* If the link is down, reject request */ -- if (!port->portEnabled && vsi->request != VDP_MODE_DEASSOCIATE) { -- LLDPAD_WARN("%s: %s not enabled, unable to associate\n", -- __func__, vsi->ifname); -- return -ENXIO; -- } -- -- profile = vdp_alloc_profile(); -- if (!profile) -- return -ENOMEM; -- mac_vlan = calloc(1, sizeof(struct mac_vlan)); -- if (!mac_vlan) { -- ret = -ENOMEM; -- goto out_err; -- } -- -- profile->port = port; -- memcpy(&mac_vlan->mac, vsi->maclist->mac, sizeof mac_vlan->mac); -- mac_vlan->vlan = vsi->maclist->vlan; -- mac_vlan->qos = vsi->maclist->qos; -- mac_vlan->req_pid = vsi->req_pid; -- mac_vlan->req_seq = vsi->req_seq; -- LIST_INSERT_HEAD(&profile->macvid_head, mac_vlan, entry); -- profile->entries = 1; -- -- profile->mgrid = vsi->vsi_mgrid; -- profile->id = vsi->vsi_typeid; -- profile->version = vsi->vsi_typeversion; -- profile->mode = vsi->request; -- profile->response = vsi->response; -- memcpy(profile->instance, vsi->vsi_uuid, sizeof vsi->vsi_uuid); -- p = vdp_add_profile(vd, profile); -- p->no_nlmsg = 1; -- p->txmit = false; -- vdp_trace_profile(p); -- if (p != profile) -- goto out_err; -- return ret; -- --out_err: -- vdp_delete_profile(profile); -- return ret; --} -- --/* -- * Query a VSI request from buddy and report its progress. Use the interface -- * name to determine the VSI profile list. Return one entry in parameter 'vsi' -- * use the structure members response and vsi_uuid. -- * Returns -- * 1 valid VSI data returned -- * 0 end of queue (no VSI data returned) -- * <0 errno -- */ --int vdp_status(int number, struct vdpnl_vsi *vsi) --{ -- struct vdp_data *vd; -- struct vsi_profile *p; -- int i = 0, ret = 0; -- -- vd = vdp_data(vsi->ifname); -- if (!vd) { -- LLDPAD_ERR("%s: %s has not yet been configured\n", __func__, -- vsi->ifname); -- return -ENODEV; -- } -- /* Interate to queue element number */ -- LIST_FOREACH(p, &vd->profile_head, profile) { -- if (++i == number) { -- ret = 1; -- break; -- } -- } -- if (ret) { -- vdp_trace_profile(p); -- vsi->response = p->response; -- memcpy(vsi->vsi_uuid, p->instance, sizeof vsi->vsi_uuid); -- if (p->response != VDP_RESPONSE_NO_RESPONSE -- && p->state == VSI_EXIT) -- vdp_remove_profile(p); -- } -- LLDPAD_DBG("%s: entry:%d more:%d\n", __func__, number, ret); -- return ret; --} -- --/* -- * Copy MAC-VLAN list from profile to vdpnl structure. -- */ --static void copy_maclist(struct vsi_profile *p, struct vdpnl_mac *macp) --{ -- struct mac_vlan *mv1; -- -- LIST_FOREACH(mv1, &p->macvid_head, entry) { -- macp->vlan = mv1->vlan; -- macp->qos = mv1->qos; -- memcpy(macp->mac, mv1->mac, sizeof macp->mac); -- ++macp; -- } --} -- --/* -- * Prepare data for a netlink message to originator of VSI. -- * Forward a notification from switch. -- */ --int vdp_trigger(struct vsi_profile *profile) --{ -- struct vdpnl_vsi vsi; -- struct vdp_data *vd; -- struct mac_vlan *macp = 0; -- int rc = -EINVAL; -- struct vdpnl_mac maclist[profile->entries]; -- -- vsi.macsz = profile->entries; -- vsi.maclist = maclist; -- LLDPAD_DBG("%s: no_nlmsg:%d\n", __func__, profile->no_nlmsg); -- vdp_trace_profile(profile); -- if (profile->no_nlmsg) -- return 0; -- if (LIST_EMPTY(&profile->macvid_head)) -- return 0; -- macp = LIST_FIRST(&profile->macvid_head); -- if (!macp->req_pid) -- return 0; -- sleep(1); /* Delay message notification */ -- if (!profile->port || !profile->port->ifname) { -- LLDPAD_ERR("%s: no ifname found for profile %p:\n", __func__, -- profile); -- goto error_exit; -- } -- memcpy(vsi.ifname, profile->port->ifname, sizeof vsi.ifname); -- vd = vdp_data(vsi.ifname); -- if (!vd) { -- LLDPAD_ERR("%s: %s could not find vdp_data\n", __func__, -- vsi.ifname); -- goto error_exit; -- } -- vsi.ifindex = if_nametoindex(vsi.ifname); -- if (vsi.ifindex == 0) { -- LLDPAD_ERR("%s: %s could not find index for ifname\n", -- __func__, vsi.ifname); -- goto error_exit; -- } -- vsi.macsz = profile->entries; -- copy_maclist(profile, vsi.maclist); -- vsi.req_pid = macp->req_pid; -- vsi.req_seq = macp->req_seq; -- vsi.vsi_mgrid = profile->mgrid; -- vsi.vsi_typeid = profile->id; -- vsi.vsi_typeversion = profile->version; -- memcpy(vsi.vsi_uuid, profile->instance, sizeof vsi.vsi_uuid); -- vsi.request = VDP_MODE_DEASSOCIATE; -- rc = vdpnl_send(&vsi); --error_exit: -- vdp_remove_profile(profile); -- return rc; --} -diff --git a/lldp_vdp_clif.c b/lldp_vdp_clif.c -deleted file mode 100644 -index 6fd1e8e..0000000 ---- a/lldp_vdp_clif.c -+++ /dev/null -@@ -1,193 +0,0 @@ --/******************************************************************************* -- -- Implementation of VDP according to IEEE 802.1Qbg -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Jens Osterkamp -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --*******************************************************************************/ -- --#include --#include --#include --#include --#include --#include "lldp_mod.h" --#include "clif_msgs.h" --#include "lldp.h" --#include "lldp_vdp.h" --#include "lldp_vdp_cmds.h" --#include "lldp_vdp_clif.h" --#include "lldp_mand_clif.h" -- --static const char *mode_state(int mode) --{ -- switch (mode) { -- case VDP_MODE_PREASSOCIATE_WITH_RR: -- return "Preassociated with RR"; -- case VDP_MODE_DEASSOCIATE: -- return "Disassociated"; -- case VDP_MODE_ASSOCIATE: -- return "Associated"; -- case VDP_MODE_PREASSOCIATE: -- return "Preassociated"; -- default: return "unknown"; -- } --} -- --/* -- * Print a complete VDP TLV. Data string constructed in function -- * vdp_clif_profile(). -- */ --static void vdp_show_tlv(UNUSED u16 len, char *info) --{ -- int rc, role, enabletx, vdpbit, mode, response, mgrid, id, idver; -- unsigned int x[16]; -- -- rc = sscanf(info, "%02x%02x%02x%02x%02x%02x%06x%02x", -- &role, &enabletx, &vdpbit, &mode, &response, &mgrid, -- &id, &idver); -- if (rc != 3 && rc != 8) -- return; -- printf("Role:%s\n", role ? VAL_BRIDGE : VAL_STATION); -- printf("\tEnabled:%s\n", enabletx ? VAL_YES : VAL_NO); -- printf("\tVDP Bit:%s\n", vdpbit ? VAL_YES : VAL_NO); -- if (rc == 3) /* No active VSI profile */ -- return; -- printf("\tMode:%d (%s)\n", mode, mode_state(mode)); -- printf("\tMgrid:%d\n", mgrid); -- printf("\tTypeid:%d\n", id); -- printf("\tTypeidversion:%d\n", idver); -- rc = sscanf(info + 20, "%02x%02x%02x%02x%02x%02x%02x%02x" -- "%02x%02x%02x%02x%02x%02x%02x%02x", -- &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], -- &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], -- &x[15]); -- if (rc != 16) -- return; -- printf("\tUUID:%02x%02x%02x%02x-%02x%02x-%02x%02x" -- "-%02x%02x-%02x%02x%02x%02x%02x%02x\n", x[0], x[1], x[2], x[3], -- x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], -- x[14], x[15]); -- mode = 52; -- rc = sscanf(info + mode, "%02x%04x", &role, &vdpbit); -- if (rc != 2) -- return; -- printf("\tFilter Format:%d\n", role); -- printf("\tEntries:%d\n", vdpbit); -- mode += 6; -- while (--vdpbit >= 0) { -- rc = sscanf(info + mode, "%02x%02x%02x%02x%02x%02x%04x", -- &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6]); -- if (rc != 7) -- return; -- printf("\t\tMAC:%02x:%02x:%02x:%02x:%02x:%02x\tVlanid:%d\n", -- x[0], x[1], x[2], x[3], x[4], x[5], x[6]); -- mode += 16; -- } --} -- --static struct type_name_info vdp_tlv_names[] = { -- { -- .type = ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE, -- .name = "VDP draft 0.2 protocol configuration", -- .key = "vdp", -- .print_info = vdp_show_tlv -- }, -- { -- .type = INVALID_TLVID -- } --}; -- --static int vdp_print_help() --{ -- struct type_name_info *tn = &vdp_tlv_names[0]; -- -- while (tn->type != INVALID_TLVID) { -- if (tn->key && strlen(tn->key) && tn->name) { -- printf(" %s", tn->key); -- if (strlen(tn->key)+3 < 8) -- printf("\t"); -- printf("\t: %s\n", tn->name); -- } -- tn++; -- } -- return 0; --} -- --static u32 vdp_lookup_tlv_name(char *tlvid_str) --{ -- struct type_name_info *tn = &vdp_tlv_names[0]; -- -- while (tn->type != INVALID_TLVID) { -- if (!strcasecmp(tn->key, tlvid_str)) -- return tn->type; -- tn++; -- } -- return INVALID_TLVID; --} -- --static void vdp_cli_unregister(struct lldp_module *mod) --{ -- free(mod); --} -- --/* return 1: if it printed the TLV -- * 0: if it did not -- */ --static int vdp_print_tlv(u32 tlvid, u16 len, char *info) --{ -- struct type_name_info *tn = &vdp_tlv_names[0]; -- -- while (tn->type != INVALID_TLVID) { -- if (tlvid == tn->type) { -- printf("%s\n", tn->name); -- if (tn->print_info) { -- printf("\t"); -- tn->print_info(len-4, info); -- } -- return 1; -- } -- tn++; -- } -- return 0; --} -- --static const struct lldp_mod_ops vdp_ops_clif = { -- .lldp_mod_register = vdp_cli_register, -- .lldp_mod_unregister = vdp_cli_unregister, -- .print_tlv = vdp_print_tlv, -- .lookup_tlv_name = vdp_lookup_tlv_name, -- .print_help = vdp_print_help, --}; -- --struct lldp_module *vdp_cli_register(void) --{ -- struct lldp_module *mod; -- -- mod = malloc(sizeof(*mod)); -- if (!mod) { -- fprintf(stderr, "failed to malloc module data\n"); -- return NULL; -- } -- mod->id = (LLDP_MOD_VDP << 8) | LLDP_VDP_SUBTYPE; -- mod->ops = &vdp_ops_clif; -- return mod; --} -diff --git a/lldp_vdp_cmds.c b/lldp_vdp_cmds.c -deleted file mode 100644 -index ec9c49c..0000000 ---- a/lldp_vdp_cmds.c -+++ /dev/null -@@ -1,668 +0,0 @@ --/****************************************************************************** -- -- Implementation of VDP according to IEEE 802.1Qbg -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Jens Osterkamp -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --#include --#include --#include --#include --#include --#include --#include "lldpad.h" --#include "ctrl_iface.h" --#include "lldp.h" --#include "lldp_vdp.h" --#include "lldp_mand_clif.h" --#include "lldp_vdp_cmds.h" --#include "lldp_qbg_utils.h" --#include "lldp/ports.h" --#include "lldp_tlv.h" --#include "messages.h" --#include "libconfig.h" --#include "config.h" --#include "clif_msgs.h" --#include "lldpad_status.h" --#include "lldp/states.h" -- --static char *check_and_update(size_t *total, size_t *length, char *s, int c) --{ -- if (c < 0) -- return NULL; -- *total += c; -- if ((unsigned)c >= *length) -- return NULL; -- *length -= c; -- return s + c; --} -- --static char *print_mode(char *s, size_t length, struct vsi_profile *p) --{ -- int c; -- size_t total = 0; -- char *r = s; -- struct mac_vlan *mac_vlan; -- char instance[VDP_UUID_STRLEN + 2]; -- -- vdp_uuid2str(p->instance, instance, sizeof(instance)); -- c = snprintf(s, length, "%d,%d,%d,%d,%s,%d", -- p->state, p->mgrid, p->id, p->version, instance, -- p->format); -- s = check_and_update(&total, &length, s, c); -- if (!s) -- return r; -- -- LIST_FOREACH(mac_vlan, &p->macvid_head, entry) { -- char macbuf[MAC_ADDR_STRLEN + 1]; -- -- mac2str(mac_vlan->mac, macbuf, MAC_ADDR_STRLEN); -- c = snprintf(s, length, ",%s,%d", macbuf, mac_vlan->vlan); -- s = check_and_update(&total, &length, s, c); -- if (!s) -- return r; -- } -- return s; --} -- --static int --get_arg_tlvtxenable(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- int value; -- char *s; -- char arg_path[VDP_BUF_SIZE]; -- -- if (cmd->cmd != cmd_gettlv) -- return cmd_invalid; -- -- switch (cmd->tlvid) { -- case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE: -- snprintf(arg_path, sizeof(arg_path), "%s.%s", VDP_PREFIX, arg); -- -- if (get_cfg(cmd->ifname, cmd->type, arg_path, &value, -- CONFIG_TYPE_BOOL)) -- value = false; -- break; -- case INVALID_TLVID: -- return cmd_invalid; -- default: -- return cmd_not_applicable; -- } -- -- if (value) -- s = VAL_YES; -- else -- s = VAL_NO; -- -- snprintf(obuf, obuf_len, "%02zx%s%04zx%s", -- strlen(arg), arg, strlen(s), s); -- -- return cmd_success; --} -- --static int _set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -- bool test) --{ -- int value, err; -- char arg_path[VDP_BUF_SIZE]; -- -- if (cmd->cmd != cmd_settlv) -- return cmd_invalid; -- -- switch (cmd->tlvid) { -- case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE: -- break; -- case INVALID_TLVID: -- return cmd_invalid; -- default: -- return cmd_not_applicable; -- } -- -- if (!strcasecmp(argvalue, VAL_YES)) -- value = 1; -- else if (!strcasecmp(argvalue, VAL_NO)) -- value = 0; -- else -- return cmd_invalid; -- -- if (test) -- return cmd_success; -- -- snprintf(arg_path, sizeof(arg_path), "%s.%s", VDP_PREFIX, arg); -- -- err = set_cfg(cmd->ifname, cmd->type, arg_path, -- &value, CONFIG_TYPE_BOOL); -- if (err) -- return cmd_failed; -- -- return cmd_success; -- --} -- --static int set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return _set_arg_tlvtxenable(cmd, arg, argvalue, false); --} -- --static int test_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return _set_arg_tlvtxenable(cmd, arg, argvalue, true); --} -- --static int get_arg_mode(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- struct vsi_profile *np; -- struct vdp_data *vd; -- char mode_str[VDP_BUF_SIZE], *t = mode_str; -- int filled = 0; -- -- if (cmd->cmd != cmd_gettlv) -- return cmd_invalid; -- -- switch (cmd->tlvid) { -- case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE: -- break; -- case INVALID_TLVID: -- return cmd_invalid; -- default: -- return cmd_not_applicable; -- } -- -- vd = vdp_data(cmd->ifname); -- if (!vd) { -- LLDPAD_ERR("%s: vdp_data for %s not found !\n", -- __func__, cmd->ifname); -- return cmd_device_not_found; -- } -- -- memset(mode_str, 0, sizeof mode_str); -- LIST_FOREACH(np, &vd->profile_head, profile) { -- t = print_mode(t, sizeof(mode_str) - filled, np); -- filled = t - mode_str; -- } -- -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int)strlen(arg), arg, (unsigned int)strlen(mode_str), -- mode_str); -- return cmd_success; --} -- --static void str2instance(struct vsi_profile *profile, char *buffer) --{ -- unsigned int i, j = 0; -- -- for (i = 0; i <= strlen(buffer); i++) { -- if (buffer[i] == '-') -- continue; -- -- if (sscanf(&buffer[i], "%02hhx", &profile->instance[j]) == 1) { -- i++; -- j++; -- } -- } --} -- --static void vdp_fill_profile(struct vsi_profile *profile, char *buffer, -- int field) --{ -- LLDPAD_DBG("%s: parsed %s\n", __func__, buffer); -- -- switch(field) { -- case MODE: -- profile->mode = atoi(buffer); -- break; -- case MGRID: -- profile->mgrid = atoi(buffer); -- break; -- case TYPEID: -- profile->id = atoi(buffer); -- break; -- case TYPEIDVERSION: -- profile->version = atoi(buffer); -- break; -- case INSTANCEID: -- str2instance(profile, buffer); -- break; -- case FORMAT: -- profile->format = atoi(buffer); -- break; -- default: -- LLDPAD_ERR("Unknown field in buffer !\n"); -- break; -- } --} -- --static struct vsi_profile *vdp_parse_mode_line(char *argvalue) --{ -- int field; -- char *cmdstring, *parsed; -- struct vsi_profile *profile; -- -- profile = vdp_alloc_profile(); -- if (!profile) -- return NULL; -- -- cmdstring = strdup(argvalue); -- if (!cmdstring) -- goto out_free; -- -- field = 0; -- -- parsed = strtok(cmdstring, ","); -- -- while (parsed != NULL) { -- vdp_fill_profile(profile, parsed, field); -- field++; -- if (field > FORMAT) -- break; -- parsed = strtok(NULL, ","); -- } -- -- if ((field <= FORMAT) || (parsed == NULL)) -- goto out_free; -- -- parsed = strtok(NULL, ","); -- -- while (parsed != NULL) { -- struct mac_vlan *mac_vlan; -- -- mac_vlan = calloc(1, sizeof(struct mac_vlan)); -- if (mac_vlan == NULL) -- goto out_free; -- -- if (str2mac(parsed, &mac_vlan->mac[0], MAC_ADDR_LEN)) { -- free(mac_vlan); -- goto out_free; -- } -- -- parsed = strtok(NULL, ","); -- if (parsed == NULL) { -- free(mac_vlan); -- goto out_free; -- } -- -- mac_vlan->vlan = atoi(parsed); -- LIST_INSERT_HEAD(&profile->macvid_head, mac_vlan, entry); -- profile->entries++; -- parsed = strtok(NULL, ","); -- } -- -- free(cmdstring); -- return profile; -- --out_free: -- free(cmdstring); -- vdp_delete_profile(profile); -- return NULL; --} -- --static int _set_arg_mode(struct cmd *cmd, char *argvalue, bool test) --{ -- struct vsi_profile *profile, *p; -- struct vdp_data *vd; -- -- if (cmd->cmd != cmd_settlv) -- return cmd_invalid; -- -- switch (cmd->tlvid) { -- case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE: -- break; -- case INVALID_TLVID: -- return cmd_invalid; -- default: -- return cmd_not_applicable; -- } -- -- profile = vdp_parse_mode_line(argvalue); -- if (profile == NULL) -- return cmd_failed; -- -- profile->port = port_find_by_name(cmd->ifname); -- -- if (!profile->port) { -- vdp_delete_profile(profile); -- return cmd_device_not_found; -- } -- -- vd = vdp_data(cmd->ifname); -- if (!vd) { -- vdp_delete_profile(profile); -- return cmd_device_not_found; -- } -- -- if (test) { -- vdp_delete_profile(profile); -- return cmd_success; -- } -- -- p = vdp_add_profile(vd, profile); -- if (profile != p) -- vdp_delete_profile(profile); -- -- return cmd_success; --} -- --static int set_arg_mode(struct cmd *cmd, UNUSED char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return _set_arg_mode(cmd, argvalue, false); --} -- --static int test_arg_mode(struct cmd *cmd, UNUSED char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return _set_arg_mode(cmd, argvalue, true); --} -- --static int get_arg_role(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- struct vdp_data *vd; -- -- if (cmd->cmd != cmd_gettlv) -- return cmd_invalid; -- -- switch (cmd->tlvid) { -- case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE: -- vd = vdp_data(cmd->ifname); -- -- if (!vd) { -- LLDPAD_ERR("%s: could not find vdp_data for %s\n", -- __FILE__, cmd->ifname); -- return cmd_device_not_found; -- } -- -- if (vd->role == VDP_ROLE_STATION) -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int) strlen(arg), arg, -- (unsigned int) strlen(VAL_STATION), -- VAL_STATION); -- else if (vd->role == VDP_ROLE_BRIDGE) -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int) strlen(arg), arg, -- (unsigned int) strlen(VAL_BRIDGE), VAL_BRIDGE); -- else -- return cmd_failed; -- break; -- case INVALID_TLVID: -- return cmd_invalid; -- default: -- return cmd_not_applicable; -- } -- -- return cmd_success; --} -- --static int _set_arg_role(struct cmd *cmd, char *arg, char *argvalue, bool test) --{ -- struct vdp_data *vd; -- char arg_path[VDP_BUF_SIZE]; -- -- if (cmd->cmd != cmd_settlv) -- return cmd_invalid; -- -- switch (cmd->tlvid) { -- case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE: -- break; -- case INVALID_TLVID: -- return cmd_invalid; -- default: -- return cmd_not_applicable; -- } -- -- vd = vdp_data(cmd->ifname); -- -- if (!vd) { -- LLDPAD_ERR("%s: could not find vdp_data for %s\n", -- __FILE__, cmd->ifname); -- return cmd_device_not_found; -- } -- -- if (!strcasecmp(argvalue, VAL_BRIDGE)) { -- if (!test) -- vd->role = VDP_ROLE_BRIDGE; -- } else if (!strcasecmp(argvalue, VAL_STATION)) { -- if (!test) -- vd->role = VDP_ROLE_STATION; -- } else { -- return cmd_invalid; -- } -- -- if (test) -- return cmd_success; -- -- snprintf(arg_path, sizeof(arg_path), "%s.%s", VDP_PREFIX, arg); -- -- const char *p = &argvalue[0]; -- if (set_cfg(cmd->ifname, cmd->type, arg_path, &p, CONFIG_TYPE_STRING)) -- return cmd_failed; -- -- return cmd_success; --} -- --static int set_arg_role(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return _set_arg_role(cmd, arg, argvalue, false); --} -- --static int test_arg_role(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return _set_arg_role(cmd, arg, argvalue, true); --} -- --static struct arg_handlers arg_handlers[] = { -- { -- .arg = ARG_VDP_MODE, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_mode, -- .handle_set = set_arg_mode, -- .handle_test = test_arg_mode -- }, -- { -- .arg = ARG_VDP_ROLE, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_role, -- .handle_set = set_arg_role, -- .handle_test = test_arg_role -- }, -- { -- .arg = ARG_TLVTXENABLE, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_tlvtxenable, -- .handle_set = set_arg_tlvtxenable, -- .handle_test = test_arg_tlvtxenable -- }, -- { -- .arg = 0 -- } --}; -- --struct arg_handlers *vdp_get_arg_handlers() --{ -- return &arg_handlers[0]; --} -- --/* -- * Interface to build information for lldptool -V vdp -- */ --struct tlv_info_vdp_nopp { /* VSI information without profile data */ -- u8 oui[3]; /* OUI */ -- u8 sub; /* Subtype */ -- u8 role; /* Role: station or bridge */ -- u8 enabletx; -- u8 vdpbit_on; --} __attribute__ ((__packed__)); -- --/* -- * Flatten a profile stored as TLV and append it. Skip the first 4 bytes. -- * They contain the OUI already stored. -- * Returns the number of bytes added to the buffer. -- */ --static int add_profile(unsigned char *pdu, size_t pdusz, struct vdp_data *vdp) --{ -- size_t size = 0; -- -- if (!vdp->vdp) -- return size; -- size = (unsigned)TLVSIZE(vdp->vdp) - 4; -- if (pdusz >= size) -- memcpy(pdu, vdp->vdp->info + 4, size); -- else { -- LLDPAD_ERR("%s: %s buffer size too small (need %d bytes)\n", -- __func__, vdp->ifname, TLVSIZE(vdp->vdp)); -- return -1; -- } -- return size; --} -- --/* -- * Create unpacked VDP tlv for VSI profile when active. -- */ --static int make_vdp_tlv(unsigned char *pdu, size_t pdusz, struct vdp_data *vdp) --{ -- struct unpacked_tlv *tlv = (struct unpacked_tlv *)pdu; -- struct tlv_info_vdp_nopp *vdpno; -- size_t pduoff; -- int rc; -- -- tlv->info = (unsigned char *)(tlv + 1); -- vdpno = (struct tlv_info_vdp_nopp *)tlv->info; -- tlv->type = ORG_SPECIFIC_TLV; -- tlv->length = sizeof(struct tlv_info_vdp_nopp); -- hton24(vdpno->oui, LLDP_MOD_VDP); -- vdpno->sub = LLDP_VDP_SUBTYPE; -- vdpno->role = vdp->role; -- vdpno->enabletx = vdp->enabletx; -- vdpno->vdpbit_on = vdp->vdpbit_on; -- pduoff = sizeof(*tlv) + tlv->length; -- pdusz -= pduoff; -- rc = add_profile(pdu + pduoff, pdusz - pduoff, vdp); -- if (rc > 0) { -- tlv->length += rc; -- rc = 0; -- } -- return rc; --} -- --/* -- * Flatten a VDP TLV into a byte stream. -- */ --static int vdp_clif_profile(char *ifname, char *rbuf, size_t rlen) --{ -- unsigned char pdu[VDP_BUF_SIZE]; /* Buffer for unpacked TLV */ -- int i, c, rstatus = cmd_success; -- size_t sum = 0; -- struct vdp_data *vd; -- struct unpacked_tlv *tlv = (struct unpacked_tlv *)pdu; -- struct packed_tlv *ptlv; -- -- LLDPAD_DBG("%s: %s rlen:%zu\n", __func__, ifname, rlen); -- vd = vdp_data(ifname); -- if (!vd) -- return cmd_device_not_found; -- -- if (make_vdp_tlv(pdu, sizeof pdu, vd)) -- return cmd_failed; -- -- /* Convert to packed TLV */ -- ptlv = pack_tlv(tlv); -- if (!ptlv) -- return cmd_failed; -- for (i = 0; i < TLVSIZE(tlv); ++i) { -- c = snprintf(rbuf, rlen, "%02x", ptlv->tlv[i]); -- rbuf = check_and_update(&sum, &rlen, rbuf, c); -- if (!rbuf) { -- rstatus = cmd_failed; -- break; -- } -- } -- free_pkd_tlv(ptlv); -- return rstatus; --} -- --/* -- * Module function to extract all VSI profile data on a given interface. It -- * is invoked via 'lldptool -t -i ethx -g ncb -V vdp' without any configuration -- * options. -- * This function does not support arguments and its values. They are handled -- * using the lldp_mand_cmds.c interfaces. -- */ --int vdp_clif_cmd(char *ibuf, UNUSED int ilen, char *rbuf, int rlen) --{ -- struct cmd cmd; -- u8 len, version; -- int c, ioff; -- size_t roff = 0, outlen = rlen; -- char *here; -- int rstatus = cmd_invalid; -- -- /* Pull out the command elements of the command message */ -- hexstr2bin(ibuf + MSG_VER, (u8 *)&version, sizeof(u8)); -- version >>= 4; -- hexstr2bin(ibuf + CMD_CODE, (u8 *)&cmd.cmd, sizeof(cmd.cmd)); -- hexstr2bin(ibuf + CMD_OPS, (u8 *)&cmd.ops, sizeof(cmd.ops)); -- cmd.ops = ntohl(cmd.ops); -- hexstr2bin(ibuf + CMD_IF_LEN, &len, sizeof(len)); -- ioff = CMD_IF; -- if (len < sizeof(cmd.ifname)) -- memcpy(cmd.ifname, ibuf + CMD_IF, len); -- else -- return cmd_failed; -- cmd.ifname[len] = '\0'; -- ioff += len; -- -- memset(rbuf, 0, rlen); -- c = snprintf(rbuf, rlen, "%c%1x%02x%08x%02x%s", -- CMD_REQUEST, CLIF_MSG_VERSION, cmd.cmd, cmd.ops, -- (unsigned int)strlen(cmd.ifname), cmd.ifname); -- here = check_and_update(&roff, &outlen, rbuf, c); -- if (!here) -- return cmd_failed; -- -- if (version == CLIF_MSG_VERSION) { -- hexstr2bin(ibuf+ioff, &cmd.type, sizeof(cmd.type)); -- ioff += 2 * sizeof(cmd.type); -- } else /* Command valid only for nearest customer bridge */ -- goto out; -- -- if (cmd.cmd == cmd_gettlv) { -- hexstr2bin(ibuf+ioff, (u8 *)&cmd.tlvid, sizeof(cmd.tlvid)); -- cmd.tlvid = ntohl(cmd.tlvid); -- ioff += 2 * sizeof(cmd.tlvid); -- } else -- goto out; -- -- c = snprintf(here, outlen, "%08x", cmd.tlvid); -- here = check_and_update(&roff, &outlen, here, c); -- if (!here) -- return cmd_failed; -- rstatus = vdp_clif_profile(cmd.ifname, here, outlen); --out: -- return rstatus; --} -diff --git a/lldpad.c b/lldpad.c -index d29a53d..406dcd5 100644 ---- a/lldpad.c -+++ b/lldpad.c -@@ -52,9 +52,9 @@ - #include "lldp_8023.h" - #include "lldp_evb.h" - #include "lldp_evb22.h" --#include "lldp_ecp22.h" --#include "lldp_vdp.h" --#include "lldp_vdp22.h" -+#include "qbg_ecp22.h" -+#include "qbg_vdp.h" -+#include "qbg_vdp22.h" - #include "lldp_8021qaz.h" - #include "config.h" - #include "lldpad_shm.h" -@@ -83,6 +83,7 @@ struct lldp_module *(*register_tlv_table[])(void) = { - char *cfg_file_name = NULL; - bool daemonize = 0; - int loglvl = LOG_WARNING; -+int omit_tstamp; - - static const char *lldpad_version = - "lldpad v" VERSION_STR "\n" -@@ -124,16 +125,17 @@ static void usage(void) - { - fprintf(stderr, - "\n" -- "usage: lldpad [-hdkspv] [-f configfile]" -+ "usage: lldpad [-hdksptv] [-f configfile] [-V level]" - "\n" - "options:\n" - " -h show this usage\n" -- " -f use configfile instead of default\n" - " -d run daemon in the background\n" - " -k terminate current running lldpad\n" - " -s remove lldpad state records\n" - " -p Do not create PID file\n" -+ " -t omit timestamps in log messages\n" - " -v show version\n" -+ " -f use configfile instead of default\n" - " -V set syslog level\n"); - - exit(1); -@@ -153,15 +155,13 @@ void send_event(int level, u32 moduleid, char *msg) - ctrl_iface_send(cd, level, moduleid, msg, strlen(msg)); - } - --static void remove_all_adapters() -+static void remove_all_adapters(void) - { -- struct port *port, *p; -+ struct port *port, *next; - -- port = porthead; -- while (port != NULL) { -- p = port; -- port = port->next; -- remove_port(p->ifname); -+ for (port = porthead; port; port = next) { -+ next = port->next; -+ remove_port(port->ifname); - } - - return; -@@ -231,9 +231,10 @@ int main(int argc, char *argv[]) - int pid_file = 1; - pid_t pid; - int cnt; -+ int rc = 1; - - for (;;) { -- c = getopt(argc, argv, "dhkvspf:V:"); -+ c = getopt(argc, argv, "hdksptvf:V:"); - if (c < 0) - break; - switch (c) { -@@ -256,6 +257,9 @@ int main(int argc, char *argv[]) - case 'p': - pid_file = 0; - break; -+ case 't': -+ omit_tstamp = 1; -+ break; - case 'v': - print_v = 1; - break; -@@ -330,29 +334,6 @@ int main(int argc, char *argv[]) - exit (0); - } - -- if (pid_file) { -- fd = open(PID_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); -- if (fd < 0) { -- LLDPAD_ERR("error opening lldpad lock file"); -- exit(1); -- } -- -- if (flock(fd, LOCK_EX | LOCK_NB) < 0) { -- if (errno == EWOULDBLOCK) { -- fprintf(stderr, "lldpad is already running\n"); -- if (read(fd, buf, sizeof(buf)) > 0) { -- fprintf(stderr, "pid of existing" -- "lldpad is %s\n", buf); -- } -- LLDPAD_ERR("lldpad already running"); -- } else { -- perror("error locking lldpad lock file"); -- LLDPAD_ERR("error locking lldpad lock file"); -- } -- exit(1); -- } -- } -- - lldpad_oom_adjust(); - - /* initialize lldpad user data */ -@@ -379,23 +360,30 @@ int main(int argc, char *argv[]) - exit(1); - } - -+ /* From this point on we know we're the only instance */ - if (daemonize && daemon(1, 0)) { - LLDPAD_ERR("error daemonizing lldpad"); -- goto out; -+ exit(1); - } - - if (pid_file) { -+ fd = open(PID_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); -+ if (fd < 0) { -+ LLDPAD_ERR("error opening lldpad pid file"); -+ exit(1); -+ } -+ - if (lseek(fd, 0, SEEK_SET) < 0) { -- LLDPAD_ERR("error seeking lldpad lock file\n"); -- exit(1); -+ LLDPAD_ERR("error seeking lldpad pid file\n"); -+ goto out_fail; - } - - memset(buf, 0, sizeof(buf)); - sprintf(buf, "%u\n", getpid()); - if (write(fd, buf, sizeof(buf)) < 0) -- perror("error writing to lldpad lock file"); -+ perror("error writing to lldpad pid file"); - if (fsync(fd) < 0) -- perror("error syncing lldpad lock file"); -+ perror("error syncing lldpad pid file"); - - close(fd); - } -@@ -403,23 +391,17 @@ int main(int argc, char *argv[]) - pid = lldpad_shm_getpid(); - if (pid < 0) { - LLDPAD_ERR("error getting shm pid"); -- if (pid_file) -- unlink(PID_FILE); -- exit(1); -+ goto out_fail; - } else if (pid == PID_NOT_SET) { - if (!lldpad_shm_setpid(getpid())) { - perror("lldpad_shm_setpid failed"); - LLDPAD_ERR("lldpad_shm_setpid failed\n"); -- if (pid_file) -- unlink(PID_FILE); -- exit (1); -+ goto out_fail; - } - } else if (pid != DONT_KILL_PID) { - if (!kill(pid, 0)) { - LLDPAD_ERR("lldpad already running"); -- if (pid_file) -- unlink(PID_FILE); -- exit(1); -+ goto out_fail; - } - /* pid in shm no longer has a process, go ahead - * and let this lldpad instance execute. -@@ -427,55 +409,51 @@ int main(int argc, char *argv[]) - if (!lldpad_shm_setpid(getpid())) { - perror("lldpad_shm_setpid failed"); - LLDPAD_ERR("error overwriting shm pid"); -- if (pid_file) -- unlink(PID_FILE); -- exit (1); -+ goto out_fail; - } - } - - openlog("lldpad", LOG_CONS | LOG_PID, LOG_DAEMON); - setlogmask(LOG_UPTO(loglvl)); - -- if (check_cfg_file()) -- exit(1); -- - /* setup event netlink interface for user space processes. - * This needs to be setup first to ensure it gets lldpads - * pid as netlink address. - */ - if (event_iface_init_user_space() < 0) { -- LLDPAD_ERR("lldpad failed to start - failed to register user space event interface\n"); -- exit(1); -+ LLDPAD_ERR("lldpad failed to start - " -+ "failed to register user space event interface\n"); -+ closelog(); -+ goto out_fail; - } - - init_modules(); - - eloop_register_signal_terminate(eloop_terminate, NULL); -- eloop_register_signal_reconfig(lldpad_reconfig, NULL); -+ eloop_register_signal_reconfig(lldpad_reconfig, NULL); - - /* setup LLDP agent */ - if (!start_lldp_agents()) { - LLDPAD_ERR("failed to initialize LLDP agent\n"); -- exit(1); -+ goto out; - } - - /* setup event RT netlink interface */ - if (event_iface_init() < 0) { - LLDPAD_ERR("failed to register event interface\n"); -- exit(1); -+ goto out; - } - - /* Find available interfaces and add adapters */ - init_ports(); - - if (ctrl_iface_register(clifd) < 0) { -- if (!daemonize) -- fprintf(stderr, "failed to register control interface\n"); - LLDPAD_ERR("lldpad failed to start - " - "failed to register control interface\n"); - goto out; - } - -+ rc = 0; - eloop_run(); - - clean_lldp_agents(); -@@ -485,12 +463,13 @@ int main(int argc, char *argv[]) - event_iface_deinit(); - stop_lldp_agents(); - out: -+ eloop_destroy(); -+ if (!eloop_terminated()) -+ rc = 1; - destroy_cfg(); - closelog(); -+out_fail: - if (pid_file) - unlink(PID_FILE); -- eloop_destroy(); -- if (eloop_terminated()) -- exit(0); -- exit(1); -+ exit(rc); - } -diff --git a/lldpad.service b/lldpad.service -index 8cc4aed..2cee1de 100644 ---- a/lldpad.service -+++ b/lldpad.service -@@ -4,7 +4,9 @@ After=syslog.target network.target - - [Service] - Type=simple --ExecStart=/usr/sbin/lldpad -+ExecStart=/usr/sbin/lldpad -t -+ExecReload=/bin/kill -HUP $MAINPID - - [Install] - WantedBy=multi-user.target -+Also=lldpad.socket -diff --git a/lldpad.socket b/lldpad.socket -new file mode 100644 -index 0000000..24f3eb6 ---- /dev/null -+++ b/lldpad.socket -@@ -0,0 +1,6 @@ -+[Socket] -+ListenDatagram=@/com/intel/lldpad -+PassCredentials=true -+ -+[Install] -+WantedBy=sockets.target -diff --git a/lldpad_shm.c b/lldpad_shm.c -index bbd001f..4afcf73 100644 ---- a/lldpad_shm.c -+++ b/lldpad_shm.c -@@ -253,8 +253,8 @@ int lldpad_shm_get_dcbx(const char *device_name) - for (i = 0; i < num_entries; i++) { - if (strcmp(shmaddr->ent[i].ifname, device_name) == 0) { - switch (shmaddr->ent[i].dcbx_mode) { -- case dcbx_subtype1: -- case dcbx_subtype2: -+ case DCBX_SUBTYPE1: -+ case DCBX_SUBTYPE2: - rval = shmaddr->ent[i].dcbx_mode; - break; - default: -@@ -303,8 +303,8 @@ int lldpad_shm_set_dcbx(const char *device_name, int dcbx_mode) - if (num_entries > MAX_LLDPAD_SHM_ENTRIES) - goto done; - -- if ((dcbx_mode != dcbx_subtype0) && (dcbx_mode != dcbx_subtype1) && -- (dcbx_mode != dcbx_subtype2)) -+ if ((dcbx_mode != DCBX_SUBTYPE0) && (dcbx_mode != DCBX_SUBTYPE1) && -+ (dcbx_mode != DCBX_SUBTYPE2)) - goto done; - - /* search for existing entry */ -diff --git a/lldptool.c b/lldptool.c -index e1ff11f..1b229c1 100644 ---- a/lldptool.c -+++ b/lldptool.c -@@ -48,7 +48,7 @@ - #include "lldp_dcbx_clif.h" - #include "lldp_evb22_clif.h" - #include "lldp_evb_clif.h" --#include "lldp_vdp_clif.h" -+#include "qbg_vdp_clif.h" - #include "lldp_8021qaz_clif.h" - #include "lldp_orgspec_clif.h" - #include "lldp_cisco_clif.h" -@@ -497,12 +497,15 @@ static int request(struct clif *clif, int argc, char *argv[]) - break; - case 'g': - if (!strcasecmp(optarg, "nearestbridge") || -+ !strcasecmp(optarg, "nearest_bridge") || - !strcasecmp(optarg, "nb")) - command.type = NEAREST_BRIDGE; - else if (!strcasecmp(optarg, "nearestcustomerbridge") || -+ !strcasecmp(optarg, "nearest_customer_bridge") || - !strcasecmp(optarg, "ncb")) - command.type = NEAREST_CUSTOMER_BRIDGE; -- else if (!strcasecmp(optarg, "nearestnontmprbridge") || -+ else if (!strcasecmp(optarg, "nearestnontpmrbridge") || -+ !strcasecmp(optarg, "nearest_nontpmr_bridge") || - !strcasecmp(optarg, "nntpmrb")) - command.type = NEAREST_NONTPMR_BRIDGE; - else { -diff --git a/lldptool_cmds.c b/lldptool_cmds.c -index 17b4d8b..daef8c8 100644 ---- a/lldptool_cmds.c -+++ b/lldptool_cmds.c -@@ -349,6 +349,9 @@ static char *print_status(cmd_status status) - case cmd_no_access: - str = "Access denied"; - break; -+ case cmd_agent_not_supported: -+ str = "TLV does not support agent type"; -+ break; - default: - str = "Unknown status"; - break; -@@ -462,12 +465,10 @@ static void print_tlvs(struct cmd *cmd, char *ibuf) - - printed = 0; - LIST_FOREACH(np, &lldp_head, lldp) { -- if (np->ops->print_tlv) -- if (np->ops->print_tlv(tlvid, tlv_len, -- ibuf+offset)) { -+ if (np->ops->print_tlv(tlvid, tlv_len, ibuf+offset)) { - printed = 1; - break; -- } -+ } - } - - if (!printed) { -diff --git a/log.c b/log.c -index e66e9c2..63b942b 100644 ---- a/log.c -+++ b/log.c -@@ -59,7 +59,7 @@ void log_message(int level, const char *format, ...) - if (daemonize) - vsyslog(level, format, vb); - else if (loglvl >= level) { -- if (!bypass_time) -+ if (!omit_tstamp && !bypass_time) - showtime(); - vprintf(format, vb); - bypass_time = strchr(format, '\n') == 0; -diff --git a/parse_cli.l b/parse_cli.l -index 529c563..3717aff 100644 ---- a/parse_cli.l -+++ b/parse_cli.l -@@ -226,19 +226,19 @@ gp { if (!cmd) { - BEGIN(cmddone); - } - --cee { dcbx_version = dcbx_subtype2; -+cee { dcbx_version = DCBX_SUBTYPE2; - BEGIN(cmddone); - } - --cin { dcbx_version = dcbx_subtype1; -+cin { dcbx_version = DCBX_SUBTYPE1; - BEGIN(cmddone); - } - --force-cee { dcbx_version = dcbx_force_subtype2; -+force-cee { dcbx_version = DCBX_FORCE_SUBTYPE2; - BEGIN(cmddone); - } - --force-cin { dcbx_version = dcbx_force_subtype1; -+force-cin { dcbx_version = DCBX_FORCE_SUBTYPE1; - BEGIN(cmddone); - } - -diff --git a/qbg/ecp.c b/qbg/ecp.c -new file mode 100644 -index 0000000..c81eb19 ---- /dev/null -+++ b/qbg/ecp.c -@@ -0,0 +1,1093 @@ -+/****************************************************************************** -+ -+ Implementation of ECP according to 802.1Qbg -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Jens Osterkamp -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "eloop.h" -+#include "lldp.h" -+#include "lldp_evb.h" -+#include "qbg_utils.h" -+#include "qbg_vdp.h" -+#include "messages.h" -+#include "config.h" -+#include "lldp/l2_packet.h" -+ -+#include "lldp_tlv.h" -+ -+static void ecp_tx_run_sm(struct vdp_data *); -+static void ecp_rx_run_sm(struct vdp_data *); -+ -+/* ecp_localchange_handler - triggers the processing of a local change -+ * @eloop_data: data structure of event loop -+ * @user_ctx: user context, vdp_data here -+ * -+ * no return value -+ * -+ * called from ecp_somethingchangedlocal when a change is pending. Calls -+ * the ECP tx station state machine. A oneshot handler. This detour is taken -+ * to not having to call the ecp code from the vdp state machine. Instead, we -+ * return to the event loop, giving other code a chance to do work. -+ */ -+static void ecp_localchange_handler(UNUSED void *eloop_data, void *user_ctx) -+{ -+ struct vdp_data *vd; -+ -+ vd = (struct vdp_data *) user_ctx; -+ if (vd->ecp.tx.localChange) { -+ LLDPAD_DBG("%s:%s ecp.tx.localChange %i\n", -+ __func__, vd->ecp.ifname, vd->ecp.tx.localChange); -+ ecp_tx_run_sm(vd); -+ } -+} -+ -+/* ecp_start_localchange_timer - starts the ECP localchange timer -+ * @vd: vdp_data for the interface -+ * -+ * returns 0 on success, -1 on error -+ * -+ * starts the ECP localchange timer when a localchange has been signaled from -+ * the VDP state machine. -+ */ -+static int ecp_start_localchange_timer(struct vdp_data *vd) -+{ -+ return eloop_register_timeout(0, ECP_LOCALCHANGE_TIMEOUT, -+ ecp_localchange_handler, -+ NULL, (void *) vd); -+} -+ -+/* ecp_stop_localchange_timer - stop the ECP localchange timer -+ * @vd: vdp_data for the interface -+ * -+ * returns the number of removed handlers -+ * -+ * stops the ECP localchange timer. Used e.g. when the host interface goes down. -+ */ -+static int ecp_stop_localchange_timer(struct vdp_data *vd) -+{ -+ LLDPAD_DBG("%s:%s stopping ecp localchange timer\n", __func__, -+ vd->ecp.ifname); -+ return eloop_cancel_timeout(ecp_localchange_handler, NULL, (void *) vd); -+} -+ -+/* ecp_ackTimer_expired - checks for expired ack timer -+ * @vd: vdp_data for interface -+ * -+ * returns true or false -+ * -+ * returns true if ack timer has expired, false otherwise. -+ */ -+static bool ecp_ackTimer_expired(struct vdp_data *vd) -+{ -+ return (vd->ecp.ackTimer == 0); -+} -+ -+/* ecp_ack_timeout_handler - handles the ack timer expiry -+ * @eloop_data: data structure of event loop -+ * @user_ctx: user context, vdp_data here -+ * -+ * no return value -+ * -+ * called when the ECP timer has expired. Calls the ECP station state machine. -+ */ -+static void ecp_ack_timeout_handler(UNUSED void *eloop_data, void *user_ctx) -+{ -+ struct vdp_data *vd; -+ -+ vd = (struct vdp_data *) user_ctx; -+ if (vd->ecp.ackTimer > 0) -+ vd->ecp.ackTimer -= ECP_ACK_TIMER_DEFAULT; -+ -+ if (ecp_ackTimer_expired(vd) == true) { -+ LLDPAD_DBG("%s:%s ecp_ackTimer_expired (%i)\n", -+ __func__, vd->ecp.ifname, vd->ecp.ackTimer); -+ ecp_tx_run_sm(vd); -+ } else { -+ LLDPAD_DBG("%s:%s BUG! handler called but" -+ "vdp->ecp.ackTimer not expired (%i)\n", -+ __func__, vd->ecp.ifname, vd->ecp.ackTimer); -+ } -+} -+ -+/* ecp_start_ack_timer - starts the ECP ack timer -+ * @vd: vdp_data for the interface -+ * -+ * returns 0 on success, -1 on error -+ * -+ * starts the ECP ack timer when a frame has been sent out. -+ */ -+static int ecp_start_ack_timer(struct vdp_data *vd) -+{ -+ return eloop_register_timeout(0, ECP_ACK_TIMER_DEFAULT, -+ ecp_ack_timeout_handler, -+ NULL, (void *) vd); -+} -+ -+/* ecp_stop_ack_timer - stop the ECP ack timer -+ * @vd: vdp_data for the interface -+ * -+ * returns the number of removed handlers -+ * -+ * stops the ECP ack timer. Used e.g. when the host interface goes down. -+ */ -+static int ecp_stop_ack_timer(struct vdp_data *vd) -+{ -+ LLDPAD_DBG("%s:%s stopping ecp ack timer\n", __func__, vd->ecp.ifname); -+ return eloop_cancel_timeout(ecp_ack_timeout_handler, NULL, (void *) vd); -+} -+ -+/* ecp_tx_stop_ackTimer - stop the ECP ack timer -+ * @vd: currently used port -+ * -+ * returns the number of removed handlers -+ * -+ * stops the ECP ack timer. used when a ack frame for the port has been -+ * received. -+ */ -+static void ecp_tx_stop_ackTimer(struct vdp_data *vd) -+{ -+ vd->ecp.ackTimer = ECP_ACK_TIMER_STOPPED; -+ LLDPAD_DBG("%s:%s stopped ecp ack timer\n", __func__, vd->ecp.ifname); -+ ecp_stop_ack_timer(vd); -+} -+ -+int ecp_deinit(char *ifname) -+{ -+ struct vdp_data *vd; -+ -+ LLDPAD_DBG("%s:%s stopping ECP\n", __func__, ifname); -+ vd = vdp_data(ifname); -+ if (!vd) { -+ LLDPAD_ERR("%s:%s unable to find vd\n", __func__, ifname); -+ return -1; -+ } -+ -+ ecp_stop_ack_timer(vd); -+ ecp_stop_localchange_timer(vd); -+ ecp_tx_stop_ackTimer(vd); -+ return 0; -+} -+ -+static const char *ecp_tx_states[] = { -+ "ECP_TX_INIT_TRANSMIT", -+ "ECP_TX_TRANSMIT_ECPDU", -+ "ECP_TX_WAIT_FOR_ACK", -+ "ECP_TX_REQUEST_PDU" -+}; -+ -+/* ecp_somethingChangedLocal - set flag if port has changed -+ * @vd: port to set the flag for -+ * @mode: mode to set the flag to -+ * -+ * no return value -+ * -+ * set the localChange flag with a mode to indicate a port has changed. -+ * used to signal an ecpdu needs to be sent out. -+ */ -+ -+void ecp_somethingChangedLocal(struct vdp_data *vd, bool flag) -+{ -+ if (!vd) -+ return; -+ -+ LLDPAD_DBG("%s:%s vd->ecp.tx.localChange to %s\n", __func__, -+ vd->ecp.ifname, (flag == true) ? "true" : "false"); -+ vd->ecp.tx.localChange = flag; -+ ecp_start_localchange_timer(vd); -+} -+ -+/* -+ * Append some data at the end of the transmit data buffer. Make sure the -+ * End TLV always fits into the buffer. -+ */ -+static u8 end_tlv[2] = { 0x0, 0x0 }; /* END TLV */ -+ -+static int ecp_append(u8 *buffer, u32 *pos, void *data, u32 len) -+{ -+ if (*pos + len > ETH_FRAME_LEN - sizeof end_tlv) -+ return 0; -+ memcpy(buffer + *pos, data, len); -+ *pos += len; -+ return 1; -+} -+ -+/* ecp_build_ECPDU - create an ecp protocol data unit -+ * @vd: currently used port -+ * -+ * returns true on success, false on failure -+ * -+ * creates the frame header with the ports mac address, the ecp header with REQ -+ * plus a list of packed TLVs created from the profiles on this -+ * port. -+ */ -+static bool ecp_build_ECPDU(struct vdp_data *vd) -+{ -+ struct l2_ethhdr eth; -+ struct ecp_hdr ecp_hdr; -+ u8 own_addr[ETH_ALEN]; -+ u32 fb_offset = 0; -+ struct packed_tlv *ptlv = NULL; -+ struct vsi_profile *p; -+ int rc; -+ -+ /* TODO: use LLDP group MAC addresses to support -+ * S-channels/multichannel -+ */ -+ memcpy(eth.h_dest, nearest_bridge, ETH_ALEN); -+ l2_packet_get_own_src_addr(vd->ecp.l2,(u8 *)&own_addr); -+ memcpy(eth.h_source, &own_addr, ETH_ALEN); -+ eth.h_proto = htons(ETH_P_ECP); -+ memset(vd->ecp.tx.frame, 0, sizeof vd->ecp.tx.frame); -+ ecp_append(vd->ecp.tx.frame, &fb_offset, (void *)ð, sizeof eth); -+ -+ ecp_hdr.oui[0] = 0x0; -+ ecp_hdr.oui[1] = 0x1b; -+ ecp_hdr.oui[2] = 0x3f; -+ ecp_hdr.pad1 = 0x0; -+ ecp_hdr.subtype = ECP_SUBTYPE; -+ ecp_hdr.mode = ECP_REQUEST; -+ -+ vd->ecp.lastSequence++; -+ ecp_hdr.seqnr = htons(vd->ecp.lastSequence); -+ ecp_append(vd->ecp.tx.frame, &fb_offset, (void *)&ecp_hdr, -+ sizeof ecp_hdr); -+ -+ /* create packed_tlvs for all profiles on this interface */ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ -+ if (!p->localChange) { -+ LLDPAD_DBG("%s:%s skipping unchanged profile\n", -+ __func__, vd->ecp.ifname); -+ continue; -+ } -+ -+ ptlv = vdp_gettlv(vd, p); -+ -+ if (!ptlv) { -+ LLDPAD_DBG("%s:%s ptlv not created\n", __func__, -+ vd->ecp.ifname); -+ continue; -+ } -+ -+ rc = ecp_append(vd->ecp.tx.frame, &fb_offset, ptlv->tlv, -+ ptlv->size); -+ ptlv = free_pkd_tlv(ptlv); -+ if (rc) -+ p->seqnr = vd->ecp.lastSequence; -+ else -+ break; -+ } -+ ecp_append(vd->ecp.tx.frame, &fb_offset, end_tlv, sizeof end_tlv); -+ vd->ecp.tx.frame_len = MAX(fb_offset, (unsigned)ETH_ZLEN); -+ return true; -+} -+ -+/* ecp_tx_Initialize - initializes the ecp tx state machine -+ * @vd: currently used port -+ * -+ * no return value -+ * -+ * initializes some variables for the ecp tx state machine. -+ */ -+static void ecp_tx_Initialize(struct vdp_data *vd) -+{ -+ memset(vd->ecp.tx.frame, 0, sizeof vd->ecp.tx.frame); -+ ecp_somethingChangedLocal(vd, true); -+ vd->ecp.lastSequence = ECP_SEQUENCE_NR_START; -+ vd->ecp.stats.statsFramesOutTotal = 0; -+ vd->ecp.ackTimer = ECP_ACK_TIMER_STOPPED; -+ vd->ecp.retries = 0; -+} -+ -+/* ecp_txFrame - transmit ecp frame -+ * @vd: currently used port -+ * -+ * returns the number of characters sent on success, -1 on failure -+ * -+ * sends out the frame stored in the frame structure using l2_packet_send. -+ */ -+static u8 ecp_txFrame(struct vdp_data *vd) -+{ -+ int status = 0; -+ -+ status = l2_packet_send(vd->ecp.l2, (u8 *)&nearest_bridge, -+ htons(ETH_P_ECP), vd->ecp.tx.frame, vd->ecp.tx.frame_len); -+ vd->ecp.stats.statsFramesOutTotal++; -+ vd->ecp.tx.frame_len = 0; -+ return status; -+} -+ -+/* ecp_tx_create_frame - create ecp frame -+ * @vd: currently used port -+ * -+ * no return value -+ */ -+static void ecp_tx_create_frame(struct vdp_data *vd) -+{ -+ /* send REQs */ -+ if (vd->ecp.tx.localChange) { -+ int ret; -+ -+ LLDPAD_DBG("%s:%s sending REQs\n", __func__, vd->ecp.ifname); -+ ret = ecp_build_ECPDU(vd); -+ -+ /* ECPDU construction succesful, send out frame */ -+ if (ret == true) { -+ hexdump_frame(vd->ecp.ifname, "frame-out", -+ vd->ecp.tx.frame, vd->ecp.tx.frame_len); -+ ecp_txFrame(vd); -+ } -+ } -+ -+ ecp_somethingChangedLocal(vd, false); -+} -+ -+/* ecp_tx_start_ackTimer - starts the ECP ack timer -+ * @vd: vdp_data to process -+ * -+ * returns 0 on success, -1 on error -+ * -+ * starts the ack timer when a frame has been sent out. -+ */ -+static void ecp_tx_start_ackTimer(struct vdp_data *vd) -+{ -+ vd->ecp.ackTimer = ECP_ACK_TIMER_DEFAULT; -+ LLDPAD_DBG("%s-%s: starting ecp ack timer\n", __func__, vd->ifname); -+ ecp_start_ack_timer(vd); -+} -+ -+/* ecp_tx_change_state - changes the ecp tx sm state -+ * @vd: currently used port -+ * @newstate: new state for the sm -+ * -+ * no return value -+ * -+ * checks state transistion for consistency and finally changes the state of -+ * the profile. -+ */ -+static void ecp_tx_change_state(struct vdp_data *vd, u8 newstate) -+{ -+ switch(newstate) { -+ case ECP_TX_INIT_TRANSMIT: -+ break; -+ case ECP_TX_TRANSMIT_ECPDU: -+ assert((vd->ecp.tx.state == ECP_TX_INIT_TRANSMIT) || -+ (vd->ecp.tx.state == ECP_TX_WAIT_FOR_ACK) || -+ (vd->ecp.tx.state == ECP_TX_REQUEST_PDU)); -+ break; -+ case ECP_TX_WAIT_FOR_ACK: -+ assert(vd->ecp.tx.state == ECP_TX_TRANSMIT_ECPDU); -+ break; -+ case ECP_TX_REQUEST_PDU: -+ assert(vd->ecp.tx.state == ECP_TX_WAIT_FOR_ACK); -+ break; -+ default: -+ LLDPAD_ERR("%s: LLDP TX state machine invalid state %d\n", -+ vd->ifname, newstate); -+ } -+ LLDPAD_DBG("%s-%s: state change %s -> %s\n", __func__, -+ vd->ifname, ecp_tx_states[vd->ecp.tx.state], -+ ecp_tx_states[newstate]); -+ vd->ecp.tx.state = newstate; -+ return; -+} -+ -+/* ecp_set_tx_state - sets the ecp tx sm state -+ * @vd: currently used port -+ * -+ * returns true or false -+ * -+ * switches the state machine to the next state depending on the input -+ * variables. returns true or false depending on wether the state machine -+ * can be run again with the new state or can stop at the current state. -+ */ -+static bool ecp_set_tx_state(struct vdp_data *vd) -+{ -+ struct port *port = port_find_by_ifindex(get_ifidx(vd->ifname)); -+ -+ if (!port) { -+ LLDPAD_ERR("%s: port not found\n", __func__); -+ return 0; -+ } -+ -+ if (!port->portEnabled && port->prevPortEnabled) { -+ LLDPAD_ERR("set_tx_state: port was disabled\n"); -+ ecp_tx_change_state(vd, ECP_TX_INIT_TRANSMIT); -+ } -+ port->prevPortEnabled = port->portEnabled; -+ -+ switch (vd->ecp.tx.state) { -+ case ECP_TX_INIT_TRANSMIT: -+ if (port->portEnabled && vd->enabletx && -+ vd->ecp.tx.localChange) { -+ ecp_tx_change_state(vd, ECP_TX_TRANSMIT_ECPDU); -+ return true; -+ } -+ return false; -+ case ECP_TX_TRANSMIT_ECPDU: -+ if (!vd->enabletx) { -+ ecp_tx_change_state(vd, ECP_TX_INIT_TRANSMIT); -+ return true; -+ } -+ ecp_tx_change_state(vd, ECP_TX_WAIT_FOR_ACK); -+ return false; -+ case ECP_TX_WAIT_FOR_ACK: -+ if (ecp_ackTimer_expired(vd)) { -+ vd->ecp.retries++; -+ if (vd->ecp.retries < ECP_MAX_RETRIES) { -+ ecp_somethingChangedLocal(vd, true); -+ ecp_tx_change_state(vd, ECP_TX_TRANSMIT_ECPDU); -+ return true; -+ } -+ if (vd->ecp.retries == ECP_MAX_RETRIES) { -+ LLDPAD_DBG("%s-%s: retries expired\n", -+ __func__, vd->ifname); -+ ecp_tx_stop_ackTimer(vd); -+ ecp_tx_change_state(vd, ECP_TX_REQUEST_PDU); -+ return true; -+ } -+ } -+ if (vd->ecp.ackReceived && -+ vd->ecp.seqECPDU == vd->ecp.lastSequence) { -+ vd->ecp.ackReceived = false; -+ if (vdp_vsis_pending(vd)) { -+ LLDPAD_DBG("%s-%s: still work pending\n", -+ __func__, vd->ifname); -+ ecp_somethingChangedLocal(vd, true); -+ } -+ ecp_tx_change_state(vd, ECP_TX_REQUEST_PDU); -+ return true; -+ } -+ return false; -+ case ECP_TX_REQUEST_PDU: -+ if (vd->ecp.tx.localChange) { -+ ecp_tx_change_state(vd, ECP_TX_TRANSMIT_ECPDU); -+ return true; -+ } -+ return false; -+ default: -+ LLDPAD_ERR("%s: LLDP TX state machine in invalid state %d\n", -+ vd->ifname, vd->ecp.tx.state); -+ return false; -+ } -+} -+ -+/* ecp_tx_run_sm - state machine for ecp tx -+ * @vd: currently used vdp_data -+ * -+ * no return value -+ * -+ * runs the state machine for ecp tx. -+ */ -+void ecp_tx_run_sm(struct vdp_data *vd) -+{ -+ do { -+ LLDPAD_DBG("%s-%s: ecp_tx - %s\n", __func__, -+ vd->ifname, ecp_tx_states[vd->ecp.tx.state]); -+ -+ switch(vd->ecp.tx.state) { -+ case ECP_TX_INIT_TRANSMIT: -+ ecp_tx_Initialize(vd); -+ break; -+ case ECP_TX_TRANSMIT_ECPDU: -+ ecp_tx_create_frame(vd); -+ ecp_tx_start_ackTimer(vd); -+ ecp_somethingChangedLocal(vd, false); -+ break; -+ case ECP_TX_WAIT_FOR_ACK: -+ if (vd->ecp.ackReceived) { -+ LLDPAD_DBG("%s-%s: ECP_TX_WAIT_FOR_ACK " -+ "ackReceived seqECPDU %#x " -+ "lastSequence %#x\n", __func__, -+ vd->ifname, vd->ecp.seqECPDU, -+ vd->ecp.lastSequence); -+ ecp_somethingChangedLocal(vd, false); -+ ecp_tx_stop_ackTimer(vd); -+ } -+ break; -+ case ECP_TX_REQUEST_PDU: -+ vd->ecp.retries = 0; -+ LLDPAD_DBG("%s-%s: ECP_TX_REQUEST_PDU lastSeq %#x\n", -+ __func__, vd->ifname, vd->ecp.lastSequence); -+ break; -+ default: -+ LLDPAD_ERR("%s: LLDP TX state machine in invalid state %d\n", -+ vd->ifname, vd->ecp.tx.state); -+ } -+ } while (ecp_set_tx_state(vd) == true); -+} -+ -+static const char *ecp_rx_states[] = { -+ "ECP_RX_IDLE", -+ "ECP_RX_INIT_RECEIVE", -+ "ECP_RX_RECEIVE_WAIT", -+ "ECP_RX_RECEIVE_ECPDU", -+ "ECP_RX_SEND_ACK", -+ "ECP_RX_RESEND_ACK", -+}; -+ -+/* ecp_rx_Initialize - initializes the ecp rx state machine -+ * @vd: vd for the state machine -+ * -+ * no return value -+ * -+ * initialize some variables, get rid of old frame if necessary -+ */ -+static void ecp_rx_Initialize(struct vdp_data *vd) -+{ -+ vd->ecp.rx.rcvFrame = false; -+ vd->ecp.ackReceived = false; -+ vd->ecp.rx.frame_len = 0; -+} -+ -+/* ecp_rx_SendAckFrame - send ack frame -+ * @vd: port used by ecp -+ * -+ * currently always returns 0 -+ * -+ * copies current received frame over to frame out, fills in address of this -+ * port and set mode field to ACK. used by ecp_rx_send_ack_frame. -+ */ -+static int ecp_rx_SendAckFrame(struct vdp_data *vd) -+{ -+ u16 tlv_offset = 0; -+ struct ecp_hdr *ecp_hdr; -+ struct l2_ethhdr *hdr; -+ u8 own_addr[ETH_ALEN]; -+ -+ LLDPAD_DBG("%s:%s acking frame\n", __func__, vd->ecp.ifname); -+ /* copy over to transmit buffer */ -+ memcpy(vd->ecp.tx.frame, vd->ecp.rx.frame, vd->ecp.rx.frame_len); -+ vd->ecp.tx.frame_len = vd->ecp.rx.frame_len; -+ -+ /* use my own addr to send ACK */ -+ hdr = (struct l2_ethhdr *)vd->ecp.tx.frame; -+ l2_packet_get_own_src_addr(vd->ecp.l2,(u8 *)&own_addr); -+ memcpy(hdr->h_source, &own_addr, ETH_ALEN); -+ -+ tlv_offset = sizeof(struct l2_ethhdr); -+ ecp_hdr = (struct ecp_hdr *)&vd->ecp.tx.frame[tlv_offset]; -+ ecp_hdr->mode = ECP_ACK; -+ -+ tlv_offset = sizeof(struct l2_ethhdr) + sizeof(struct ecp_hdr); -+ LLDPAD_DBG("%s:%s zeroing out rest of ack frame from %i to %i\n", -+ __func__, vd->ecp.ifname, tlv_offset, vd->ecp.rx.frame_len); -+ memset(&vd->ecp.tx.frame[tlv_offset], 0, -+ vd->ecp.rx.frame_len - tlv_offset); -+ return 0; -+} -+ -+/* ecp_rx_send_ack_frame - send out ack frame for received frame -+ * @vd: vd for the state machine -+ * -+ * no return value -+ * -+ * creates an ack frame for a just received frame, prints the about to be -+ * sent frame and finally transmits it. -+ */ -+void ecp_rx_send_ack_frame(struct vdp_data *vd) -+{ -+ ecp_rx_SendAckFrame(vd); -+ hexdump_frame(vd->ecp.ifname, "frame-ack", vd->ecp.tx.frame, -+ vd->ecp.tx.frame_len); -+ ecp_txFrame(vd); -+} -+ -+/* ecp_rx_ReceiveFrame - receive ecp frame -+ * @ctx: rx callback context, struct vd * in this case -+ * @ifindex: index of interface -+ * @buf: buffer which contains the frame just received -+ * @len: size of buffer (frame) -+ * -+ * no return value -+ * -+ * creates a local copy of the buffer and checks the header. keeps some -+ * statistics about ecp frames. Checks if it is a request or an ack frame -+ * and branches to ecp rx or ecp tx state machine. -+ */ -+static void ecp_rx_ReceiveFrame(void *ctx, UNUSED int ifindex, const u8 *buf, -+ size_t len) -+{ -+ struct vdp_data *vd; -+ struct port *port; -+ u8 frame_error = 0; -+ u16 tlv_offset; -+ struct l2_ethhdr *hdr; -+ struct l2_ethhdr example_hdr,*ex; -+ struct ecp_hdr *ecp_hdr; -+ -+ if (!ctx) { -+ LLDPAD_WARN("%s: no ctx - can't process frame\n", __func__); -+ return; -+ } -+ -+ vd = (struct vdp_data *)ctx; -+ port = port_find_by_ifindex(get_ifidx(vd->ifname)); -+ if (!port) -+ return; -+ -+ LLDPAD_DBG("%s:%s received packet with size %i\n", __func__, -+ vd->ecp.ifname, (int)len); -+ if (vd->enabletx == false) -+ return; -+ -+ if (vd->ecp.rx.frame_len == len && -+ (memcmp(buf, vd->ecp.rx.frame, len) == 0)) { -+ vd->ecp.stats.statsFramesInTotal++; -+ return; -+ } -+ -+ memset(vd->ecp.rx.frame, 0, len); -+ memcpy(vd->ecp.rx.frame, buf, len); -+ -+ vd->ecp.rx.frame_len = (u16)len; -+ ex = &example_hdr; -+ memcpy(ex->h_dest, nearest_bridge, ETH_ALEN); -+ ex->h_proto = htons(ETH_P_ECP); -+ hdr = (struct l2_ethhdr *)vd->ecp.rx.frame; -+ -+ if ((memcmp(hdr->h_dest, ex->h_dest, ETH_ALEN) != 0)) { -+ LLDPAD_ERR("%s:%s ERROR multicast address error in incoming frame." -+ " Dropping frame.\n", __func__, vd->ecp.ifname); -+ frame_error++; -+ return; -+ } -+ -+ if (hdr->h_proto != example_hdr.h_proto) { -+ LLDPAD_ERR("%s:%s ERROR ethertype %#x not ECP ethertype", -+ __func__, vd->ecp.ifname, htons(hdr->h_proto)); -+ frame_error++; -+ return; -+ } -+ -+ if (!frame_error) { -+ vd->ecp.stats.statsFramesInTotal++; -+ vd->ecp.rx.rcvFrame = true; -+ } -+ -+ tlv_offset = sizeof(struct l2_ethhdr); -+ ecp_hdr = (struct ecp_hdr *)&vd->ecp.rx.frame[tlv_offset]; -+ vd->ecp.seqECPDU = ntohs(ecp_hdr->seqnr); -+ hexdump_frame(vd->ecp.ifname, "frame-in", vd->ecp.rx.frame, -+ vd->ecp.rx.frame_len); -+ -+ switch(ecp_hdr->mode) { -+ case ECP_REQUEST: -+ LLDPAD_DBG("%s:%s received REQ frame\n", __func__, -+ vd->ecp.ifname); -+ vd->ecp.ackReceived = false; -+ ecp_rx_run_sm(vd); -+ break; -+ case ECP_ACK: -+ LLDPAD_DBG("%s:%s received ACK frame\n", __func__, -+ vd->ecp.ifname); -+ vd->ecp.ackReceived = true; -+ vdp_ack_profiles(vd, vd->ecp.seqECPDU); -+ ecp_tx_run_sm(vd); -+ vd->ecp.ackReceived = false; -+ break; -+ default: -+ LLDPAD_ERR("%s:%s ERROR: unknown mode %i\n", __func__, -+ vd->ecp.ifname, ecp_hdr->mode); -+ return; -+ } -+ -+} -+ -+/* ecp_rx_change_state - changes the ecp rx sm state -+ * @vd: currently used port -+ * @newstate: new state for the sm -+ * -+ * no return value -+ * -+ * checks state transistion for consistency and finally changes the state of -+ * the profile. -+ */ -+static void ecp_rx_change_state(struct vdp_data *vd, u8 newstate) -+{ -+ switch(newstate) { -+ case ECP_RX_IDLE: -+ break; -+ case ECP_RX_INIT_RECEIVE: -+ break; -+ case ECP_RX_RECEIVE_WAIT: -+ assert((vd->ecp.rx.state == ECP_RX_INIT_RECEIVE) || -+ (vd->ecp.rx.state == ECP_RX_IDLE) || -+ (vd->ecp.rx.state == ECP_RX_SEND_ACK) || -+ (vd->ecp.rx.state == ECP_RX_RESEND_ACK)); -+ break; -+ case ECP_RX_RECEIVE_ECPDU: -+ assert(vd->ecp.rx.state == ECP_RX_RECEIVE_WAIT); -+ break; -+ case ECP_RX_SEND_ACK: -+ assert(vd->ecp.rx.state == ECP_RX_RECEIVE_ECPDU); -+ break; -+ case ECP_RX_RESEND_ACK: -+ assert(vd->ecp.rx.state == ECP_RX_RECEIVE_ECPDU); -+ break; -+ default: -+ LLDPAD_ERR("%s:%s LLDP RX state machine invalid state %d\n", -+ __func__, vd->ecp.ifname, newstate); -+ } -+ -+ LLDPAD_DBG("%s:%s state change %s -> %s\n", __func__, -+ vd->ecp.ifname, ecp_rx_states[vd->ecp.rx.state], -+ ecp_rx_states[newstate]); -+ -+ vd->ecp.rx.state = newstate; -+} -+ -+/* ecp_init - initialize ecp module -+ * @ifname: interface for which the module is initialized -+ * -+ * returns 0 on success, -1 on error -+ * -+ * finds the port to the interface name, sets up the receive handle for -+ * incoming ecp frames and initializes the ecp rx and tx state machines. -+ * should usually be called when a successful exchange of EVB TLVs has been -+ * made and ECP and VDP protocols are supported by both sides. -+ */ -+int ecp_init(char *ifname) -+{ -+ struct vdp_data *vd; -+ -+ LLDPAD_DBG("%s:%s starting ECP\n", __func__, ifname); -+ vd = vdp_data(ifname); -+ if (!vd) { -+ LLDPAD_ERR("%s:%s unable to find vd\n", __func__, ifname); -+ return -1; -+ } -+ -+ if (!vd->ecp.l2) -+ vd->ecp.l2 = l2_packet_init(vd->ifname, NULL, ETH_P_ECP, -+ ecp_rx_ReceiveFrame, vd, 1); -+ -+ if (!vd->ecp.l2) { -+ LLDPAD_ERR("%s:%s failed to access layer 2 access ETH_P_ECP\n", -+ __func__, ifname); -+ return -1; -+ } -+ strncpy(vd->ecp.ifname, ifname, sizeof vd->ecp.ifname); -+ ecp_rx_change_state(vd, ECP_RX_IDLE); -+ ecp_rx_run_sm(vd); -+ ecp_somethingChangedLocal(vd, true); -+ return 0; -+} -+ -+/* ecp_rx_validate_frame - validates received frame -+ * @vd: vdp_data used by ecp -+ * -+ * no return value -+ * -+ * checks wether received frame has correct subtype and mode -+ */ -+ -+static void ecp_rx_validate_frame(struct vdp_data *vd) -+{ -+ u16 tlv_offset = 0; -+ struct ecp_hdr *ecp_hdr; -+ -+ LLDPAD_DBG("%s:%s validating frame\n", __func__, vd->ecp.ifname); -+ tlv_offset = sizeof(struct l2_ethhdr); -+ ecp_hdr = (struct ecp_hdr *)&vd->ecp.rx.frame[tlv_offset]; -+ LLDPAD_DBG("%s:%s ecp packet with subtype %#x mode %#x seq %#04x\n", -+ __func__, vd->ecp.ifname, ecp_hdr->subtype, ecp_hdr->mode, -+ ntohs(ecp_hdr->seqnr)); -+ -+ if (ecp_hdr->subtype != ECP_SUBTYPE) { -+ LLDPAD_ERR("%s:%s ERROR: unknown subtype\n", __func__, -+ vd->ecp.ifname); -+ return; -+ } -+ -+ if ((ecp_hdr->oui[0] != 0x0) || (ecp_hdr->oui[1] != 0x1b) || -+ (ecp_hdr->oui[2] != 0x3f)) { -+ LLDPAD_ERR("%s:%s ERROR: incorrect OUI 0x%02x%02x%02x\n", -+ __func__, vd->ecp.ifname, ecp_hdr->oui[0], -+ ecp_hdr->oui[1], ecp_hdr->oui[2]); -+ return; -+ } -+ -+ switch(ecp_hdr->mode) { -+ case ECP_REQUEST: -+ break; -+ case ECP_ACK: -+ break; -+ default: -+ LLDPAD_ERR("%s:%s ERROR: unknown mode %i\n", __func__, -+ vd->ecp.ifname, ecp_hdr->mode); -+ return; -+ } -+ -+ /* FIXME: also done in ecp_rx_ReceiveFrame, -+ * are both necessary ? */ -+ vd->ecp.seqECPDU = ntohs(ecp_hdr->seqnr); -+} -+ -+/* ecp_rx_ProcessFrame - process received ecp frames -+ * @vd: currently used port -+ * -+ * no return value -+ * -+ * walks through the packed vsi tlvs in an ecp frame, extracts them -+ * and passes them to the VDP ULP with vdp_indicate. -+ */ -+static void ecp_rx_ProcessFrame(struct vdp_data *vd) -+{ -+ u16 tlv_cnt = 0; -+ u8 tlv_type = 0; -+ u16 tlv_length = 0; -+ u16 tlv_offset = 0; -+ u16 *tlv_head_ptr = NULL; -+ u8 frame_error = 0; -+ bool tlv_stored = false; -+ struct ecp_hdr *ecp_hdr; -+ int vdp_called; -+ -+ LLDPAD_DBG("%s:%s processing frame\n", __func__, vd->ecp.ifname); -+ tlv_offset = sizeof(struct l2_ethhdr); -+ -+ ecp_hdr = (struct ecp_hdr *)&vd->ecp.rx.frame[tlv_offset]; -+ LLDPAD_DBG("%s:%s ecp packet with subtype %#x mode %#x seq %#04x\n", -+ __func__, vd->ifname, ecp_hdr->subtype, -+ ecp_hdr->mode, ntohs(ecp_hdr->seqnr)); -+ if (ecp_hdr->mode == ECP_ACK) -+ return; -+ -+ /* processing of VSI_TLVs starts here */ -+ tlv_offset += sizeof(struct ecp_hdr); -+ vdp_called = 0; -+ do { -+ tlv_cnt++; -+ -+ if (tlv_offset > vd->ecp.rx.frame_len) { -+ LLDPAD_ERR("%s:%s ERROR: Frame overrun! tlv_offset %i" -+ " frame_len %i cnt %i\n", __func__, -+ vd->ecp.ifname, tlv_offset, -+ vd->ecp.rx.frame_len, tlv_cnt); -+ frame_error++; -+ goto out; -+ } -+ -+ if (tlv_offset + 2 > vd->ecp.rx.frame_len) { -+ LLDPAD_DBG("%s:%s tlv EOF problem size=%d offset=%d\n", -+ __func__, vd->ecp.ifname, -+ vd->ecp.rx.frame_len, tlv_offset); -+ frame_error++; -+ goto out; -+ } -+ -+ tlv_head_ptr = (u16 *)&vd->ecp.rx.frame[tlv_offset]; -+ tlv_length = htons(*tlv_head_ptr) & 0x01FF; -+ tlv_type = (u8)(htons(*tlv_head_ptr) >> 9); -+ -+ u16 tmp_offset = tlv_offset + tlv_length; -+ if (tmp_offset > vd->ecp.rx.frame_len) { -+ LLDPAD_ERR("%s:%s ERROR: Frame overflow: offset=%d " -+ "rx.size=%d\n", __func__, vd->ecp.ifname, -+ tmp_offset, vd->ecp.rx.frame_len); -+ frame_error++; -+ goto out; -+ } -+ -+ u8 *info = (u8 *)&vd->ecp.rx.frame[tlv_offset + -+ sizeof(*tlv_head_ptr)]; -+ -+ struct unpacked_tlv *tlv = create_tlv(); -+ -+ if (!tlv) { -+ LLDPAD_DBG("%s:%s failed malloc for incoming TLV\n", -+ __func__, vd->ecp.ifname); -+ goto out; -+ } -+ -+ if ((tlv_length == 0) && (tlv->type != TYPE_0)) { -+ LLDPAD_DBG("%s:%s tlv_length == 0\n", __func__, -+ vd->ecp.ifname); -+ free_unpkd_tlv(tlv); -+ goto out; -+ } -+ -+ tlv->type = tlv_type; -+ tlv->length = tlv_length; -+ tlv->info = (u8 *)malloc(tlv_length); -+ if (tlv->info) { -+ memset(tlv->info,0, tlv_length); -+ memcpy(tlv->info, info, tlv_length); -+ } else { -+ LLDPAD_DBG("%s:%s failed malloc for incoming TLV info\n", -+ __func__, vd->ecp.ifname); -+ free_unpkd_tlv(tlv); -+ goto out; -+ } -+ -+ /* Validate the TLV */ -+ tlv_offset += sizeof(*tlv_head_ptr) + tlv_length; -+ -+ if (tlv->type == TYPE_127) { /* private TLV */ -+ /* give VSI TLV to VDP */ -+ if (!vdp_indicate(vd, tlv)) { -+ tlv_stored = true; -+ ++vdp_called; -+ } else { -+ /* TODO -+ * put it in a list and try again later until -+ * timer and retries have expired -+ */ -+ tlv_stored = false; -+ } -+ } -+ -+ if ((tlv->type != TYPE_0) && !tlv_stored) { -+ LLDPAD_DBG("%s:%s TLV (%u) was not stored (%p)\n", -+ __func__, vd->ecp.ifname, tlv->type, tlv); -+ tlv = free_unpkd_tlv(tlv); -+ vd->ecp.stats.statsTLVsUnrecognizedTotal++; -+ } -+ tlv = NULL; -+ tlv_stored = false; -+ } while (tlv_offset < vd->ecp.rx.frame_len); -+out: -+ if (frame_error) { -+ vd->ecp.stats.statsFramesDiscardedTotal++; -+ vd->ecp.stats.statsFramesInErrorsTotal++; -+ } -+ if (vdp_called) -+ vdp_advance_sm(vd); -+} -+ -+/* ecp_set_rx_state - sets the ecp rx sm state -+ * @vd: currently used port -+ * -+ * returns true or false -+ * -+ * switches the state machine to the next state depending on the input -+ * variables. returns true or false depending on wether the state machine -+ * can be run again with the new state or can stop at the current state. -+ */ -+static bool ecp_set_rx_state(struct vdp_data *vd) -+{ -+ struct port *port = port_find_by_ifindex(get_ifidx(vd->ifname)); -+ -+ if (!port) -+ return false; -+ -+ if (port->portEnabled == false) -+ ecp_rx_change_state(vd, ECP_RX_IDLE); -+ -+ switch(vd->ecp.rx.state) { -+ case ECP_RX_IDLE: -+ if (port->portEnabled == true) { -+ ecp_rx_change_state(vd, ECP_RX_INIT_RECEIVE); -+ return true; -+ } -+ return false; -+ case ECP_RX_INIT_RECEIVE: -+ if (vd->enabletx == true) { -+ ecp_rx_change_state(vd, ECP_RX_RECEIVE_WAIT); -+ return true; -+ } -+ return false; -+ case ECP_RX_RECEIVE_WAIT: -+ if (vd->enabletx == false) { -+ ecp_rx_change_state(vd, ECP_RX_IDLE); -+ return true; -+ } -+ if (vd->ecp.rx.rcvFrame == true) { -+ ecp_rx_change_state(vd, ECP_RX_RECEIVE_ECPDU); -+ return true; -+ } -+ return false; -+ case ECP_RX_RECEIVE_ECPDU: -+ if (vd->ecp.seqECPDU == vd->ecp.lastSequence) { -+ LLDPAD_DBG("%s:%s seqECPDU %x, lastSequence %x\n", -+ __func__, vd->ecp.ifname, vd->ecp.seqECPDU, -+ vd->ecp.lastSequence); -+ ecp_rx_change_state(vd, ECP_RX_RESEND_ACK); -+ return true; -+ } -+ if (vd->ecp.seqECPDU != vd->ecp.lastSequence) { -+ ecp_rx_change_state(vd, ECP_RX_RESEND_ACK); -+ return true; -+ } -+ return false; -+ case ECP_RX_SEND_ACK: -+ case ECP_RX_RESEND_ACK: -+ ecp_rx_change_state(vd, ECP_RX_RECEIVE_WAIT); -+ return false; -+ default: -+ LLDPAD_DBG("%s:%s ECP RX state machine in invalid state %d\n", -+ __func__, vd->ecp.ifname, vd->ecp.rx.state); -+ return false; -+ } -+} -+ -+/* ecp_rx_run_sm - state machine for ecp rx -+ * @vd: currently used port -+ * -+ * no return value -+ * -+ * runs the state machine for ecp rx. -+ */ -+static void ecp_rx_run_sm(struct vdp_data *vd) -+{ -+ ecp_set_rx_state(vd); -+ do { -+ LLDPAD_DBG("%s:%s ecp_rx - %s\n", __func__, vd->ecp.ifname, -+ ecp_rx_states[vd->ecp.tx.state]); -+ -+ switch(vd->ecp.rx.state) { -+ case ECP_RX_IDLE: -+ break; -+ case ECP_RX_INIT_RECEIVE: -+ ecp_rx_Initialize(vd); -+ break; -+ case ECP_RX_RECEIVE_WAIT: -+ break; -+ case ECP_RX_RECEIVE_ECPDU: -+ vd->ecp.rx.rcvFrame = false; -+ ecp_rx_validate_frame(vd); -+ break; -+ case ECP_RX_SEND_ACK: -+ ecp_rx_ProcessFrame(vd); -+ break; -+ case ECP_RX_RESEND_ACK: -+ ecp_rx_ProcessFrame(vd); -+ if (!vd->ecp.ackReceived) { -+ ecp_rx_send_ack_frame(vd); -+ } -+ break; -+ default: -+ LLDPAD_DBG("%s:%s ECP RX state machine in invalid state %d\n", -+ __func__, vd->ecp.ifname, vd->ecp.rx.state); -+ } -+ } while (ecp_set_rx_state(vd) == true); -+} -diff --git a/qbg/ecp22.c b/qbg/ecp22.c -new file mode 100644 -index 0000000..4640701 ---- /dev/null -+++ b/qbg/ecp22.c -@@ -0,0 +1,1055 @@ -+/****************************************************************************** -+ -+ Implementation of ECP according to 802.1Qbg -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Jens Osterkamp -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+#include -+#include -+#include -+#include -+ -+#include "eloop.h" -+#include "qbg_ecp22.h" -+#include "messages.h" -+#include "qbg_utils.h" -+#include "lldp/l2_packet.h" -+#include "lldp_tlv.h" -+ -+#define ECP22_MAX_RETRIES_DEFAULT (3) /* Default # of max retries */ -+#define ECP22_ACK_TIMER_STOPPED (-1) -+/* -+ * Defaults to 2ms wait time for acknowledgement packet reception. -+ */ -+#define ECP22_ACK_TIMER_DEFAULT (8) -+ -+static void ecp22_tx_run_sm(struct ecp22 *); -+ -+static const char *const ecp22_rx_states[] = { /* Receive states verbatim */ -+ "ECP22_RX_BEGIN", -+ "ECP22_RX_WAIT", -+ "ECP22_RX_WAIT2", -+ "ECP22_RX_FIRST", -+ "ECP22_RX_REC_ECPDU", -+ "ECP22_RX_NEW_ECPDU", -+ "ECP22_RX_SEND_ACK" -+}; -+ -+static const char *const ecp22_tx_states[] = { /* Transmit states verbatim */ -+ "ECP22_TX_BEGIN", -+ "ECP22_TX_INIT", -+ "ECP22_TX_TXMIT_ECPDU", -+ "ECP22_TX_WAIT_FORREQ", -+ "ECP22_TX_WAIT_ONDATA", -+ "ECP22_TX_ERROR" -+}; -+ -+/* -+ * Increment sequence number. Do not return zero as sequence number. -+ */ -+static unsigned short inc_seqno(unsigned short x) -+{ -+ ++x; -+ if (!x) /* Wrapped */ -+ ++x; -+ return x; -+} -+ -+/* -+ * Find the ecp data associated with an interface. -+ * Return pointer or NULL if not found. -+ */ -+static struct ecp22 *find_ecpdata(char *ifname, struct ecp22_user_data *eud) -+{ -+ struct ecp22 *ecp = 0; -+ -+ if (eud) { -+ LIST_FOREACH(ecp, &eud->head, node) -+ if (!strncmp(ifname, ecp->ifname, IFNAMSIZ)) -+ break; -+ } -+ return ecp; -+} -+ -+/* -+ * ecp22_txframe - transmit ecp frame -+ * @ecp: pointer to currently used ecp data structure -+ * -+ * returns the number of characters sent on success, -1 on failure -+ * -+ * sends out the frame stored in the frame structure using l2_packet_send. -+ */ -+static int ecp22_txframe(struct ecp22 *ecp, char *txt, unsigned char *dst, -+ unsigned char *ack, size_t len) -+{ -+ hexdump_frame(ecp->ifname, txt, ack, len); -+ return l2_packet_send(ecp->l2, dst, htons(ETH_P_ECP22), ack, len); -+} -+ -+static void ecp22_append(u8 *buffer, u32 *pos, void *data, u32 len) -+{ -+ if (*pos + len > ETH_FRAME_LEN) -+ return; -+ memcpy(buffer + *pos, data, len); -+ *pos += len; -+} -+ -+/* -+ * Return a payload node to the freelist. -+ */ -+void ecp22_putnode(struct ecp22_freelist *list, struct ecp22_payload_node *elm) -+{ -+ elm->ptlv = free_pkd_tlv(elm->ptlv); -+ if (list->freecnt > ecp22_maxpayload) -+ free(elm); -+ else { -+ ++list->freecnt; -+ LIST_INSERT_HEAD(&list->head, elm, node); -+ } -+} -+ -+/* -+ * ecp22_build_ecpdu - create an ecp protocol data unit -+ * @ecp: pointer to currently used ecp data structure -+ * -+ * returns true on success, false on failure -+ * -+ * creates the frame header with the ports mac address, the ecp header with REQ -+ * plus a packed TLVs created taken from the send queue. -+ */ -+static bool ecp22_build_ecpdu(struct ecp22 *ecp) -+{ -+ struct l2_ethhdr eth; -+ struct ecp22_hdr ecph; -+ u32 fb_offset = 0; -+ struct packed_tlv *ptlv; -+ struct ecp22_payload_node *p = LIST_FIRST(&ecp->inuse.head); -+ -+ if (!p) -+ return false; -+ ecp->tx.ecpdu_received = true; /* Txmit buffer in use */ -+ memcpy(eth.h_dest, p->mac, ETH_ALEN); -+ l2_packet_get_own_src_addr(ecp->l2, eth.h_source); -+ eth.h_proto = htons(ETH_P_ECP22); -+ memset(ecp->tx.frame, 0, sizeof ecp->tx.frame); -+ ecp22_append(ecp->tx.frame, &fb_offset, (void *)ð, sizeof eth); -+ -+ ecp22_hdr_set_version(&ecph, 1); -+ ecp22_hdr_set_op(&ecph, ECP22_REQUEST); -+ ecp22_hdr_set_subtype(&ecph, ECP22_VDP); -+ ecph.ver_op_sub = htons(ecph.ver_op_sub); -+ ecph.seqno = htons(ecp->tx.seqno); -+ ecp22_append(ecp->tx.frame, &fb_offset, (void *)&ecph, sizeof ecph); -+ -+ ptlv = p->ptlv; -+ ecp22_append(ecp->tx.frame, &fb_offset, ptlv->tlv, ptlv->size); -+ ecp->tx.frame_len = MAX(fb_offset, (unsigned)ETH_ZLEN); -+ LIST_REMOVE(p, node); -+ ecp22_putnode(&ecp->isfree, p); -+ LLDPAD_DBG("%s:%s seqno %#hx frame_len %#hx\n", __func__, -+ ecp->ifname, ecp->tx.seqno, ecp->tx.frame_len); -+ return true; -+} -+ -+/* -+ * Execute transmit state transmitECPDU. -+ */ -+static void ecp22_es_waitforreq(struct ecp22 *ecp) -+{ -+ ecp->tx.retries = 0; -+ ecp->tx.ack_received = false; -+ ecp->tx.ecpdu_received = false; -+ ecp->tx.seqno = inc_seqno(ecp->tx.seqno); -+ LLDPAD_DBG("%s:%s seqno %#hx\n", __func__, ecp->ifname, ecp->tx.seqno); -+} -+ -+/* -+ * Execute transmit state countErrors. -+ */ -+static void ecp22_es_counterror(struct ecp22 *ecp) -+{ -+ ++ecp->tx.errors; -+ LLDPAD_DBG("%s:%s errors %lu\n", __func__, ecp->ifname, -+ ecp->tx.errors); -+} -+ -+/* -+ * Execute transmit state initTransmit. -+ */ -+static void ecp22_es_inittransmit(struct ecp22 *ecp) -+{ -+ ecp->tx.errors = 0; -+ ecp->tx.seqno = 0; -+} -+ -+/* -+ * Return RTE value in milliseconds. -+ */ -+static int rtevalue(unsigned char rte) -+{ -+ return (1 << rte) * 10; -+} -+ -+/* -+ * ecp22_ack_timeout_handler - handles the ack timer expiry -+ * @eloop_data: data structure of event loop -+ * @user_ctx: user context, vdp_data here -+ * -+ * no return value -+ * -+ * called when the ECP timer has expired. Calls the ECP station state machine. -+ */ -+static void ecp22_ack_timeout_handler(UNUSED void *eloop_data, void *user_ctx) -+{ -+ struct ecp22 *ecp = (struct ecp22 *)user_ctx; -+ -+ LLDPAD_DBG("%s:%s retries:%d\n", __func__, -+ ecp->ifname, ecp->tx.retries); -+ ecp22_tx_run_sm(ecp); -+} -+ -+/* -+ * ecp22_tx_start_acktimer - starts the ECP ack timer -+ * @ecp: pointer to currently used ecp data structure -+ * -+ * returns 0 on success, -1 on error -+ * -+ * starts the ack timer when a frame has been sent out. -+ */ -+static void ecp22_tx_start_acktimer(struct ecp22 *ecp) -+{ -+ unsigned long ack_sec = rtevalue(ecp->max_rte) / 1000000; -+ unsigned long ack_usec = rtevalue(ecp->max_rte) % 1000000; -+ -+ LLDPAD_DBG("%s:%s [%ld.%06ld]\n", __func__, ecp->ifname, ack_sec, -+ ack_usec); -+ eloop_register_timeout(ack_sec, ack_usec, ecp22_ack_timeout_handler, -+ 0, (void *)ecp); -+} -+ -+/* -+ * ecp22_tx_change_state - changes the ecp tx sm state -+ * @ecp: pointer to currently used ecp data structure -+ * @newstate: new state for the sm -+ * -+ * no return value -+ * -+ * checks state transistion for consistency and finally changes the state of -+ * the profile. -+ */ -+static void ecp22_tx_change_state(struct ecp22 *ecp, unsigned char newstate) -+{ -+ switch (newstate) { -+ case ECP22_TX_BEGIN: -+ break; -+ case ECP22_TX_INIT: -+ assert(ecp->tx.state == ECP22_TX_BEGIN); -+ break; -+ case ECP22_TX_WAIT_FORREQ: -+ assert(ecp->tx.state == ECP22_TX_INIT || -+ ecp->tx.state == ECP22_TX_ERROR || -+ ecp->tx.state == ECP22_TX_TXMIT_ECPDU); -+ break; -+ case ECP22_TX_WAIT_ONDATA: -+ assert(ecp->tx.state == ECP22_TX_WAIT_FORREQ); -+ break; -+ case ECP22_TX_TXMIT_ECPDU: -+ assert(ecp->tx.state == ECP22_TX_WAIT_ONDATA); -+ break; -+ case ECP22_TX_ERROR: -+ assert(ecp->tx.state == ECP22_TX_TXMIT_ECPDU); -+ break; -+ default: -+ LLDPAD_ERR("%s: ECP TX state machine invalid state %d\n", -+ ecp->ifname, newstate); -+ } -+ LLDPAD_DBG("%s:%s state change %s -> %s\n", __func__, -+ ecp->ifname, ecp22_tx_states[ecp->tx.state], -+ ecp22_tx_states[newstate]); -+ ecp->tx.state = newstate; -+} -+ -+/* -+ * Send the payload data. -+ */ -+static int ecp22_es_txmit(struct ecp22 *ecp) -+{ -+ int rc = 0; -+ -+ ++ecp->tx.retries; -+ ecp22_txframe(ecp, "ecp-out", ecp->tx.frame, ecp->tx.frame, -+ ecp->tx.frame_len); -+ ecp22_tx_start_acktimer(ecp); -+ return rc; -+} -+ -+/* -+ * ecp22_set_tx_state - sets the ecp tx state machine state -+ * @ecp: pointer to currently used ecp data structure -+ * -+ * returns true or false -+ * -+ * switches the state machine to the next state depending on the input -+ * variables. returns true or false depending on wether the state machine -+ * can be run again with the new state or can stop at the current state. -+ */ -+static bool ecp22_set_tx_state(struct ecp22 *ecp) -+{ -+ struct port *port = port_find_by_ifindex(get_ifidx(ecp->ifname)); -+ -+ if (!port) { -+ LLDPAD_ERR("%s:%s port not found\n", __func__, ecp->ifname); -+ return false; -+ } -+ if (!port->portEnabled && port->prevPortEnabled) { -+ LLDPAD_ERR("%s:%s port was disabled\n", __func__, ecp->ifname); -+ ecp22_tx_change_state(ecp, ECP22_TX_BEGIN); -+ } -+ port->prevPortEnabled = port->portEnabled; -+ -+ switch (ecp->tx.state) { -+ case ECP22_TX_BEGIN: -+ ecp22_tx_change_state(ecp, ECP22_TX_INIT); -+ return true; -+ case ECP22_TX_INIT: -+ ecp22_tx_change_state(ecp, ECP22_TX_WAIT_FORREQ); -+ return true; -+ case ECP22_TX_WAIT_FORREQ: -+ ecp22_tx_change_state(ecp, ECP22_TX_WAIT_ONDATA); -+ return true; -+ case ECP22_TX_WAIT_ONDATA: -+ if (LIST_FIRST(&ecp->inuse.head)) { /* Data to send */ -+ ecp22_build_ecpdu(ecp); -+ ecp22_tx_change_state(ecp, ECP22_TX_TXMIT_ECPDU); -+ return true; -+ } -+ return false; -+ case ECP22_TX_TXMIT_ECPDU: -+ if (ecp->tx.ack_received) { -+ ecp22_tx_change_state(ecp, ECP22_TX_WAIT_FORREQ); -+ return true; -+ } -+ if (ecp->tx.retries > ecp->max_retries) { -+ ecp22_tx_change_state(ecp, ECP22_TX_ERROR); -+ return true; -+ } -+ return false; -+ case ECP22_TX_ERROR: -+ ecp22_tx_change_state(ecp, ECP22_TX_WAIT_FORREQ); -+ return true; -+ default: -+ LLDPAD_ERR("%s: ECP TX state machine in invalid state %d\n", -+ ecp->ifname, ecp->tx.state); -+ return false; -+ } -+} -+ -+/* -+ * ecp22_tx_run_sm - state machine for ecp transmit -+ * @ecp: pointer to currently used ecp data structure -+ * -+ * no return value -+ */ -+static void ecp22_tx_run_sm(struct ecp22 *ecp) -+{ -+ ecp22_set_tx_state(ecp); -+ do { -+ LLDPAD_DBG("%s:%s state %s\n", __func__, -+ ecp->ifname, ecp22_tx_states[ecp->tx.state]); -+ -+ switch (ecp->tx.state) { -+ case ECP22_TX_BEGIN: -+ break; -+ case ECP22_TX_INIT: -+ ecp22_es_inittransmit(ecp); -+ break; -+ case ECP22_TX_WAIT_FORREQ: -+ ecp22_es_waitforreq(ecp); -+ break; -+ case ECP22_TX_WAIT_ONDATA: -+ break; -+ case ECP22_TX_TXMIT_ECPDU: -+ ecp22_es_txmit(ecp); -+ break; -+ case ECP22_TX_ERROR: -+ ecp22_es_counterror(ecp); -+ break; -+ } -+ } while (ecp22_set_tx_state(ecp) == true); -+} -+ -+/* -+ * ecp22_rx_change_state - changes the ecp rx sm state -+ * @ecp: pointer to currently used ecp data structure -+ * @newstate: new state for the sm -+ * -+ * no return value -+ * -+ * checks state transistion for consistency and finally changes the state of -+ * the ecp receive buffer. -+ */ -+static void ecp22_rx_change_state(struct ecp22 *ecp, u8 newstate) -+{ -+ switch (newstate) { -+ case ECP22_RX_BEGIN: -+ break; -+ case ECP22_RX_WAIT: -+ assert(ecp->rx.state == ECP22_RX_BEGIN); -+ break; -+ case ECP22_RX_FIRST: -+ assert(ecp->rx.state == ECP22_RX_WAIT); -+ break; -+ case ECP22_RX_REC_ECPDU: -+ assert((ecp->rx.state == ECP22_RX_FIRST) || -+ (ecp->rx.state == ECP22_RX_WAIT2)); -+ break; -+ case ECP22_RX_NEW_ECPDU: -+ assert(ecp->rx.state == ECP22_RX_REC_ECPDU); -+ break; -+ case ECP22_RX_SEND_ACK: -+ assert((ecp->rx.state == ECP22_RX_REC_ECPDU) || -+ (ecp->rx.state == ECP22_RX_NEW_ECPDU)); -+ break; -+ case ECP22_RX_WAIT2: -+ assert(ecp->rx.state == ECP22_RX_SEND_ACK); -+ break; -+ default: -+ LLDPAD_ERR("%s:%s LLDP RX state machine invalid state %d\n", -+ __func__, ecp->ifname, newstate); -+ } -+ LLDPAD_DBG("%s:%s state change %s -> %s\n", __func__, -+ ecp->ifname, ecp22_rx_states[ecp->rx.state], -+ ecp22_rx_states[newstate]); -+ ecp->rx.state = newstate; -+} -+ -+/* -+ * Execute action in state sendack. Construct and send an acknowledgement -+ * for the received ECP packet. -+ */ -+static void ecp22_es_send_ack(struct ecp22 *ecp) -+{ -+ unsigned char ack_frame[ETH_HLEN + sizeof(struct ecp22_hdr)]; -+ struct ethhdr *ethdst = (struct ethhdr *)ack_frame; -+ struct ecp22_hdr *ecpdst = (struct ecp22_hdr *)&ack_frame[ETH_HLEN]; -+ struct ethhdr *ethsrc = (struct ethhdr *)ecp->rx.frame; -+ struct ecp22_hdr *ecpsrc = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -+ struct ecp22_hdr ack; -+ -+ LLDPAD_DBG("%s:%s state %s seqno %#hx\n", __func__, ecp->ifname, -+ ecp22_rx_states[ecp->rx.state], ecp->rx.seqno); -+ memcpy(ethdst->h_dest, nearest_customer_bridge, ETH_ALEN); -+ l2_packet_get_own_src_addr(ecp->l2, (u8 *)ðdst->h_source); -+ ethdst->h_proto = ethsrc->h_proto; -+ /* Set ECP header */ -+ ack.ver_op_sub = ntohs(ecpsrc->ver_op_sub); -+ ecp22_hdr_set_op(&ack, ECP22_ACK); -+ ecpdst->ver_op_sub = htons(ack.ver_op_sub); -+ ecpdst->seqno = htons(ecp->rx.seqno); -+ ecp22_txframe(ecp, "ecp-ack", ethsrc->h_source, ack_frame, -+ sizeof ack_frame); -+} -+ -+ -+/* -+ * Notify upper layer protocol function of ECP payload data just received. -+ */ -+static void ecp22_to_ulp(unsigned short ulp, struct ecp22 *ecp) -+{ -+ size_t offset = ETH_HLEN + sizeof(struct ecp22_hdr); -+ struct qbg22_imm to_ulp; -+ -+ to_ulp.data_type = ECP22_TO_ULP; -+ to_ulp.u.c.len = ecp->rx.frame_len - offset; -+ to_ulp.u.c.data = &ecp->rx.frame[offset]; -+ if (ulp == ECP22_VDP) -+ modules_notify(LLDP_MOD_VDP22, LLDP_MOD_ECP22, ecp->ifname, -+ &to_ulp); -+ else -+ LLDPAD_INFO("%s:%s ECP subtype %d not yet implemented\n", -+ __func__, ecp->ifname, ulp); -+} -+ -+/* -+ * Execute action in state newECPDU. -+ * Notify upper layer protocol of new data. -+ */ -+static void ecp22_es_new_ecpdu(struct ecp22 *ecp) -+{ -+ struct ecp22_hdr *hdr = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -+ struct ecp22_hdr ecphdr; -+ unsigned short ulp; -+ -+ ecphdr.ver_op_sub = ntohs(hdr->ver_op_sub); -+ ulp = ecp22_hdr_read_subtype(&ecphdr); -+ LLDPAD_DBG("%s:%s state %s notify ULP %d seqno %#hx\n", __func__, -+ ecp->ifname, ecp22_rx_states[ecp->rx.state], -+ ulp, ecp->rx.seqno); -+ ecp->rx.last_seqno = ecp->rx.seqno; -+ ecp22_to_ulp(ulp, ecp); -+} -+ -+/* -+ * Execute action in state receiveECPDU. -+ */ -+static void ecp22_es_rec_ecpdu(struct ecp22 *ecp) -+{ -+ struct ecp22_hdr *hdr = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -+ -+ ecp->rx.seqno = ntohs(hdr->seqno); -+ LLDPAD_DBG("%s:%s state %s seqno %#hx\n", __func__, ecp->ifname, -+ ecp22_rx_states[ecp->rx.state], ecp->rx.seqno); -+} -+ -+/* -+ * Execute action in state receiveFirst. -+ */ -+static void ecp22_es_first(struct ecp22 *ecp) -+{ -+ struct ecp22_hdr *hdr = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -+ -+ LLDPAD_DBG("%s:%s state %s\n", __func__, ecp->ifname, -+ ecp22_rx_states[ecp->rx.state]); -+ ecp->rx.last_seqno = ntohs(hdr->seqno) - 1; -+} -+ -+/* -+ * Execute action in state receiveWait. -+ */ -+static void ecp22_es_wait(struct ecp22 *ecp) -+{ -+ LLDPAD_DBG("%s:%s state %s\n", __func__, ecp->ifname, -+ ecp22_rx_states[ecp->rx.state]); -+ ecp->rx.ecpdu_received = false; -+} -+ -+/* -+ * ecp22_set_rx_state - sets the ecp receive state machine state -+ * @ecp: pointer to currently used ecp data structure -+ * -+ * returns true or false -+ * -+ * switches the state machine to the next state depending on the input -+ * variables. Returns true or false depending on wether the state machine -+ * can be run again with the new state or can stop at the current state. -+ */ -+static bool ecp22_set_rx_state(struct ecp22 *ecp) -+{ -+ struct port *port = port_find_by_ifindex(get_ifidx(ecp->ifname)); -+ -+ if (!port) -+ return false; -+ -+ LLDPAD_DBG("%s:%s state %s\n", __func__, ecp->ifname, -+ ecp22_rx_states[ecp->rx.state]); -+ if (!port->portEnabled) -+ ecp22_rx_change_state(ecp, ECP22_RX_BEGIN); -+ switch (ecp->rx.state) { -+ case ECP22_RX_BEGIN: -+ ecp22_rx_change_state(ecp, ECP22_RX_WAIT); -+ return false; -+ case ECP22_RX_WAIT: -+ if (ecp->rx.ecpdu_received) { -+ ecp22_rx_change_state(ecp, ECP22_RX_FIRST); -+ return true; -+ } -+ return false; -+ case ECP22_RX_WAIT2: -+ if (ecp->rx.ecpdu_received) { -+ ecp22_rx_change_state(ecp, ECP22_RX_REC_ECPDU); -+ return true; -+ } -+ return false; -+ case ECP22_RX_FIRST: -+ ecp22_rx_change_state(ecp, ECP22_RX_REC_ECPDU); -+ return true; -+ case ECP22_RX_REC_ECPDU: -+ if (ecp->rx.seqno == ecp->rx.last_seqno) -+ ecp22_rx_change_state(ecp, ECP22_RX_SEND_ACK); -+ else -+ ecp22_rx_change_state(ecp, ECP22_RX_NEW_ECPDU); -+ return true; -+ case ECP22_RX_NEW_ECPDU: -+ ecp22_rx_change_state(ecp, ECP22_RX_SEND_ACK); -+ return true; -+ case ECP22_RX_SEND_ACK: -+ ecp22_rx_change_state(ecp, ECP22_RX_WAIT2); -+ return true; -+ default: -+ LLDPAD_DBG("%s:%s ECP RX state machine in invalid state %d\n", -+ __func__, ecp->ifname, ecp->rx.state); -+ return false; -+ } -+} -+ -+/* -+ * ecp22_rx_run_sm - state machine for ecp receive protocol -+ * @ecp: pointer to currently used ecp data structure -+ * -+ * no return value -+ * -+ * runs the state machine for ecp22 receive function. -+ */ -+static void ecp22_rx_run_sm(struct ecp22 *ecp) -+{ -+ ecp22_set_rx_state(ecp); -+ do { -+ switch (ecp->rx.state) { -+ case ECP22_RX_WAIT: -+ case ECP22_RX_WAIT2: -+ ecp22_es_wait(ecp); -+ break; -+ case ECP22_RX_FIRST: -+ ecp22_es_first(ecp); -+ break; -+ case ECP22_RX_REC_ECPDU: -+ ecp22_es_rec_ecpdu(ecp); -+ break; -+ case ECP22_RX_NEW_ECPDU: -+ ecp22_es_new_ecpdu(ecp); -+ break; -+ case ECP22_RX_SEND_ACK: -+ ecp22_es_send_ack(ecp); -+ break; -+ default: -+ LLDPAD_DBG("%s:%s ECP RX state machine in invalid " -+ "state %d\n", __func__, ecp->ifname, -+ ecp->rx.state); -+ } -+ } while (ecp22_set_rx_state(ecp) == true); -+} -+ -+/* -+ * Received an aknowledgement frame. -+ * Check if we have a transmit pending and the ack'ed packet number matches -+ * the send packet. -+ */ -+static void ecp22_recack_frame(struct ecp22 *ecp, unsigned short seqno) -+{ -+ LLDPAD_DBG("%s:%s txmit:%d seqno %#hx ack-seqno %#hx\n", __func__, -+ ecp->ifname, ecp->tx.ecpdu_received, ecp->tx.seqno, seqno); -+ if (ecp->tx.ecpdu_received) { -+ if (ecp->tx.seqno == seqno) -+ ecp->tx.ack_received = true; -+ } -+} -+ -+/* -+ * ecp22_rx_receiveframe - receive am ecp frame -+ * @ctx: rx callback context, struct ecp * in this case -+ * @ifindex: index of interface -+ * @buf: buffer which contains the frame just received -+ * @len: size of buffer (frame) -+ * -+ * no return value -+ * -+ * creates a local copy of the buffer and checks the header. keeps some -+ * statistics about ecp frames. Checks if it is a request or an ack frame and -+ * branches to ecp rx or ecp tx state machine. -+ */ -+static void ecp22_rx_receiveframe(void *ctx, int ifindex, const u8 *buf, -+ size_t len) -+{ -+ struct ecp22 *ecp = (struct ecp22 *)ctx; -+ struct port *port; -+ struct ecp22_hdr *ecp_hdr, ecphdr; -+ -+ LLDPAD_DBG("%s:%s ifindex:%d len:%zd state:%s ecpdu_received:%d\n", -+ __func__, ecp->ifname, ifindex, len, -+ ecp22_rx_states[ecp->rx.state], ecp->rx.ecpdu_received); -+ hexdump_frame(ecp->ifname, "frame-in", buf, len); -+ port = port_find_by_ifindex(get_ifidx(ecp->ifname)); -+ if (!port || ecp->rx.ecpdu_received) -+ /* Port not found or buffer not free */ -+ return; -+ -+ memcpy(ecp->rx.frame, buf, len); -+ ecp->rx.frame_len = len; -+ ecp->stats.statsFramesInTotal++; -+ -+ ecp_hdr = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -+ ecphdr.ver_op_sub = ntohs(ecp_hdr->ver_op_sub); -+ -+ /* Check for correct subtype and version number */ -+ if (ecp22_hdr_read_version(&ecphdr) != 1) { -+ LLDPAD_ERR("%s:%s ERROR unknown version %#02hx seqno %#hx\n", -+ __func__, ecp->ifname, ecphdr.ver_op_sub, -+ ntohs(ecp_hdr->seqno)); -+ return; -+ } -+ switch (ecp22_hdr_read_subtype(&ecphdr)) { -+ default: -+ LLDPAD_ERR("%s:%s ERROR unknown subtype %#02hx seqno %#hx\n", -+ __func__, ecp->ifname, ecphdr.ver_op_sub, -+ ntohs(ecp_hdr->seqno)); -+ return; -+ case ECP22_PECSP: -+ case ECP22_VDP: -+ /* Subtype ok, fall through intended */ -+ break; -+ } -+ -+ switch (ecp22_hdr_read_op(&ecphdr)) { -+ case ECP22_REQUEST: -+ LLDPAD_DBG("%s:%s received REQ frame seqno %#hx\n", __func__, -+ ecp->ifname, ntohs(ecp_hdr->seqno)); -+ ecp->rx.ecpdu_received = true; -+ ecp22_rx_run_sm(ecp); -+ break; -+ case ECP22_ACK: -+ LLDPAD_DBG("%s:%s received ACK frame seqno %#hx\n", __func__, -+ ecp->ifname, ntohs(ecp_hdr->seqno)); -+ ecp22_recack_frame(ecp, ntohs(ecp_hdr->seqno)); -+ break; -+ default: -+ LLDPAD_ERR("%s:%s ERROR unknown mode %#02hx seqno %#hx\n", -+ __func__, ecp->ifname, ecphdr.ver_op_sub, -+ ntohs(ecp_hdr->seqno)); -+ } -+} -+ -+/* -+ * ecp22_create - create data structure and initialize ecp protocol -+ * @ifname: interface for which the ecp protocol is initialized -+ * -+ * returns NULL on error and an pointer to the ecp22 structure on success. -+ * -+ * finds the port to the interface name, sets up the receive handle for -+ * incoming ecp frames and initializes the ecp rx and tx state machines. -+ * To be called when a successful exchange of EVB TLVs has been -+ * made and ECP protocols are supported by both sides. -+ */ -+static struct ecp22 *ecp22_create(char *ifname, struct ecp22_user_data *eud) -+{ -+ struct ecp22 *ecp; -+ -+ ecp = calloc(1, sizeof *ecp); -+ if (!ecp) { -+ LLDPAD_ERR("%s:%s unable to allocate ecp protocol\n", __func__, -+ ifname); -+ return NULL; -+ } -+ strncpy(ecp->ifname, ifname, sizeof ecp->ifname); -+ ecp->l2 = l2_packet_init(ecp->ifname, 0, ETH_P_ECP22, -+ ecp22_rx_receiveframe, ecp, 1); -+ -+ if (!ecp->l2) { -+ LLDPAD_ERR("%s:%s error open layer 2 ETH_P_ECP\n", __func__, -+ ifname); -+ free(ecp); -+ return NULL; -+ } -+ LIST_INSERT_HEAD(&eud->head, ecp, node); -+ LLDPAD_DBG("%s:%s create ecp data\n", __func__, ifname); -+ return ecp; -+} -+ -+/* -+ * ecp22_start - build up ecp structures for an interface -+ * @ifname: name of the interface -+ */ -+void ecp22_start(char *ifname) -+{ -+ struct ecp22_user_data *eud; -+ struct ecp22 *ecp; -+ -+ LLDPAD_DBG("%s:%s start ecp\n", __func__, ifname); -+ eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); -+ if (!eud) { -+ LLDPAD_DBG("%s:%s no ECP module\n", __func__, ifname); -+ return; -+ } -+ ecp = find_ecpdata(ifname, eud); -+ if (!ecp) -+ ecp = ecp22_create(ifname, eud); -+ ecp->max_retries = ECP22_MAX_RETRIES_DEFAULT; -+ ecp->max_rte = ECP22_ACK_TIMER_DEFAULT; -+ LIST_INIT(&ecp->inuse.head); -+ ecp->inuse.last = 0; -+ LIST_INIT(&ecp->isfree.head); -+ ecp->isfree.freecnt = 0; -+ ecp->rx.state = ECP22_RX_BEGIN; -+ ecp22_rx_run_sm(ecp); -+ ecp->tx.state = ECP22_TX_BEGIN; -+ ecp22_tx_run_sm(ecp); -+} -+ -+/* -+ * Remove the ecp_payload nodes -+ */ -+static void ecp22_removelist(ecp22_list *ptr) -+{ -+ struct ecp22_payload_node *np; -+ -+ while ((np = LIST_FIRST(ptr))) { -+ LIST_REMOVE(np, node); -+ np->ptlv = free_pkd_tlv(np->ptlv); -+ free(np); -+ } -+} -+ -+static void ecp22_remove(struct ecp22 *ecp) -+{ -+ LLDPAD_DBG("%s:%s remove ecp\n", __func__, ecp->ifname); -+ ecp22_removelist(&ecp->inuse.head); -+ ecp->inuse.last = 0; -+ ecp22_removelist(&ecp->isfree.head); -+ ecp->isfree.freecnt = 0; -+ LIST_REMOVE(ecp, node); -+ free(ecp); -+} -+ -+/* -+ * ecp22_stop - tear down ecp structures for a interface -+ * @ifname: name of the interface -+ * -+ * no return value -+ * -+ */ -+void ecp22_stop(char *ifname) -+{ -+ struct ecp22_user_data *eud; -+ struct ecp22 *ecp; -+ -+ LLDPAD_DBG("%s:%s stop ecp\n", __func__, ifname); -+ eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); -+ ecp = find_ecpdata(ifname, eud); -+ if (ecp) -+ ecp22_remove(ecp); -+} -+ -+/* -+ * Update data exchanged via EVB protocol. -+ * Returns true when data update succeeded. -+ */ -+static int ecp22_data_from_evb(char *ifname, struct evb22_to_ecp22 *ptr) -+{ -+ struct ecp22_user_data *eud; -+ struct ecp22 *ecp; -+ -+ eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); -+ ecp = find_ecpdata(ifname, eud); -+ if (ecp) { -+ ecp->max_rte = ptr->max_rte; -+ ecp->max_retries = ptr->max_retry; -+ LLDPAD_DBG("%s:%s max_rte:%d max_retries:%d\n", __func__, -+ ifname, ecp->max_rte, ecp->max_retries); -+ return 0; -+ } -+ return -ENOENT; -+} -+ -+/* -+ * Add ecp payload data at the end of the queue. -+ */ -+static void ecp22_add_payload(struct ecp22 *ecp, -+ struct ecp22_payload_node *elem) -+{ -+ if (LIST_EMPTY(&ecp->inuse.head)) -+ LIST_INSERT_HEAD(&ecp->inuse.head, elem, node); -+ else -+ LIST_INSERT_AFTER(ecp->inuse.last, elem, node); -+ ecp->inuse.last = elem; -+ if (!ecp->tx.ecpdu_received) /* Transmit buffer free */ -+ ecp22_tx_run_sm(ecp); -+} -+ -+/* -+ * Copy the payload data. -+ */ -+static struct packed_tlv *copy_ptlv(struct packed_tlv *from) -+{ -+ struct packed_tlv *ptlv = create_ptlv(); -+ -+ if (!ptlv) -+ return NULL; -+ ptlv->size = from->size; -+ ptlv->tlv = calloc(ptlv->size, sizeof(unsigned char)); -+ if (!ptlv->tlv) { -+ free_pkd_tlv(ptlv); -+ return NULL; -+ } -+ memcpy(ptlv->tlv, from->tlv, from->size); -+ return ptlv; -+} -+ -+/* -+ * Create a node for the ecp payload data. Get it from the free list if not -+ * empty. Otherwise allocate from heap. -+ */ -+static struct ecp22_payload_node *ecp22_getnode(struct ecp22_freelist *list) -+{ -+ struct ecp22_payload_node *elem = LIST_FIRST(&list->head); -+ -+ if (!elem) -+ elem = calloc(1, sizeof *elem); -+ else { -+ LIST_REMOVE(elem, node); -+ --list->freecnt; -+ } -+ return elem; -+} -+ -+/* -+ * Receive upper layer protocol data unit for transmit. -+ * Returns error if the request could not be queued for transmision. -+ */ -+static int ecp22_req2send(char *ifname, unsigned short subtype, -+ unsigned const char *mac, struct packed_tlv *du) -+{ -+ struct ecp22_user_data *eud; -+ struct ecp22 *ecp; -+ struct ecp22_payload_node *payda; -+ struct packed_tlv *ptlv = copy_ptlv(du); -+ int rc = 0; -+ -+ LLDPAD_DBG("%s:%s subtype:%d\n", __func__, ifname, subtype); -+ -+ eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); -+ ecp = find_ecpdata(ifname, eud); -+ if (!ecp) { -+ rc = -ENODEV; -+ goto out; -+ } -+ if (!ptlv) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ if (ptlv->size >= ECP22_MAXPAYLOAD_LEN) { -+ rc = -E2BIG; -+ goto out; -+ } -+ payda = ecp22_getnode(&ecp->isfree); -+ if (!payda) { -+ free_pkd_tlv(ptlv); -+ rc = -ENOMEM; -+ goto out; -+ } -+ payda->ptlv = ptlv; -+ payda->subtype = subtype; -+ memcpy(payda->mac, mac, sizeof payda->mac); -+ ecp22_add_payload(ecp, payda); -+out: -+ LLDPAD_DBG("%s:%s rc:%d\n", __func__, ifname, rc); -+ return rc; -+} -+ -+/* -+ * Payload data from VDP module. -+ * Returns true when data update succeeded. -+ */ -+static int data_from_vdp(char *ifname, struct ecp22_to_ulp *ptr) -+{ -+ struct packed_tlv d; -+ -+ d.size = ptr->len; -+ d.tlv = ptr->data; -+ return ecp22_req2send(ifname, ECP22_VDP, nearest_customer_bridge, &d); -+} -+ -+/* -+ * Handle notifications from other modules. Check if sender-id and data type -+ * indicator match. Return false when data could not be delivered. -+ */ -+static int ecp22_notify(int sender_id, char *ifname, void *data) -+{ -+ struct qbg22_imm *qbg = (struct qbg22_imm *)data; -+ -+ LLDPAD_DBG("%s:%s sender-id:%#x data_type:%d\n", __func__, ifname, -+ sender_id, qbg->data_type); -+ if (sender_id == LLDP_MOD_EVB22 && qbg->data_type == EVB22_TO_ECP22) -+ return ecp22_data_from_evb(ifname, &qbg->u.a); -+ if (sender_id == LLDP_MOD_VDP22 && qbg->data_type == VDP22_TO_ECP22) -+ return data_from_vdp(ifname, &qbg->u.c); -+ return 0; -+} -+ -+static const struct lldp_mod_ops ecp22_ops = { -+ .lldp_mod_register = ecp22_register, -+ .lldp_mod_unregister = ecp22_unregister, -+ .lldp_mod_notify = ecp22_notify -+}; -+ -+/* -+ * ecp22_register - register ecp module to lldpad -+ * -+ * returns lldp_module struct on success, NULL on error -+ * -+ * allocates a module structure with ecp module information and returns it -+ * to lldpad. -+ */ -+struct lldp_module *ecp22_register(void) -+{ -+ struct lldp_module *mod; -+ struct ecp22_user_data *eud; -+ -+ mod = calloc(1, sizeof *mod); -+ if (!mod) { -+ LLDPAD_ERR("%s:can not allocate ecp module data\n", __func__); -+ return NULL; -+ } -+ eud = calloc(1, sizeof(struct ecp22_user_data)); -+ if (!eud) { -+ free(mod); -+ LLDPAD_ERR("%s:can not allocate ecp user data\n", __func__); -+ return NULL; -+ } -+ LIST_INIT(&eud->head); -+ mod->id = LLDP_MOD_ECP22; -+ mod->ops = &ecp22_ops; -+ mod->data = eud; -+ LLDPAD_DBG("%s: done\n", __func__); -+ return mod; -+} -+ -+/* -+ * ecp22_free_data - frees up ecp data chain -+ */ -+static void ecp22_free_data(struct ecp22_user_data *ud) -+{ -+ struct ecp22 *ecp; -+ -+ if (ud) { -+ while (!LIST_EMPTY(&ud->head)) { -+ ecp = LIST_FIRST(&ud->head); -+ ecp22_remove(ecp); -+ } -+ } -+} -+ -+/* -+ * ecp22_unregister - unregister ecp module from lldpad -+ * -+ * no return value -+ * -+ * frees ecp module structure and user data. -+ */ -+void ecp22_unregister(struct lldp_module *mod) -+{ -+ if (mod->data) { -+ ecp22_free_data((struct ecp22_user_data *)mod->data); -+ free(mod->data); -+ } -+ free(mod); -+ LLDPAD_DBG("%s: done\n", __func__); -+} -diff --git a/qbg/lldp_ecp22.c b/qbg/lldp_ecp22.c -deleted file mode 100644 -index 3341cc6..0000000 ---- a/qbg/lldp_ecp22.c -+++ /dev/null -@@ -1,1060 +0,0 @@ --/****************************************************************************** -- -- Implementation of ECP according to 802.1Qbg -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Jens Osterkamp -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --#include --#include --#include --#include -- --#include "eloop.h" --#include "lldp_ecp22.h" --#include "messages.h" --#include "lldp_qbg_utils.h" --#include "lldp/l2_packet.h" --#include "lldp_tlv.h" -- --#define ECP22_MAX_RETRIES_DEFAULT (3) /* Default # of max retries */ --#define ECP22_ACK_TIMER_STOPPED (-1) --/* -- * Defaults to 2ms wait time for acknowledgement packet reception. -- */ --#define ECP22_ACK_TIMER_DEFAULT (8) -- --static void ecp22_tx_run_sm(struct ecp22 *); -- --static const char *const ecp22_rx_states[] = { /* Receive states verbatim */ -- "ECP22_RX_BEGIN", -- "ECP22_RX_WAIT", -- "ECP22_RX_WAIT2", -- "ECP22_RX_FIRST", -- "ECP22_RX_REC_ECPDU", -- "ECP22_RX_NEW_ECPDU", -- "ECP22_RX_SEND_ACK" --}; -- --static const char *const ecp22_tx_states[] = { /* Transmit states verbatim */ -- "ECP22_TX_BEGIN", -- "ECP22_TX_INIT", -- "ECP22_TX_TXMIT_ECPDU", -- "ECP22_TX_WAIT_FORREQ", -- "ECP22_TX_WAIT_ONDATA", -- "ECP22_TX_ERROR" --}; -- --/* -- * Increment sequence number. Do not return zero as sequence number. -- */ --static unsigned short inc_seqno(unsigned short x) --{ -- ++x; -- if (!x) /* Wrapped */ -- ++x; -- return x; --} -- --/* -- * Find the ecp data associated with an interface. -- * Return pointer or NULL if not found. -- */ --static struct ecp22 *find_ecpdata(char *ifname, struct ecp22_user_data *eud) --{ -- struct ecp22 *ecp = 0; -- -- if (eud) { -- LIST_FOREACH(ecp, &eud->head, node) -- if (!strncmp(ifname, ecp->ifname, IFNAMSIZ)) -- break; -- } -- return ecp; --} -- --/* -- * ecp22_txframe - transmit ecp frame -- * @ecp: pointer to currently used ecp data structure -- * -- * returns the number of characters sent on success, -1 on failure -- * -- * sends out the frame stored in the frame structure using l2_packet_send. -- */ --static int ecp22_txframe(struct ecp22 *ecp, char *txt, unsigned char *dst, -- unsigned char *ack, size_t len) --{ -- hexdump_frame(ecp->ifname, txt, ack, len); -- return l2_packet_send(ecp->l2, dst, htons(ETH_P_ECP22), ack, len); --} -- --/* -- * Append some data at the end of the transmit data buffer. Make sure the -- * End TLV always fits into the buffer. -- */ --static unsigned char end_tlv[2] = { 0x0, 0x0 }; /* END TLV */ -- --static void ecp22_append(u8 *buffer, u32 *pos, void *data, u32 len) --{ -- if (*pos + len > ETH_FRAME_LEN - sizeof end_tlv) -- return; -- memcpy(buffer + *pos, data, len); -- *pos += len; --} -- --/* -- * Return a payload node to the freelist. -- */ --void ecp22_putnode(struct ecp22_freelist *list, struct ecp22_payload_node *elm) --{ -- elm->ptlv = free_pkd_tlv(elm->ptlv); -- if (list->freecnt > ecp22_maxpayload) -- free(elm); -- else { -- ++list->freecnt; -- LIST_INSERT_HEAD(&list->head, elm, node); -- } --} -- --/* -- * ecp22_build_ecpdu - create an ecp protocol data unit -- * @ecp: pointer to currently used ecp data structure -- * -- * returns true on success, false on failure -- * -- * creates the frame header with the ports mac address, the ecp header with REQ -- * plus a packed TLVs created taken from the send queue. -- */ --static bool ecp22_build_ecpdu(struct ecp22 *ecp) --{ -- struct l2_ethhdr eth; -- struct ecp22_hdr ecph; -- u32 fb_offset = 0; -- struct packed_tlv *ptlv; -- struct ecp22_payload_node *p = LIST_FIRST(&ecp->inuse.head); -- -- if (!p) -- return false; -- ecp->tx.ecpdu_received = true; /* Txmit buffer in use */ -- memcpy(eth.h_dest, p->mac, ETH_ALEN); -- l2_packet_get_own_src_addr(ecp->l2, eth.h_source); -- eth.h_proto = htons(ETH_P_ECP22); -- memset(ecp->tx.frame, 0, sizeof ecp->tx.frame); -- ecp22_append(ecp->tx.frame, &fb_offset, (void *)ð, sizeof eth); -- -- ecp22_hdr_set_version(&ecph, 1); -- ecp22_hdr_set_op(&ecph, ECP22_REQUEST); -- ecp22_hdr_set_subtype(&ecph, ECP22_VDP); -- ecph.ver_op_sub = htons(ecph.ver_op_sub); -- ecph.seqno = htons(ecp->tx.seqno); -- ecp22_append(ecp->tx.frame, &fb_offset, (void *)&ecph, sizeof ecph); -- -- ptlv = p->ptlv; -- ecp22_append(ecp->tx.frame, &fb_offset, ptlv->tlv, ptlv->size); -- ecp22_append(ecp->tx.frame, &fb_offset, end_tlv, sizeof end_tlv); -- ecp->tx.frame_len = MAX(fb_offset, (unsigned)ETH_ZLEN); -- LIST_REMOVE(p, node); -- ecp22_putnode(&ecp->isfree, p); -- LLDPAD_DBG("%s:%s seqno %#hx frame_len %#hx\n", __func__, -- ecp->ifname, ecp->tx.seqno, ecp->tx.frame_len); -- return true; --} -- --/* -- * Execute transmit state transmitECPDU. -- */ --static void ecp22_es_waitforreq(struct ecp22 *ecp) --{ -- ecp->tx.retries = 0; -- ecp->tx.ack_received = false; -- ecp->tx.ecpdu_received = false; -- ecp->tx.seqno = inc_seqno(ecp->tx.seqno); -- LLDPAD_DBG("%s:%s seqno %#hx\n", __func__, ecp->ifname, ecp->tx.seqno); --} -- --/* -- * Execute transmit state countErrors. -- */ --static void ecp22_es_counterror(struct ecp22 *ecp) --{ -- ++ecp->tx.errors; -- LLDPAD_DBG("%s:%s errors %lu\n", __func__, ecp->ifname, -- ecp->tx.errors); --} -- --/* -- * Execute transmit state initTransmit. -- */ --static void ecp22_es_inittransmit(struct ecp22 *ecp) --{ -- ecp->tx.errors = 0; -- ecp->tx.seqno = 0; --} -- --/* -- * Return RTE value in milliseconds. -- */ --static int rtevalue(unsigned char rte) --{ -- return (1 << rte) * 10; --} -- --/* -- * ecp22_ack_timeout_handler - handles the ack timer expiry -- * @eloop_data: data structure of event loop -- * @user_ctx: user context, vdp_data here -- * -- * no return value -- * -- * called when the ECP timer has expired. Calls the ECP station state machine. -- */ --static void ecp22_ack_timeout_handler(UNUSED void *eloop_data, void *user_ctx) --{ -- struct ecp22 *ecp = (struct ecp22 *)user_ctx; -- -- LLDPAD_DBG("%s:%s retries:%d\n", __func__, -- ecp->ifname, ecp->tx.retries); -- ecp22_tx_run_sm(ecp); --} -- --/* -- * ecp22_tx_start_acktimer - starts the ECP ack timer -- * @ecp: pointer to currently used ecp data structure -- * -- * returns 0 on success, -1 on error -- * -- * starts the ack timer when a frame has been sent out. -- */ --static void ecp22_tx_start_acktimer(struct ecp22 *ecp) --{ -- unsigned long ack_sec = rtevalue(ecp->max_rte) / 1000000; -- unsigned long ack_usec = rtevalue(ecp->max_rte) % 1000000; -- -- LLDPAD_DBG("%s:%s [%ld.%06ld]\n", __func__, ecp->ifname, ack_sec, -- ack_usec); -- eloop_register_timeout(ack_sec, ack_usec, ecp22_ack_timeout_handler, -- 0, (void *)ecp); --} -- --/* -- * ecp22_tx_change_state - changes the ecp tx sm state -- * @ecp: pointer to currently used ecp data structure -- * @newstate: new state for the sm -- * -- * no return value -- * -- * checks state transistion for consistency and finally changes the state of -- * the profile. -- */ --static void ecp22_tx_change_state(struct ecp22 *ecp, unsigned char newstate) --{ -- switch (newstate) { -- case ECP22_TX_BEGIN: -- break; -- case ECP22_TX_INIT: -- assert(ecp->tx.state == ECP22_TX_BEGIN); -- break; -- case ECP22_TX_WAIT_FORREQ: -- assert(ecp->tx.state == ECP22_TX_INIT || -- ecp->tx.state == ECP22_TX_ERROR || -- ecp->tx.state == ECP22_TX_TXMIT_ECPDU); -- break; -- case ECP22_TX_WAIT_ONDATA: -- assert(ecp->tx.state == ECP22_TX_WAIT_FORREQ); -- break; -- case ECP22_TX_TXMIT_ECPDU: -- assert(ecp->tx.state == ECP22_TX_WAIT_ONDATA); -- break; -- case ECP22_TX_ERROR: -- assert(ecp->tx.state == ECP22_TX_TXMIT_ECPDU); -- break; -- default: -- LLDPAD_ERR("%s: ECP TX state machine invalid state %d\n", -- ecp->ifname, newstate); -- } -- LLDPAD_DBG("%s:%s state change %s -> %s\n", __func__, -- ecp->ifname, ecp22_tx_states[ecp->tx.state], -- ecp22_tx_states[newstate]); -- ecp->tx.state = newstate; --} -- --/* -- * Send the payload data. -- */ --static int ecp22_es_txmit(struct ecp22 *ecp) --{ -- int rc = 0; -- -- ++ecp->tx.retries; -- ecp22_txframe(ecp, "ecp-out", ecp->tx.frame, ecp->tx.frame, -- ecp->tx.frame_len); -- ecp22_tx_start_acktimer(ecp); -- return rc; --} -- --/* -- * ecp22_set_tx_state - sets the ecp tx state machine state -- * @ecp: pointer to currently used ecp data structure -- * -- * returns true or false -- * -- * switches the state machine to the next state depending on the input -- * variables. returns true or false depending on wether the state machine -- * can be run again with the new state or can stop at the current state. -- */ --static bool ecp22_set_tx_state(struct ecp22 *ecp) --{ -- struct port *port = port_find_by_name(ecp->ifname); -- -- if (!port) { -- LLDPAD_ERR("%s:%s port not found\n", __func__, ecp->ifname); -- return 0; -- } -- if ((port->portEnabled == false) && (port->prevPortEnabled == true)) { -- LLDPAD_ERR("%s:%s port was disabled\n", __func__, ecp->ifname); -- ecp22_tx_change_state(ecp, ECP22_TX_BEGIN); -- } -- port->prevPortEnabled = port->portEnabled; -- -- switch (ecp->tx.state) { -- case ECP22_TX_BEGIN: -- ecp22_tx_change_state(ecp, ECP22_TX_INIT); -- return true; -- case ECP22_TX_INIT: -- ecp22_tx_change_state(ecp, ECP22_TX_WAIT_FORREQ); -- return true; -- case ECP22_TX_WAIT_FORREQ: -- ecp22_tx_change_state(ecp, ECP22_TX_WAIT_ONDATA); -- return true; -- case ECP22_TX_WAIT_ONDATA: -- if (LIST_FIRST(&ecp->inuse.head)) { /* Data to send */ -- ecp22_build_ecpdu(ecp); -- ecp22_tx_change_state(ecp, ECP22_TX_TXMIT_ECPDU); -- return true; -- } -- return false; -- case ECP22_TX_TXMIT_ECPDU: -- if (ecp->tx.ack_received) { -- ecp22_tx_change_state(ecp, ECP22_TX_WAIT_FORREQ); -- return true; -- } -- if (ecp->tx.retries > ecp->max_retries) { -- ecp22_tx_change_state(ecp, ECP22_TX_ERROR); -- return true; -- } -- return false; -- case ECP22_TX_ERROR: -- ecp22_tx_change_state(ecp, ECP22_TX_WAIT_FORREQ); -- return true; -- default: -- LLDPAD_ERR("%s: ECP TX state machine in invalid state %d\n", -- ecp->ifname, ecp->tx.state); -- return false; -- } --} -- --/* -- * ecp22_tx_run_sm - state machine for ecp transmit -- * @ecp: pointer to currently used ecp data structure -- * -- * no return value -- */ --static void ecp22_tx_run_sm(struct ecp22 *ecp) --{ -- ecp22_set_tx_state(ecp); -- do { -- LLDPAD_DBG("%s:%s state %s\n", __func__, -- ecp->ifname, ecp22_tx_states[ecp->tx.state]); -- -- switch (ecp->tx.state) { -- case ECP22_TX_BEGIN: -- break; -- case ECP22_TX_INIT: -- ecp22_es_inittransmit(ecp); -- break; -- case ECP22_TX_WAIT_FORREQ: -- ecp22_es_waitforreq(ecp); -- break; -- case ECP22_TX_WAIT_ONDATA: -- break; -- case ECP22_TX_TXMIT_ECPDU: -- ecp22_es_txmit(ecp); -- break; -- case ECP22_TX_ERROR: -- ecp22_es_counterror(ecp); -- break; -- } -- } while (ecp22_set_tx_state(ecp) == true); --} -- --/* -- * ecp22_rx_change_state - changes the ecp rx sm state -- * @ecp: pointer to currently used ecp data structure -- * @newstate: new state for the sm -- * -- * no return value -- * -- * checks state transistion for consistency and finally changes the state of -- * the ecp receive buffer. -- */ --static void ecp22_rx_change_state(struct ecp22 *ecp, u8 newstate) --{ -- switch (newstate) { -- case ECP22_RX_BEGIN: -- break; -- case ECP22_RX_WAIT: -- assert(ecp->rx.state == ECP22_RX_BEGIN); -- break; -- case ECP22_RX_FIRST: -- assert(ecp->rx.state == ECP22_RX_WAIT); -- break; -- case ECP22_RX_REC_ECPDU: -- assert((ecp->rx.state == ECP22_RX_FIRST) || -- (ecp->rx.state == ECP22_RX_WAIT2)); -- break; -- case ECP22_RX_NEW_ECPDU: -- assert(ecp->rx.state == ECP22_RX_REC_ECPDU); -- break; -- case ECP22_RX_SEND_ACK: -- assert((ecp->rx.state == ECP22_RX_REC_ECPDU) || -- (ecp->rx.state == ECP22_RX_NEW_ECPDU)); -- break; -- case ECP22_RX_WAIT2: -- assert(ecp->rx.state == ECP22_RX_SEND_ACK); -- break; -- default: -- LLDPAD_ERR("%s:%s LLDP RX state machine invalid state %d\n", -- __func__, ecp->ifname, newstate); -- } -- LLDPAD_DBG("%s:%s state change %s -> %s\n", __func__, -- ecp->ifname, ecp22_rx_states[ecp->rx.state], -- ecp22_rx_states[newstate]); -- ecp->rx.state = newstate; --} -- --/* -- * Execute action in state sendack. Construct and send an acknowledgement -- * for the received ECP packet. -- */ --static void ecp22_es_send_ack(struct ecp22 *ecp) --{ -- unsigned char ack_frame[ETH_HLEN + sizeof(struct ecp22_hdr)]; -- struct ethhdr *ethdst = (struct ethhdr *)ack_frame; -- struct ecp22_hdr *ecpdst = (struct ecp22_hdr *)&ack_frame[ETH_HLEN]; -- struct ethhdr *ethsrc = (struct ethhdr *)ecp->rx.frame; -- struct ecp22_hdr *ecpsrc = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -- struct ecp22_hdr ack; -- -- LLDPAD_DBG("%s:%s state %s seqno %#hx\n", __func__, ecp->ifname, -- ecp22_rx_states[ecp->rx.state], ecp->rx.seqno); -- memcpy(ethdst->h_dest, nearest_customer_bridge, ETH_ALEN); -- l2_packet_get_own_src_addr(ecp->l2, (u8 *)ðdst->h_source); -- ethdst->h_proto = ethsrc->h_proto; -- /* Set ECP header */ -- ack.ver_op_sub = ntohs(ecpsrc->ver_op_sub); -- ecp22_hdr_set_op(&ack, ECP22_ACK); -- ecpdst->ver_op_sub = htons(ack.ver_op_sub); -- ecpdst->seqno = htons(ecp->rx.seqno); -- ecp22_txframe(ecp, "ecp-ack", ethsrc->h_source, ack_frame, -- sizeof ack_frame); --} -- -- --/* -- * Notify upper layer protocol function of ECP payload data just received. -- */ --static void ecp22_to_ulp(unsigned short ulp, struct ecp22 *ecp) --{ -- size_t offset = ETH_HLEN + sizeof(struct ecp22_hdr); -- struct qbg22_imm to_ulp; -- -- to_ulp.data_type = ECP22_TO_ULP; -- to_ulp.u.c.len = ecp->rx.frame_len - offset; -- to_ulp.u.c.data = &ecp->rx.frame[offset]; -- if (ulp == ECP22_VDP) -- modules_notify(LLDP_MOD_VDP22, LLDP_MOD_ECP22, ecp->ifname, -- &to_ulp); -- else -- LLDPAD_INFO("%s:%s ECP subtype %d not yet implemented\n", -- __func__, ecp->ifname, ulp); --} -- --/* -- * Execute action in state newECPDU. -- * Notify upper layer protocol of new data. -- */ --static void ecp22_es_new_ecpdu(struct ecp22 *ecp) --{ -- struct ecp22_hdr *hdr = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -- struct ecp22_hdr ecphdr; -- unsigned short ulp; -- -- ecphdr.ver_op_sub = ntohs(hdr->ver_op_sub); -- ulp = ecp22_hdr_read_subtype(&ecphdr); -- LLDPAD_DBG("%s:%s state %s notify ULP %d seqno %#hx\n", __func__, -- ecp->ifname, ecp22_rx_states[ecp->rx.state], -- ulp, ecp->rx.seqno); -- ecp->rx.last_seqno = ecp->rx.seqno; -- ecp22_to_ulp(ulp, ecp); --} -- --/* -- * Execute action in state receiveECPDU. -- */ --static void ecp22_es_rec_ecpdu(struct ecp22 *ecp) --{ -- struct ecp22_hdr *hdr = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -- -- ecp->rx.seqno = ntohs(hdr->seqno); -- LLDPAD_DBG("%s:%s state %s seqno %#hx\n", __func__, ecp->ifname, -- ecp22_rx_states[ecp->rx.state], ecp->rx.seqno); --} -- --/* -- * Execute action in state receiveFirst. -- */ --static void ecp22_es_first(struct ecp22 *ecp) --{ -- struct ecp22_hdr *hdr = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -- -- LLDPAD_DBG("%s:%s state %s\n", __func__, ecp->ifname, -- ecp22_rx_states[ecp->rx.state]); -- ecp->rx.last_seqno = ntohs(hdr->seqno) - 1; --} -- --/* -- * Execute action in state receiveWait. -- */ --static void ecp22_es_wait(struct ecp22 *ecp) --{ -- LLDPAD_DBG("%s:%s state %s\n", __func__, ecp->ifname, -- ecp22_rx_states[ecp->rx.state]); -- ecp->rx.ecpdu_received = false; --} -- --/* -- * ecp22_set_rx_state - sets the ecp receive state machine state -- * @ecp: pointer to currently used ecp data structure -- * -- * returns true or false -- * -- * switches the state machine to the next state depending on the input -- * variables. Returns true or false depending on wether the state machine -- * can be run again with the new state or can stop at the current state. -- */ --static bool ecp22_set_rx_state(struct ecp22 *ecp) --{ -- struct port *port = port_find_by_name(ecp->ifname); -- -- if (!port) -- return false; -- -- LLDPAD_DBG("%s:%s state %s\n", __func__, ecp->ifname, -- ecp22_rx_states[ecp->rx.state]); -- if (port->portEnabled == false) -- ecp22_rx_change_state(ecp, ECP22_RX_BEGIN); -- switch (ecp->rx.state) { -- case ECP22_RX_BEGIN: -- ecp22_rx_change_state(ecp, ECP22_RX_WAIT); -- return false; -- case ECP22_RX_WAIT: -- if (ecp->rx.ecpdu_received) { -- ecp22_rx_change_state(ecp, ECP22_RX_FIRST); -- return true; -- } -- return false; -- case ECP22_RX_WAIT2: -- if (ecp->rx.ecpdu_received) { -- ecp22_rx_change_state(ecp, ECP22_RX_REC_ECPDU); -- return true; -- } -- return false; -- case ECP22_RX_FIRST: -- ecp22_rx_change_state(ecp, ECP22_RX_REC_ECPDU); -- return true; -- case ECP22_RX_REC_ECPDU: -- if (ecp->rx.seqno == ecp->rx.last_seqno) -- ecp22_rx_change_state(ecp, ECP22_RX_SEND_ACK); -- else -- ecp22_rx_change_state(ecp, ECP22_RX_NEW_ECPDU); -- return true; -- case ECP22_RX_NEW_ECPDU: -- ecp22_rx_change_state(ecp, ECP22_RX_SEND_ACK); -- return true; -- case ECP22_RX_SEND_ACK: -- ecp22_rx_change_state(ecp, ECP22_RX_WAIT2); -- return true; -- default: -- LLDPAD_DBG("%s:%s ECP RX state machine in invalid state %d\n", -- __func__, ecp->ifname, ecp->rx.state); -- return false; -- } --} -- --/* -- * ecp22_rx_run_sm - state machine for ecp receive protocol -- * @ecp: pointer to currently used ecp data structure -- * -- * no return value -- * -- * runs the state machine for ecp22 receive function. -- */ --static void ecp22_rx_run_sm(struct ecp22 *ecp) --{ -- ecp22_set_rx_state(ecp); -- do { -- switch (ecp->rx.state) { -- case ECP22_RX_WAIT: -- case ECP22_RX_WAIT2: -- ecp22_es_wait(ecp); -- break; -- case ECP22_RX_FIRST: -- ecp22_es_first(ecp); -- break; -- case ECP22_RX_REC_ECPDU: -- ecp22_es_rec_ecpdu(ecp); -- break; -- case ECP22_RX_NEW_ECPDU: -- ecp22_es_new_ecpdu(ecp); -- break; -- case ECP22_RX_SEND_ACK: -- ecp22_es_send_ack(ecp); -- break; -- default: -- LLDPAD_DBG("%s:%s ECP RX state machine in invalid " -- "state %d\n", __func__, ecp->ifname, -- ecp->rx.state); -- } -- } while (ecp22_set_rx_state(ecp) == true); --} -- --/* -- * Received an aknowledgement frame. -- * Check if we have a transmit pending and the ack'ed packet number matches -- * the send packet. -- */ --static void ecp22_recack_frame(struct ecp22 *ecp, unsigned short seqno) --{ -- LLDPAD_DBG("%s:%s txmit:%d seqno %#hx ack-seqno %#hx\n", __func__, -- ecp->ifname, ecp->tx.ecpdu_received, ecp->tx.seqno, seqno); -- if (ecp->tx.ecpdu_received) { -- if (ecp->tx.seqno == seqno) -- ecp->tx.ack_received = true; -- } --} -- --/* -- * ecp22_rx_receiveframe - receive am ecp frame -- * @ctx: rx callback context, struct ecp * in this case -- * @ifindex: index of interface -- * @buf: buffer which contains the frame just received -- * @len: size of buffer (frame) -- * -- * no return value -- * -- * creates a local copy of the buffer and checks the header. keeps some -- * statistics about ecp frames. Checks if it is a request or an ack frame and -- * branches to ecp rx or ecp tx state machine. -- */ --static void ecp22_rx_receiveframe(void *ctx, int ifindex, const u8 *buf, -- size_t len) --{ -- struct ecp22 *ecp = (struct ecp22 *)ctx; -- struct port *port; -- struct ecp22_hdr *ecp_hdr, ecphdr; -- -- LLDPAD_DBG("%s:%s ifindex:%d len:%zd state:%s ecpdu_received:%d\n", -- __func__, ecp->ifname, ifindex, len, -- ecp22_rx_states[ecp->rx.state], ecp->rx.ecpdu_received); -- hexdump_frame(ecp->ifname, "frame-in", buf, len); -- port = port_find_by_name(ecp->ifname); -- if (!port || ecp->rx.ecpdu_received) -- /* Port not found or buffer not free */ -- return; -- -- memcpy(ecp->rx.frame, buf, len); -- ecp->rx.frame_len = len; -- ecp->stats.statsFramesInTotal++; -- -- ecp_hdr = (struct ecp22_hdr *)&ecp->rx.frame[ETH_HLEN]; -- ecphdr.ver_op_sub = ntohs(ecp_hdr->ver_op_sub); -- -- /* Check for correct subtype and version number */ -- if (ecp22_hdr_read_version(&ecphdr) != 1) { -- LLDPAD_ERR("%s:%s ERROR unknown version %#02hx seqno %#hx\n", -- __func__, ecp->ifname, ecphdr.ver_op_sub, -- ntohs(ecp_hdr->seqno)); -- return; -- } -- switch (ecp22_hdr_read_subtype(&ecphdr)) { -- default: -- LLDPAD_ERR("%s:%s ERROR unknown subtype %#02hx seqno %#hx\n", -- __func__, ecp->ifname, ecphdr.ver_op_sub, -- ntohs(ecp_hdr->seqno)); -- return; -- case ECP22_PECSP: -- case ECP22_VDP: -- /* Subtype ok, fall through intended */ -- break; -- } -- -- switch (ecp22_hdr_read_op(&ecphdr)) { -- case ECP22_REQUEST: -- LLDPAD_DBG("%s:%s received REQ frame seqno %#hx\n", __func__, -- ecp->ifname, ntohs(ecp_hdr->seqno)); -- ecp->rx.ecpdu_received = true; -- ecp22_rx_run_sm(ecp); -- break; -- case ECP22_ACK: -- LLDPAD_DBG("%s:%s received ACK frame seqno %#hx\n", __func__, -- ecp->ifname, ntohs(ecp_hdr->seqno)); -- ecp22_recack_frame(ecp, ntohs(ecp_hdr->seqno)); -- break; -- default: -- LLDPAD_ERR("%s:%s ERROR unknown mode %#02hx seqno %#hx\n", -- __func__, ecp->ifname, ecphdr.ver_op_sub, -- ntohs(ecp_hdr->seqno)); -- } --} -- --/* -- * ecp22_create - create data structure and initialize ecp protocol -- * @ifname: interface for which the ecp protocol is initialized -- * -- * returns NULL on error and an pointer to the ecp22 structure on success. -- * -- * finds the port to the interface name, sets up the receive handle for -- * incoming ecp frames and initializes the ecp rx and tx state machines. -- * To be called when a successful exchange of EVB TLVs has been -- * made and ECP protocols are supported by both sides. -- */ --static struct ecp22 *ecp22_create(char *ifname, struct ecp22_user_data *eud) --{ -- struct ecp22 *ecp; -- -- ecp = calloc(1, sizeof *ecp); -- if (!ecp) { -- LLDPAD_ERR("%s:%s unable to allocate ecp protocol\n", __func__, -- ifname); -- return NULL; -- } -- strncpy(ecp->ifname, ifname, sizeof ecp->ifname); -- ecp->l2 = l2_packet_init(ecp->ifname, 0, ETH_P_ECP22, -- ecp22_rx_receiveframe, ecp, 1); -- -- if (!ecp->l2) { -- LLDPAD_ERR("%s:%s error open layer 2 ETH_P_ECP\n", __func__, -- ifname); -- free(ecp); -- return NULL; -- } -- LIST_INSERT_HEAD(&eud->head, ecp, node); -- LLDPAD_DBG("%s:%s create ecp data\n", __func__, ifname); -- return ecp; --} -- --/* -- * ecp22_start - build up ecp structures for an interface -- * @ifname: name of the interface -- */ --void ecp22_start(char *ifname) --{ -- struct ecp22_user_data *eud; -- struct ecp22 *ecp; -- -- LLDPAD_DBG("%s:%s start ecp\n", __func__, ifname); -- eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); -- if (!eud) { -- LLDPAD_DBG("%s:%s no ECP module\n", __func__, ifname); -- return; -- } -- ecp = find_ecpdata(ifname, eud); -- if (!ecp) -- ecp = ecp22_create(ifname, eud); -- ecp->max_retries = ECP22_MAX_RETRIES_DEFAULT; -- ecp->max_rte = ECP22_ACK_TIMER_DEFAULT; -- LIST_INIT(&ecp->inuse.head); -- ecp->inuse.last = 0; -- LIST_INIT(&ecp->isfree.head); -- ecp->isfree.freecnt = 0; -- ecp->rx.state = ECP22_RX_BEGIN; -- ecp22_rx_run_sm(ecp); -- ecp->tx.state = ECP22_TX_BEGIN; -- ecp22_tx_run_sm(ecp); --} -- --/* -- * Remove the ecp_payload nodes -- */ --static void ecp22_removelist(ecp22_list *ptr) --{ -- struct ecp22_payload_node *np; -- -- while ((np = LIST_FIRST(ptr))) { -- LIST_REMOVE(np, node); -- np->ptlv = free_pkd_tlv(np->ptlv); -- free(np); -- } --} -- --static void ecp22_remove(struct ecp22 *ecp) --{ -- LLDPAD_DBG("%s:%s remove ecp\n", __func__, ecp->ifname); -- ecp22_removelist(&ecp->inuse.head); -- ecp->inuse.last = 0; -- ecp22_removelist(&ecp->isfree.head); -- ecp->isfree.freecnt = 0; -- LIST_REMOVE(ecp, node); -- free(ecp); --} -- --/* -- * ecp22_stop - tear down ecp structures for a interface -- * @ifname: name of the interface -- * -- * no return value -- * -- */ --void ecp22_stop(char *ifname) --{ -- struct ecp22_user_data *eud; -- struct ecp22 *ecp; -- -- LLDPAD_DBG("%s:%s stop ecp\n", __func__, ifname); -- eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); -- ecp = find_ecpdata(ifname, eud); -- if (ecp) -- ecp22_remove(ecp); --} -- --/* -- * Update data exchanged via EVB protocol. -- * Returns true when data update succeeded. -- */ --static int data_from_evb(char *ifname, struct evb22_to_ecp22 *ptr) --{ -- struct ecp22_user_data *eud; -- struct ecp22 *ecp; -- -- eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); -- ecp = find_ecpdata(ifname, eud); -- if (ecp) { -- ecp->max_rte = ptr->max_rte; -- ecp->max_retries = ptr->max_retry; -- return 0; -- } -- return -ENOENT; --} -- --/* -- * Add ecp payload data at the end of the queue. -- */ --static void ecp22_add_payload(struct ecp22 *ecp, -- struct ecp22_payload_node *elem) --{ -- if (LIST_EMPTY(&ecp->inuse.head)) -- LIST_INSERT_HEAD(&ecp->inuse.head, elem, node); -- else -- LIST_INSERT_AFTER(ecp->inuse.last, elem, node); -- ecp->inuse.last = elem; -- if (!ecp->tx.ecpdu_received) /* Transmit buffer free */ -- ecp22_tx_run_sm(ecp); --} -- --/* -- * Copy the payload data. -- */ --static struct packed_tlv *copy_ptlv(struct packed_tlv *from) --{ -- struct packed_tlv *ptlv = create_ptlv(); -- -- if (!ptlv) -- return NULL; -- ptlv->size = from->size; -- ptlv->tlv = calloc(ptlv->size, sizeof(unsigned char)); -- if (!ptlv->tlv) { -- free_pkd_tlv(ptlv); -- return NULL; -- } -- memcpy(ptlv->tlv, from->tlv, from->size); -- return ptlv; --} -- --/* -- * Create a node for the ecp payload data. Get it from the free list if not -- * empty. Otherwise allocate from heap. -- */ --static struct ecp22_payload_node *ecp22_getnode(struct ecp22_freelist *list) --{ -- struct ecp22_payload_node *elem = LIST_FIRST(&list->head); -- -- if (!elem) -- elem = calloc(1, sizeof *elem); -- else { -- LIST_REMOVE(elem, node); -- --list->freecnt; -- } -- return elem; --} -- --/* -- * Receive upper layer protocol data unit for transmit. -- * Returns error if the request could not be queued for transmision. -- */ --static int ecp22_req2send(char *ifname, unsigned short subtype, -- unsigned const char *mac, struct packed_tlv *du) --{ -- struct ecp22_user_data *eud; -- struct ecp22 *ecp; -- struct ecp22_payload_node *payda; -- struct packed_tlv *ptlv = copy_ptlv(du); -- int rc = 0; -- -- LLDPAD_DBG("%s:%s subtype:%d\n", __func__, ifname, subtype); -- -- eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); -- ecp = find_ecpdata(ifname, eud); -- if (!ecp) { -- rc = -ENODEV; -- goto out; -- } -- if (!ptlv) { -- rc = -ENOMEM; -- goto out; -- } -- if (ptlv->size >= ECP22_MAXPAYLOAD_LEN) { -- rc = -E2BIG; -- goto out; -- } -- payda = ecp22_getnode(&ecp->isfree); -- if (!payda) { -- free_pkd_tlv(ptlv); -- rc = -ENOMEM; -- goto out; -- } -- payda->ptlv = ptlv; -- payda->subtype = subtype; -- memcpy(payda->mac, mac, sizeof payda->mac); -- ecp22_add_payload(ecp, payda); --out: -- LLDPAD_DBG("%s:%s rc:%d\n", __func__, ifname, rc); -- return rc; --} -- --/* -- * Payload data from VDP module. -- * Returns true when data update succeeded. -- */ --static int data_from_vdp(char *ifname, struct ecp22_to_ulp *ptr) --{ -- struct packed_tlv d; -- -- d.size = ptr->len; -- d.tlv = ptr->data; -- return ecp22_req2send(ifname, ECP22_VDP, nearest_customer_bridge, &d); --} -- --/* -- * Handle notifications from other modules. Check if sender-id and data type -- * indicator match. Return false when data could not be delivered. -- */ --static int ecp22_notify(int sender_id, char *ifname, void *data) --{ -- struct qbg22_imm *qbg = (struct qbg22_imm *)data; -- -- LLDPAD_DBG("%s:%s sender-id:%#x data_type:%d\n", __func__, ifname, -- sender_id, qbg->data_type); -- if (sender_id == LLDP_MOD_EVB22 && qbg->data_type == EVB22_TO_ECP22) -- return data_from_evb(ifname, &qbg->u.a); -- if (sender_id == LLDP_MOD_VDP22 && qbg->data_type == VDP22_TO_ECP22) -- return data_from_vdp(ifname, &qbg->u.c); -- return 0; --} -- --static const struct lldp_mod_ops ecp22_ops = { -- .lldp_mod_register = ecp22_register, -- .lldp_mod_unregister = ecp22_unregister, -- .lldp_mod_notify = ecp22_notify --}; -- --/* -- * ecp22_register - register ecp module to lldpad -- * -- * returns lldp_module struct on success, NULL on error -- * -- * allocates a module structure with ecp module information and returns it -- * to lldpad. -- */ --struct lldp_module *ecp22_register(void) --{ -- struct lldp_module *mod; -- struct ecp22_user_data *eud; -- -- mod = calloc(1, sizeof *mod); -- if (!mod) { -- LLDPAD_ERR("%s:can not allocate ecp module data\n", __func__); -- return NULL; -- } -- eud = calloc(1, sizeof(struct ecp22_user_data)); -- if (!eud) { -- free(mod); -- LLDPAD_ERR("%s:can not allocate ecp user data\n", __func__); -- return NULL; -- } -- LIST_INIT(&eud->head); -- mod->id = LLDP_MOD_ECP22; -- mod->ops = &ecp22_ops; -- mod->data = eud; -- LLDPAD_DBG("%s: done\n", __func__); -- return mod; --} -- --/* -- * ecp22_free_data - frees up ecp data chain -- */ --static void ecp22_free_data(struct ecp22_user_data *ud) --{ -- struct ecp22 *ecp; -- -- if (ud) { -- while (!LIST_EMPTY(&ud->head)) { -- ecp = LIST_FIRST(&ud->head); -- ecp22_remove(ecp); -- } -- } --} -- --/* -- * ecp22_unregister - unregister ecp module from lldpad -- * -- * no return value -- * -- * frees ecp module structure and user data. -- */ --void ecp22_unregister(struct lldp_module *mod) --{ -- if (mod->data) { -- ecp22_free_data((struct ecp22_user_data *)mod->data); -- free(mod->data); -- } -- free(mod); -- LLDPAD_DBG("%s: done\n", __func__); --} -diff --git a/qbg/lldp_evb22.c b/qbg/lldp_evb22.c -deleted file mode 100644 -index f9eeace..0000000 ---- a/qbg/lldp_evb22.c -+++ /dev/null -@@ -1,556 +0,0 @@ --/****************************************************************************** -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2012 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --#define _GNU_SOURCE --#include --#include -- --#include "lldp.h" --#include "lldp_tlv.h" --#include "lldp_evb22.h" --#include "lldp_ecp22.h" --#include "lldp_vdp22.h" --#include "lldp_qbg_utils.h" --#include "lldp_evb_cmds.h" --#include "messages.h" --#include "config.h" -- --extern struct lldp_head lldp_head; -- --struct evb22_data *evb22_data(char *ifname, enum agent_type type) --{ -- struct evb22_user_data *ud; -- struct evb22_data *ed = NULL; -- -- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB22); -- if (ud) { -- LIST_FOREACH(ed, &ud->head, entry) { -- if (!strncmp(ifname, ed->ifname, IFNAMSIZ) && -- (type == ed->agenttype)) -- break; -- } -- } -- return ed; --} -- --static void evb22_format_tlv(char *buf, size_t len, struct evb22_tlv *tlv) --{ -- int comma = 0; -- char bridge_txt[32], station_txt[32]; -- -- memset(bridge_txt, 0, sizeof bridge_txt); -- if (evb_ex_bgid(tlv->bridge_s)) { -- strcat(bridge_txt, "bgid"); -- comma = 1; -- } -- if (evb_ex_rrcap(tlv->bridge_s)) { -- if (comma) -- strcat(bridge_txt, ","); -- strcat(bridge_txt, "rrcap"); -- comma = 1; -- } -- if (evb_ex_rrctr(tlv->bridge_s)) { -- if (comma) -- strcat(bridge_txt, ","); -- strcat(bridge_txt, "rrctr"); -- } -- -- comma = 0; -- memset(station_txt, 0, sizeof station_txt); -- if (evb_ex_sgid(tlv->station_s)) { -- strcat(station_txt, "sgid"); -- comma = 1; -- } -- if (evb_ex_rrreq(tlv->station_s)) { -- if (comma) -- strcat(station_txt, ","); -- strcat(station_txt, "rrreq"); -- comma = 1; -- } -- if (evb_ex_rrstat(tlv->station_s)) { -- if (comma) -- strcat(station_txt, ","); -- strcat(station_txt, "rrstat"); -- } -- snprintf(buf, len, "bridge:%s(%#02x) station:%s(%#02x) " -- "retries:%d rte:%d mode:%d r/l:%d rwd:%d " -- "r/l:%d rka:%d", bridge_txt, tlv->bridge_s, -- station_txt, tlv->station_s, -- evb_ex_retries(tlv->r_rte), evb_ex_rte(tlv->r_rte), -- evb_ex_evbmode(tlv->evb_mode), evb_ex_rol(tlv->evb_mode), -- evb_ex_rwd(tlv->evb_mode), -- evb_ex_rol(tlv->rl_rka), evb_ex_rka(tlv->rl_rka)); --} -- --static void evb22_print_tlvinfo(char *ifname, struct evb22_tlv *tlv) --{ -- char buf[256]; -- -- evb22_format_tlv(buf, sizeof buf, tlv); -- LLDPAD_DBG("%s evb %s\n", ifname, buf); --} -- --static void evb22_dump_tlv(char *ifname, struct unpacked_tlv *tlv) --{ -- int i, left = 0; -- char buffer[256]; -- -- for (i = 0; i < tlv->length; i++) { -- int c; -- -- c = snprintf(buffer + left, -- sizeof buffer - left, -- "%02x ", tlv->info[i]); -- -- if (c < 0 || (c >= (int)sizeof buffer - left)) -- break; -- else -- left += c; -- } -- -- LLDPAD_DBG("%s:%s type %i length %i info %s\n", -- __func__, ifname, tlv->type, tlv->length, buffer); --} -- --static void common_tlv(struct evb22_data *ed) --{ -- struct evb22_tlv *recv = &ed->last; -- struct evb22_tlv *mine = &ed->policy; -- u8 val; -- -- /* Set retries and rte value */ -- val = evb_ex_retries(recv->r_rte); -- if (evb_ex_retries(mine->r_rte) > val) -- val = evb_ex_retries(mine->r_rte); -- ed->out.r_rte = evb_set_retries(val); -- val = evb_ex_rte(recv->r_rte); -- if (evb_ex_rte(mine->r_rte) > val) -- val = evb_ex_rte(mine->r_rte); -- ed->out.r_rte |= evb_set_rte(val); -- -- /* Set evbmode */ -- ed->out.evb_mode = evb_set_evbmode(evb_ex_evbmode(mine->evb_mode)); -- val = evb_ex_rwd(recv->evb_mode); -- if (evb_ex_rwd(mine->evb_mode) > val) -- val = evb_ex_rwd(mine->evb_mode); -- else -- ed->out.evb_mode |= evb_set_rol(1); -- ed->out.evb_mode |= evb_set_rwd(val); -- -- /* Set rka */ -- ed->out.rl_rka = 0; -- val = evb_ex_rka(recv->rl_rka); -- if (evb_ex_rka(mine->rl_rka) > val) -- val = evb_ex_rka(mine->rl_rka); -- else -- ed->out.rl_rka = evb_set_rol(1); -- ed->out.rl_rka |= evb_set_rka(val); --} -- --/* -- * Fill the EVB DU for LLDP transmition. Sender is bridge. -- */ --static void bridge_tlv(struct evb22_data *ed) --{ -- struct evb22_tlv *recv = &ed->last; -- struct evb22_tlv *mine = &ed->policy; -- -- /* Copy my last station status */ -- ed->out.station_s = recv->station_s; -- -- /* Set bridge status */ -- ed->out.bridge_s = mine->bridge_s; -- if (evb_ex_rrreq(recv->station_s) && evb_ex_rrcap(mine->bridge_s)) -- ed->out.bridge_s |= evb_set_rrctr(1); -- common_tlv(ed); --} -- --/* -- * Fill the EVB DU for LLDP transmition. Sender is station. -- */ --static void station_tlv(struct evb22_data *ed) --{ -- struct evb22_tlv *recv = &ed->last; -- struct evb22_tlv *mine = &ed->policy; -- u8 val; -- -- /* Copy my last bridge status */ -- ed->out.bridge_s = recv->bridge_s; -- -- /* -- * Set station status, 2nd byte of OUI is 0x80. If 0x00 -- * nothing received from bridge. -- */ -- if (recv->oui[1] == 0) -- val = EVB_RRSTAT_DONT; -- else if (evb_ex_rrctr(recv->bridge_s)) -- val = EVB_RRSTAT_YES; -- else -- val = EVB_RRSTAT_NO; -- ed->out.station_s = evb_maskoff_rrstat(mine->station_s) -- | evb_set_rrstat(val); -- common_tlv(ed); --} -- --/* -- * Checks values received in TLV and takes over some values. -- * Sets the new suggestion in member tie to be send out to switch. -- * -- * Also notify depending modules about the new values. -- */ --static void evb22_update_tlv(struct evb22_data *ed) --{ -- struct qbg22_imm qbg; -- -- if (evb_ex_evbmode(ed->policy.evb_mode) == EVB_STATION) -- station_tlv(ed); -- else -- bridge_tlv(ed); -- -- qbg.data_type = EVB22_TO_ECP22; -- qbg.u.a.max_rte = evb_ex_rte(ed->out.r_rte); -- qbg.u.a.max_retry = evb_ex_retries(ed->out.r_rte); -- modules_notify(LLDP_MOD_ECP22, LLDP_MOD_EVB22, ed->ifname, &qbg); -- -- qbg.data_type = EVB22_TO_VDP22; -- qbg.u.b.max_rka = evb_ex_rka(ed->out.rl_rka); -- qbg.u.b.max_rwd = evb_ex_rwd(ed->out.evb_mode); -- /* Support group identifiers when advertised by both sides */ -- qbg.u.b.gpid = evb_ex_bgid(ed->out.bridge_s) -- && evb_ex_sgid(ed->out.station_s); -- modules_notify(LLDP_MOD_VDP22, LLDP_MOD_EVB22, ed->ifname, &qbg); --} -- --/* -- * Build the packed EVB TLV. -- * Returns a pointer to the packed tlv or 0 on failure. -- */ --static struct packed_tlv *evb22_build_tlv(struct evb22_data *ed) --{ -- struct packed_tlv *ptlv = 0; -- u8 infobuf[sizeof(struct evb22_tlv)]; -- struct unpacked_tlv tlv = { -- .type = ORG_SPECIFIC_TLV, -- .length = sizeof(struct evb22_tlv), -- .info = infobuf -- }; -- -- evb22_update_tlv(ed); -- memcpy(tlv.info, &ed->out, tlv.length); -- ptlv = pack_tlv(&tlv); -- if (ptlv) { -- LLDPAD_DBG("%s:%s TLV about to be sent out:\n", __func__, -- ed->ifname); -- evb22_dump_tlv(ed->ifname, &tlv); -- } else -- LLDPAD_DBG("%s:%s failed to pack EVB TLV\n", __func__, -- ed->ifname); -- return ptlv; --} -- --/* -- * Function call to build and return module specific packed EVB TLV. -- * Returned packed_tlv is free'ed by caller of this function. -- */ --static struct packed_tlv *evb22_gettlv(struct port *port, -- struct lldp_agent *agent) --{ -- struct evb22_data *ed; -- -- if (agent->type != NEAREST_CUSTOMER_BRIDGE) -- return 0; -- ed = evb22_data(port->ifname, agent->type); -- if (!ed) { -- LLDPAD_ERR("%s:%s agent %d failed\n", __func__, port->ifname, -- agent->type); -- return 0; -- } -- return (ed->txmit) ? evb22_build_tlv(ed) : 0; --} -- --/* -- * evb_rchange: process received EVB TLV LLDPDU -- * -- * TLV not consumed on error -- */ --static int evb22_rchange(struct port *port, struct lldp_agent *agent, -- struct unpacked_tlv *tlv) --{ -- struct evb22_data *ed; -- u8 oui_subtype[OUI_SUB_SIZE] = LLDP_MOD_EVB22_OUI; -- -- if (agent->type != NEAREST_CUSTOMER_BRIDGE) -- return 0; -- ed = evb22_data(port->ifname, agent->type); -- -- if (!ed) -- return SUBTYPE_INVALID; -- -- if (tlv->type == TYPE_127) { -- /* check for length */ -- if (tlv->length < OUI_SUB_SIZE) -- return TLV_ERR; -- -- /* check for oui */ -- if (memcmp(tlv->info, &oui_subtype, OUI_SUB_SIZE)) -- return SUBTYPE_INVALID; -- -- /* disable rx if tx has been disabled by administrator */ -- if (!ed->txmit) { -- LLDPAD_WARN("%s:%s agent %d EVB Config disabled\n", -- __func__, ed->ifname, agent->type); -- return TLV_OK; -- } -- -- LLDPAD_DBG("%s:%s agent %d received tlv:\n", __func__, -- port->ifname, agent->type); -- evb22_dump_tlv(ed->ifname, tlv); -- memcpy(&ed->last, tlv->info, tlv->length); -- evb22_print_tlvinfo(ed->ifname, &ed->last); -- -- evb22_update_tlv(ed); -- somethingChangedLocal(ed->ifname, agent->type); -- -- LLDPAD_DBG("%s:%s agent %d new tlv:\n", __func__, port->ifname, -- agent->type); -- evb22_print_tlvinfo(ed->ifname, &ed->out); -- /* TODO vdp_update(port->ifname, ed->tie.ccap); */ -- } -- return TLV_OK; --} -- --/* -- * Stop all modules which depend on EVB capabilities. -- */ --static void evb22_stop_modules(char *ifname) --{ -- LLDPAD_DBG("%s:%s STOP\n", __func__, ifname); -- ecp22_stop(ifname); -- vdp22_stop(ifname); --} -- --static void evb22_ifdown(char *ifname, struct lldp_agent *agent) --{ -- struct evb22_data *ed; -- -- if (agent->type != NEAREST_CUSTOMER_BRIDGE) -- return; -- LLDPAD_DBG("%s:%s agent %d called\n", __func__, ifname, agent->type); -- -- ed = evb22_data(ifname, agent->type); -- if (!ed) { -- LLDPAD_DBG("%s:%s agent %d does not exist.\n", __func__, -- ifname, agent->type); -- return; -- } -- if (ed->vdp_start) -- evb22_stop_modules(ifname); -- LIST_REMOVE(ed, entry); -- free(ed); -- LLDPAD_INFO("%s:%s agent %d removed\n", __func__, ifname, agent->type); --} -- --/* -- * Fill up evb structure with reasonable info from the configuration file. -- */ --static void evb22_init_tlv(struct evb22_data *ed, struct lldp_agent *agent) --{ -- u8 mode; -- -- memset(&ed->last, 0, sizeof ed->last); -- memset(&ed->out, 0, sizeof ed->out); -- memset(&ed->policy, 0, sizeof ed->policy); -- -- ed->txmit = evb22_conf_enabletx(ed->ifname, agent->type); -- if (!ed->txmit) -- LLDPAD_DBG("%s:%s agent %d EVB tx is currently disabled\n", -- __func__, ed->ifname, agent->type); -- -- hton24(ed->policy.oui, LLDP_MOD_EVB22); -- ed->policy.sub = LLDP_MOD_EVB22_SUBTYPE; -- hton24(ed->out.oui, LLDP_MOD_EVB22); -- ed->out.sub = LLDP_MOD_EVB22_SUBTYPE; -- -- mode = evb22_conf_evbmode(ed->ifname, agent->type); -- ed->policy.evb_mode = evb_set_rol(0) -- | evb_set_rwd(evb22_conf_rwd(ed->ifname, agent->type)) -- | evb_set_evbmode(mode); -- if (mode == EVB_STATION) { -- mode = evb22_conf_rrreq(ed->ifname, agent->type); -- ed->policy.station_s = evb_set_rrstat(EVB_RRSTAT_DONT) -- | evb_set_sgid(evb22_conf_gid(ed->ifname, agent->type)) -- | evb_set_rrreq(mode); -- ed->policy.bridge_s = 0; -- } else { -- mode = evb22_conf_rrcap(ed->ifname, agent->type); -- ed->policy.bridge_s = evb_set_rrcap(mode) -- | evb_set_bgid(evb22_conf_gid(ed->ifname, agent->type)); -- ed->policy.station_s = 0; -- } -- ed->policy.r_rte = -- evb_set_retries(evb22_conf_retries(ed->ifname, agent->type)) -- | evb_set_rte(evb22_conf_rte(ed->ifname, agent->type)); -- ed->policy.rl_rka = evb_set_rol(0) -- | evb_set_rka(evb22_conf_rka(ed->ifname, agent->type)); --} -- --static void evb22_ifup(char *ifname, struct lldp_agent *agent) --{ -- struct evb22_data *ed; -- struct evb22_user_data *ud; -- -- if (agent->type != NEAREST_CUSTOMER_BRIDGE) -- return; -- LLDPAD_DBG("%s:%s agent %d called\n", __func__, ifname, agent->type); -- -- ed = evb22_data(ifname, agent->type); -- if (ed) { -- LLDPAD_DBG("%s:%s agent %d already exists\n", __func__, ifname, -- agent->type); -- return; -- } -- -- /* not found, alloc/init per-port tlv data */ -- ed = (struct evb22_data *) calloc(1, sizeof *ed); -- if (!ed) { -- LLDPAD_ERR("%s:%s agent %d malloc %zu failed\n", -- __func__, ifname, agent->type, sizeof *ed); -- return; -- } -- strncpy(ed->ifname, ifname, IFNAMSIZ); -- ed->agenttype = agent->type; -- evb22_init_tlv(ed, agent); -- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB22); -- LIST_INSERT_HEAD(&ud->head, ed, entry); -- LLDPAD_DBG("%s:%s agent %d added\n", __func__, ifname, agent->type); --} -- --/* -- * Start all modules which depend on EVB capabilities: ECP, VDP, CDCP. -- */ --static void evb22_start_modules(char *ifname) --{ -- LLDPAD_DBG("%s:%s START\n", __func__, ifname); -- ecp22_start(ifname); -- vdp22_start(ifname); --} -- --/* -- * Check for stable interfaces. When an interface goes up the carrier might -- * come and go during a start up time. Define a window during which the port -- * is considered unstable for EVB/VDP protocols. -- * -- * Use the dormantDelay counter of the port to determine a stable interface. -- */ --static int evb22_timer(struct port *port, struct lldp_agent *agent) --{ -- struct evb22_data *ed; -- -- if (agent->type != NEAREST_CUSTOMER_BRIDGE) -- return 0; -- ed = evb22_data(port->ifname, agent->type); -- if (!ed) -- return 0; -- if (!ed->vdp_start -- && evb_ex_rrstat(ed->out.station_s) == EVB_RRSTAT_YES) { -- ed->vdp_start = true; -- evb22_start_modules(port->ifname); -- } -- return 0; --} -- --static u8 evb22_mibdelete(struct port *port, struct lldp_agent *agent) --{ -- struct evb22_data *ed; -- -- ed = evb22_data(port->ifname, agent->type); -- if (ed && (agent->type == ed->agenttype)) { -- memset(&ed->last, 0, sizeof ed->last); -- /* TODO vdp_update(port->ifname, 0); */ -- } -- return 0; --} -- --/* -- * Remove all interface/agent specific evb data. -- */ --static void evb22_free_data(struct evb22_user_data *ud) --{ -- struct evb22_data *ed; -- -- if (ud) { -- while (!LIST_EMPTY(&ud->head)) { -- ed = LIST_FIRST(&ud->head); -- LIST_REMOVE(ed, entry); -- free(ed); -- } -- } --} -- --void evb22_unregister(struct lldp_module *mod) --{ -- if (mod->data) { -- evb22_free_data((struct evb22_user_data *) mod->data); -- free(mod->data); -- } -- free(mod); -- LLDPAD_DBG("%s:done\n", __func__); --} -- --static const struct lldp_mod_ops evb22_ops = { -- .lldp_mod_gettlv = evb22_gettlv, -- .lldp_mod_rchange = evb22_rchange, -- .lldp_mod_mibdelete = evb22_mibdelete, -- .timer = evb22_timer, -- .lldp_mod_ifdown = evb22_ifdown, -- .lldp_mod_ifup = evb22_ifup, -- .lldp_mod_register = evb22_register, -- .lldp_mod_unregister = evb22_unregister, -- .get_arg_handler = evb22_get_arg_handlers --}; -- --struct lldp_module *evb22_register(void) --{ -- struct lldp_module *mod; -- struct evb22_user_data *ud; -- -- mod = calloc(1, sizeof *mod); -- if (!mod) { -- LLDPAD_ERR("%s: failed to malloc module data\n", __func__); -- return NULL; -- } -- ud = calloc(1, sizeof *ud); -- if (!ud) { -- free(mod); -- LLDPAD_ERR("%s failed to malloc module user data\n", __func__); -- return NULL; -- } -- LIST_INIT(&ud->head); -- mod->id = LLDP_MOD_EVB22; -- mod->ops = &evb22_ops; -- mod->data = ud; -- LLDPAD_DBG("%s:done\n", __func__); -- return mod; --} -diff --git a/qbg/lldp_evb22_clif.c b/qbg/lldp_evb22_clif.c -deleted file mode 100644 -index 336273f..0000000 ---- a/qbg/lldp_evb22_clif.c -+++ /dev/null -@@ -1,201 +0,0 @@ --/****************************************************************************** -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2010, 2012 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --#include --#include -- --#include "lldp_tlv.h" --#include "clif_msgs.h" --#include "lldp_mod.h" --#include "lldptool.h" --#include "lldp.h" --#include "lldp_evb22.h" --#include "lldp_evb22_clif.h" -- --static void show_tlv(char *buf, size_t len, struct evb22_tlv *tlv) --{ -- int comma = 0; -- char bridge_txt[32], station_txt[32]; -- -- memset(bridge_txt, 0, sizeof bridge_txt); -- if (evb_ex_bgid(tlv->bridge_s)) { -- strcat(bridge_txt, "bgid"); -- comma = 1; -- } -- if (evb_ex_rrcap(tlv->bridge_s)) { -- if (comma) -- strcat(bridge_txt, ","); -- strcat(bridge_txt, "rrcap"); -- comma = 1; -- } -- if (evb_ex_rrctr(tlv->bridge_s)) { -- if (comma) -- strcat(bridge_txt, ","); -- strcat(bridge_txt, "rrctr"); -- } -- -- comma = 0; -- memset(station_txt, 0, sizeof station_txt); -- if (evb_ex_sgid(tlv->station_s)) { -- strcat(station_txt, "sgid"); -- comma = 1; -- } -- if (evb_ex_rrreq(tlv->station_s)) { -- if (comma) -- strcat(station_txt, ","); -- strcat(station_txt, "rrreq"); -- comma = 1; -- } -- if (evb_ex_rrstat(tlv->station_s)) { -- if (comma) -- strcat(station_txt, ","); -- strcat(station_txt, "rrstat"); -- } -- -- snprintf(buf, len, "bridge:%s(%#02x)\n" -- "\tstation:%s(%#02x)\n" -- "\tretries:%d rte:%d\n" -- "\tmode:%s r/l:%d rwd:%d\n" -- "\tr/l:%d rka:%d\n", -- bridge_txt, tlv->bridge_s, -- station_txt, tlv->station_s, -- evb_ex_retries(tlv->r_rte), evb_ex_rte(tlv->r_rte), -- evb_ex_evbmode(tlv->evb_mode) == EVB_STATION ? -- "station" : "bridge", -- evb_ex_rol(tlv->evb_mode), -- evb_ex_rwd(tlv->evb_mode), -- evb_ex_rol(tlv->rl_rka), evb_ex_rka(tlv->rl_rka)); --} -- --static void evb22_print_cfg_tlv(u16 len, char *info) --{ -- struct evb22_tlv tlv; -- char buf[256]; -- -- if (len != 5) { -- printf("Bad evbcfg TLV: %s\n", info); -- return; -- } -- memset(&tlv, 0, sizeof tlv); -- memset(buf, 0, sizeof buf); -- hexstr2bin(&info[0], &tlv.bridge_s, sizeof tlv.bridge_s); -- hexstr2bin(&info[2], &tlv.station_s, sizeof tlv.station_s); -- hexstr2bin(&info[4], &tlv.r_rte, sizeof tlv.r_rte); -- hexstr2bin(&info[6], &tlv.evb_mode, sizeof tlv.evb_mode); -- hexstr2bin(&info[8], &tlv.rl_rka, sizeof tlv.rl_rka); -- show_tlv(buf, sizeof buf, &tlv); -- printf("%s", buf); --} -- --static struct type_name_info evb22_tlv_names[] = { -- { -- .type = TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE), -- .name = "EVB Configuration TLV", -- .key = "evb", -- .print_info = evb22_print_cfg_tlv -- }, -- { -- .type = INVALID_TLVID -- } --}; -- --static int evb22_print_help() --{ -- struct type_name_info *tn = &evb22_tlv_names[0]; -- -- while (tn->type != INVALID_TLVID) { -- if (tn->key && strlen(tn->key) && tn->name) { -- printf(" %s", tn->key); -- if (strlen(tn->key)+3 < 8) -- printf("\t"); -- printf("\t: %s\n", tn->name); -- } -- tn++; -- } -- -- return 0; --} -- --static void evb22_cli_unregister(struct lldp_module *mod) --{ -- free(mod); --} -- --/* return 1: if it printed the TLV -- * 0: if it did not -- */ --static int evb22_print_tlv(u32 tlvid, u16 len, char *info) --{ -- struct type_name_info *tn = &evb22_tlv_names[0]; -- -- while (tn->type != INVALID_TLVID) { -- if (tlvid == tn->type) { -- printf("%s\n", tn->name); -- if (tn->print_info) { -- printf("\t"); -- tn->print_info(len-4, info); -- } -- return 1; -- } -- tn++; -- } -- -- return 0; --} -- --static u32 evb22_lookup_tlv_name(char *tlvid_str) --{ -- struct type_name_info *tn = &evb22_tlv_names[0]; -- -- while (tn->type != INVALID_TLVID) { -- if (!strcasecmp(tn->key, tlvid_str)) -- return tn->type; -- tn++; -- } -- return INVALID_TLVID; --} -- --static const struct lldp_mod_ops evb22_ops_clif = { -- .lldp_mod_register = evb22_cli_register, -- .lldp_mod_unregister = evb22_cli_unregister, -- .print_tlv = evb22_print_tlv, -- .lookup_tlv_name = evb22_lookup_tlv_name, -- .print_help = evb22_print_help --}; -- --struct lldp_module *evb22_cli_register(void) --{ -- struct lldp_module *mod; -- -- mod = calloc(1, sizeof(*mod)); -- if (!mod) { -- fprintf(stderr, "%s failed to malloc module data\n", __func__); -- return NULL; -- } -- mod->id = LLDP_MOD_EVB22; -- mod->ops = &evb22_ops_clif; -- -- return mod; --} -diff --git a/qbg/lldp_evb22_cmds.c b/qbg/lldp_evb22_cmds.c -deleted file mode 100644 -index 51b7ba1..0000000 ---- a/qbg/lldp_evb22_cmds.c -+++ /dev/null -@@ -1,738 +0,0 @@ --/****************************************************************************** -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2012 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --#define _GNU_SOURCE -- --#include --#include --#include -- --#include "lldp.h" --#include "lldp_evb22.h" --#include "lldp_tlv.h" --#include "lldp_mand_clif.h" --#include "config.h" --#include "clif_msgs.h" --#include "messages.h" -- --/* -- * Defines for configuration file name tags. -- */ --#define EVB_BUF_SIZE 256 --#define EVB_CONF_MODE "evbmode" --#define EVB_CONF_RRREQ "evbrrreq" --#define EVB_CONF_RRCAP "evbrrcap" --#define EVB_CONF_GPID "evbgpid" --#define EVB_CONF_RETRIES "ecpretries" --#define EVB_CONF_RTE "ecprte" --#define EVB_CONF_RWD "vdprwd" --#define EVB_CONF_RKA "vdprka" --#define EVB_CONF_BRIDGE "bridge" --#define EVB_CONF_STATION "station" -- --/* -- * Read EVB specific data from the configuration file. -- */ --static const char *evb22_conf_string(char *ifname, enum agent_type type, -- char *ext, int def) --{ -- char arg_path[EVB_BUF_SIZE]; -- const char *param = NULL; -- -- snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -- TLVID_PREFIX, TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE), -- ext); -- if (get_cfg(ifname, type, arg_path, ¶m, CONFIG_TYPE_STRING)) -- LLDPAD_INFO("%s:%s agent %d loading EVB policy for %s" -- " failed, using default (%d)\n", __func__, -- ifname, type, ext, def); -- return param; --} -- --static int evb22_conf_int(char *ifname, enum agent_type type, -- char *ext, int def, int cfgtype) --{ -- char arg_path[EVB_BUF_SIZE]; -- int param; -- -- snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -- TLVID_PREFIX, TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE), -- ext); -- if (get_cfg(ifname, type, arg_path, ¶m, cfgtype)) { -- LLDPAD_INFO("%s:%s agent %d loading EVB policy for %s" -- " failed, using default (%d)\n", __func__, -- ifname, type, ext, def); -- return def; -- } -- return param; --} -- --/* -- * Read EXP parameter. Defaults to 8 --> 10 * 2 ^ 8 = 2560us > 2ms. -- */ --static int exponent(char *ifname, enum agent_type type, char *txt, int def) --{ -- int value; -- -- value = evb22_conf_int(ifname, type, txt, def, CONFIG_TYPE_INT); -- if (value > 31) { -- LLDPAD_DBG("%s:%s agent %d invalid %s %d\n", __func__, -- ifname, type, txt, value); -- value = def; -- } -- LLDPAD_DBG("%s:%s agent %d policy %s %d\n", __func__, -- ifname, type, txt, value); -- return value; --} -- --/* -- * Read retransmission exponent parameter. -- */ --int evb22_conf_rte(char *ifname, enum agent_type type) --{ -- return exponent(ifname, type, EVB_CONF_RTE, 8); --} -- --/* -- * Read reinit keep alive parameter. Same as RTE. -- */ --int evb22_conf_rka(char *ifname, enum agent_type type) --{ -- return exponent(ifname, type, EVB_CONF_RKA, 20); --} -- --/* -- * Read resource wait delay parameter. Same as RTE. -- */ --int evb22_conf_rwd(char *ifname, enum agent_type type) --{ -- return exponent(ifname, type, EVB_CONF_RWD, 20); --} -- --/* -- * Read max retries parameter. Defaults to 3. -- */ --int evb22_conf_retries(char *ifname, enum agent_type type) --{ -- int value; -- -- value = evb22_conf_int(ifname, type, EVB_CONF_RETRIES, 3, -- CONFIG_TYPE_INT); -- if (value > 7) { -- LLDPAD_DBG("%s:%s agent %d invalid %s %d\n", __func__, -- ifname, type, EVB_CONF_RETRIES, value); -- value = 3; -- } -- LLDPAD_DBG("%s:%s agent %d policy %s %d\n", __func__, -- ifname, type, EVB_CONF_RETRIES, value); -- return value; --} -- --/* -- * Read station group id parameter. Defaults to false. -- */ --int evb22_conf_gid(char *ifname, enum agent_type type) --{ -- int value; -- -- value = evb22_conf_int(ifname, type, EVB_CONF_GPID, false, -- CONFIG_TYPE_BOOL); -- LLDPAD_DBG("%s:%s agent %d policy %s %s\n", __func__, -- ifname, type, EVB_CONF_GPID, value ? "true" : "false"); -- return value; --} -- --/* -- * Read reflective-relay bridge capability parameter. Defaults to false. -- */ --int evb22_conf_rrcap(char *ifname, enum agent_type type) --{ -- int value; -- -- value = evb22_conf_int(ifname, type, EVB_CONF_RRCAP, false, -- CONFIG_TYPE_BOOL); -- LLDPAD_DBG("%s:%s agent %d policy %s %s\n", __func__, -- ifname, type, EVB_CONF_RRCAP, value ? "true" : "false"); -- return value; --} -- --/* -- * Read reflective-relay station request parameter. Defaults to false. -- */ --int evb22_conf_rrreq(char *ifname, enum agent_type type) --{ -- int value; -- -- value = evb22_conf_int(ifname, type, EVB_CONF_RRREQ, false, -- CONFIG_TYPE_BOOL); -- LLDPAD_DBG("%s:%s agent %d policy %s %s\n", __func__, -- ifname, type, EVB_CONF_RRREQ, value ? "true" : "false"); -- return value; --} -- --/* -- * Read station/bridge role from configuration file. Defaults to station -- */ --int evb22_conf_evbmode(char *ifname, enum agent_type type) --{ -- int mode = EVB_STATION; -- const char *value; -- -- value = evb22_conf_string(ifname, type, EVB_CONF_MODE, mode); -- if (value) { -- if (!strcasecmp(value, EVB_CONF_BRIDGE)) -- mode = EVB_BRIDGE; -- else if (strcasecmp(value, EVB_CONF_STATION)) { -- LLDPAD_ERR("%s:%s agent %d invalid evbmode %s\n", -- __func__, ifname, type, value); -- value = EVB_CONF_STATION; -- } -- } else -- value = EVB_CONF_STATION; -- LLDPAD_DBG("%s:%s agent %d policy %s %s(%#x)\n", __func__, -- ifname, type, EVB_CONF_MODE, value, mode); -- return mode; --} -- --/* -- * Read transmit status from configuration file. -- */ --int evb22_conf_enabletx(char *ifname, enum agent_type type) --{ -- return is_tlv_txenabled(ifname, type, -- TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE)); --} -- --static int evb22_cmdok(struct cmd *cmd, cmd_status expected) --{ -- if (cmd->cmd != expected) -- return cmd_invalid; -- switch (cmd->tlvid) { -- case TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE): -- return cmd_success; -- case INVALID_TLVID: -- return cmd_invalid; -- default: -- return cmd_not_applicable; -- } --} -- --static int get_arg_evbmode(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- struct evb22_data *ed; -- char *s; -- cmd_status good_cmd = evb22_cmdok(cmd, cmd_gettlv); -- -- if (good_cmd != cmd_success) -- return good_cmd; -- ed = evb22_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (evb_ex_evbmode(ed->policy.evb_mode) == EVB_STATION) -- s = EVB_CONF_STATION; -- else -- s = EVB_CONF_BRIDGE; -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int)strlen(arg), arg, (unsigned int)strlen(s), s); -- return cmd_success; --} -- --static int set2_arg_evbmode(struct cmd *cmd, char *arg, const char *argvalue, -- bool test) --{ -- char arg_path[EVB_BUF_SIZE]; -- struct evb22_data *ed; -- cmd_status good_cmd = evb22_cmdok(cmd, cmd_settlv); -- u8 mode; -- -- if (good_cmd != cmd_success) -- return good_cmd; -- if (strcasecmp(argvalue, EVB_CONF_BRIDGE) -- && strcasecmp(argvalue, EVB_CONF_STATION)) -- return cmd_bad_params; -- ed = evb22_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (test) -- return cmd_success; -- snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -- TLVID_PREFIX, cmd->tlvid, arg); -- -- if (set_cfg(cmd->ifname, cmd->type, arg_path, &argvalue, -- CONFIG_TYPE_STRING)) { -- LLDPAD_ERR("%s: error saving EVB mode (%s)\n", ed->ifname, -- argvalue); -- return cmd_failed; -- } -- mode = strcasecmp(argvalue, EVB_CONF_BRIDGE) ? EVB_STATION : EVB_BRIDGE; -- ed->policy.evb_mode = evb_maskoff_evbmode(ed->policy.evb_mode) | -- evb_set_evbmode(mode); -- LLDPAD_INFO("%s: changed EVB mode (%s)\n", ed->ifname, argvalue); -- return cmd_success; --} -- --static int set_arg_evbmode(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return set2_arg_evbmode(cmd, arg, argvalue, false); --} -- --static int test_arg_evbmode(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return set2_arg_evbmode(cmd, arg, argvalue, true); --} -- --static int get_txmit(struct evb22_data *ed) --{ -- return ed->txmit; --} -- --static void set_txmit(struct evb22_data *ed, int value) --{ -- ed->txmit = value; --} -- --static int get_gpid(struct evb22_data *ed) --{ -- int mode = evb_ex_evbmode(ed->policy.evb_mode); -- -- if (mode == EVB_STATION && evb_ex_sgid(ed->policy.station_s)) -- return 1; -- if (mode == EVB_BRIDGE && evb_ex_bgid(ed->policy.bridge_s)) -- return 1; -- return 0; --} -- --static void set_gpid(struct evb22_data *ed, int value) --{ -- if (evb_ex_evbmode(ed->policy.evb_mode) == EVB_STATION) -- ed->policy.station_s = evb_maskoff_sgid(ed->policy.station_s) -- | evb_set_sgid(value); -- else -- ed->policy.bridge_s = evb_maskoff_bgid(ed->policy.bridge_s) -- | evb_set_bgid(value); --} -- --static void set_rrcap(struct evb22_data *ed, int value) --{ -- ed->policy.bridge_s = evb_maskoff_rrcap(ed->policy.bridge_s) -- | evb_set_rrcap(value); --} -- --static int get_rrcap(struct evb22_data *ed) --{ -- return evb_ex_rrcap(ed->policy.bridge_s); --} -- --static void set_rrreq(struct evb22_data *ed, int value) --{ -- ed->policy.station_s = evb_maskoff_rrreq(ed->policy.station_s) -- | evb_set_rrreq(value); --} -- --static int get_rrreq(struct evb22_data *ed) --{ -- return evb_ex_rrreq(ed->policy.station_s); --} -- --/* -- * Read a boolean value from the command line argument and apply the new -- * value to parameter. -- */ --static int scan_bool(struct cmd *cmd, char *arg, char *argvalue, bool test, -- void (*fct)(struct evb22_data *, int)) --{ -- int value; -- char arg_path[EVB_BUF_SIZE]; -- struct evb22_data *ed; -- cmd_status good_cmd = evb22_cmdok(cmd, cmd_settlv); -- -- if (good_cmd != cmd_success) -- return good_cmd; -- if (!strcasecmp(argvalue, VAL_YES)) -- value = 1; -- else if (!strcasecmp(argvalue, VAL_NO)) -- value = 0; -- else -- return cmd_bad_params; -- ed = evb22_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (test) -- return cmd_success; -- snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -- TLVID_PREFIX, cmd->tlvid, arg); -- if (set_cfg(cmd->ifname, cmd->type, arg_path, &value, -- CONFIG_TYPE_BOOL)){ -- LLDPAD_ERR("%s: error saving EVB enabletx (%s)\n", ed->ifname, -- argvalue); -- return cmd_failed; -- } -- LLDPAD_INFO("%s: changed EVB %s (%s)\n", ed->ifname, arg, argvalue); -- (*fct)(ed, value); -- somethingChangedLocal(cmd->ifname, cmd->type); -- return cmd_success; --} -- --static int show_bool(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len, -- int (*fct)(struct evb22_data *)) --{ -- struct evb22_data *ed; -- char *s; -- cmd_status good_cmd = evb22_cmdok(cmd, cmd_gettlv); -- -- if (good_cmd != cmd_success) -- return good_cmd; -- ed = evb22_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if ((*fct)(ed)) -- s = VAL_YES; -- else -- s = VAL_NO; -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int)strlen(arg), arg, (unsigned int)strlen(s), s); -- return cmd_success; --} -- --static int get_arg_tlvtxenable(struct cmd *cmd, char *arg, -- UNUSED char *argvalue, char *obuf, int obuf_len) --{ -- return show_bool(cmd, arg, argvalue, obuf, obuf_len, get_txmit); --} -- --static int set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_bool(cmd, arg, argvalue, false, set_txmit); --} -- --static int test_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_bool(cmd, arg, argvalue, true, 0); --} -- --static int get_arg_gpid(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- return show_bool(cmd, arg, argvalue, obuf, obuf_len, get_gpid); --} -- --static int set_arg_gpid(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_bool(cmd, arg, argvalue, false, set_gpid); --} -- --static int test_arg_gpid(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_bool(cmd, arg, argvalue, true, 0); --} -- --static int get_arg_rrcap(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- return show_bool(cmd, arg, argvalue, obuf, obuf_len, get_rrcap); --} -- --static int set_arg_rrcap(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_bool(cmd, arg, argvalue, false, set_rrcap); --} -- --static int test_arg_rrcap(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_bool(cmd, arg, argvalue, true, 0); --} -- --static int get_arg_rrreq(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- return show_bool(cmd, arg, argvalue, obuf, obuf_len, get_rrreq); --} -- --static int set_arg_rrreq(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_bool(cmd, arg, argvalue, false, set_rrreq); --} -- --static int test_arg_rrreq(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_bool(cmd, arg, argvalue, true, 0); --} -- -- --static void set_retries(struct evb22_data *ed, int value) --{ -- ed->policy.r_rte = evb_maskoff_retries(ed->policy.r_rte) -- | evb_set_retries(value); --} -- --static int get_retries(struct evb22_data *ed) --{ -- return evb_ex_retries(ed->policy.r_rte); --} -- --static void set_rte(struct evb22_data *ed, int value) --{ -- ed->policy.r_rte = evb_maskoff_rte(ed->policy.r_rte) -- | evb_set_rte(value); --} -- --static int get_rte(struct evb22_data *ed) --{ -- return evb_ex_rte(ed->policy.r_rte); --} -- --static void set_rwd(struct evb22_data *ed, int value) --{ -- ed->policy.evb_mode = evb_maskoff_rwd(ed->policy.evb_mode) -- | evb_set_rwd(value); --} -- --static int get_rwd(struct evb22_data *ed) --{ -- return evb_ex_rwd(ed->policy.evb_mode); --} -- --static void set_rka(struct evb22_data *ed, int value) --{ -- ed->policy.rl_rka = evb_maskoff_rka(ed->policy.rl_rka) -- | evb_set_rka(value); --} -- --static int get_rka(struct evb22_data *ed) --{ -- return evb_ex_rka(ed->policy.rl_rka); --} -- --static int scan_31bit(struct cmd *cmd, char *arg, const char *argvalue, -- bool test, void (*fct)(struct evb22_data *, int), -- int limit) --{ -- char arg_path[EVB_BUF_SIZE]; -- struct evb22_data *ed; -- int value; -- char *endp; -- cmd_status good_cmd = evb22_cmdok(cmd, cmd_settlv); -- -- if (good_cmd != cmd_success) -- return good_cmd; -- value = strtoul(argvalue, &endp, 0); -- if (*endp != '\0' || value > limit) -- return cmd_bad_params; -- ed = evb22_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (test) -- return cmd_success; -- snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", -- TLVID_PREFIX, cmd->tlvid, arg); -- if (set_cfg(ed->ifname, cmd->type, arg_path, &value, -- CONFIG_TYPE_INT)){ -- LLDPAD_ERR("%s: error saving EVB %s (%d)\n", ed->ifname, arg, -- value); -- return cmd_failed; -- } -- LLDPAD_INFO("%s: changed EVB %s (%s)\n", ed->ifname, arg, argvalue); -- (*fct)(ed, value); -- somethingChangedLocal(cmd->ifname, cmd->type); -- return cmd_success; --} -- --static int show_31bit(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len, -- int (*fct)(struct evb22_data *)) --{ -- struct evb22_data *ed; -- char s[EVB_BUF_SIZE]; -- cmd_status good_cmd = evb22_cmdok(cmd, cmd_gettlv); -- -- if (good_cmd != cmd_success) -- return good_cmd; -- ed = evb22_data((char *) &cmd->ifname, cmd->type); -- if (!ed) -- return cmd_invalid; -- if (sprintf(s, "%i", (*fct)(ed)) <= 0) -- return cmd_invalid; -- snprintf(obuf, obuf_len, "%02x%s%04x%s", -- (unsigned int)strlen(arg), arg, (unsigned int)strlen(s), s); -- return cmd_success; --} -- --static int get_arg_retries(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- return show_31bit(cmd, arg, argvalue, obuf, obuf_len, get_retries); --} -- --static int set_arg_retries(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_31bit(cmd, arg, argvalue, false, set_retries, 7); --} -- --static int test_arg_retries(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_31bit(cmd, arg, argvalue, true, 0, 7); --} -- --static int get_arg_rte(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- return show_31bit(cmd, arg, argvalue, obuf, obuf_len, get_rte); --} -- --static int set_arg_rte(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_31bit(cmd, arg, argvalue, false, set_rte, 31); --} -- --static int test_arg_rte(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_31bit(cmd, arg, argvalue, true, 0, 31); --} -- --static int get_arg_rwd(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- return show_31bit(cmd, arg, argvalue, obuf, obuf_len, get_rwd); --} -- --static int set_arg_rwd(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_31bit(cmd, arg, argvalue, false, set_rwd, 31); --} -- --static int test_arg_rwd(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_31bit(cmd, arg, argvalue, true, 0, 31); --} -- --static int get_arg_rka(struct cmd *cmd, char *arg, UNUSED char *argvalue, -- char *obuf, int obuf_len) --{ -- return show_31bit(cmd, arg, argvalue, obuf, obuf_len, get_rka); --} -- --static int set_arg_rka(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_31bit(cmd, arg, argvalue, false, set_rka, 31); --} -- --static int test_arg_rka(struct cmd *cmd, char *arg, char *argvalue, -- UNUSED char *obuf, UNUSED int obuf_len) --{ -- return scan_31bit(cmd, arg, argvalue, true, 0, 31); --} -- --static struct arg_handlers arg_handlers[] = { -- { -- .arg = EVB_CONF_RKA, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_rka, -- .handle_set = set_arg_rka, -- .handle_test = test_arg_rka -- }, -- { -- .arg = EVB_CONF_RWD, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_rwd, -- .handle_set = set_arg_rwd, -- .handle_test = test_arg_rwd -- }, -- { -- .arg = EVB_CONF_RTE, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_rte, -- .handle_set = set_arg_rte, -- .handle_test = test_arg_rte -- }, -- { -- .arg = EVB_CONF_RETRIES, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_retries, -- .handle_set = set_arg_retries, -- .handle_test = test_arg_retries -- }, -- { -- .arg = EVB_CONF_RRREQ, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_rrreq, -- .handle_set = set_arg_rrreq, -- .handle_test = test_arg_rrreq -- }, -- { -- .arg = EVB_CONF_RRCAP, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_rrcap, -- .handle_set = set_arg_rrcap, -- .handle_test = test_arg_rrcap -- }, -- { -- .arg = EVB_CONF_GPID, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_gpid, -- .handle_set = set_arg_gpid, -- .handle_test = test_arg_gpid -- }, -- { -- .arg = EVB_CONF_MODE, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_evbmode, -- .handle_set = set_arg_evbmode, -- .handle_test = test_arg_evbmode -- }, -- { -- .arg = ARG_TLVTXENABLE, -- .arg_class = TLV_ARG, -- .handle_get = get_arg_tlvtxenable, -- .handle_set = set_arg_tlvtxenable, -- .handle_test = test_arg_tlvtxenable -- }, -- { -- .arg = 0 -- } --}; -- --struct arg_handlers *evb22_get_arg_handlers() --{ -- return &arg_handlers[0]; --} -diff --git a/qbg/lldp_vdp22.c b/qbg/lldp_vdp22.c -deleted file mode 100644 -index 1d151ea..0000000 ---- a/qbg/lldp_vdp22.c -+++ /dev/null -@@ -1,287 +0,0 @@ --/****************************************************************************** -- -- Implementation of EVB TLVs for LLDP -- (c) Copyright IBM Corp. 2013 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --#define _GNU_SOURCE --#include --#include --#include -- --#include -- --#include "messages.h" --#include "config.h" -- --#include "lldp_vdpnl.h" --#include "lldp_qbg22.h" --#include "lldp_vdp22.h" -- --/* -- * VDP22 helper functions -- */ --/* -- * Find the vdp data associated with an interface. -- * Return pointer or NULL if not found. -- */ --static struct vdp22 *vdp22_findif(const char *ifname, -- struct vdp22_user_data *ud) --{ -- struct vdp22 *vdp = 0; -- -- if (ud) { -- LIST_FOREACH(vdp, &ud->head, entry) -- if (!strncmp(ifname, vdp->ifname, IFNAMSIZ)) -- break; -- } -- return vdp; --} -- --/* -- * Update data exchanged via ECP protocol. -- * Returns true when data update succeeded. -- */ --static int data_from_ecp(char *ifname, struct ecp22_to_ulp *ptr) --{ -- struct vdp22_user_data *vud; -- struct vdp22 *vdp; -- -- vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); -- vdp = vdp22_findif(ifname, vud); -- if (vdp) { -- memcpy(vdp->input, ptr->data, ptr->len); -- vdp->input_len = ptr->len; -- return 0; -- } -- return -ENOENT; --} -- --/* -- * Update data exchanged via EVB protocol. -- * Returns true when data update succeeded. -- */ --static int data_from_evb(char *ifname, struct evb22_to_vdp22 *ptr) --{ -- struct vdp22_user_data *vud; -- struct vdp22 *vdp; -- -- vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); -- vdp = vdp22_findif(ifname, vud); -- if (vdp) { -- vdp->max_rwd = ptr->max_rwd; -- vdp->max_rka = ptr->max_rka; -- vdp->gpid = ptr->gpid; -- return 0; -- } -- return -ENOENT; --} -- --/* -- * Handle notifications from other modules. Check if sender-id and data type -- * indicator match. Return false when data could not be delivered. -- */ --static int vdp22_notify(int sender_id, char *ifname, void *data) --{ -- struct qbg22_imm *qbg = (struct qbg22_imm *)data; -- -- LLDPAD_DBG("%s:%s sender-id:%#x data_type:%d\n", __func__, ifname, -- sender_id, qbg->data_type); -- if (sender_id == LLDP_MOD_EVB22 && qbg->data_type == EVB22_TO_VDP22) -- return data_from_evb(ifname, &qbg->u.b); -- if (sender_id == LLDP_MOD_ECP22 && qbg->data_type == ECP22_TO_ULP) -- return data_from_ecp(ifname, &qbg->u.c); -- return 0; --} -- --/* -- * Remove a vdp22 element and delete the chain of active profiles. -- */ --static void vdp22_free_elem(struct vdp22 *vdp) --{ -- while (!LIST_EMPTY(&vdp->prof22_head)) { -- struct vsi22_profile *prof = LIST_FIRST(&vdp->prof22_head); -- -- free(prof); -- } -- LIST_REMOVE(vdp, entry); -- free(vdp); --} -- --/* -- * Disable the interface for VDP protocol support. -- */ --void vdp22_stop(char *ifname) --{ -- struct vdp22_user_data *vud; -- struct vdp22 *vdp; -- -- LLDPAD_DBG("%s:%s stop vdp\n", __func__, ifname); -- vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); -- if (!vud) { -- LLDPAD_ERR("%s:%s no VDP22 module\n", __func__, ifname); -- return; -- } -- vdp = vdp22_findif(ifname, vud); -- if (!vdp) { -- LLDPAD_ERR("%s:%s no VDP22 data\n", __func__, ifname); -- return; -- } -- vdp22_free_elem(vdp); --} -- --/* -- * vdp22_create - create data structure and initialize vdp protocol -- * @ifname: interface for which the vdp protocol is initialized -- * -- * returns NULL on error and an pointer to the vdp22 structure on success. -- * -- * finds the port to the interface name, sets up the receive handle for -- * incoming vdp frames and initializes the vdp rx and tx state machines. -- * To be called when a successful exchange of EVB TLVs has been -- * made and ECP protocols are supported by both sides. -- */ --static struct vdp22 *vdp22_create(const char *ifname, -- struct vdp22_user_data *eud) --{ -- struct vdp22 *vdp; -- -- vdp = calloc(1, sizeof *vdp); -- if (!vdp) { -- LLDPAD_ERR("%s:%s unable to allocate vdp protocol\n", __func__, -- ifname); -- return NULL; -- } -- strncpy(vdp->ifname, ifname, sizeof vdp->ifname); -- LIST_INIT(&vdp->prof22_head); -- LIST_INSERT_HEAD(&eud->head, vdp, entry); -- LLDPAD_DBG("%s:%s create vdp data\n", __func__, ifname); -- return vdp; --} -- --/* -- * Query the supported VDP protocol on an interface. -- */ --static struct vdp22 *vdp22_getvdp(const char *ifname) --{ -- struct vdp22_user_data *vud; -- struct vdp22 *vdp = NULL; -- -- vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); -- if (vud) -- vdp = vdp22_findif(ifname, vud); -- LLDPAD_DBG("%s:%s vdp %p\n", __func__, ifname, vdp); -- return vdp; --} -- --int vdp22_query(const char *ifname) --{ -- int rc = 0; -- -- if (vdp22_getvdp(ifname)) -- rc = 1; -- LLDPAD_DBG("%s:%s rc:%d\n", __func__, ifname, rc); -- return rc; --} -- --/* -- * Enable the interface for VDP protocol support. -- */ --void vdp22_start(const char *ifname) --{ -- struct vdp22_user_data *vud; -- struct vdp22 *vdp; -- -- LLDPAD_DBG("%s:%s start vdp\n", __func__, ifname); -- vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); -- if (!vud) { -- LLDPAD_ERR("%s:%s no VDP22 module\n", __func__, ifname); -- return; -- } -- vdp = vdp22_findif(ifname, vud); -- if (!vdp) -- vdp = vdp22_create(ifname, vud); --} -- --/* -- * Handle a VSI request from buddy. -- */ --int vdp22_request(struct vdpnl_vsi *vsi) --{ -- int rc = -ENODEV; -- LLDPAD_DBG("%s:%s rc:%d\n", __func__, vsi->ifname, rc); -- return rc; --} -- --/* -- * Remove all interface/agent specific vdp data. -- */ --static void vdp22_free_data(struct vdp22_user_data *ud) --{ -- if (ud) { -- while (!LIST_EMPTY(&ud->head)) { -- struct vdp22 *vd = LIST_FIRST(&ud->head); -- -- vdp22_free_elem(vd); -- } -- } --} -- --void vdp22_unregister(struct lldp_module *mod) --{ -- if (mod->data) { -- vdp22_free_data((struct vdp22_user_data *)mod->data); -- free(mod->data); -- } -- free(mod); -- LLDPAD_DBG("%s:done\n", __func__); --} -- --static const struct lldp_mod_ops vdp22_ops = { -- .lldp_mod_register = vdp22_register, -- .lldp_mod_unregister = vdp22_unregister, -- .lldp_mod_notify = vdp22_notify --}; -- --struct lldp_module *vdp22_register(void) --{ -- struct lldp_module *mod; -- struct vdp22_user_data *ud; -- -- mod = calloc(1, sizeof *mod); -- if (!mod) { -- LLDPAD_ERR("%s: failed to malloc module data\n", __func__); -- return NULL; -- } -- ud = calloc(1, sizeof *ud); -- if (!ud) { -- free(mod); -- LLDPAD_ERR("%s failed to malloc module user data\n", __func__); -- return NULL; -- } -- LIST_INIT(&ud->head); -- mod->id = LLDP_MOD_VDP22; -- mod->ops = &vdp22_ops; -- mod->data = ud; -- LLDPAD_DBG("%s:done\n", __func__); -- return mod; --} -diff --git a/qbg/lldp_vdpnl.c b/qbg/lldp_vdpnl.c -deleted file mode 100644 -index 4a117d6..0000000 ---- a/qbg/lldp_vdpnl.c -+++ /dev/null -@@ -1,502 +0,0 @@ --/****************************************************************************** -- -- Implementation of VDP according to IEEE 802.1Qbg -- (c) Copyright IBM Corp. 2013 -- -- Author(s): Thomas Richter -- -- This program is free software; you can redistribute it and/or modify it -- under the terms and conditions of the GNU General Public License, -- version 2, as published by the Free Software Foundation. -- -- This program is distributed in the hope it will be useful, but WITHOUT -- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -- more details. -- -- You should have received a copy of the GNU General Public License along with -- this program; if not, write to the Free Software Foundation, Inc., -- 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -- -- The full GNU General Public License is included in this distribution in -- the file called "COPYING". -- --******************************************************************************/ -- --/* -- * Contains netlink message parsing for VDP protocol from libvirtd or other -- * buddies. -- */ -- --#include --#include --#include -- --#include -- --#include --#include --#include -- --#include "messages.h" --#include "lldp_vdp.h" --#include "lldp_vdp22.h" --#include "lldp_vdpnl.h" --#include "lldp_qbg_utils.h" --#include "lldp_rtnl.h" -- --static struct nla_policy ifla_vf_policy[IFLA_VF_MAX + 1] = { -- [IFLA_VF_MAC] = { .minlen = sizeof(struct ifla_vf_mac), -- .maxlen = sizeof(struct ifla_vf_mac)}, -- [IFLA_VF_VLAN] = { .minlen = sizeof(struct ifla_vf_vlan), -- .maxlen = sizeof(struct ifla_vf_vlan)}, --}; -- --static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] = { -- [IFLA_PORT_VF] = { .type = NLA_U32 }, -- [IFLA_PORT_PROFILE] = { .type = NLA_STRING }, -- [IFLA_PORT_VSI_TYPE] = { .minlen = sizeof(struct ifla_port_vsi) }, -- [IFLA_PORT_INSTANCE_UUID] = { .minlen = PORT_UUID_MAX, -- .maxlen = PORT_UUID_MAX, }, -- [IFLA_PORT_HOST_UUID] = { .minlen = PORT_UUID_MAX, -- .maxlen = PORT_UUID_MAX, }, -- [IFLA_PORT_REQUEST] = { .type = NLA_U8 }, -- [IFLA_PORT_RESPONSE] = { .type = NLA_U16 }, --}; -- --/* -- * Retrieve name of interface and its index value from the netlink messaage -- * and store it in the data structure. -- * The GETLINK message may or may not contain the IFLA_IFNAME attribute. -- * Return 0 on success and errno on error. -- */ --static int vdpnl_get(struct nlmsghdr *nlh, struct vdpnl_vsi *p) --{ -- struct nlattr *tb[IFLA_MAX + 1]; -- struct ifinfomsg *ifinfo; -- -- if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), -- (struct nlattr **)&tb, IFLA_MAX, NULL)) { -- LLDPAD_ERR("%s: error parsing GETLINK request\n", __func__); -- return -EINVAL; -- } -- -- ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh); -- p->ifindex = ifinfo->ifi_index; -- if (tb[IFLA_IFNAME]) { -- memcpy(p->ifname, (char *)RTA_DATA(tb[IFLA_IFNAME]), -- sizeof p->ifname); -- } else if (!if_indextoname(p->ifindex, p->ifname)) { -- LLDPAD_ERR("%s: ifindex %d without interface name\n", __func__, -- p->ifindex); -- return -EINVAL; -- } -- LLDPAD_DBG("%s: IFLA_IFNAME:%s ifindex:%d\n", __func__, p->ifname, -- p->ifindex); -- return 0; --} -- --static void vdpnl_show(struct vdpnl_vsi *vsi) --{ -- char instance[VDP_UUID_STRLEN + 2]; -- struct vdpnl_mac *mac; -- int i; -- -- LLDPAD_DBG("%s: IFLA_IFNAME=%s index:%d\n", __func__, vsi->ifname, -- vsi->ifindex); -- for (i = 0, mac = vsi->maclist; i < vsi->macsz; ++i, ++mac) { -- LLDPAD_DBG("%s: IFLA_VF_MAC=%2x:%2x:%2x:%2x:%2x:%2x\n", -- __func__, mac->mac[0], mac->mac[1], mac->mac[2], -- mac->mac[3], mac->mac[4], mac->mac[5]); -- LLDPAD_DBG("%s: IFLA_VF_VLAN=%d\n", __func__, mac->vlan); -- } -- LLDPAD_DBG("%s: IFLA_PORT_VSI_TYPE=mgr_id:%d type_id:%ld " -- "typeid_version:%d\n", -- __func__, vsi->vsi_mgrid, vsi->vsi_typeid, -- vsi->vsi_typeversion); -- vdp_uuid2str(vsi->vsi_uuid, instance, sizeof(instance)); -- LLDPAD_DBG("%s: IFLA_PORT_INSTANCE_UUID=%s\n", __func__, instance); -- LLDPAD_DBG("%s: IFLA_PORT_REQUEST=%d\n", __func__, vsi->request); -- LLDPAD_DBG("%s: IFLA_PORT_RESPONSE=%d\n", __func__, vsi->response); --} -- --/* -- * Parse the IFLA_IFLA_VF_PORTIFLA_VF_PORTS block of the netlink message. -- * Return zero on success and errno else. -- */ --static int vdpnl_vfports(struct nlattr *vfports, struct vdpnl_vsi *vsi) --{ -- char instance[VDP_UUID_STRLEN + 2]; -- struct nlattr *tb_vf_ports, *tb3[IFLA_PORT_MAX + 1]; -- int rem; -- -- if (!vfports) { -- LLDPAD_DBG("%s: FOUND NO IFLA_VF_PORTS\n", __func__); -- return -EINVAL; -- } -- -- nla_for_each_nested(tb_vf_ports, vfports, rem) { -- if (nla_type(tb_vf_ports) != IFLA_VF_PORT) { -- LLDPAD_DBG("%s: not a IFLA_VF_PORT skipping\n", -- __func__); -- continue; -- } -- if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb_vf_ports, -- ifla_port_policy)) { -- LLDPAD_ERR("%s: IFLA_PORT_MAX parsing failed\n", -- __func__); -- return -EINVAL; -- } -- if (tb3[IFLA_PORT_VF]) -- LLDPAD_DBG("%s: IFLA_PORT_VF=%d\n", __func__, -- *(uint32_t *) RTA_DATA(tb3[IFLA_PORT_VF])); -- if (tb3[IFLA_PORT_PROFILE]) -- LLDPAD_DBG("%s: IFLA_PORT_PROFILE=%s\n", __func__, -- (char *)RTA_DATA(tb3[IFLA_PORT_PROFILE])); -- if (tb3[IFLA_PORT_HOST_UUID]) { -- unsigned char *uuid; -- -- uuid = (unsigned char *) -- RTA_DATA(tb3[IFLA_PORT_HOST_UUID]); -- vdp_uuid2str(uuid, instance, sizeof(instance)); -- LLDPAD_DBG("%s: IFLA_PORT_HOST_UUID=%s\n", __func__, -- instance); -- } -- if (tb3[IFLA_PORT_VSI_TYPE]) { -- struct ifla_port_vsi *pvsi; -- int tid = 0; -- -- pvsi = (struct ifla_port_vsi *) -- RTA_DATA(tb3[IFLA_PORT_VSI_TYPE]); -- tid = pvsi->vsi_type_id[2] << 16 | -- pvsi->vsi_type_id[1] << 8 | -- pvsi->vsi_type_id[0]; -- vsi->vsi_mgrid = pvsi->vsi_mgr_id; -- vsi->vsi_typeversion = pvsi->vsi_type_version; -- vsi->vsi_typeid = tid; -- } -- if (tb3[IFLA_PORT_INSTANCE_UUID]) { -- unsigned char *uuid = (unsigned char *) -- RTA_DATA(tb3[IFLA_PORT_INSTANCE_UUID]); -- memcpy(vsi->vsi_uuid, uuid, sizeof vsi->vsi_uuid); -- } -- if (tb3[IFLA_PORT_REQUEST]) -- vsi->request = -- *(uint8_t *) RTA_DATA(tb3[IFLA_PORT_REQUEST]); -- if (tb3[IFLA_PORT_RESPONSE]) -- vsi->response = -- *(uint16_t *) RTA_DATA(tb3[IFLA_PORT_RESPONSE]); -- } -- return 0; --} -- --/* -- * Parse the IFLA_VFINFO_LIST block of the netlink message. -- * Return zero on success and errno else. -- */ --static int vdpnl_vfinfolist(struct nlattr *vfinfolist, struct vdpnl_vsi *vsi) --{ -- struct nlattr *le1, *vf[IFLA_VF_MAX + 1]; -- int rem; -- -- if (!vfinfolist) { -- LLDPAD_ERR("%s: IFLA_VFINFO_LIST missing\n", __func__); -- return -EINVAL; -- } -- nla_for_each_nested(le1, vfinfolist, rem) { -- if (nla_type(le1) != IFLA_VF_INFO) { -- LLDPAD_ERR("%s: parsing of IFLA_VFINFO_LIST failed\n", -- __func__); -- return -EINVAL; -- } -- if (nla_parse_nested(vf, IFLA_VF_MAX, le1, ifla_vf_policy)) { -- LLDPAD_ERR("%s: parsing of IFLA_VF_INFO failed\n", -- __func__); -- return -EINVAL; -- } -- -- if (vf[IFLA_VF_MAC]) { -- struct ifla_vf_mac *mac = RTA_DATA(vf[IFLA_VF_MAC]); -- -- memcpy(vsi->maclist->mac, mac->mac, ETH_ALEN); -- } -- -- if (vf[IFLA_VF_VLAN]) { -- struct ifla_vf_vlan *vlan = RTA_DATA(vf[IFLA_VF_VLAN]); -- -- vsi->maclist->vlan = vlan->vlan; -- } -- } -- return 0; --} -- --/* -- * Convert the SETLINK message into internal data structure. -- */ --static int vdpnl_set(struct nlmsghdr *nlh, struct vdpnl_vsi *vsi) --{ -- struct nlattr *tb[IFLA_MAX + 1]; -- struct ifinfomsg *ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh); -- int rc; -- -- if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), -- (struct nlattr **)&tb, IFLA_MAX, NULL)) { -- LLDPAD_ERR("%s: error parsing SETLINK request\n", __func__); -- return -EINVAL; -- } -- -- vsi->ifindex = ifinfo->ifi_index; -- if (tb[IFLA_IFNAME]) -- strncpy(vsi->ifname, (char *)RTA_DATA(tb[IFLA_IFNAME]), -- sizeof vsi->ifname); -- else { -- if (!if_indextoname(ifinfo->ifi_index, vsi->ifname)) { -- LLDPAD_ERR("%s: can not find name for interface %i\n", -- __func__, ifinfo->ifi_index); -- return -ENXIO; -- } -- } -- vsi->req_pid = nlh->nlmsg_pid; -- vsi->req_seq = nlh->nlmsg_seq; -- rc = vdpnl_vfinfolist(tb[IFLA_VFINFO_LIST], vsi); -- if (!rc) { -- rc = vdpnl_vfports(tb[IFLA_VF_PORTS], vsi); -- if (!rc) -- vdpnl_show(vsi); -- } -- return rc; --} -- --/* -- * Return the error code (can be zero) to the sender. Assume buffer is -- * large enough to hold the information. -- * Construct the netlink response on the input buffer. -- */ --static int vdpnl_error(int err, struct nlmsghdr *from, size_t len) --{ -- struct nlmsgerr nlmsgerr; -- -- LLDPAD_DBG("%s: error %d\n", __func__, err); -- nlmsgerr.error = err; -- nlmsgerr.msg = *from; -- memset(from, 0, len); -- from->nlmsg_type = NLMSG_ERROR; -- from->nlmsg_seq = nlmsgerr.msg.nlmsg_seq; -- from->nlmsg_pid = nlmsgerr.msg.nlmsg_pid; -- from->nlmsg_flags = 0; -- from->nlmsg_len = NLMSG_SPACE(sizeof nlmsgerr); -- memcpy(NLMSG_DATA(from), &nlmsgerr, sizeof nlmsgerr); -- return from->nlmsg_len; --} -- --/* -- * Build the first part of the netlink reply message for status inquiry. -- * It contains the header and the ifinfo data structure. -- */ --static void vdpnl_reply1(struct vdpnl_vsi *p, struct nlmsghdr *nlh, size_t len) --{ -- struct nlmsghdr to; -- struct ifinfomsg ifinfo; -- -- to.nlmsg_type = NLMSG_DONE; -- to.nlmsg_seq = nlh->nlmsg_seq; -- to.nlmsg_pid = nlh->nlmsg_pid; -- to.nlmsg_flags = 0; -- to.nlmsg_len = NLMSG_SPACE(sizeof ifinfo); -- -- memset(&ifinfo, 0, sizeof ifinfo); -- ifinfo.ifi_index = p->ifindex; -- memset(nlh, 0, len); -- memcpy(nlh, &to, sizeof to); -- memcpy(NLMSG_DATA(nlh), &ifinfo, sizeof ifinfo); --} -- --/* -- * Build the variable part of the netlink reply message for status inquiry. -- * It contains the UUID and the response field for the VSI profile. -- */ --static void vdpnl_reply2(struct vdpnl_vsi *p, struct nlmsghdr *nlh) --{ -- char instance[VDP_UUID_STRLEN + 2]; -- -- mynla_put(nlh, IFLA_PORT_INSTANCE_UUID, sizeof p->vsi_uuid, -- p->vsi_uuid); -- vdp_uuid2str(p->vsi_uuid, instance, sizeof instance); -- LLDPAD_DBG("%s: IFLA_PORT_INSTANCE_UUID=%s\n", __func__, instance); -- mynla_put_u32(nlh, IFLA_PORT_VF, PORT_SELF_VF); -- LLDPAD_DBG("%s: IFLA_PORT_VF=%d\n", __func__, PORT_SELF_VF); -- if (p->response != VDP_RESPONSE_NO_RESPONSE) { -- mynla_put_u16(nlh, IFLA_PORT_RESPONSE, p->response); -- LLDPAD_DBG("%s: IFLA_PORT_RESPONSE=%d\n", __func__, -- p->response); -- } --} -- --/* -- * Extract the interface name and loop over all VSI profile entries. -- * Find UUID and response field for each active profile and construct a -- * netlink response message. -- * -- * Return message size. -- */ --static int vdpnl_getlink(struct nlmsghdr *nlh, size_t len) --{ -- struct vdpnl_vsi p; -- int i = 0, rc; -- struct nlattr *vf_ports, *vf_port; -- -- memset(&p, 0, sizeof p); -- rc = vdpnl_get(nlh, &p); -- if (rc) -- return vdpnl_error(rc, nlh, len); -- vdpnl_reply1(&p, nlh, len); -- vf_ports = mynla_nest_start(nlh, IFLA_VF_PORTS); -- vf_port = mynla_nest_start(nlh, IFLA_VF_PORT); -- /* Iterate over all profiles */ -- do { -- rc = vdp_status(++i, &p); -- if (rc == 1) -- vdpnl_reply2(&p, nlh); -- if (rc == 0) { -- mynla_nest_end(nlh, vf_port); -- mynla_nest_end(nlh, vf_ports); -- } -- } while (rc == 1); -- if (rc < 0) -- return vdpnl_error(rc, nlh, len); -- LLDPAD_DBG("%s: message-size:%d\n", __func__, nlh->nlmsg_len); -- return nlh->nlmsg_len; --} -- --/* -- * Parse incoming command and create a data structure to store the VSI data. -- */ --static int vdpnl_setlink(struct nlmsghdr *nlh, size_t len) --{ -- int rc = -ENOMEM; -- struct vdpnl_mac mac; -- struct vdpnl_vsi p; -- -- memset(&p, 0, sizeof p); -- p.macsz = 1; -- p.maclist = &mac; -- rc = vdpnl_set(nlh, &p); -- if (!rc) -- rc = vdp22_query(p.ifname) ? vdp22_request(&p) -- : vdp_request(&p); -- return vdpnl_error(rc, nlh, len); --} -- --/* -- * Process the netlink message. Parameters are the socket, the message and -- * its length in bytes. -- * The message buffer 'buf' is used for parsing the incoming message. -- * After parsing and decoding, the outgoing message is stored in 'buf'. -- * -- * Returns: -- * < 0: Errno number when message parsing failed. -- * == 0: Message ok and no response. -- * > 0: Message ok and response returned in buf parameter. Returns bytes -- * of response. -- */ --int vdpnl_recv(unsigned char *buf, size_t buflen) --{ -- struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -- -- LLDPAD_DBG("%s: buflen:%zd nlh.nl_pid:%d nlh_type:%d nlh_seq:%d " -- "nlh_len:%d\n", __func__, buflen, nlh->nlmsg_pid, -- nlh->nlmsg_type, nlh->nlmsg_seq, nlh->nlmsg_len); -- -- switch (nlh->nlmsg_type) { -- case RTM_SETLINK: -- return vdpnl_setlink(nlh, buflen); -- case RTM_GETLINK: -- return vdpnl_getlink(nlh, buflen); -- default: -- LLDPAD_ERR("%s: unknown type %d\n", __func__, nlh->nlmsg_type); -- } -- return -ENODEV; --} -- --/* -- * Add one entry in the list of MAC,VLAN pairs. -- */ --static void add_pair(struct vdpnl_mac *mac, struct nlmsghdr *nlh) --{ -- struct nlattr *vfinfo; -- struct ifla_vf_mac ifla_vf_mac = { -- .vf = PORT_SELF_VF, -- .mac = { 0, } -- }; -- struct ifla_vf_vlan ifla_vf_vlan = { -- .vf = PORT_SELF_VF, -- .vlan = mac->vlan, -- .qos = mac->qos -- }; -- -- vfinfo = mynla_nest_start(nlh, IFLA_VF_INFO); -- memcpy(ifla_vf_mac.mac, mac->mac, sizeof mac->mac); -- mynla_put(nlh, IFLA_VF_MAC, sizeof ifla_vf_mac, &ifla_vf_mac); -- mynla_put(nlh, IFLA_VF_VLAN, sizeof ifla_vf_vlan, &ifla_vf_vlan); -- mynla_nest_end(nlh, vfinfo); --} -- --/* -- * Walk along the MAC,VLAN ID list and add each entry into the message. -- */ --static void add_mac_vlan(struct vdpnl_vsi *vsi, struct nlmsghdr *nlh) --{ -- struct nlattr *vfinfolist; -- int i; -- -- vfinfolist = mynla_nest_start(nlh, IFLA_VFINFO_LIST); -- for (i = 0; i < vsi->macsz; ++i) -- add_pair(&vsi->maclist[i], nlh); -- mynla_nest_end(nlh, vfinfolist); --} -- --/* -- * Build an unsolicited netlink message to the VSI requestor. The originator -- * is the switch abondoning the VSI profile. -- * Assumes the messages fits into an 4KB buffer. -- * Returns the message size in bytes. -- */ --int vdpnl_send(struct vdpnl_vsi *vsi) --{ -- unsigned char buf[MAX_PAYLOAD]; -- struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -- struct nlattr *vf_ports, *vf_port; -- struct ifinfomsg ifinfo; -- struct ifla_port_vsi portvsi; -- -- memset(buf, 0, sizeof buf); -- nlh->nlmsg_pid = getpid(); -- nlh->nlmsg_seq = vsi->req_seq; -- nlh->nlmsg_type = RTM_SETLINK; -- nlh->nlmsg_len = NLMSG_SPACE(sizeof ifinfo); -- -- memset(&ifinfo, 0, sizeof ifinfo); -- ifinfo.ifi_index = vsi->ifindex; -- memcpy(NLMSG_DATA(nlh), &ifinfo, sizeof ifinfo); -- mynla_put(nlh, IFLA_IFNAME, 1 + strlen(vsi->ifname), vsi->ifname); -- -- add_mac_vlan(vsi, nlh); -- portvsi.vsi_mgr_id = vsi->vsi_mgrid; -- portvsi.vsi_type_id[0] = vsi->vsi_typeid & 0xff; -- portvsi.vsi_type_id[1] = (vsi->vsi_typeid >> 8) & 0xff; -- portvsi.vsi_type_id[2] = (vsi->vsi_typeid >> 16) & 0xff; -- portvsi.vsi_type_version = vsi->vsi_typeversion; -- vf_ports = mynla_nest_start(nlh, IFLA_VF_PORTS); -- vf_port = mynla_nest_start(nlh, IFLA_VF_PORT); -- mynla_put(nlh, IFLA_PORT_VSI_TYPE, sizeof portvsi, &portvsi); -- mynla_put(nlh, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, vsi->vsi_uuid); -- mynla_put_u32(nlh, IFLA_PORT_VF, PORT_SELF_VF); -- mynla_put_u16(nlh, IFLA_PORT_REQUEST, vsi->request); -- mynla_nest_end(nlh, vf_port); -- mynla_nest_end(nlh, vf_ports); -- vdpnl_show(vsi); -- LLDPAD_DBG("%s: nlh.nl_pid:%d nlh_type:%d nlh_seq:%d nlh_len:%d\n", -- __func__, nlh->nlmsg_pid, nlh->nlmsg_type, nlh->nlmsg_seq, -- nlh->nlmsg_len); -- return event_trigger(nlh, vsi->req_pid); --} -diff --git a/qbg/vdp.c b/qbg/vdp.c -new file mode 100644 -index 0000000..074a1e1 ---- /dev/null -+++ b/qbg/vdp.c -@@ -0,0 +1,1916 @@ -+/****************************************************************************** -+ -+ Implementation of VDP according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Jens Osterkamp -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "lldp.h" -+#include "qbg_vdp.h" -+#include "qbg_vdpnl.h" -+#include "eloop.h" -+#include "lldp_evb.h" -+#include "messages.h" -+#include "config.h" -+#include "lldp_tlv.h" -+#include "qbg_vdp_cmds.h" -+#include "qbg_utils.h" -+#include "lldp_mand_clif.h" -+ -+/* Define Module id. Must match with value in lldp_vdp_clif.c */ -+#define LLDP_MOD_VDP02 ((LLDP_MOD_VDP << 8) | LLDP_VDP_SUBTYPE) -+ -+static const char * const vsi_responses[] = { -+ [VDP_RESPONSE_SUCCESS] = "success", -+ [VDP_RESPONSE_INVALID_FORMAT] = "invalid format", -+ [VDP_RESPONSE_INSUFF_RESOURCES] = "insufficient resources", -+ [VDP_RESPONSE_UNUSED_VTID] = "unused VTID", -+ [VDP_RESPONSE_VTID_VIOLATION] = "VTID violation", -+ [VDP_RESPONSE_VTID_VER_VIOLATION] = "VTID version violation", -+ [VDP_RESPONSE_OUT_OF_SYNC] = "out of sync", -+ [VDP_RESPONSE_UNKNOWN] = "unknown response", -+ [VDP_RESPONSE_NO_RESPONSE] = "no response", -+}; -+ -+const char * const vsi_states[] = { -+ [VSI_UNASSOCIATED] = "VSI_UNASSOCIATED", -+ [VSI_ASSOC_PROCESSING] = "VSI_ASSOC_PROCESSING", -+ [VSI_ASSOCIATED] = "VSI_ASSOCIATED", -+ [VSI_PREASSOC_PROCESSING] = "VSI_PREASSOC_PROCESSING", -+ [VSI_PREASSOCIATED] = "VSI_PREASSOCIATED", -+ [VSI_DEASSOC_PROCESSING] = "VSI_DEASSOC_PROCESSING", -+ [VSI_EXIT] = "VSI_EXIT", -+}; -+ -+int vdp_start_localchange_timer(struct vsi_profile *p); -+int vdp_remove_profile(struct vsi_profile *profile); -+int vdp_trigger(struct vsi_profile *profile); -+ -+void vdp_trace_profile(struct vsi_profile *p) -+{ -+ char instance[VDP_UUID_STRLEN + 2]; -+ struct mac_vlan *mac_vlan; -+ -+ vdp_uuid2str(p->instance, instance, sizeof(instance)); -+ -+ LLDPAD_DBG("profile:%p mode:%d response:%d state:%d (%s) no_nlmsg:%d" -+ " txmit:%i" -+ " mgrid:%d id:%d(%#x) version:%d %s format:%d entries:%d\n", -+ p, p->mode, p->response, p->state, vsi_states[p->state], -+ p->no_nlmsg, p->txmit, -+ p->mgrid, p->id, p->id, p->version, instance, p->format, -+ p->entries); -+ LIST_FOREACH(mac_vlan, &p->macvid_head, entry) { -+ char macbuf[MAC_ADDR_STRLEN + 1]; -+ -+ mac2str(mac_vlan->mac, macbuf, MAC_ADDR_STRLEN); -+ LLDPAD_DBG("profile:%p mac:%s vlan:%d qos:%d pid:%d seq:%d\n", -+ p, macbuf, mac_vlan->vlan, mac_vlan->qos, -+ mac_vlan->req_pid, mac_vlan->req_seq); -+ } -+} -+ -+struct vsi_profile *vdp_alloc_profile() -+{ -+ struct vsi_profile *prof; -+ -+ prof = calloc(1, sizeof *prof); -+ if (prof) -+ LIST_INIT(&prof->macvid_head); -+ return prof; -+} -+ -+/* -+ * vdp_remove_macvlan - remove all mac/vlan pairs in the profile -+ * @profile: profile to remove -+ * -+ * Remove all allocated pairs on the profile. -+ */ -+static void vdp_remove_macvlan(struct vsi_profile *profile) -+{ -+ struct mac_vlan *p; -+ -+ while ((p = LIST_FIRST(&profile->macvid_head))) { -+ LIST_REMOVE(p, entry); -+ free(p); -+ } -+} -+ -+void vdp_delete_profile(struct vsi_profile *prof) -+{ -+ vdp_remove_macvlan(prof); -+ free(prof); -+} -+ -+/* vdp_profile_equal - checks for equality of 2 profiles -+ * @p1: profile 1 -+ * @p2: profile 2 -+ * -+ * returns true if equal, false if not -+ * -+ * compares mgrid, id, version, instance 2 vsi profiles to find -+ * out if they are equal. -+ */ -+static bool vdp_profile_equal(struct vsi_profile *p1, struct vsi_profile *p2) -+{ -+ if (p1->mgrid != p2->mgrid) -+ return false; -+ -+ if (p1->id != p2->id) -+ return false; -+ -+ if (p1->version != p2->version) -+ return false; -+ -+ if (memcmp(p1->instance, p2->instance, 16)) -+ return false; -+ -+ return true; -+} -+ -+/* -+ * vdp_find_profile - Find a profile in the list of profiles already allocated -+ * -+ * Returns pointer to already allocated profile in list, 0 if not. -+ */ -+ -+struct vsi_profile *vdp_find_profile(struct vdp_data *vd, -+ struct vsi_profile *thisone) -+{ -+ struct vsi_profile *p; -+ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ if (vdp_profile_equal(p, thisone)) -+ return p; -+ } -+ return 0; -+} -+ -+/* vdp_data - searches vdp_data in the list of modules for this port -+ * @ifname: interface name to search for -+ * -+ * returns vdp_data on success, NULL on error -+ * -+ * searches the list of user_data for the VDP module user_data. -+ */ -+struct vdp_data *vdp_data(char *ifname) -+{ -+ struct vdp_user_data *ud; -+ struct vdp_data *vd = NULL; -+ -+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP02); -+ if (ud) { -+ LIST_FOREACH(vd, &ud->head, entry) { -+ if (!strncmp(ifname, vd->ifname, IFNAMSIZ)) -+ return vd; -+ } -+ } -+ return NULL; -+} -+ -+/* vdp_free_tlv - free tlv in vdp_data -+ * @vd: vdp_data -+ * -+ * no return value -+ * -+ * frees up tlv in vdp_data. used in vdp_free_data. -+ */ -+static void vdp_free_tlv(struct vdp_data *vd) -+{ -+ if (vd) { -+ FREE_UNPKD_TLV(vd, vdp); -+ } -+} -+ -+/* vdp_free_data - frees up vdp data -+ * @ud: user data structure -+ * -+ * no return value -+ * -+ * removes vd_structure from the user_data list. frees up tlv in vdp_data. -+ * used in vdp_unregister. -+ */ -+static void vdp_free_data(struct vdp_user_data *ud) -+{ -+ struct vdp_data *vd; -+ if (ud) { -+ while (!LIST_EMPTY(&ud->head)) { -+ vd = LIST_FIRST(&ud->head); -+ LIST_REMOVE(vd, entry); -+ vdp_free_tlv(vd); -+ free(vd); -+ } -+ } -+} -+ -+/* vdp_response2str - map response to string -+ * @response: response received -+ * -+ * no return value -+ * -+ * maps VDP response received for a profile to human readable string for -+ * printing. -+ */ -+const char *vdp_response2str(int response) -+{ -+ if ((response >= VDP_RESPONSE_SUCCESS) && -+ (response <= VDP_RESPONSE_OUT_OF_SYNC)) -+ return vsi_responses[response]; -+ -+ if (response == VDP_RESPONSE_NO_RESPONSE) -+ return vsi_responses[VDP_RESPONSE_NO_RESPONSE]; -+ -+ return vsi_responses[VDP_RESPONSE_UNKNOWN]; -+} -+ -+/* vdp_ack_profiles - clear ackReceived for all profiles with seqnr -+ * @vd: vd for the interface -+ * @seqnr: seqnr the ack has been received with -+ * -+ * no return value -+ * -+ * clear the ackReceived for all profiles which have been sent out with -+ * the seqnr that we now have received the ecp ack for. -+ */ -+void vdp_ack_profiles(struct vdp_data *vd, int seqnr) -+{ -+ struct vsi_profile *p; -+ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ if (p->seqnr == seqnr) { -+ p->ackReceived = false; -+ p->txmit = true; -+ } -+ } -+ -+} -+ -+/* vdp_vsis - find out number of VSIs for this interface -+ * @ifname: interfac name -+ * -+ * returns the number of VSIs -+ * -+ * walk through the list of VSIs and return the count. -+ */ -+int vdp_vsis(char *ifname) -+{ -+ struct vdp_data *vd; -+ struct vsi_profile *p; -+ int count = 0; -+ -+ vd = vdp_data(ifname); -+ -+ if (!vd) -+ return 0; -+ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ count++; -+ } -+ -+ return count; -+} -+ -+/* vdp_vsis_pending - check for pending VSIs -+ * @vd: vdp data for the interface -+ * -+ * returns the number of VSIs found -+ * -+ * walk through the list of VSIs and return the count. -+ */ -+int vdp_vsis_pending(struct vdp_data *vd) -+{ -+ struct vsi_profile *p; -+ int count = 0; -+ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ if (p->localChange && (p->txmit == false)) -+ count++; -+ } -+ -+ return count; -+} -+ -+/* vdp_somethingChangedLocal - set flag if profile has changed -+ * @profile: profile to set the flag for -+ * @flag: set the flag to true or false -+ * -+ * no return value -+ * -+ * set the localChange flag with a mode to indicate a profile has changed. -+ * used next time when a ecpdu with profiles is sent out. -+ */ -+void vdp_somethingChangedLocal(struct vsi_profile *profile, bool flag) -+{ -+ LLDPAD_DBG("%s: setting profile->localChange to %s\n", -+ __func__, (flag == true) ? "true" : "false"); -+ -+ profile->localChange = flag; -+ -+ if (flag == true) -+ vdp_start_localchange_timer(profile); -+} -+ -+/* vdp_keepaliveTimer_expired - checks for expired ack timer -+ * @profile: profile to be checked -+ * -+ * returns true or false -+ * -+ * returns value of profile->keepaliveTimerExpired, true if ack timer has -+ * expired, * false otherwise. -+ */ -+static bool vdp_keepaliveTimer_expired(struct vsi_profile *profile) -+{ -+ return (profile->keepaliveTimer == 0); -+} -+ -+/* vdp_ackTimer_expired - checks for expired ack timer -+ * @profile: profile to be checked -+ * -+ * returns true or false -+ * -+ * returns value of profile->ackTimerExpired, true if ack timer has expired, -+ * false otherwise. -+ */ -+static bool vdp_ackTimer_expired(struct vsi_profile *profile) -+{ -+ return (profile->ackTimer == 0); -+} -+ -+/* vdp_localchange_handler - triggers in case of vdp_ack or on vdp -+ * localchange -+ * @eloop_data: data structure of event loop -+ * @user_ctx: user context, vdp_data here -+ * -+ * no return value -+ * -+ * called from vdp_somethingchangedlocal or vdp_ack_profiles when a change is -+ * pending. Calls the VDP station state machine. This detour is taken -+ * to not having to call the vdp code from the ecp state machine. Instead, we -+ * return to the event loop, giving other code a chance to do work. -+ */ -+void vdp_localchange_handler(UNUSED void *eloop_data, void *user_ctx) -+{ -+ struct vsi_profile *p; -+ -+ p = (struct vsi_profile *) user_ctx; -+ -+ if ((p->ackReceived) || (p->localChange)) { -+ LLDPAD_DBG("%s: p->localChange %i p->ackReceived %i\n", -+ __func__, p->localChange, p->ackReceived); -+ vdp_vsi_sm_station(p); -+ } -+} -+ -+/* -+ * vdp_stop - cancel the VDP localchange timer -+ * -+ * returns 0 on success, -1 on error -+ * -+ * cancels the VPP localchange timer when a profile has been deleted. -+ */ -+int vdp_stop_localchange_timer(struct vsi_profile *p) -+{ -+ return eloop_cancel_timeout(vdp_localchange_handler, NULL, (void *) p); -+} -+ -+/* vdp_start_localchange_timer - starts the VDP localchange timer -+ * @vd: vdp_data for the interface -+ * -+ * returns 0 on success, -1 on error -+ * -+ * starts the VPP localchange timer when a localchange has been signaled from -+ * the VDP state machine. -+ */ -+int vdp_start_localchange_timer(struct vsi_profile *p) -+{ -+ unsigned int usecs; -+ -+ usecs = VDP_LOCALCHANGE_TIMEOUT; -+ -+ return eloop_register_timeout(0, usecs, vdp_localchange_handler, NULL, -+ (void *) p); -+} -+ -+/* vdp_ack_timeout_handler - handles the ack timer expiry -+ * @eloop_data: data structure of event loop -+ * @user_ctx: user context, vdp_data here -+ * -+ * no return value -+ * -+ * called when the VDP ack timer for a profile has expired. -+ * Calls the VDP station state machine for the profile. -+ */ -+void vdp_ack_timeout_handler(UNUSED void *eloop_data, void *user_ctx) -+{ -+ struct vsi_profile *p = (struct vsi_profile *) user_ctx; -+ -+ if (p->ackTimer > 0) -+ p->ackTimer -= VDP_ACK_TIMER_DEFAULT; -+ -+ if (vdp_ackTimer_expired(p)) { -+ LLDPAD_DBG("%s: profile %#02x vdp_ackTimer_expired %i" -+ " p->ackReceived %i\n", __func__, p->instance[15], -+ vdp_ackTimer_expired(p), p->ackReceived); -+ vdp_vsi_sm_station(p); -+ } -+} -+ -+/* vdp_start_ack_timer - starts the VDP profile ack timer -+ * @profile: vsi_profile -+ * -+ * returns 0 on success, -1 on error -+ * -+ * starts the VDP profile ack timer when a profile has been handed to ecp for -+ * transmission. -+ */ -+static int vdp_start_ackTimer(struct vsi_profile *profile) -+{ -+ unsigned int usecs; -+ -+ usecs = VDP_ACK_TIMER_DEFAULT; -+ -+ profile->ackTimer = VDP_ACK_TIMER_DEFAULT; -+ -+ LLDPAD_DBG("%s: %s starting ack timer for %#02x (%i)\n", -+ __func__, profile->port->ifname, -+ profile->instance[15], profile->ackTimer); -+ -+ return eloop_register_timeout(0, usecs, vdp_ack_timeout_handler, NULL, -+ (void *)profile); -+} -+ -+/* vdp_stop_ackTimer - stops the VDP profile ack timer -+ * @vd: vdp_data for the interface -+ * -+ * returns the number of removed handlers -+ * -+ * stops the VDP tck imer. Used e.g. when the host interface goes down. -+ */ -+static int vdp_stop_ackTimer(struct vsi_profile *profile) -+{ -+ LLDPAD_DBG("%s: %s stopping ack timer for %#02x (%i)\n", __func__, -+ profile->port->ifname, profile->instance[15], -+ profile->ackTimer); -+ -+ return eloop_cancel_timeout(vdp_ack_timeout_handler, NULL, -+ (void *)profile); -+} -+ -+/* vdp_keepalive_timeout_handler - handles the keepalive timer expiry -+ * @eloop_data: data structure of event loop -+ * @user_ctx: user context, vdp_data here -+ * -+ * no return value -+ * -+ * called when the VDP keepalive timer for a profile has expired. -+ * Calls the VDP station state machine for the profile. -+ */ -+void vdp_keepalive_timeout_handler(UNUSED void *eloop_data, void *user_ctx) -+{ -+ struct vsi_profile *p = (struct vsi_profile *) user_ctx; -+ -+ if (p->keepaliveTimer > 0) -+ p->keepaliveTimer -= VDP_KEEPALIVE_TIMER_DEFAULT; -+ -+ if (vdp_keepaliveTimer_expired(p)) { -+ LLDPAD_DBG("%s: profile %#02x vdp_keepaliveTimer_expired %i" -+ " p->ackReceived %i p->ackReceived %i\n", __func__, -+ p->instance[15], vdp_keepaliveTimer_expired(p), -+ p->ackReceived, p->ackReceived); -+ vdp_vsi_sm_station(p); -+ } -+} -+ -+/* vdp_start_keepalive_timer - starts the VDP profile keepalive timer -+ * @vd: vdp_data for the interface -+ * -+ * returns 0 on success, -1 on error -+ * -+ * starts the VDP profile keepalive timer when a profile has been handed to -+ * ecp for transmission. -+ */ -+static int vdp_start_keepaliveTimer(struct vsi_profile *profile) -+{ -+ unsigned int usecs; -+ -+ usecs = VDP_KEEPALIVE_TIMER_DEFAULT; -+ -+ profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT; -+ -+ LLDPAD_DBG("%s: %s starting keepalive timer for %#02x (%i)\n", -+ __func__, profile->port->ifname, profile->instance[15], -+ profile->keepaliveTimer); -+ -+ return eloop_register_timeout(0, usecs, vdp_keepalive_timeout_handler, -+ NULL, (void *) profile); -+} -+ -+/* vdp_stop_keepalive_timer - stops the VDP profile keepalive timer -+ * @vd: vdp_data for the interface -+ * -+ * returns the number of removed handlers -+ * -+ * stops the VDP tck imer. Used e.g. when the host interface goes down. -+ */ -+static int vdp_stop_keepaliveTimer(struct vsi_profile *profile) -+{ -+ profile->keepaliveTimer = VDP_KEEPALIVE_TIMER_STOPPED; -+ -+ LLDPAD_DBG("%s: %s stopping keepalive timer for %#02x (%i)\n", -+ __func__, profile->port->ifname, -+ profile->instance[15], profile->keepaliveTimer); -+ -+ return eloop_cancel_timeout(vdp_keepalive_timeout_handler, NULL, -+ (void *) profile); -+} -+ -+static bool vdp_vsi_negative_response(struct vsi_profile *profile) -+{ -+ if ((profile->response > 0) && (profile->response < 255)) -+ return true; -+ else -+ return false; -+} -+ -+/* vdp_vsi_change_station_state - changes the VDP station sm state -+ * @profile: profile to process -+ * @newstate: new state for the sm -+ * -+ * no return value -+ * -+ * actually changes the state of the profile -+ */ -+void vdp_vsi_change_station_state(struct vsi_profile *profile, u8 newstate) -+{ -+ switch(newstate) { -+ case VSI_UNASSOCIATED: -+ break; -+ case VSI_ASSOC_PROCESSING: -+ assert((profile->state == VSI_PREASSOCIATED) || -+ (profile->state == VSI_ASSOCIATED) || -+ (profile->state == VSI_UNASSOCIATED)); -+ break; -+ case VSI_ASSOCIATED: -+ assert((profile->state == VSI_ASSOC_PROCESSING) || -+ (profile->state == VSI_ASSOCIATED)); -+ break; -+ case VSI_PREASSOC_PROCESSING: -+ assert((profile->state == VSI_PREASSOCIATED) || -+ (profile->state == VSI_ASSOCIATED) || -+ (profile->state == VSI_UNASSOCIATED)); -+ break; -+ case VSI_PREASSOCIATED: -+ assert((profile->state == VSI_PREASSOC_PROCESSING) || -+ (profile->state == VSI_PREASSOCIATED)); -+ break; -+ case VSI_DEASSOC_PROCESSING: -+ assert((profile->state == VSI_PREASSOCIATED) || -+ (profile->state == VSI_UNASSOCIATED) || -+ (profile->state == VSI_ASSOCIATED)); -+ break; -+ case VSI_EXIT: -+ assert((profile->state == VSI_ASSOC_PROCESSING) || -+ (profile->state == VSI_PREASSOC_PROCESSING) || -+ (profile->state == VSI_DEASSOC_PROCESSING) || -+ (profile->state == VSI_PREASSOCIATED) || -+ (profile->state == VSI_ASSOCIATED)); -+ break; -+ default: -+ LLDPAD_ERR("ERROR: The VDP station State Machine is broken\n"); -+ break; -+ } -+ -+ LLDPAD_DBG("%s: %s state change %s -> %s\n", __func__, -+ profile->port->ifname, vsi_states[profile->state], -+ vsi_states[newstate]); -+ -+ profile->state = newstate; -+} -+ -+/* vdp_vsi_set_station_state - sets the vdp sm station state -+ * @profile: profile to process -+ * -+ * returns true or false -+ * -+ * switches the state machine to the next state depending on the input -+ * variables. returns true or false depending on wether the state machine -+ * can be run again with the new state or can stop at the current state. -+ */ -+static bool vdp_vsi_set_station_state(struct vsi_profile *profile) -+{ -+ switch(profile->state) { -+ case VSI_UNASSOCIATED: -+ if ((profile->mode == VDP_MODE_PREASSOCIATE) || -+ (profile->mode == VDP_MODE_PREASSOCIATE_WITH_RR)) { -+ vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING); -+ vdp_somethingChangedLocal(profile, true); -+ return true; -+ } else if (profile->mode == VDP_MODE_ASSOCIATE) { -+ vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING); -+ vdp_somethingChangedLocal(profile, true); -+ return true; -+ } else if (profile->mode == VDP_MODE_DEASSOCIATE) { -+ vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING); -+ vdp_somethingChangedLocal(profile, true); -+ return true; -+ } -+ return false; -+ case VSI_ASSOC_PROCESSING: -+ if (profile->ackReceived) { -+ if (profile->response == 0) -+ vdp_vsi_change_station_state(profile, VSI_ASSOCIATED); -+ else -+ vdp_vsi_change_station_state(profile, VSI_EXIT); -+ return true; -+ } else if (!profile->ackReceived && vdp_ackTimer_expired(profile)) { -+ vdp_vsi_change_station_state(profile, VSI_EXIT); -+ return true; -+ } -+ return false; -+ case VSI_ASSOCIATED: -+ if (profile->mode == VDP_MODE_PREASSOCIATE) { -+ vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING); -+ return true; -+ } else if (profile->mode == VDP_MODE_DEASSOCIATE) { -+ vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING); -+ return true; -+ } else if (vdp_vsi_negative_response(profile)) { -+ vdp_vsi_change_station_state(profile, VSI_EXIT); -+ return true; -+ } else if (vdp_keepaliveTimer_expired(profile)) { -+ vdp_stop_keepaliveTimer(profile); -+ vdp_somethingChangedLocal(profile, true); -+ vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING); -+ return true; -+ } -+ return false; -+ case VSI_PREASSOC_PROCESSING: -+ LLDPAD_DBG("%s: profile->ackReceived %i, vdp_ackTimer %i\n", -+ __func__, profile->ackReceived, profile->ackTimer); -+ if (profile->ackReceived) { -+ if (profile->response == 0) -+ vdp_vsi_change_station_state(profile, VSI_PREASSOCIATED); -+ else -+ vdp_vsi_change_station_state(profile, VSI_EXIT); -+ return true; -+ } else if (!profile->ackReceived && vdp_ackTimer_expired(profile)) { -+ vdp_vsi_change_station_state(profile, VSI_EXIT); -+ return true; -+ } -+ return false; -+ case VSI_PREASSOCIATED: -+ if (profile->mode == VDP_MODE_ASSOCIATE) { -+ vdp_vsi_change_station_state(profile, VSI_ASSOC_PROCESSING); -+ return true; -+ } else if (profile->mode == VDP_MODE_DEASSOCIATE) { -+ vdp_vsi_change_station_state(profile, VSI_DEASSOC_PROCESSING); -+ return true; -+ } else if (vdp_keepaliveTimer_expired(profile)) { -+ vdp_stop_keepaliveTimer(profile); -+ vdp_somethingChangedLocal(profile, true); -+ vdp_vsi_change_station_state(profile, VSI_PREASSOC_PROCESSING); -+ return true; -+ } -+ return false; -+ case VSI_DEASSOC_PROCESSING: -+ if ((profile->ackReceived) || vdp_ackTimer_expired(profile) || -+ profile->remoteChange) { -+ vdp_vsi_change_station_state(profile, VSI_EXIT); -+ return true; -+ } -+ return false; -+ case VSI_EXIT: -+ return false; -+ default: -+ LLDPAD_ERR("%s: VSI state machine in invalid state %d\n", -+ profile->port->ifname, profile->state); -+ return false; -+ } -+} -+ -+/* vdp_vsi_sm_station - state machine for vdp station role -+ * @profile: profile for which the state is processed -+ * -+ * no return value -+ * -+ * runs the state machine for the station role of VDP. -+ */ -+void vdp_vsi_sm_station(struct vsi_profile *profile) -+{ -+ struct vdp_data *vd = vdp_data(profile->port->ifname); -+ int bye = 0; -+ -+ vdp_vsi_set_station_state(profile); -+ do { -+ LLDPAD_DBG("%s: %s station for %#02x - %s\n", -+ __func__, profile->port->ifname, -+ profile->instance[15], vsi_states[profile->state]); -+ -+ switch(profile->state) { -+ case VSI_UNASSOCIATED: -+ break; -+ case VSI_ASSOC_PROCESSING: -+ vdp_stop_keepaliveTimer(profile); -+ profile->response = VDP_RESPONSE_NO_RESPONSE; -+ if (profile->localChange) { -+ ecp_somethingChangedLocal(vd, true); -+ profile->ackReceived = false; -+ vdp_start_ackTimer(profile); -+ } -+ break; -+ case VSI_ASSOCIATED: -+ profile->ackReceived = false; -+ vdp_somethingChangedLocal(profile, false); -+ vdp_stop_ackTimer(profile); -+ vdp_start_keepaliveTimer(profile); -+ break; -+ case VSI_PREASSOC_PROCESSING: -+ vdp_stop_keepaliveTimer(profile); -+ profile->response = VDP_RESPONSE_NO_RESPONSE; -+ if (profile->localChange) { -+ profile->ackReceived = false; -+ ecp_somethingChangedLocal(vd, true); -+ vdp_start_ackTimer(profile); -+ } -+ break; -+ case VSI_PREASSOCIATED: -+ profile->ackReceived = false; -+ vdp_somethingChangedLocal(profile, false); -+ vdp_stop_ackTimer(profile); -+ vdp_start_keepaliveTimer(profile); -+ break; -+ case VSI_DEASSOC_PROCESSING: -+ profile->ackReceived = false; -+ vdp_stop_keepaliveTimer(profile); -+ profile->response = VDP_RESPONSE_NO_RESPONSE; -+ if (profile->localChange) { -+ profile->ackReceived = false; -+ ecp_somethingChangedLocal(vd, true); -+ vdp_start_ackTimer(profile); -+ } -+ break; -+ case VSI_EXIT: -+ if (profile->no_nlmsg && !profile->ackReceived && -+ vdp_ackTimer_expired(profile)) -+ bye = 1; -+ vdp_stop_ackTimer(profile); -+ vdp_stop_keepaliveTimer(profile); -+ vdp_stop_localchange_timer(profile); -+ if (bye) -+ vdp_remove_profile(profile); -+ else -+ vdp_trigger(profile); -+ break; -+ default: -+ LLDPAD_ERR("%s: ERROR VSI state machine in invalid state %d\n", -+ vd->ifname, profile->state); -+ } -+ } while (vdp_vsi_set_station_state(profile) == true); -+ -+} -+ -+/* vdp_advance_sm - advance state machine after update from switch -+ * -+ * no return value -+ */ -+void vdp_advance_sm(struct vdp_data *vd) -+{ -+ struct vsi_profile *p; -+ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ LLDPAD_DBG("%s: %s station for %#02x - %s ackReceived %i\n", -+ __func__, p->port->ifname, -+ p->instance[15], vsi_states[p->state], -+ p->ackReceived); -+ if (p->ackReceived) { -+ vdp_vsi_sm_station(p); -+ p->ackReceived = false; -+ } -+ } -+} -+ -+/* vdp_vsi_change_bridge_state - changes the VDP bridge sm state -+ * @profile: profile to process -+ * @newstate: new state for the sm -+ * -+ * no return value -+ * -+ * actually changes the state of the profile -+ */ -+static void vdp_vsi_change_bridge_state(struct vsi_profile *profile, -+ u8 newstate) -+{ -+ switch(newstate) { -+ case VSI_UNASSOCIATED: -+ break; -+ case VSI_ASSOC_PROCESSING: -+ assert((profile->state == VSI_UNASSOCIATED) || -+ (profile->state == VSI_PREASSOCIATED) || -+ (profile->state == VSI_ASSOCIATED)); -+ break; -+ case VSI_ASSOCIATED: -+ assert(profile->state == VSI_ASSOC_PROCESSING); -+ break; -+ case VSI_PREASSOC_PROCESSING: -+ assert((profile->state == VSI_UNASSOCIATED) || -+ (profile->state == VSI_PREASSOCIATED) || -+ (profile->state == VSI_ASSOCIATED)); -+ break; -+ case VSI_PREASSOCIATED: -+ assert(profile->state == VSI_PREASSOC_PROCESSING); -+ break; -+ case VSI_DEASSOC_PROCESSING: -+ assert((profile->state == VSI_UNASSOCIATED) || -+ (profile->state == VSI_PREASSOCIATED) || -+ (profile->state == VSI_ASSOCIATED)); -+ break; -+ case VSI_EXIT: -+ assert((profile->state == VSI_DEASSOC_PROCESSING) || -+ (profile->state == VSI_PREASSOC_PROCESSING) || -+ (profile->state == VSI_ASSOC_PROCESSING)); -+ break; -+ default: -+ LLDPAD_ERR("ERROR: The VDP bridge State Machine is broken\n"); -+ break; -+ } -+ profile->state = newstate; -+} -+ -+/* vdp_vsi_set_bridge_state - sets the vdp sm bridge state -+ * @profile: profile to process -+ * -+ * returns true or false -+ * -+ * switches the state machine to the next state depending on the input -+ * variables. returns true or false depending on wether the state machine -+ * can be run again with the new state or can stop at the current state. -+ */ -+static bool vdp_vsi_set_bridge_state(struct vsi_profile *profile) -+{ -+ switch(profile->state) { -+ case VSI_UNASSOCIATED: -+ if ((profile->mode == VDP_MODE_DEASSOCIATE)) /* || (INACTIVE)) */ { -+ vdp_vsi_change_bridge_state(profile, VSI_DEASSOC_PROCESSING); -+ return true; -+ } else if (profile->mode == VDP_MODE_ASSOCIATE) { -+ vdp_vsi_change_bridge_state(profile, VSI_ASSOC_PROCESSING); -+ return true; -+ } else if (profile->mode == VDP_MODE_PREASSOCIATE) { -+ vdp_vsi_change_bridge_state(profile, VSI_PREASSOC_PROCESSING); -+ return true; -+ } -+ return false; -+ case VSI_ASSOC_PROCESSING: -+ /* TODO: handle error case -+ if (!vsiError) || -+ (vsiError && vsiState == Assoc) { -+ */ -+ if (profile->mode == VDP_MODE_ASSOCIATE) { -+ vdp_vsi_change_bridge_state(profile, VSI_ASSOCIATED); -+ return true; -+ } -+ return false; -+ case VSI_ASSOCIATED: -+ if (profile->mode == VDP_MODE_ASSOCIATE) /* || ( INACTIVE )*/ { -+ vdp_vsi_change_bridge_state(profile, VSI_DEASSOC_PROCESSING); -+ return true; -+ } else if (profile->mode == VDP_MODE_PREASSOCIATE) { -+ vdp_vsi_change_bridge_state(profile, VSI_PREASSOC_PROCESSING); -+ return true; -+ } else if (profile->mode == VDP_MODE_ASSOCIATE) { -+ vdp_vsi_change_bridge_state(profile, VSI_ASSOC_PROCESSING); -+ return true; -+ } -+ return false; -+ case VSI_PREASSOC_PROCESSING: -+ if (profile->response != VDP_RESPONSE_SUCCESS) { -+ vdp_vsi_change_bridge_state(profile, VSI_EXIT); -+ return true; -+ } -+ vdp_vsi_change_bridge_state(profile, VSI_PREASSOCIATED); -+ return false; -+ case VSI_PREASSOCIATED: -+ if (profile->mode == VDP_MODE_ASSOCIATE) { -+ vdp_vsi_change_bridge_state(profile, VSI_ASSOC_PROCESSING); -+ return true; -+ } else if (profile->mode == VDP_MODE_DEASSOCIATE ) { -+ vdp_vsi_change_bridge_state(profile, VSI_DEASSOC_PROCESSING); -+ return true; -+ } else if (profile->mode == VDP_MODE_PREASSOCIATE ) { -+ vdp_vsi_change_bridge_state(profile, VSI_PREASSOC_PROCESSING); -+ return true; -+ } -+ return false; -+ case VSI_DEASSOC_PROCESSING: -+ vdp_vsi_change_bridge_state(profile, VSI_EXIT); -+ return false; -+ case VSI_EXIT: -+ return false; -+ default: -+ LLDPAD_ERR("%s: ERROR VSI state machine (bridge) in invalid state %d\n", -+ profile->port->ifname, profile->state); -+ return false; -+ } -+} -+ -+/* vdp_vsi_sm_bridge - state machine for vdp bridge role -+ * @profile: profile for which the state is processed -+ * -+ * no return value -+ * -+ * runs the state machine for the bridge role of VDP. -+ */ -+static void vdp_vsi_sm_bridge(struct vsi_profile *profile) -+{ -+ struct vdp_data *vd = vdp_data(profile->port->ifname); -+ -+ vdp_vsi_set_bridge_state(profile); -+ do { -+ LLDPAD_DBG("%s: %s bridge - %s\n", __func__, -+ profile->port->ifname, vsi_states[profile->state]); -+ switch(profile->state) { -+ case VSI_UNASSOCIATED: -+ break; -+ case VSI_ASSOC_PROCESSING: -+ /* TODO: vsiError = ProcRxandSetCfg(remoteTLV, localtlv, vsistate); -+ * if (vsiError) -+ * txTLV(Assoc NACK) -+ * else -+ * txTLV(Assoc ACK) -+ */ -+ break; -+ case VSI_ASSOCIATED: -+ break; -+ case VSI_PREASSOC_PROCESSING: -+ /* TODO: vsiError = ProcRxandSetCfg(remoteTLV, localtlv, vsistate); -+ * if (vsiError) -+ * txTLV(PreAssoc NACK) -+ * else -+ * txTLV(PreAssoc ACK) -+ */ -+ /* for now, we always succeed */ -+ profile->response = VDP_RESPONSE_SUCCESS; -+ ecp_rx_send_ack_frame(vd); -+ break; -+ case VSI_PREASSOCIATED: -+ LLDPAD_DBG("%s: %s\n", __func__, profile->port->ifname); -+ break; -+ case VSI_DEASSOC_PROCESSING: -+ /* TODO: txTLV(DeAssoc ACK) */ -+ break; -+ case VSI_EXIT: -+ vdp_remove_profile(profile); -+ break; -+ default: -+ LLDPAD_ERR("%s: ERROR VSI state machine in invalid state %d\n", -+ vd->ifname, profile->state); -+ } -+ } while (vdp_vsi_set_bridge_state(profile) == true); -+ -+} -+ -+/* -+ * vdp_validate_tlv - validates vsi tlvs -+ * @vdp: decoded vsi tlv -+ * -+ * Returns 0 on success, 1 on error -+ * -+ * checks the contents of an already decoded vsi tlv for inconsistencies -+ */ -+static int vdp_validate_tlv(struct tlv_info_vdp *vdp, struct unpacked_tlv *tlv) -+{ -+ int pairs = (tlv->length - sizeof *vdp) / sizeof(struct mac_vlan_p); -+ -+ if (ntoh24(vdp->oui) != OUI_IEEE_8021Qbg) { -+ LLDPAD_DBG("vdp->oui %#06x\n", ntoh24(vdp->oui)); -+ goto out_err; -+ } -+ -+ if (vdp->sub != LLDP_VDP_SUBTYPE) { -+ LLDPAD_DBG("vdp->sub %#02x\n", vdp->sub); -+ goto out_err; -+ } -+ -+ if (vdp->mode > VDP_MODE_DEASSOCIATE) { -+ LLDPAD_DBG("unknown mode %#02x in vsi tlv\n", vdp->mode); -+ goto out_err; -+ } -+ -+ if (vdp->response > VDP_RESPONSE_OUT_OF_SYNC) { -+ LLDPAD_DBG("unknown response %#02x\n", vdp->response); -+ goto out_err; -+ } -+ -+ if (vdp->format != VDP_FILTER_INFO_FORMAT_MACVID) { -+ LLDPAD_DBG("unknown format %#02x in vsi tlv\n", vdp->format); -+ goto out_err; -+ } -+ -+ if (ntohs(vdp->entries) < 1) { -+ LLDPAD_DBG("invalid # of entries %#02x in vsi tlv\n", -+ ntohs(vdp->entries)); -+ goto out_err; -+ } -+ -+ /* Check for number of entries of MAC,VLAN pairs */ -+ if (ntohs(vdp->entries) != pairs) { -+ LLDPAD_DBG("mismatching # of entries %#x/%#x in vsi tlv\n", -+ ntohs(vdp->entries), pairs); -+ goto out_err; -+ } -+ return 0; -+ -+out_err: -+ return 1; -+} -+ -+/* -+ * Create a VSI profile structure from switch response. -+ */ -+static void make_profile(struct vsi_profile *new, struct tlv_info_vdp *vdp, -+ struct unpacked_tlv *tlv) -+{ -+ int i; -+ u8 *pos = tlv->info + sizeof *vdp; -+ -+ new->mode = vdp->mode; -+ new->response = vdp->response; -+ new->mgrid = vdp->mgrid; -+ new->id = ntoh24(vdp->id); -+ new->version = vdp->version; -+ memcpy(&new->instance, &vdp->instance, sizeof new->instance); -+ new->format = vdp->format; -+ new->entries = ntohs(vdp->entries); -+ LLDPAD_DBG("%s: MAC/VLAN filter info format %u, # of entries %u\n", -+ __func__, new->format, new->entries); -+ -+ /* Add MAC,VLAN to list */ -+ for (i = 0; i < new->entries; ++i) { -+ struct mac_vlan *mac_vlan = calloc(1, sizeof(struct mac_vlan)); -+ u16 vlan; -+ char macbuf[MAC_ADDR_STRLEN + 1]; -+ -+ if (!mac_vlan) { -+ new->entries = i; -+ return; -+ } -+ memcpy(&mac_vlan->mac, pos, ETH_ALEN); -+ pos += ETH_ALEN; -+ mac2str(mac_vlan->mac, macbuf, MAC_ADDR_STRLEN); -+ memcpy(&vlan, pos, 2); -+ pos += 2; -+ mac_vlan->vlan = ntohs(vlan); -+ LLDPAD_DBG("%s: mac %s vlan %d\n", __func__, macbuf, -+ mac_vlan->vlan); -+ LIST_INSERT_HEAD(&new->macvid_head, mac_vlan, entry); -+ } -+} -+ -+/* -+ * vdp_indicate - receive VSI TLVs from ECP -+ * @port: the port on which the tlv was received -+ * @tlv: the unpacked tlv to receive -+ * -+ * Returns 0 on success -+ * -+ * receives a vsi tlv and creates a profile. Take appropriate action -+ * depending on the role of the (receive) port -+ */ -+int vdp_indicate(struct vdp_data *vd, struct unpacked_tlv *tlv) -+{ -+ struct tlv_info_vdp vdp; -+ struct vsi_profile *p, *profile; -+ struct port *port = port_find_by_ifindex(get_ifidx(vd->ifname)); -+ -+ LLDPAD_DBG("%s: indicating vdp of length %u (%zu) for %s\n", -+ __func__, tlv->length, sizeof(struct tlv_info_vdp), -+ vd->ifname); -+ -+ if (!port) { -+ LLDPAD_ERR("%s: port not found for %s\n", __func__, -+ vd->ifname); -+ goto out_err; -+ } -+ -+ memset(&vdp, 0, sizeof vdp); -+ /* copy only vdp header w/o list of mac/vlan/groupid pairs */ -+ memcpy(&vdp, tlv->info, sizeof vdp); -+ -+ if (vdp_validate_tlv(&vdp, tlv)) { -+ LLDPAD_ERR("%s: invalid TLV received\n", __func__); -+ goto out_err; -+ } -+ -+ profile = vdp_alloc_profile(); -+ if (!profile) { -+ LLDPAD_ERR("%s: unable to allocate profile\n", __func__); -+ goto out_err; -+ } -+ make_profile(profile, &vdp, tlv); -+ -+ profile->port = port; -+ -+ if (vd->role == VDP_ROLE_STATION) { -+ /* do we have the profile already ? */ -+ p = vdp_find_profile(vd, profile); -+ if (p) { -+ LLDPAD_DBG("%s: station profile found localChange %i " -+ "ackReceived %i no_nlmsg:%d\n", -+ __func__, p->localChange, p->ackReceived, -+ p->no_nlmsg); -+ -+ if (profile->mode == VDP_MODE_DEASSOCIATE && -+ (p->response == VDP_RESPONSE_NO_RESPONSE || -+ p->response == VDP_RESPONSE_SUCCESS) && -+ p->mode == VDP_MODE_PREASSOCIATE) { -+ LLDPAD_DBG("%s: ignore dis-associate request " -+ "in pre-association\n", __func__); -+ vdp_delete_profile(profile); -+ return 0; -+ } -+ -+ p->ackReceived = true; -+ p->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT; -+ if (profile->mode != p->mode) { -+ p->mode = profile->mode; -+ p->remoteChange = true; -+ if (profile->mode == VDP_MODE_DEASSOCIATE) -+ p->no_nlmsg = 0; -+ } else -+ p->remoteChange = false; -+ p->response = profile->response; -+ LLDPAD_DBG("%s: remoteChange %i no_nlmsg %d mode %d\n", -+ __func__, p->remoteChange, p->no_nlmsg, -+ p->mode); -+ if (vdp_vsi_negative_response(p)) -+ p->mode = VDP_MODE_DEASSOCIATE; -+ -+ LLDPAD_DBG("%s: profile response: %s (%i) " -+ "for profile %#02x at state %s\n", -+ __func__, -+ vdp_response2str(p->response), -+ p->response, p->instance[15], -+ vsi_states[p->state]); -+ } else { -+ LLDPAD_DBG("%s: station profile not found\n", __func__); -+ } -+ vdp_delete_profile(profile); -+ } -+ -+ if (vd->role == VDP_ROLE_BRIDGE) { -+ /* do we have the profile already ? */ -+ p = vdp_find_profile(vd, profile); -+ if (p) { -+ LLDPAD_DBG("%s: bridge profile found\n", __func__); -+ vdp_delete_profile(profile); -+ } else { -+ LLDPAD_DBG("%s: bridge profile not found\n", __func__); -+ /* put it in the list */ -+ profile->state = VSI_UNASSOCIATED; -+ LIST_INSERT_HEAD(&vd->profile_head, profile, profile); -+ } -+ -+ vdp_vsi_sm_bridge(profile); -+ } -+ -+ return 0; -+ -+out_err: -+ return 1; -+} -+ -+/* -+ * vdp_bld_vsi_tlv - build the VDP VSI TLV -+ * @vd: vdp_data structure for this port -+ * @profile: profile the vsi tlv is created from -+ * -+ * Returns 0 on success, ENOMEM otherwise -+ * -+ * creates a vdp structure from an existing profile -+ */ -+static int vdp_bld_vsi_tlv(struct vdp_data *vd, struct vsi_profile *profile) -+{ -+ struct mac_vlan *mv; -+ struct mac_vlan_p *mv_p; -+ struct tlv_info_vdp *vdp; -+ int rc = 0; -+ struct unpacked_tlv *tlv = NULL; -+ int size = sizeof(struct tlv_info_vdp) + -+ profile->entries * sizeof(struct mac_vlan_p); -+ -+ vdp = malloc(size); -+ -+ if (!vdp) { -+ LLDPAD_DBG("%s: unable to allocate memory for VDP TLV\n", -+ __func__); -+ rc = ENOMEM; -+ goto out_err; -+ } -+ -+ memset(vdp, 0, size); -+ -+ hton24(vdp->oui, OUI_IEEE_8021Qbg); -+ vdp->sub = LLDP_VDP_SUBTYPE; -+ vdp->mode = profile->mode; -+ vdp->response = 0; -+ vdp->mgrid = profile->mgrid; -+ hton24(vdp->id, profile->id); -+ vdp->version = profile->version; -+ memcpy(&vdp->instance, &profile->instance, 16); -+ vdp->format = VDP_FILTER_INFO_FORMAT_MACVID; -+ vdp->entries = htons(profile->entries); -+ -+ mv_p = (struct mac_vlan_p *)(vdp + 1); -+ -+ LIST_FOREACH(mv, &profile->macvid_head, entry) { -+ memcpy(mv_p->mac, mv->mac, MAC_ADDR_LEN); -+ mv_p->vlan = htons(mv->vlan); -+ mv_p++; -+ } -+ -+ tlv = create_tlv(); -+ if (!tlv) { -+ rc = ENOMEM; -+ goto out_free; -+ } -+ -+ tlv->type = ORG_SPECIFIC_TLV; -+ tlv->length = size; -+ tlv->info = (u8 *)malloc(tlv->length); -+ if(!tlv->info) { -+ free(tlv); -+ tlv = NULL; -+ rc = ENOMEM; -+ goto out_free; -+ } -+ -+ FREE_UNPKD_TLV(vd, vdp); -+ -+ memcpy(tlv->info, vdp, tlv->length); -+ -+ vd->vdp = tlv; -+ -+out_free: -+ free(vdp); -+ -+out_err: -+ return rc; -+} -+ -+/* vdp_bld_tlv - builds a tlv from a profile -+ * @vd: vdp_data structure for this port -+ * @profile: profile the vsi tlv is created from -+ * -+ * returns 0 on success, != 0 on error -+ * -+ * wrapper function around vdp_bld_vsi_tlv. adds some checks and calls -+ * vdp_bld_vsi_tlv. -+ */ -+ -+static int vdp_bld_tlv(struct vdp_data *vd, struct vsi_profile *profile) -+{ -+ if (!port_find_by_ifindex(get_ifidx(vd->ifname))) -+ return -EEXIST; -+ -+ if (vdp_bld_vsi_tlv(vd, profile)) { -+ LLDPAD_ERR("%s: %s vdp_bld_vsi_tlv() failed\n", -+ __func__, vd->ifname); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* vdp_gettlv - get the tlv for a profile -+ * @port: the port on which the tlv was received -+ * @profile: profile the vsi tlv is created from -+ * -+ * returns 0 on success -+ * -+ * this is the interface function called from ecp_build_ECPDU. It returns the -+ * packed tlv for a profile. -+ */ -+struct packed_tlv *vdp_gettlv(struct vdp_data *vd, struct vsi_profile *profile) -+{ -+ int size; -+ struct packed_tlv *ptlv = NULL; -+ -+ /* frees the unpacked_tlv in vdp_data -+ * also done in vdp_bld_vsi_tlv */ -+ vdp_free_tlv(vd); -+ -+ if (vdp_bld_tlv(vd, profile)) { -+ LLDPAD_ERR("%s: %s vdp_bld_tlv failed\n", -+ __func__, vd->ifname); -+ goto out_err; -+ } -+ -+ size = TLVSIZE(vd->vdp); -+ -+ if (!size) { -+ LLDPAD_ERR("%s: size %i of unpacked_tlv not correct\n", -+ __func__, size); -+ goto out_err; -+ } -+ -+ ptlv = create_ptlv(); -+ if (!ptlv) -+ goto out_err; -+ -+ ptlv->tlv = malloc(size); -+ if (!ptlv->tlv) -+ goto out_free; -+ -+ ptlv->size = 0; -+ PACK_TLV_AFTER(vd->vdp, ptlv, size, out_free); -+ -+ return ptlv; -+ -+out_free: -+ ptlv = free_pkd_tlv(ptlv); -+out_err: -+ LLDPAD_ERR("%s: %s failed\n", __func__, vd->ifname); -+ return NULL; -+} -+ -+/* vdp_macvlan_equal - checks for equality of 2 mac/vlan pairs -+ * @mv1: mac/vlan pair 1 -+ * @mv2: mac/vlan pair 2 -+ * -+ * returns true if equal, false if not -+ * -+ * compares mac address and vlan if they are equal. -+ */ -+bool vdp_macvlan_equal(struct mac_vlan *mv1, struct mac_vlan *mv2) -+{ -+ if (memcmp(mv1->mac, mv2->mac, MAC_ADDR_LEN)) -+ return false; -+ -+ if (mv1->vlan != mv2->vlan) -+ return false; -+ -+ return true; -+} -+ -+/* -+ * Check if the current profile already has this entry. If so take over -+ * PID and other fields. If not add this MAC,VLAN to our list. -+ * -+ * Returns 1 it the entry already exist, 0 if not. -+ */ -+static int have_macvlan(struct vsi_profile *p1, struct mac_vlan *new) -+{ -+ struct mac_vlan *mv1; -+ -+ LIST_FOREACH(mv1, &p1->macvid_head, entry) -+ if (vdp_macvlan_equal(mv1, new) == true) { -+ mv1->req_pid = new->req_pid; -+ mv1->req_seq = new->req_seq; -+ mv1->qos = new->qos; -+ return 1; -+ } -+ LIST_INSERT_HEAD(&p1->macvid_head, new, entry); -+ p1->entries++; -+ return 0; -+} -+ -+/* vdp_takeover_macvlans - take over macvlan pairs from p2 into p1 -+ * @p1: profile 1 -+ * @p2: profile 2 -+ * -+ * returns number of mac/vlan pairs taken over -+ * -+ * loops over all mac/vlan pairs in profile 2 and looks for them in profile 1. -+ * If the mac/vlan pair does not yet exist in profile 1, it adds the new pair to -+ * the list in profile 1. -+ */ -+void vdp_takeover_macvlans(struct vsi_profile *p1, struct vsi_profile *p2) -+{ -+ struct mac_vlan *mv2; -+ int count = 0; -+ -+ LLDPAD_DBG("%s: taking over mac/vlan pairs\n", __func__); -+ -+ while ((mv2 = LIST_FIRST(&p2->macvid_head))) { -+ LIST_REMOVE(mv2, entry); -+ p2->entries--; -+ if (have_macvlan(p1, mv2)) -+ free(mv2); -+ else -+ count++; -+ } -+ -+ LLDPAD_DBG("%s: %u mac/vlan pairs taken over\n", __func__, count); -+} -+ -+/* vdp_add_profile - adds a profile to a per port list -+ * @profile: profile to add -+ * -+ * returns the profile that has been found or added, NULL otherwise. -+ * -+ * main interface function which adds a profile to a list kept on a per-port -+ * basis. Checks if the profile is already in the list, adds it if necessary. -+ */ -+struct vsi_profile *vdp_add_profile(struct vdp_data *vd, -+ struct vsi_profile *profile) -+{ -+ struct vsi_profile *p; -+ -+ LLDPAD_DBG("%s: adding vdp profile for %s\n", __func__, -+ profile->port->ifname); -+ vdp_trace_profile(profile); -+ -+ /* -+ * Search this profile. If found check, -+ * if the MAC/VLAN pair already exists. If not, add it. -+ */ -+ p = vdp_find_profile(vd, profile); -+ if (p) { -+ LLDPAD_DBG("%s: profile already exists\n", __func__); -+ -+ vdp_takeover_macvlans(p, profile); -+ -+ if (p->mode != profile->mode) { -+ LLDPAD_DBG("%s: new mode %i\n", -+ __func__, profile->mode); -+ p->mode = profile->mode; -+ p->response = VDP_RESPONSE_NO_RESPONSE; -+ } -+ profile = p; -+ } else { -+ -+ /* -+ * Libvirt sends dis-assoc command and no profile active. -+ * Add to list with successful status to return the success -+ * to libvirtd when it queries for results. -+ */ -+ if (profile->mode == VDP_MODE_DEASSOCIATE) { -+ profile->response = VDP_RESPONSE_SUCCESS; -+ LLDPAD_DBG("%s: dis-assoc without profile\n", __func__); -+ } else -+ profile->response = VDP_RESPONSE_NO_RESPONSE; -+ -+ LIST_INSERT_HEAD(&vd->profile_head, profile, profile); -+ } -+ -+ if (profile->response != VDP_RESPONSE_SUCCESS) -+ vdp_somethingChangedLocal(profile, true); -+ -+ return profile; -+} -+ -+/* vdp_remove_profile - remove a profile from a per port list -+ * @profile: profile to remove -+ * -+ * returns 0 if removal was successful, -1 if removal failed -+ * -+ * function used in the state machines to remove a profile from a list kept on -+ * a per-port basis. Checks if the profile is in the list, removes it if there. -+ */ -+int vdp_remove_profile(struct vsi_profile *profile) -+{ -+ struct vsi_profile *p; -+ struct vdp_data *vd; -+ -+ LLDPAD_DBG("%s: removing vdp profile on %s\n", __func__, -+ profile->port->ifname); -+ vdp_trace_profile(profile); -+ -+ vd = vdp_data(profile->port->ifname); -+ if (!vd) { -+ LLDPAD_ERR("%s: could not find vdp_data for %s\n", __func__, -+ profile->port->ifname); -+ return -1; -+ } -+ /* Check if profile exists. If yes, remove it. */ -+ p = vdp_find_profile(vd, profile); -+ if (p) { -+ LIST_REMOVE(p, profile); -+ vdp_delete_profile(p); -+ return 0; -+ } -+ return -1; /* Not found */ -+} -+ -+/* vdp_ifdown - tear down vdp structures for a interface -+ * @ifname: name of the interface -+ * -+ * no return value -+ * -+ * interface function to lldpad. tears down vdp specific structures if -+ * interface "ifname" goes down. -+ */ -+void vdp_ifdown(char *ifname, UNUSED struct lldp_agent *agent) -+{ -+ struct vdp_data *vd; -+ struct vsi_profile *p; -+ -+ LLDPAD_DBG("%s: called on interface %s\n", __func__, ifname); -+ -+ vd = vdp_data(ifname); -+ if (!vd) -+ goto out_err; -+ -+ if (ecp_deinit(ifname)) -+ goto out_err; -+ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ if (p->ackTimer > 0) -+ vdp_stop_ackTimer(p); -+ if (p->keepaliveTimer > 0) -+ vdp_stop_keepaliveTimer(p); -+ } -+ -+ LLDPAD_INFO("%s: %s vdp data removed\n", __func__, ifname); -+ return; -+out_err: -+ LLDPAD_INFO("%s: %s vdp data remove failed\n", __func__, ifname); -+ -+ return; -+} -+ -+/* vdp_ifup - build up vdp structures for a interface -+ * @ifname: name of the interface -+ * -+ * no return value -+ * -+ * interface function to lldpad. builds up vdp specific structures if -+ * interface "ifname" goes up. -+ */ -+void vdp_ifup(char *ifname, struct lldp_agent *agent) -+{ -+ char *role; -+ char config_path[16]; -+ struct vdp_data *vd; -+ struct vdp_user_data *ud; -+ struct vsi_profile *p; -+ int enabletx = false; -+ -+ LLDPAD_DBG("%s: %s agent:%d start VDP\n", -+ __func__, ifname, agent->type); -+ -+ snprintf(config_path, sizeof(config_path), "%s.%s", -+ VDP_PREFIX, ARG_TLVTXENABLE); -+ -+ if (get_config_setting(ifname, agent->type, config_path, -+ (void *)&enabletx, CONFIG_TYPE_BOOL)) -+ enabletx = false; -+ -+ if (enabletx == false) { -+ LLDPAD_DBG("%s: %s not enabled for VDP\n", __func__, ifname); -+ return; -+ } -+ -+ vd = vdp_data(ifname); -+ if (vd) { -+ vd->enabletx = enabletx; -+ -+ LLDPAD_WARN("%s: %s vdp data already exists\n", -+ __func__, ifname); -+ goto out_start_again; -+ } -+ -+ /* not found, alloc/init per-port module data */ -+ vd = (struct vdp_data *) calloc(1, sizeof(struct vdp_data)); -+ if (!vd) { -+ LLDPAD_ERR("%s: %s malloc %zu failed\n", -+ __func__, ifname, sizeof(*vd)); -+ goto out_err; -+ } -+ strncpy(vd->ifname, ifname, IFNAMSIZ); -+ -+ vd->role = VDP_ROLE_STATION; -+ vd->enabletx = enabletx; -+ -+ if (!get_cfg(ifname, NEAREST_CUSTOMER_BRIDGE, "vdp.role", (void *)&role, -+ CONFIG_TYPE_STRING)) { -+ if (!strcasecmp(role, VAL_BRIDGE)) { -+ vd->role = VDP_ROLE_BRIDGE; -+ } -+ } -+ -+ LLDPAD_DBG("%s: configured for %s mode\n", ifname, -+ (vd->role ==VDP_ROLE_BRIDGE) ? "bridge" : "station"); -+ -+ LIST_INIT(&vd->profile_head); -+ -+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP02); -+ LIST_INSERT_HEAD(&ud->head, vd, entry); -+ -+out_start_again: -+ if (ecp_init(ifname)) { -+ LLDPAD_ERR("%s: %s unable to init ecp\n", __func__, ifname); -+ vdp_ifdown(ifname, agent); -+ goto out_err; -+ } -+ -+ vd->keepaliveTimer = VDP_KEEPALIVE_TIMER_DEFAULT; -+ vd->ackTimer = VDP_ACK_TIMER_DEFAULT; -+ -+ LLDPAD_DBG("%s: %s starting vdp timer (%i)\n", __func__, -+ vd->ifname, vd->nroftimers); -+ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ if (p->ackTimer > 0) { -+ vdp_somethingChangedLocal(p, true); -+ vdp_start_ackTimer(p); -+ } -+ if (p->keepaliveTimer > 0) -+ vdp_start_keepaliveTimer(p); -+ } -+ -+ LLDPAD_DBG("%s: %s agent:%d vdp added\n", __func__, ifname, -+ agent->type); -+ return; -+ -+out_err: -+ LLDPAD_ERR("%s: %s agent:%d vdp adding failed\n", -+ __func__, ifname, agent->type); -+} -+ -+static int vdp_client_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, -+ UNUSED socklen_t fromlen, char *ibuf, int ilen, -+ char *rbuf, int rlen) -+{ -+ return vdp_clif_cmd(ibuf, ilen, rbuf, rlen); -+} -+ -+static const struct lldp_mod_ops vdp_ops = { -+ .lldp_mod_register = vdp_register, -+ .lldp_mod_unregister = vdp_unregister, -+ .get_arg_handler = vdp_get_arg_handlers, -+ .client_cmd = vdp_client_cmd -+}; -+ -+/* vdp_register - register vdp module to lldpad -+ * @none -+ * -+ * returns lldp_module struct on success, NULL on error -+ * -+ * allocates a module structure with vdp module information and returns it -+ * to lldpad. -+ */ -+struct lldp_module *vdp_register(void) -+{ -+ struct lldp_module *mod; -+ struct vdp_user_data *ud; -+ -+ mod = malloc(sizeof(*mod)); -+ if (!mod) { -+ LLDPAD_ERR("%s: failed to start - vdp data\n", __func__); -+ return NULL; -+ } -+ ud = malloc(sizeof(struct vdp_user_data)); -+ if (!ud) { -+ free(mod); -+ LLDPAD_ERR("%s: failed to start - vdp user data\n", __func__); -+ return NULL; -+ } -+ LIST_INIT(&ud->head); -+ mod->id = LLDP_MOD_VDP02; -+ mod->ops = &vdp_ops; -+ mod->data = ud; -+ LLDPAD_DBG("%s: done\n", __func__); -+ return mod; -+} -+ -+/* vdp_unregister - unregister vdp module from lldpad -+ * @none -+ * -+ * no return value -+ * -+ * frees vdp module structure. -+ */ -+void vdp_unregister(struct lldp_module *mod) -+{ -+ if (mod->data) { -+ vdp_free_data((struct vdp_user_data *) mod->data); -+ free(mod->data); -+ } -+ free(mod); -+ LLDPAD_DBG("%s: done\n", __func__); -+} -+ -+void vdp_update(char *ifname, u8 ccap) -+{ -+ struct vdp_data *vdp = vdp_data(ifname); -+ -+ if (vdp) { -+ vdp->vdpbit_on = ccap & LLDP_EVB_CAPABILITY_PROTOCOL_VDP; -+ LLDPAD_DBG("%s:%s vdpbit_on %d\n", __func__, ifname, -+ vdp->vdpbit_on); -+ } -+} -+ -+/* -+ * Handle a VSI request from buddy. -+ */ -+int vdp_request(struct vdpnl_vsi *vsi) -+{ -+ struct vdp_data *vd; -+ struct vsi_profile *profile, *p; -+ struct port *port = port_find_by_ifindex(get_ifidx(vsi->ifname)); -+ struct mac_vlan *mac_vlan; -+ int ret = 0; -+ -+ vd = vdp_data(vsi->ifname); -+ if (!vd) { -+ LLDPAD_ERR("%s: %s has not yet been configured\n", __func__, -+ vsi->ifname); -+ return -ENXIO; -+ } -+ if (!vd->vdpbit_on) { -+ LLDPAD_ERR("%s: %s has VDP disabled\n", __func__, vsi->ifname); -+ return -ENXIO; -+ } -+ -+ if (!port) { -+ LLDPAD_ERR("%s: %s can not find port\n", __func__, vsi->ifname); -+ return -ENODEV; -+ } -+ /* If the link is down, reject request */ -+ if (!port->portEnabled && vsi->request != VDP_MODE_DEASSOCIATE) { -+ LLDPAD_WARN("%s: %s not enabled, unable to associate\n", -+ __func__, vsi->ifname); -+ return -ENXIO; -+ } -+ -+ profile = vdp_alloc_profile(); -+ if (!profile) -+ return -ENOMEM; -+ mac_vlan = calloc(1, sizeof(struct mac_vlan)); -+ if (!mac_vlan) { -+ ret = -ENOMEM; -+ goto out_err; -+ } -+ -+ profile->port = port; -+ memcpy(&mac_vlan->mac, vsi->maclist->mac, sizeof mac_vlan->mac); -+ mac_vlan->vlan = vsi->maclist->vlan; -+ mac_vlan->qos = vsi->maclist->qos; -+ mac_vlan->req_pid = vsi->req_pid; -+ mac_vlan->req_seq = vsi->req_seq; -+ LIST_INSERT_HEAD(&profile->macvid_head, mac_vlan, entry); -+ profile->entries = 1; -+ -+ profile->mgrid = vsi->vsi_mgrid; -+ profile->id = vsi->vsi_typeid; -+ profile->version = vsi->vsi_typeversion; -+ profile->mode = vsi->request; -+ profile->response = vsi->response; -+ memcpy(profile->instance, vsi->vsi_uuid, sizeof vsi->vsi_uuid); -+ p = vdp_add_profile(vd, profile); -+ p->no_nlmsg = 1; -+ p->txmit = false; -+ vdp_trace_profile(p); -+ if (p != profile) -+ goto out_err; -+ return ret; -+ -+out_err: -+ vdp_delete_profile(profile); -+ return ret; -+} -+ -+/* -+ * Query a VSI request from buddy and report its progress. Use the interface -+ * name to determine the VSI profile list. Return one entry in parameter 'vsi' -+ * use the structure members response and vsi_uuid. -+ * Returns -+ * 1 valid VSI data returned -+ * 0 end of queue (no VSI data returned) -+ * <0 errno -+ */ -+int vdp_status(int number, struct vdpnl_vsi *vsi) -+{ -+ struct vdp_data *vd; -+ struct vsi_profile *p; -+ int i = 0, ret = 0; -+ -+ vd = vdp_data(vsi->ifname); -+ if (!vd) { -+ LLDPAD_ERR("%s: %s has not yet been configured\n", __func__, -+ vsi->ifname); -+ return -ENODEV; -+ } -+ /* Interate to queue element number */ -+ LIST_FOREACH(p, &vd->profile_head, profile) { -+ if (++i == number) { -+ ret = 1; -+ break; -+ } -+ } -+ if (ret) { -+ vdp_trace_profile(p); -+ vsi->macsz = 0; -+ vsi->response = p->response; -+ memcpy(vsi->vsi_uuid, p->instance, sizeof vsi->vsi_uuid); -+ if (p->response != VDP_RESPONSE_NO_RESPONSE -+ && p->state == VSI_EXIT) -+ vdp_remove_profile(p); -+ } -+ LLDPAD_DBG("%s: entry:%d more:%d\n", __func__, number, ret); -+ return ret; -+} -+ -+/* -+ * Copy MAC-VLAN list from profile to vdpnl structure. -+ */ -+static void copy_maclist(struct vsi_profile *p, struct vdpnl_mac *macp) -+{ -+ struct mac_vlan *mv1; -+ -+ LIST_FOREACH(mv1, &p->macvid_head, entry) { -+ macp->vlan = mv1->vlan; -+ macp->qos = mv1->qos; -+ memcpy(macp->mac, mv1->mac, sizeof macp->mac); -+ ++macp; -+ } -+} -+ -+/* -+ * Prepare data for a netlink message to originator of VSI. -+ * Forward a notification from switch. -+ */ -+int vdp_trigger(struct vsi_profile *profile) -+{ -+ struct vdpnl_vsi vsi; -+ struct vdp_data *vd; -+ struct mac_vlan *macp = 0; -+ int rc = -EINVAL; -+ struct vdpnl_mac maclist[profile->entries]; -+ -+ vsi.macsz = profile->entries; -+ vsi.maclist = maclist; -+ LLDPAD_DBG("%s: no_nlmsg:%d\n", __func__, profile->no_nlmsg); -+ vdp_trace_profile(profile); -+ if (profile->no_nlmsg) -+ return 0; -+ if (LIST_EMPTY(&profile->macvid_head)) -+ return 0; -+ macp = LIST_FIRST(&profile->macvid_head); -+ if (!macp->req_pid) -+ return 0; -+ sleep(1); /* Delay message notification */ -+ if (!profile->port || !profile->port->ifname) { -+ LLDPAD_ERR("%s: no ifname found for profile %p:\n", __func__, -+ profile); -+ goto error_exit; -+ } -+ memcpy(vsi.ifname, profile->port->ifname, sizeof vsi.ifname); -+ vd = vdp_data(vsi.ifname); -+ if (!vd) { -+ LLDPAD_ERR("%s: %s could not find vdp_data\n", __func__, -+ vsi.ifname); -+ goto error_exit; -+ } -+ vsi.ifindex = if_nametoindex(vsi.ifname); -+ if (vsi.ifindex == 0) { -+ LLDPAD_ERR("%s: %s could not find index for ifname\n", -+ __func__, vsi.ifname); -+ goto error_exit; -+ } -+ vsi.macsz = profile->entries; -+ copy_maclist(profile, vsi.maclist); -+ vsi.req_pid = macp->req_pid; -+ vsi.req_seq = macp->req_seq; -+ vsi.vsi_mgrid = profile->mgrid; -+ vsi.vsi_typeid = profile->id; -+ vsi.vsi_typeversion = profile->version; -+ memcpy(vsi.vsi_uuid, profile->instance, sizeof vsi.vsi_uuid); -+ vsi.request = VDP_MODE_DEASSOCIATE; -+ rc = vdpnl_send(&vsi); -+error_exit: -+ vdp_remove_profile(profile); -+ return rc; -+} -diff --git a/qbg/vdp22.c b/qbg/vdp22.c -new file mode 100644 -index 0000000..a3cb7c9 ---- /dev/null -+++ b/qbg/vdp22.c -@@ -0,0 +1,1081 @@ -+/****************************************************************************** -+ -+ Implementation of VDP22 protocol for IEEE 802.1 Qbg ratified standard -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "messages.h" -+#include "config.h" -+ -+#include "lldp_mod.h" -+#include "lldp_util.h" -+#include "qbg_vdpnl.h" -+#include "qbg22.h" -+#include "qbg_vdp22.h" -+#include "qbg_utils.h" -+#include "qbg_vdp22_cmds.h" -+ -+/* -+ * VDP22 helper functions -+ */ -+ -+/* -+ * Convert IPv4 address to string. -+ */ -+int vdp22_ipv42str(const u8 *p, char *dst, size_t size) -+{ -+ if (dst && size > VDP_UUID_STRLEN) { -+ snprintf(dst, size, "%02x%02x:%02x%02x:%02x%02x", -+ p[10], p[11], p[12], p[13], p[14], p[15]); -+ return 0; -+ } -+ return -1; -+} -+ -+/* -+ * Convert IPv6 address to string. -+ * TODO -+ * - compression of 16 bits zero fields -+ * - omit leading zeroes -+ */ -+int vdp22_ipv62str(const u8 *p, char *dst, size_t size) -+{ -+ if (dst && size > VDP_UUID_STRLEN) { -+ snprintf(dst, size, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" -+ "%02x%02x:%02x%02x:%02x%02x:%02x%02x", -+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], -+ p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); -+ return 0; -+ } -+ return -1; -+} -+ -+static int vdp22_local2str(const u8 *p, char *dst, size_t size) -+{ -+ if (dst && size > VDP_UUID_STRLEN) { -+ snprintf(dst, size, "%02x%02x%02x%02x%02x%02x%02x%02x" -+ "%02x%02x%02x%02x%02x%02x%02x%02x", -+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], -+ p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); -+ return 0; -+ } -+ return -1; -+} -+ -+/* -+ * Print VSI filter information data. -+ */ -+static void showvsifid(char *txt, unsigned char fif, unsigned short no, -+ struct fid22 *fe) -+{ -+ char idbuf[VDP_UUID_STRLEN + 2]; -+ int i; -+ -+ for (i = 0; i < no; ++i, ++fe) { -+ switch (fif) { -+ case VDP22_FFMT_GROUPVID: -+ LLDPAD_DBG("%s:grpid:%ld vlan:%d qos:%d" -+ " pid:%d seq:%ld\n", txt, fe->grpid, -+ vdp22_get_vlanid(fe->vlan), -+ vdp22_get_qos(fe->vlan), -+ fe->requestor.req_pid, -+ fe->requestor.req_seq); -+ break; -+ case VDP22_FFMT_GROUPMACVID: -+ mac2str(fe->mac, idbuf, sizeof idbuf); -+ LLDPAD_DBG("%s:mac:%s grpid:%ld vlan:%d" -+ " qos:%d pid:%d seq:%ld\n", txt, idbuf, -+ fe->grpid, vdp22_get_vlanid(fe->vlan), -+ vdp22_get_qos(fe->vlan), -+ fe->requestor.req_pid, -+ fe->requestor.req_seq); -+ break; -+ case VDP22_FFMT_VID: -+ LLDPAD_DBG("%s:vlan:%d qos:%d pid:%d seq:%ld\n", -+ txt, vdp22_get_vlanid(fe->vlan), -+ vdp22_get_qos(fe->vlan), -+ fe->requestor.req_pid, -+ fe->requestor.req_seq); -+ break; -+ case VDP22_FFMT_MACVID: -+ mac2str(fe->mac, idbuf, sizeof idbuf); -+ LLDPAD_DBG("%s:mac:%s vlan:%d qos:%d" -+ " pid:%d seq:%ld\n", txt, idbuf, -+ vdp22_get_vlanid(fe->vlan), -+ vdp22_get_qos(fe->vlan), -+ fe->requestor.req_pid, -+ fe->requestor.req_seq); -+ break; -+ default: -+ LLDPAD_DBG("%s:unsupported filter info format\n", txt); -+ } -+ } -+} -+ -+/* -+ * Convert a mgrid to a printable string. -+ */ -+static void mgrid2str(struct vsi22 *p, char *buf, size_t len) -+{ -+ int i, nul; -+ bool print = false; -+ -+ /* Find last non nul byte */ -+ for (nul = sizeof(p->mgrid) - 1; nul >= 0; --nul) { -+ if (p->mgrid[nul] != '\0') -+ break; -+ } -+ if (nul == 0) { -+ sprintf(buf, "%d", p->mgrid[0]); -+ return; -+ } -+ for (i = 0; i <= nul; ++i) { -+ if (isprint(p->mgrid[i])) -+ print = true; -+ else -+ break; -+ } -+ if (print) -+ strncpy(buf, (char *)p->mgrid, len); -+ else -+ vdp22_local2str(p->mgrid, buf, len); -+} -+ -+/* -+ * Print VSI data -+ */ -+void vdp22_showvsi(struct vsi22 *p) -+{ -+ char idbuf[VDP_UUID_STRLEN + 2]; -+ char mgridbuf[VDP_UUID_STRLEN + 2]; -+ -+ switch (p->vsi_fmt) { -+ case VDP22_ID_UUID: -+ vdp_uuid2str(p->vsi, idbuf, sizeof(idbuf)); -+ break; -+ case VDP22_ID_MAC: -+ mac2str(p->vsi + 10, idbuf, sizeof(idbuf)); -+ break; -+ case VDP22_ID_IP4: -+ vdp22_ipv42str(p->vsi, idbuf, sizeof(idbuf)); -+ break; -+ case VDP22_ID_IP6: -+ vdp22_ipv62str(p->vsi, idbuf, sizeof(idbuf)); -+ break; -+ case VDP22_ID_LOCAL: -+ vdp22_local2str(p->vsi, idbuf, sizeof(idbuf)); -+ break; -+ default: -+ strcpy(idbuf, "unsupported format"); -+ break; -+ } -+ -+ mgrid2str(p, mgridbuf, sizeof(mgridbuf)); -+ LLDPAD_DBG("vsi:%p flags:%#lx vsi_mode:%d,%d status:%#x" -+ " mgrid:%s id:%ld(%#lx) version:%d" -+ " id_fmt:%d %s format:%d no:%d\n", -+ p, p->flags, p->vsi_mode, p->cc_vsi_mode, p->status, -+ mgridbuf, p->type_id, -+ p->type_id, p->type_ver, p->vsi_fmt, idbuf, -+ p->fif, p->no_fdata); -+ if (p->fdata) -+ showvsifid("fid", p->fif, p->no_fdata, p->fdata); -+ LLDPAD_DBG("smi:state:%d kato:%d ackreceived:%d acktimeout:%d" -+ " localchg:%d deassoc:%d txmit:%d resp_ok:%d" -+ " txmit_error:%d\n", p->smi.state, p->smi.kato, -+ p->smi.ackreceived, p->smi.acktimeout, p->smi.localchg, -+ p->smi.deassoc, p->smi.txmit, p->smi.resp_ok, -+ p->smi.txmit_error); -+} -+ -+/* -+ * Delete a complete VSI node not on queue. -+ */ -+static void vdp22_delete_vsi(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, -+ p->vsi[0]); -+ free(p->fdata); -+ free(p); -+} -+ -+/* -+ * Remove a VSI node from list and delete it. -+ */ -+void vdp22_listdel_vsi(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, -+ p->vsi[0]); -+ LIST_REMOVE(p, node); -+ vdp22_delete_vsi(p); -+} -+ -+/* Check for valid VSI request mode, filter info format and VSI ID */ -+/* -+ * Return true if data consists completely of zeroes. -+ */ -+static bool is_zeroes(unsigned char *cp, size_t len) -+{ -+ size_t x; -+ -+ for (x = 0; x < len; ++x) -+ if (*cp++) -+ return false; -+ return true; -+} -+ -+/* -+ * IPV4 address right aligned with leading zeros. -+ */ -+static bool is_ipv4(unsigned char *cp) -+{ -+ if (!is_zeroes(cp, 10)) -+ return false; -+ if (cp[10] != 0xff && cp[11] != 0xff) -+ return false; -+ if (is_zeroes(cp + 12, 4)) -+ return false; -+ return true; -+} -+ -+/* -+ * MAC address right aligned with leading zeros. -+ */ -+static bool is_mac(unsigned char *cp) -+{ -+ if (!is_zeroes(cp, 10)) -+ return false; -+ return is_valid_mac(cp + 10); -+} -+ -+/* -+ * IPV6 address. -+ */ -+static bool is_ipv6(unsigned char *cp) -+{ -+ if (is_zeroes(cp, 16)) -+ return false; -+ return true; -+} -+ -+/* -+ * Check if VSI request is valid. -+ */ -+static bool check_vsirequest(unsigned char request) -+{ -+ bool rc = true; -+ -+ switch (request) { -+ case VDP22_PREASSOC: -+ case VDP22_PREASSOC_WITH_RR: -+ case VDP22_ASSOC: -+ case VDP22_DEASSOC: -+ case VDP22_MGRID: -+ case VDP22_OUI: -+ break; -+ default: -+ rc = false; -+ } -+ LLDPAD_DBG("%s rc:%d\n", __func__, rc); -+ return rc; -+} -+ -+/* -+ * Check if VSI filter information format is valid. -+ */ -+static bool check_filterfmt(unsigned char filter_fmt) -+{ -+ bool rc = true; -+ -+ switch (filter_fmt) { -+ case VDP22_FFMT_VID: -+ case VDP22_FFMT_MACVID: -+ case VDP22_FFMT_GROUPVID: -+ case VDP22_FFMT_GROUPMACVID: -+ break; -+ default: -+ rc = false; -+ } -+ LLDPAD_DBG("%s rc:%d\n", __func__, rc); -+ return rc; -+} -+ -+/* -+ * Check if VSI identifier is valid. -+ */ -+static bool check_vsiid(unsigned char fmt, unsigned char *vsi_uuid) -+{ -+ bool rc = true; -+ -+ switch (fmt) { -+ case VDP22_ID_IP4: -+ if (!is_ipv4(vsi_uuid)) -+ rc = false; -+ break; -+ case VDP22_ID_IP6: -+ if (!is_ipv6(vsi_uuid)) -+ rc = false; -+ break; -+ case VDP22_ID_MAC: -+ if (!is_mac(vsi_uuid)) -+ rc = false; -+ break; -+ case VDP22_ID_UUID: -+ if (is_zeroes(vsi_uuid, sizeof(vsi_uuid))) -+ rc = false; -+ break; -+ case VDP22_ID_LOCAL: -+ /* Anything goes */ -+ break; -+ default: -+ rc = false; -+ } -+ LLDPAD_DBG("%s rc:%d\n", __func__, rc); -+ return rc; -+} -+ -+/* -+ * Check if VSI information received via netlink message is valid. -+ */ -+static bool check_vsinl(struct vdpnl_vsi *vsi) -+{ -+ bool rc; -+ -+ rc = check_vsiid(vsi->vsi_idfmt, vsi->vsi_uuid) -+ && check_vsirequest(vsi->request) -+ && check_filterfmt(vsi->filter_fmt); -+ LLDPAD_DBG("%s:%s request:%d filter_fmt:%d vsi_fmt:%d rc:%d\n", -+ __func__, vsi->ifname, vsi->request, vsi->filter_fmt, -+ vsi->vsi_idfmt, rc); -+ return rc; -+} -+ -+/* -+ * Check if VSI information received via TLV message is valid. -+ */ -+static bool check_vsi(struct vsi22 *vsi) -+{ -+ bool rc; -+ -+ rc = check_vsiid(vsi->vsi_fmt, vsi->vsi) -+ && check_vsirequest(vsi->vsi_mode) && check_filterfmt(vsi->fif); -+ LLDPAD_DBG("%s:%s vsi_mode:%d filter_fmt:%d vsi_fmt:%d rc:%d\n", -+ __func__, vsi->vdp->ifname, vsi->vsi_mode, vsi->fif, -+ vsi->vsi_fmt, rc); -+ return rc; -+} -+ -+/* -+ * Copy filter information data. -+ */ -+static void copy_filter(unsigned char fif, struct fid22 *fp, -+ struct vdpnl_mac *from) -+{ -+ switch (fif) { -+ case VDP22_FFMT_GROUPMACVID: -+ case VDP22_FFMT_GROUPVID: -+ fp->grpid = from->gpid; -+ if (fif == VDP22_FFMT_GROUPVID) -+ goto vid; -+ /* Fall through intended */ -+ case VDP22_FFMT_MACVID: -+ memcpy(fp->mac, from->mac, sizeof(fp->mac)); -+ /* Fall through intended */ -+ case VDP22_FFMT_VID: -+vid: -+ fp->vlan = vdp22_set_vlanid(from->vlan) -+ | vdp22_set_qos(from->qos); -+ break; -+ } -+} -+ -+/* -+ * Check supplied filter information. -+ */ -+static bool check_mac(struct fid22 *fp) -+{ -+ if (!is_valid_mac(fp->mac)) -+ return false; -+ return true; -+} -+ -+static bool check_vid(struct fid22 *fp) -+{ -+ unsigned short num = vdp22_get_vlanid(fp->vlan); -+ -+ if (num > 0 && (num < 2 || num > 4094)) -+ return false; -+ return true; -+} -+ -+static bool check_group(struct fid22 *fp) -+{ -+ return fp->grpid ? true : false; -+} -+ -+/* -+ * Check for filter information consistency. -+ */ -+static bool filter_ok(unsigned char ffmt, struct fid22 *fp, -+ unsigned char gpid_on) -+{ -+ bool rc = false; -+ -+ switch (ffmt) { -+ case VDP22_FFMT_VID: -+ rc = check_vid(fp); -+ break; -+ case VDP22_FFMT_MACVID: -+ rc = check_vid(fp) && check_mac(fp); -+ break; -+ case VDP22_FFMT_GROUPVID: -+ if (gpid_on) -+ rc = check_vid(fp) && check_group(fp); -+ else -+ rc = false; -+ break; -+ case VDP22_FFMT_GROUPMACVID: -+ if (gpid_on) -+ rc = check_vid(fp) && check_mac(fp) && -+ check_group(fp); -+ else -+ rc = false; -+ } -+ LLDPAD_DBG("%s:rc:%d\n", __func__, rc); -+ return rc; -+} -+ -+/* -+ * Allocate a VSI node with filter information data. -+ * Check if input data is valid. -+ */ -+static struct vsi22 *vdp22_alloc_vsi(struct vdpnl_vsi *vsi, struct vdp22 *vdp, -+ int *rc) -+{ -+ struct vsi22 *p; -+ int i; -+ -+ *rc = -EINVAL; -+ if (!check_vsinl(vsi)) -+ return NULL; -+ p = calloc(1, sizeof(*p)); -+ if (!p) { -+ *rc = -ENOMEM; -+ return p; -+ } -+ -+ p->no_fdata = vsi->macsz; -+ p->fdata = calloc(vsi->macsz, sizeof(struct fid22)); -+ if (!p->fdata) { -+ free(p); -+ *rc = -ENOMEM; -+ return NULL; -+ } -+ -+ p->vdp = vdp; -+ p->vsi_mode = vsi->request; -+ p->cc_vsi_mode = VDP22_DEASSOC; -+ p->hints = vsi->hints; -+ p->status = VDP22_RESP_NONE; -+ p->flags = VDP22_BUSY | VDP22_NLCMD; -+ if (vsi->nl_version == vdpnl_nlf2) -+ memcpy(p->mgrid, vsi->vsi_mgrid2, sizeof(p->mgrid)); -+ else -+ p->mgrid[0] = vsi->vsi_mgrid; -+ p->type_ver = vsi->vsi_typeversion; -+ p->type_id = vsi->vsi_typeid; -+ p->vsi_fmt = VDP22_ID_UUID; -+ memcpy(p->vsi, vsi->vsi_uuid, sizeof(p->vsi)); -+ p->fif = vsi->filter_fmt; -+ -+ /* Copy filter info and do some sanity checks based on format */ -+ for (i = 0; i < vsi->macsz; ++i) { -+ struct vdpnl_mac *from = &vsi->maclist[i]; -+ struct fid22 *fp = &p->fdata[i]; -+ -+ copy_filter(p->fif, fp, from); -+ if (from->vlan == 0) { -+ /* Only one filter member with null vlan id */ -+ if (vsi->macsz > 1 && p->fif == VDP22_FFMT_VID) { -+ *rc = -EINVAL; -+ goto error1; -+ } -+ p->flags |= VDP22_RETURN_VID; -+ } -+ if (!filter_ok(p->fif, fp, vdp->gpid)) { -+ *rc = -EINVAL; -+ goto error1; -+ } -+ fp->requestor.req_pid = vsi->req_pid; -+ fp->requestor.req_seq = vsi->req_seq; -+ } -+ *rc = 0; -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, vsi->ifname, p, p->vsi[0]); -+ return p; -+error1: -+ vdp22_showvsi(p); -+ vdp22_delete_vsi(p); -+ return NULL; -+} -+ -+/* -+ * Allocate a VSI node with filter information data. -+ * Check if input data is valid. Data was received by bridge from unknown -+ * counterpart and might be invalid. -+ */ -+struct vsi22 *vdp22_copy_vsi(struct vsi22 *old) -+{ -+ struct vsi22 *p; -+ int i; -+ -+ if (!check_vsi(old)) -+ return NULL; -+ p = calloc(1, sizeof(*p)); -+ if (!p) -+ return p; -+ *p = *old; -+ p->flags = 0; -+ p->cc_vsi_mode = VDP22_DEASSOC; -+ p->fdata = calloc(p->no_fdata, sizeof(struct fid22)); -+ if (!p->fdata) -+ goto error1; -+ -+ /* Copy filter info and do some sanity checks based on format */ -+ for (i = 0; i < p->no_fdata; ++i) { -+ p->fdata[i] = old->fdata[i]; -+ /* Only one filter member with wildcard vlan id */ -+ if (p->fdata[i].vlan == 0) { -+ if (p->no_fdata > 1 && p->fif == VDP22_FFMT_VID) -+ goto error1; -+ } -+ if (!filter_ok(p->fif, &p->fdata[i], p->vdp->gpid)) -+ goto error1; -+ } -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, -+ p->vsi[0]); -+ return p; -+error1: -+ vdp22_delete_vsi(p); -+ return NULL; -+} -+ -+/* -+ * Find the vdp data associated with an interface. -+ * Parameter 'ud' may be zero, then search for the module first. -+ * -+ * Return pointer or NULL if not found. -+ */ -+static struct vdp22 *vdp22_findif(const char *ifname, -+ struct vdp22_user_data *ud) -+{ -+ struct vdp22 *vdp = 0; -+ -+ if (!ud) { -+ ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); -+ if (!ud) -+ LLDPAD_DBG("%s:%s no VDP22 module\n", __func__, -+ ifname); -+ } -+ if (ud) { -+ LIST_FOREACH(vdp, &ud->head, node) -+ if (!strncmp(ifname, vdp->ifname, IFNAMSIZ)) -+ break; -+ } -+ return vdp; -+} -+ -+/* -+ * Update data exchanged via ECP protocol. -+ * Returns true when data update succeeded. -+ */ -+static int data_from_ecp(char *ifname, struct ecp22_to_ulp *ptr) -+{ -+ int rc = -ENOENT; -+ struct vdp22 *vdp; -+ -+ vdp = vdp22_findif(ifname, NULL); -+ if (vdp) { -+ memcpy(vdp->input, ptr->data, ptr->len); -+ vdp->input_len = ptr->len; -+ rc = vdp22_from_ecp22(vdp); -+ LLDPAD_DBG("%s:%s rc:%d ", __func__, ifname, rc); -+ } -+ return rc; -+} -+ -+/* -+ * Update data exchanged via EVB protocol. -+ * Calculate the various time out values based in input parameters. -+ * See IEEE 802.1Qbg ratified standard 41.5.5.7 + 41.5.5.9 -+ * Returns true when data update succeeded. -+ */ -+static int data_from_evb(char *ifname, struct evb22_to_vdp22 *ptr) -+{ -+ int rc = -ENOENT; -+ struct vdp22 *vdp; -+ -+ vdp = vdp22_findif(ifname, NULL); -+ if (vdp) { -+ vdp->ecp_retries = ptr->max_retry; -+ vdp->ecp_rte = ptr->max_rte; -+ vdp->vdp_rka = ptr->max_rka; -+ vdp->vdp_rwd = ptr->max_rwd; -+ vdp->gpid = ptr->gpid; -+ vdp->evbon = ptr->evbon; -+ LLDPAD_DBG("%s:%s rwd:%d rka:%d gpid:%d retry:%d rte:%d evb:%d\n", -+ __func__, ifname, ptr->max_rwd, ptr->max_rka, -+ ptr->gpid, ptr->max_retry, ptr->max_rte, ptr->evbon); -+ rc = 0; -+ } -+ return rc; -+} -+ -+/* -+ * Handle notifications from other modules. Check if sender-id and data type -+ * indicator match. Return false when data could not be delivered. -+ */ -+static int vdp22_notify(int sender_id, char *ifname, void *data) -+{ -+ struct qbg22_imm *qbg = (struct qbg22_imm *)data; -+ -+ LLDPAD_DBG("%s:%s sender-id:%#x data_type:%d\n", __func__, ifname, -+ sender_id, qbg->data_type); -+ if (sender_id == LLDP_MOD_EVB22 && qbg->data_type == EVB22_TO_VDP22) -+ return data_from_evb(ifname, &qbg->u.b); -+ if (sender_id == LLDP_MOD_ECP22 && qbg->data_type == ECP22_TO_ULP) -+ return data_from_ecp(ifname, &qbg->u.c); -+ return 0; -+} -+ -+/* -+ * Remove a vdp22 element and delete the chain of active VSIs -+ */ -+static void vdp22_free_elem(struct vdp22 *vdp) -+{ -+ while (!LIST_EMPTY(&vdp->vsi22_que)) { -+ struct vsi22 *p = LIST_FIRST(&vdp->vsi22_que); -+ -+ vdp22_listdel_vsi(p); -+ } -+ LIST_REMOVE(vdp, node); -+ free(vdp); -+} -+ -+/* -+ * Disable the interface for VDP protocol support. -+ */ -+void vdp22_stop(char *ifname) -+{ -+ struct vdp22_user_data *vud; -+ struct vdp22 *vdp; -+ struct vsi22 *vsi; -+ -+ LLDPAD_DBG("%s:%s stop vdp\n", __func__, ifname); -+ vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); -+ if (!vud) { -+ LLDPAD_ERR("%s:%s no VDP22 module\n", __func__, ifname); -+ return; -+ } -+ vdp = vdp22_findif(ifname, vud); -+ if (!vdp) { -+ LLDPAD_ERR("%s:%s no VDP22 data\n", __func__, ifname); -+ return; -+ } -+ -+ LIST_FOREACH(vsi, &vdp->vsi22_que, node) { -+ vdp22_stop_timers(vsi); -+ } -+} -+ -+/* -+ * vdp22_create - create data structure and initialize vdp protocol -+ * @ifname: interface for which the vdp protocol is initialized -+ * -+ * returns NULL on error and an pointer to the vdp22 structure on success. -+ * -+ * Finds the port to the interface name, sets up the receive handle for -+ * incoming vdp frames and initializes the vdp rx and tx state machines. -+ * To be called when a successful exchange of EVB TLVs has been -+ * made and ECP protocols are supported by both sides. -+ * -+ * Read the role (station vs bridge) from the configuration file. -+ */ -+static struct vdp22 *vdp22_create(const char *ifname, -+ struct vdp22_user_data *eud, int role) -+{ -+ struct vdp22 *vdp; -+ -+ vdp = calloc(1, sizeof *vdp); -+ if (!vdp) { -+ LLDPAD_ERR("%s:%s unable to allocate vdp protocol\n", __func__, -+ ifname); -+ return NULL; -+ } -+ strncpy(vdp->ifname, ifname, sizeof vdp->ifname); -+ vdp->myrole = role; -+ LIST_INIT(&vdp->vsi22_que); -+ LIST_INSERT_HEAD(&eud->head, vdp, node); -+ LLDPAD_DBG("%s:%s role:%d\n", __func__, ifname, role); -+ return vdp; -+} -+ -+/* -+ * Query the supported VDP protocol on an interface. -+ */ -+static struct vdp22 *vdp22_getvdp(const char *ifname) -+{ -+ struct vdp22 *vdp; -+ -+ vdp = vdp22_findif(ifname, NULL); -+ LLDPAD_DBG("%s:%s vdp %p\n", __func__, ifname, vdp); -+ return vdp; -+} -+ -+int vdp22_query(const char *ifname) -+{ -+ int rc = 0; -+ -+ if (vdp22_getvdp(ifname)) -+ rc = 1; -+ LLDPAD_DBG("%s:%s rc:%d\n", __func__, ifname, rc); -+ return rc; -+} -+ -+/* -+ * Enable the interface for VDP protocol support. -+ */ -+void vdp22_start(const char *ifname, int role) -+{ -+ struct vdp22_user_data *vud; -+ struct vdp22 *vdp; -+ struct vsi22 *vsi; -+ -+ LLDPAD_DBG("%s:%s start vdp\n", __func__, ifname); -+ vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); -+ if (!vud) { -+ LLDPAD_ERR("%s:%s no VDP22 module\n", __func__, ifname); -+ return; -+ } -+ vdp = vdp22_findif(ifname, vud); -+ -+ if (!vdp) { -+ vdp = vdp22_create(ifname, vud, role); -+ } else { -+ LIST_FOREACH(vsi, &vdp->vsi22_que, node) { -+ vsi->smi.localchg = true; -+ vdp22_showvsi(vsi); -+ vdp22_start_localchange_timer(vsi); -+ } -+ } -+} -+ -+/* -+ * Handle a VSI request from buddy. -+ */ -+int vdp22_request(struct vdpnl_vsi *vsi, int clif) -+{ -+ int rc; -+ struct vsi22 *p; -+ struct vdp22 *vdp; -+ -+ LLDPAD_DBG("%s:%s clif:%d\n", __func__, vsi->ifname, clif); -+ vdp = vdp22_findif(vsi->ifname, NULL); -+ if (vdp) { -+ if (!vdp->evbon) { -+ rc = -EPROTONOSUPPORT; -+ goto out; -+ } -+ if (vdp->myrole == VDP22_BRIDGE) { -+ rc = -EOPNOTSUPP; -+ goto out; -+ } -+ /* Adjust numbering for VDP 0.2 protocol from netlink */ -+ if (!clif) -+ vsi->request += 1; -+ p = vdp22_alloc_vsi(vsi, vdp, &rc); -+ if (p) { -+ rc = vdp22_addreq(p, vdp); -+ if (rc) -+ vdp22_delete_vsi(p); -+ } -+ } else -+ rc = -ENODEV; -+out: -+ LLDPAD_DBG("%s:%s rc:%d\n", __func__, vsi->ifname, rc); -+ return rc; -+} -+ -+/* -+ * Remove all interface/agent specific vdp data. -+ */ -+static void vdp22_free_data(struct vdp22_user_data *ud) -+{ -+ if (ud) { -+ while (!LIST_EMPTY(&ud->head)) { -+ struct vdp22 *vd = LIST_FIRST(&ud->head); -+ -+ vdp22_free_elem(vd); -+ } -+ } -+} -+ -+void vdp22_unregister(struct lldp_module *mod) -+{ -+ if (mod->data) { -+ vdp22_free_data((struct vdp22_user_data *)mod->data); -+ free(mod->data); -+ } -+ free(mod); -+ LLDPAD_DBG("%s:done\n", __func__); -+} -+ -+static int clnt(void *data, struct sockaddr_un *from, socklen_t fromlen, -+ char *ibuf, int ilen, char *rbuf, int rlen) -+{ -+ return vdp22_clif_cmd(data, from, fromlen, ibuf, ilen, rbuf, rlen); -+} -+ -+static const struct lldp_mod_ops vdp22_ops = { -+ .lldp_mod_register = vdp22_register, -+ .lldp_mod_unregister = vdp22_unregister, -+ .lldp_mod_notify = vdp22_notify, -+ .get_arg_handler = vdp22_arg_handlers, -+ .client_cmd = clnt, -+}; -+ -+struct lldp_module *vdp22_register(void) -+{ -+ struct lldp_module *mod; -+ struct vdp22_user_data *ud; -+ -+ mod = calloc(1, sizeof *mod); -+ if (!mod) { -+ LLDPAD_ERR("%s: failed to malloc module data\n", __func__); -+ return NULL; -+ } -+ ud = calloc(1, sizeof *ud); -+ if (!ud) { -+ free(mod); -+ LLDPAD_ERR("%s failed to malloc module user data\n", __func__); -+ return NULL; -+ } -+ LIST_INIT(&ud->head); -+ mod->id = LLDP_MOD_VDP22; -+ mod->ops = &vdp22_ops; -+ mod->data = ud; -+ LLDPAD_DBG("%s:done\n", __func__); -+ return mod; -+} -+ -+static void copy_fid(struct vdpnl_vsi *vsi, struct vsi22 *p) -+{ -+ int i; -+ -+ vsi->maclist = calloc(p->no_fdata, sizeof(*vsi->maclist)); -+ if (!vsi->maclist) -+ return; -+ vsi->macsz = p->no_fdata; -+ vsi->filter_fmt = p->fif; -+ for (i = 0; i < p->no_fdata; ++i) { -+ vsi->maclist[i].gpid = p->fdata[i].grpid; -+ vsi->maclist[i].vlan = vdp22_get_vlanid(p->fdata[i].vlan); -+ vsi->maclist[i].qos = vdp22_get_qos(p->fdata[i].vlan); -+ vsi->maclist[i].changed = 1; -+ memcpy(vsi->maclist[i].mac, p->fdata[i].mac, -+ sizeof(vsi->maclist[i].mac)); -+ } -+} -+ -+/* -+ * Fill the VSI data to return to caller. Currently returned data depends -+ * on requestor: -+ * 1. Via netlink message from libvirtd and vdptest: -+ * Return UUID, Response when available. changed FID. -+ * 2. Via lldptool: -+ * All data. -+ */ -+static void copy_vsi(struct vdpnl_vsi *vsi, struct vsi22 *p, int clif) -+{ -+ /* For netlink reply */ -+ vsi->response = p->status; -+ memcpy(vsi->vsi_uuid, p->vsi, sizeof(vsi->vsi_uuid)); -+ /* For client interface reply */ -+ vsi->request = p->vsi_mode; -+ vsi->vsi_typeid = p->type_id; -+ vsi->vsi_typeversion = p->type_ver; -+ memcpy(vsi->vsi_mgrid2, p->mgrid, sizeof(vsi->vsi_mgrid2)); -+ vsi->vsi_idfmt = p->vsi_fmt; -+ vsi->hints = p->cc_vsi_mode; -+ p->flags &= ~VDP22_NLCMD; -+ if (clif || (p->flags & VDP22_RETURN_VID)) { -+ copy_fid(vsi, p); -+ p->flags &= ~VDP22_RETURN_VID; -+ } -+} -+ -+/* -+ * Query a VSI request from buddy and report its progress. Use the interface -+ * name to determine the VSI profile list. Return one entry in parameter 'vsi' -+ * use the structure members response and vsi_uuid. -+ * Returns -+ * 1 valid VSI data returned -+ * 0 end of queue (no VSI data returned) -+ * <0 errno -+ */ -+int vdp22_status(int number, struct vdpnl_vsi *vsi, int clif) -+{ -+ struct vdp22 *vdp; -+ struct vsi22 *p; -+ int i = 0, ret = 0; -+ -+ LLDPAD_DBG("%s:%s clif:%d\n", __func__, vsi->ifname, clif); -+ vdp = vdp22_findif(vsi->ifname, NULL); -+ if (!vdp) { -+ LLDPAD_ERR("%s:%s has not yet been configured\n", __func__, -+ vsi->ifname); -+ return -ENODEV; -+ } -+ /* Iterate to queue element number */ -+ LIST_FOREACH(p, &vdp->vsi22_que, node) { -+ if (++i == number) { -+ ret = 1; -+ break; -+ } -+ } -+ if (ret) { -+ vdp22_showvsi(p); -+ copy_vsi(vsi, p, clif); -+ if (vsi->response != VDP22_RESP_NONE && -+ (p->flags & VDP22_DELETE_ME)) -+ vdp22_listdel_vsi(p); -+ } -+ LLDPAD_DBG("%s:%s entry:%d more:%d\n", __func__, vsi->ifname, -+ number, ret); -+ return ret; -+} -+ -+/* -+ * Find out if vsi command was received via netlink interface or via -+ * attached control interface. Pid equals zero means control interface. -+ */ -+static pid_t havepid(struct vsi22 *vsi) -+{ -+ pid_t mypid = 0; -+ int i; -+ -+ for (i = 0; i < vsi->no_fdata; ++i) -+ mypid = vsi->fdata[i].requestor.req_pid; -+ return mypid; -+} -+ -+/* -+ * Convert and VSI22 to VDP netlink format and send it back to the originator. -+ */ -+static int vdp22_back(struct vsi22 *vsi, pid_t to, -+ int (*fct)(struct vdpnl_vsi *)) -+{ -+ int i; -+ struct vdpnl_vsi nl; -+ struct vdpnl_mac nlmac[vsi->no_fdata]; -+ -+ LLDPAD_DBG("%s:%s to:%d\n", __func__, vsi->vdp->ifname, to); -+ memset(&nl, 0, sizeof(nl)); -+ memset(nlmac, 0, sizeof(nlmac)); -+ nl.maclist = nlmac; -+ nl.macsz = vsi->no_fdata; -+ memcpy(nl.ifname, vsi->vdp->ifname, sizeof(nl.ifname)); -+ nl.request = vsi->vsi_mode; -+ nl.response = vsi->status; -+ nl.vsi_mgrid = vsi->mgrid[0]; -+ memcpy(nl.vsi_mgrid2, vsi->mgrid, sizeof(nl.vsi_mgrid2)); -+ nl.vsi_typeversion = vsi->type_ver; -+ nl.vsi_typeid = vsi->type_id; -+ nl.vsi_idfmt = VDP22_ID_UUID; -+ memcpy(nl.vsi_uuid, vsi->vsi, sizeof(nl.vsi_uuid)); -+ nl.filter_fmt = vsi->fif; -+ for (i = 0; i < nl.macsz; ++i) { -+ nlmac[i].vlan = vdp22_get_vlanid(vsi->fdata[i].vlan); -+ nlmac[i].qos = vdp22_get_qos(vsi->fdata[i].vlan); -+ memcpy(nlmac[i].mac, vsi->fdata[i].mac, sizeof(nlmac[i].mac)); -+ nl.req_pid = vsi->fdata[i].requestor.req_pid; -+ nl.req_seq = vsi->fdata[i].requestor.req_seq; -+ } -+ if (to) -+ nl.request -= 1; /* Maintain old number */ -+ (*fct)(&nl); -+ if (vsi->flags & VDP22_DELETE_ME) -+ vdp22_listdel_vsi(vsi); -+ return 0; -+} -+ -+/* -+ * Send information back to netlink clients. When command was received via -+ * control interface do not send back anything. -+ */ -+int vdp22_nlback(struct vsi22 *vsi) -+{ -+ pid_t nl_pid = havepid(vsi); -+ -+ LLDPAD_DBG("%s:%s vsi:%p(%#2x) nl_pid:%d\n", __func__, vsi->vdp->ifname, -+ vsi, vsi->vsi[0], nl_pid); -+ return (nl_pid) ? vdp22_back(vsi, nl_pid, vdpnl_send) : 0; -+} -+ -+/* -+ * Send information back to attached clients. When command was received via -+ * netlink message do not send back anything. -+ */ -+int vdp22_clntback(struct vsi22 *vsi) -+{ -+ pid_t nl_pid = havepid(vsi); -+ -+ LLDPAD_DBG("%s:%s vsi:%p(%#2x) nl_pid:%d\n", __func__, vsi->vdp->ifname, -+ vsi, vsi->vsi[0], nl_pid); -+ return (!nl_pid) ? vdp22_back(vsi, 0, vdp22_sendevent) : 0; -+} -+ -+/* -+ * Query role. Return error when interface not available or interface is -+ * running in bridge mode. -+ */ -+int vdp22_info(const char *ifname) -+{ -+ int rc = 0; -+ struct vdp22 *vdp = vdp22_findif(ifname, NULL); -+ -+ if (!vdp) -+ rc = -ENODEV; -+ else if (vdp->myrole == VDP22_BRIDGE) -+ rc = -EOPNOTSUPP; -+ LLDPAD_DBG("%s:%s rc:%d\n", __func__, ifname, rc); -+ return rc; -+ -+} -diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c -new file mode 100644 -index 0000000..a75c02d ---- /dev/null -+++ b/qbg/vdp22_cmds.c -@@ -0,0 +1,489 @@ -+/******************************************************************************* -+ -+ Implementation of VDP 22 (ratified standard) according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2014 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+/* -+ * Command line interface for vdp22 module. Handle argument parsing and -+ * setting. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "lldp.h" -+#include "lldpad.h" -+#include "lldp_mod.h" -+#include "clif_msgs.h" -+#include "libconfig.h" -+#include "config.h" -+#include "messages.h" -+#include "qbg22.h" -+#include "qbg_vdp22def.h" -+#include "qbg_vdp22.h" -+#include "qbg_vdpnl.h" -+#include "qbg_vdp22_cmds.h" -+#include "qbg_vdp22_clif.h" -+ -+/* -+ * Find module we are called for. -+ */ -+static struct lldp_module *get_my_module(int thisid) -+{ -+ struct lldp_module *np = NULL; -+ -+ LIST_FOREACH(np, &lldp_head, lldp) -+ if (thisid == np->id) -+ break; -+ return np; -+} -+ -+/* -+ * Find argument handlers for module we are called for. -+ */ -+static struct arg_handlers *get_my_arghndl(int thisid) -+{ -+ struct lldp_module *np; -+ struct arg_handlers *ah = NULL; -+ -+ np = get_my_module(thisid); -+ if (np) -+ if (np->ops && np->ops->get_arg_handler) -+ ah = np->ops->get_arg_handler(); -+ return ah; -+} -+ -+static int handle_get_arg(struct cmd *cmd, char *arg, char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ struct arg_handlers *ah; -+ int rval, status = cmd_not_applicable; -+ -+ ah = get_my_arghndl(cmd->module_id); -+ if (!ah) -+ return status; -+ for (; ah->arg; ++ah) { -+ if (!ah->handle_get) -+ continue; -+ if (!strncasecmp(ah->arg, arg, strlen(ah->arg))) { -+ rval = ah->handle_get(cmd, arg, argvalue, -+ obuf, obuf_len); -+ if (rval != cmd_success && -+ rval != cmd_not_applicable) -+ return rval; -+ else if (rval == cmd_success) -+ status = rval; -+ break; -+ } -+ } -+ return status; -+} -+ -+static int handle_get(struct cmd *cmd, UNUSED char *arg, char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ struct arg_handlers *ah; -+ int rval; -+ char *nbuf; -+ int nbuf_len; -+ -+ memset(obuf, 0, obuf_len); -+ nbuf = obuf + 12; -+ nbuf_len = obuf_len - 12; -+ -+ ah = get_my_arghndl(cmd->module_id); -+ if (!ah) -+ return cmd_not_applicable; -+ for (; ah->arg; ++ah) { -+ if (strcmp(ah->arg, ARG_VDP22_VSI)) -+ continue; -+ if (ah->handle_get && (ah->arg_class == TLV_ARG)) { -+ rval = ah->handle_get(cmd, ah->arg, argvalue, -+ nbuf, nbuf_len); -+ if (rval != cmd_success && rval != cmd_not_applicable) -+ return rval; -+ -+ nbuf_len -= strlen(nbuf); -+ nbuf = nbuf + strlen(nbuf); -+ } -+ } -+ return cmd_success; -+} -+ -+static int handle_test_arg(struct cmd *cmd, char *arg, char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ struct arg_handlers *ah; -+ int rval, status = cmd_not_applicable; -+ -+ ah = get_my_arghndl(cmd->module_id); -+ if (!ah) -+ return status; -+ for (; ah->arg; ++ah) { -+ if (!strcasecmp(ah->arg, arg) && ah->handle_test) { -+ rval = ah->handle_test(cmd, ah->arg, argvalue, -+ obuf, obuf_len); -+ if (rval != cmd_not_applicable && -+ rval != cmd_success) -+ return rval; -+ else if (rval == cmd_success) -+ status = rval; -+ break; -+ } -+ } -+ return status; -+} -+ -+static int handle_set_arg(struct cmd *cmd, char *arg, char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ struct arg_handlers *ah; -+ int rval, status = cmd_not_applicable; -+ -+ ah = get_my_arghndl(cmd->module_id); -+ if (!ah) -+ return status; -+ for (; ah->arg; ++ah) { -+ if (!strcasecmp(ah->arg, arg) && ah->handle_set) { -+ rval = ah->handle_set(cmd, ah->arg, argvalue, -+ obuf, obuf_len); -+ if (rval != cmd_not_applicable && -+ rval != cmd_success) -+ return rval; -+ else if (rval == cmd_success) -+ status = rval; -+ break; -+ } -+ } -+ return status; -+} -+ -+/* -+ * Interface function called from attached client. This client can receive -+ * events from lldpad. -+ * -+ * The command string has the following format in ascii: -+ * M000080c4C3020000001c05veth0020080c40003vsi004btext -+ * aaaaaaaabbccddddddddeefffffgghhhhhhhhiijjjkkkkllll -+ * -+ * with -+ * aaaaaaaa: 8 hex digits module identifier (which has been stripped already) -+ * bb: C for command and 2 or 3 for message version number -+ * cc: 1 for get command and 2 for set command -+ * dddddddd: 8 hex digits options, supported are op_arg, op_argval, op_conifg -+ * and op_local -+ * ee: 2 hex digit length of interface name -+ * ffff: string for interface name -+ * gg: 2 hex digit for bridge type (nearest customer bridge only) -+ * hhhhhhhh: 8 hex digit TLV identifier -+ * ii: 2 hex digit length of argument name -+ * jjj: string for argument name -+ * kkkk: 4 hex digits for length of argument value -+ * llll: argument value -+ * -+ * Note the kkkk and llll fields may show up more than once. It depends. -+ * The total input length can be used to determine the number of arguaments. -+ * -+ * The member ops of struct cmd settings depends on the invoked with -+ * -T (cmd_gettlv) -a assoc: -+ * -c key --> ops=(0x15) op_config,op_arg,op_local), numargs > 0 -+ * -c key=abc --> ops=(0x1d) op_config,op_arg,op_argval,op_local), numargs > 0 -+ * -c --> ops=0x11 (op_config,op_local), numargs = 0 -+ * without -c --> ops=0x1 (op_local), numargs = 0 -+ * -+ * Without flag op_config being set invoke a function which retrieves all -+ * TLVs for pretty printing. This is currently not supported. -+ * -+ * With flag op_config being set return all currently active VSI associations. -+ */ -+int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, -+ UNUSED socklen_t fromlen, -+ char *ibuf, int ilen, char *rbuf, int rlen) -+{ -+ struct cmd cmd; -+ u8 len, version; -+ int ioff, roff; -+ int rstatus = cmd_invalid; -+ char **args; -+ char **argvals; -+ bool test_failed = false; -+ int numargs = 0; -+ int i, offset; -+ -+ memset(&cmd, 0, sizeof(cmd)); -+ cmd.module_id = LLDP_MOD_VDP22; -+ /* Pull out the command elements of the command message */ -+ hexstr2bin(ibuf + MSG_VER, (u8 *)&version, sizeof(u8)); -+ version = version >> 4; -+ hexstr2bin(ibuf + CMD_CODE, (u8 *)&cmd.cmd, sizeof(cmd.cmd)); -+ hexstr2bin(ibuf + CMD_OPS, (u8 *)&cmd.ops, sizeof(cmd.ops)); -+ cmd.ops = ntohl(cmd.ops); -+ hexstr2bin(ibuf + CMD_IF_LEN, &len, sizeof(len)); -+ ioff = CMD_IF; -+ if (len < sizeof(cmd.ifname)) -+ memcpy(cmd.ifname, ibuf+CMD_IF, len); -+ else -+ return rstatus; -+ -+ cmd.ifname[len] = '\0'; -+ ioff += len; -+ -+ if (version == CLIF_MSG_VERSION) { -+ hexstr2bin(ibuf+ioff, &cmd.type, sizeof(cmd.type)); -+ ioff += 2 * sizeof(cmd.type); -+ } else { -+ return cmd_not_applicable; -+ } -+ -+ if (cmd.cmd == cmd_gettlv || cmd.cmd == cmd_settlv) { -+ hexstr2bin(ibuf + ioff, (u8 *)&cmd.tlvid, sizeof(cmd.tlvid)); -+ cmd.tlvid = ntohl(cmd.tlvid); -+ ioff += 2 * sizeof(cmd.tlvid); -+ if (cmd.tlvid != VDP22_ASSOC && cmd.tlvid != VDP22_DEASSOC -+ && cmd.tlvid != VDP22_PREASSOC -+ && cmd.tlvid != VDP22_PREASSOC_WITH_RR) -+ return cmd_invalid; -+ } else { -+ return cmd_not_applicable; -+ } -+ -+ if (!(cmd.ops & op_config)) -+ return cmd_invalid; -+ -+ /* Count args and argvalues */ -+ offset = ioff; -+ for (numargs = 0; (ilen - offset) > 2; numargs++) { -+ offset += 2; -+ if (ilen - offset > 0) { -+ offset++; -+ if (ilen - offset > 4) -+ offset += 4; -+ } -+ } -+ -+ args = calloc(numargs, sizeof(char *)); -+ if (!args) -+ return cmd_failed; -+ -+ argvals = calloc(numargs, sizeof(char *)); -+ if (!argvals) { -+ free(args); -+ return cmd_failed; -+ } -+ -+ if ((cmd.ops & op_arg) && (cmd.ops & op_argval)) -+ numargs = get_arg_val_list(ibuf, ilen, &ioff, args, argvals); -+ else if (cmd.ops & op_arg) -+ numargs = get_arg_list(ibuf, ilen, &ioff, args); -+ -+ snprintf(rbuf, rlen, "%c%1x%02x%08x%02x%s", -+ CMD_REQUEST, CLIF_MSG_VERSION, -+ cmd.cmd, cmd.ops, -+ (unsigned int)strlen(cmd.ifname), cmd.ifname); -+ roff = strlen(rbuf); -+ -+ /* Confirm port is a valid LLDP port */ -+ if (!get_ifidx(cmd.ifname) || !is_valid_lldp_device(cmd.ifname)) { -+ free(argvals); -+ free(args); -+ return cmd_device_not_found; -+ } -+ -+ snprintf(rbuf + roff, rlen - roff, "%08x", cmd.tlvid); -+ roff += 8; -+ if (cmd.cmd == cmd_gettlv) { -+ if (!numargs) -+ rstatus = handle_get(&cmd, NULL, NULL, -+ rbuf + strlen(rbuf), -+ rlen - strlen(rbuf)); -+ else -+ for (i = 0; i < numargs; i++) -+ rstatus = handle_get_arg(&cmd, args[i], NULL, -+ rbuf + strlen(rbuf), -+ rlen - strlen(rbuf)); -+ } else { -+ for (i = 0; i < numargs; i++) { -+ rstatus = handle_test_arg(&cmd, args[i], argvals[i], -+ rbuf + strlen(rbuf), -+ rlen - strlen(rbuf)); -+ if (rstatus != cmd_not_applicable && -+ rstatus != cmd_success) -+ test_failed = true; -+ } -+ if (!test_failed) -+ for (i = 0; i < numargs; i++) -+ rstatus = handle_set_arg(&cmd, args[i], -+ argvals[i], -+ rbuf + strlen(rbuf), -+ rlen - strlen(rbuf)); -+ } -+ -+ free(argvals); -+ free(args); -+ return rstatus; -+} -+ -+/* -+ * Trigger an event to an attached client. -+ */ -+int vdp22_sendevent(struct vdpnl_vsi *p) -+{ -+ char msg[MAX_CLIF_MSGBUF]; -+ -+ vdp_vdpnl2str(p, msg, sizeof(msg)); -+ LLDPAD_DBG("%s:%s vsi:%p(%#2x), len:%zd msg:%s\n", __func__, -+ p->ifname, p, p->vsi_uuid[0], strlen(msg), msg); -+ send_event(16, LLDP_MOD_VDP22, msg); -+ return 0; -+} -+ -+static int vdp22_cmdok(struct cmd *cmd, cmd_status expected) -+{ -+ if (cmd->cmd != expected) -+ return cmd_invalid; -+ -+ switch (cmd->module_id) { -+ case LLDP_MOD_VDP22: -+ if (cmd->type != NEAREST_CUSTOMER_BRIDGE) -+ return cmd_agent_not_supported; -+ -+ return cmd_success; -+ case INVALID_TLVID: -+ return cmd_invalid; -+ default: -+ return cmd_not_applicable; -+ } -+} -+ -+/* -+ * Test if role is station and VDP protocol supported for this interface. -+ * Needed to enable testing of possible command failure. -+ */ -+static int ifok(struct cmd *cmd) -+{ -+ cmd_status good_cmd = cmd_success; -+ -+ switch (vdp22_info(cmd->ifname)) { -+ case -ENODEV: -+ good_cmd = cmd_device_not_found; -+ break; -+ case -EOPNOTSUPP: -+ good_cmd = cmd_not_applicable; -+ break; -+ } -+ return good_cmd; -+} -+ -+static int set_arg_vsi3(struct cmd *cmd, char *argvalue, bool test, int size) -+{ -+ cmd_status good_cmd = vdp22_cmdok(cmd, cmd_settlv); -+ int rc; -+ struct vdpnl_vsi vsi; -+ struct vdpnl_mac mac[size]; -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ -+ memset(&vsi, 0, sizeof(vsi)); -+ memset(&mac, 0, sizeof(mac)); -+ vsi.maclist = mac; -+ vsi.macsz = size; -+ rc = vdp_str2vdpnl(argvalue, &vsi, cmd->ifname); -+ if (rc) { -+ good_cmd = cmd_bad_params; -+ goto out; -+ } -+ if (!port_find_by_ifindex(get_ifidx(cmd->ifname))) { -+ good_cmd = cmd_device_not_found; -+ goto out; -+ } -+ good_cmd = ifok(cmd); -+ if (good_cmd != cmd_success || test) -+ goto out; -+ rc = vdp22_request(&vsi, 1); -+ if (!rc) -+ good_cmd = cmd_success; -+ else if (rc == -ENODEV) -+ good_cmd = cmd_device_not_found; -+ else -+ good_cmd = cmd_failed; -+out: -+ return good_cmd; -+} -+ -+/* -+ * Count the number of fid data fields in the argument value. -+ */ -+#define VDP22_FID_IDX 6 /* Min index of fid data */ -+static int count_fid(char *argvalue) -+{ -+ char *p = argvalue; -+ int i; -+ -+ for (i = 0; (p = strchr(p, ',')); ++i, ++p) -+ ; -+ return i + 1 - VDP22_FID_IDX; -+} -+ -+static int set_arg_vsi2(struct cmd *cmd, char *argvalue, bool test) -+{ -+ int no = count_fid(argvalue); -+ -+ if (no <= 0) -+ return -EINVAL; -+ return set_arg_vsi3(cmd, argvalue, test, no); -+} -+ -+static int set_arg_vsi(struct cmd *cmd, UNUSED char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return set_arg_vsi2(cmd, argvalue, false); -+} -+ -+static int test_arg_vsi(struct cmd *cmd, UNUSED char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return set_arg_vsi2(cmd, argvalue, true); -+} -+ -+static struct arg_handlers arg_handlers[] = { -+ { -+ .arg = ARG_VDP22_VSI, -+ .arg_class = TLV_ARG, -+ .handle_set = set_arg_vsi, -+ .handle_test = test_arg_vsi -+ }, -+ { -+ .arg = 0 -+ } -+}; -+ -+struct arg_handlers *vdp22_arg_handlers() -+{ -+ return &arg_handlers[0]; -+} -diff --git a/qbg/vdp22br.c b/qbg/vdp22br.c -new file mode 100644 -index 0000000..03bb00b ---- /dev/null -+++ b/qbg/vdp22br.c -@@ -0,0 +1,190 @@ -+/****************************************************************************** -+ -+ Implementation of VDP 2.2 bridge resource allocation simulator for LLDP -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+/* -+ * VDP22 bridge simulation code. For now return true all the time. -+ * When configured with --enable-debug option -+ * special combination of input parameters trigger errors decribed -+ * below. -+ * -+ * TODO -+ * Will be replaced by lldpad configuration file section to allow -+ * rejection and acception of VSI profiles on a configurable bases. -+ * For now this is good enough for basic state machine testing. -+ */ -+ -+#define _GNU_SOURCE -+#include -+ -+#include -+#include -+ -+#include "messages.h" -+#include "config.h" -+#include "eloop.h" -+ -+#include "qbg22.h" -+#include "qbg_vdp22.h" -+#include "qbg_utils.h" -+ -+#ifdef BUILD_DEBUG -+static unsigned char deassoc_buf[256]; -+static unsigned char ifname_buf[16]; -+static struct qbg22_imm deassoc_qbg; -+ -+static void deassoc(void *ctx, void *parm) -+{ -+ struct qbg22_imm *qbg = (struct qbg22_imm *)parm; -+ char *ifname = (char *)ctx; -+ int rc; -+ -+ rc = modules_notify(LLDP_MOD_ECP22, LLDP_MOD_VDP22, ifname, qbg); -+ LLDPAD_DBG("%s:%s leave rc:%d\n", __func__, ifname, rc); -+} -+ -+static void trigger_deassoc(struct vdp22 *vdp) -+{ -+ deassoc_qbg.data_type = VDP22_TO_ECP22; -+ deassoc_qbg.u.c.len = vdp->input_len; -+ deassoc_qbg.u.c.data = deassoc_buf; -+ memcpy(deassoc_buf, vdp->input, vdp->input_len); -+ deassoc_buf[18] = VDP22_DEASSOC << 1; /* Offset of TLV */ -+ deassoc_buf[18 + 2] = 0; -+ memcpy(ifname_buf, vdp->ifname, sizeof(ifname_buf)); -+ eloop_register_timeout(35, 0, deassoc, ifname_buf, &deassoc_qbg); -+ LLDPAD_DBG("%s:%s vdp->input_len:%d\n", __func__, vdp->ifname, -+ vdp->input_len); -+} -+ -+static void change_vlan0(struct vsi22 *p, unsigned short idx, int with_qos) -+{ -+ if (p->fif == VDP22_FFMT_MACVID) -+ p->fdata[idx].vlan = vdp22_set_vlanid(p->type_id); -+ else -+ p->fdata[idx].vlan = vdp22_set_vlanid(p->fdata[idx].grpid); -+ if (with_qos) -+ p->fdata[idx].vlan |= vdp22_set_qos(8 + (p->type_ver & 7)); -+} -+ -+static int change_fid(struct vsi22 *p) -+{ -+ unsigned short idx = p->type_ver >> 4 & 0xf; -+ -+ if (idx >= p->no_fdata) -+ return VDP22_RESP_NOADDR; -+ if (p->type_id == 204) { -+ p->fdata[idx].vlan = vdp22_set_vlanid(p->fdata[idx].grpid) -+ | vdp22_set_qos(8 + (p->type_ver & 7)); -+ } else if (p->type_id == 205) { -+ p->fdata[idx].vlan = vdp22_set_vlanid(p->type_id); -+ } else if (p->type_id == 206) { -+ p->fdata[idx].vlan = vdp22_get_vlanid(p->fdata[idx].vlan) -+ | vdp22_set_qos(8 + (p->type_ver & 7)); -+ } else if (p->type_id == 207) { -+ p->fdata[idx].vlan = vdp22_set_vlanid(p->fdata[idx].grpid); -+ } else if (p->type_id == 208 && p->fif != VDP22_FFMT_VID) { -+ int i; -+ -+ for (i = 0; i < p->no_fdata; ++i) -+ if (!vdp22_get_vlanid(p->fdata[i].vlan)) -+ change_vlan0(p, i, idx); -+ } -+ return 0; -+} -+#endif -+ -+int vdp22br_resources(struct vsi22 *p, int *error) -+{ -+ int rc = VDP22_RESP_SUCCESS; -+ static unsigned long called; -+ -+ *error = 0; -+ ++called; -+ LLDPAD_DBG("%s:%s vsi:%p(%02x) called:%ld id:%ld\n", __func__, -+ p->vdp->ifname, p, p->vsi[0], called, p->type_id); -+ rc = (p->vsi_mode == VDP22_DEASSOC) ? VDP22_RESP_DEASSOC : -+ VDP22_RESP_SUCCESS; -+#ifdef BUILD_DEBUG -+ /* -+ * Trigger errors -+ * Typeid 199 trigger delayed bridge resource availability -+ * Typeid 200 trigger de-assoc -+ * Typeid 201 trigger de-assoc error response -+ * Typeid 202 trigger keep error response with keep bit set -+ * Typeid 203 trigger de-assoc error response with hard bit set -+ * Typeid 199-202 type_ver determines when fired. -+ * -+ * Typeid 204 replace VLAN with groupid as VLAN ID and type_ver as QoS -+ * Typeid 205 replace VLAN 0 with typeid as VLAN ID -+ * Typeid 206 replace QoS 0 with type_ver as QoS -+ * Typeid 207 replace VLAN with groupid as VLAN ID -+ * For typeid 204-207 use upper nipple of type_ver as index into fid -+ * array. -+ * -+ * Typeid 208 replace all VLAN 0 -+ * - with typeid as VLAN ID (filter format MAC/VID) -+ * - with group identifier as VLAN ID (filter format GROUP/[MAC/]VID) -+ * - use upper nibble of type_ver to indicate a QoS change (true), -+ * lower nibble of type_ver is QoS value. -+ */ -+ switch (p->type_id) { -+ case 199: -+ if (called == p->type_ver) { -+ rc = VDP22_RESP_TIMEOUT; -+ } -+ break; -+ case 200: -+ trigger_deassoc(p->vdp); -+ break; -+ case 201: -+ case 203: -+ if (called == p->type_ver) { -+ *error = VDP22_RESP_NO_RESOURCES; -+ rc = VDP22_RESP_DEASSOC; -+ if (p->type_id == 203) -+ *error |= 0x10; -+ } -+ break; -+ case 202: -+ if (called == p->type_ver) { -+ *error = VDP22_RESP_NO_VSIMGR; -+ rc = VDP22_RESP_KEEP; -+ } -+ break; -+ case 204: -+ case 205: -+ case 206: -+ case 207: -+ case 208: -+ *error = change_fid(p); -+ if (*error == VDP22_RESP_NOADDR) -+ rc = VDP22_RESP_DEASSOC; -+ break; -+ } -+#endif -+ LLDPAD_DBG("%s:%s resp_vsi_mode:%d rc:%d error:%d\n", __func__, -+ p->vdp->ifname, p->resp_vsi_mode, rc, *error); -+ return rc; -+} -diff --git a/qbg/vdp22sm.c b/qbg/vdp22sm.c -new file mode 100644 -index 0000000..d1f65b4 ---- /dev/null -+++ b/qbg/vdp22sm.c -@@ -0,0 +1,1752 @@ -+/****************************************************************************** -+ -+ Implementation of VDP 2.2 bridge and station state machines for -+ IEEE 802.1 Qbg ratified standard. -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+/* -+ * Implement the IEEE 802.1Qbg ratified standard VDP Protocol state machines. -+ */ -+ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "messages.h" -+#include "config.h" -+#include "eloop.h" -+ -+#include "qbg22.h" -+#include "qbg_vdp22.h" -+#include "qbg_utils.h" -+ -+struct vdp22_ptlv { /* Packed TLV for VDP data exchange */ -+ unsigned short head; /* TLV 16 bit header */ -+ unsigned char data[]; /* TLV Data buffer */ -+}; -+ -+enum { /* VDP22 Protocol command responses */ -+ USEC_PER_SEC = 1000000, /* Microseconds per second */ -+ VDP22_RESBIT = 0x80, /* VSI reserved bit */ -+ VDP22_ACKBIT = 0x40, /* VSI Acknowledgement bit */ -+ VDP22_KEEPBIT = 0x20, /* VSI keep error bit */ -+ VDP22_HARDBIT = 0x10, /* VSI hard error bit */ -+ VDP22_STATUS_MASK = 0x0f, /* Status mask */ -+ VDP22_STATUS_SHIFT = 0, /* Status offset */ -+}; -+ -+/* -+ * Set status code -+ */ -+static inline unsigned char make_status(int x) -+{ -+ return (x << VDP22_STATUS_SHIFT) & VDP22_STATUS_MASK; -+} -+ -+enum vdp22br_states { /* State for VDP22 bridge processing */ -+ VDP22_BR_START = 100, /* Start state */ -+ VDP22_BR_BEGIN, /* Begin state */ -+ VDP22_BR_INIT, /* Init state */ -+ VDP22_BR_PROCESS, /* Process command from station */ -+ VDP22_BR_SEND, /* Send result to station */ -+ VDP22_BR_WAITCMD, /* Wait for cmd from station */ -+ VDP22_BR_WAITCMD_2, /* End of wait for cmd from station */ -+ VDP22_BR_KEEP, /* Send keep result to station */ -+ VDP22_BR_DEASSOC, /* Send de-assoc result to station */ -+ VDP22_BR_ALIVE, /* Process keep alive from station state */ -+ VDP22_BR_DEASSOCIATED, /* Deassoc state */ -+ VDP22_BR_END /* End state */ -+}; -+ -+/* VDP22 bridge states verbatim */ -+static const char *const vdp22br_states_n[] = { -+ "unknown", -+ "VDP22_BR_BEGIN", -+ "VDP22_BR_INIT", -+ "VDP22_BR_PROCESS", -+ "VDP22_BR_SEND", -+ "VDP22_BR_WAITCMD", -+ "VDP22_BR_WAITCMD_2", -+ "VDP22_BR_KEEP", -+ "VDP22_BR_DEASSOC", -+ "VDP22_BR_ALIVE", -+ "VDP22_BR_DEASSOCIATED", -+ "VDP22_BR_END" -+}; -+ -+static inline const char *vdp22br_state_name(enum vdp22br_states x) -+{ -+ return vdp22br_states_n[x - VDP22_BR_START]; -+} -+ -+enum vdp22_states { /* VDP22 station states */ -+ VDP22_BEGIN = 1, -+ VDP22_INIT, -+ VDP22_STATION_PROC, /* Station processing */ -+ VDP22_STATION_PROCWAIT, /* Station processing, wait for reply */ -+ VDP22_STATION_PROCWAIT_2, /* Station processing, received reply */ -+ VDP22_ASSOC_NEW, -+ VDP22_ASSOC_COMPL, /* Assoc complete */ -+ VDP22_PREASSOC_NEW, -+ VDP22_WAIT_SYSCMD, -+ VDP22_WAIT_SYSCMD_2, -+ VDP22_TXMIT_KA, /* Transmit keep alive */ -+ VDP22_TXMIT_KAWAIT, /* Transmit keep alive, wait for reply */ -+ VDP22_TXMIT_KAWAIT_2, /* Transmit keep alive, received message */ -+ VDP22_TXMIT_DEASSOC, /* Transmit Deassociation */ -+ VDP22_TXMIT_DEAWAIT, /* Transmit Deassociation, wait for reply */ -+ VDP22_TXMIT_DEAWAIT_2, /* Transmit Deassociation, received reply */ -+ VDP22_END -+}; -+ -+/* VDP22 station states verbatim */ -+static const char *const vdp22_states_n[] = { -+ "unknown", -+ "VDP22_BEGIN", -+ "VDP22_INIT", -+ "VDP22_STATION_PROC", -+ "VDP22_STATION_PROCWAIT", -+ "VDP22_STATION_PROCWAIT_2", -+ "VDP22_ASSOC_NEW", -+ "VDP22_ASSOC_COMPL", -+ "VDP22_PREASSOC_NEW", -+ "VDP22_WAIT_SYSCMD", -+ "VDP22_WAIT_SYSCMD_2", -+ "VDP22_TXMIT_KA", -+ "VDP22_TXMIT_KAWAIT", -+ "VDP22_TXMIT_KAWAIT_2", -+ "VDP22_TXMIT_DEASSOC", -+ "VDP22_TXMIT_DEAWAIT", -+ "VDP22_TXMIT_DEAWAIT_2", -+ "VDP22_END" -+}; -+ -+/* -+ * Forward definition of function prototypes. -+ */ -+static void vdp22st_run(struct vsi22 *); -+static void vdp22br_run(struct vsi22 *); -+static void vdp22_station_info(struct vsi22 *); -+ -+/* -+ * Return size of packed and unpacked VSI tlv. -+ */ -+static inline size_t mgr22_tlv_sz(void) -+{ -+ return 16; -+} -+ -+static inline size_t mgr22_ptlv_sz(void) -+{ -+ return 2 + mgr22_tlv_sz(); -+} -+ -+/* Return size for each filter data format */ -+static inline size_t vsi22_fdata_sz(unsigned char fif) -+{ -+ switch (fif) { -+ case VDP22_FFMT_VID: -+ return 2; -+ case VDP22_FFMT_MACVID: -+ return 8; -+ case VDP22_FFMT_GROUPVID: -+ return 6; -+ case VDP22_FFMT_GROUPMACVID: -+ return 12; -+ } -+ return 0; -+} -+ -+static inline size_t vsi22_tlv_fifsz(struct vsi22 *vp) -+{ -+ return vp->no_fdata * vsi22_fdata_sz(vp->fif); -+} -+ -+static inline size_t vsi22_tlv_sz(struct vsi22 *vp) -+{ -+ return 23 + 2 + vsi22_tlv_fifsz(vp); -+} -+ -+static inline size_t vsi22_ptlv_sz(struct vsi22 *vp) -+{ -+ return 2 + vsi22_tlv_sz(vp); -+} -+ -+/* -+ * Extract 1, 2, 3, 4 byte integers in network byte format. -+ * Extract n bytes. -+ * Assume enough space available. -+ * Return number of bytes extracted. -+ */ -+static inline size_t extract_1o(unsigned char *data, const unsigned char *cp) -+{ -+ *data = *cp; -+ return 1; -+} -+ -+static inline size_t extract_2o(unsigned short *data, const unsigned char *cp) -+{ -+ *data = (*cp << 8) | *(cp + 1); -+ return 2; -+} -+ -+static inline size_t extract_3o(unsigned long *data, const unsigned char *cp) -+{ -+ *data = (*cp << 16) | (*(cp + 1) << 8) | *(cp + 2); -+ return 3; -+} -+ -+static inline size_t extract_4o(unsigned long *data, const unsigned char *cp) -+{ -+ *data = (*cp << 24) | (*(cp + 1) << 16) | (*(cp + 2) << 8) | *(cp + 3); -+ return 4; -+} -+static inline size_t extract_no(unsigned char *data, const unsigned char *cp, -+ const size_t len) -+{ -+ memcpy(data, cp, len); -+ return len; -+} -+ -+/* -+ * Append 1, 2, 3, 4 byte integers in network byte format. -+ * Append n bytes. -+ * Assume enough space available. -+ * Return number of bytes written. -+ */ -+static inline size_t append_1o(unsigned char *cp, const unsigned char data) -+{ -+ *cp = data; -+ return 1; -+} -+ -+static inline size_t append_2o(unsigned char *cp, const unsigned short data) -+{ -+ *cp = (data >> 8) & 0xff; -+ *(cp + 1) = data & 0xff; -+ return 2; -+} -+ -+static inline size_t append_3o(unsigned char *cp, const unsigned long data) -+{ -+ *cp = (data >> 16) & 0xff; -+ *(cp + 1) = (data >> 8) & 0xff; -+ *(cp + 2) = data & 0xff; -+ return 3; -+} -+ -+static inline size_t append_4o(unsigned char *cp, const unsigned long data) -+{ -+ *cp = (data >> 24) & 0xff; -+ *(cp + 1) = (data >> 16) & 0xff; -+ *(cp + 2) = (data >> 8) & 0xff; -+ *(cp + 3) = data & 0xff; -+ return 4; -+} -+ -+static inline size_t append_nb(unsigned char *cp, const unsigned char *data, -+ const size_t nlen) -+{ -+ memcpy(cp, data, nlen); -+ return nlen; -+} -+ -+/* -+ * Packed TLV header manipulation. -+ */ -+static inline unsigned short ptlv_head(unsigned short type, unsigned short len) -+{ -+ return (type & 0x7f) << 9 | (len & 0x1ff); -+} -+ -+static inline unsigned short ptlv_length(unsigned short header) -+{ -+ return 2 + (header & 0x1ff); -+} -+ -+static inline unsigned short ptlv_type(unsigned short header) -+{ -+ return (header >> 9) & 0x7f; -+} -+ -+/* -+ * Build a VSI tlv. -+ */ -+static size_t vsi22_2tlv_fdata(unsigned char *cp, struct fid22 *p, -+ unsigned char fif) -+{ -+ size_t nbytes = 0; -+ -+ switch (fif) { -+ case VDP22_FFMT_VID: -+ nbytes = append_2o(cp, p->vlan); -+ break; -+ case VDP22_FFMT_MACVID: -+ nbytes = append_nb(cp, p->mac, sizeof(p->mac)); -+ nbytes += append_2o(cp + nbytes, p->vlan); -+ break; -+ case VDP22_FFMT_GROUPVID: -+ nbytes = append_4o(cp, p->grpid); -+ nbytes += append_2o(cp + nbytes, p->vlan); -+ break; -+ case VDP22_FFMT_GROUPMACVID: -+ nbytes = append_4o(cp, p->grpid); -+ nbytes += append_nb(cp + nbytes, p->mac, sizeof(p->mac)); -+ nbytes += append_2o(cp + nbytes, p->vlan); -+ break; -+ } -+ return nbytes; -+} -+ -+static void vsi22_2tlv(struct vsi22 *vp, char unsigned *cp, unsigned char stat) -+{ -+ size_t offset = 0, i; -+ unsigned short head = ptlv_head(vp->vsi_mode, vsi22_tlv_sz(vp)); -+ -+ offset = append_2o(cp, head); -+ offset += append_1o(cp + offset, stat); -+ offset += append_3o(cp + offset, vp->type_id); -+ offset += append_1o(cp + offset, vp->type_ver); -+ offset += append_1o(cp + offset, vp->vsi_fmt); -+ offset += append_nb(cp + offset, vp->vsi, sizeof(vp->vsi)); -+ offset += append_1o(cp + offset, vp->fif); -+ offset += append_2o(cp + offset, vp->no_fdata); -+ for (i = 0; i < vp->no_fdata; ++i) -+ offset += vsi22_2tlv_fdata(cp + offset, &vp->fdata[i], vp->fif); -+} -+ -+static void mgr22_2tlv(struct vsi22 *vp, unsigned char *cp) -+{ -+ unsigned short head = ptlv_head(VDP22_MGRID, mgr22_tlv_sz()); -+ size_t offset; -+ -+ offset = append_2o(cp, head); -+ append_nb(cp + offset, vp->mgrid, sizeof(vp->mgrid)); -+} -+ -+/* -+ * Code for VSI station state machine -+ */ -+/* -+ * VSI ACK time out handler -+ */ -+static void vdp22st_handle_kato(UNUSED void *ctx, void *data) -+{ -+ struct vsi22 *p = data; -+ -+ LLDPAD_DBG("%s:%s timeout keep alive timer for %p(%02x)\n", -+ __func__, p->vdp->ifname, p, p->vsi[0]); -+ p->smi.kato = true; -+ vdp22st_run(p); -+} -+ -+/* -+ * Start the VSI station keep alive timer when a VSI state has been agreed upon. -+ */ -+static int vdp22st_start_katimer(struct vsi22 *p) -+{ -+ unsigned long long towait = (1 << p->vdp->vdp_rka) * 10; -+ unsigned int secs, usecs; -+ -+ secs = towait / USEC_PER_SEC; -+ usecs = towait % USEC_PER_SEC; -+ p->smi.kato = false; -+ LLDPAD_DBG("%s:%s start keep alive timer for %p(%02x) [%i,%i]\n", -+ __func__, p->vdp->ifname, p, p->vsi[0], secs, usecs); -+ return eloop_register_timeout(secs, usecs, vdp22st_handle_kato, NULL, -+ (void *)p); -+} -+ -+/* -+ * Stops the VSI ack timer -+ * Returns the number of removed handlers -+ */ -+static int vdp22st_stop_katimer(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s stop keep alive timer for %p(%02x)\n", __func__, -+ p->vdp->ifname, p, p->vsi[0]); -+ return eloop_cancel_timeout(vdp22st_handle_kato, NULL, (void *)p); -+} -+ -+/* -+ * VSI ACK time out handler -+ */ -+static void vdp22st_handle_ackto(UNUSED void *ctx, void *data) -+{ -+ struct vsi22 *p = data; -+ -+ LLDPAD_DBG("%s:%s timeout ack timer for %p(%02x) ackreceived:%d\n", -+ __func__, p->vdp->ifname, p, p->vsi[0], p->smi.ackreceived); -+ if (!p->smi.ackreceived) { -+ p->smi.kato = true; -+ vdp22st_run(p); -+ } -+} -+ -+/* -+ * Calculate VDP22 keep alive/response wait delay timeout. See 41.5.5.9. -+ */ -+static void vdp22_timeout(struct vdp22 *p, unsigned char exp, -+ unsigned int *secs, unsigned int *usecs) -+{ -+ unsigned long long towait; -+ -+ towait = (1 + 2 * p->ecp_retries) * (1 << p->ecp_rte) * 10; -+ towait += (1 << exp) * 10; -+ towait += towait / 2; -+ *secs = towait / USEC_PER_SEC; -+ *usecs = towait % USEC_PER_SEC; -+} -+ -+/* -+ * Starts the VPD22 station response wait delay timer. See 41.5.5.9. -+ */ -+static int vdp22st_start_acktimer(struct vsi22 *p) -+{ -+ unsigned int secs, usecs; -+ -+ p->smi.txmit = true; -+ p->smi.txmit_error = 0; -+ p->smi.ackreceived = false; -+ p->smi.acktimeout = false; -+ p->smi.resp_ok = false; -+ p->smi.localchg = false; -+ vdp22_timeout(p->vdp, p->vdp->vdp_rwd, &secs, &usecs); -+ LLDPAD_DBG("%s:%s start ack timer for %p(%02x) [%i,%i]\n", -+ __func__, p->vdp->ifname, p, p->vsi[0], secs, usecs); -+ return eloop_register_timeout(secs, usecs, vdp22st_handle_ackto, NULL, -+ (void *)p); -+} -+ -+/* -+ % Stops the VSI ack timer -+ * Returns the number of removed handlers -+ */ -+static int vdp22st_stop_acktimer(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s stop ack timer for %p(%02x)\n", __func__, -+ p->vdp->ifname, p, p->vsi[0]); -+ return eloop_cancel_timeout(vdp22st_handle_ackto, NULL, (void *)p); -+} -+ -+/* -+ * Station init state -+ */ -+static void vdp22st_init(struct vsi22 *vsip) -+{ -+ vsip->smi.state = VDP22_INIT; -+ vsip->status = VDP22_RESP_NONE; -+} -+ -+/* -+ * Station association new and complete state -+ */ -+static void vdp22st_assoc_compl(struct vsi22 *vsip) -+{ -+ vsip->flags &= ~VDP22_BUSY; -+ vsip->resp_vsi_mode = 0; -+} -+ -+static void vdp22st_assoc_new(struct vsi22 *vsip, enum vdp22_modes x) -+{ -+ vdp22st_assoc_compl(vsip); -+ vsip->cc_vsi_mode = x; -+} -+ -+/* -+ * Station wait system command state -+ */ -+static void vdp22st_wait_syscmd(struct vsi22 *vsip) -+{ -+ vdp22st_start_katimer(vsip); -+} -+ -+/* -+ * Station processing state, send packed tlvs to bridge. Allocate send buffer -+ * on stack and create packed TLVs. -+ */ -+static void vdp22st_process(struct vsi22 *vsi) -+{ -+ unsigned short len = mgr22_ptlv_sz() + vsi22_ptlv_sz(vsi); -+ unsigned char buf[len]; -+ struct qbg22_imm qbg; -+ -+ qbg.data_type = VDP22_TO_ECP22; -+ qbg.u.c.len = len; -+ qbg.u.c.data = buf; -+ mgr22_2tlv(vsi, buf); -+ vsi22_2tlv(vsi, buf + mgr22_ptlv_sz(), vsi->hints); -+ vsi->smi.txmit_error = modules_notify(LLDP_MOD_ECP22, LLDP_MOD_VDP22, -+ vsi->vdp->ifname, &qbg); -+ if (!vsi->smi.txmit_error) { -+ vdp22st_stop_katimer(vsi); /* Could still be running */ -+ vdp22st_start_acktimer(vsi); -+ } -+ LLDPAD_DBG("%s:%s len:%hd rc:%d\n", __func__, vsi->vdp->ifname, len, -+ vsi->smi.txmit_error); -+} -+ -+/* -+ * Station transmit deassociate state. -+ */ -+static void vdp22st_txdea(struct vsi22 *vsip) -+{ -+ vsip->vsi_mode = VDP22_DEASSOC; -+ vsip->flags |= VDP22_BUSY; -+ vdp22st_process(vsip); -+} -+ -+/* -+ * Station transmit keep alive state. -+ */ -+static void vdp22st_txka(struct vsi22 *vsip) -+{ -+ vdp22st_process(vsip); -+} -+ -+/* -+ * Station remove a VSI from the VDP22 protocol state machine. -+ * Notification of clients depends on the interface used to establish the -+ * association: -+ * 1. When through netlink interface (draft 0.2) the client is polling for some -+ * time. In this case send a netlink message only when no command pending. -+ * 2. When through attached client (draft 2.2) the client is waiting for -+ * response (time out in operation on client side) and does not poll. -+ */ -+static void vdp22st_end(struct vsi22 *vsi) -+{ -+ vdp22st_stop_acktimer(vsi); -+ vdp22st_stop_katimer(vsi); -+ LLDPAD_DBG("%s:%s vsi:%p(%02x) flags:%#lx vsi_mode:%d,%d" -+ " resp_vsi_mode:%d\n", __func__, -+ vsi->vdp->ifname, vsi, vsi->vsi[0], vsi->flags, -+ vsi->vsi_mode, vsi->cc_vsi_mode, vsi->resp_vsi_mode); -+ vsi->vsi_mode = vsi->cc_vsi_mode = VDP22_DEASSOC; -+ vsi->flags |= VDP22_DELETE_ME; -+ vsi->flags &= ~VDP22_BUSY; -+ if (vsi->flags & VDP22_NOTIFY) -+ vdp22_nlback(vsi); /* Notify netlink when no cmd pending */ -+ vdp22_clntback(vsi); /* Notify attached client */ -+} -+ -+/* -+ * Station change into a new state. -+ */ -+static void vdp22st_change_state(struct vsi22 *vsi, enum vdp22_states newstate) -+{ -+ switch (newstate) { -+ case VDP22_INIT: -+ assert(vsi->smi.state == VDP22_BEGIN); -+ break; -+ case VDP22_STATION_PROC: -+ assert(vsi->smi.state == VDP22_INIT -+ || vsi->smi.state == VDP22_WAIT_SYSCMD_2); -+ break; -+ case VDP22_STATION_PROCWAIT: -+ assert(vsi->smi.state == VDP22_STATION_PROC); -+ break; -+ case VDP22_STATION_PROCWAIT_2: -+ assert(vsi->smi.state == VDP22_STATION_PROCWAIT); -+ break; -+ case VDP22_PREASSOC_NEW: -+ assert(vsi->smi.state == VDP22_STATION_PROCWAIT_2); -+ break; -+ case VDP22_ASSOC_NEW: -+ assert(vsi->smi.state == VDP22_STATION_PROCWAIT_2); -+ break; -+ case VDP22_ASSOC_COMPL: -+ assert(vsi->smi.state == VDP22_ASSOC_NEW -+ || vsi->smi.state == VDP22_STATION_PROCWAIT_2); -+ break; -+ case VDP22_WAIT_SYSCMD: -+ assert(vsi->smi.state == VDP22_ASSOC_COMPL -+ || vsi->smi.state == VDP22_PREASSOC_NEW -+ || vsi->smi.state == VDP22_TXMIT_KAWAIT_2); -+ break; -+ case VDP22_WAIT_SYSCMD_2: -+ assert(vsi->smi.state == VDP22_WAIT_SYSCMD); -+ break; -+ case VDP22_TXMIT_KA: -+ assert(vsi->smi.state == VDP22_WAIT_SYSCMD_2); -+ break; -+ case VDP22_TXMIT_KAWAIT: -+ assert(vsi->smi.state == VDP22_TXMIT_KA); -+ break; -+ case VDP22_TXMIT_KAWAIT_2: -+ assert(vsi->smi.state == VDP22_TXMIT_KAWAIT); -+ break; -+ case VDP22_TXMIT_DEASSOC: -+ assert(vsi->smi.state == VDP22_TXMIT_KAWAIT_2); -+ break; -+ case VDP22_TXMIT_DEAWAIT: -+ assert(vsi->smi.state == VDP22_TXMIT_DEASSOC); -+ break; -+ case VDP22_TXMIT_DEAWAIT_2: -+ assert(vsi->smi.state == VDP22_TXMIT_DEAWAIT); -+ break; -+ case VDP22_END: -+ assert(vsi->smi.state == VDP22_STATION_PROCWAIT -+ || vsi->smi.state == VDP22_STATION_PROCWAIT_2 -+ || vsi->smi.state == VDP22_TXMIT_KAWAIT -+ || vsi->smi.state == VDP22_TXMIT_KAWAIT_2 -+ || vsi->smi.state == VDP22_WAIT_SYSCMD_2 -+ || vsi->smi.state == VDP22_TXMIT_DEASSOC -+ || vsi->smi.state == VDP22_TXMIT_DEAWAIT -+ || vsi->smi.state == VDP22_TXMIT_DEAWAIT_2); -+ break; -+ default: -+ LLDPAD_ERR("%s:%s VDP station machine INVALID STATE %d\n", -+ __func__, vsi->vdp->ifname, newstate); -+ } -+ LLDPAD_DBG("%s:%s state change %s -> %s\n", __func__, -+ vsi->vdp->ifname, vdp22_states_n[vsi->smi.state], -+ vdp22_states_n[newstate]); -+ vsi->smi.state = newstate; -+} -+ -+/* -+ * Check for hard and soft errors. -+ */ -+static inline bool bad_error(unsigned char x) -+{ -+ return (x && (x & VDP22_KEEPBIT) == 0) ? true : false; -+} -+ -+static inline bool keep_error(unsigned char x) -+{ -+ return (x && (x & VDP22_KEEPBIT)) ? true : false; -+} -+ -+/* -+ * Return error code. Check for HARDBIT/KEEPBIT set and no error code. -+ */ -+static inline unsigned char get_error(unsigned char x) -+{ -+ return (x & VDP22_STATUS_MASK) ? x & ~(VDP22_RESBIT|VDP22_ACKBIT) : 0; -+} -+ -+/* -+ * vdp22st_move_state - advances the VDP station state machine state -+ * -+ * Switches the state machine to the next state depending on the input -+ * variables. returns true or false depending on wether the state machine -+ * can be run again with the new state or can stop at the current state. -+ */ -+static bool vdp22st_move_state(struct vsi22 *vsi) -+{ -+ enum vdp22_states newstate; -+ -+ LLDPAD_DBG("%s:%s state %s\n", __func__, vsi->vdp->ifname, -+ vdp22_states_n[vsi->smi.state]); -+ switch (vsi->smi.state) { -+ case VDP22_BEGIN: -+ vdp22st_change_state(vsi, VDP22_INIT); -+ return true; -+ case VDP22_INIT: -+ vdp22st_change_state(vsi, VDP22_STATION_PROC); -+ return true; -+ case VDP22_STATION_PROC: -+ vdp22st_change_state(vsi, VDP22_STATION_PROCWAIT); -+ return true; -+ case VDP22_STATION_PROCWAIT: -+ if (vsi->smi.txmit_error || vsi->smi.acktimeout) { -+ /* Error handover to ECP22 or no VDP22 ack */ -+ vdp22st_change_state(vsi, VDP22_END); -+ return true; -+ } -+ if (vsi->smi.ackreceived) { -+ vdp22st_change_state(vsi, VDP22_STATION_PROCWAIT_2); -+ return true; -+ } -+ return false; -+ case VDP22_STATION_PROCWAIT_2: -+ if (!vsi->smi.resp_ok /* Mismatch in response */ -+ || bad_error(vsi->status)) { /* Error without KEEP */ -+ vdp22st_change_state(vsi, VDP22_END); -+ return true; -+ } -+ if (keep_error(vsi->status)) { /* Error with KEEP on */ -+ if (vsi->resp_vsi_mode == VDP22_ASSOC) -+ newstate = VDP22_ASSOC_COMPL; -+ else -+ newstate = VDP22_END; -+ } else if (vsi->resp_vsi_mode == VDP22_PREASSOC -+ || vsi->resp_vsi_mode == VDP22_PREASSOC_WITH_RR) -+ newstate = VDP22_PREASSOC_NEW; -+ else if (vsi->resp_vsi_mode == VDP22_DEASSOC) -+ newstate = VDP22_END; -+ else -+ newstate = VDP22_ASSOC_NEW; -+ vdp22st_change_state(vsi, newstate); -+ return true; -+ case VDP22_ASSOC_NEW: -+ vdp22st_change_state(vsi, VDP22_ASSOC_COMPL); -+ return true; -+ case VDP22_ASSOC_COMPL: -+ case VDP22_PREASSOC_NEW: -+ vdp22st_change_state(vsi, VDP22_WAIT_SYSCMD); -+ return true; -+ case VDP22_WAIT_SYSCMD: -+ vdp22st_change_state(vsi, VDP22_WAIT_SYSCMD_2); -+ return true; -+ case VDP22_WAIT_SYSCMD_2: -+ if (vsi->smi.kato) { -+ vdp22st_change_state(vsi, VDP22_TXMIT_KA); -+ return true; -+ } -+ if (vsi->smi.localchg) { -+ vdp22st_change_state(vsi, VDP22_STATION_PROC); -+ return true; -+ } -+ if (vsi->smi.deassoc) { -+ vdp22st_change_state(vsi, VDP22_END); -+ return true; -+ } -+ return false; -+ case VDP22_TXMIT_KA: -+ vdp22st_change_state(vsi, VDP22_TXMIT_KAWAIT); -+ return true; -+ case VDP22_TXMIT_KAWAIT: -+ if (vsi->smi.txmit_error || vsi->smi.acktimeout) { -+ /* Error handover to ECP22 or no VDP22 ack */ -+ vdp22st_change_state(vsi, VDP22_END); -+ return true; -+ } -+ if (vsi->smi.ackreceived) { -+ vdp22st_change_state(vsi, VDP22_TXMIT_KAWAIT_2); -+ return true; -+ } -+ return false; -+ case VDP22_TXMIT_KAWAIT_2: -+ if (!vsi->smi.resp_ok /* Mismatch in response */ -+ || bad_error(vsi->status)) { /* Error without KEEP */ -+ vdp22st_change_state(vsi, VDP22_END); -+ return true; -+ } -+ if (keep_error(vsi->status) -+ && vsi->resp_vsi_mode == VDP22_ASSOC) -+ vdp22st_change_state(vsi, VDP22_TXMIT_DEASSOC); -+ else if (vsi->resp_vsi_mode == VDP22_DEASSOC) -+ vdp22st_change_state(vsi, VDP22_END); -+ else -+ vdp22st_change_state(vsi, VDP22_WAIT_SYSCMD); -+ return true; -+ case VDP22_TXMIT_DEASSOC: -+ vdp22st_change_state(vsi, VDP22_TXMIT_DEAWAIT); -+ return true; -+ case VDP22_TXMIT_DEAWAIT: -+ if (vsi->smi.txmit_error || vsi->smi.acktimeout) { -+ /* Error handover to ECP22 or no VDP22 ack */ -+ vdp22st_change_state(vsi, VDP22_END); -+ return true; -+ } -+ if (vsi->smi.ackreceived) { -+ vdp22st_change_state(vsi, VDP22_TXMIT_DEAWAIT_2); -+ return true; -+ } -+ return false; -+ case VDP22_TXMIT_DEAWAIT_2: -+ vdp22st_change_state(vsi, VDP22_END); -+ return true; -+ case VDP22_END: -+ return false; -+ } -+ return false; -+} -+ -+/* -+ * Start state machine for VSI station -+ * @vsi: pointer to currently used vsi data structure -+ * -+ * No return value -+ */ -+static void vdp22st_run(struct vsi22 *vsi) -+{ -+ vdp22st_move_state(vsi); -+ do { -+ LLDPAD_DBG("%s:%s state %s\n", __func__, -+ vsi->vdp->ifname, vdp22_states_n[vsi->smi.state]); -+ -+ switch (vsi->smi.state) { -+ case VDP22_INIT: -+ vdp22st_init(vsi); -+ break; -+ case VDP22_STATION_PROC: -+ vdp22st_process(vsi); -+ break; -+ case VDP22_STATION_PROCWAIT: -+ case VDP22_STATION_PROCWAIT_2: -+ break; -+ case VDP22_ASSOC_NEW: -+ case VDP22_PREASSOC_NEW: -+ vdp22st_assoc_new(vsi, vsi->resp_vsi_mode); -+ vdp22_clntback(vsi); -+ break; -+ case VDP22_ASSOC_COMPL: -+ vdp22st_assoc_compl(vsi); -+ break; -+ case VDP22_WAIT_SYSCMD: -+ vdp22st_wait_syscmd(vsi); -+ break; -+ case VDP22_WAIT_SYSCMD_2: -+ break; -+ case VDP22_TXMIT_KA: -+ vdp22st_txka(vsi); -+ break; -+ case VDP22_TXMIT_KAWAIT: -+ case VDP22_TXMIT_KAWAIT_2: -+ break; -+ case VDP22_TXMIT_DEASSOC: -+ vdp22st_txdea(vsi); -+ break; -+ case VDP22_TXMIT_DEAWAIT: -+ break; -+ case VDP22_TXMIT_DEAWAIT_2: -+ vdp22st_assoc_compl(vsi); -+ break; -+ case VDP22_END: -+ break; -+ default: -+ LLDPAD_DBG("%s:%s state %d unknown\n", __func__, -+ vsi->vdp->ifname, vsi->smi.state); -+ break; -+ } -+ } while (vdp22st_move_state(vsi) == true); -+ if (vsi->smi.state == VDP22_END) -+ vdp22st_end(vsi); -+} -+ -+static void vdp22_localchange_handler(UNUSED void *eloop_data, void *user_ctx) -+{ -+ struct vsi22 *vsi; -+ -+ vsi = (struct vsi22 *) user_ctx; -+ -+ if ((vsi->smi.localchg)) { -+ LLDPAD_DBG("%s:%s p->localChange %i p->ackReceived %i\n", -+ __func__, vsi->vdp->ifname, vsi->smi.localchg, -+ vsi->smi.ackreceived); -+ vdp22st_run(vsi); -+ } -+} -+ -+int vdp22_start_localchange_timer(struct vsi22 *p) -+{ -+ return eloop_register_timeout(0, 100, vdp22_localchange_handler, NULL, -+ (void *) p); -+} -+ -+/* -+ * Checks if 2 VSI records are identical. -+ * -+ * returns true if equal, false if not -+ * -+ * compares mgrid, type id, type version, id format, id and filter info format -+ * returns true if they are equal. -+ */ -+static bool vdp22_vsi_equal(struct vsi22 *p1, struct vsi22 *p2) -+{ -+ if (memcmp(p1->mgrid, p2->mgrid, sizeof(p2->mgrid))) -+ return false; -+ if (p1->type_id != p2->type_id) -+ return false; -+ if (p1->type_ver != p2->type_ver) -+ return false; -+ if (p1->vsi_fmt != p2->vsi_fmt) -+ return false; -+ if (memcmp(p1->vsi, p2->vsi, sizeof(p1->vsi))) -+ return false; -+ if (p1->fif != p2->fif) -+ return false; -+ return true; -+} -+ -+/* -+ * Find a VSI in the list of VSIs already allocated -+ * -+ * Returns pointer to already allocated VSI in list, 0 if not. -+ */ -+static struct vsi22 *vdp22_findvsi(struct vdp22 *vdp, struct vsi22 *me) -+{ -+ struct vsi22 *p; -+ -+ LIST_FOREACH(p, &vdp->vsi22_que, node) { -+ if (vdp22_vsi_equal(p, me)) -+ return p; -+ } -+ return NULL; -+} -+ -+/* -+ * Modify VSI22 information and trigger state machine. -+ * Parameter me identifies the VSI to be modified. -+ */ -+static int vdp22_modvsi(struct vsi22 *me, enum vdp22_modes x) -+{ -+ LLDPAD_DBG("%s:%s me:%p flags:%#lx mode change %d --> %d\n", __func__, -+ me->vdp->ifname, me, me->flags, me->vsi_mode, x); -+ if (me->flags & VDP22_DELETE_ME) -+ return -ENODEV; -+ if (me->vsi_mode > x) -+ return -EINVAL; -+ me->vsi_mode = x; -+ me->smi.localchg = true; -+ me->flags |= VDP22_BUSY | VDP22_NLCMD; -+ vdp22st_run(me); -+ return 0; -+} -+ -+/* -+ * Insert in queue and enter state machine. -+ */ -+static void vdp22_addvsi(struct vsi22 *vsip, struct vdp22 *vdp) -+{ -+ vsip->smi.state = VDP22_BEGIN; -+ LIST_INSERT_HEAD(&vdp->vsi22_que, vsip, node); -+ LLDPAD_DBG("%s:%s vsip:%p\n", __func__, vsip->vdp->ifname, vsip); -+ vdp22st_run(vsip); -+} -+ -+/* -+ * Compare VSI filter data. Return true if they match. -+ * All fields are compared, even if some are not used. Unused field are -+ * initialized to zeros and always match. -+ */ -+static bool cmp_fdata1(struct fid22 *p1, struct fid22 *p2, unsigned char fif) -+{ -+ bool is_good = true; -+ -+ if (fif == VDP22_FFMT_MACVID || fif == VDP22_FFMT_GROUPMACVID) -+ is_good = !memcmp(p1->mac, p2->mac, sizeof(p1->mac)); -+ if (fif == VDP22_FFMT_GROUPVID || fif == VDP22_FFMT_GROUPMACVID) -+ is_good = (p1->grpid == p2->grpid); -+ if (is_good) { -+ if (vdp22_get_vlanid(p1->vlan)) -+ is_good = (vdp22_get_vlanid(p1->vlan) == -+ vdp22_get_vlanid(p2->vlan)); -+ if (is_good && vdp22_get_ps(p1->vlan)) -+ is_good = (p1->vlan == p2->vlan); -+ } -+ return is_good; -+} -+ -+static bool vdp22_cmp_fdata(struct vsi22 *p, struct vsi22 *vsip) -+{ -+ int i; -+ -+ if (p->no_fdata != vsip->no_fdata) -+ return false; -+ for (i = 0; i < p->no_fdata; ++i) { -+ struct fid22 *p1 = &p->fdata[i]; -+ struct fid22 *p2 = &vsip->fdata[i]; -+ -+ if (!cmp_fdata1(p1, p2, p->fif)) { -+ p->status = VDP22_RESP_NOADDR; -+ return false; -+ } -+ } -+ return true; -+} -+ -+/* -+ * Update a current/existing VSI instance. -+ * The next table describes the transition diagram for the VSI instance update: -+ * -+ * Current mode -+ * New Mode | none preassoc preassoc-RR assoc -+ * ===========|================================================================= -+ * preassoc | do_preassoc do_preassoc do_preassoc error -+ * preassoc-RR| do_preassoc-RR do_preassoc-RR do_preassoc-RR error -+ * assoc | do_assoc do_assoc do_assoc do-assoc -+ * deassoc | error do_deassoc do_deassoc do-deassoc -+ * -+ * These operations get more complicated because the filter data may differ: -+ * ============================================================================= -+ * Transitions: -+ * If the filter data of the current VSI node and the new VSI node -+ * matches completely, resend TLVs -+ * -+ * TODO: -+ * If the new mode changes only part of the currently active -+ * filter data, then do: -+ * 1. Clone the filter data which is undergoing a mode change and -+ * create a new VSI node -+ * 2. Delete the filter data in the currently active VSI node. -+ * 3. Search for a VSI node with the same key and new mode: -+ * a. If such a node is found append filter data and resent TLVs -+ * b. If no such node is found, append the new VSI node with -+ * the new mode to the list of cloned VSIs. Send TLV for the -+ * new VSI node. -+ * -+ * If the key matches and the VSI mode is also identical and the filter data -+ * in the new request does not match any filter data element in the current -+ * request, then add the new filter data and resent the TLVs. -+ * -+ * Without the TODO items we currently support an exact match of the -+ * filter data information. This is the same behavior as in the currently -+ * supported IEEE 802.1 QBG draft version 0.2. -+ */ -+ -+/* -+ * Handle a new request. -+ */ -+int vdp22_addreq(struct vsi22 *vsip, struct vdp22 *vdp) -+{ -+ int rc = 0; -+ struct vsi22 *p; -+ -+ LLDPAD_DBG("%s:%s mode:%d\n", __func__, vsip->vdp->ifname, -+ vsip->vsi_mode); -+ if (vsip->vsi_mode > VDP22_DEASSOC || vsip->vsi_mode < VDP22_PREASSOC) -+ return -EINVAL; -+ p = vdp22_findvsi(vdp, vsip); -+ if (!p) { /* New VSI */ -+ if (vsip->vsi_mode == VDP22_DEASSOC) { -+ /* -+ * Disassociate of unknown VSI. Return error. -+ * Nothing to send to switch. -+ */ -+ rc = -EINVAL; -+ LLDPAD_DBG("%s:%s dis-assoc without assoc [%02x]\n", -+ __func__, vsip->vdp->ifname, vsip->vsi[0]); -+ } else -+ vdp22_addvsi(vsip, vdp); /* Add new VSI */ -+ } else { /* Profile on list --> change state */ -+ /* -+ * Request is still busy, do not accept another one. -+ */ -+ if (p->flags & VDP22_BUSY) { -+ rc = -EBUSY; -+ goto out; -+ } -+ /* -+ * Check if filter data is identical. Right now support -+ * for exact filter data is implemented (as in draft 0.2) -+ * -+ * TODO -+ * Support for different filter data information. -+ */ -+ if (!vdp22_cmp_fdata(p, vsip)) { -+ LLDPAD_DBG("%s:%s TODO mismatch filter data [%02x]\n", -+ __func__, vsip->vdp->ifname, vsip->vsi[0]); -+ rc = -EINVAL; -+ } else -+ rc = vdp22_modvsi(p, vsip->vsi_mode); -+ } -+out: -+ LLDPAD_DBG("%s:%s rc:%d\n", __func__, vsip->vdp->ifname, rc); -+ return rc; -+} -+ -+/* -+ * Test for returned filter information. -+ * Set VDP22_RETURN_VID bit in flags when VLAN id or QoS change is detected. -+ */ -+static void vdp22_cpfid(struct vsi22 *hit, struct vsi22 *from) -+{ -+ int i; -+ struct fid22 *hitm = hit->fdata, *fromm = from->fdata; -+ -+ LLDPAD_DBG("%s:%s no_fdata:%hd,%hd\n", __func__, hit->vdp->ifname, -+ from->no_fdata, hit->no_fdata); -+ if (hit->no_fdata != from->no_fdata) -+ return; -+ for (i = 0; i < hit->no_fdata; ++i, ++hitm, ++fromm) { -+ LLDPAD_DBG("%s:%s vlan:%#hx,%#hx\n", __func__, -+ hit->vdp->ifname, hitm->vlan, fromm->vlan); -+ if (hitm->vlan != fromm->vlan) { -+ hitm->vlan = fromm->vlan; -+ hit->flags |= VDP22_RETURN_VID; -+ } -+ } -+ LLDPAD_DBG("%s:%s flags:%#lx\n", __func__, hit->vdp->ifname, -+ hit->flags); -+} -+ -+/* -+ * Input from bridge side. -+ * -+ * NOTE: -+ * - Parameter vsip and associated fid data is on stack memory. -+ */ -+static void vdp22_bridge_info(struct vsi22 *vsip) -+{ -+ struct vsi22 *hit = vdp22_findvsi(vsip->vdp, vsip); -+ -+ if (!hit) { -+ LLDPAD_DBG("%s:%s station received TLV not found:\n", __func__, -+ vsip->vdp->ifname); -+ vdp22_showvsi(vsip); -+ return; -+ } -+ hit->smi.ackreceived = true; -+ hit->smi.deassoc = hit->smi.acktimeout = false; -+ vdp22st_stop_acktimer(hit); -+ hit->status = get_error(vsip->status); -+ if (!(vsip->status & VDP22_ACKBIT) && vsip->vsi_mode == VDP22_DEASSOC) { -+ /* Unsolicited de-assoc request from switch */ -+ hit->smi.deassoc = true; -+ hit->status = 0; -+ } -+ /* -+ * We have already tested some fields of the TLV. Now test the -+ * filter data. -+ */ -+ if (vdp22_cmp_fdata(hit, vsip)) { -+ hit->smi.resp_ok = true; -+ hit->resp_vsi_mode = vsip->vsi_mode; /* Take response */ -+ vdp22_cpfid(hit, vsip); /* Take filter */ -+ if (hit->cc_vsi_mode != VDP22_DEASSOC -+ && (hit->resp_vsi_mode == VDP22_DEASSOC -+ || bad_error(hit->status)) -+ && !(hit->flags & VDP22_NLCMD)) -+ hit->flags |= VDP22_NOTIFY; /* Notify originator */ -+ } -+ LLDPAD_DBG("%s:%s found:%p resp_ok:%d vsi_mode:%d,%d resp_vsi_mode:%d " -+ "flags:%#lx status:%#x deassoc:%d\n", -+ __func__, vsip->vdp->ifname, hit, hit->smi.resp_ok, -+ hit->vsi_mode, hit->cc_vsi_mode, hit->resp_vsi_mode, -+ hit->flags, hit->status, hit->smi.deassoc); -+ vdp22st_run(hit); -+} -+ -+/* -+ * vdp22 input processing from ECP22 received data. Check if data is valid -+ * and do some basic checks. -+ */ -+/* -+ * Advance to next packed tlv location. -+ */ -+static inline struct vdp22_ptlv *next_ptlv(struct vdp22_ptlv *p, -+ const unsigned short len) -+{ -+ return (struct vdp22_ptlv *)((unsigned char *)p + len); -+} -+ -+/* -+ * Convert a VDP22 packed TLV to vsi22 filter data. -+ * Return number of bytes (in input packed TLV) processed. -+ */ -+static size_t ptlv_2_fdata(struct fid22 *fidp, const unsigned char *cp, -+ const unsigned char ffmt) -+{ -+ size_t offset = 0; -+ -+ memset(fidp, 0, sizeof(*fidp)); -+ switch (ffmt) { -+ case VDP22_FFMT_VID: -+ offset = extract_2o(&fidp->vlan, cp); -+ break; -+ case VDP22_FFMT_MACVID: -+ offset = extract_no(fidp->mac, cp, sizeof(fidp->mac)); -+ offset += extract_2o(&fidp->vlan, cp + offset); -+ break; -+ case VDP22_FFMT_GROUPVID: -+ offset = extract_4o(&fidp->grpid, cp); -+ offset += extract_2o(&fidp->vlan, cp + offset); -+ break; -+ case VDP22_FFMT_GROUPMACVID: -+ offset = extract_4o(&fidp->grpid, cp); -+ offset += extract_no(fidp->mac, cp + offset, sizeof(fidp->mac)); -+ offset += extract_2o(&fidp->vlan, cp + offset); -+ break; -+ } -+ return offset; -+} -+ -+/* -+ * Bridge sends replies with ACK bit set or DEASSOC request. -+ * Station sends requests, ignore error bits, ACK bit must be cleared. -+ */ -+static inline bool response_ok(struct vsi22 *vsip) -+{ -+ if (vsip->vdp->myrole == VDP22_BRIDGE) -+ return (vsip->status & VDP22_ACKBIT) ? false : true; -+ if ((vsip->status & VDP22_ACKBIT) || -+ (!(vsip->status & VDP22_ACKBIT) && vsip->vsi_mode == VDP22_DEASSOC)) -+ return true; -+ return false; -+} -+ -+/* -+ * Convert a VDP22 packed TLV to vsi22 to struct vsi22 data format. -+ */ -+static void ptlv_2_vsi22(struct vsi22 *vsip, struct vdp22_ptlv *ptlv) -+{ -+ int i; -+ size_t offset; -+ unsigned char *cp = ptlv->data; -+ -+ offset = extract_1o(&vsip->status, cp); -+ offset += extract_3o(&vsip->type_id, cp + offset); -+ offset += extract_1o(&vsip->type_ver, cp + offset); -+ offset += extract_1o(&vsip->vsi_fmt, cp + offset); -+ offset += extract_no(vsip->vsi, cp + offset, sizeof(vsip->vsi)); -+ offset += extract_1o(&vsip->fif, cp + offset); -+ offset += extract_2o(&vsip->no_fdata, cp + offset); -+ -+ if (ptlv_length(ntohs(ptlv->head)) == vsi22_ptlv_sz(vsip) -+ && vsip->no_fdata && response_ok(vsip)) { -+ struct fid22 fid[vsip->no_fdata]; -+ -+ vsip->fdata = fid; -+ for (i = 0; i < vsip->no_fdata; ++i) -+ offset += ptlv_2_fdata(&fid[i], cp + offset, vsip->fif); -+ if (vsip->vdp->myrole == VDP22_STATION) -+ vdp22_bridge_info(vsip); -+ else -+ vdp22_station_info(vsip); -+ return; -+ } -+ LLDPAD_DBG("%s:%s TLV ignored\n", __func__, vsip->vdp->ifname); -+ vdp22_showvsi(vsip); -+} -+ -+/* -+ * Interate along the packed TLVs and extract information. Packed TLV has -+ * passed basic consistency checking. -+ */ -+static void vdp22_input(struct vdp22 *vdp) -+{ -+ struct vsi22 vsi; -+ struct vdp22_ptlv *ptlv = (struct vdp22_ptlv *)vdp->input; -+ enum vdp22_modes mode; -+ -+ LLDPAD_DBG("%s:%s input_len:%d\n", __func__, vdp->ifname, -+ vdp->input_len); -+ memset(&vsi, 0, sizeof(vsi)); -+ vsi.vdp = vdp; -+ for (; (mode = ptlv_type(ntohs(ptlv->head))) != 0; -+ ptlv = next_ptlv(ptlv, ptlv_length(ntohs(ptlv->head)))) { -+ switch (mode) { -+ default: -+ case VDP22_ENDTLV: -+ break; -+ case VDP22_MGRID: -+ memcpy(&vsi.mgrid, ptlv->data, sizeof(vsi.mgrid)); -+ break; -+ case VDP22_PREASSOC: -+ case VDP22_PREASSOC_WITH_RR: -+ case VDP22_ASSOC: -+ case VDP22_DEASSOC: -+ vsi.vsi_mode = mode; -+ ptlv_2_vsi22(&vsi, ptlv); -+ break; -+ } -+ } -+} -+ -+/* -+ * Receive data from the ECP22 module. Check for valid input data. -+ */ -+static void vdp22_ecp22in(UNUSED void *ctx, void *parm) -+{ -+ struct vdp22 *vdp = (struct vdp22 *)parm; -+ struct vdp22_ptlv *ptlv = (struct vdp22_ptlv *)vdp->input; -+ int total_len = vdp->input_len; -+ unsigned short ptlv_len; -+ -+ if (vdp->myrole == VDP22_BRIDGE && vdp->br_down) { -+ LLDPAD_DBG("%s:%s bridge down\n", __func__, vdp->ifname); -+ return; -+ } -+ /* Verify 1st TLV is a manager id TLV */ -+ if (ptlv_type(ntohs(ptlv->head)) != VDP22_MGRID) { -+ LLDPAD_ERR("%s:%s No Manager ID TLV -- packet dropped\n", -+ __func__, vdp->ifname); -+ return; -+ } -+ ptlv_len = ptlv_length(ntohs(ptlv->head)); -+ if (ptlv_len > total_len) { -+ LLDPAD_ERR("%s:%s Invalid Manager ID TLV length -- " -+ "packet dropped\n", __func__, vdp->ifname); -+ return; -+ } -+ total_len -= ptlv_len; -+ do { /* Iterrate over all packed TLVs */ -+ ptlv = (struct vdp22_ptlv *)((unsigned char *)ptlv + ptlv_len); -+ ptlv_len = ptlv_length(ntohs(ptlv->head)); -+ -+ switch (ptlv_type(ntohs(ptlv->head))) { -+ case VDP22_ENDTLV: -+ total_len = 0; -+ break; -+ case VDP22_MGRID: -+ LLDPAD_ERR("%s:%s Duplicate Manager ID TLV -- " -+ "packet dropped\n", __func__, vdp->ifname); -+ return; -+ case VDP22_PREASSOC: -+ case VDP22_PREASSOC_WITH_RR: -+ case VDP22_ASSOC: -+ case VDP22_DEASSOC: -+ if (ptlv_len > total_len) { -+ LLDPAD_ERR("%s:%s Invalid TLV length -- " -+ "packet dropped\n", __func__, -+ vdp->ifname); -+ return; -+ } -+ total_len -= ptlv_len; -+ break; -+ default: -+ LLDPAD_DBG("%s:%s Unknown TLV ID (%#hx) -- " -+ "ignored\n", __func__, vdp->ifname, -+ ptlv_type(ptlv->head)); -+ if (!ptlv_len) -+ ptlv_len = 2; /* Keep TLVs moving */ -+ total_len -= ptlv_len; -+ } -+ } while (total_len > 0); -+ -+ if (total_len < 0) { -+ LLDPAD_ERR("%s:%s Received packed TLV length error (%d)\n", -+ __func__, vdp->ifname, total_len); -+ return; -+ } -+ return vdp22_input(vdp); -+} -+ -+/* -+ * Called when ECP22 module delivers data. Wait a very short time to allow -+ * the ECP module to return its acknowledgement before data is processed. -+ */ -+int vdp22_from_ecp22(struct vdp22 *vdp) -+{ -+ return eloop_register_timeout(0, 2 * 1000, vdp22_ecp22in, NULL, vdp); -+} -+ -+/* -+ * Bridge state machine code starts here. -+ */ -+static void vdp22br_init(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, -+ p->vsi[0]); -+ p->flags = 0; -+ p->cc_vsi_mode = VDP22_DEASSOC; -+ p->resp_vsi_mode = VDP22_RESP_NONE; -+ p->smi.localchg = true; /* Change triggered by station */ -+ p->smi.kato = false; -+ p->smi.resp_ok = false; /* Response from VSI manager */ -+ /* FOLLOWING MEMBERS NOT USED BY BRIDGE STATE MACHINE */ -+ p->smi.deassoc = p->smi.acktimeout = p->smi.ackreceived = false; -+ p->smi.txmit = false; -+ p->smi.txmit_error = 0; -+} -+ -+/* -+ * VSI bridge time out handler. -+ */ -+static void vdp22br_handle_kato(UNUSED void *ctx, void *data) -+{ -+ struct vsi22 *p = data; -+ -+ LLDPAD_DBG("%s:%s timeout keep alive timer for %#02x\n", -+ __func__, p->vdp->ifname, p->vsi[0]); -+ p->smi.kato = true; -+ vdp22br_run(p); -+} -+ -+/* -+ * Starts the VSI bridge keep alive timer. -+ */ -+static int vdp22br_start_katimer(struct vsi22 *p) -+{ -+ unsigned int usecs, secs; -+ -+ p->smi.kato = false; -+ vdp22_timeout(p->vdp, p->vdp->vdp_rka, &secs, &usecs); -+ LLDPAD_DBG("%s:%s start keep alive timer for %p(%02x) [%i,%i]\n", -+ __func__, p->vdp->ifname, p, p->vsi[0], secs, usecs); -+ return eloop_register_timeout(secs, usecs, vdp22br_handle_kato, NULL, -+ (void *)p); -+} -+ -+/* -+ * Stops the bridge keep alive timer. -+ */ -+static int vdp22br_stop_katimer(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s stop keep alive timer for %p(%02x)\n", __func__, -+ p->vdp->ifname, p, p->vsi[0]); -+ return eloop_cancel_timeout(vdp22br_handle_kato, NULL, (void *)p); -+} -+ -+/* -+ * Bridge resource processing timers. -+ */ -+static void vdp22br_handle_resto(UNUSED void *ctx, void *data) -+{ -+ struct vsi22 *p = data; -+ -+ LLDPAD_DBG("%s:%s timeout resource wait delay for %p(%#02x)\n", -+ __func__, p->vdp->ifname, p, p->vsi[0]); -+ p->smi.resp_ok = true; -+ vdp22br_run(p); -+} -+ -+static int vdp22br_stop_restimer(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s stop resource wait timer for %p(%02x)\n", -+ __func__, p->vdp->ifname, p, p->vsi[0]); -+ return eloop_cancel_timeout(vdp22br_handle_resto, NULL, (void *)p); -+} -+ -+/* -+ * Start resource wait delay timer. -+ */ -+static int vdp22br_start_restimer(struct vsi22 *p) -+{ -+ unsigned long long towait = (1 << p->vdp->vdp_rwd) * 10; -+ unsigned int secs, usecs; -+ -+ p->smi.resp_ok = false; -+ p->resp_vsi_mode = VDP22_RESP_NONE; -+ secs = towait / USEC_PER_SEC; -+ usecs = towait % USEC_PER_SEC; -+ LLDPAD_DBG("%s:%s start resource wait timer for %p(%02x) [%i,%i]\n", -+ __func__, p->vdp->ifname, p, p->vsi[0], secs, usecs); -+ return eloop_register_timeout(secs, usecs, vdp22br_handle_resto, NULL, -+ (void *)p); -+} -+ -+static void vdp22br_process(struct vsi22 *p) -+{ -+ int rc, error = 0; -+ -+ LLDPAD_DBG("%s:%s vsi:%p(%02x) id:%ld\n", __func__, -+ p->vdp->ifname, p, p->vsi[0], p->type_id); -+ vdp22br_start_restimer(p); -+ p->status = 0; -+ p->resp_vsi_mode = VDP22_RESP_SUCCESS; -+ rc = vdp22br_resources(p, &error); -+ switch (rc) { -+ case VDP22_RESP_TIMEOUT: -+ break; -+ case VDP22_RESP_KEEP: -+ p->status = VDP22_KEEPBIT; -+ goto rest; -+ case VDP22_RESP_DEASSOC: -+ if (error > VDP22_STATUS_MASK) -+ p->status = VDP22_HARDBIT; -+ /* Fall through intended */ -+ case VDP22_RESP_SUCCESS: -+rest: -+ p->status |= VDP22_ACKBIT | make_status(error); -+ vdp22br_stop_restimer(p); -+ p->smi.resp_ok = true; -+ break; -+ } -+ p->resp_vsi_mode = rc; -+ LLDPAD_DBG("%s:%s resp_vsi_mode:%d status:%#x\n", __func__, -+ p->vdp->ifname, p->resp_vsi_mode, p->status); -+} -+ -+void vdp22_stop_timers(struct vsi22 *vsi) -+{ -+ vdp22st_stop_acktimer(vsi); -+ vdp22st_stop_katimer(vsi); -+} -+ -+static void vdp22br_end(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, -+ p->vsi[0]); -+ vdp22_listdel_vsi(p); -+} -+ -+/* -+ * Add a VSI to bridge state machine. -+ */ -+static void vdp22br_addvsi(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, -+ p->vsi[0]); -+ p->smi.state = VDP22_BR_BEGIN; -+ p->flags = VDP22_BUSY; -+ LIST_INSERT_HEAD(&p->vdp->vsi22_que, p, node); -+ vdp22br_run(p); -+} -+ -+/* -+ * Send a bridge reply. Allocate send buffer on stack and create packed TLVs. -+ */ -+static void vdp22br_reply(struct vsi22 *vsi) -+{ -+ unsigned short len = mgr22_ptlv_sz() + vsi22_ptlv_sz(vsi); -+ unsigned char buf[len]; -+ struct qbg22_imm qbg; -+ -+ qbg.data_type = VDP22_TO_ECP22; -+ qbg.u.c.len = len; -+ qbg.u.c.data = buf; -+ mgr22_2tlv(vsi, buf); -+ vsi22_2tlv(vsi, buf + mgr22_ptlv_sz(), vsi->status); -+ modules_notify(LLDP_MOD_ECP22, LLDP_MOD_VDP22, vsi->vdp->ifname, &qbg); -+ vsi->flags &= ~VDP22_BUSY; -+ vsi->smi.localchg = false; -+ LLDPAD_DBG("%s:%s len:%hd rc:%d\n", __func__, vsi->vdp->ifname, len, -+ vsi->smi.txmit_error); -+} -+ -+/* -+ * Send a keep status TLV as bridge reply. -+ */ -+static void vdp22br_sendack(struct vsi22 *p, unsigned char status) -+{ -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, -+ p->vsi[0]); -+ p->status = status; -+ vdp22br_reply(p); -+} -+ -+/* -+ * Send a de-associate TLV as bridge reply. -+ */ -+static void vdp22br_deassoc(struct vsi22 *p, unsigned char status) -+{ -+ LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, -+ p->vsi[0]); -+ p->vsi_mode = VDP22_DEASSOC; -+ vdp22br_sendack(p, status); -+} -+ -+/* -+ * Change bridge state machine into a new state. -+ */ -+static void vdp22br_change_state(struct vsi22 *p, enum vdp22br_states new) -+{ -+ switch (new) { -+ case VDP22_BR_INIT: -+ assert(p->smi.state == VDP22_BR_BEGIN); -+ break; -+ case VDP22_BR_PROCESS: -+ assert(p->smi.state == VDP22_BR_WAITCMD_2 -+ || p->smi.state == VDP22_BR_INIT); -+ break; -+ case VDP22_BR_SEND: -+ assert(p->smi.state == VDP22_BR_PROCESS); -+ break; -+ case VDP22_BR_KEEP: -+ assert(p->smi.state == VDP22_BR_PROCESS); -+ break; -+ case VDP22_BR_DEASSOC: -+ assert(p->smi.state == VDP22_BR_PROCESS); -+ break; -+ case VDP22_BR_WAITCMD: -+ assert(p->smi.state == VDP22_BR_SEND -+ || p->smi.state == VDP22_BR_KEEP -+ || p->smi.state == VDP22_BR_ALIVE); -+ break; -+ case VDP22_BR_WAITCMD_2: -+ assert(p->smi.state == VDP22_BR_WAITCMD); -+ break; -+ case VDP22_BR_ALIVE: -+ assert(p->smi.state == VDP22_BR_WAITCMD_2); -+ break; -+ case VDP22_BR_DEASSOCIATED: -+ assert(p->smi.state == VDP22_BR_PROCESS -+ || p->smi.state == VDP22_BR_WAITCMD); -+ break; -+ case VDP22_BR_END: -+ assert(p->smi.state == VDP22_BR_DEASSOC -+ || p->smi.state == VDP22_BR_DEASSOCIATED); -+ break; -+ default: -+ LLDPAD_ERR("%s:%s VDP bridge machine INVALID STATE %d\n", -+ __func__, p->vdp->ifname, new); -+ } -+ LLDPAD_DBG("%s:%s state change %s -> %s\n", __func__, -+ p->vdp->ifname, vdp22br_state_name(p->smi.state), -+ vdp22br_state_name(new)); -+ p->smi.state = new; -+} -+ -+/* -+ * vdp22br_move_state - advances the VDP bridge state machine state -+ * -+ * returns true or false -+ * -+ * Switches the state machine to the next state depending on the input -+ * variables. Returns true or false depending on wether the state machine -+ * can be run again with the new state or has to stop at the current state. -+ */ -+static bool vdp22br_move_state(struct vsi22 *p) -+{ -+ LLDPAD_DBG("%s:%s state %s\n", __func__, p->vdp->ifname, -+ vdp22br_state_name(p->smi.state)); -+ switch (p->smi.state) { -+ case VDP22_BR_BEGIN: -+ vdp22br_change_state(p, VDP22_BR_INIT); -+ return true; -+ case VDP22_BR_INIT: -+ vdp22br_change_state(p, VDP22_BR_PROCESS); -+ return true; -+ case VDP22_BR_PROCESS: -+ if (!p->smi.resp_ok) /* No resource wait response */ -+ return false; -+ /* Assumes status and error bits set accordingly */ -+ if (p->resp_vsi_mode == VDP22_RESP_NONE) { /* Timeout */ -+ if (p->cc_vsi_mode == VDP22_ASSOC) -+ vdp22br_change_state(p, VDP22_BR_KEEP); -+ else -+ vdp22br_change_state(p, VDP22_BR_DEASSOCIATED); -+ } else if (p->resp_vsi_mode == VDP22_RESP_SUCCESS) -+ vdp22br_change_state(p, VDP22_BR_SEND); -+ else if (p->resp_vsi_mode == VDP22_RESP_KEEP) -+ vdp22br_change_state(p, VDP22_BR_KEEP); -+ else -+ vdp22br_change_state(p, VDP22_BR_DEASSOC); -+ return true; -+ case VDP22_BR_SEND: -+ case VDP22_BR_KEEP: -+ vdp22br_change_state(p, VDP22_BR_WAITCMD); -+ return true; -+ case VDP22_BR_DEASSOC: -+ vdp22br_change_state(p, VDP22_BR_END); -+ return true; -+ case VDP22_BR_WAITCMD: -+ if (p->smi.localchg) { /* New station request */ -+ vdp22br_change_state(p, VDP22_BR_WAITCMD_2); -+ return true; -+ } -+ if (p->smi.kato) { /* Keep alive timeout */ -+ vdp22br_change_state(p, VDP22_BR_DEASSOCIATED); -+ return true; -+ } -+ return false; -+ case VDP22_BR_WAITCMD_2: /* Handle station msg */ -+ if (p->cc_vsi_mode == p->vsi_mode) -+ vdp22br_change_state(p, VDP22_BR_ALIVE); -+ else -+ vdp22br_change_state(p, VDP22_BR_PROCESS); -+ return true; -+ case VDP22_BR_DEASSOCIATED: -+ vdp22br_change_state(p, VDP22_BR_END); -+ return true; -+ case VDP22_BR_ALIVE: -+ vdp22br_change_state(p, VDP22_BR_WAITCMD); -+ return true; -+ case VDP22_BR_END: -+ return false; -+ default: -+ LLDPAD_DBG("%s:%s unhandled state %s\n", __func__, -+ p->vdp->ifname, vdp22br_state_name(p->smi.state)); -+ } -+ return false; -+} -+ -+/* -+ * Run bridge state machine. -+ */ -+static void vdp22br_run(struct vsi22 *p) -+{ -+ vdp22br_move_state(p); -+ do { -+ LLDPAD_DBG("%s:%s state %s\n", __func__, -+ p->vdp->ifname, -+ vdp22br_state_name(p->smi.state)); -+ -+ switch (p->smi.state) { -+ case VDP22_BR_INIT: -+ vdp22br_init(p); -+ break; -+ case VDP22_BR_PROCESS: -+ vdp22br_process(p); -+ break; -+ case VDP22_BR_SEND: -+ vdp22br_reply(p); -+ break; -+ case VDP22_BR_KEEP: -+ vdp22br_sendack(p, p->status); -+ break; -+ case VDP22_BR_DEASSOC: -+ vdp22br_deassoc(p, p->status); -+ break; -+ case VDP22_BR_WAITCMD: -+ vdp22br_start_katimer(p); -+ break; -+ case VDP22_BR_WAITCMD_2: -+ break; -+ case VDP22_BR_ALIVE: -+ vdp22br_sendack(p, VDP22_ACKBIT); -+ break; -+ case VDP22_BR_DEASSOCIATED: -+ vdp22br_deassoc(p, 0); -+ break; -+ case VDP22_BR_END: -+ vdp22br_end(p); -+ break; -+ } -+ } while (vdp22br_move_state(p) == true); -+} -+ -+/* -+ * Process the request from the station. -+ * -+ * NOTE: -+ * - Parameter vsip and associated fid data is on stack memory. -+ * - New filter information data assigned to new_fdata/new_no_fdata. -+ */ -+static void vdp22_station_info(struct vsi22 *vsip) -+{ -+ struct vdp22 *vdp = vsip->vdp; -+ struct vsi22 *hit = vdp22_findvsi(vsip->vdp, vsip); -+ -+ LLDPAD_DBG("%s:%s received VSI hit:%p\n", __func__, vdp->ifname, hit); -+ vdp22_showvsi(vsip); -+ if (!hit) { -+ if (vsip->vsi_mode == VDP22_DEASSOC) { -+ /* Nothing allocated and de-assoc --> return ack */ -+ vsip->status = VDP22_ACKBIT; -+ } else { -+ /* Create VSI & enter init state */ -+ struct vsi22 *new = vdp22_copy_vsi(vsip); -+ -+ if (new) -+ return vdp22br_addvsi(new); -+ vsip->status = VDP22_ACKBIT -+ | make_status(VDP22_RESP_NO_RESOURCES); -+ } -+ /* Send back response without state machine resources */ -+ return vdp22br_reply(vsip); -+ } -+ LLDPAD_DBG("%s:%s vsi_mode:%d flags:%#lx\n", __func__, vdp->ifname, -+ hit->vsi_mode, hit->flags); -+ if (hit->flags & VDP22_BUSY) -+ return; -+ vdp22br_stop_katimer(hit); -+ if (!vdp22_cmp_fdata(hit, vsip)) { -+ LLDPAD_DBG("%s:%s TODO mismatch filter data [%02x]\n", -+ __func__, vsip->vdp->ifname, vsip->vsi[0]); -+ return; -+ } -+ hit->smi.localchg = true; -+ hit->vsi_mode = vsip->vsi_mode; /* Take new request */ -+ vdp22br_run(hit); -+} -diff --git a/qbg/vdp_ascii.c b/qbg/vdp_ascii.c -new file mode 100644 -index 0000000..0ace562 ---- /dev/null -+++ b/qbg/vdp_ascii.c -@@ -0,0 +1,479 @@ -+/****************************************************************************** -+ -+ Implementation of VDP 22 (ratified standard) according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2014 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+/* -+ * Convertion function for data exchange between lldptool and lldpad. -+ * Get an ascii string and convert it to a vdpnl_vsi structure. -+ * Get a vdpnl_vsi structure and convert it to an ascii string. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "qbg_vdp22def.h" -+#include "qbg_vdp22.h" -+#include "qbg_vdpnl.h" -+#include "qbg_utils.h" -+ -+/* -+ * Check if it is a UUID and consists of hexadecimal digits and dashes only. -+ * If so convert it to UUID. -+ */ -+int vdp_str2uuid(unsigned char *to, char *buffer, size_t max) -+{ -+ unsigned int i, j = 0; -+ size_t buffer_len = strlen(buffer); -+ -+ if (strspn(buffer, "01234567890AaBbCcDdEeFf-") != buffer_len) -+ return -1; -+ memset(to, 0, max); -+ for (i = 0; i < buffer_len && j < max; i++) { -+ if (buffer[i] == '-') -+ continue; -+ if (sscanf(&buffer[i], "%02hhx", &to[j]) == 1) { -+ i++; -+ j++; -+ } -+ } -+ if (i < buffer_len) -+ return -2; /* Not enough space */ -+ return 0; -+} -+ -+/* -+ * Convert a 16byte uuid to string. Insert dashes for better readability. -+ */ -+int vdp_uuid2str(const unsigned char *p, char *dst, size_t size) -+{ -+ if (dst && size > VDP_UUID_STRLEN) { -+ snprintf(dst, size, "%02x%02x%02x%02x-%02x%02x-%02x%02x" -+ "-%02x%02x-%02x%02x%02x%02x%02x%02x", -+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], -+ p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); -+ return 0; -+ } -+ return -1; -+} -+ -+/* -+ * Return true if string is a number between min and max. -+ */ -+static bool getnumber(char *s, unsigned int min, unsigned int max, -+ unsigned int *no) -+{ -+ char *myend; -+ -+ *no = strtol(s, &myend, 0); -+ if (s && *myend == '\0' && min <= *no && *no <= max) -+ return true; -+ return false; -+} -+ -+/* -+ * Read filter information data. The format is an ascii string: -+ * filter-data filter-format -+ * vlan 1 -+ * vlan-mac 2 -+ * vlan--group 3 -+ * vlan-mac-group 4 -+ */ -+static bool getfid(struct vdpnl_vsi *p, char *value, long idx) -+{ -+ char *delim2 = 0, *delim = strchr(value, '-'); -+ unsigned int vlan, gpid = 0; -+ int fif, i, have_mac = 1, have_gpid = 1; -+ unsigned char x[ETH_ALEN]; -+ -+ memset(x, 0, sizeof(x)); -+ if (!delim) /* No dash --> no mac, no group */ -+ have_gpid = have_mac = 0; -+ else { -+ *delim = '\0'; -+ delim2 = strchr(delim + 1, '-'); -+ if (!delim2) /* No 2nd dash --> have mac but no group */ -+ have_gpid = 0; -+ else { /* 2 dashes --> check for mac */ -+ *delim2 = '\0'; -+ if (delim + 1 == delim2) -+ /* -- means vlan and group without mac */ -+ have_mac = 0; -+ } -+ } -+ if (!getnumber(value, 0, 0xffff, &vlan)) -+ return false; -+ fif = VDP22_FFMT_VID; -+ if (have_mac) { -+ i = sscanf(delim + 1, -+ "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", -+ &x[0], &x[1], &x[2], &x[3], &x[4], &x[5]); -+ if (i != ETH_ALEN) -+ return false; -+ fif = VDP22_FFMT_MACVID; -+ } -+ -+ /* Check for optional group identifier */ -+ if (have_gpid && *(delim2 + 1)) { -+ if (!getnumber(delim2 + 1, 1, ~0U, &gpid)) -+ return false; -+ fif += 2; -+ } -+ -+ /* We already have filter information data, filter format must match */ -+ if (p->filter_fmt && p->filter_fmt != fif) -+ return false; -+ p->filter_fmt = fif; -+ -+ /* Check if this mac is already in our list */ -+ for (i = 0; have_mac && i < p->macsz; ++i) { -+ if (!memcmp(x, p->maclist[i].mac, sizeof(p->maclist[i].mac))) -+ return false; -+ } -+ -+ /* Append to end of list */ -+ p->maclist[idx].vlan = vdp22_get_vlanid(vlan); -+ p->maclist[idx].qos = vdp22_get_qos(vlan); -+ p->maclist[idx].gpid = gpid; -+ memcpy(p->maclist[idx].mac, x, sizeof(p->maclist[0].mac)); -+ return true; -+} -+ -+/* -+ * Read manager identifier (max 16 bytes). Check if it is a UUID and consists -+ * of hexadecimal digits only. If so convert it to UUID. -+ */ -+static bool getmgr2id(struct vdpnl_vsi *p, char *s) -+{ -+ bool is_good; -+ size_t cnt = 0, i, slen = strlen(s); -+ char *s_old = s; -+ -+ if (vdp_str2uuid(p->vsi_mgrid2, s, sizeof(p->vsi_mgrid2)) == 0) -+ return true; -+ /* Check for alphanumeric string */ -+ for (i = 0; i < slen; ++i, ++s) -+ if (isalnum(*s)) -+ ++cnt; -+ is_good = cnt == slen && cnt < sizeof(p->vsi_mgrid2); -+ if (is_good) -+ memcpy(p->vsi_mgrid2, s_old, cnt); -+ return is_good; -+} -+ -+/* -+ * Read VSI VM hints. -+ */ -+static bool gethints(struct vdpnl_vsi *p, char *s) -+{ -+ if (!strcasecmp(s, "to")) -+ p->hints = VDP22_MIGTO; -+ else if (!strcasecmp(s, "from")) -+ p->hints = VDP22_MIGFROM; -+ else if (!strcasecmp(s, "none") || !strcasecmp(s, "-")) -+ p->hints = 0; -+ else -+ return false; -+ return true; -+} -+ -+/* -+ * Read VSI association mode. If can be followed by an error code in brackets. -+ * For vdp22 protocol the allowed words are assoc, preassoc, preassoc-rr and -+ * deassoc. -+ * For vdp draft 0.2 the allowed commands are 0, 1, 2 and 3. -+ */ -+static bool getmode(struct vdpnl_vsi *p, char *s) -+{ -+ char *myend, *bracket = strchr(s, '['); -+ int no; -+ -+ if (strlen(s) == 1) { -+ switch (*s) { -+ case '0': p->request = VDP22_PREASSOC; -+ break; -+ case '1': p->request = VDP22_PREASSOC_WITH_RR; -+ break; -+ case '2': p->request = VDP22_ASSOC; -+ break; -+ case '3': p->request = VDP22_DEASSOC; -+ break; -+ default: return false; -+ } -+ p->request -= 1; -+ p->nl_version = vdpnl_nlf1; -+ return true; -+ } -+ -+ if (bracket) { -+ *bracket = '\0'; -+ no = strtol(bracket + 1, &myend, 0); -+ if (*myend != ']') -+ return false; -+ p->response = no; -+ } -+ if (!strcasecmp(s, "assoc")) -+ p->request = VDP22_ASSOC; -+ else if (!strcasecmp(s, "preassoc")) -+ p->request = VDP22_PREASSOC; -+ else if (!strcasecmp(s, "preassoc-rr")) -+ p->request = VDP22_PREASSOC_WITH_RR; -+ else if (!strcasecmp(s, "deassoc")) -+ p->request = VDP22_DEASSOC; -+ else -+ return false; -+ p->nl_version = vdpnl_nlf2; -+ return true; -+} -+ -+/* -+ * Parse the mode parameter to create/change an VSI assoication. -+ * The format is a comma separated list of tokens: -+ * cmd,mgrid,typeid,typeidversion,vsiid,hints,fid[,fid,fid,...] -+ * with -+ * cmd := "assoc" | "deassoc" | "preassoc" | "preassoc-rr" -+ * mgrid := less or equal to 16 byte alphanumeric characters -+ * | UUID (with dashes in between) -+ * typeid := number in range of 1 - 2^24 -1 -+ * typeidversion:= number in range of 1 - 255 -+ * vsiid := UUID (with dashes in between) -+ * hints := varies between input (command) and output (event message) -+ * on input --> dash (-) | "none" | "from" | "to" -+ * on output --> response (number between 0..255) -+ * fid := vlan -+ * | vlan-mac -+ * | vlan--group -+ * | vlan-mac-group -+ * vlan := number in range of 1..2^16 -1 -+ * group := number in range of 1..2^32 - 1 -+ * mac := xx:xx:xx:xx:xx:xx -+ */ -+ -+static int str2vdpnl(char *argvalue, struct vdpnl_vsi *vsi) -+{ -+ int rc = -ENOMEM; -+ unsigned int no; -+ unsigned short idx; -+ char *cmdstring, *token; -+ -+ cmdstring = strdup(argvalue); -+ if (!cmdstring) -+ goto out_free; -+ rc = -EINVAL; -+ /* 1st field is VSI command */ -+ token = strtok(cmdstring, ","); -+ if (!token || !getmode(vsi, token)) -+ goto out_free; -+ -+ /* 2nd field is VSI Manager Identifer (16 bytes maximum) */ -+ token = strtok(NULL, ","); -+ if (!token || !getmgr2id(vsi, token)) -+ goto out_free; -+ -+ /* 3rd field is type identifier */ -+ token = strtok(NULL, ","); -+ if (!token || !getnumber(token, 0, 0xffffff, &no)) -+ goto out_free; -+ vsi->vsi_typeid = no; -+ -+ /* 4th field is type version identifier */ -+ token = strtok(NULL, ","); -+ if (!token || !getnumber(token, 0, 0xff, &no)) -+ goto out_free; -+ vsi->vsi_typeversion = no; -+ -+ /* 5th field is filter VSI UUID */ -+ token = strtok(NULL, ","); -+ if (!token || vdp_str2uuid(vsi->vsi_uuid, token, sizeof(vsi->vsi_uuid))) -+ goto out_free; -+ vsi->vsi_idfmt = VDP22_ID_UUID; -+ -+ /* 6th field is migration hints */ -+ token = strtok(NULL, ","); -+ if (!token || !gethints(vsi, token)) -+ goto out_free; -+ -+ /* -+ * 7th and remaining fields are filter information format data. -+ * All fields must have the same format. The first fid field determines -+ * the format. -+ */ -+ for (idx = 0, token = strtok(NULL, ","); token != NULL; -+ ++idx, token = strtok(NULL, ",")) { -+ if (idx < vsi->macsz && !getfid(vsi, token, idx)) -+ goto out_free; -+ } -+ -+ /* Return error if no filter information provided */ -+ if (idx) -+ rc = 0; -+out_free: -+ free(cmdstring); -+ return rc; -+} -+ -+/* -+ * Fill the vdpnl_vsi structure from the string. -+ * Allocate the maclist. Must be free'ed by caller. -+ */ -+int vdp_str2vdpnl(char *argvalue, struct vdpnl_vsi *vsi, char *ifname) -+{ -+ if (ifname) -+ strncpy(vsi->ifname, ifname, sizeof(vsi->ifname) - 1); -+ return str2vdpnl(argvalue, vsi); -+} -+ -+/* -+ * Convert VSI profile into string. Use the same format as on input. -+ * Return the number of bytes written into buffer. Return zero if not -+ * enough buffer space. This ensures an entry is complete and no partial -+ * entries are in buffer. -+ */ -+ -+/* -+ * Check if snprintf() result completely fits into buffer. -+ */ -+static char *check_and_update(size_t *total, size_t *length, char *s, int c) -+{ -+ if (c < 0) -+ return NULL; -+ *total += c; -+ if ((unsigned)c >= *length) -+ return NULL; -+ *length -= c; -+ return s + c; -+} -+ -+/* -+ * Convert VSI association to string. -+ */ -+static const char *mode2str(unsigned char x) -+{ -+ if (x == VDP22_ASSOC) -+ return "assoc"; -+ else if (x == VDP22_PREASSOC) -+ return "preassoc"; -+ else if (x == VDP22_PREASSOC_WITH_RR) -+ return "preassoc-rr"; -+ else if (x == VDP22_DEASSOC) -+ return "deassoc"; -+ return "unknown"; -+} -+ -+/* -+ * Convert filter information format into vlan[-mac][-group] string. -+ * Return the number of bytes written into buffer. Return 0 if not -+ * enough buffer space. -+ */ -+static int fid2str(char *s, size_t length, int fif, struct vdpnl_mac *p) -+{ -+ int c; -+ size_t total = 0; -+ -+ c = snprintf(s, length, "%d", vdp22_set_qos(p->qos) | -+ vdp22_set_vlanid(p->vlan)); -+ s = check_and_update(&total, &length, s, c); -+ if (!s) -+ goto out; -+ if (fif == VDP22_FFMT_MACVID || fif == VDP22_FFMT_GROUPMACVID) { -+ c = snprintf(s, length, "-%02x:%02x:%02x:%02x:%02x:%02x", -+ p->mac[0], p->mac[1], p->mac[2], p->mac[3], -+ p->mac[4], p->mac[5]); -+ s = check_and_update(&total, &length, s, c); -+ if (!s) -+ goto out; -+ } -+ if (fif == VDP22_FFMT_GROUPVID || fif == VDP22_FFMT_GROUPMACVID) { -+ c = snprintf(s, length, "-%ld", p->gpid); -+ s = check_and_update(&total, &length, s, c); -+ if (!s) -+ goto out; -+ } -+out: -+ return s ? total : 0; -+} -+ -+/* -+ * Mgrid can be a one byte number ranging from 0..255 or a 16byte long -+ * identifier. -+ */ -+static void mgrid2str(char *to, struct vdpnl_vsi *p, size_t to_len) -+{ -+ int c; -+ -+ memset(to, 0, to_len); -+ for (c = sizeof(p->vsi_mgrid2); c > 0; ) -+ if (p->vsi_mgrid2[--c]) -+ break; -+ if (c) -+ memcpy(to, p->vsi_mgrid2, sizeof(p->vsi_mgrid2)); -+ else -+ snprintf(to, to_len, "%d", p->vsi_mgrid2[0]); -+} -+ -+/* -+ * Convert a vdpnl_vsi to string. -+ */ -+int vdp_vdpnl2str(struct vdpnl_vsi *p, char *s, size_t length) -+{ -+ int c, i; -+ size_t total = 0; -+ char instance[VDP_UUID_STRLEN + 2]; -+ -+ mgrid2str(instance, p, sizeof(instance)); -+ c = snprintf(s, length, "%s,%s,%ld,%d,", -+ mode2str(p->request), instance, p->vsi_typeid, -+ p->vsi_typeversion); -+ s = check_and_update(&total, &length, s, c); -+ if (!s) -+ goto out; -+ -+ vdp_uuid2str(p->vsi_uuid, instance, sizeof(instance)); -+ c = snprintf(s, length, "%s,%d,", instance, p->response); -+ s = check_and_update(&total, &length, s, c); -+ if (!s) -+ goto out; -+ -+ /* Add Filter information data */ -+ for (i = 0; i < p->macsz; ++i) { -+ c = fid2str(s, length, p->filter_fmt, &p->maclist[i]); -+ s = check_and_update(&total, &length, s, c); -+ if (!c) -+ goto out; -+ if (p->macsz > 1 && i < p->macsz - 1) { -+ c = snprintf(s, length, ","); -+ s = check_and_update(&total, &length, s, c); -+ if (!s) -+ goto out; -+ } -+ } -+out: -+ return s ? total : 0; -+} -diff --git a/qbg/vdp_clif.c b/qbg/vdp_clif.c -new file mode 100644 -index 0000000..89f0645 ---- /dev/null -+++ b/qbg/vdp_clif.c -@@ -0,0 +1,193 @@ -+/******************************************************************************* -+ -+ Implementation of VDP according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Jens Osterkamp -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+*******************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include "lldp_mod.h" -+#include "clif_msgs.h" -+#include "lldp.h" -+#include "qbg_vdp.h" -+#include "qbg_vdp_cmds.h" -+#include "qbg_vdp_clif.h" -+#include "lldp_mand_clif.h" -+ -+static const char *mode_state(int mode) -+{ -+ switch (mode) { -+ case VDP_MODE_PREASSOCIATE_WITH_RR: -+ return "Preassociated with RR"; -+ case VDP_MODE_DEASSOCIATE: -+ return "Disassociated"; -+ case VDP_MODE_ASSOCIATE: -+ return "Associated"; -+ case VDP_MODE_PREASSOCIATE: -+ return "Preassociated"; -+ default: return "unknown"; -+ } -+} -+ -+/* -+ * Print a complete VDP TLV. Data string constructed in function -+ * vdp_clif_profile(). -+ */ -+static void vdp_show_tlv(UNUSED u16 len, char *info) -+{ -+ int rc, role, enabletx, vdpbit, mode, response, mgrid, id, idver; -+ unsigned int x[16]; -+ -+ rc = sscanf(info, "%02x%02x%02x%02x%02x%02x%06x%02x", -+ &role, &enabletx, &vdpbit, &mode, &response, &mgrid, -+ &id, &idver); -+ if (rc != 3 && rc != 8) -+ return; -+ printf("Role:%s\n", role ? VAL_BRIDGE : VAL_STATION); -+ printf("\tEnabled:%s\n", enabletx ? VAL_YES : VAL_NO); -+ printf("\tVDP Bit:%s\n", vdpbit ? VAL_YES : VAL_NO); -+ if (rc == 3) /* No active VSI profile */ -+ return; -+ printf("\tMode:%d (%s)\n", mode, mode_state(mode)); -+ printf("\tMgrid:%d\n", mgrid); -+ printf("\tTypeid:%d\n", id); -+ printf("\tTypeidversion:%d\n", idver); -+ rc = sscanf(info + 20, "%02x%02x%02x%02x%02x%02x%02x%02x" -+ "%02x%02x%02x%02x%02x%02x%02x%02x", -+ &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], -+ &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], -+ &x[15]); -+ if (rc != 16) -+ return; -+ printf("\tUUID:%02x%02x%02x%02x-%02x%02x-%02x%02x" -+ "-%02x%02x-%02x%02x%02x%02x%02x%02x\n", x[0], x[1], x[2], x[3], -+ x[4], x[5], x[6], x[7], x[8], x[9], x[10], x[11], x[12], x[13], -+ x[14], x[15]); -+ mode = 52; -+ rc = sscanf(info + mode, "%02x%04x", &role, &vdpbit); -+ if (rc != 2) -+ return; -+ printf("\tFilter Format:%d\n", role); -+ printf("\tEntries:%d\n", vdpbit); -+ mode += 6; -+ while (--vdpbit >= 0) { -+ rc = sscanf(info + mode, "%02x%02x%02x%02x%02x%02x%04x", -+ &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6]); -+ if (rc != 7) -+ return; -+ printf("\t\tMAC:%02x:%02x:%02x:%02x:%02x:%02x\tVlanid:%d\n", -+ x[0], x[1], x[2], x[3], x[4], x[5], x[6]); -+ mode += 16; -+ } -+} -+ -+static struct type_name_info vdp_tlv_names[] = { -+ { -+ .type = ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE, -+ .name = "VDP draft 0.2 protocol configuration", -+ .key = "vdp", -+ .print_info = vdp_show_tlv -+ }, -+ { -+ .type = INVALID_TLVID -+ } -+}; -+ -+static int vdp_print_help() -+{ -+ struct type_name_info *tn = &vdp_tlv_names[0]; -+ -+ while (tn->type != INVALID_TLVID) { -+ if (tn->key && strlen(tn->key) && tn->name) { -+ printf(" %s", tn->key); -+ if (strlen(tn->key)+3 < 8) -+ printf("\t"); -+ printf("\t: %s\n", tn->name); -+ } -+ tn++; -+ } -+ return 0; -+} -+ -+static u32 vdp_lookup_tlv_name(char *tlvid_str) -+{ -+ struct type_name_info *tn = &vdp_tlv_names[0]; -+ -+ while (tn->type != INVALID_TLVID) { -+ if (!strcasecmp(tn->key, tlvid_str)) -+ return tn->type; -+ tn++; -+ } -+ return INVALID_TLVID; -+} -+ -+static void vdp_cli_unregister(struct lldp_module *mod) -+{ -+ free(mod); -+} -+ -+/* return 1: if it printed the TLV -+ * 0: if it did not -+ */ -+static int vdp_print_tlv(u32 tlvid, u16 len, char *info) -+{ -+ struct type_name_info *tn = &vdp_tlv_names[0]; -+ -+ while (tn->type != INVALID_TLVID) { -+ if (tlvid == tn->type) { -+ printf("%s\n", tn->name); -+ if (tn->print_info) { -+ printf("\t"); -+ tn->print_info(len-4, info); -+ } -+ return 1; -+ } -+ tn++; -+ } -+ return 0; -+} -+ -+static const struct lldp_mod_ops vdp_ops_clif = { -+ .lldp_mod_register = vdp_cli_register, -+ .lldp_mod_unregister = vdp_cli_unregister, -+ .print_tlv = vdp_print_tlv, -+ .lookup_tlv_name = vdp_lookup_tlv_name, -+ .print_help = vdp_print_help, -+}; -+ -+struct lldp_module *vdp_cli_register(void) -+{ -+ struct lldp_module *mod; -+ -+ mod = malloc(sizeof(*mod)); -+ if (!mod) { -+ fprintf(stderr, "failed to malloc module data\n"); -+ return NULL; -+ } -+ mod->id = (LLDP_MOD_VDP << 8) | LLDP_VDP_SUBTYPE; -+ mod->ops = &vdp_ops_clif; -+ return mod; -+} -diff --git a/qbg/vdp_cmds.c b/qbg/vdp_cmds.c -new file mode 100644 -index 0000000..95bcfb1 ---- /dev/null -+++ b/qbg/vdp_cmds.c -@@ -0,0 +1,632 @@ -+/****************************************************************************** -+ -+ Implementation of VDP according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2010, 2012 -+ -+ Author(s): Jens Osterkamp -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "lldpad.h" -+#include "ctrl_iface.h" -+#include "lldp.h" -+#include "qbg_vdp.h" -+#include "lldp_mand_clif.h" -+#include "qbg_vdp_cmds.h" -+#include "qbg_utils.h" -+#include "lldp/ports.h" -+#include "lldp_tlv.h" -+#include "messages.h" -+#include "libconfig.h" -+#include "config.h" -+#include "clif_msgs.h" -+#include "lldpad_status.h" -+#include "lldp/states.h" -+ -+static char *check_and_update(size_t *total, size_t *length, char *s, int c) -+{ -+ if (c < 0) -+ return NULL; -+ *total += c; -+ if ((unsigned)c >= *length) -+ return NULL; -+ *length -= c; -+ return s + c; -+} -+ -+static char *print_mode(char *s, size_t length, struct vsi_profile *p) -+{ -+ int c; -+ size_t total = 0; -+ char *r = s; -+ struct mac_vlan *mac_vlan; -+ char instance[VDP_UUID_STRLEN + 2]; -+ -+ vdp_uuid2str(p->instance, instance, sizeof(instance)); -+ c = snprintf(s, length, "%d,%d,%d,%d,%s,%d", -+ p->state, p->mgrid, p->id, p->version, instance, -+ p->format); -+ s = check_and_update(&total, &length, s, c); -+ if (!s) -+ return r; -+ -+ LIST_FOREACH(mac_vlan, &p->macvid_head, entry) { -+ char macbuf[MAC_ADDR_STRLEN + 1]; -+ -+ mac2str(mac_vlan->mac, macbuf, MAC_ADDR_STRLEN); -+ c = snprintf(s, length, ",%s,%d", macbuf, mac_vlan->vlan); -+ s = check_and_update(&total, &length, s, c); -+ if (!s) -+ return r; -+ } -+ return s; -+} -+ -+static int vdp_cmdok(struct cmd *cmd, cmd_status expected) -+{ -+ if (cmd->cmd != expected) -+ return cmd_invalid; -+ -+ switch (cmd->tlvid) { -+ case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE: -+ if (cmd->type != NEAREST_CUSTOMER_BRIDGE) -+ return cmd_agent_not_supported; -+ -+ return cmd_success; -+ case INVALID_TLVID: -+ return cmd_invalid; -+ default: -+ return cmd_not_applicable; -+ } -+} -+ -+static int -+get_arg_tlvtxenable(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ cmd_status good_cmd = vdp_cmdok(cmd, cmd_gettlv); -+ int value; -+ char *s; -+ char arg_path[VDP_BUF_SIZE]; -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ -+ snprintf(arg_path, sizeof(arg_path), "%s.%s", VDP_PREFIX, arg); -+ -+ if (get_cfg(cmd->ifname, cmd->type, arg_path, &value, -+ CONFIG_TYPE_BOOL)) -+ value = false; -+ -+ if (value) -+ s = VAL_YES; -+ else -+ s = VAL_NO; -+ -+ snprintf(obuf, obuf_len, "%02zx%s%04zx%s", -+ strlen(arg), arg, strlen(s), s); -+ -+ return cmd_success; -+} -+ -+static int _set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -+ bool test) -+{ -+ cmd_status good_cmd = vdp_cmdok(cmd, cmd_settlv); -+ int value, err; -+ char arg_path[VDP_BUF_SIZE]; -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ -+ if (!strcasecmp(argvalue, VAL_YES)) -+ value = 1; -+ else if (!strcasecmp(argvalue, VAL_NO)) -+ value = 0; -+ else -+ return cmd_invalid; -+ -+ if (test) -+ return cmd_success; -+ -+ snprintf(arg_path, sizeof(arg_path), "%s.%s", VDP_PREFIX, arg); -+ -+ err = set_cfg(cmd->ifname, cmd->type, arg_path, -+ &value, CONFIG_TYPE_BOOL); -+ if (err) -+ return cmd_failed; -+ -+ return cmd_success; -+ -+} -+ -+static int set_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return _set_arg_tlvtxenable(cmd, arg, argvalue, false); -+} -+ -+static int test_arg_tlvtxenable(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return _set_arg_tlvtxenable(cmd, arg, argvalue, true); -+} -+ -+static int get_arg_mode(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ struct vsi_profile *np; -+ struct vdp_data *vd; -+ char mode_str[VDP_BUF_SIZE], *t = mode_str; -+ int filled = 0; -+ -+ if (cmd->cmd != cmd_gettlv) -+ return cmd_invalid; -+ -+ switch (cmd->tlvid) { -+ case ((LLDP_MOD_VDP) << 8) | LLDP_VDP_SUBTYPE: -+ break; -+ case INVALID_TLVID: -+ return cmd_invalid; -+ default: -+ return cmd_not_applicable; -+ } -+ -+ vd = vdp_data(cmd->ifname); -+ if (!vd) { -+ LLDPAD_ERR("%s: vdp_data for %s not found !\n", -+ __func__, cmd->ifname); -+ return cmd_device_not_found; -+ } -+ -+ memset(mode_str, 0, sizeof mode_str); -+ LIST_FOREACH(np, &vd->profile_head, profile) { -+ t = print_mode(t, sizeof(mode_str) - filled, np); -+ filled = t - mode_str; -+ } -+ -+ snprintf(obuf, obuf_len, "%02x%s%04x%s", -+ (unsigned int)strlen(arg), arg, (unsigned int)strlen(mode_str), -+ mode_str); -+ return cmd_success; -+} -+ -+static void str2instance(struct vsi_profile *profile, char *buffer) -+{ -+ unsigned int i, j = 0; -+ -+ for (i = 0; i <= strlen(buffer); i++) { -+ if (buffer[i] == '-') -+ continue; -+ -+ if (sscanf(&buffer[i], "%02hhx", &profile->instance[j]) == 1) { -+ i++; -+ j++; -+ } -+ } -+} -+ -+static void vdp_fill_profile(struct vsi_profile *profile, char *buffer, -+ int field) -+{ -+ LLDPAD_DBG("%s: parsed %s\n", __func__, buffer); -+ -+ switch(field) { -+ case MODE: -+ profile->mode = atoi(buffer); -+ break; -+ case MGRID: -+ profile->mgrid = atoi(buffer); -+ break; -+ case TYPEID: -+ profile->id = atoi(buffer); -+ break; -+ case TYPEIDVERSION: -+ profile->version = atoi(buffer); -+ break; -+ case INSTANCEID: -+ str2instance(profile, buffer); -+ break; -+ case FORMAT: -+ profile->format = atoi(buffer); -+ break; -+ default: -+ LLDPAD_ERR("Unknown field in buffer !\n"); -+ break; -+ } -+} -+ -+static struct vsi_profile *vdp_parse_mode_line(char *argvalue) -+{ -+ int field; -+ char *cmdstring, *parsed; -+ struct vsi_profile *profile; -+ -+ profile = vdp_alloc_profile(); -+ if (!profile) -+ return NULL; -+ -+ cmdstring = strdup(argvalue); -+ if (!cmdstring) -+ goto out_free; -+ -+ field = 0; -+ -+ parsed = strtok(cmdstring, ","); -+ -+ while (parsed != NULL) { -+ vdp_fill_profile(profile, parsed, field); -+ field++; -+ if (field > FORMAT) -+ break; -+ parsed = strtok(NULL, ","); -+ } -+ -+ if ((field <= FORMAT) || (parsed == NULL)) -+ goto out_free; -+ -+ parsed = strtok(NULL, ","); -+ -+ while (parsed != NULL) { -+ struct mac_vlan *mac_vlan; -+ -+ mac_vlan = calloc(1, sizeof(struct mac_vlan)); -+ if (mac_vlan == NULL) -+ goto out_free; -+ -+ if (str2mac(parsed, &mac_vlan->mac[0], MAC_ADDR_LEN)) { -+ free(mac_vlan); -+ goto out_free; -+ } -+ -+ parsed = strtok(NULL, ","); -+ if (parsed == NULL) { -+ free(mac_vlan); -+ goto out_free; -+ } -+ -+ mac_vlan->vlan = atoi(parsed); -+ LIST_INSERT_HEAD(&profile->macvid_head, mac_vlan, entry); -+ profile->entries++; -+ parsed = strtok(NULL, ","); -+ } -+ -+ free(cmdstring); -+ return profile; -+ -+out_free: -+ free(cmdstring); -+ vdp_delete_profile(profile); -+ return NULL; -+} -+ -+static int _set_arg_mode(struct cmd *cmd, char *argvalue, bool test) -+{ -+ cmd_status good_cmd = vdp_cmdok(cmd, cmd_settlv); -+ struct vsi_profile *profile, *p; -+ struct vdp_data *vd; -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ -+ profile = vdp_parse_mode_line(argvalue); -+ if (profile == NULL) -+ return cmd_failed; -+ -+ profile->port = port_find_by_ifindex(get_ifidx(cmd->ifname)); -+ -+ if (!profile->port) { -+ vdp_delete_profile(profile); -+ return cmd_device_not_found; -+ } -+ -+ vd = vdp_data(cmd->ifname); -+ if (!vd) { -+ vdp_delete_profile(profile); -+ return cmd_device_not_found; -+ } -+ -+ if (test) { -+ vdp_delete_profile(profile); -+ return cmd_success; -+ } -+ -+ p = vdp_add_profile(vd, profile); -+ if (profile != p) -+ vdp_delete_profile(profile); -+ -+ return cmd_success; -+} -+ -+static int set_arg_mode(struct cmd *cmd, UNUSED char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return _set_arg_mode(cmd, argvalue, false); -+} -+ -+static int test_arg_mode(struct cmd *cmd, UNUSED char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return _set_arg_mode(cmd, argvalue, true); -+} -+ -+static int get_arg_role(struct cmd *cmd, char *arg, UNUSED char *argvalue, -+ char *obuf, int obuf_len) -+{ -+ cmd_status good_cmd = vdp_cmdok(cmd, cmd_gettlv); -+ char arg_path[VDP_BUF_SIZE]; -+ const char *p; -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ -+ snprintf(arg_path, sizeof(arg_path), "%s.%s", VDP_PREFIX, arg); -+ if (get_cfg(cmd->ifname, cmd->type, -+ arg_path, &p, CONFIG_TYPE_STRING)) -+ p = VAL_STATION; -+ -+ snprintf(obuf, obuf_len, "%02x%s%04x%s", -+ (unsigned int) strlen(arg), arg, -+ (unsigned int) strlen(p), p); -+ -+ return cmd_success; -+} -+ -+static int _set_arg_role(struct cmd *cmd, char *arg, char *argvalue, bool test) -+{ -+ cmd_status good_cmd = vdp_cmdok(cmd, cmd_settlv); -+ struct vdp_data *vd; -+ char arg_path[VDP_BUF_SIZE]; -+ -+ if (good_cmd != cmd_success) -+ return good_cmd; -+ -+ vd = vdp_data(cmd->ifname); -+ -+ if (!strcasecmp(argvalue, VAL_BRIDGE)) { -+ if (!test && vd) -+ vd->role = VDP_ROLE_BRIDGE; -+ } else if (!strcasecmp(argvalue, VAL_STATION)) { -+ if (!test && vd) -+ vd->role = VDP_ROLE_STATION; -+ } else { -+ return cmd_invalid; -+ } -+ -+ if (test) -+ return cmd_success; -+ -+ snprintf(arg_path, sizeof(arg_path), "%s.%s", VDP_PREFIX, arg); -+ -+ const char *p = &argvalue[0]; -+ if (set_cfg(cmd->ifname, cmd->type, arg_path, &p, CONFIG_TYPE_STRING)) -+ return cmd_failed; -+ -+ return cmd_success; -+} -+ -+static int set_arg_role(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return _set_arg_role(cmd, arg, argvalue, false); -+} -+ -+static int test_arg_role(struct cmd *cmd, char *arg, char *argvalue, -+ UNUSED char *obuf, UNUSED int obuf_len) -+{ -+ return _set_arg_role(cmd, arg, argvalue, true); -+} -+ -+static struct arg_handlers arg_handlers[] = { -+ { -+ .arg = ARG_VDP_MODE, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_mode, -+ .handle_set = set_arg_mode, -+ .handle_test = test_arg_mode -+ }, -+ { -+ .arg = ARG_VDP_ROLE, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_role, -+ .handle_set = set_arg_role, -+ .handle_test = test_arg_role -+ }, -+ { -+ .arg = ARG_TLVTXENABLE, -+ .arg_class = TLV_ARG, -+ .handle_get = get_arg_tlvtxenable, -+ .handle_set = set_arg_tlvtxenable, -+ .handle_test = test_arg_tlvtxenable -+ }, -+ { -+ .arg = 0 -+ } -+}; -+ -+struct arg_handlers *vdp_get_arg_handlers() -+{ -+ return &arg_handlers[0]; -+} -+ -+/* -+ * Interface to build information for lldptool -V vdp -+ */ -+struct tlv_info_vdp_nopp { /* VSI information without profile data */ -+ u8 oui[3]; /* OUI */ -+ u8 sub; /* Subtype */ -+ u8 role; /* Role: station or bridge */ -+ u8 enabletx; -+ u8 vdpbit_on; -+} __attribute__ ((__packed__)); -+ -+/* -+ * Flatten a profile stored as TLV and append it. Skip the first 4 bytes. -+ * They contain the OUI already stored. -+ * Returns the number of bytes added to the buffer. -+ */ -+static int add_profile(unsigned char *pdu, size_t pdusz, struct vdp_data *vdp) -+{ -+ size_t size = 0; -+ -+ if (!vdp->vdp) -+ return size; -+ size = (unsigned)TLVSIZE(vdp->vdp) - 4; -+ if (pdusz >= size) -+ memcpy(pdu, vdp->vdp->info + 4, size); -+ else { -+ LLDPAD_ERR("%s: %s buffer size too small (need %d bytes)\n", -+ __func__, vdp->ifname, TLVSIZE(vdp->vdp)); -+ return -1; -+ } -+ return size; -+} -+ -+/* -+ * Create unpacked VDP tlv for VSI profile when active. -+ */ -+static int make_vdp_tlv(unsigned char *pdu, size_t pdusz, struct vdp_data *vdp) -+{ -+ struct unpacked_tlv *tlv = (struct unpacked_tlv *)pdu; -+ struct tlv_info_vdp_nopp *vdpno; -+ size_t pduoff; -+ int rc; -+ -+ tlv->info = (unsigned char *)(tlv + 1); -+ vdpno = (struct tlv_info_vdp_nopp *)tlv->info; -+ tlv->type = ORG_SPECIFIC_TLV; -+ tlv->length = sizeof(struct tlv_info_vdp_nopp); -+ hton24(vdpno->oui, LLDP_MOD_VDP); -+ vdpno->sub = LLDP_VDP_SUBTYPE; -+ vdpno->role = vdp->role; -+ vdpno->enabletx = vdp->enabletx; -+ vdpno->vdpbit_on = vdp->vdpbit_on; -+ pduoff = sizeof(*tlv) + tlv->length; -+ pdusz -= pduoff; -+ rc = add_profile(pdu + pduoff, pdusz - pduoff, vdp); -+ if (rc > 0) { -+ tlv->length += rc; -+ rc = 0; -+ } -+ return rc; -+} -+ -+/* -+ * Flatten a VDP TLV into a byte stream. -+ */ -+static int vdp_clif_profile(char *ifname, char *rbuf, size_t rlen) -+{ -+ unsigned char pdu[VDP_BUF_SIZE]; /* Buffer for unpacked TLV */ -+ int i, c, rstatus = cmd_success; -+ size_t sum = 0; -+ struct vdp_data *vd; -+ struct unpacked_tlv *tlv = (struct unpacked_tlv *)pdu; -+ struct packed_tlv *ptlv; -+ -+ LLDPAD_DBG("%s: %s rlen:%zu\n", __func__, ifname, rlen); -+ vd = vdp_data(ifname); -+ if (!vd) -+ return cmd_device_not_found; -+ -+ if (make_vdp_tlv(pdu, sizeof pdu, vd)) -+ return cmd_failed; -+ -+ /* Convert to packed TLV */ -+ ptlv = pack_tlv(tlv); -+ if (!ptlv) -+ return cmd_failed; -+ for (i = 0; i < TLVSIZE(tlv); ++i) { -+ c = snprintf(rbuf, rlen, "%02x", ptlv->tlv[i]); -+ rbuf = check_and_update(&sum, &rlen, rbuf, c); -+ if (!rbuf) { -+ rstatus = cmd_failed; -+ break; -+ } -+ } -+ free_pkd_tlv(ptlv); -+ return rstatus; -+} -+ -+/* -+ * Module function to extract all VSI profile data on a given interface. It -+ * is invoked via 'lldptool -t -i ethx -g ncb -V vdp' without any configuration -+ * options. -+ * This function does not support arguments and its values. They are handled -+ * using the lldp_mand_cmds.c interfaces. -+ */ -+int vdp_clif_cmd(char *ibuf, UNUSED int ilen, char *rbuf, int rlen) -+{ -+ struct cmd cmd; -+ u8 len, version; -+ int c, ioff; -+ size_t roff = 0, outlen = rlen; -+ char *here; -+ int rstatus = cmd_invalid; -+ -+ /* Pull out the command elements of the command message */ -+ hexstr2bin(ibuf + MSG_VER, (u8 *)&version, sizeof(u8)); -+ version >>= 4; -+ hexstr2bin(ibuf + CMD_CODE, (u8 *)&cmd.cmd, sizeof(cmd.cmd)); -+ hexstr2bin(ibuf + CMD_OPS, (u8 *)&cmd.ops, sizeof(cmd.ops)); -+ cmd.ops = ntohl(cmd.ops); -+ hexstr2bin(ibuf + CMD_IF_LEN, &len, sizeof(len)); -+ ioff = CMD_IF; -+ if (len < sizeof(cmd.ifname)) -+ memcpy(cmd.ifname, ibuf + CMD_IF, len); -+ else -+ return cmd_failed; -+ cmd.ifname[len] = '\0'; -+ ioff += len; -+ -+ memset(rbuf, 0, rlen); -+ c = snprintf(rbuf, rlen, "%c%1x%02x%08x%02x%s", -+ CMD_REQUEST, CLIF_MSG_VERSION, cmd.cmd, cmd.ops, -+ (unsigned int)strlen(cmd.ifname), cmd.ifname); -+ here = check_and_update(&roff, &outlen, rbuf, c); -+ if (!here) -+ return cmd_failed; -+ -+ if (version == CLIF_MSG_VERSION) { -+ hexstr2bin(ibuf+ioff, &cmd.type, sizeof(cmd.type)); -+ ioff += 2 * sizeof(cmd.type); -+ } else /* Command valid only for nearest customer bridge */ -+ goto out; -+ -+ if (cmd.cmd == cmd_gettlv) { -+ hexstr2bin(ibuf+ioff, (u8 *)&cmd.tlvid, sizeof(cmd.tlvid)); -+ cmd.tlvid = ntohl(cmd.tlvid); -+ ioff += 2 * sizeof(cmd.tlvid); -+ } else -+ goto out; -+ -+ c = snprintf(here, outlen, "%08x", cmd.tlvid); -+ here = check_and_update(&roff, &outlen, here, c); -+ if (!here) -+ return cmd_failed; -+ rstatus = vdp_clif_profile(cmd.ifname, here, outlen); -+out: -+ return rstatus; -+} -diff --git a/qbg/vdpnl.c b/qbg/vdpnl.c -new file mode 100644 -index 0000000..5c0ffd4 ---- /dev/null -+++ b/qbg/vdpnl.c -@@ -0,0 +1,575 @@ -+/****************************************************************************** -+ -+ Implementation of VDP according to IEEE 802.1Qbg -+ (c) Copyright IBM Corp. 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+/* -+ * Contains netlink message parsing for VDP protocol from libvirtd or other -+ * buddies. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "messages.h" -+#include "qbg_vdp.h" -+#include "qbg_vdp22.h" -+#include "qbg_vdpnl.h" -+#include "qbg_utils.h" -+#include "lldp_rtnl.h" -+ -+static struct nla_policy ifla_vf_policy[IFLA_VF_MAX + 1] = { -+ [IFLA_VF_MAC] = { -+ .minlen = sizeof(struct ifla_vf_mac), -+ .maxlen = sizeof(struct ifla_vf_mac) -+ }, -+ [IFLA_VF_VLAN] = { -+ .minlen = sizeof(struct ifla_vf_vlan), -+ .maxlen = sizeof(struct ifla_vf_vlan) -+ } -+}; -+ -+static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] = { -+ [IFLA_PORT_VF] = { .type = NLA_U32 }, -+ [IFLA_PORT_PROFILE] = { .type = NLA_STRING }, -+ [IFLA_PORT_VSI_TYPE] = { .minlen = sizeof(struct ifla_port_vsi) }, -+ [IFLA_PORT_INSTANCE_UUID] = { .minlen = PORT_UUID_MAX, -+ .maxlen = PORT_UUID_MAX, }, -+ [IFLA_PORT_HOST_UUID] = { .minlen = PORT_UUID_MAX, -+ .maxlen = PORT_UUID_MAX, }, -+ [IFLA_PORT_REQUEST] = { .type = NLA_U8 }, -+ [IFLA_PORT_RESPONSE] = { .type = NLA_U16 }, -+}; -+ -+static void vdpnl_show(struct vdpnl_vsi *vsi) -+{ -+ char instance[VDP_UUID_STRLEN + 2]; -+ struct vdpnl_mac *mac; -+ int i; -+ -+ LLDPAD_DBG("%s:IFLA_IFNAME:%s index:%d\n", __func__, vsi->ifname, -+ vsi->ifindex); -+ for (i = 0, mac = vsi->maclist; i < vsi->macsz; ++i, ++mac) { -+ LLDPAD_DBG("%s:IFLA_VF_MAC:%2x:%2x:%2x:%2x:%2x:%2x\n", -+ __func__, mac->mac[0], mac->mac[1], mac->mac[2], -+ mac->mac[3], mac->mac[4], mac->mac[5]); -+ LLDPAD_DBG("%s:IFLA_VF_VLAN:%d QOS:%d\n", __func__, mac->vlan, -+ mac->qos); -+ } -+ LLDPAD_DBG("%s:IFLA_PORT_VSI_TYPE:mgr_id:%d type_id:%ld " -+ "typeid_version:%d\n", -+ __func__, vsi->vsi_mgrid, vsi->vsi_typeid, -+ vsi->vsi_typeversion); -+ vdp_uuid2str(vsi->vsi_uuid, instance, sizeof(instance)); -+ LLDPAD_DBG("%s:IFLA_PORT_INSTANCE_UUID:%s\n", __func__, instance); -+ LLDPAD_DBG("%s:IFLA_PORT_REQUEST:%d\n", __func__, vsi->request); -+ LLDPAD_DBG("%s:IFLA_PORT_RESPONSE:%d\n", __func__, vsi->response); -+} -+ -+/* -+ * Parse the IFLA_IFLA_VF_PORTIFLA_VF_PORTS block of the netlink message. -+ * Return zero on success and errno else. -+ */ -+static int vdpnl_vfports(struct nlattr *vfports, struct vdpnl_vsi *vsi) -+{ -+ char instance[VDP_UUID_STRLEN + 2]; -+ struct nlattr *tb_vf_ports, *tb3[IFLA_PORT_MAX + 1]; -+ int rem; -+ -+ if (!vfports) { -+ LLDPAD_DBG("%s:FOUND NO IFLA_VF_PORTS\n", __func__); -+ return -EINVAL; -+ } -+ -+ nla_for_each_nested(tb_vf_ports, vfports, rem) { -+ if (nla_type(tb_vf_ports) != IFLA_VF_PORT) { -+ LLDPAD_DBG("%s:not a IFLA_VF_PORT skipping\n", -+ __func__); -+ continue; -+ } -+ if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb_vf_ports, -+ ifla_port_policy)) { -+ LLDPAD_ERR("%s:IFLA_PORT_MAX parsing failed\n", -+ __func__); -+ return -EINVAL; -+ } -+ if (tb3[IFLA_PORT_VF]) -+ LLDPAD_DBG("%s:IFLA_PORT_VF:%d\n", __func__, -+ *(uint32_t *) RTA_DATA(tb3[IFLA_PORT_VF])); -+ if (tb3[IFLA_PORT_PROFILE]) -+ LLDPAD_DBG("%s:IFLA_PORT_PROFILE:%s\n", __func__, -+ (char *)RTA_DATA(tb3[IFLA_PORT_PROFILE])); -+ if (tb3[IFLA_PORT_HOST_UUID]) { -+ unsigned char *uuid; -+ -+ uuid = (unsigned char *) -+ RTA_DATA(tb3[IFLA_PORT_HOST_UUID]); -+ vdp_uuid2str(uuid, instance, sizeof(instance)); -+ LLDPAD_DBG("%s:IFLA_PORT_HOST_UUID:%s\n", __func__, -+ instance); -+ } -+ if (tb3[IFLA_PORT_VSI_TYPE]) { -+ struct ifla_port_vsi *pvsi; -+ int tid = 0; -+ -+ pvsi = (struct ifla_port_vsi *) -+ RTA_DATA(tb3[IFLA_PORT_VSI_TYPE]); -+ tid = pvsi->vsi_type_id[2] << 16 | -+ pvsi->vsi_type_id[1] << 8 | -+ pvsi->vsi_type_id[0]; -+ vsi->vsi_mgrid = pvsi->vsi_mgr_id; -+ vsi->vsi_typeversion = pvsi->vsi_type_version; -+ vsi->vsi_typeid = tid; -+ } -+ if (tb3[IFLA_PORT_INSTANCE_UUID]) { -+ unsigned char *uuid = (unsigned char *) -+ RTA_DATA(tb3[IFLA_PORT_INSTANCE_UUID]); -+ memcpy(vsi->vsi_uuid, uuid, sizeof vsi->vsi_uuid); -+ } -+ if (tb3[IFLA_PORT_REQUEST]) -+ vsi->request = -+ *(uint8_t *) RTA_DATA(tb3[IFLA_PORT_REQUEST]); -+ if (tb3[IFLA_PORT_RESPONSE]) -+ vsi->response = -+ *(uint16_t *) RTA_DATA(tb3[IFLA_PORT_RESPONSE]); -+ } -+ return 0; -+} -+ -+/* -+ * Parse the IFLA_VFINFO_LIST block of the netlink message. -+ * Return zero on success and errno else. -+ */ -+static int vdpnl_vfinfolist(struct nlattr *vfinfolist, struct vdpnl_vsi *vsi) -+{ -+ struct nlattr *le1, *vf[IFLA_VF_MAX + 1]; -+ int rem; -+ -+ if (!vfinfolist) { -+ LLDPAD_ERR("%s:IFLA_VFINFO_LIST missing\n", __func__); -+ return -EINVAL; -+ } -+ nla_for_each_nested(le1, vfinfolist, rem) { -+ bool have_mac = false, have_vid = false; -+ -+ if (nla_type(le1) != IFLA_VF_INFO) { -+ LLDPAD_ERR("%s:parsing of IFLA_VFINFO_LIST failed\n", -+ __func__); -+ return -EINVAL; -+ } -+ if (nla_parse_nested(vf, IFLA_VF_MAX, le1, ifla_vf_policy)) { -+ LLDPAD_ERR("%s:parsing of IFLA_VF_INFO failed\n", -+ __func__); -+ return -EINVAL; -+ } -+ -+ if (vf[IFLA_VF_MAC]) { -+ struct ifla_vf_mac *mac = RTA_DATA(vf[IFLA_VF_MAC]); -+ -+ memcpy(vsi->maclist->mac, mac->mac, ETH_ALEN); -+ have_mac = true; -+ } -+ -+ if (vf[IFLA_VF_VLAN]) { -+ struct ifla_vf_vlan *vlan = RTA_DATA(vf[IFLA_VF_VLAN]); -+ -+ vsi->maclist->vlan = vlan->vlan; -+ vsi->maclist->qos = vlan->qos; -+ have_vid = true; -+ } -+ LLDPAD_DBG("%s:have_vid:%d have_mac:%d\n", __func__, have_vid, -+ have_mac); -+ if (have_vid && have_mac) -+ vsi->filter_fmt = VDP22_FFMT_MACVID; -+ else if (have_vid) -+ vsi->filter_fmt = VDP22_FFMT_VID; -+ else -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+/* -+ * Convert the SETLINK message into internal data structure. -+ */ -+static int vdpnl_set(struct nlmsghdr *nlh, struct vdpnl_vsi *vsi) -+{ -+ struct nlattr *tb[IFLA_MAX + 1]; -+ struct ifinfomsg *ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh); -+ int rc; -+ -+ if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), -+ (struct nlattr **)&tb, IFLA_MAX, NULL)) { -+ LLDPAD_ERR("%s:error parsing SETLINK request\n", __func__); -+ return -EINVAL; -+ } -+ -+ vsi->ifindex = ifinfo->ifi_index; -+ if (tb[IFLA_IFNAME]) -+ strncpy(vsi->ifname, (char *)RTA_DATA(tb[IFLA_IFNAME]), -+ sizeof vsi->ifname); -+ else { -+ if (!if_indextoname(ifinfo->ifi_index, vsi->ifname)) { -+ LLDPAD_ERR("%s:can not find name for interface %i\n", -+ __func__, ifinfo->ifi_index); -+ return -ENXIO; -+ } -+ } -+ vsi->req_pid = nlh->nlmsg_pid; -+ vsi->req_seq = nlh->nlmsg_seq; -+ rc = vdpnl_vfinfolist(tb[IFLA_VFINFO_LIST], vsi); -+ if (!rc) { -+ rc = vdpnl_vfports(tb[IFLA_VF_PORTS], vsi); -+ if (!rc) -+ vdpnl_show(vsi); -+ } -+ return rc; -+} -+ -+/* -+ * Return the error code (can be zero) to the sender. Assume buffer is -+ * large enough to hold the information. -+ * Construct the netlink response on the input buffer. -+ */ -+static int vdpnl_error(int err, struct nlmsghdr *from, size_t len) -+{ -+ struct nlmsgerr nlmsgerr; -+ -+ LLDPAD_DBG("%s:error %d\n", __func__, err); -+ nlmsgerr.error = err; -+ nlmsgerr.msg = *from; -+ memset(from, 0, len); -+ from->nlmsg_type = NLMSG_ERROR; -+ from->nlmsg_seq = nlmsgerr.msg.nlmsg_seq; -+ from->nlmsg_pid = nlmsgerr.msg.nlmsg_pid; -+ from->nlmsg_flags = 0; -+ from->nlmsg_len = NLMSG_SPACE(sizeof nlmsgerr); -+ memcpy(NLMSG_DATA(from), &nlmsgerr, sizeof nlmsgerr); -+ return from->nlmsg_len; -+} -+ -+/* -+ * Build the variable part of the netlink reply message for status inquiry. -+ * It contains the UUID and the response field for the VSI profile. -+ */ -+static void vdpnl_reply2(struct vdpnl_vsi *p, struct nl_msg *nlh) -+{ -+ char instance[VDP_UUID_STRLEN + 2]; -+ -+ nla_put(nlh, IFLA_PORT_INSTANCE_UUID, sizeof p->vsi_uuid, -+ p->vsi_uuid); -+ vdp_uuid2str(p->vsi_uuid, instance, sizeof instance); -+ LLDPAD_DBG("%s:IFLA_PORT_INSTANCE_UUID:%s\n", __func__, instance); -+ nla_put_u32(nlh, IFLA_PORT_VF, PORT_SELF_VF); -+ LLDPAD_DBG("%s:IFLA_PORT_VF:%d\n", __func__, PORT_SELF_VF); -+ if (p->response != VDP_RESPONSE_NO_RESPONSE) { -+ nla_put_u16(nlh, IFLA_PORT_RESPONSE, p->response); -+ LLDPAD_DBG("%s:IFLA_PORT_RESPONSE:%d\n", __func__, -+ p->response); -+ } -+} -+ -+/* -+ * Return bytes needed for one VSI in a netlink message. -+ */ -+static size_t vdp_nllen(void) -+{ -+ size_t needed; -+ -+ needed = nla_total_size(sizeof(struct nlattr)) /* IFLA_VF_PORT */ -+ + nla_total_size(4); /* IFLA_PORT_VF */ -+ + nla_total_size(PORT_UUID_MAX); /* IFLA_PORT_INSTANCE_UUID */ -+ + nla_total_size(2); /* IFLA_PORT_RESPONSE */ -+ return needed; -+} -+ -+/* -+ * Get interface name (either from netlink message for from ifi_index). -+ * Return error when no interface available. -+ */ -+static int vdpnl_ifname(struct vdpnl_vsi *p, struct nlattr *tb) -+{ -+ int rc = 0; -+ -+ if (tb) -+ nla_strlcpy(p->ifname, tb, sizeof(p->ifname)); -+ else if (!if_indextoname(p->ifindex, p->ifname)) { -+ LLDPAD_ERR("%s:ifindex %d without interface name\n", __func__, -+ p->ifindex); -+ rc = -EINVAL; -+ } -+ return rc; -+} -+ -+/* -+ * Parse a received netlink request message and return a filled VSI data -+ * structure. -+ */ -+static struct nla_policy pc_max[IFLA_MAX + 1] = { -+ [IFLA_IFNAME] = { -+ .minlen = 1, -+ .maxlen = IFNAMSIZ + 1, -+ .type = NLA_STRING -+ } -+}; -+ -+/* -+ * Retrieve name of interface and its index value from the netlink messaage -+ * and store it in the data structure. -+ * The GETLINK message may or may not contain the IFLA_IFNAME attribute. -+ * Return 0 on success and errno on error. -+ */ -+static int vdpnl_get(struct vdpnl_vsi *p, struct nlmsghdr *nlh) -+{ -+ int rc; -+ struct nlattr *tb[IFLA_MAX + 1]; -+ struct ifinfomsg *ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh); -+ -+ memset(tb, 0, sizeof(tb)); -+ rc = nla_parse(tb, sizeof(tb) / sizeof(tb[0]), -+ (struct nlattr *)IFLA_RTA(NLMSG_DATA(nlh)), -+ IFLA_PAYLOAD(nlh), pc_max); -+ if (rc) { -+ LLDPAD_ERR("%s:error parsing GETLINK request\n", __func__); -+ return -EINVAL; -+ } -+ p->ifindex = ifinfo->ifi_index; -+ return vdpnl_ifname(p, tb[IFLA_IFNAME]); -+} -+ -+/* -+ * Free an malloc'ed maclist array. -+ */ -+void vdp22_freemaclist(struct vdpnl_vsi *vsi) -+{ -+ vsi->macsz = 0; -+ free(vsi->maclist); -+ vsi->maclist = NULL; -+} -+ -+/* -+ * Extract the interface name and loop over all VSI profile entries. -+ * Find UUID and response field for each active profile and construct a -+ * netlink response message. -+ * -+ * Return message size. -+ */ -+static int vdpnl_getlink(struct nlmsghdr *nlh, size_t len) -+{ -+ struct nlmsghdr *nlh_new; -+ struct nl_msg *msg; -+ struct vdpnl_vsi p; -+ int i = 0, rc = -ENOMEM; -+ struct nlattr *vf_ports, *vf_port; -+ struct ifinfomsg ifinfo; -+ size_t mylen = nla_total_size(sizeof(struct ifinfomsg)) -+ + nla_total_size(sizeof(struct nlattr)); -+ /* Header + IFLA_VF_PORTS */ -+ -+ mylen = nlmsg_total_size(mylen); -+ memset(&ifinfo, 0, sizeof ifinfo); -+ memset(&p, 0, sizeof p); -+ msg = nlmsg_alloc_size(len); -+ if (msg) -+ rc = vdpnl_get(&p, nlh); -+ if (rc) { -+ nlmsg_free(msg); -+ return vdpnl_error(rc, nlh, len); -+ } -+ nlmsg_put(msg, nlh->nlmsg_pid, nlh->nlmsg_seq, NLMSG_DONE, 0, 0); -+ ifinfo.ifi_index = p.ifindex; -+ nlmsg_append(msg, &ifinfo, sizeof(ifinfo), 0); -+ -+ vf_ports = nla_nest_start(msg, IFLA_VF_PORTS); -+ /* Iterate over all profiles */ -+ do { -+ rc = vdp22_query(p.ifname) ? vdp22_status(++i, &p, 0) -+ : vdp_status(++i, &p); -+ mylen += vdp_nllen(); -+ if (rc == 1 && mylen < len) { -+ vf_port = nla_nest_start(msg, IFLA_VF_PORT); -+ vdpnl_reply2(&p, msg); -+ nla_nest_end(msg, vf_port); -+ } -+ vdp22_freemaclist(&p); -+ } while (rc == 1); -+ nla_nest_end(msg, vf_ports); -+ if (rc < 0) { -+ nlmsg_free(msg); -+ return vdpnl_error(rc, nlh, len); -+ } -+ nlh_new = nlmsg_hdr(msg); -+ rc = nlh_new->nlmsg_len; -+ memcpy((unsigned char *)nlh, nlh_new, rc); -+ nlmsg_free(msg); -+ LLDPAD_DBG("%s:message-size:%d\n", __func__, rc); -+ return rc; -+} -+ -+/* -+ * Parse incoming command and create a data structure to store the VSI data. -+ */ -+static int vdpnl_setlink(struct nlmsghdr *nlh, size_t len) -+{ -+ int rc = -ENOMEM; -+ struct vdpnl_mac mac; -+ struct vdpnl_vsi p; -+ -+ memset(&p, 0, sizeof p); -+ memset(&mac, 0, sizeof mac); -+ p.vsi_idfmt = VDP22_ID_UUID; -+ p.macsz = 1; -+ p.maclist = &mac; -+ rc = vdpnl_set(nlh, &p); -+ if (!rc) -+ rc = vdp22_query(p.ifname) ? vdp22_request(&p, 0) -+ : vdp_request(&p); -+ return vdpnl_error(rc, nlh, len); -+} -+ -+/* -+ * Process the netlink message. Parameters are the socket, the message and -+ * its length in bytes. -+ * The message buffer 'buf' is used for parsing the incoming message. -+ * After parsing and decoding, the outgoing message is stored in 'buf'. -+ * -+ * Returns: -+ * < 0: Errno number when message parsing failed. -+ * == 0: Message ok and no response. -+ * > 0: Message ok and response returned in buf parameter. Returns bytes -+ * of response. -+ */ -+int vdpnl_recv(unsigned char *buf, size_t buflen) -+{ -+ struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -+ -+ LLDPAD_DBG("%s:buflen:%zd nlh.nl_pid:%d nlh_type:%d nlh_seq:%d " -+ "nlh_len:%d\n", __func__, buflen, nlh->nlmsg_pid, -+ nlh->nlmsg_type, nlh->nlmsg_seq, nlh->nlmsg_len); -+ -+ switch (nlh->nlmsg_type) { -+ case RTM_SETLINK: -+ return vdpnl_setlink(nlh, buflen); -+ case RTM_GETLINK: -+ return vdpnl_getlink(nlh, buflen); -+ default: -+ LLDPAD_ERR("%s:unknown type %d\n", __func__, nlh->nlmsg_type); -+ } -+ return -ENODEV; -+} -+ -+/* -+ * Add one entry in the list of MAC,VLAN pairs. -+ */ -+static void add_pair(struct vdpnl_mac *mac, struct nl_msg *nlh) -+{ -+ struct nlattr *vfinfo; -+ struct ifla_vf_mac ifla_vf_mac = { -+ .vf = PORT_SELF_VF, -+ .mac = { 0, } -+ }; -+ struct ifla_vf_vlan ifla_vf_vlan = { -+ .vf = PORT_SELF_VF, -+ .vlan = mac->vlan, -+ .qos = mac->qos -+ }; -+ -+ vfinfo = nla_nest_start(nlh, IFLA_VF_INFO); -+ memcpy(ifla_vf_mac.mac, mac->mac, sizeof mac->mac); -+ nla_put(nlh, IFLA_VF_MAC, sizeof ifla_vf_mac, &ifla_vf_mac); -+ nla_put(nlh, IFLA_VF_VLAN, sizeof ifla_vf_vlan, &ifla_vf_vlan); -+ nla_nest_end(nlh, vfinfo); -+} -+ -+/* -+ * Walk along the MAC,VLAN ID list and add each entry into the message. -+ */ -+static void add_mac_vlan(struct vdpnl_vsi *vsi, struct nl_msg *nlh) -+{ -+ struct nlattr *vfinfolist; -+ int i; -+ -+ vfinfolist = nla_nest_start(nlh, IFLA_VFINFO_LIST); -+ for (i = 0; i < vsi->macsz; ++i) -+ add_pair(&vsi->maclist[i], nlh); -+ nla_nest_end(nlh, vfinfolist); -+} -+ -+/* -+ * Build an unsolicited netlink message to the VSI requestor. The originator -+ * is the switch abondoning the VSI profile. -+ * Assumes the messages fits into an 4KB buffer. -+ * Returns the message size in bytes. -+ */ -+int vdpnl_send(struct vdpnl_vsi *vsi) -+{ -+ struct nlmsghdr *nlh; -+ struct nlattr *vf_ports, *vf_port; -+ struct ifinfomsg ifinfo; -+ struct ifla_port_vsi portvsi; -+ struct nl_msg *msg; -+ int rc = -ENOMEM; -+ -+ msg = nlmsg_alloc(); -+ if (!msg) { -+ LLDPAD_DBG("%s:%s error allocating netlink message memory:\n", -+ __func__, vsi->ifname); -+ return rc; -+ } -+ nlmsg_put(msg, getpid(), vsi->req_seq, RTM_SETLINK, 0, 0); -+ -+ memset(&ifinfo, 0, sizeof ifinfo); -+ ifinfo.ifi_index = vsi->ifindex; -+ nlmsg_append(msg, &ifinfo, sizeof(ifinfo), 0); -+ nla_put_string(msg, IFLA_IFNAME, vsi->ifname); -+ -+ add_mac_vlan(vsi, msg); -+ portvsi.vsi_mgr_id = vsi->vsi_mgrid; -+ portvsi.vsi_type_id[0] = vsi->vsi_typeid & 0xff; -+ portvsi.vsi_type_id[1] = (vsi->vsi_typeid >> 8) & 0xff; -+ portvsi.vsi_type_id[2] = (vsi->vsi_typeid >> 16) & 0xff; -+ portvsi.vsi_type_version = vsi->vsi_typeversion; -+ vf_ports = nla_nest_start(msg, IFLA_VF_PORTS); -+ vf_port = nla_nest_start(msg, IFLA_VF_PORT); -+ nla_put(msg, IFLA_PORT_VSI_TYPE, sizeof portvsi, &portvsi); -+ nla_put(msg, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, vsi->vsi_uuid); -+ nla_put_u32(msg, IFLA_PORT_VF, PORT_SELF_VF); -+ nla_put_u16(msg, IFLA_PORT_REQUEST, vsi->request); -+ nla_nest_end(msg, vf_port); -+ nla_nest_end(msg, vf_ports); -+ vdpnl_show(vsi); -+ nlh = nlmsg_hdr(msg); -+ LLDPAD_DBG("%s:nlh.nl_pid:%d nlh_type:%d nlh_seq:%d nlh_len:%d\n", -+ __func__, nlh->nlmsg_pid, nlh->nlmsg_type, nlh->nlmsg_seq, -+ nlh->nlmsg_len); -+ rc = event_trigger(nlh, vsi->req_pid); -+ nlmsg_free(msg); -+ return rc; -+} -diff --git a/qbg_utils.c b/qbg_utils.c -new file mode 100644 -index 0000000..9daeade ---- /dev/null -+++ b/qbg_utils.c -@@ -0,0 +1,83 @@ -+/****************************************************************************** -+ -+ Implementation of ECP according to 802.1Qbg -+ (c) Copyright IBM Corp. 2010, 2013 -+ -+ Author(s): Thomas Richter -+ -+ This program is free software; you can redistribute it and/or modify it -+ under the terms and conditions of the GNU General Public License, -+ version 2, as published by the Free Software Foundation. -+ -+ This program is distributed in the hope it will be useful, but WITHOUT -+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ more details. -+ -+ You should have received a copy of the GNU General Public License along with -+ this program; if not, write to the Free Software Foundation, Inc., -+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+ The full GNU General Public License is included in this distribution in -+ the file called "COPYING". -+ -+******************************************************************************/ -+ -+/* -+ * This file contains common support utilities for the ECP protocols. -+ */ -+ -+#include -+#include -+ -+#include "lldp.h" -+#include "lldp_mod.h" -+#include "messages.h" -+#include "qbg_utils.h" -+ -+extern int loglvl; /* Global lldpad log level */ -+extern struct lldp_head lldp_head; -+ -+/* -+ * hexdump_frame - print raw evb/ecp/vdp frame -+ */ -+void hexdump_frame(const char *ifname, char *txt, const unsigned char *buf, -+ size_t len) -+{ -+ size_t i; -+ int left = 0; -+ char buffer[ETH_FRAME_LEN * 3]; -+ -+ /* Only collect data when the loglvl ensures data printout */ -+ if (LOG_DEBUG < loglvl) -+ return; -+ for (i = 0; i < len; i++) { -+ int c; -+ c = snprintf(buffer + left, sizeof buffer - left, "%02x%c", -+ buf[i], !((i + 1) % 16) ? '\n' : ' '); -+ if (c > 0 && (c < (int)sizeof buffer - left)) -+ left += c; -+ } -+ LLDPAD_DBG("%s:%s %s\n%s\n", __func__, ifname, txt, buffer); -+} -+ -+/* -+ * Function to advertise changed variables to other modules. -+ * -+ * Parameters are interface name, target module id and data. -+ * When sending the data, the module call back function contains the -+ * module id of the sender. -+ * -+ * Return 0 when no addressee found or addressess found but addressee was -+ * unable to handle data. -+ */ -+int modules_notify(int id, int sender_id, char *ifname, void *data) -+{ -+ struct lldp_module *mp = find_module_by_id(&lldp_head, id); -+ int rc = 0; -+ -+ if (mp && mp->ops->lldp_mod_notify) -+ rc = mp->ops->lldp_mod_notify(sender_id, ifname, data); -+ LLDPAD_DBG("%s:%s target-id:%#x rc:%d\n", __func__, ifname, id, rc); -+ return rc; -+} -diff --git a/test/nltest.c b/test/nltest.c -index 7ace3b1..da05463 100644 ---- a/test/nltest.c -+++ b/test/nltest.c -@@ -1156,12 +1156,14 @@ void print_pfc(struct ieee_pfc *pfc) - - printf("\t requests: "); - for (i = 0; i < 8; i++) -- printf("%lli ", pfc->requests[i]); -+ printf("%llu ", -+ (unsigned long long)pfc->requests[i]); - printf("\n"); - - printf("\t requests: "); - for (i = 0; i < 8; i++) -- printf("%lli ", pfc->indications[i]); -+ printf("%llu ", -+ (unsigned long long)pfc->indications[i]); - printf("\n"); - } - -diff --git a/test/qbg22/README b/test/qbg22/README -new file mode 100644 -index 0000000..bb0c6e8 ---- /dev/null -+++ b/test/qbg22/README -@@ -0,0 +1,19 @@ -+ -+(c) Copyright IBM Corp. 2013 -+ -+Thomas Richter, IBM Research and Development, Germany, April 2013 -+ -+Test cases for IEEE802.1Qbg ratified standard QBG22 support. -+ -+29-Apr-2013 -+=========== -+The test cases run on one machine using 2 network name spaces: -+1. Run on one machine using 2 network name spaces (requires linux-3.8 kernel). -+2. Create a pair of virtual network interfaces (veth0 and veth2) and assign -+ veth2 to network name space bridge_ns -+ -+lldpad (station rile) uses the default network name space and veth0. -+The qbg22 simulator program qbg22sim uses bridge_ns and veth2 interface. -+The lldpad (bridge role) vor vpd22 protocol testing uses the bridge_ns and -+veth2 interface and creates an unnamed IPC name space to have its on shared -+memory segment. -diff --git a/test/qbg22/ecp22/1-lldpad.conf b/test/qbg22/ecp22/1-lldpad.conf -new file mode 100644 -index 0000000..484322a ---- /dev/null -+++ b/test/qbg22/ecp22/1-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of ECP according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = false; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/ecp22/1.chk b/test/qbg22/ecp22/1.chk -new file mode 100644 -index 0000000..f5bf6df ---- /dev/null -+++ b/test/qbg22/ecp22/1.chk -@@ -0,0 +1,45 @@ -+#!/bin/bash -+# -+# Execute test case for LLDPAD testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2013 -+# Check of lldpad did start the ecp module, it shound not. -+ -+# Note first parameter is the test case number -+tfile=/tmp/$1-lldpad.conf.out -+ -+echo "check for ecp22 module not started" -+ -+if [ ! -r $tfile ] -+then -+ echo "lldpad trace file not readable" -+ exit 126 -+fi -+ -+if fgrep -q 'ecp22_start:veth0' $tfile -+then -+ echo "error ecp22 module started" -+ exit 125 -+fi -+ -+echo SUCCESS -+exit 0 -diff --git a/test/qbg22/ecp22/1.ecp b/test/qbg22/ecp22/1.ecp -new file mode 100644 -index 0000000..d1f8b95 ---- /dev/null -+++ b/test/qbg22/ecp22/1.ecp -@@ -0,0 +1,65 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (- is replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. ECP header and paylaod data field according to standard 802.1qbg -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * ECP negotiation -+ * Bridge does not offer reflective relay. -+ * Check that LLDPAD does not start ECP module. -+ */ -+ -+#include "defines.ecp" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_norr_ack -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_norr_ack -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_norr_ack -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_norr_ack -+ -+18 lldpad_mac - ecp_type 10:01 12:24 0a:0b:0c:0d -+21 lldpad_mac - ecp_type 10:01 12:25 0a:0b:0c:0d -+24 lldpad_mac - ecp_type 10:01 12:26 0a:0b:0c:0d -+ -+35 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/ecp22/10-lldpad.conf b/test/qbg22/ecp22/10-lldpad.conf -new file mode 100644 -index 0000000..2355662 ---- /dev/null -+++ b/test/qbg22/ecp22/10-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of ECP according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/ecp22/10.ecp b/test/qbg22/ecp22/10.ecp -new file mode 100644 -index 0000000..9cdbe18 ---- /dev/null -+++ b/test/qbg22/ecp22/10.ecp -@@ -0,0 +1,64 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (- is replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. ECP header and paylaod data field according to standard 802.1qbg -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * ECP negotiation -+ * Bridge offer reflective relay. -+ * Check that lldpad start ecp transmit state machine. -+ */ -+ -+#include "defines.ecp" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:def_counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:def_counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+ -+ -+60 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/ecp22/11-lldpad.conf b/test/qbg22/ecp22/11-lldpad.conf -new file mode 100644 -index 0000000..2355662 ---- /dev/null -+++ b/test/qbg22/ecp22/11-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of ECP according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/ecp22/11.ecp b/test/qbg22/ecp22/11.ecp -new file mode 100644 -index 0000000..937d2f0 ---- /dev/null -+++ b/test/qbg22/ecp22/11.ecp -@@ -0,0 +1,68 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (- is replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. ECP header and paylaod data field according to standard 802.1qbg -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * ECP negotiation -+ * Bridge offer reflective relay. -+ * Check that lldpad start ecp transmit state machine. -+ * Needs special code that transmits a data packet after some time out -+ * inside ECP module of lldpad !!!!!!!!!!!!!!!!!!!! -+ */ -+ -+#include "defines.ecp" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:def_counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:def_counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+11 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:6f:00:00 end_tlv @evbhead:03:05:6f:88:08 -+ -+ -+60 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/ecp22/2-lldpad.conf b/test/qbg22/ecp22/2-lldpad.conf -new file mode 100644 -index 0000000..2355662 ---- /dev/null -+++ b/test/qbg22/ecp22/2-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of ECP according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/ecp22/2.chk b/test/qbg22/ecp22/2.chk -new file mode 100644 -index 0000000..bb9aa41 ---- /dev/null -+++ b/test/qbg22/ecp22/2.chk -@@ -0,0 +1,54 @@ -+#!/bin/bash -+# -+# Execute test case for LLDPAD testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2013 -+# Check of lldpad did start the ecp module, it shound not. -+ -+# Note first parameter is the test case number -+ -+tfile=/tmp/$1-lldpad.conf.out -+ -+if [ ! -r $tfile ] -+then -+ echo "lldpad trace file not readable" -+ exit 126 -+fi -+ -+echo "check for ecp22 module started" -+ -+if ! fgrep -q 'ecp22_start:veth0' $tfile -+then -+ echo "error ecp22 module not started" -+ exit 125 -+fi -+ -+echo "check for one ULP notification" -+count=$(fgrep 'notify ULP 1 seqno 0x1224' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 invalid ULP notifications:$count" -+ exit 124 -+fi -+ -+echo SUCCESS -+exit 0 -diff --git a/test/qbg22/ecp22/2.ecp b/test/qbg22/ecp22/2.ecp -new file mode 100644 -index 0000000..3fcea5e ---- /dev/null -+++ b/test/qbg22/ecp22/2.ecp -@@ -0,0 +1,70 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (- is replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. ECP header and paylaod data field according to standard 802.1qbg -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * ECP negotiation -+ * Bridge offer reflective relay. -+ * Check that LLDPAD starts ECP module and negotiates sequence number exchange. -+ * Use same sequence number and check for acknowledgement. Only ONE!!!! upper -+ * layer notification on the lldpad side -+ */ -+ -+#include "defines.ecp" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:def_counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:def_counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+ -+15 lldpad_mac - ecp_type 10:01 12:24 end_tlv @14:01:12:24 -+16 lldpad_mac - ecp_type 10:01 12:24 end_tlv @14:01:12:24 -+17 lldpad_mac - ecp_type 10:01 12:24 end_tlv @14:01:12:24 -+ -+ -+30 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/ecp22/3-lldpad.conf b/test/qbg22/ecp22/3-lldpad.conf -new file mode 100644 -index 0000000..2355662 ---- /dev/null -+++ b/test/qbg22/ecp22/3-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of ECP according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/ecp22/3.chk b/test/qbg22/ecp22/3.chk -new file mode 100755 -index 0000000..a70475e ---- /dev/null -+++ b/test/qbg22/ecp22/3.chk -@@ -0,0 +1,68 @@ -+#!/bin/bash -+# -+# Execute test case for LLDPAD testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2013 -+# Check of lldpad did start the ecp module, it shound not. -+ -+# Note first parameter is the test case number -+ -+tfile=/tmp/$1-lldpad.conf.out -+ -+if [ ! -r $tfile ] -+then -+ echo "lldpad trace file not readable" -+ exit 126 -+fi -+ -+echo "check for ecp22 module started" -+ -+if ! fgrep -q 'ecp22_start:veth0' $tfile -+then -+ echo "error ecp22 module not started" -+ exit 125 -+fi -+ -+echo "check for one ULP notification seqno 0x1224" -+count=$(fgrep 'notify ULP 1 seqno 0x1224' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 invalid ULP notifications:$count sequence 0x1224" -+ exit 124 -+fi -+echo "check for one ULP notification seqno 0x1225" -+count=$(fgrep 'notify ULP 1 seqno 0x1225' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 invalid ULP notifications:$count sequence 0x1225" -+ exit 123 -+fi -+echo "check for one ULP notification seqno 0x1226" -+count=$(fgrep 'notify ULP 1 seqno 0x1226' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 invalid ULP notifications:$count sequence 0x1226" -+ exit 122 -+fi -+ -+echo SUCCESS -+exit 0 -diff --git a/test/qbg22/ecp22/3.ecp b/test/qbg22/ecp22/3.ecp -new file mode 100644 -index 0000000..d4f7b31 ---- /dev/null -+++ b/test/qbg22/ecp22/3.ecp -@@ -0,0 +1,70 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (- is replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. ECP header and paylaod data field according to standard 802.1qbg -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * ECP negotiation -+ * Bridge offer reflective relay. -+ * Check that LLDPAD starts ECP module and negotiates sequence number exchange. -+ * Use different sequence number and check for acknowledgement. 3 upper -+ * layer notification on the lldpad side -+ */ -+ -+#include "defines.ecp" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:def_counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:def_counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+ -+15 lldpad_mac - ecp_type 10:01 12:24 aa:bb:cc:dd end_tlv @14:01:12:24 -+17 lldpad_mac - ecp_type 10:01 12:25 00:11:22:33 end_tlv @14:01:12:25 -+19 lldpad_mac - ecp_type 10:01 12:26 44:55:66:77 end_tlv @14:01:12:26 -+ -+ -+30 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/ecp22/30-lldpad.conf b/test/qbg22/ecp22/30-lldpad.conf -new file mode 100644 -index 0000000..2355662 ---- /dev/null -+++ b/test/qbg22/ecp22/30-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of ECP according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/ecp22/30.ecp b/test/qbg22/ecp22/30.ecp -new file mode 100644 -index 0000000..63e06cf ---- /dev/null -+++ b/test/qbg22/ecp22/30.ecp -@@ -0,0 +1,83 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (- is replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. ECP header and paylaod data field according to standard 802.1qbg -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * ECP negotiation -+ * Bridge offer reflective relay. -+ * Check that LLDPAD starts ECP module and negotiates sequence number exchange. -+ */ -+ -+#include "defines.ecp" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:def_counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:def_counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+ -+20 lldpad_mac - ecp_type 10:01 12:30 44:55:66:77 end_tlv @14:01:12:30 -+ -+/* -+ * In the mean time disable and enable interface on target machine -+ * via remote executed shell script. Disable happens after 30 seconds and -+ * enable is after 40 seconds. -+ */ -+ -+45 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:def_counts -+46 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:def_counts -+47 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+48 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+49 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+60 lldpad_mac - ecp_type 10:01 12:31 44:55:66:77 end_tlv @14:01:12:31 -+ -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/ecp22/30.sh b/test/qbg22/ecp22/30.sh -new file mode 100755 -index 0000000..875c9ca ---- /dev/null -+++ b/test/qbg22/ecp22/30.sh -@@ -0,0 +1,38 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD ECP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Nov-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 30 seconds and disable/enable interface -+sleep 30; -+ip l s down dev veth0 -+sleep 10 -+ip l s up dev veth0 -+ip a sh dev veth0 | fgrep -q UP -+exit $? -+ -diff --git a/test/qbg22/ecp22/4-lldpad.conf b/test/qbg22/ecp22/4-lldpad.conf -new file mode 100644 -index 0000000..2355662 ---- /dev/null -+++ b/test/qbg22/ecp22/4-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of ECP according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/ecp22/4.chk b/test/qbg22/ecp22/4.chk -new file mode 100644 -index 0000000..d24eca4 ---- /dev/null -+++ b/test/qbg22/ecp22/4.chk -@@ -0,0 +1,68 @@ -+#!/bin/bash -+# -+# Execute test case for LLDPAD testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2013 -+# Check of lldpad did start the ecp module, it shound not. -+ -+# Note first parameter is the test case number -+ -+tfile=/tmp/$1-lldpad.conf.out -+ -+if [ ! -r $tfile ] -+then -+ echo "lldpad trace file not readable" -+ exit 126 -+fi -+ -+echo "check for ecp22 module started" -+ -+if ! fgrep -q 'ecp22_start:veth0' $tfile -+then -+ echo "error ecp22 module not started" -+ exit 125 -+fi -+ -+echo "check for unknown version 0xf001 seqno 0x1224" -+count=$(fgrep 'unknown version 0xf001 seqno 0x1224' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 unknown version 0xf001:$count sequence 0x1224" -+ exit 124 -+fi -+echo "check for unknown version 0xf001 seqno 0x1225" -+count=$(fgrep 'unknown version 0xf001 seqno 0x1225' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 unknown version 0xf001:$count sequence 0x1225" -+ exit 123 -+fi -+echo "check for unknown version 0xf001 seqno 0x1226" -+count=$(fgrep 'unknown version 0xf001 seqno 0x1226' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 unknown version 0xf001:$count sequence 0x1226" -+ exit 122 -+fi -+ -+echo SUCCESS -+exit 0 -diff --git a/test/qbg22/ecp22/4.ecp b/test/qbg22/ecp22/4.ecp -new file mode 100644 -index 0000000..79bb5ba ---- /dev/null -+++ b/test/qbg22/ecp22/4.ecp -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (- is replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. ECP header and paylaod data field according to standard 802.1qbg -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * ECP negotiation -+ * Bridge offer reflective relay. -+ * Check that LLDPAD starts ECP module and negotiates sequence number exchange. -+ * Use invalid version number. No acknowledgement expected. -+ * Use different sequence number and check for acknowledgement. No upper -+ * layer notification on the lldpad side. -+ */ -+ -+#include "defines.ecp" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:def_counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:def_counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+ -+15 lldpad_mac - ecp_type f0:01 12:24 aa:bb:cc:dd end_tlv -+17 lldpad_mac - ecp_type f0:01 12:25 00:11:22:33 end_tlv -+19 lldpad_mac - ecp_type f0:01 12:26 44:55:66:77 end_tlv -+ -+25 lldpad_mac - ecp_type 10:01 12:27 44:55:66:77 end_tlv @14:01:12:27 -+ -+30 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/ecp22/5-lldpad.conf b/test/qbg22/ecp22/5-lldpad.conf -new file mode 100644 -index 0000000..2355662 ---- /dev/null -+++ b/test/qbg22/ecp22/5-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of ECP according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/ecp22/5.chk b/test/qbg22/ecp22/5.chk -new file mode 100644 -index 0000000..a1e7c9a ---- /dev/null -+++ b/test/qbg22/ecp22/5.chk -@@ -0,0 +1,68 @@ -+#!/bin/bash -+# -+# Execute test case for LLDPAD testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2013 -+# Check of lldpad did start the ecp module, it shound not. -+ -+# Note first parameter is the test case number -+ -+tfile=/tmp/$1-lldpad.conf.out -+ -+if [ ! -r $tfile ] -+then -+ echo "lldpad trace file not readable" -+ exit 126 -+fi -+ -+echo "check for ecp22 module started" -+ -+if ! fgrep -q 'ecp22_start:veth0' $tfile -+then -+ echo "error ecp22 module not started" -+ exit 125 -+fi -+ -+echo "check for unknown subtype 0x100f seqno 0x1224" -+count=$(fgrep 'unknown subtype 0x100f seqno 0x1224' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 unknown subtype 0x100f:$count sequence 0x1224" -+ exit 124 -+fi -+echo "check for unknown subtype 0x100f seqno 0x1225" -+count=$(fgrep 'unknown subtype 0x100f seqno 0x1225' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 unknown subtype 0x100f:$count sequence 0x1225" -+ exit 123 -+fi -+echo "check for unknown subtype 0x100f seqno 0x1226" -+count=$(fgrep 'unknown subtype 0x100f seqno 0x1226' $tfile | wc -l) -+if [ "$count" -ne 1 ] -+then -+ echo "error ecp22 unknown subtype 0x100f:$count sequence 0x1226" -+ exit 122 -+fi -+ -+echo SUCCESS -+exit 0 -diff --git a/test/qbg22/ecp22/5.ecp b/test/qbg22/ecp22/5.ecp -new file mode 100644 -index 0000000..2d6c15a ---- /dev/null -+++ b/test/qbg22/ecp22/5.ecp -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (- is replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. ECP header and paylaod data field according to standard 802.1qbg -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * ECP negotiation -+ * Bridge offer reflective relay. -+ * Check that LLDPAD starts ECP module and negotiates sequence number exchange. -+ * Use invalid subtype number. No acknowledgement expected. -+ * Use different sequence number and check for acknowledgement. No upper -+ * layer notification on the lldpad side. -+ */ -+ -+#include "defines.ecp" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:def_counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:def_counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:def_counts -+ -+15 lldpad_mac - ecp_type 10:0f 12:24 aa:bb:cc:dd end_tlv -+17 lldpad_mac - ecp_type 10:0f 12:25 00:11:22:33 end_tlv -+19 lldpad_mac - ecp_type 10:0f 12:26 44:55:66:77 end_tlv -+ -+25 lldpad_mac - ecp_type 10:01 12:27 44:55:66:77 end_tlv @14:01:12:27 -+ -+30 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/ecp22/README b/test/qbg22/ecp22/README -new file mode 100644 -index 0000000..e0b2137 ---- /dev/null -+++ b/test/qbg22/ecp22/README -@@ -0,0 +1,80 @@ -+ -+Implementation of EVB according to IEEE 802.1Qbg -+(c) Copyright IBM Corp. 2014 -+ -+Author(s): Thomas Richter -+ -+This program is free software; you can redistribute it and/or modify it -+under the terms and conditions of the GNU General Public License, -+version 2, as published by the Free Software Foundation. -+ -+This program is distributed in the hope it will be useful, but WITHOUT -+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+more details. -+ -+You should have received a copy of the GNU General Public License along with -+this program; if not, write to the Free Software Foundation, Inc., -+51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ -+The full GNU General Public License is included in this distribution in -+the file called "COPYING". -+ -+Thomas Richter, IBM Research and Development, Germany, Aug 2012 -+ -+Test cases for IEEE802.1Qbg ratified standard ECP module. -+ -+Files -+===== -+There are 3 shell scripts which are executed on f18a. -+allecp.sh: Runs all test cases with file names [1-9]*.ecp. Uses -+ runecp.sh to execute one test case. -+ On success the exit code is zero, on failure none zero. -+ A none zero exit code termintes the programme immediately. -+runecp.sh Runs one test case. Symbolic link to runevb.sh -+3.sh .sh contain shell scripts to be executed -+ on the remote virtual machine. Usually done to change some -+ lldpad configuration settings during execution of lldpad. -+3.chk Runs a shell script to scan the lldpad trace file and -+ checks for proper entries. -+ -+Tests -+===== -+The following test cases are executed. Each test case has a number. -+All test cases need a lldpad.conf configuration file and an ECP test input -+file: -+- The ECP test input files have the extension .ecp. The test case number -+ is the base file name. -+- The lldpad configuration file has the extension -lldpad.conf. -+ -+The purpose is to trigger an ECP DU exchange between qbg22sim and llpdad. -+The exchanged data can be inspected automaticly with little inteligence -+(see qbg22sim.1) or manually. -+ -+Test Description -+1 bridge does not support refective-relay. -+2 bridge supports refective-relay. Use same sequence number -+3 bridge supports refective-relay. Use different sequence numbers -+4 bridge supports refective-relay. Use different invalid version -+5 bridge supports refective-relay. Use different invalid subversion -+30 bridge supports refective-relay. Interface will go down and up -+ again during the ECP module run time. -+ -+Remarks: -+ -+Test Execution -+============== -+Directory structure: -+ -+The following directory structure is assumed: -+/home/richter/dcn/qbg/mywork/open-lldp --> lldpad to test on target f18b -+/home/richter/dcn/qbg/mywork/testns/qbg22/evb22 --> EVB protocol test cases -+/home/richter/dcn/qbg/mywork/testns/qbg22/ecp22 --> ECP protocol test cases -+ -+Select the qbg22sim program by adding the path relative to test directory -+1. cd /home/richter/dcn/qbg/mywork/test/qbg22/ecp22 -+2. Symbolic link such as ./qbg22sim --> ../../../lldpad/qbg22sim. -+3. Add the environment variable LLDPAD_DIR=abc to select an different lldpad -+ executable. For example the invocation -+ LLDPAD_DIR=new ecpall.sh -+ selects the file /home/richter/dcn/qbg/mywork/new/lldpad for execution. -diff --git a/test/qbg22/ecp22/allecp.sh b/test/qbg22/ecp22/allecp.sh -new file mode 100755 -index 0000000..6f5a418 ---- /dev/null -+++ b/test/qbg22/ecp22/allecp.sh -@@ -0,0 +1,68 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD ECP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute the complete evb test suite. -+# -+ -+runcommand() -+{ -+ # echo parameter $@ -+ cmd=$1 -+ file=$2 -+ -+ echo "start testcase $number" -+ $cmd $file $@ 2>&1 -+ rc="$?" -+ if [ "$rc" -ne 0 ] -+ then -+ echo -en "\\033[1;31m" # Failures in red -+ echo "ERROR $file exit with $rc" -+ echo -en "\\033[0;39m" -+ exit 2 -+ fi -+ echo -en "\\033[1;32m" # Success in green -+ echo "OK testcase $file" -+ echo -en "\\033[0;39m" -+ return 0 -+} -+ -+# Extract type of test case from the first 3 characters of invocation file -+type=$(basename $0) -+type="${type:3:3}" -+ -+if ! which run$type.sh 2>/dev/null -+then -+ export PATH=$PATH:$PWD -+fi -+ -+echo "Start testsuite at $(date)" -+for i in $(ls [1-9]*.$type|sort -n) -+do -+ runcommand run$type.sh $i -+done -+echo "Stop testsuite at $(date)" -+exit 0 -diff --git a/test/qbg22/ecp22/defines.ecp b/test/qbg22/ecp22/defines.ecp -new file mode 100644 -index 0000000..ea53399 ---- /dev/null -+++ b/test/qbg22/ecp22/defines.ecp -@@ -0,0 +1,52 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * ECP Protocol test data. Define a complete ECP DU in hex. One complete set -+ * is needed for each transmission. -+ */ -+/* -+ * Very common defines -+ */ -+ -+#define lldpad_mac 01:80:c2:00:00:00 -+#define lldp_type 88:cc -+#define chassis_tlv 02:07:06:64:75:6d:6d:79:00 -+#define port_tlv 04:05:05:65:74:68:30 -+#define ttl_tlv120 06:02:00:78 -+#define ttl_tlv0 06:02:00:00 -+#define end_tlv 00:00 -+ -+#define evbhead fe:09:00:80:c2:0d -+#define def_counts 68:88:08 /* Default ECP values */ -+ -+/* Bridge denies reflective-relay */ -+#define evb_norr evbhead:00:00:00:40:00 -+#define evb_norr_ack evbhead:00:00:def_counts -+ -+#define ecp_type 89:40 -+ -+/* Bridge offers reflective-relay */ -+#define evb_brrr evbhead:02:00:00:40:00 -+#define evb_brrr_ack evbhead:02:00:def_counts -diff --git a/test/qbg22/ecp22/runecp.sh b/test/qbg22/ecp22/runecp.sh -new file mode 100755 -index 0000000..bf6b0ef ---- /dev/null -+++ b/test/qbg22/ecp22/runecp.sh -@@ -0,0 +1,153 @@ -+#!/bin/bash -+# -+# Execute test case for LLDPAD testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single test. Parameter is the name of the test file -+# -+ -+# Check if lldpad is up and running. Return pid or 0 if not running. -+# Note that lldpad may be started without creating a PID file. If no PID file -+# exists, use the lldptool to query the PID of lldpad. -+function lldpad_up() -+{ -+ if [ ! -r /var/run/lldpad.pid ] -+ then -+ pidfile=$(../../../lldptool -p 2>/dev/null) -+ if [ "$?" -ne 0 ] -+ then -+ return 0 -+ fi -+ else -+ pidfile="$(cat /var/run/lldpad.pid)" -+ fi -+ if [ -z "$pidfile" ] -+ then -+ return 0 -+ else -+ ps -p $pidfile -o pid --no-header > /dev/null -+ if [ $? -ne 0 ] -+ then -+ return 0 -+ fi -+ fi -+ echo "LLDPAD running pid $pidfile" -+ return $pidfile -+} -+ -+function lldpad_down() -+{ -+ if [ ! -r /var/run/lldpad.pid ] -+ then -+ pidfile=$(../../../lldptool -p 2>/dev/null) -+ if [ "$?" -ne 0 ] -+ then -+ return 1 -+ fi -+ else -+ pidfile="$(cat /var/run/lldpad.pid)" -+ fi -+ if [ -z "$pidfile" ] -+ then -+ return 1 -+ fi -+ kill -s SIGTERM $pidfile -+ sleep 1 -+ ps -p $pidfile -o pid --no-header > /dev/null -+ if [ $? -ne 1 ] -+ then -+ kill -s SIGKILL $pidfile -+ fi -+ return 0 -+} -+ -+# Use the correct lldpad configuration file and start lldpad. -+# Parameter 1: path to lldpad to use -+# Parameter 2: name of configuration file -+function lldpad_start() -+{ -+ if lldpad_up -+ then -+ rm -f /var/lib/lldpad/lldpad.conf ./lldpad.conf -+ cp $2 /tmp/$2 -+ $1/lldpad -V7 -f /tmp/$2 >/tmp/$2.out 2>&1 & -+ sleep 1 -+ if lldpad_up -+ then -+ echo "$0:lldpad not started or terminated unexpectedly" -+ exit 1 -+ fi -+ else -+ exit 1 -+ fi -+ return 0 -+} -+ -+if ! which runecp.sh 1>/dev/null 2>/dev/null -+then -+ export PATH=$PATH:$PWD -+fi -+ -+# Extract type of test case from last 3 characters of invocation -+type=$(basename $0) -+type=".${type:3:3}" -+ -+testfile=$1 -+no=$(basename $testfile $type) -+ -+# Start lldpad using this name space -+if ! lldpad_start ../../.. $no-lldpad.conf -+then -+ echo "$0:can not start lldpad" -+ exit 1 -+fi -+ -+# Check for shell script to run in parallel -+if [ -r "./$no.sh" -a -x "./$no.sh" ] -+then -+ ./$no.sh ../../.. & -+fi -+ -+# get the duration fron the last entry in the test file. -+duration=$(cpp $testfile | cut -f1 -d' ' | sed '/^$/d' | tail -1) -+let duration=duration+5 -+ -+# run the test with output save to /tmp/testfile.out -+ip netns exec bridge_ns ../../../qbg22sim -v -v -v -T 2500000 -d $duration veth2 $testfile > /tmp/$testfile.out -+rc=$? -+ -+# Stop lldpad -+if ! lldpad_down -+then -+ echo "$0:can not stop lldpad" -+ exit 1 -+fi -+ -+# Check for shell script to test result of test case -+if [ -r "./$no.chk" -a -x "./$no.chk" ] -+then -+ ./$no.chk $no >/tmp/$no.chk.out -+ rc=$? -+fi -+ -+exit $rc -diff --git a/test/qbg22/evb22/1-lldpad.conf b/test/qbg22/evb22/1-lldpad.conf -new file mode 100644 -index 0000000..280566b ---- /dev/null -+++ b/test/qbg22/evb22/1-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "041A17CEF5FBBD"; -+ }; -+ tlvid00000002 : -+ { -+ info = "031A17CEF5FBBD"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = false; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/1.evb b/test/qbg22/evb22/1.evb -new file mode 100644 -index 0000000..8c94f60 ---- /dev/null -+++ b/test/qbg22/evb22/1.evb -@@ -0,0 +1,59 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_norr_ack -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_norr_ack -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_norr_ack -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_norr_ack -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/10-lldpad.conf b/test/qbg22/evb22/10-lldpad.conf -new file mode 100644 -index 0000000..a219bbf ---- /dev/null -+++ b/test/qbg22/evb22/10-lldpad.conf -@@ -0,0 +1,32 @@ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/10.evb b/test/qbg22/evb22/10.evb -new file mode 100644 -index 0000000..e90cd1d ---- /dev/null -+++ b/test/qbg22/evb22/10.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. RKA value is lower than on station. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/11-lldpad.conf b/test/qbg22/evb22/11-lldpad.conf -new file mode 100644 -index 0000000..3f86198 ---- /dev/null -+++ b/test/qbg22/evb22/11-lldpad.conf -@@ -0,0 +1,54 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/11.evb b/test/qbg22/evb22/11.evb -new file mode 100644 -index 0000000..45b228a ---- /dev/null -+++ b/test/qbg22/evb22/11.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. RWD value is higher than on station. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:5f:00 end_tlv @evbhead:00:04:68:bf:08 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:5f:00 end_tlv @evbhead:00:04:68:bf:08 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:5f:00 end_tlv @evbhead:00:04:68:bf:08 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:5f:00 end_tlv @evbhead:00:04:68:bf:08 -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/12-lldpad.conf b/test/qbg22/evb22/12-lldpad.conf -new file mode 100644 -index 0000000..3f86198 ---- /dev/null -+++ b/test/qbg22/evb22/12-lldpad.conf -@@ -0,0 +1,54 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/12.evb b/test/qbg22/evb22/12.evb -new file mode 100644 -index 0000000..0de9daa ---- /dev/null -+++ b/test/qbg22/evb22/12.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. RWD value is lower than on station. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/13-lldpad.conf b/test/qbg22/evb22/13-lldpad.conf -new file mode 100644 -index 0000000..3f86198 ---- /dev/null -+++ b/test/qbg22/evb22/13-lldpad.conf -@@ -0,0 +1,54 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/13.evb b/test/qbg22/evb22/13.evb -new file mode 100644 -index 0000000..1b41f46 ---- /dev/null -+++ b/test/qbg22/evb22/13.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. Retry value is higher than on station. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:e0:40:00 end_tlv @evbhead:00:04:e8:88:08 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:e0:40:00 end_tlv @evbhead:00:04:e8:88:08 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:e0:40:00 end_tlv @evbhead:00:04:e8:88:08 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:e0:40:00 end_tlv @evbhead:00:04:e8:88:08 -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/14-lldpad.conf b/test/qbg22/evb22/14-lldpad.conf -new file mode 100644 -index 0000000..3f86198 ---- /dev/null -+++ b/test/qbg22/evb22/14-lldpad.conf -@@ -0,0 +1,54 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/14.evb b/test/qbg22/evb22/14.evb -new file mode 100644 -index 0000000..0de9daa ---- /dev/null -+++ b/test/qbg22/evb22/14.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. RWD value is lower than on station. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/2-lldpad.conf b/test/qbg22/evb22/2-lldpad.conf -new file mode 100644 -index 0000000..0db19ce ---- /dev/null -+++ b/test/qbg22/evb22/2-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = false; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/2.evb b/test/qbg22/evb22/2.evb -new file mode 100644 -index 0000000..2059520 ---- /dev/null -+++ b/test/qbg22/evb22/2.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay but station -+ * does not request it. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evb_brrr_ack -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evb_brrr_ack -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evb_brrr_ack -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evb_brrr_ack -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/20-lldpad.conf b/test/qbg22/evb22/20-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/20-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/20.evb b/test/qbg22/evb22/20.evb -new file mode 100644 -index 0000000..43cfd94 ---- /dev/null -+++ b/test/qbg22/evb22/20.evb -@@ -0,0 +1,62 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge sets group id bit, but station denies. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:04:00:00:00 end_tlv @evbhead:07:05:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:00:00 end_tlv @evbhead:07:05:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:00:00 end_tlv @evbhead:07:05:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:00:00 end_tlv @evbhead:07:05:counts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/21-lldpad.conf b/test/qbg22/evb22/21-lldpad.conf -new file mode 100644 -index 0000000..456da71 ---- /dev/null -+++ b/test/qbg22/evb22/21-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/21.evb b/test/qbg22/evb22/21.evb -new file mode 100644 -index 0000000..d68e299 ---- /dev/null -+++ b/test/qbg22/evb22/21.evb -@@ -0,0 +1,62 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge denies group id bit, but station sets it. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:40:00 end_tlv @evbhead:02:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0c:00:00:00 end_tlv @evbhead:03:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0c:00:00:00 end_tlv @evbhead:03:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0c:00:00:00 end_tlv @evbhead:03:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0c:00:00:00 end_tlv @evbhead:03:0d:counts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/22-lldpad.conf b/test/qbg22/evb22/22-lldpad.conf -new file mode 100644 -index 0000000..456da71 ---- /dev/null -+++ b/test/qbg22/evb22/22-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/22.evb b/test/qbg22/evb22/22.evb -new file mode 100644 -index 0000000..628a7ea ---- /dev/null -+++ b/test/qbg22/evb22/22.evb -@@ -0,0 +1,62 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:00:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:00:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:00:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:00:00 end_tlv @evbhead:07:0d:counts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/23-lldpad.conf b/test/qbg22/evb22/23-lldpad.conf -new file mode 100644 -index 0000000..456da71 ---- /dev/null -+++ b/test/qbg22/evb22/23-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/23.evb b/test/qbg22/evb22/23.evb -new file mode 100644 -index 0000000..ebce9c9 ---- /dev/null -+++ b/test/qbg22/evb22/23.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. Bridge turns off bgid -+ * later. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:00:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:00:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:00:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:00:00 end_tlv @evbhead:07:0d:counts -+40 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0d:00:00:00 end_tlv @evbhead:03:0d:counts -+41 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0d:00:00:00 end_tlv @evbhead:03:0d:counts -+42 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0d:00:00:00 end_tlv @evbhead:03:0d:counts -+43 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0d:00:00:00 end_tlv @evbhead:03:0d:counts -+44 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:0d:00:00:00 end_tlv @evbhead:03:0d:counts -diff --git a/test/qbg22/evb22/24-lldpad.conf b/test/qbg22/evb22/24-lldpad.conf -new file mode 100644 -index 0000000..456da71 ---- /dev/null -+++ b/test/qbg22/evb22/24-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/24.evb b/test/qbg22/evb22/24.evb -new file mode 100644 -index 0000000..d79a2a9 ---- /dev/null -+++ b/test/qbg22/evb22/24.evb -@@ -0,0 +1,73 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. Station turns off -+ * sgid later. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:05:counts -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:05:counts -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:05:counts -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:05:counts -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:05:counts -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/24.sh b/test/qbg22/evb22/24.sh -new file mode 100755 -index 0000000..f208a1d ---- /dev/null -+++ b/test/qbg22/evb22/24.sh -@@ -0,0 +1,33 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds change setting -+sleep 50; -+$1/lldptool -i veth0 -gncb -T -V evb -c evbgpid=no -diff --git a/test/qbg22/evb22/25-lldpad.conf b/test/qbg22/evb22/25-lldpad.conf -new file mode 100644 -index 0000000..cea1077 ---- /dev/null -+++ b/test/qbg22/evb22/25-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = false; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/25.evb b/test/qbg22/evb22/25.evb -new file mode 100644 -index 0000000..e78fd0b ---- /dev/null -+++ b/test/qbg22/evb22/25.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv \\ -+ @02:07:04:e6:f1:20:5a:b0:e6\\ -+ @04:07:03:e6:f1:20:5a:b0:e6\\ -+ @06:02:00:78:00:00 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv \\ -+ @02:07:04:e6:f1:20:5a:b0:e6\\ -+ @04:07:03:e6:f1:20:5a:b0:e6\\ -+ @06:02:00:78:00:00 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv \\ -+ @02:07:04:e6:f1:20:5a:b0:e6\\ -+ @04:07:03:e6:f1:20:5a:b0:e6\\ -+ @06:02:00:78:00:00 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv \\ -+ @02:07:04:e6:f1:20:5a:b0:e6\\ -+ @04:07:03:e6:f1:20:5a:b0:e6\\ -+ @06:02:00:78:00:00 -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/26-lldpad.conf b/test/qbg22/evb22/26-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/26-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/26.evb b/test/qbg22/evb22/26.evb -new file mode 100644 -index 0000000..f3ff74d ---- /dev/null -+++ b/test/qbg22/evb22/26.evb -@@ -0,0 +1,83 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:counts -+10 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:counts -+11 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:counts -+41 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv \\ -+ @02:07:04:e6:f1:20:5a:b0:e6\\ -+ @04:07:03:e6:f1:20:5a:b0:e6\\ -+ @06:02:00:78:00:00 -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv \\ -+ @02:07:04:e6:f1:20:5a:b0:e6\\ -+ @04:07:03:e6:f1:20:5a:b0:e6\\ -+ @06:02:00:78:00:00 -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv \\ -+ @02:07:04:e6:f1:20:5a:b0:e6\\ -+ @04:07:03:e6:f1:20:5a:b0:e6\\ -+ @06:02:00:78:00:00 -+90 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/26.sh b/test/qbg22/evb22/26.sh -new file mode 100755 -index 0000000..10abfac ---- /dev/null -+++ b/test/qbg22/evb22/26.sh -@@ -0,0 +1,33 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds change setting -+sleep 50; -+$1/lldptool -i veth0 -gncb -T -V evb -c enableTx=no -diff --git a/test/qbg22/evb22/3-lldpad.conf b/test/qbg22/evb22/3-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/3-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/3.evb b/test/qbg22/evb22/3.evb -new file mode 100644 -index 0000000..cd80fd0 ---- /dev/null -+++ b/test/qbg22/evb22/3.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv @evb_strr_ack -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr2 end_tlv @evb_strr_ack -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr2 end_tlv @evb_strr_ack -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr2 end_tlv @evb_strr_ack -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/30-lldpad.conf b/test/qbg22/evb22/30-lldpad.conf -new file mode 100644 -index 0000000..0b1dcd8 ---- /dev/null -+++ b/test/qbg22/evb22/30-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "bridge"; -+ evbrrcap = false; -+ evbrrreq = false; -+ evbgpid = false; -+ ecpretries = 5; -+ ecprte = 6; -+ vdprwd = 24; -+ vdprka = 24; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/30.evb b/test/qbg22/evb22/30.evb -new file mode 100644 -index 0000000..49bbe29 ---- /dev/null -+++ b/test/qbg22/evb22/30.evb -@@ -0,0 +1,61 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Runs a station. No reflective relay and sgid support. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:01:00:80:00 end_tlv @evbhead:00:01:stcounts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:00:00 end_tlv @evbhead:00:00:stcounts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:00:00 end_tlv @evbhead:00:00:stcounts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:00:00 end_tlv @evbhead:00:00:stcounts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:00:00 end_tlv @evbhead:00:00:stcounts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/31-lldpad.conf b/test/qbg22/evb22/31-lldpad.conf -new file mode 100644 -index 0000000..e2a7c42 ---- /dev/null -+++ b/test/qbg22/evb22/31-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "bridge"; -+ evbrrcap = true; -+ evbrrreq = false; -+ evbgpid = false; -+ ecpretries = 5; -+ ecprte = 6; -+ vdprwd = 24; -+ vdprka = 24; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/31.evb b/test/qbg22/evb22/31.evb -new file mode 100644 -index 0000000..4b6d8e6 ---- /dev/null -+++ b/test/qbg22/evb22/31.evb -@@ -0,0 +1,62 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Runs a station. Bridge offers reflective relay, -+ * no sgid support. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:01:00:80:00 end_tlv @evbhead:02:01:stcounts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:00:00 end_tlv @evbhead:02:00:stcounts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:00:00 end_tlv @evbhead:02:00:stcounts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:00:00 end_tlv @evbhead:02:00:stcounts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:00:00 end_tlv @evbhead:02:00:stcounts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/32-lldpad.conf b/test/qbg22/evb22/32-lldpad.conf -new file mode 100644 -index 0000000..78608e4 ---- /dev/null -+++ b/test/qbg22/evb22/32-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "bridge"; -+ evbrrcap = true; -+ evbrrreq = false; -+ evbgpid = true; -+ ecpretries = 5; -+ ecprte = 6; -+ vdprwd = 24; -+ vdprka = 24; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/32.evb b/test/qbg22/evb22/32.evb -new file mode 100644 -index 0000000..23127c4 ---- /dev/null -+++ b/test/qbg22/evb22/32.evb -@@ -0,0 +1,62 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Runs a station. Bridge offers reflective relay and -+ * sgid support. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:01:00:80:00 end_tlv @evbhead:06:01:stcounts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:00:00 end_tlv @evbhead:06:00:stcounts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:00:00 end_tlv @evbhead:06:00:stcounts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:00:00 end_tlv @evbhead:06:00:stcounts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:00:00 end_tlv @evbhead:06:00:stcounts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/33-lldpad.conf b/test/qbg22/evb22/33-lldpad.conf -new file mode 100644 -index 0000000..78608e4 ---- /dev/null -+++ b/test/qbg22/evb22/33-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "bridge"; -+ evbrrcap = true; -+ evbrrreq = false; -+ evbgpid = true; -+ ecpretries = 5; -+ ecprte = 6; -+ vdprwd = 24; -+ vdprka = 24; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/33.evb b/test/qbg22/evb22/33.evb -new file mode 100644 -index 0000000..65da9d2 ---- /dev/null -+++ b/test/qbg22/evb22/33.evb -@@ -0,0 +1,62 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Runs a station. Bridge offers eflective relay and -+ * sgid support. Station accepts both. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:0d:00:80:00 end_tlv @evbhead:07:0d:stcounts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0e:00:00:00 end_tlv @evbhead:07:0e:stcounts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0e:00:00:00 end_tlv @evbhead:07:0e:stcounts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0e:00:00:00 end_tlv @evbhead:07:0e:stcounts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0e:00:00:00 end_tlv @evbhead:07:0e:stcounts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/4-lldpad.conf b/test/qbg22/evb22/4-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/4-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/4.evb b/test/qbg22/evb22/4.evb -new file mode 100644 -index 0000000..e64e5b5 ---- /dev/null -+++ b/test/qbg22/evb22/4.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:00:00 end_tlv @evbhead:03:05:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:00:00 end_tlv @evbhead:03:05:counts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/41-lldpad.conf b/test/qbg22/evb22/41-lldpad.conf -new file mode 100644 -index 0000000..ec9b520 ---- /dev/null -+++ b/test/qbg22/evb22/41-lldpad.conf -@@ -0,0 +1,43 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ }; -+}; -diff --git a/test/qbg22/evb22/41.evb b/test/qbg22/evb22/41.evb -new file mode 100644 -index 0000000..ef941ce ---- /dev/null -+++ b/test/qbg22/evb22/41.evb -@@ -0,0 +1,57 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Do nothing, send data and expect no response. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+35 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+65 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -diff --git a/test/qbg22/evb22/41.sh b/test/qbg22/evb22/41.sh -new file mode 100755 -index 0000000..03a1d00 ---- /dev/null -+++ b/test/qbg22/evb22/41.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait some seconds and then change setting, define evb22.enableTx=no -+sleep 30; -+$1/lldptool -i veth0 -gncb -T -V evb -c enableTx=no -+rc=$? -+if [ $rc -ne 0 ] -+then -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c enabletx=no" -+ exit $rc -+fi -+ -+sleep 20 -+$1/lldptool -i veth0 -gncb -T -V evbcfg -c enableTx=no -+rc=$? -+if [ $rc -ne 0 ] -+then -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evbcfg -c enabletx=no" -+ exit $rc -+fi -+ -+sleep 10 -+lines="$(fgrep 'enableTx = false;' /tmp/$(basename $0 .sh)-lldpad.conf | wc -l)" -+ -+if [ "x$lines" != x2 ] -+then -+ rc=5 -+ echo $rc "FAILURE:lldptool -V evbcfg/evb -c enabletx=no" -+fi -+exit $rc -diff --git a/test/qbg22/evb22/42-lldpad.conf b/test/qbg22/evb22/42-lldpad.conf -new file mode 100644 -index 0000000..ec9b520 ---- /dev/null -+++ b/test/qbg22/evb22/42-lldpad.conf -@@ -0,0 +1,43 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ }; -+}; -diff --git a/test/qbg22/evb22/42.evb b/test/qbg22/evb22/42.evb -new file mode 100644 -index 0000000..ef941ce ---- /dev/null -+++ b/test/qbg22/evb22/42.evb -@@ -0,0 +1,57 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Do nothing, send data and expect no response. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+35 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+65 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -diff --git a/test/qbg22/evb22/42.sh b/test/qbg22/evb22/42.sh -new file mode 100755 -index 0000000..dd9d179 ---- /dev/null -+++ b/test/qbg22/evb22/42.sh -@@ -0,0 +1,65 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait some seconds and then change setting -+sleep 30; -+$1/lldptool -i veth0 -gncb -T -V evb -c enableTx=no -+rc=$? -+if [ $rc -ne 0 ] -+then -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c enabletx=no" -+ exit $rc -+fi -+lines="$(fgrep 'enableTx = false;' /tmp/$(basename $0 .sh)-lldpad.conf | wc -l)" -+if [ "x$lines" != x1 ] -+then -+ rc=4 -+ echo $rc "FAILURE:lldptool -V evb -c enabletx=no" -+ exit $rc -+fi -+ -+sleep 20 -+$1/lldptool -i veth0 -gncb -T -V evbcfg -c enableTx=yes -c fmode=reflectiverelay -c capabilities="rte ecp vdp" -+rc=$? -+if [ $rc -ne 0 ] -+then -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evbcfg -c enabletx=yes ..." -+ exit $rc -+fi -+ -+lines="$(fgrep 'enableTx = true;' /tmp/$(basename $0 .sh)-lldpad.conf | wc -l)" -+if [ "x$lines" != x1 ] -+then -+ rc=5 -+ echo $rc "FAILURE:lldptool -V evbcfg -c enabletx=yes ..." -+ echo lines $lines -+ exit $rc -+fi -+exit $rc -diff --git a/test/qbg22/evb22/43-lldpad.conf b/test/qbg22/evb22/43-lldpad.conf -new file mode 100644 -index 0000000..ec9b520 ---- /dev/null -+++ b/test/qbg22/evb22/43-lldpad.conf -@@ -0,0 +1,43 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ }; -+}; -diff --git a/test/qbg22/evb22/43.evb b/test/qbg22/evb22/43.evb -new file mode 100644 -index 0000000..ef941ce ---- /dev/null -+++ b/test/qbg22/evb22/43.evb -@@ -0,0 +1,57 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Do nothing, send data and expect no response. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+35 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+65 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -diff --git a/test/qbg22/evb22/43.sh b/test/qbg22/evb22/43.sh -new file mode 100755 -index 0000000..4961e59 ---- /dev/null -+++ b/test/qbg22/evb22/43.sh -@@ -0,0 +1,64 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait some seconds and then change setting -+sleep 30; -+$1/lldptool -i veth0 -gncb -T -V evb -c enableTx=yes -+rc=$? -+if [ $rc -ne 0 ] -+then -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c enabletx=yes" -+ exit $rc -+fi -+lines="$(fgrep 'enableTx = true;' /tmp/$(basename $0 .sh)-lldpad.conf | wc -l)" -+if [ "x$lines" != x1 ] -+then -+ rc=4 -+ echo $rc "FAILURE:lldptool -V evb -c enabletx=no" -+ exit $rc -+fi -+ -+sleep 20 -+$1/lldptool -i veth0 -gncb -T -V evbcfg -c enableTx=no -c fmode=reflectiverelay -c capabilities="rte ecp vdp" -+rc=$? -+if [ $rc -ne 0 ] -+then -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evbcfg -c enabletx=no ..." -+ exit $rc -+fi -+ -+lines="$(fgrep 'enableTx = false;' /tmp/$(basename $0 .sh)-lldpad.conf | wc -l)" -+if [ "x$lines" != x1 ] -+then -+ rc=5 -+ echo $rc "FAILURE:lldptool -V evbcfg -c enabletx=no ..." -+ exit $rc -+fi -+exit $rc -diff --git a/test/qbg22/evb22/44-lldpad.conf b/test/qbg22/evb22/44-lldpad.conf -new file mode 100644 -index 0000000..ec9b520 ---- /dev/null -+++ b/test/qbg22/evb22/44-lldpad.conf -@@ -0,0 +1,43 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ }; -+}; -diff --git a/test/qbg22/evb22/44.evb b/test/qbg22/evb22/44.evb -new file mode 100644 -index 0000000..d0b552e ---- /dev/null -+++ b/test/qbg22/evb22/44.evb -@@ -0,0 +1,59 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Do nothing, send data and expect no response. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+35 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+65 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+95 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+125 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -diff --git a/test/qbg22/evb22/44.sh b/test/qbg22/evb22/44.sh -new file mode 100755 -index 0000000..351a478 ---- /dev/null -+++ b/test/qbg22/evb22/44.sh -@@ -0,0 +1,60 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait some seconds and then change setting -+sleep 30; -+$1/lldptool -i veth0 -gncb -T -V evbcfg -c enableTx=yes -c fmode=reflectiverelay -c capabilities="rte ecp vdp" -+rc=$? -+if [ $rc -ne 0 ] -+then -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evbcfg -c enabletx=yes ..." -+ exit $rc -+fi -+ -+sleep 20 -+# Command must not succeed -+$1/lldptool -i veth0 -gncb -T -V evb -c enableTx=yes >/dev/null -+rc=$? -+if [ $rc -ne 1 ] -+then -+ rc=4 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c enabletx=yes" -+ exit $rc -+fi -+rc=0 -+ -+sleep 30 -+lines="$(fgrep 'enableTx = true;' /tmp/$(basename $0 .sh)-lldpad.conf | wc -l)" -+if [ "x$lines" != x1 ] -+then -+ rc=5 -+ echo $rc "FAILURE:lldptool -V evbcfg/evb -c enabletx=yes" -+fi -+exit $rc -diff --git a/test/qbg22/evb22/45-lldpad.conf b/test/qbg22/evb22/45-lldpad.conf -new file mode 100644 -index 0000000..12b2304 ---- /dev/null -+++ b/test/qbg22/evb22/45-lldpad.conf -@@ -0,0 +1,53 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid001b3f00 : -+ { -+ enableTx = true; -+ fmode = "reflectiverelay"; -+ capabilities = "rte ecp vdp"; -+ }; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/45.evb b/test/qbg22/evb22/45.evb -new file mode 100644 -index 0000000..bdcd955 ---- /dev/null -+++ b/test/qbg22/evb22/45.evb -@@ -0,0 +1,56 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Do nothing, send data and expect no response. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+35 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -diff --git a/test/qbg22/evb22/45.sh b/test/qbg22/evb22/45.sh -new file mode 100755 -index 0000000..a4dacf7 ---- /dev/null -+++ b/test/qbg22/evb22/45.sh -@@ -0,0 +1,40 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait some seconds and then change setting -+sleep 30; -+rc=0 -+hit="$(fgrep 'evb22_ifup:veth0 evb draft 0.2 protocol already enabled' /tmp/$(basename $0 .sh)-lldpad.conf.out )" -+if [ -z "$hit" ] -+then -+ rc=4 -+ echo $rc "FAILURE:lldpad configuration file has evb and evb22 enabled" -+fi -+exit $rc -diff --git a/test/qbg22/evb22/46-lldpad.conf b/test/qbg22/evb22/46-lldpad.conf -new file mode 100644 -index 0000000..ec9b520 ---- /dev/null -+++ b/test/qbg22/evb22/46-lldpad.conf -@@ -0,0 +1,43 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ }; -+}; -diff --git a/test/qbg22/evb22/46.evb b/test/qbg22/evb22/46.evb -new file mode 100644 -index 0000000..d0b552e ---- /dev/null -+++ b/test/qbg22/evb22/46.evb -@@ -0,0 +1,59 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - Do nothing, send data and expect no response. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+35 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+65 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+95 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -+125 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 -diff --git a/test/qbg22/evb22/46.sh b/test/qbg22/evb22/46.sh -new file mode 100755 -index 0000000..49142b4 ---- /dev/null -+++ b/test/qbg22/evb22/46.sh -@@ -0,0 +1,60 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait some seconds and then change setting -+sleep 30; -+$1/lldptool -i veth0 -gncb -T -V evb -c enableTx=yes -+rc=$? -+if [ $rc -ne 0 ] -+then -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evbcfg -c enabletx=yes ..." -+ exit $rc -+fi -+ -+sleep 20 -+# command must not succeed -+$1/lldptool -i veth0 -gncb -T -V evbcfg -c enableTx=yes -c fmode=reflectiverelay -c capabilities="rte ecp vdp" > /dev/null -+rc=$? -+if [ $rc -ne 1 ] -+then -+ rc=3 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c enabletx=yes" -+ exit $rc -+fi -+rc=0 -+ -+sleep 10 -+lines="$(fgrep 'enableTx = true;' /tmp/$(basename $0 .sh)-lldpad.conf | wc -l)" -+if [ "x$lines" != x1 ] -+then -+ rc=5 -+ echo $rc "FAILURE:lldptool -V evbcfg/evb -c enabletx=yes" -+fi -+exit $rc -diff --git a/test/qbg22/evb22/5-lldpad.conf b/test/qbg22/evb22/5-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/5-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/5.evb b/test/qbg22/evb22/5.evb -new file mode 100644 -index 0000000..8367de0 ---- /dev/null -+++ b/test/qbg22/evb22/5.evb -@@ -0,0 +1,75 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation -+ * - bridge offers support for reflective relay. -+ * - station request it. -+ * - bridge withdraws reflective relay support some time later. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:40:00 end_tlv @evbhead:03:05:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:40:00 end_tlv @evbhead:03:05:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:40:00 end_tlv @evbhead:03:05:counts -+41 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:40:00 end_tlv @evbhead:03:05:counts -+60 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:06:00:40:00 end_tlv @evbhead:00:04:counts -+61 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:04:00:40:00 end_tlv @evbhead:00:04:counts -+62 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:04:00:40:00 end_tlv @evbhead:00:04:counts -+63 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:04:00:40:00 end_tlv @evbhead:00:04:counts -+64 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:04:00:40:00 end_tlv @evbhead:00:04:counts -+ -+75 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/6-lldpad.conf b/test/qbg22/evb22/6-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/6-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/6.evb b/test/qbg22/evb22/6.evb -new file mode 100644 -index 0000000..c01377c ---- /dev/null -+++ b/test/qbg22/evb22/6.evb -@@ -0,0 +1,75 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation -+ * - bridge offers support for reflective relay. -+ * - station request it. -+ * - station withdraws reflective relay support some time later. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_brrr end_tlv @evbhead:02:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:04:00:40:00 end_tlv @evbhead:03:05:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:40:00 end_tlv @evbhead:03:05:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:40:00 end_tlv @evbhead:03:05:counts -+41 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:03:05:00:40:00 end_tlv @evbhead:03:05:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:40:00 end_tlv @evbhead:02:00:counts -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:40:00 end_tlv @evbhead:02:00:counts -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:40:00 end_tlv @evbhead:02:00:counts -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:40:00 end_tlv @evbhead:02:00:counts -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:02:00:00:40:00 end_tlv @evbhead:02:00:counts -+ -+75 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/6.sh b/test/qbg22/evb22/6.sh -new file mode 100755 -index 0000000..557cc60 ---- /dev/null -+++ b/test/qbg22/evb22/6.sh -@@ -0,0 +1,33 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds change setting -+sleep 50; -+$1/lldptool -i veth0 -gncb -T -V evb -c evbrrreq=no -diff --git a/test/qbg22/evb22/7-lldpad.conf b/test/qbg22/evb22/7-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/7-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/7.evb b/test/qbg22/evb22/7.evb -new file mode 100644 -index 0000000..ea13107 ---- /dev/null -+++ b/test/qbg22/evb22/7.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. RTE value is higher than on station. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:1f:40:00 end_tlv @evbhead:00:04:7f:88:08 -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:1f:40:00 end_tlv @evbhead:00:04:7f:88:08 -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:1f:40:00 end_tlv @evbhead:00:04:7f:88:08 -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:1f:40:00 end_tlv @evbhead:00:04:7f:88:08 -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/8-lldpad.conf b/test/qbg22/evb22/8-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/8-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/8.evb b/test/qbg22/evb22/8.evb -new file mode 100644 -index 0000000..26b10c7 ---- /dev/null -+++ b/test/qbg22/evb22/8.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. RTE value is lower than on station. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:40:00 end_tlv @evbhead:00:04:counts -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/80-lldpad.conf b/test/qbg22/evb22/80-lldpad.conf -new file mode 100644 -index 0000000..456da71 ---- /dev/null -+++ b/test/qbg22/evb22/80-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/80.evb b/test/qbg22/evb22/80.evb -new file mode 100644 -index 0000000..12924b9 ---- /dev/null -+++ b/test/qbg22/evb22/80.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:0d:counts -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:0d:counts -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:0d:counts -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:0d:counts -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv @evbhead:07:0d:counts -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/80.sh b/test/qbg22/evb22/80.sh -new file mode 100755 -index 0000000..fb8e3fa ---- /dev/null -+++ b/test/qbg22/evb22/80.sh -@@ -0,0 +1,47 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+# Replace newlines by blanks for easier comparison -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c | tr '\n' ' ') -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ #echo out ":$out:" -+ if [ "$out" != "vdprka=8 vdprwd=8 ecprte=8 ecpretries=3 evbrrreq=yes evbrrcap=no evbgpid=yes evbmode=station enableTx=yes " ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -diff --git a/test/qbg22/evb22/81-lldpad.conf b/test/qbg22/evb22/81-lldpad.conf -new file mode 100644 -index 0000000..456da71 ---- /dev/null -+++ b/test/qbg22/evb22/81-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/81.evb b/test/qbg22/evb22/81.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/81.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/81.sh b/test/qbg22/evb22/81.sh -new file mode 100755 -index 0000000..03490ca ---- /dev/null -+++ b/test/qbg22/evb22/81.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c enabletx=no -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c enabletx=no" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c enabletx) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "enableTx=no" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/82-lldpad.conf b/test/qbg22/evb22/82-lldpad.conf -new file mode 100644 -index 0000000..456da71 ---- /dev/null -+++ b/test/qbg22/evb22/82-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/82.evb b/test/qbg22/evb22/82.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/82.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/82.sh b/test/qbg22/evb22/82.sh -new file mode 100755 -index 0000000..4db9e0b ---- /dev/null -+++ b/test/qbg22/evb22/82.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c evbmode=bridge -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c evbmode=bridge" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c evbmode) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "evbmode=bridge" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/83-lldpad.conf b/test/qbg22/evb22/83-lldpad.conf -new file mode 100644 -index 0000000..456da71 ---- /dev/null -+++ b/test/qbg22/evb22/83-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/83.evb b/test/qbg22/evb22/83.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/83.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/83.sh b/test/qbg22/evb22/83.sh -new file mode 100755 -index 0000000..fbdce26 ---- /dev/null -+++ b/test/qbg22/evb22/83.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c evbrrreq=no -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c evbrrreq=no" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c evbrrreq) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "evbrrreq=no" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/84-lldpad.conf b/test/qbg22/evb22/84-lldpad.conf -new file mode 100644 -index 0000000..20ef072 ---- /dev/null -+++ b/test/qbg22/evb22/84-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/84.evb b/test/qbg22/evb22/84.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/84.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/84.sh b/test/qbg22/evb22/84.sh -new file mode 100755 -index 0000000..092f35a ---- /dev/null -+++ b/test/qbg22/evb22/84.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c evbrrcap=no -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c evbrrcap=no" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c evbrrcap) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "evbrrcap=no" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/85-lldpad.conf b/test/qbg22/evb22/85-lldpad.conf -new file mode 100644 -index 0000000..20ef072 ---- /dev/null -+++ b/test/qbg22/evb22/85-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/85.evb b/test/qbg22/evb22/85.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/85.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/85.sh b/test/qbg22/evb22/85.sh -new file mode 100755 -index 0000000..597a3ff ---- /dev/null -+++ b/test/qbg22/evb22/85.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c evbgpid=no -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c evbgpid=no" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c evbgpid) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "evbgpid=no" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/86-lldpad.conf b/test/qbg22/evb22/86-lldpad.conf -new file mode 100644 -index 0000000..20ef072 ---- /dev/null -+++ b/test/qbg22/evb22/86-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/86.evb b/test/qbg22/evb22/86.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/86.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/86.sh b/test/qbg22/evb22/86.sh -new file mode 100755 -index 0000000..882220f ---- /dev/null -+++ b/test/qbg22/evb22/86.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c ecpretries=7 -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c ecpretries=7" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c ecpretries) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "ecpretries=7" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/87-lldpad.conf b/test/qbg22/evb22/87-lldpad.conf -new file mode 100644 -index 0000000..20ef072 ---- /dev/null -+++ b/test/qbg22/evb22/87-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/87.evb b/test/qbg22/evb22/87.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/87.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/87.sh b/test/qbg22/evb22/87.sh -new file mode 100755 -index 0000000..17f7b96 ---- /dev/null -+++ b/test/qbg22/evb22/87.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c ecprte=31 -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c ecprte=31" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c ecprte) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "ecprte=31" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/88-lldpad.conf b/test/qbg22/evb22/88-lldpad.conf -new file mode 100644 -index 0000000..20ef072 ---- /dev/null -+++ b/test/qbg22/evb22/88-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/88.evb b/test/qbg22/evb22/88.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/88.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/88.sh b/test/qbg22/evb22/88.sh -new file mode 100755 -index 0000000..3474e77 ---- /dev/null -+++ b/test/qbg22/evb22/88.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c vdprwd=31 -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c vdprwd=31" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c vdprwd) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "vdprwd=31" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/89-lldpad.conf b/test/qbg22/evb22/89-lldpad.conf -new file mode 100644 -index 0000000..20ef072 ---- /dev/null -+++ b/test/qbg22/evb22/89-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/89.evb b/test/qbg22/evb22/89.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/89.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/89.sh b/test/qbg22/evb22/89.sh -new file mode 100755 -index 0000000..a10330e ---- /dev/null -+++ b/test/qbg22/evb22/89.sh -@@ -0,0 +1,58 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+$1/lldptool -i veth0 -gncb -T -V evb -c vdprka=31 -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ let rc=98 -+ echo $rc "FAILURE:lldptool -i veth0 -gncb -T -V evb -c vdprka=31" -+ exit $rc -+fi -+ -+sleep 3 -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb -c vdprka) -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "vdprka=31" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/9-lldpad.conf b/test/qbg22/evb22/9-lldpad.conf -new file mode 100644 -index 0000000..ebe91e0 ---- /dev/null -+++ b/test/qbg22/evb22/9-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/9.evb b/test/qbg22/evb22/9.evb -new file mode 100644 -index 0000000..46ce2b6 ---- /dev/null -+++ b/test/qbg22/evb22/9.evb -@@ -0,0 +1,60 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge does not support reflective relay but station -+ * requests it. RKA value is higher than on station. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:04:1f end_tlv @evbhead:00:04:68:88:3f -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:04:1f end_tlv @evbhead:00:04:68:88:3f -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:04:1f end_tlv @evbhead:00:04:68:88:3f -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:00:00:00:04:1f end_tlv @evbhead:00:04:68:88:3f -+15 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/90-lldpad.conf b/test/qbg22/evb22/90-lldpad.conf -new file mode 100644 -index 0000000..20ef072 ---- /dev/null -+++ b/test/qbg22/evb22/90-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "0452540050244E"; -+ }; -+ tlvid00000002 : -+ { -+ info = "0352540050244E"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 8; -+ vdprwd = 8; -+ vdprka = 8; -+ }; -+ }; -+}; -diff --git a/test/qbg22/evb22/90.evb b/test/qbg22/evb22/90.evb -new file mode 100644 -index 0000000..3b88d6c ---- /dev/null -+++ b/test/qbg22/evb22/90.evb -@@ -0,0 +1,72 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - bridge offers support for reflective relay and station -+ * requests it. Bridge and station set group id bit. -+ */ -+ -+#include "defines.evb" -+ -+5 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:06:00:00:40:00 end_tlv @evbhead:06:0c:counts -+6 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0c:00:40:00 end_tlv @evbhead:07:0d:counts -+7 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+8 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+9 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:0d:00:40:00 end_tlv @evbhead:07:0d:counts -+51 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+52 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+53 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+54 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+55 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evbhead:07:05:00:40:00 end_tlv -+80 lldpad_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/90.sh b/test/qbg22/evb22/90.sh -new file mode 100755 -index 0000000..1492d3b ---- /dev/null -+++ b/test/qbg22/evb22/90.sh -@@ -0,0 +1,47 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single task on the machine running lldpad -+# -+ -+# Wait 50 seconds before executing command -+sleep 50; -+ -+out=$($1/lldptool -i veth0 -gncb -t -V evb | tr -d '\t\n') -+rc=$? -+if [ "$rc" -eq 0 ] -+then -+ # echo out ":$out:" -+ if [ "$out" != "EVB Configuration TLVbridge:bgid,rrcap,rrctr(0x7)station:sgid,rrreq,rrstat(0xd)retries:3 rte:8mode:station r/l:0 rwd:8r/l:0 rka:8" ] -+ then -+ rc=99 -+ fi -+fi -+# First field contains exit code of shell script, 0 for success anything else -+# for failure. -+echo $rc ":$out:" -+exit $rc -diff --git a/test/qbg22/evb22/README b/test/qbg22/evb22/README -new file mode 100644 -index 0000000..f9814b4 ---- /dev/null -+++ b/test/qbg22/evb22/README -@@ -0,0 +1,142 @@ -+# -+# Implementation of EVB according to IEEE 802.1Qbg ratified standard -+# (c) Copyright IBM Corp. 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# The full GNU General Public License is included in this distribution in -+# the file called "COPYING". -+# -+ -+ -+Test cases for IEEE802.1Qbg ratified standard EVB module. -+To test this setup: -+- on bridge_ns 'qbg22sim -v -v -v -d 30 veth2' to display any messages. -+- on 'qbg22sim -v -v -v -d 20 veth0 brtest.evb' to send 5 messages. -+On netns2 name space messages with EVB TLV should be displayed. -+ -+Files -+===== -+There are 3 shell scripts which are executed on f18a -+allevb.sh: Runs all test cases with file names [1-9]*.evb. Uses -+ runevb.sh to execute one test case. -+ On success the exit code is zero, on failure none zero. -+ A none zero exit code termintes the evball.sh immediately. -+runevb.sh Runs one test case. -+ Return 0 on success and none zero otherwise. -+ Uses ssh for remote communication between virtual machines -+ and predefined pathes/IP addresses. -+24.sh .sh contain shell scripts to be executed -+ on the remote virtual machine. Usually done to change some -+ lldpad configuration settings during execution of lldpad. -+ -+Tests -+===== -+The following test cases are executed. Each test case has a number. -+All test cases need a lldpad.conf configuration file and an qbg22sim input -+file: -+- The qbg22sim input files have the extension .evb. -+- The lldpad configuration file has the extension -lldpad.conf -+ -+The purpose is to trigger an EVB DU exchange between qbg22sim and llpdad. -+The exchanged data can be inspected automaticly with little inteligence -+(see qbg22sim.1) or manually. -+ -+Test Description -+1 Neither station nor bridge support refective-relay. -+2 Station denies reflective-relay but bridge offers it. -+3 Station request reflective-relay but bridge does not support it. -+4 Station request reflective-relay and bridge supports it. -+5 Station request reflective-relay and bridge supports it. After some -+ time bridge turns off reflective relay support. -+6 Station request reflective-relay and bridge supports it. After some -+ time station does not request reflective relay support anymore. -+7 Use different RTE value. Local value is higher. -+8 Use different RTE value. Local value is lower. -+9 Use different RKA value. Local value is higher. -+10 Use different RKA value. Local value is lower. -+11 Use different RWD value. Local value is lower. -+12 Use different RWD value. Local value is higher. -+13 Use different retry value. Local value is higher. -+14 Use different retry value. Local value is lower. -+20 Station request reflective-relay and bridge supports it. Bridge sets -+ group id support, but station denies this. -+21 Station request reflective-relay and bridge supports it. Station sets -+ group id support, but bridge denies this. -+22 Station request reflective-relay and bridge supports it. Bridge sets -+ group id support, station sets group id support. -+23 Station request reflective-relay and bridge supports it. Bridge sets -+ group id support, station sets group id support. Bridge turns it off. -+24 Station request reflective-relay and bridge supports it. Bridge sets -+ group id support, station sets group id support. Station turns it off. -+25 Station request reflective-relay and bridge supports it. EVB TLV -+ transmission turned off. -+26 Station request reflective-relay and bridge supports it. EVB TLV -+ changed after 30 seconds via lldptool on station side -+30 Lldpad runs as bridge no reflective relay support. -+31 Lldpad runs as bridge with reflective relay support. -+32 Lldpad runs as bridge with reflective relay support and bgid support. -+33 Lldpad runs as bridge with reflective relay support and bgid support. -+ Station runs with reflective relay and sgid support -+41 Check for creation of evb.enableTx=off and evb22.enableTx=off -+42 Check for creation of evb.enableTx=on and evb22.enableTx=off -+43 Check for creation of evb.enableTx=off and evb22.enableTx=on -+44 Check for creation of evb.enableTx=on and evb22.enableTx=on -+45 Check for evb.enableTx=on and evb22.enableTx=on in config file -+46 Check for creation of evb22.enableTx=on and evb.enableTx=on -+80 Check for lldptool command using evb22 protocol display evb22 (-c only) -+90 Check for lldptool command using evb22 protocol display evb22 -+81-89 Check for lldptool command using evb22 protocol turn off various parms -+ -+Remarks: -+On some tests the warning "expect_reply reply to message sent (xx sec) missing -+may appear or not. This is randon, sometime all tests run without any warning -+at all, sometimes several tests display this warning. -+The warning can be ignored. The warning is displayed be the qbg22sim program -+only when an expected reply has not been received in time (1 second). -+The reason is: -+1. qbg22sim sends out and LLDP message -+2. lldpad receives the message and updates its MIB -+3. lldpad waits about 900ms until it sends out its updated LLDP TLS -+4. Mostly qbg22sim gets the reply from lldpad before it sends the next EVB TLV -+ one second later. In vary rare cases the TLVs are received after the timer -+ in qbg22sim expired and the next message is sent. When the next message is -+ sent and no reply received, the warning is issue. -+5. This is no problem at all. The LLDP standard says the messages are exchanged -+ in 1 second intervals without any handshaking at all. Each party simply -+ transmit its current status. -+ -+Test Execution -+============== -+Directory structure: -+The following directory structure is assumed: -+/home/richter/dcn/qbg/mywork/open-lldp --> lldpad -+/home/richter/dcn/qbg/mywork/open-lldp --> qbg22sim -+/home/richter/dcn/qbg/mywork/nstest/qbg22/evb22 --> EVB protocol test cases -+ -+To allow flexibility the path to execute the executables can be specified. -+Set the PATH variable properly. -+ -+Select the qbg22sim simulation program by adding a symbolic link -+directory -+1. cd /home/richter/dcn/qbg/mywork/test/qbg22/evb22 -+2. Create a symbolic link to the qbg22sim program -+ to use. Something like 'ln -s ../../../open-lldp-new/qbg22sim' -+3. Add the environment variable LLDPAD_DIR=abc to select an different lldpad -+ executable. For example the invocation -+ LLDPAD_DIR=open-lldp-new evball.sh -+ selects the file /home/richter/dcn/qbg/mywork/open-lldp-new/lldpad -+ for execution. -diff --git a/test/qbg22/evb22/allevb.sh b/test/qbg22/evb22/allevb.sh -new file mode 100755 -index 0000000..62b3fb2 ---- /dev/null -+++ b/test/qbg22/evb22/allevb.sh -@@ -0,0 +1,64 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD EVB Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Configuration file for unknwon vsi data test cases -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute the complete evb test suite. -+# -+ -+runcommand() -+{ -+ # echo parameter $@ -+ cmd=$1 -+ file=$2 -+ -+ echo "start testcase $number" -+ $cmd $file $@ 2>&1 -+ rc="$?" -+ if [ "$rc" -ne 0 ] -+ then -+ echo -en "\\033[1;31m" # Failures in red -+ echo "ERROR $file exit with $rc" -+ echo -en "\\033[0;39m" -+ exit 2 -+ fi -+ echo -en "\\033[1;32m" # Success in green -+ echo "OK testcase $file" -+ echo -en "\\033[0;39m" -+ return 0 -+} -+ -+if ! which runevb.sh 2>/dev/null -+then -+ export PATH=$PATH:$PWD -+fi -+ -+echo "Start testsuite at $(date)" -+for i in $(ls [1-9]*.evb|sort -n) -+do -+ runcommand runevb.sh $i -+done -+echo "Stop testsuite at $(date)" -+exit 0 -diff --git a/test/qbg22/evb22/brtest.evb b/test/qbg22/evb22/brtest.evb -new file mode 100644 -index 0000000..8871830 ---- /dev/null -+++ b/test/qbg22/evb22/brtest.evb -@@ -0,0 +1,69 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ * The first column defines the run time of the test program in seconds -+ * when the remaining data on this line will be sent. The rest of the line are -+ * data fields which define the TLVs. -+ * Line limit is 5KB, long lines can be split with \\ as last character. -+ * -+ * The files are preprocessed with cpp before being read by the test program. -+ * -+ * The data fields per line are -+ * 1. time -+ * 2. destination MAC -+ * 3. source MAC (dash(-) replaced by the senders MAC address) -+ * 4. ethertype -+ * 5. Severval TLVs according to standard 802.3ad (Mandatory TLV are -+ * chassis-id, port-id, ttl and end) -+ * 6. Optional. Several TLVs starting with @ which are expected results. -+ * Its an error is it is missing in the reply or TLV differs. -+ */ -+/* -+ * EVB negotiation - test virtual bridge forwards mac multicast to -+ * nearest customer bridge (01:80:c2:00:00:00). -+ */ -+ -+#define dst_mac 01:80:c2:00:00:00 -+#define lldp_type 88:cc -+#define chassis_tlv 02:07:06:64:75:6d:6d:79:00 -+#define port_tlv 04:05:05:65:74:68:30 -+#define ttl_tlv120 06:02:00:78 -+#define ttl_tlv0 06:02:00:00 -+#define end_tlv 00:00 -+ -+#define evbhead fe:09:00:80:c2:0d -+#define evb_norr evbhead:00:00:00:40:00 -+ -+5 dst_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv -+6 dst_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv -+7 dst_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv -+8 dst_mac - lldp_type chassis_tlv port_tlv ttl_tlv120 \\ -+ evb_norr end_tlv -+15 dst_mac - lldp_type chassis_tlv port_tlv ttl_tlv0 end_tlv -diff --git a/test/qbg22/evb22/defines.evb b/test/qbg22/evb22/defines.evb -new file mode 100644 -index 0000000..7e01a75 ---- /dev/null -+++ b/test/qbg22/evb22/defines.evb -@@ -0,0 +1,53 @@ -+/* -+ * Implementation of EVB according to IEEE 802.1Qbg -+ * (c) Copyright IBM Corp. 2014 -+ * -+ * Author(s): Thomas Richter -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * The full GNU General Public License is included in this distribution in -+ * the file called "COPYING". -+ * -+ */ -+ -+/* -+ * EVB Protocol test data. Define a complete LLDP DU in hex. One complete set -+ * is needed for each transmission. -+ */ -+/* -+ * Very common defines -+ */ -+ -+#define lldpad_mac 01:80:c2:00:00:00 -+#define lldp_type 88:cc -+#define chassis_tlv 02:07:06:64:75:6d:6d:79:00 -+#define port_tlv 04:05:05:65:74:68:30 -+#define ttl_tlv120 06:02:00:78 -+#define ttl_tlv0 06:02:00:00 -+#define end_tlv 00:00 -+ -+#define evbhead fe:09:00:80:c2:0d -+#define counts 68:88:08 -+#define stcounts a6:58:18 -+ -+/* No Reflective Relay on bridge */ -+#define evb_norr evbhead:00:00:00:40:00 -+#define evb_norr_ack evbhead:00:00:counts -+/* Bridge offers reflective-relay */ -+#define evb_brrr evbhead:02:00:00:40:00 -+#define evb_brrr_ack evbhead:02:00:counts -+/* Station request reflective relay */ -+#define evb_norr2 evbhead:00:04:00:40:00 -+#define evb_strr_ack evbhead:00:04:counts -diff --git a/test/qbg22/evb22/runevb.sh b/test/qbg22/evb22/runevb.sh -new file mode 100755 -index 0000000..c4cc88c ---- /dev/null -+++ b/test/qbg22/evb22/runevb.sh -@@ -0,0 +1,152 @@ -+#!/bin/bash -+# -+# Execute test case for LLDPAD testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single test. Parameter is the name of the test file -+# -+ -+# Check if lldpad is up and running. Return pid or 0 if not running. -+# Note that lldpad may be started without creating a PID file. If no PID file -+# exists, use the lldptool to query the PID of lldpad. -+function lldpad_up() -+{ -+ if [ ! -r /var/run/lldpad.pid ] -+ then -+ pidfile=$(../../../lldptool -p 2>/dev/null) -+ if [ "$?" -ne 0 ] -+ then -+ return 0 -+ fi -+ else -+ pidfile="$(cat /var/run/lldpad.pid)" -+ fi -+ if [ -z "$pidfile" ] -+ then -+ return 0 -+ else -+ ps -p $pidfile -o pid --no-header > /dev/null -+ if [ $? -ne 0 ] -+ then -+ return 0 -+ fi -+ fi -+ echo "LLDPAD running pid $pidfile" -+ return $pidfile -+} -+ -+function lldpad_down() -+{ -+ if [ ! -r /var/run/lldpad.pid ] -+ then -+ pidfile=$(../../../lldptool -p 2>/dev/null) -+ if [ "$?" -ne 0 ] -+ then -+ return 1 -+ fi -+ else -+ pidfile="$(cat /var/run/lldpad.pid)" -+ fi -+ if [ -z "$pidfile" ] -+ then -+ return 1 -+ fi -+ kill -s SIGTERM $pidfile -+ sleep 1 -+ ps -p $pidfile -o pid --no-header > /dev/null -+ if [ $? -ne 1 ] -+ then -+ kill -s SIGKILL $pidfile -+ fi -+ return 0 -+} -+ -+# Use the correct lldpad configuration file and start lldpad. -+# Parameter 1: path to lldpad to use -+# Parameter 2: name of configuration file -+function lldpad_start() -+{ -+ if lldpad_up -+ then -+ rm -f /var/lib/lldpad/lldpad.conf ./lldpad.conf -+ cp $2 /tmp/$2 -+ $1/lldpad -V7 -f /tmp/$2 >/tmp/$2.out 2>&1 & -+ sleep 1 -+ if lldpad_up -+ then -+ echo "$0:lldpad not started or terminated unexpectedly" -+ exit 1 -+ fi -+ else -+ exit 1 -+ fi -+ return 0 -+} -+ -+if ! which runevb.sh 1>/dev/null 2>/dev/null -+then -+ export PATH=$PATH:$PWD -+fi -+ -+# Extract type of test case from last 3 characters of invocation -+type=$(basename $0) -+type=".${type:3:3}" -+ -+testfile=$1 -+no=$(basename $testfile $type) -+ -+# Start lldpad using this name space -+if ! lldpad_start ../../.. $no-lldpad.conf -+then -+ echo "$0:can not start lldpad" -+ exit 1 -+fi -+ -+# Check for shell script to run in parallel -+if [ -r "./$no.sh" -a -x "./$no.sh" ] -+then -+ ./$no.sh ../../.. > /tmp/$no.sh.out & -+fi -+ -+# get the duration from the last entry in the test file. -+duration=$(cpp $testfile | cut -f1 -d' ' | sed '/^$/d' | tail -1) -+let duration=duration+5 -+ -+# run the test with output save to /tmp/testfile.out -+ip netns exec bridge_ns ../../../qbg22sim -v -v -v -T 5000000 -d $duration veth2 $testfile > /tmp/$testfile.out -+rc=$? -+ -+# Stop lldpad -+if ! lldpad_down -+then -+ echo "$0:can not stop lldpad" -+ exit 1 -+fi -+ -+# Check for output file script to test result of test case -+if [ -r "/tmp/$no.sh.out" ] -+then -+ rc=$(cut -f1 -d' ' "/tmp/$no.sh.out") -+fi -+ -+exit $rc -diff --git a/test/qbg22/vdp22/100-lldpad.conf b/test/qbg22/vdp22/100-lldpad.conf -new file mode 100644 -index 0000000..9c76b9c ---- /dev/null -+++ b/test/qbg22/vdp22/100-lldpad.conf -@@ -0,0 +1,55 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = false; -+ evbmode = "station"; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/100.nlc b/test/qbg22/vdp22/100.nlc -new file mode 100755 -index 0000000..5d746ba ---- /dev/null -+++ b/test/qbg22/vdp22/100.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc/de-assoc test. Station has no EVB TLV disabled -+# Expect failure -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm1,e=-93 -s,w=10 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/100.vdp b/test/qbg22/vdp22/100.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/100.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/101-lldpad.conf b/test/qbg22/vdp22/101-lldpad.conf -new file mode 100644 -index 0000000..ff35cc7 ---- /dev/null -+++ b/test/qbg22/vdp22/101-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "bridge"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/101.nlc b/test/qbg22/vdp22/101.nlc -new file mode 100755 -index 0000000..b63c8a5 ---- /dev/null -+++ b/test/qbg22/vdp22/101.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc and expect error because lldpad runs in bridge role. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm1,e=-95 -s,w=5 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/101.vdp b/test/qbg22/vdp22/101.vdp -new file mode 100644 -index 0000000..9ae4eaa ---- /dev/null -+++ b/test/qbg22/vdp22/101.vdp -@@ -0,0 +1,57 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/102-lldpad.conf b/test/qbg22/vdp22/102-lldpad.conf -new file mode 100644 -index 0000000..2ea4e18 ---- /dev/null -+++ b/test/qbg22/vdp22/102-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = false; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/102.nlc b/test/qbg22/vdp22/102.nlc -new file mode 100755 -index 0000000..8dd7558 ---- /dev/null -+++ b/test/qbg22/vdp22/102.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc/de-assoc test. Station has no RR capabililty requested. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm1 -s,w=30 -d vm1 -s,w=10 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/102.vdp b/test/qbg22/vdp22/102.vdp -new file mode 100644 -index 0000000..1f56138 ---- /dev/null -+++ b/test/qbg22/vdp22/102.vdp -@@ -0,0 +1,47 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ } -+}; -diff --git a/test/qbg22/vdp22/103-lldpad.conf b/test/qbg22/vdp22/103-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/103-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/103.nlc b/test/qbg22/vdp22/103.nlc -new file mode 100755 -index 0000000..69fbdbc ---- /dev/null -+++ b/test/qbg22/vdp22/103.nlc -@@ -0,0 +1,35 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc/de-assoc test. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -s,w=30 -a vm1,w=20 -s,w=60 -d vm1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/103.vdp b/test/qbg22/vdp22/103.vdp -new file mode 100644 -index 0000000..5b1f36a ---- /dev/null -+++ b/test/qbg22/vdp22/103.vdp -@@ -0,0 +1,47 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/104-lldpad.conf b/test/qbg22/vdp22/104-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/104-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/104.nlc b/test/qbg22/vdp22/104.nlc -new file mode 100755 -index 0000000..ea3c17c ---- /dev/null -+++ b/test/qbg22/vdp22/104.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute two simple assoc/de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm1 -s,w=5 -a vm2 -s,w=60 -d vm1 -d vm2 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/104.vdp b/test/qbg22/vdp22/104.vdp -new file mode 100644 -index 0000000..5de5046 ---- /dev/null -+++ b/test/qbg22/vdp22/104.vdp -@@ -0,0 +1,45 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/105-lldpad.conf b/test/qbg22/vdp22/105-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/105-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/105.nlc b/test/qbg22/vdp22/105.nlc -new file mode 100755 -index 0000000..4ee9d30 ---- /dev/null -+++ b/test/qbg22/vdp22/105.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc/de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -p vm1 -s,w=45 -d vm1 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/105.vdp b/test/qbg22/vdp22/105.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/105.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/106-lldpad.conf b/test/qbg22/vdp22/106-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/106-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/106.nlc b/test/qbg22/vdp22/106.nlc -new file mode 100755 -index 0000000..833051a ---- /dev/null -+++ b/test/qbg22/vdp22/106.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute two pre-assoc/de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -p vm1 -s,w=5 -p vm2 -s,w=60 -d vm1 -d vm2 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/106.vdp b/test/qbg22/vdp22/106.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/106.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/107-lldpad.conf b/test/qbg22/vdp22/107-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/107-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/107.nlc b/test/qbg22/vdp22/107.nlc -new file mode 100755 -index 0000000..99d80a0 ---- /dev/null -+++ b/test/qbg22/vdp22/107.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc-rr/de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -r vm1 -s,w=45 -d vm1 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/107.vdp b/test/qbg22/vdp22/107.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/107.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/108-lldpad.conf b/test/qbg22/vdp22/108-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/108-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/108.nlc b/test/qbg22/vdp22/108.nlc -new file mode 100755 -index 0000000..8381135 ---- /dev/null -+++ b/test/qbg22/vdp22/108.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc/pre-assoc test. Expect error. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm1 -s,w=45 -p vm1,e=-22 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/108.vdp b/test/qbg22/vdp22/108.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/108.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/110-lldpad.conf b/test/qbg22/vdp22/110-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/110-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/110.nlc b/test/qbg22/vdp22/110.nlc -new file mode 100755 -index 0000000..7878340 ---- /dev/null -+++ b/test/qbg22/vdp22/110.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc/pre-assoc-rr/assoc/de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -p vm1 -s,w=30 -r vm1 -s,w=30 -a vm1 -s,w=30 -d vm1 -s,w=10 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/110.vdp b/test/qbg22/vdp22/110.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/110.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/111-lldpad.conf b/test/qbg22/vdp22/111-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/111-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/111.nlc b/test/qbg22/vdp22/111.nlc -new file mode 100755 -index 0000000..4f15b28 ---- /dev/null -+++ b/test/qbg22/vdp22/111.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc/pre-assoc/de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -p vm1 -s,w=30 -p vm1 -s,w=30 -d vm1 -s,w=10 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/111.vdp b/test/qbg22/vdp22/111.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/111.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/112-lldpad.conf b/test/qbg22/vdp22/112-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/112-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/112.nlc b/test/qbg22/vdp22/112.nlc -new file mode 100755 -index 0000000..6b14209 ---- /dev/null -+++ b/test/qbg22/vdp22/112.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc-rr/pre-assoc-rr/de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -r vm1 -s,w=30 -r vm1 -s,w=30 -d vm1 -s,w=10 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/112.vdp b/test/qbg22/vdp22/112.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/112.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/113-lldpad.conf b/test/qbg22/vdp22/113-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/113-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/113.nlc b/test/qbg22/vdp22/113.nlc -new file mode 100755 -index 0000000..bd53ba6 ---- /dev/null -+++ b/test/qbg22/vdp22/113.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc/assoc/de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm1 -s,w=36 -a vm1 -s,w=37 -d vm1 -s,w=10 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/113.vdp b/test/qbg22/vdp22/113.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/113.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/114-lldpad.conf b/test/qbg22/vdp22/114-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/114-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/114.nlc b/test/qbg22/vdp22/114.nlc -new file mode 100755 -index 0000000..97ba73a ---- /dev/null -+++ b/test/qbg22/vdp22/114.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple de-assoc test. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -d vm1,e=-22 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/114.vdp b/test/qbg22/vdp22/114.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/114.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/115-lldpad.conf b/test/qbg22/vdp22/115-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/115-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/115.nlc b/test/qbg22/vdp22/115.nlc -new file mode 100755 -index 0000000..58af2db ---- /dev/null -+++ b/test/qbg22/vdp22/115.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with error returned -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm201,e=2 -s,w=5 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/115.vdp b/test/qbg22/vdp22/115.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/115.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/116-lldpad.conf b/test/qbg22/vdp22/116-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/116-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/116.nlc b/test/qbg22/vdp22/116.nlc -new file mode 100755 -index 0000000..da6448a ---- /dev/null -+++ b/test/qbg22/vdp22/116.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc with error returned after 1. keep alive message. -+# Expect de-assoc response after first KA message -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -Cnew=vmxxx,name=vm201,typeidver=2 -i veth0 -a vmxxx -g,e=1,w=60 -s,w=20 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/116.vdp b/test/qbg22/vdp22/116.vdp -new file mode 100644 -index 0000000..1f56138 ---- /dev/null -+++ b/test/qbg22/vdp22/116.vdp -@@ -0,0 +1,47 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ } -+}; -diff --git a/test/qbg22/vdp22/117-lldpad.conf b/test/qbg22/vdp22/117-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/117-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/117.nlc b/test/qbg22/vdp22/117.nlc -new file mode 100755 -index 0000000..89864df ---- /dev/null -+++ b/test/qbg22/vdp22/117.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with unsolicited de-assoc message from switch -+# Expect unsolicited message from lldpad. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm200 -g,e=1,w=90 -s,w=20 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/117.vdp b/test/qbg22/vdp22/117.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/117.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/118-lldpad.conf b/test/qbg22/vdp22/118-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/118-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/118.nlc b/test/qbg22/vdp22/118.nlc -new file mode 100755 -index 0000000..32083a6 ---- /dev/null -+++ b/test/qbg22/vdp22/118.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc with error returned -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -p vm201,e=2 -s,w=5 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/118.vdp b/test/qbg22/vdp22/118.vdp -new file mode 100644 -index 0000000..171d0a0 ---- /dev/null -+++ b/test/qbg22/vdp22/118.vdp -@@ -0,0 +1,44 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/119-lldpad.conf b/test/qbg22/vdp22/119-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/119-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/119.nlc b/test/qbg22/vdp22/119.nlc -new file mode 100755 -index 0000000..b46ff6b ---- /dev/null -+++ b/test/qbg22/vdp22/119.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc-rr with error returned after 1. keep alive message. -+# Expect unsolicited message from lldpad. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -Cnew=vm999,name=vm201,typeidver=2 -i veth0 -r vm999 -g,e=1,w=60 -s,w=20 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/119.vdp b/test/qbg22/vdp22/119.vdp -new file mode 100644 -index 0000000..48d5499 ---- /dev/null -+++ b/test/qbg22/vdp22/119.vdp -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/120-lldpad.conf b/test/qbg22/vdp22/120-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/120-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/120.nlc b/test/qbg22/vdp22/120.nlc -new file mode 100755 -index 0000000..ea8d2cb ---- /dev/null -+++ b/test/qbg22/vdp22/120.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc with unsolicited de-assoc message from switch -+# Expect unsolicited message from lldpad. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -p vm200 -g,e=1,w=90 -s,w=20 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/120.vdp b/test/qbg22/vdp22/120.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/120.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/121-lldpad.conf b/test/qbg22/vdp22/121-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/121-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/121.nlc b/test/qbg22/vdp22/121.nlc -new file mode 100755 -index 0000000..761dec4 ---- /dev/null -+++ b/test/qbg22/vdp22/121.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with keep-error returned after 1. keep alive message. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm202 -g,e=1,w=60 -s,w=20 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/121.vdp b/test/qbg22/vdp22/121.vdp -new file mode 100644 -index 0000000..48d5499 ---- /dev/null -+++ b/test/qbg22/vdp22/121.vdp -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/122-lldpad.conf b/test/qbg22/vdp22/122-lldpad.conf -new file mode 100644 -index 0000000..fdbb132 ---- /dev/null -+++ b/test/qbg22/vdp22/122-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/122.nlc b/test/qbg22/vdp22/122.nlc -new file mode 100755 -index 0000000..c2fc425 ---- /dev/null -+++ b/test/qbg22/vdp22/122.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple pre-assoc with hard-error returned from switch -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -Cnew=vmxxx,name=vm201,typeid=203 -p vmxxx,e=18 -s,w=5 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/122.vdp b/test/qbg22/vdp22/122.vdp -new file mode 100644 -index 0000000..48d5499 ---- /dev/null -+++ b/test/qbg22/vdp22/122.vdp -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/123-lldpad.conf b/test/qbg22/vdp22/123-lldpad.conf -new file mode 100644 -index 0000000..7e61fbc ---- /dev/null -+++ b/test/qbg22/vdp22/123-lldpad.conf -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ tlvid0080c20d : -+ { -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = false; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 15; -+ vdprka = 20; -+ }; -+ }; -+}; -diff --git a/test/qbg22/vdp22/123.nlc b/test/qbg22/vdp22/123.nlc -new file mode 100755 -index 0000000..006a1b6 ---- /dev/null -+++ b/test/qbg22/vdp22/123.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc test and expect resource wait delay timeout -+# from bridge. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm.cfg -i veth0 -a vm199,w=15000,d=12000 -s,w=30 -+rc=$? -+exit $rc -diff --git a/test/qbg22/vdp22/123.vdp b/test/qbg22/vdp22/123.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/123.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/200-lldpad.conf b/test/qbg22/vdp22/200-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/200-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/200.nlc b/test/qbg22/vdp22/200.nlc -new file mode 100755 -index 0000000..88e3112 ---- /dev/null -+++ b/test/qbg22/vdp22/200.nlc -@@ -0,0 +1,35 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc/de-assoc test. Use command line interface -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -s,w=30 -a vm2_1 -s,w=30 -d vm2_1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/200.vdp b/test/qbg22/vdp22/200.vdp -new file mode 100644 -index 0000000..171d0a0 ---- /dev/null -+++ b/test/qbg22/vdp22/200.vdp -@@ -0,0 +1,44 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/201-lldpad.conf b/test/qbg22/vdp22/201-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/201-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/201.nlc b/test/qbg22/vdp22/201.nlc -new file mode 100755 -index 0000000..2791190 ---- /dev/null -+++ b/test/qbg22/vdp22/201.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with group id support requested and not supportted by -+# bridge and station. -+# -+ -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+# Must: Wait some time for lldpad to start up and initialize -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xxx,name=vm2_1,map=13-52:bb:cc:dd:ee:ff-222 -i veth0 -s,w=30 -a vm2_xxx,e=1 -s,w=30 -+exit $? -diff --git a/test/qbg22/vdp22/201.vdp b/test/qbg22/vdp22/201.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/201.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/202-lldpad.conf b/test/qbg22/vdp22/202-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/202-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/202.nlc b/test/qbg22/vdp22/202.nlc -new file mode 100755 -index 0000000..9cd3a90 ---- /dev/null -+++ b/test/qbg22/vdp22/202.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Assign VID by bridge and report back to caller. -+# Caller then de-assoc with wrong vid. -+# -+ -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+# Must: Wait some time for lldpad to start up and initialize -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xxx,name=vm2_205,map=0/205 -i veth0 -s,w=30 -a vm2_xxx -s,w=30 -d vm2_xxx,e=1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/202.vdp b/test/qbg22/vdp22/202.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/202.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/203-lldpad.conf b/test/qbg22/vdp22/203-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/203-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/203.nlc b/test/qbg22/vdp22/203.nlc -new file mode 100755 -index 0000000..6afe8f8 ---- /dev/null -+++ b/test/qbg22/vdp22/203.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Assign VID by bridge and report back to caller, caller de-assoc with correct -+# filter. -+# -+ -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+# Must: Wait some time for lldpad to start up and initialize -+../../../vdptest -n -v -v -v -F vm2.cfg -Cnew=vm2_xxx,name=vm2_205,map=0/205 -i veth0 -s,w=30 -a vm2_xxx -s,w=30 -Cnew=vm2_yyy,name=vm2_205,map=205 -d vm2_yyy -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/203.vdp b/test/qbg22/vdp22/203.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/203.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/204-lldpad.conf b/test/qbg22/vdp22/204-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/204-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/204.nlc b/test/qbg22/vdp22/204.nlc -new file mode 100755 -index 0000000..2e515ba ---- /dev/null -+++ b/test/qbg22/vdp22/204.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Assign QoS by bridge and report back to caller, caller de-assoc with incorrect -+# QoS. -+# -+ -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+# Must: Wait some time for lldpad to start up and initialize -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xx1,name=vm2_206,map=2/61442 -i veth0 -s,w=30 -a vm2_xx1 -s,w=30 -Cnew=vm2_xx2,name=vm2_206,map=2 -d vm2_xx2,e=1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/204.vdp b/test/qbg22/vdp22/204.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/204.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/205-lldpad.conf b/test/qbg22/vdp22/205-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/205-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/205.nlc b/test/qbg22/vdp22/205.nlc -new file mode 100755 -index 0000000..084ef12 ---- /dev/null -+++ b/test/qbg22/vdp22/205.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Assign QoS by bridge and report back to caller, caller de-assoc with correct -+# QoS. -+# -+ -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+# Must: Wait some time for lldpad to start up and initialize -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xx1,name=vm2_206,map=2/61442 -i veth0 -s,w=30 -a vm2_xx1 -s,w=30 -Cnew=vm2_xx2,name=vm2_206,map=61442 -d vm2_xx2 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/205.vdp b/test/qbg22/vdp22/205.vdp -new file mode 100644 -index 0000000..171d0a0 ---- /dev/null -+++ b/test/qbg22/vdp22/205.vdp -@@ -0,0 +1,44 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/206-lldpad.conf b/test/qbg22/vdp22/206-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/206-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/206.nlc b/test/qbg22/vdp22/206.nlc -new file mode 100755 -index 0000000..0704a25 ---- /dev/null -+++ b/test/qbg22/vdp22/206.nlc -@@ -0,0 +1,35 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Provoke invalid Filter data response from bridge -+# -+ -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xx1,name=vm2_206,map=2/61440,typeidver=0x15 -i veth0 -s,w=30 -a vm2_xx1,e=5 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/206.vdp b/test/qbg22/vdp22/206.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/206.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/207-lldpad.conf b/test/qbg22/vdp22/207-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/207-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/207.nlc b/test/qbg22/vdp22/207.nlc -new file mode 100755 -index 0000000..99a6800 ---- /dev/null -+++ b/test/qbg22/vdp22/207.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Assign QoS by bridge and report back to caller, caller does not expected -+# changed QoS. -+# -+ -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xx1,name=vm2_206,map=2,e=250 -i veth0 -s,w=30 -a vm2_xx1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/207.vdp b/test/qbg22/vdp22/207.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/207.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/208-lldpad.conf b/test/qbg22/vdp22/208-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/208-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/208.nlc b/test/qbg22/vdp22/208.nlc -new file mode 100755 -index 0000000..e7d953f ---- /dev/null -+++ b/test/qbg22/vdp22/208.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Send VLAN/QoS to bridge and report back to caller. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xx1,name=vm2_1,map=0x8002 -i veth0 -s,w=30 -a vm2_xx1 -s,w=30 -d vm2_xx1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/208.vdp b/test/qbg22/vdp22/208.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/208.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/209-lldpad.conf b/test/qbg22/vdp22/209-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/209-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/209.nlc b/test/qbg22/vdp22/209.nlc -new file mode 100755 -index 0000000..41ddb21 ---- /dev/null -+++ b/test/qbg22/vdp22/209.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Send VLAN/QoS to bridge and report back to caller. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xx1,name=vm2_206,map=0x8002 -i veth0 -s,w=30 -a vm2_xx1,e=5 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/209.vdp b/test/qbg22/vdp22/209.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/209.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/210-lldpad.conf b/test/qbg22/vdp22/210-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/210-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/210.nlc b/test/qbg22/vdp22/210.nlc -new file mode 100755 -index 0000000..7b6a457 ---- /dev/null -+++ b/test/qbg22/vdp22/210.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Send many VIDs (one VID is zero) and expect error as VID 0 must be the only -+# VID in the list. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -Cnew=vm2_xxx,name=vm2_205a -i veth0 -s,w=30 -a vm2_xxx,e=1 -s,w=30 -d vm2_xxx,e=1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/210.vdp b/test/qbg22/vdp22/210.vdp -new file mode 100644 -index 0000000..171d0a0 ---- /dev/null -+++ b/test/qbg22/vdp22/210.vdp -@@ -0,0 +1,44 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/211-lldpad.conf b/test/qbg22/vdp22/211-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/211-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/211.nlc b/test/qbg22/vdp22/211.nlc -new file mode 100755 -index 0000000..ac978bf ---- /dev/null -+++ b/test/qbg22/vdp22/211.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Send many VIDs and expect QoS for VID indexed 3 changed -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -s,w=30 -a vm2_206b -s,w=30 -Cnew=vm2_xxx,name=vm2_206b,map=10,map=11,map=12,map=0xd00d,map=14,map=15 -d vm2_xxx -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/211.vdp b/test/qbg22/vdp22/211.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/211.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/212-lldpad.conf b/test/qbg22/vdp22/212-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/212-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/212.nlc b/test/qbg22/vdp22/212.nlc -new file mode 100755 -index 0000000..91d856c ---- /dev/null -+++ b/test/qbg22/vdp22/212.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Send many VIDs (filter format VID/MAC) and expect VID 0 replaced. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -s,w=30 -a vm2_208 -s,w=30 -Cnew=vm2_xxx,name=vm2_208,map=10-aa:bb:00:00:00:10,map=20-aa:bb:00:00:00:11,map=0xb0d0-aa:bb:00:00:00:22 -d vm2_xxx,e=1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/212.vdp b/test/qbg22/vdp22/212.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/212.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/213-lldpad.conf b/test/qbg22/vdp22/213-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/213-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/213.nlc b/test/qbg22/vdp22/213.nlc -new file mode 100755 -index 0000000..cd011d5 ---- /dev/null -+++ b/test/qbg22/vdp22/213.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Send many VIDs (filter format VID/MAC) and expect VID 0 replaced. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -s,w=30 -a vm2_208 -s,w=30 -Cnew=vm2_xxx,name=vm2_208,map=10-aa:bb:00:00:00:10,map=0xb0d0-aa:bb:00:00:00:11,map=0xb0d0-aa:bb:00:00:00:22 -d vm2_xxx -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/213.vdp b/test/qbg22/vdp22/213.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/213.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/220-lldpad.conf b/test/qbg22/vdp22/220-lldpad.conf -new file mode 100644 -index 0000000..c75f7f2 ---- /dev/null -+++ b/test/qbg22/vdp22/220-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/220.nlc b/test/qbg22/vdp22/220.nlc -new file mode 100755 -index 0000000..a7a83fe ---- /dev/null -+++ b/test/qbg22/vdp22/220.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with group id support on bridge and station. -+# Send 1 VIDs (filter format VID/MAC/GPID) and expect no VID replacement. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -Cnew=vm2_xx1,name=vm2_1,map=13-52:bb:cc:dd:ee:ff-1024 -s,w=30 -a vm2_xx1 -s,w=30 -d vm2_xx1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/220.vdp b/test/qbg22/vdp22/220.vdp -new file mode 100644 -index 0000000..0f29fa0 ---- /dev/null -+++ b/test/qbg22/vdp22/220.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/221-lldpad.conf b/test/qbg22/vdp22/221-lldpad.conf -new file mode 100644 -index 0000000..c75f7f2 ---- /dev/null -+++ b/test/qbg22/vdp22/221-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/221.nlc b/test/qbg22/vdp22/221.nlc -new file mode 100755 -index 0000000..1b85957 ---- /dev/null -+++ b/test/qbg22/vdp22/221.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with group id support on bridge and station. -+# Send 1 VIDs (filter format VID/MAC/GPID) and expect VID replaced. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -Cnew=vm2_xx1,name=vm2_207,map=0/1014-aa:bb:cc:00:00:ff-1014 -s,w=30 -a vm2_xx1 -s,w=30 -Cnew=vm2_xx2,name=vm2_207,map=1014-aa:bb:cc:00:00:ff-1014 -d vm2_xx2 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/221.vdp b/test/qbg22/vdp22/221.vdp -new file mode 100644 -index 0000000..0f29fa0 ---- /dev/null -+++ b/test/qbg22/vdp22/221.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/222-lldpad.conf b/test/qbg22/vdp22/222-lldpad.conf -new file mode 100644 -index 0000000..c75f7f2 ---- /dev/null -+++ b/test/qbg22/vdp22/222-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/222.nlc b/test/qbg22/vdp22/222.nlc -new file mode 100755 -index 0000000..cc1fbd9 ---- /dev/null -+++ b/test/qbg22/vdp22/222.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with group id support on bridge and station. -+# Send many VIDs (filter format VID/MAC/GPID) and expect no VID replacement. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -Cnew=vm2_xx1,name=vm2_1,map=13-52:bb:cc:dd:ee:ff-1024,map=14-52:bb:cc:dd:ee:10-1025,map=15-52:bb:cc:dd:ee:00-1025 -s,w=30 -a vm2_xx1 -s,w=30 -d vm2_xx1 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/222.vdp b/test/qbg22/vdp22/222.vdp -new file mode 100644 -index 0000000..0f29fa0 ---- /dev/null -+++ b/test/qbg22/vdp22/222.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/223-lldpad.conf b/test/qbg22/vdp22/223-lldpad.conf -new file mode 100644 -index 0000000..c75f7f2 ---- /dev/null -+++ b/test/qbg22/vdp22/223-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/223.nlc b/test/qbg22/vdp22/223.nlc -new file mode 100755 -index 0000000..587b08a ---- /dev/null -+++ b/test/qbg22/vdp22/223.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with group id support on bridge and station. -+# Send many VIDs (filter format VID/MAC//GPID) and expect VID 0 replaced. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -Cnew=vm2_xx1,name=vm2_208,typeidver=0,map=0/1014-aa:bb:cc:00:00:ff-1014,map=0/1024-aa:bb:cc:00:00:dd-1024,map=1024-aa:bb:cc:00:00:aa-1024 -s,w=30 -a vm2_xx1 -s,w=30 -Cnew=vm2_xx2,name=vm2_208,typeidver=0,map=1014-aa:bb:cc:00:00:ff-1014,map=1024-aa:bb:cc:00:00:dd-1024,map=1024-aa:bb:cc:00:00:aa-1024 -d vm2_xx2 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/223.vdp b/test/qbg22/vdp22/223.vdp -new file mode 100644 -index 0000000..0f29fa0 ---- /dev/null -+++ b/test/qbg22/vdp22/223.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/224-lldpad.conf b/test/qbg22/vdp22/224-lldpad.conf -new file mode 100644 -index 0000000..c75f7f2 ---- /dev/null -+++ b/test/qbg22/vdp22/224-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/224.nlc b/test/qbg22/vdp22/224.nlc -new file mode 100755 -index 0000000..864cb76 ---- /dev/null -+++ b/test/qbg22/vdp22/224.nlc -@@ -0,0 +1,36 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with group id support on bridge and station. -+# Send many VIDs (filter format VID/MAC/GPID) and expect QoS (fid 1) set. -+# -+ -+sleep 30 # Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -Cnew=vm2_xx1,name=vm2_206,typeidver=0x11,map=1014-aa:bb:cc:00:00:ff-1014,map=1024/0x9400-aa:bb:cc:00:00:dd-1024,map=1024-aa:bb:cc:00:00:aa-1024 -s,w=30 -a vm2_xx1 -s,w=30 -Cnew=vm2_xx2,name=vm2_206,typeidver=0x11,map=1014-aa:bb:cc:00:00:ff-1014,map=0x9400-aa:bb:cc:00:00:dd-1024,map=1024-aa:bb:cc:00:00:aa-1024 -d vm2_xx2 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/224.vdp b/test/qbg22/vdp22/224.vdp -new file mode 100644 -index 0000000..0f29fa0 ---- /dev/null -+++ b/test/qbg22/vdp22/224.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/225-lldpad.conf b/test/qbg22/vdp22/225-lldpad.conf -new file mode 100644 -index 0000000..c75f7f2 ---- /dev/null -+++ b/test/qbg22/vdp22/225-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/225.nlc b/test/qbg22/vdp22/225.nlc -new file mode 100755 -index 0000000..ffc209e ---- /dev/null -+++ b/test/qbg22/vdp22/225.nlc -@@ -0,0 +1,37 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc with group id support on bridge and station. -+# Send many VIDs (filter format VID/MAC/GPID) and expect VID 0 replaced and -+# QoS set. -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -Cnew=vm2_xx1,name=vm2_208,map=0/0xb3f6-aa:bb:cc:00:00:ff-0x3f6,map=0/0xb400-aa:bb:cc:00:00:dd-0x400 -s,w=30 -a vm2_xx1 -s,w=30 -Cnew=vm2_xx2,name=vm2_208,map=0xb3f6-aa:bb:cc:00:00:ff-0x3f6,map=0xb400-aa:bb:cc:00:00:dd-0x400 -d vm2_xx2 -s,w=10 -+exit $? -diff --git a/test/qbg22/vdp22/225.vdp b/test/qbg22/vdp22/225.vdp -new file mode 100644 -index 0000000..0f29fa0 ---- /dev/null -+++ b/test/qbg22/vdp22/225.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_groupid.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/240-lldpad.conf b/test/qbg22/vdp22/240-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/240-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/240.nlc b/test/qbg22/vdp22/240.nlc -new file mode 100755 -index 0000000..2a0de5a ---- /dev/null -+++ b/test/qbg22/vdp22/240.nlc -@@ -0,0 +1,43 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Check for hint bit support -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+testcase=$(basename $outfile .nlc) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -s,w=30 -a vm2_1 -s,w=30 -d vm2_1 -s,w=10 -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ exit $rc -+fi -+fgrep -q '06 21 10 00 00 01 00 05 a1 41 28 57' /tmp/$testcase-lldpad.conf.out -+exit $? -diff --git a/test/qbg22/vdp22/240.vdp b/test/qbg22/vdp22/240.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/240.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/241-lldpad.conf b/test/qbg22/vdp22/241-lldpad.conf -new file mode 100644 -index 0000000..d22aa2b ---- /dev/null -+++ b/test/qbg22/vdp22/241-lldpad.conf -@@ -0,0 +1,46 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station rule configuration file -+# -+ -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth0 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "stevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/241.nlc b/test/qbg22/vdp22/241.nlc -new file mode 100755 -index 0000000..b508e8a ---- /dev/null -+++ b/test/qbg22/vdp22/241.nlc -@@ -0,0 +1,43 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2014 -+# -+# Execute a simple assoc without group id support in bridge and station. -+# Check for hint bit support -+# -+ -+# Must: Wait some time for lldpad to start up and initialize -+outfile=$(basename $0) -+dirfile=$(dirname $0) -+testcase=$(basename $outfile .nlc) -+cd $dirfile -+ -+../../../vdptest -v -v -v -F vm2.cfg -i veth0 -Cnew=vm2_xx1,name=vm2_1,hints=from -s,w=30 -a vm2_xx1 -s,w=30 -d vm2_xx1 -s,w=10 -+rc=$? -+if [ "$rc" -ne 0 ] -+then -+ exit $rc -+fi -+fgrep -q '06 21 20 00 00 01 00 05 a1 41 28 57' /tmp/$testcase-lldpad.conf.out -+exit $? -diff --git a/test/qbg22/vdp22/241.vdp b/test/qbg22/vdp22/241.vdp -new file mode 100644 -index 0000000..fa3efbd ---- /dev/null -+++ b/test/qbg22/vdp22/241.vdp -@@ -0,0 +1,43 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2014 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 -+# lldpad bridge mode configuration file -+dcbx : -+{ -+ version = "1.0"; -+ dcbx_version = 2; -+}; -+nearest_customer_bridge : -+{ -+ veth2 : -+ { -+ tlvid00000001 : -+ { -+ info = "04C68829509676"; -+ }; -+ tlvid00000002 : -+ { -+ info = "03C68829509676"; -+ }; -+ adminStatus = 3; -+ @include "brevb_default.res" -+ }; -+}; -diff --git a/test/qbg22/vdp22/README b/test/qbg22/vdp22/README -new file mode 100644 -index 0000000..f58df8a ---- /dev/null -+++ b/test/qbg22/vdp22/README -@@ -0,0 +1,148 @@ -+ -+(c) Copyright IBM Corp. 2012, 2013 -+ -+Thomas Richter, IBM Research and Development, Germany, Mar 2013 -+ -+Test cases for IEEE802.1Qbg ratified standard VDP module. -+ -+14-Jun-2013 -+=========== -+Some test cases run the lldpad program in station mode and in bridge mode -+This is achieved via namespaces for network and IPC. Additionally the -+lldpad in bridge mode does not create a pid run time file /var/run/lldpad.pid. -+Use the network name space bridge_ns and then create an unnamed IPC namespace -+and execute lldpad in bridge mode. -+ -+Files -+===== -+ns_unshare Executes a command and with prior set of namespaces. Used to -+ set up an unnamed IPC namespace so 2 shared memory segments can -+ coexist for both lldpads (station and bridge role). -+runvdp.sh Runs one test case. -+ Return 0 on success and none zero otherwise. Uses qbg22sim as -+ bridge simulator. Test case result is determined by the -+ qbg22sim program. -+vm.cfg Configuration file for vdptest -+vm2.cfg Configuration file for vdptest using netlink format 2 -+ -+Tests -+===== -+The following test cases are executed. Each test case has a number. -+All test cases need a lldpad.conf configuration file, a VDP test input -+file and a netlink command file to send request to lldpad: -+- The VDP test input files have the extension .vdp. The test case number -+ is the base file name. This can be a qbg22sim input file or an lldpad -+ bridge-role configuration file. -+- The lldpad configuration file has the extension -lldpad.conf -+- The netlink command file has the extension .nlc -+ -+The purpose is to trigger an VDP DU exchange between qbg22sim and llpdad. -+The exchanged data can be inspected automaticly with little inteligence -+(see qbg22sim.1) or manually. -+ -+All test case with numbers 1 to 99 use lldpad as station role and numbers -+higher then 100 use lldpad as station and bridge role. -+ -+Test cases with number 200 and higher use netlink message format 2 to -+communicate between vdptest and llpdad. -+ -+Test cases with number 300 and higher use lldptool to trigger VDP22 protocol. -+ -+A (M) indication manual checking via lldpad trace output file inspection. -+ -+Test Description -+ -+100 Run assoc test with EVB22 disabled -+101 Check if netlink message is ignored in bridge role. -+102 Run assoc test with RR disabled -+103 Run a simple assoc and de-assoc test -+104 Run two simple assoc and de-assoc test -+105 Run a simple pre-assoc and de-assoc test -+106 Run two simple pre-assoc and de-assoc test -+107 Run a simple pre-assoc-rr and de-assoc test -+108 Run assoc --> pre-assoc test -+110 Run pre-assoc --> pre-assoc-rr --> assoc --> de-assoc test -+111 Run pre-assoc --> pre-assoc -- de-assoc test -+112 Run pre-assoc-rr --> pre-assoc-rr -- de-assoc test -+113 Run assoc --> assoc -- de-assoc test -+114 Run de-assoc test -+ -+115 Run assoc test with error response from switch -+116 Run pre-assoc test with error response in first keep alive from switch -+117 Run assoc test with de-assoc response in unsolicited message from switch -+118 Run pre-assoc test with error response from switch -+119 Run pre-assoc-rr test with error response in first keep alive from -+ switch -+120 Run pre-assoc test with de-assoc response in unsolicited message from -+ switch -+121 Run assoc test with keep-error response in first keep alive from switch -+122 Run pre-assoc test with hard-error response from switch switch -+123 Run assoc test with resource wait delay timeout on bridge. -+124 Run assoc test with keep alive timeout on bridge. -+ -+200 Run assoc/de-assoc test with long manager-id -+201 Run assoc/de-assoc test with gpid and group support turned off -+202 Run assoc/de-assoc test with vlan 0 replacement (fif 1) -+ de-assoc fails due to wrong filter -+203 Run assoc/de-assoc test with vlan 0 replacement (fif 1) -+ de-assoc succeeds due to correct filter -+204 Run assoc/de-assoc test with qos 0 replacement (fif 1) -+ de-assoc fails due to incorrect filter -+205 Run assoc/de-assoc test with qos 0 replacement (fif 1) -+ de-assoc succeeds due to correct filter -+206 Run assoc/de-assoc test with qos 0 replacement (fif 1) -+ fails due to wrong filter index -+207 Run assoc/de-assoc test with qos 0 replacement (fif 1) -+ fails due to unexpected QoS returned -+208 Run assoc/de-assoc test with vlan/qos requested by caller (fif 1) -+209 Run assoc/de-assoc test with vlan/qos requested by caller but not -+ confirmed by swtich (fif 1) -+210 Run assoc/de-assoc with multiple VID and one VID set to zero (fif 1) -+ fails because only one VID entry allowed, which is 0. -+211 Run assoc/de-assoc with multiple VIDs and expect QoS changed -+ for entry 4 (fif 1) -+212 Run assoc/de-assoc with multiple MAC/VIDs and expect all VLAN ID 0 -+ changed (fif 2). De-assoc fails because of wrong filter. -+213 Run assoc/de-assoc with multiple MAC/VIDs and expect all VLAN ID 0 -+ changed (fif 2). De-assoc succeeds. -+ -+Tests with group identifer support -+220 Run assoc/de-assoc test with 1 filter entry (fif 4) -+221 Run assoc/de-assoc test with 1 vlan 0 replacement (fif 4) -+222 Run assoc/de-assoc test with several filter entries (fif 4) -+223 Run assoc/de-assoc test with several vlan 0 replacement (fif 4) -+224 Run assoc/de-assoc test with QoS replacement (fif 4) -+225 Run assoc/de-assoc test with several vlan 0 and QoS replacement (fif 4) -+ -+Test with hint bits -+240 Run assoc/de-assoc test with suspend hints -+241 Run assoc/de-assoc test with migrate hints -+ -+TODO -+Test case with multiple filter entries. Combiniation of filter data. -+Run assoc(1) and assoc(2) with deassoc(1,2) -+ -+Run ethernet interface up/down tests while VSI actives -+Add filter info data to an existing VSI -+ -+ -+Remarks: -+ -+Test Execution -+============== -+Directory structure: -+ -+The following directory structure is assumed: -+/home/richter/dcn/qbg/mywork/open-lldp --> lldpad to test on target f18b -+/home/richter/dcn/qbg/mywork/test/qbg22/evb22 --> EVB protocol test cases -+/home/richter/dcn/qbg/mywork/test/qbg22/ecp22 --> ECP protocol test cases -+/home/richter/dcn/qbg/mywork/test/qbg22/vdp22 --> VDP protocol test cases -+ -+On local machine f18a: -+Select the evttest program by adding the path relative to test directory -+1. cd /home/richter/dcn/qbg/mywork/test/qbg22/vdp22 -+2. Use a symbolic link such as ./qbg22sim --> ../../../xxx/qbg22sim. -+3. Add the environment variable LLDPAD_DIR=abc to select an different lldpad -+ executable. For example the invocation -+ LLDPAD_DIR=new vdprun.sh 1.vdp -+ selects the file /home/richter/dcn/qbg/mywork/new/lldpad for execution. -diff --git a/test/qbg22/vdp22/allvdp.sh b/test/qbg22/vdp22/allvdp.sh -new file mode 100755 -index 0000000..0012618 ---- /dev/null -+++ b/test/qbg22/vdp22/allvdp.sh -@@ -0,0 +1,66 @@ -+#!/bin/bash -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2013 -+# -+# Execute the complete vdp test suite. -+# -+ -+runcommand() -+{ -+ # echo parameter $@ -+ cmd=$1 -+ file=$2 -+ -+ echo "start testcase $number" -+ $cmd $file 2>&1 -+ rc="$?" -+ if [ "$rc" -ne 0 ] -+ then -+ echo -en "\\033[1;31m" # Failures in red -+ echo "ERROR $file exit with $rc" -+ echo -en "\\033[0;39m" -+ exit 2 -+ fi -+ echo -en "\\033[1;32m" # Success in green -+ echo "OK testcase $file" -+ echo -en "\\033[0;39m" -+ return 0 -+} -+ -+# Extract type of test case from the first 3 characters of invocation file -+type=$(basename $0) -+type="${type:3:3}" -+ -+if ! which run$type.sh 2>/dev/null -+then -+ export PATH=$PATH:. -+fi -+ -+echo "Start testsuite at $(date)" -+for i in $(ls [1-9]*.$type|sort -n) -+do -+ runcommand run$type.sh $i -+done -+echo "Stop testsuite at $(date)" -+exit 0 -diff --git a/test/qbg22/vdp22/brevb_default.res b/test/qbg22/vdp22/brevb_default.res -new file mode 100644 -index 0000000..c626be1 ---- /dev/null -+++ b/test/qbg22/vdp22/brevb_default.res -@@ -0,0 +1,36 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD bridge mode default resource file -+# -+tlvid0080c20d : -+{ -+ enableTx = true; -+ evbmode = "bridge"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+}; -diff --git a/test/qbg22/vdp22/brevb_groupid.res b/test/qbg22/vdp22/brevb_groupid.res -new file mode 100644 -index 0000000..3651381 ---- /dev/null -+++ b/test/qbg22/vdp22/brevb_groupid.res -@@ -0,0 +1,36 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD bridge mode default resource file -+# -+tlvid0080c20d : -+{ -+ enableTx = true; -+ evbmode = "bridge"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+}; -diff --git a/test/qbg22/vdp22/ns_unshare.c b/test/qbg22/vdp22/ns_unshare.c -new file mode 100644 -index 0000000..cbc322a ---- /dev/null -+++ b/test/qbg22/vdp22/ns_unshare.c -@@ -0,0 +1,54 @@ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+ -+/* A simple error-handling function: print an error message based -+ on the value in 'errno' and terminate the calling process */ -+ -+#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ -+ } while (0) -+ -+static void -+usage(char *pname) -+{ -+ fprintf(stderr, "Usage: %s [options] program [arg...]\n", pname); -+ fprintf(stderr, "Options can be:\n"); -+ fprintf(stderr, " -i unshare IPC namespace\n"); -+ fprintf(stderr, " -m unshare mount namespace\n"); -+ fprintf(stderr, " -n unshare network namespace\n"); -+ fprintf(stderr, " -p unshare PID namespace\n"); -+ fprintf(stderr, " -u unshare UTS namespace\n"); -+ fprintf(stderr, " -U unshare user namespace\n"); -+ exit(EXIT_FAILURE); -+} -+ -+int -+main(int argc, char *argv[]) -+{ -+ int flags, opt; -+ -+ flags = 0; -+ -+ while ((opt = getopt(argc, argv, "imnpuU")) != -1) { -+ switch (opt) { -+ case 'i': flags |= CLONE_NEWIPC; break; -+ case 'm': flags |= CLONE_NEWNS; break; -+ case 'n': flags |= CLONE_NEWNET; break; -+ case 'p': flags |= CLONE_NEWPID; break; -+ case 'u': flags |= CLONE_NEWUTS; break; -+ case 'U': flags |= CLONE_NEWUSER; break; -+ default: usage(argv[0]); -+ } -+ } -+ -+ if (optind >= argc) -+ usage(argv[0]); -+ -+ if (unshare(flags) == -1) -+ errExit("unshare"); -+ -+ execvp(argv[optind], &argv[optind]); -+ errExit("execvp"); -+} -diff --git a/test/qbg22/vdp22/runvdp.sh b/test/qbg22/vdp22/runvdp.sh -new file mode 100755 -index 0000000..538c956 ---- /dev/null -+++ b/test/qbg22/vdp22/runvdp.sh -@@ -0,0 +1,186 @@ -+#!/bin/bash -+# -+# Execute test case for LLDPAD testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+ -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 16-Aug-2012 -+# -+# Execute a single test. Parameter is the name of the test file. -+# Run 2 lldpad instances in parallel using 2 network name spaces -+# -+ -+# Check if lldpad (bridge role) is up and running. Do not use the pid file. -+# Return 0 is not running and 1 if running (pid returned as string) -+function lldpad_brpid() -+{ -+ PID_lldpbr=$(ps -ef | fgrep lldpad | fgrep -- .vdp | awk '{ print $2 }') -+ if [ -z "$PID_lldpbr" ] -+ then -+ return 0 -+ fi -+ return 1 -+} -+ -+# Check if lldpad is up and running. Return pid or 0 if not running. -+function lldpad_pid() -+{ -+ PID_lldp=$(ps -ef | fgrep lldpad | fgrep -- .conf | awk '{ print $2 }') -+ if [ -z "$PID_lldp" ] -+ then -+ return 0 -+ fi -+ return 1 -+} -+ -+function lldpad_stop() -+{ -+ if [ "$1" -eq 0 ] -+ then -+ echo "$0:lldpad $2 terminated unexpectedly" -+ return 1 -+ fi -+ kill -s SIGTERM $1 -+ sleep 1 -+ ps -p $1 -o pid --no-header > /dev/null -+ if [ $? -ne 1 ] -+ then -+ kill -s SIGKILL $1 -+ fi -+ return 0 -+} -+ -+function cp_include() -+{ -+ for i in $(fgrep @include $1 | awk '{ print $2 }' | sed 's-"--gp') -+ do -+ cp $i /tmp -+ done -+} -+ -+# Use the correct lldpad configuration file and start lldpad. -+# Parameter 1: path to lldpad to use -+# Parameter 2: name of configuration file -+function lldpad_start() -+{ -+ if lldpad_pid -+ then -+ rm -f /var/lib/lldpad/lldpad.conf ./lldpad.conf -+ cp $2 /tmp/$2 -+ $1/lldpad -V7 -f /tmp/$2 >/tmp/$2.out 2>&1 & -+ sleep 1 -+ if lldpad_pid -+ then -+ echo "$0:lldpad not started or terminated unexpectedly" -+ exit 1 -+ else -+ echo "LLDPAD running pid $PID_lldp" -+ fi -+ else -+ exit 1 -+ fi -+ return 0 -+} -+ -+# Start lldpad in bridge role -+# Testfile is an lldpad configuration file with bridge settings. -+# Run lldpad without creating the /var/run/lldpad.pid file -+function lldpad_brstart() -+{ -+ if lldpad_brpid -+ then -+ cp $2 /tmp/$2 -+ cp_include $2 -+ cmd="./ns_unshare -i -- ../../../lldpad -p -V7 -f /tmp/$2" -+ ip netns exec bridge_ns $cmd > /tmp/$2.out 2>&1 & -+ sleep 1 -+ if lldpad_brpid -+ then -+ echo "$0:lldpad bridge role not started or terminated unexpectedly" -+ return 1 -+ else -+ echo "LLDPAD bridge role running pid $PID_lldpbr" -+ fi -+ else -+ return 1 -+ fi -+ return 0 -+} -+ -+if ! ip netns list | fgrep -qi bridge_ns -+then -+ echo "$0:bridge_ns network name space missing" -+ exit 1 -+fi -+ -+if ! which runvdp.sh 1>/dev/null 2>/dev/null -+then -+ export PATH=$PATH:$PWD -+fi -+ -+# Extract type of test case from last 3 characters of invocation -+type=$(basename $0) -+type=".${type:3:3}" -+ -+testfile=$1 -+no=$(basename $testfile $type) -+ -+# Find out if test case file is a lldpad configuration file to run lldpad -+# in bridge mode -+if ! egrep -qi tlvid0080c20d $testfile && egrep -qi 'evbmode[ \t]*=[ \t]*"?bridge"?' $testfile -+then -+ echo "$0:use qbg22sim as bridge simulator" -+ exit 1 -+fi -+ -+# Start lldpad using this name space -+if ! lldpad_start ../../.. $no-lldpad.conf -+then -+ echo "$0:can not start lldpad" -+ exit 1 -+fi -+ -+# Start lldpad bridge role -+if ! lldpad_brstart ../../.. $no.vdp -+then -+ echo "$0:can not start lldpad in bridge role" -+ # Stop lldpad -+ lldpad_stop $PID_lldp "station role" -+ exit 1 -+fi -+ -+# Check for shell script to run in parallel -+if [ -r "./$no.sh" -a -x "./$no.sh" ] -+then -+ ./$no.sh ../../.. & -+fi -+ -+# Start vdptest test program -+if [ -r "$no.nlc" ] -+then -+ ./$no.nlc >/tmp/$no.nlc.out 2>&1 -+ rc=$? -+fi -+ -+# Stop lldpad -+lldpad_stop $PID_lldpbr "bridge role" -+lldpad_stop $PID_lldp "station role" -+ -+exit $rc -diff --git a/test/qbg22/vdp22/stevb_default.res b/test/qbg22/vdp22/stevb_default.res -new file mode 100644 -index 0000000..2dbf8f8 ---- /dev/null -+++ b/test/qbg22/vdp22/stevb_default.res -@@ -0,0 +1,36 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station mode default resource file -+# -+tlvid0080c20d : -+{ -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = false; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+}; -diff --git a/test/qbg22/vdp22/stevb_groupid.res b/test/qbg22/vdp22/stevb_groupid.res -new file mode 100644 -index 0000000..f83e241 ---- /dev/null -+++ b/test/qbg22/vdp22/stevb_groupid.res -@@ -0,0 +1,36 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2013 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 11-Jul-2013 -+# -+# LLDPAD station mode default resource file -+# -+tlvid0080c20d : -+{ -+ enableTx = true; -+ evbmode = "station"; -+ evbrrcap = true; -+ evbrrreq = true; -+ evbgpid = true; -+ ecpretries = 3; -+ ecprte = 14; -+ vdprwd = 20; -+ vdprka = 20; -+}; -diff --git a/test/qbg22/vdp22/vm.cfg b/test/qbg22/vdp22/vm.cfg -new file mode 100644 -index 0000000..cf5c21e ---- /dev/null -+++ b/test/qbg22/vdp22/vm.cfg -@@ -0,0 +1,56 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2012 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2012 -+# -+# Configuration file for vsi data test cases -+# -+ -+name=vm1,mgrid=1,typeid=1,typeidver=1,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53aa,\ -+ map=2-52:54:00:8e:aa:11 -+name=vm3,mgrid=1,typeid=1,typeidver=1,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53aa,\ -+ map=2-52:54:00:8e:aa:1a -+name=vm2,mgrid=1,typeid=1,typeidver=1,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53dd,\ -+ map=2-52:54:00:8e:aa:22 -+name=vm1u3,mgrid=1,typeid=1,typeidver=1,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53aa,\ -+ map=2-52:54:00:8e:aa:11, \ -+ map=2-52:54:00:8e:aa:1a -+ -+# Used type ID 199 and check for bridge resource wait delay timeout -+name=vm199,mgrid=1,typeid=199,typeidver=1,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53aa,\ -+ map=3-52:54:00:8e:aa:33 -+# Used type ID 200 and check for bridge unsolicited deassoc message -+name=vm200,mgrid=1,typeid=200,typeidver=3,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53aa,\ -+ map=3-52:54:00:8e:aa:33 -+# Used type ID 201 and check if bridge return error response -+name=vm201,mgrid=1,typeid=201,typeidver=1,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53aa,\ -+ map=4-52:54:00:8e:aa:44 -+# Used type ID 202 and check if bridge return keep-error response -+name=vm202,mgrid=1,typeid=202,typeidver=3,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53aa,\ -+ map=202-52:54:00:8e:aa:44 -diff --git a/test/qbg22/vdp22/vm2.cfg b/test/qbg22/vdp22/vm2.cfg -new file mode 100644 -index 0000000..c27a08b ---- /dev/null -+++ b/test/qbg22/vdp22/vm2.cfg -@@ -0,0 +1,58 @@ -+# -+# Test case for LLDPAD VDP Testing according to IEEE 802.1Qbg -+# -+# Copyright (c) International Business Machines Corp., 2012 -+# -+# Author(s): Thomas Richter -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms and conditions of the GNU General Public License, -+# version 2, as published by the Free Software Foundation. -+# -+# This program is distributed in the hope it will be useful, but WITHOUT -+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+# more details. -+# -+# You should have received a copy of the GNU General Public License along with -+# this program; if not, write to the Free Software Foundation, Inc., -+# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+# -+# -+# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 21-Sep-2013 -+# -+# Configuration file for vsi data test cases. Use new netlink message format 2 -+# supporting features from the vdptest program: -+# - new group notation in the filter information: vlan-mac-group -+# - vlan id zero -+# - new long mgrid -+# - hint flags for VM migration support. -+ -+# Test new message format, filter info format 2 -+name=vm2_1,2mgrid=blabla,typeid=1,typeidver=0,hints=to,\ -+ uuid=a1412857-60f7-4ce1-e95a-2164943f53aa,\ -+ map=13-52:bb:cc:dd:ee:ff -+# Test VLAN 0 return. Bridge returns typeid as vlan. -+name=vm2_205,2mgrid=vlantest,typeid=205,typeidver=0,\ -+ uuid=00000000-1111-2222-3333-aabbccddeeff,\ -+ map=14 -+name=vm2_205a,2mgrid=vlantesta,typeid=205,typeidver=0,\ -+ uuid=00000000-1111-2222-3333-aabbccddeeff,\ -+ map=3,map=0/205,map=2,map=32 -+name=vm2_208,2mgrid=vlantestb,typeid=208,typeidver=0x13,\ -+ uuid=00000000-1111-2222-3333-aabbccddeeff,\ -+ map=10-aa:bb:00:00:00:10,map=0/0xb0d0-aa:bb:00:00:00:11,\ -+ map=0/0xb0d0-aa:bb:00:00:00:22 -+# Test QoS return. Bridge returns typeidver as qos (lower 3 bits). -+# Typeidver upper nibble used as index in fid array. -+name=vm2_206,2mgrid=qostest,typeid=206,typeidver=7,\ -+ uuid=00000000-1111-2222-3333-aabbccddeeff,\ -+ map=14 -+name=vm2_206b,2mgrid=qostest,typeid=206,typeidver=0x35,\ -+ uuid=00000000-1111-2222-3333-aabbccddeeff,\ -+ map=10,map=11,map=12,map=13/0xd00d,map=14,map=15 -+# Test VLAN assigned by bridge using group-id. -+# Typeidver upper nibble used as index in fid array. -+name=vm2_207,2mgrid=groupidtest,typeid=207,typeidver=0,\ -+ uuid=00000000-1111-2222-3333-aabbccddeeff,\ -+ map=2 -diff --git a/test/qbg22/veth-setup.sh b/test/qbg22/veth-setup.sh -new file mode 100755 -index 0000000..be94fa1 ---- /dev/null -+++ b/test/qbg22/veth-setup.sh -@@ -0,0 +1,45 @@ -+#!/bin/bash -+# -+# Thomas Richter, DCN Linux Technology Center, IBM Research, Germany 29-Apr-2013 -+# -+# Setup a lldpad test environment with 2 virtual ethernet device in 2 different -+# network name spaces. -+# lldpad runs in default name space and the qbg22sim runs in the newly created -+# bridge_ns name space. veth0 is in the default net name space where as -+# interface veth2 is in the bridge_ns name space -+# -+ -+# Check if the name space already exists. Also check if the interface veth0 -+# has been defined. -+if ip netns list | fgrep -qi bridge_ns -+then -+ if ip link | fgrep -qi veth0 -+ then -+ if ip netns exec bridge_ns ip link | fgrep -qi veth2 -+ then -+ exit 0 # veth0 and veth2 exists -+ else -+ echo interface veth2 missing -+ ip netns del bridge_ns -+ fi -+ else -+ ip netns del bridge_ns -+ fi -+fi -+ -+# create veth pair(veth0, veth2) -+# with this mac address on veth0 e6:f1:20:5a:b0:e6 for evb testing -+ip link add veth0 address e6:f1:20:5a:b0:e6 type veth peer name veth2 -+ip link set veth0 up -+ip addr add 50.0.0.1/24 dev veth0 -+ -+# create a new network namespace bridge_ns, bring up veth0 and assign an ip addr -+ip netns add bridge_ns -+ -+# move veth2 to bridge_ns -+ip link set veth2 netns bridge_ns -+ip netns exec bridge_ns ip link set veth2 up -+ip netns exec bridge_ns ip addr add 50.0.0.2/24 dev veth2 -+ -+# exec bash in bridge_ns -+# ip netns exec bridge_ns bash -diff --git a/test/qbg22sim.c b/test/qbg22sim.c -index eeafd7e..9ca227b 100644 ---- a/test/qbg22sim.c -+++ b/test/qbg22sim.c -@@ -59,7 +59,7 @@ - #define MYDEBUG 0 - #define DIM(x) (sizeof(x)/sizeof(x[0])) - #define ETH_P_LLDP 0x88cc --#define ETH_P_ECP 0x8890 -+#define ETH_P_ECP 0x8940 - #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - #define MAC2STR(a) (a)[0] & 0xff, (a)[1] & 0xff, (a)[2] & 0xff, \ - (a)[3] & 0xff, (a)[4] & 0xff, (a)[5] & 0xff -@@ -70,7 +70,7 @@ - - static char *progname; - static unsigned char eth_p_lldp[2] = { 0x88, 0xcc }; --static unsigned char eth_p_ecp[2] = { 0x88, 0x90 }; -+static unsigned char eth_p_ecp[2] = { ETH_P_ECP >> 8, ETH_P_ECP & 0xff }; - - static int verbose; - static char *tokens[1024]; /* Used to parse command line params */ -@@ -118,7 +118,7 @@ struct lldp { /* LLDP DUs */ - unsigned long runtime; /* Program run time in seconds */ - static struct lldp *lldphead; /* List of commands */ - static struct lldp *er_ecp; /* Expected replies ECP protocol */ --static struct lldp *er_evb; /* Expected replies ECP protocol */ -+static struct lldp *er_evb; /* Expected replies EVB protocol */ - - struct ecphdr { /* ECP header received */ - unsigned char version; /* Version number */ -@@ -534,7 +534,10 @@ static int addone(void) - exit(3); - p->opr = valid_cmd(); - if (p->opr) { -- p->ether = validate("88:90", 0); -+ char ecp_str[8]; -+ -+ sprintf(ecp_str, "%02x:%02x", eth_p_ecp[0], eth_p_ecp[1]); -+ p->ether = validate(ecp_str, 0); - goto out; - } - p->dst = validate(tokens[1], 0); -diff --git a/test/vdptest.1 b/test/vdptest.1 -index 81a2e60..5f1a1b9 100644 ---- a/test/vdptest.1 -+++ b/test/vdptest.1 -@@ -1,5 +1,5 @@ - .PU --.TH vdptest 1 "LLDPAD" "Revision: 0.1" -+.TH vdptest 1 "LLDPAD" "Revision: 0.2" - .SH NAME - vdptest \- VDP/VSI Protocol Test Program for LLDPAD - .SH SYNOPSIS -@@ -89,12 +89,16 @@ terminates. - .br - .B vdptest - should be used for testing and debug purposes only. -+It should be noted that there is no state stored in vdptest between calls, but -+will be stored in lldpad (until the process restarts). -+A profile must be created and acted upon on in the same vdptest command. - .SS Profiles - .br - Profile is a comma separated list of key '=' value - pairs describing the VSI profile data. - Profiles consists of the following keywords, --they are all mandatory: -+they are all mandatory with the execption of -+hints: - .TP - name: - Defines the name of the entry. -@@ -105,10 +109,20 @@ starting - with a character. - .TP - mgrid: --Defines the manager identifier for this entry. -+Defines the 1 byte manager identifier for this entry -+as defined by the IEEE 802.1 Qbg draft version 0.2. - The value should be a number in the - range of 0..255 inclusive. - .TP -+2mgrid: -+Defines the 16 byte manager identifier for this entry -+as defined by the IEEE 802.1 Qbg ratified standard. -+Either the -+.B mgrid -+or the -+.B 2mgrid -+should be used for an entry. -+.TP - typeid: - Defines the type identifier for this entry. - The value should be a number in the -@@ -130,26 +144,77 @@ The string is converted into 16 byte UUID - with 2 nibbles converted into one byte. - .TP - map: --Defines a VLAN-MAC address pair for this entry. -+Defines a VLAN-MAC-GROUP address triple for this entry. - The value is of the following format: - .EX --vlanid-aa:bb:cc:dd:ee:ff -+vlanid[/newvid][-[aa:bb:cc:dd:ee:ff][-grid]] - .EE - Vlandid is converted into a number ranging --from 0..4095. --Following the vlanid is a dash (\-) and --an MAC address. -+from 0..65535. -+If the vlanid is followed by an option slash ('/') -+the number following the slash is the new vlan identifier -+expected from the switch. -+Following the vlanid is an optional dash (\-) and -+a MAC address. - The MAC address is a 6 byte value, each byte - delimited by a colon (':'). -+A second optional dash (\-) can be -+specified to supply a group identifier. -+If omitted the group identifier is assumed to -+be zero and is ignored. - This keyword can be listed several times to allow --multiple MAC-VLAN pairs per entry. -+multiple MAC-VLAN-GROUP triples per entry. -+.sp 1 -+The form of this entry determines the format of the -+filter information data send to the switch. -+The input -+.EX -+map=1 -+.EE -+is converted to filter information format -+.IR VID . -+The input -+.EX -+map=1--123 -+.EE -+is converted to filter information format -+.IR GROUP/VID . -+The input -+.EX -+map=1-11:22:33:44:55:66 -+.EE -+is converted to filter information format -+.IR VID/MAC . -+The input -+.EX -+map=1-11:22:33:44:55:66-123 -+.EE -+is converted to filter information format -+.IR GROUP/VID/MAC . -+Note that filter information formats can not be mixed in -+a single entry. Multiple -+map entries have to be of the same format. -+.TP -+hints: -+This keyword is optional and if omitted defaults to -+.IR none . -+Indicates support for IEEE 802.1 Qbg ratified standard -+virtual machine migration. -+Valid keywords are -+.I none -+(no indicate no migration support), -+.I to -+(to indicate the virtual machine is migrating to this VSI) -+and -+.I from -+(to indicate the virtual machine is migrating from this VSI). - .TP - Example: - Here is an example of a profile definition: - .EX --name=thomas2,mgrid=1,typeid=123452,typeidver=1,\(rs -+name=thomas2,mgrid=1,typeid=123452,typeidver=1,hints=none\(rs - uuid=a1412857-60f7-4ce1-e95a-2164943f53dd,\(rs -- map=2-52:54:00:8e:50:53 -+ map=2-52:54:00:8e:50:53-9999,map=0/10-52:54:00:8e:50:54-8888 - .EE - .SS Commands - Command is an option character followed -@@ -272,12 +337,12 @@ Several definitions using the same - .I name - are not allowed. - .TP --.B "\-C\fIname,new=new-name,changes\fP" -+.B "\-C\fInew=new-name,name=old-name,changes\fP" - Copy the profile entry named --.I name --and assign it -+.I old-name -+and assign it to - .IR new-name. --After the first comma, list the fields which -+After the second comma list the fields which - are to be changed using the same syntax as in - the profile definition. - If an error is encountered during keyword parsing -@@ -401,17 +466,13 @@ flag. If this option is not set then the following default values - are used: delaytime (1 second), waittime (1 second) and number of acknowledgements - reads (1). - .SH "EXAMPLES" -+Define a profile and show its definition. -+.sp 1 - .EX - vdptest -Aname=thomas2,mgrid=1,typeid=123452,typeidver=1, - uuid=a1412857-60f7-4ce1-e95a-2164943f53dd,map=2-52:54:00:8e:50:53 -S - .EE - .sp 1 --Define a profile and show its definition. --.sp 1 --.EX --vdptest -C thomas2,new=unknown,typeid=99999 --.EE --.sp 1 - Copies the entry named - .I thomas2 - and assigns its contents to the name -@@ -425,7 +486,7 @@ is the - field. - .sp 1 - .EX --vdptest -i eth2 -F vdptest.cfg -a unknown,w=10,r=2,e=3 -s -+vdptest -Cnew=unknown,name=thomas2,typeid=99999 - .EE - .sp 1 - Use interface eth2 and read the VSI configuration from file -@@ -434,12 +495,13 @@ Use the VSI definition named - .I unknown - and send an ASSOCIATION command to the switch. - Wait up to 10 seconds for the status confirmation 2 --times and expected the error code 3 from the switch. -+times and expected the error code 3 from the switch -+(NOTE that this will cause vdptest to return FAILURE under -+normal conditions). - Wait one second before termintation. - .sp 1 - .EX --vdptest -i eth2 -F vdptest.cfg -Cthomas2,new=x1,mgrid=2 \(rs -- -athomas2,w=10,r=2,e=3 -s -a x1,w=5 -+vdptest -i eth2 -F vdptest.cfg -a unknown,w=10,r=2,e=3 -s - .EE - .sp 1 - Use interface eth2 and read the VSI configuration from file -@@ -455,12 +517,17 @@ Send an ASSOCIATION command with parameters stored in - wait one second and - send an ASSOCIATION command with parameters stored in - .IR x1 . -+.sp 1 -+.EX -+vdptest -i eth2 -F vdptest.cfg -Cnew=x1,name=thomas2,2mgrid=blabla \(rs -+ -a thomas2,w=10,r=2,e=3 -s -a x1,w=5 -+.EE - .SH FILES --/var/run/lldpad.pid -+/var/run/lldpad.pid, /var/lib/lldpad/lldpad.conf - .SH "ENVIRONMENT" --Linux RHEL -+Linux - .SH "SEE ALSO" --lldpad(8), lldptool(8) -+lldpad(8), lldptool(8), libvirtd(8) - .SH DIAGNOSTICS - Exit status is zero on success and non zero on failure or mismatch. - .SH AUTHOR -diff --git a/test/vdptest.c b/test/vdptest.c -index 8447c6c..8a423fb 100644 ---- a/test/vdptest.c -+++ b/test/vdptest.c -@@ -29,7 +29,27 @@ - * - associate a VSI - * - disassociate a VSI - * - receive a netlink message from lldpad when -- * - the switch de-associates the VSI profile (switch data base cleaned) -+ * - the switch de-associates the VSI profile (switch data base cleaned) -+ * -+ * Note: -+ * libvirtd is currently the only production code user of lldpad netlink -+ * interface. It uses -+ * - no qos: always set to 0. -+ * - only one mac/macvlan pair. -+ * - netlink message format 1 (no qos/vlanid change on switch side, no group -+ * id support at all) -+ * -+ * Netlink message format 1 is the default and does not -+ * - expect vlanid etc back from switch -+ * - use the vsi.maclist.qos member at all. -+ * -+ * Netlink message format 2 is selected when -+ * - group id is entered in the map keyword -+ * - 2mgrid is selected as keyword to specified long manager identifier -+ * - replacement vlan identifier is specified in the map keyword -+ * - hints keyword is specified. -+ * This format handles a reply from the switch and compares returned vlan/qos -+ * values. - */ - - #include -@@ -40,7 +60,10 @@ - #include - #include - #include -+#include -+#include - -+#include - #include - #include - -@@ -48,15 +71,17 @@ - #include - #include - -+#include - #include - - #include "clif.h" - #include "clif_msgs.h" -+#include "include/qbg22.h" -+#include "qbg_vdp22def.h" -+#include "qbg_vdpnl.h" - --#define UUIDLEN 16 --#define DIM(x) (sizeof(x)/sizeof(x[0])) --#define COPY_OP "new=" --#define KEYLEN 16 -+#define COPY_OP "new=" -+#define KEYLEN 16 - #define CMD_ASSOC 'a' /* Association */ - #define CMD_DEASSOC 'd' /* DE-Association */ - #define CMD_PREASSOC 'p' /* pre-Association */ -@@ -67,23 +92,710 @@ - #define CMD_EXTERN 'E' /* External command */ - #define CMD_SETDF 'X' /* Change defaults */ - -+#define BAD_FILTER 250 /* VLAN error in filter data */ -+ -+#define DIM(x) (sizeof(x)/sizeof(x[0])) -+ -+/* -+ * New version, implemented as library function and header file in lldpad-devel -+ * package. -+ * -+ * Netlink message for QBG 2.2 ratified standard -+ */ -+ -+enum { /* 802.1Qbg VDP ratified standard */ -+ IFLA_PORT_VSI_TYPE22 = IFLA_PORT_MAX, -+ IFLA_PORT_VSI_FILTER, -+ __IFLA_PORT_MAX_NEW -+}; -+ -+#undef IFLA_PORT_MAX -+#define IFLA_PORT_MAX (__IFLA_PORT_MAX_NEW - 1) -+ -+/* -+ * Filter information data. Valid fields are determined by the -+ * filter information format type member named 'vsi_filter_fmt'. The -+ * number of the entries available is stored in the member named -+ * 'vsi_filter_num', see below. -+ */ -+struct ifla_port_vsi_filter { -+ __u32 gpid; /* Group Identifier*/ -+ __u16 vlanid; /* Vlan id and QoS */ -+ __u8 mac[6]; /* MAC address */ -+}; -+ -+struct ifla_port_vsi22 { /* 802.1 Qbg Ratified standard */ -+ __u8 vsi_mgrid[PORT_UUID_MAX]; /* Manager identifier */ -+ __u8 vsi_uuid[PORT_UUID_MAX]; /* VSI identifier */ -+ __u8 vsi_uuidfmt; /* Format of UUID string */ -+ __u8 vsi_type_id[3]; /* Type identifier */ -+ __u8 vsi_type_version; /* Type version identifier */ -+ __u8 vsi_hints; /* Hint bits */ -+ __u8 vsi_filter_fmt; /* Filter information format */ -+ __u16 vsi_filter_num; /* # of filter data entries */ -+}; -+ -+/* -+ * Helper functions to construct a netlink message. -+ * The functions assume the nlmsghdr.nlmsg_len is set correctly. -+ */ -+static void mynla_nest_end(struct nlmsghdr *nlh, struct nlattr *start) -+{ -+ start->nla_type |= NLA_F_NESTED; -+ start->nla_len = (void *)nlh + nlh->nlmsg_len - (void *)start; -+} -+ -+static struct nlattr *mynla_nest_start(struct nlmsghdr *nlh, int type) -+{ -+ struct nlattr *ap = (struct nlattr *)((void *)nlh + nlh->nlmsg_len); -+ -+ ap->nla_type = type; -+ nlh->nlmsg_len += NLA_HDRLEN; -+ return ap; -+} -+ -+static void mynla_put(struct nlmsghdr *nlh, int type, size_t len, void *data) -+{ -+ struct nlattr *ap = (struct nlattr *)((void *)nlh + nlh->nlmsg_len); -+ -+ ap->nla_type = type; -+ ap->nla_len = NLA_HDRLEN + len; -+ memcpy(ap + 1, data, len); -+ nlh->nlmsg_len += NLA_HDRLEN + NLA_ALIGN(len); -+} -+ -+static void mynla_put_u8(struct nlmsghdr *nlh, int type, __u8 data) -+{ -+ mynla_put(nlh, type, sizeof data, &data); -+} -+ -+static void mynla_put_u32(struct nlmsghdr *nlh, int type, __u32 data) -+{ -+ mynla_put(nlh, type, sizeof data, &data); -+} -+ -+static void *mynla_data(const struct nlattr *nla) -+{ -+ return (char *)nla + NLA_HDRLEN; -+} -+ -+static void mynla_get(const struct nlattr *nla, size_t len, void *data) -+{ -+ memcpy(data, mynla_data(nla), len); -+} -+ -+static __u32 mynla_get_u32(const struct nlattr *nla) -+{ -+ return *(__u32 *)mynla_data(nla); -+} -+ -+static __u16 mynla_get_u16(const struct nlattr *nla) -+{ -+ return *(__u16 *)mynla_data(nla); -+} -+ -+static int mynla_payload(const struct nlattr *nla) -+{ -+ return nla->nla_len - NLA_HDRLEN; -+} -+ -+static int mynla_type(const struct nlattr *nla) -+{ -+ return nla->nla_type & ~NLA_F_NESTED; -+} -+ -+static int mynla_ok(const struct nlattr *nla, int rest) -+{ -+ return rest >= (int) sizeof(*nla) && -+ nla->nla_len >= sizeof(*nla) && nla->nla_len <= rest; -+} -+ -+static struct nlattr *mynla_next(const struct nlattr *nla, int *rest) -+{ -+ int len = NLA_ALIGN(nla->nla_len); -+ -+ *rest -= len; -+ return (struct nlattr *)((char *)nla + len); -+} -+ -+static inline int mynla_attr_size(int payload) -+{ -+ return NLA_HDRLEN + payload; -+} -+ -+static int mynla_total_size(int payload) -+{ -+ return NLA_ALIGN(mynla_attr_size(payload)); -+} -+ -+/* -+ * Parse a list of netlink attributes. -+ * Return 0 on success and errno when the parsing fails. -+ */ -+static int mynla_parse(struct nlattr **tb, size_t tb_len, struct nlattr *pos, -+ int attrlen) -+{ -+ unsigned short nla_type; -+ -+ while (mynla_ok(pos, attrlen)) { -+ nla_type = mynla_type(pos); -+ if (nla_type < tb_len) -+ tb[nla_type] = (struct nlattr *)pos; -+ pos = mynla_next(pos, &attrlen); -+ } -+ return (attrlen) ? -EINVAL : 0; -+} -+ -+ -+/* -+ * Return needed buffer space in bytes to construct netlink message setlink -+ * request. Return the maximum size needed. -+ * In netlink message format 1 only one MAC/VLAN pair is supported. -+ * In netlink message format 2 many MAC/VLAN/group pairs are supported. -+ */ -+static size_t nlvsi_getsize(struct vdpnl_vsi *vsip) -+{ -+ return NLMSG_SPACE(sizeof(struct ifinfomsg)) /* Header */ -+ + mynla_total_size(IFNAMSIZ + 1) /* IFLA_IFNAME */ -+ + mynla_total_size(sizeof(struct nlattr)) /* IFLA_VF_PORTS */ -+ + mynla_total_size(4) /* VF_PORTS */ -+ + mynla_total_size(4) /* VF_PORT */ -+ + mynla_total_size(1) /* PORT_VDP_REQUEST */ -+ + mynla_total_size(2) /* PORT_VDP_RESPONSE */ -+ + mynla_total_size(PORT_UUID_MAX) /* INSTANCE UUID */ -+ + mynla_total_size(sizeof(struct ifla_port_vsi)) -+ /* VSI_TYPE */ -+ + mynla_total_size(sizeof(struct nlattr)) -+ /* IFLA_VFINFO_LIST */ -+ + mynla_total_size(sizeof(struct nlattr)) -+ /* IFLA_VF_INFO */ -+ + mynla_total_size(sizeof(struct ifla_vf_mac)) -+ /* IFLA_VF_MAC */ -+ + mynla_total_size(sizeof(struct ifla_vf_vlan )) -+ /* IFLA_VF_VLAN */ -+ + mynla_total_size(sizeof(struct ifla_port_vsi22)) -+ + mynla_total_size(vsip->macsz -+ * sizeof(struct ifla_port_vsi_filter)); -+} -+ -+/* -+ * Test input and return false on error. -+ */ -+static int nlvsi_isgood(struct vdpnl_vsi *vsip) -+{ -+ if (!vsip->macsz) -+ return 0; -+ switch (vsip->filter_fmt) { -+ case VDP22_FFMT_MACVID: -+ case VDP22_FFMT_VID: -+ case VDP22_FFMT_GROUPMACVID: -+ case VDP22_FFMT_GROUPVID: -+ break; -+ default: -+ return 0; -+ } -+ -+ /* -+ * Adjust for different request numbering. -+ * Draft 0.2 starts from 0 and ratified standard starts from 1. -+ * Sequence is PREASSOC, PREASSOC_RR, ASSOC, DEASSOC -+ * -+ * Expect "offical" draft 0.2 numbering defined in -+ * /usr/include/linux/if_link.h -+ */ -+ switch (vsip->request + 1) { -+ case VDP22_PREASSOC: -+ case VDP22_PREASSOC_WITH_RR: -+ case VDP22_ASSOC: -+ case VDP22_DEASSOC: -+ break; -+ default: -+ return 0; -+ } -+ -+ switch (vsip->vsi_idfmt) { -+ case VDP22_ID_IP4: -+ case VDP22_ID_IP6: -+ case VDP22_ID_MAC: -+ case VDP22_ID_LOCAL: -+ case VDP22_ID_UUID: -+ break; -+ default: -+ return 0; -+ } -+ -+ if (vsip->hints && (vsip->hints != VDP22_MIGTO -+ && vsip->hints != VDP22_MIGFROM)) -+ return 0; -+ -+ if (vsip->vsi_typeid >= (1 << 24)) /* 3 byte type identifier */ -+ return 0; -+ return 1; -+} -+ -+/* -+ * Build netlink message 1 format. -+ */ -+static void nlf1(struct vdpnl_vsi *vsip, struct nlmsghdr *nlh) -+{ -+ struct nlattr *port, *ports; -+ struct ifla_port_vsi myvsi; -+ int i; -+ -+ ports = mynla_nest_start(nlh, IFLA_VF_PORTS); -+ port = mynla_nest_start(nlh, IFLA_VF_PORT); -+ mynla_put_u8(nlh, IFLA_PORT_REQUEST, vsip->request); -+ memset(&myvsi, 0, sizeof(myvsi)); -+ myvsi.vsi_mgr_id = vsip->vsi_mgrid; -+ myvsi.vsi_type_id[2] = (vsip->vsi_typeid >> 16) & 0xff; -+ myvsi.vsi_type_id[1] = (vsip->vsi_typeid >> 8) & 0xff; -+ myvsi.vsi_type_id[0] = vsip->vsi_typeid & 0xff; -+ myvsi.vsi_type_version = vsip->vsi_typeversion; -+ mynla_put(nlh, IFLA_PORT_VSI_TYPE, sizeof(myvsi), &myvsi); -+ mynla_put(nlh, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, vsip->vsi_uuid); -+ mynla_nest_end(nlh, port); -+ mynla_nest_end(nlh, ports); -+ -+ ports = mynla_nest_start(nlh, IFLA_VFINFO_LIST); -+ for (i = 0; i < vsip->macsz; ++i) { -+ port = mynla_nest_start(nlh, IFLA_VF_INFO); -+ if (vsip->filter_fmt == VDP22_FFMT_MACVID) { -+ struct ifla_vf_mac vf_mac = { -+ .vf = PORT_SELF_VF -+ }; -+ -+ memcpy(vf_mac.mac, vsip->maclist[i].mac, ETH_ALEN); -+ mynla_put(nlh, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); -+ } -+ if (vsip->filter_fmt) { -+ struct ifla_vf_vlan vf_vlan = { -+ .vf = PORT_SELF_VF, -+ .vlan = vsip->maclist[i].vlan & 0xfff, -+ .qos = (vsip->maclist[i].vlan >> 12) & 7 -+ }; -+ -+ mynla_put(nlh, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); -+ } -+ mynla_nest_end(nlh, port); -+ } -+ mynla_nest_end(nlh, ports); -+} -+ -+/* -+ * Build netlink message 2 format. -+ */ -+static void nlf2(struct vdpnl_vsi *vsip, struct nlmsghdr *nlh) -+{ -+ struct ifla_port_vsi22 myvsi; -+ struct ifla_port_vsi_filter fdata[vsip->macsz]; -+ struct nlattr *port, *ports; -+ int i; -+ -+ memset(&myvsi, 0, sizeof(myvsi)); -+ memset(fdata, 0, sizeof(fdata)); -+ ports = mynla_nest_start(nlh, IFLA_VF_PORTS); -+ port = mynla_nest_start(nlh, IFLA_VF_PORT); -+ mynla_put_u32(nlh, IFLA_PORT_VF, vsip->vf); -+ mynla_put_u8(nlh, IFLA_PORT_REQUEST, vsip->request); -+ mynla_put(nlh, IFLA_PORT_INSTANCE_UUID, PORT_UUID_MAX, vsip->vsi_uuid); -+ myvsi.vsi_type_id[2] = (vsip->vsi_typeid >> 16) & 0xff; -+ myvsi.vsi_type_id[1] = (vsip->vsi_typeid >> 8) & 0xff; -+ myvsi.vsi_type_id[0] = vsip->vsi_typeid & 0xff; -+ myvsi.vsi_type_version = vsip->vsi_typeversion; -+ myvsi.vsi_uuidfmt = vsip->vsi_idfmt; -+ memcpy(myvsi.vsi_mgrid, vsip->vsi_mgrid2, sizeof(myvsi.vsi_mgrid)); -+ myvsi.vsi_hints = vsip->hints; -+ myvsi.vsi_filter_fmt = vsip->filter_fmt; -+ myvsi.vsi_filter_num = vsip->macsz; -+ mynla_put(nlh, IFLA_PORT_VSI_TYPE22, sizeof(myvsi), &myvsi); -+ for (i = 0; i < vsip->macsz; ++i) { -+ struct ifla_port_vsi_filter *ep = &fdata[i]; -+ -+ ep->vlanid = vsip->maclist[i].vlan; -+ if (vsip->filter_fmt == VDP22_FFMT_MACVID -+ || vsip->filter_fmt == VDP22_FFMT_GROUPMACVID) -+ memcpy(ep->mac, vsip->maclist[i].mac, sizeof(ep->mac)); -+ if (vsip->filter_fmt == VDP22_FFMT_GROUPVID -+ || vsip->filter_fmt == VDP22_FFMT_GROUPMACVID) -+ ep->gpid = vsip->maclist[i].gpid; -+ } -+ mynla_put(nlh, IFLA_PORT_VSI_FILTER, sizeof(fdata), fdata); -+ mynla_nest_end(nlh, port); -+ mynla_nest_end(nlh, ports); -+} -+ -+/* -+ * Construct the netlink request message for the VSI profile. -+ * Return number of bytes occupied in buffer or errno on error. -+ */ -+static int vdpnl_request_build(struct vdpnl_vsi *vsip, unsigned char *buf, -+ size_t len) -+{ -+ struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -+ struct ifinfomsg ifinfo; -+ -+ if (!nlvsi_isgood(vsip)) -+ return -EINVAL; -+ if (nlvsi_getsize(vsip) > len) -+ return -ENOMEM; -+ memset(buf, 0, len); -+ memset(&ifinfo, 0, sizeof(ifinfo)); -+ nlh->nlmsg_type = RTM_SETLINK; -+ nlh->nlmsg_pid = getpid(); -+ nlh->nlmsg_seq = vsip->req_seq; -+ nlh->nlmsg_flags = NLM_F_REQUEST; -+ nlh->nlmsg_len = NLMSG_SPACE(sizeof ifinfo); -+ ifinfo.ifi_index = vsip->ifindex; -+ ifinfo.ifi_family = AF_UNSPEC; -+ memcpy(NLMSG_DATA(nlh), &ifinfo, sizeof(ifinfo)); -+ mynla_put(nlh, IFLA_IFNAME, 1 + strlen(vsip->ifname), vsip->ifname); -+ if (vsip->nl_version == vdpnl_nlf2) -+ nlf2(vsip, nlh); -+ else -+ nlf1(vsip, nlh); -+ return nlh->nlmsg_len; -+} -+ -+/* -+ * Read the contents of the IFLA_PORT_VSI_FILTER netlink attribute. -+ * It is an array of struct ifla_port_vsi_filter entries. -+ * Return 0 on success and errno on failure. -+ * -+ * Code to parse netlink message format 2. -+ */ -+static void parse_filter_data(struct vdpnl_vsi *vsip, struct nlattr *tb) -+{ -+ int i = 0; -+ struct ifla_port_vsi_filter elem[vsip->macsz]; -+ -+ mynla_get(tb, sizeof(elem), elem); -+ for (i = 0; i < vsip->macsz; ++i) { -+ struct vdpnl_mac *macp = &vsip->maclist[i]; -+ struct ifla_port_vsi_filter *ep = &elem[i]; -+ -+ macp->vlan = ep->vlanid; -+ macp->gpid = ep->gpid; -+ memcpy(macp->mac, ep->mac, sizeof(macp->mac)); -+ } -+} -+ -+/* -+ * Read the contents of the IFLA_PORT_VSI_FILTER netlink attribute. -+ * Return 0 on success and errno on failure. -+ * -+ * Code to parse netlink message format 2. -+ */ -+static int parse_vsi_type22(struct vdpnl_vsi *vsip, struct nlattr *tb, -+ struct nlattr *tc) -+{ -+ struct ifla_port_vsi22 myvsi; -+ -+ mynla_get(tb, sizeof(myvsi), &myvsi); -+ vsip->filter_fmt = myvsi.vsi_filter_fmt; -+ if (vsip->macsz >= myvsi.vsi_filter_num) { -+ vsip->macsz = myvsi.vsi_filter_num; -+ parse_filter_data(vsip, tc); -+ return 0; -+ } -+ return -E2BIG; -+} -+ -+/* -+ * Parse the IFLA_VF_PORT block of the netlink message. -+ * Return 1 when uuid found and 0 when not found and errno else. -+ * Set length of filter pair on return. -+ * -+ * Code to parse netlink message format 1. -+ */ -+static int scan_vf_port(struct vdpnl_vsi *vsi, struct nlattr *tb) -+{ -+ struct nlattr *vf[IFLA_PORT_MAX + 1]; -+ int found = 0, rc; -+ -+ memset(vf, 0, sizeof(vf)); -+ rc = mynla_parse(vf, DIM(vf), mynla_data(tb), mynla_payload(tb)); -+ if (rc) -+ return -EINVAL; -+ if (vf[IFLA_PORT_INSTANCE_UUID]) { -+ if (!memcmp(mynla_data(vf[IFLA_PORT_INSTANCE_UUID]), -+ vsi->vsi_uuid, sizeof(vsi->vsi_uuid)) -+ && vf[IFLA_PORT_RESPONSE]) { -+ found = 1; -+ vsi->response = mynla_get_u16(vf[IFLA_PORT_RESPONSE]); -+ } -+ } else -+ return -EINVAL; -+ if (found && vf[IFLA_PORT_VSI_TYPE22] && vf[IFLA_PORT_VSI_FILTER]) -+ rc = parse_vsi_type22(vsi, vf[IFLA_PORT_VSI_TYPE22], -+ vf[IFLA_PORT_VSI_FILTER]); -+ else -+ vsi->macsz = 0; -+ return found; -+} -+ -+/* -+ * Parse the IFLA_VF_PORTS block of the netlink message. Expect many -+ * IFLA_VF_PORT attribute and search the one we are looking for. -+ * Return zero on success and errno else. -+ * -+ * Code to parse netlink message format 1. -+ */ -+static int scan_vf_ports(struct vdpnl_vsi *vsi, struct nlattr *tb) -+{ -+ struct nlattr *pos; -+ int rest, rc = 0; -+ -+ for (rest = mynla_payload(tb), pos = mynla_data(tb); -+ mynla_ok(pos, rest) && rc == 0; pos = mynla_next(pos, &rest)) { -+ if (mynla_type(pos) == IFLA_VF_PORT) -+ rc = scan_vf_port(vsi, pos); -+ else -+ rc = -EINVAL; -+ } -+ return rc; -+} -+ -+/* -+ * Scan the GETLINK reply and parse the response for the UUID. -+ * -+ * Return -+ * < 0 on error -+ * 0 wanted UUID not in reply -+ * 1 found -+ */ -+static int vdpnl_getreply_parse(struct vdpnl_vsi *p, unsigned char *buf, -+ size_t len) -+{ -+ struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -+ struct nlattr *tb[IFLA_MAX + 1]; -+ int rc; -+ -+ if (len < nlh->nlmsg_len) -+ return -ENOMEM; -+ memset(tb, 0, sizeof(tb)); -+ rc = mynla_parse(tb, DIM(tb), -+ (struct nlattr *)IFLA_RTA(NLMSG_DATA(nlh)), -+ IFLA_PAYLOAD(nlh)); -+ if (rc || !tb[IFLA_VF_PORTS]) -+ return -EINVAL; -+ return scan_vf_ports(p, tb[IFLA_VF_PORTS]); -+} -+ -+/* -+ * Parse a received netlink request message and check for errors. -+ * When a netlink error message is received, return it in the 3rd -+ * parameter. -+ * -+ * Return -+ * <0 on parse error. -+ * 1 when a netlink error response is received. -+ * 0 when no netlink error response -+ */ -+static int vdpnl_getreply_error(unsigned char *buf, size_t len, int *error) -+{ -+ struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -+ -+ if (len < nlh->nlmsg_len) -+ return -ENOMEM; -+ if (nlh->nlmsg_type == NLMSG_ERROR) { -+ struct nlmsgerr *err = NLMSG_DATA(nlh); -+ -+ if (error) -+ *error = err->error; -+ return 1; -+ } -+ return 0; -+} -+ - /* -- * Set the define MYDEBUG to any value for detailed debugging -+ * Parse the IFLA_VF_PORT block of an unsolicited netlink message triggered -+ * after a dis-associated from switch. -+ * Set length of filter pair on return. -+ * -+ * Code to parse netlink message format 1. - */ -+static int trigger_vf_port(struct vdpnl_vsi *vsi, struct nlattr *tb) -+{ -+ struct nlattr *vf[IFLA_PORT_MAX + 1]; -+ int rc; -+ struct ifla_port_vsi portvsi; - -+ memset(vf, 0, sizeof(vf)); -+ rc = mynla_parse(vf, DIM(vf), mynla_data(tb), mynla_payload(tb)); -+ if (rc) -+ return -EINVAL; -+ if (vf[IFLA_PORT_INSTANCE_UUID]) -+ mynla_get(vf[IFLA_PORT_INSTANCE_UUID], sizeof(vsi->vsi_uuid), -+ vsi->vsi_uuid); -+ else -+ return -EINVAL; -+ if (vf[IFLA_PORT_REQUEST]) -+ vsi->response = mynla_get_u16(vf[IFLA_PORT_REQUEST]); -+ else -+ return -EINVAL; -+ if (vf[IFLA_PORT_VF]) -+ vsi->vf = mynla_get_u32(vf[IFLA_PORT_VF]); -+ else -+ return -EINVAL; -+ if (vf[IFLA_PORT_VSI_TYPE]) { -+ mynla_get(vf[IFLA_PORT_VSI_TYPE], sizeof portvsi, &portvsi); -+ vsi->vsi_mgrid = portvsi.vsi_mgr_id; -+ vsi->vsi_typeversion = portvsi.vsi_type_version; -+ vsi->vsi_typeid = portvsi.vsi_type_id[0] << 16 -+ | portvsi.vsi_type_id[1] << 8 -+ | portvsi.vsi_type_id[2] << 8; -+ } else -+ return -EINVAL; -+ vsi->macsz = 0; /* No returned filter data */ -+ return 0; -+} -+ -+/* -+ * Parse the IFLA_VF_PORTS block of the netlink message. Expect many -+ * IFLA_VF_PORT attribute and search the one we are looking for. -+ * Return zero on success and errno else. -+ * -+ * Code to parse netlink message format 1. -+ */ -+static int trigger_vf_ports(struct vdpnl_vsi *vsi, struct nlattr *tb) -+{ -+ struct nlattr *pos; -+ int rest, rc = 0; -+ -+ for (rest = mynla_payload(tb), pos = mynla_data(tb); -+ mynla_ok(pos, rest) && rc == 0; pos = mynla_next(pos, &rest)) { -+ if (mynla_type(pos) == IFLA_VF_PORT) -+ rc = trigger_vf_port(vsi, pos); -+ else -+ rc = -EINVAL; -+ } -+ return rc; -+} -+ -+/* -+ * Parse the IFLA_VF_INFO block. -+ */ -+static int trigger_vf_info(struct vdpnl_mac *p, struct nlattr *tb) -+{ -+ struct nlattr *vf[IFLA_VF_MAX + 1]; -+ struct ifla_vf_mac ifla_vf_mac; -+ struct ifla_vf_vlan ifla_vf_vlan; -+ int rc; -+ -+ memset(vf, 0, sizeof(vf)); -+ memset(&ifla_vf_mac, 0, sizeof(ifla_vf_mac)); -+ memset(&ifla_vf_vlan, 0, sizeof(ifla_vf_vlan)); -+ rc = mynla_parse(vf, DIM(vf), mynla_data(tb), mynla_payload(tb)); -+ if (rc) -+ return -EINVAL; -+ if (vf[IFLA_VF_MAC]) { -+ mynla_get(vf[IFLA_VF_MAC], sizeof ifla_vf_mac, &ifla_vf_mac); -+ memcpy(p->mac, ifla_vf_mac.mac, sizeof(p->mac)); -+ } else -+ return -EINVAL; -+ if (vf[IFLA_VF_VLAN]) { -+ mynla_get(vf[IFLA_VF_VLAN], sizeof ifla_vf_vlan, &ifla_vf_vlan); -+ p->vlan = ifla_vf_vlan.vlan & 0xfff; -+ p->qos = ifla_vf_vlan.qos & 0xf; -+ } else -+ return -EINVAL; -+ return 0; -+} -+ -+/* -+ * Parse the IFLA_VFINFO_LIST block which contains blocks of VF_INFO blocks. -+ */ -+static int trigger_vfinfo_list(struct vdpnl_vsi *p, struct nlattr *tb) -+{ -+ struct nlattr *pos; -+ int i = 0, rest, rc = 0; -+ -+ if (p->macsz) /* This must be netlink format 2 */ -+ return -EINVAL; -+ for (rest = mynla_payload(tb), pos = mynla_data(tb); -+ mynla_ok(pos, rest); pos = mynla_next(pos, &rest)) { -+ ++p->macsz; -+ } -+ if (!p->macsz) /* No VLAN/MAC pair */ -+ return -EINVAL; -+ p->maclist = calloc(p->macsz, sizeof(*p->maclist)); -+ if (!p->maclist) { -+ p->macsz = 0; -+ return -ENOMEM; -+ } -+ for (rest = mynla_payload(tb), pos = mynla_data(tb); -+ mynla_ok(pos, rest) && rc == 0; -+ ++i, pos = mynla_next(pos, &rest)) { -+ if (mynla_type(pos) == IFLA_VF_INFO) -+ rc = trigger_vf_info(&p->maclist[i], pos); -+ else -+ rc = -EINVAL; -+ } -+ if (rc) { -+ free(p->maclist); -+ p->maclist = NULL; -+ p->macsz = 0; -+ } -+ return rc; -+} -+ -+/* -+ * Scan an unsolicited message from lldpad and parse the response for the UUID. -+ * -+ * Return -+ * < 0 on error -+ * 0 success -+ */ -+static int vdpnl_trigger_parse(struct vdpnl_vsi *p, unsigned char *buf, -+ size_t len) -+{ -+ struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -+ struct nlattr *tb[IFLA_MAX + 1]; -+ int rc; -+ -+ if (len < nlh->nlmsg_len) -+ return -ENOMEM; -+ memset(tb, 0, sizeof(tb)); -+ rc = mynla_parse(tb, DIM(tb), -+ (struct nlattr *)IFLA_RTA(NLMSG_DATA(nlh)), -+ IFLA_PAYLOAD(nlh)); -+ if (rc || !tb[IFLA_VF_PORTS] || !tb[IFLA_IFNAME] -+ || !tb[IFLA_VFINFO_LIST]) -+ return -EINVAL; -+ mynla_get(tb[IFLA_IFNAME], sizeof(p->ifname), p->ifname); -+ return trigger_vf_ports(p, tb[IFLA_VF_PORTS]) -+ | trigger_vfinfo_list(p, tb[IFLA_VFINFO_LIST]); -+} -+ -+ -+/* -+ * Code for construction vdp protocol messages. -+ */ - enum { - f_map, - f_mgrid, - f_typeid, - f_typeidver, -- f_uuid -+ f_uuid, -+ f_hints, -+ f_2mgrid -+}; -+ -+enum { -+ fid_clr = 0, /* Returned filter check */ -+ fid_ok = 1, /* Filter changed ok */ -+ fid_mod = 2 /* Filter modified unexpectedly */ - }; - - struct macvlan { - unsigned char mac[ETH_ALEN]; /* MAC address */ -- unsigned short vlanid; /* VLAN Id */ -+ unsigned short vlanid; /* VLAN Id */ -+ unsigned long gpid; /* Group */ -+ unsigned short newvid; /* New vlan id returned from switch */ -+ unsigned char flags; /* Tested? */ - }; - -+#define CMDTABSZ 32 /* Table size for VSI commands */ - static struct vdpdata { - char key[KEYLEN]; /* Profile name */ - unsigned char modified; /* Field altered */ -@@ -91,9 +803,20 @@ static struct vdpdata { - unsigned char mgrid; /* Manager ID */ - unsigned char typeidver; /* Type ID version */ - unsigned int typeid; /* Type ID */ -- unsigned char uuid[UUIDLEN]; /* Instance ID */ -+ unsigned char uuid[PORT_UUID_MAX]; /* Instance ID */ -+ unsigned char mgrid2[PORT_UUID_MAX]; /* Manager ID VDP22 */ - struct macvlan addr[10]; /* Pairs of MAC/VLAN */ --} vsidata[32]; -+ unsigned char fif; /* Filter info format */ -+ unsigned char hints; /* Migrate to/from hits */ -+ unsigned char nlmsg_v; /* Version of netlink message to use */ -+} vsidata[CMDTABSZ]; -+ -+struct vdpback { /* Reply data from lldpad */ -+ unsigned char uuid[PORT_UUID_MAX]; /* Instance ID */ -+ unsigned short resp; /* Response */ -+ unsigned char pairs; /* # of returned VLAN */ -+ struct macvlan addr[10]; /* Pairs of MAC/VLAN */ -+}; - - static struct command { /* Command structure */ - char key[KEYLEN]; /* Name of profile to use */ -@@ -104,8 +827,9 @@ static struct command { /* Command structure */ - unsigned char no_err; /* # of expected errors */ - int errors[4]; /* Expected errors */ - int rc; /* Encountered error */ -+ int sys_rc; /* System error on send/receive of messages */ - char *text; /* Text to display */ --} cmds[32], defaults = { /* Default values in structure */ -+} cmds[CMDTABSZ], defaults = { /* Default values in structure */ - .waittime = 1, - .repeats = 1, - .delay = 1000 -@@ -119,24 +843,6 @@ static int ifindex; /* Index of ifname */ - static char *ifname; /* Interface to operate on */ - static pid_t lldpad; /* LLDPAD process identifier */ - static int my_sock; /* Netlink socket for lldpad talk */ --static char mybuf[1024]; /* Buffer for netlink message decode */ -- --static struct nla_policy ifla_vf_policy[IFLA_VF_MAX + 1] = { -- [IFLA_VF_MAC] = { -- .minlen = sizeof(struct ifla_vf_mac), -- .maxlen = sizeof(struct ifla_vf_mac) -- }, -- [IFLA_VF_VLAN] = { -- .minlen = sizeof(struct ifla_vf_vlan), -- .maxlen = sizeof(struct ifla_vf_vlan) -- } --}; -- --static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] = { -- [IFLA_PORT_RESPONSE] = { -- .type = NLA_U16 -- } --}; - - static void uuid2buf(const unsigned char *p, char *buf) - { -@@ -146,167 +852,94 @@ static void uuid2buf(const unsigned char *p, char *buf) - p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); - } - --static int addit(char *format, ...) -+#if 0 -+static void showmac(struct vdpnl_vsi *p) - { -- size_t left = strlen(mybuf); -- int c; -- va_list ap; -+ int i; -+ struct vdpnl_mac *macp = p->maclist; - -- va_start(ap, format); -- c = vsnprintf(mybuf + left, sizeof mybuf - left, format, ap); -- va_end(ap); -- return (c < 0 || ((unsigned)c >= sizeof mybuf - left)) ? -1 : 0; -+ for (i = 0; i < p->macsz; ++i, ++macp) -+ printf("\tvlan:%hd qos:%d\n", macp->vlan, macp->qos); - } -+#endif - --static int showerror(struct nlmsghdr *nlh) -+static int test_new(unsigned short new, unsigned short me) - { -- struct nlmsgerr *err = NLMSG_DATA(nlh); -+ unsigned short new_vlan = (new & 0xfff); -+ unsigned char new_qos = (new >> 12) & 0xf; -+ unsigned short vlan = (me & 0xfff); -+ unsigned char qos = (me >> 12) & 0xf; - -- if (verbose) -- printf("%s setlink response:%d\n", progname, err->error); -- return err->error; -+ return (vlan == new_vlan && qos == new_qos); - } - --static void parse_vfinfolist(struct nlattr *vfinfolist) -+static void expect_fid(struct vdpdata *vdp) - { -- struct nlattr *le1, *vf[IFLA_VF_MAX + 1]; -- int rem; -- -- addit("\tfound IFLA_VFINFO_LIST!\n"); -- nla_for_each_nested(le1, vfinfolist, rem) { -- if (nla_type(le1) != IFLA_VF_INFO) { -- fprintf(stderr, "%s nested parsing of" -- "IFLA_VFINFO_LIST failed\n", progname); -- return; -- } -- if (nla_parse_nested(vf, IFLA_VF_MAX, le1, ifla_vf_policy)) { -- fprintf(stderr, "%s nested parsing of " -- "IFLA_VF_INFO failed\n", progname); -- return; -- } -- -- if (vf[IFLA_VF_MAC]) { -- struct ifla_vf_mac *mac = RTA_DATA(vf[IFLA_VF_MAC]); -- unsigned char *m = mac->mac; -- -- addit("\tIFLA_VF_MAC=%02x:%02x:%02x:" -- " %02x:%02x:%02x\n", -- m[0], m[1], m[2], m[3], m[4], m[5]); -- } -- -- if (vf[IFLA_VF_VLAN]) { -- struct ifla_vf_vlan *vlan = RTA_DATA(vf[IFLA_VF_VLAN]); -+ int i; -+ struct macvlan *mac = vdp->addr; -+ -+ printf(" expected"); -+ for (i = 0; i < vdp->pairs; ++i, ++mac) -+ if( mac->flags == fid_clr) -+ printf(" [%hu,%hu]", -+ (mac->newvid ?: mac->vlanid) & 0xfff, -+ (mac->newvid ?: mac->vlanid) >> 12 & 0xf); -+} - -- addit("\tIFLA_VF_VLAN=%d\n", vlan->vlan); -+static int test_fid(struct vdpnl_mac *new, struct vdpdata *vdp) -+{ -+ int i; -+ struct macvlan *mac = vdp->addr; -+ -+ for (i = 0; i < vdp->pairs; ++i, ++mac) { -+ if (mac->flags == fid_clr) { -+ if (test_new(new->vlan, mac->newvid ?: mac->vlanid)) { -+ mac->flags = fid_ok; -+ return 0; -+ } - } - } -+ return BAD_FILTER; - } - --static void show_nlas(struct nlattr **tb, int max) -+static int compare_fid(struct vdpnl_vsi *back, struct vdpdata *vdp) - { -- int rem; -- -- for (rem = 0; rem < max; ++rem) { -- if (tb[rem]) -- printf("nlattr %02d type:%d len:%d\n", rem, -- tb[rem]->nla_type, tb[rem]->nla_len); -+ int rc = 0, i; -+ -+ for (i = 0; i < vdp->pairs; ++i) -+ vdp->addr[i].flags = fid_clr; -+ /* -+ * Check each returned filter data. Should be in the list of newvid. -+ */ -+ for (i = 0; rc == 0 && i < back->macsz; ++i) { -+ rc |= test_fid(&back->maclist[i], vdp); -+ if (verbose >= 3) { -+ printf("%s fid:%d vlan:%hu qos:%hu", -+ progname, i, back->maclist[i].vlan & 0xfff, -+ (back->maclist[i].vlan >> 12) & 0xf); -+ if (rc) -+ expect_fid(vdp); -+ else -+ printf(" match ok"); -+ printf("\n"); -+ } - } -+ return rc; - } - --static void showmsg(struct nlmsghdr *nlh, int *status) -+static int compare_vsi(struct vdpnl_vsi *p, struct vdpdata *vdp) - { -- struct nlattr *tb[IFLA_MAX + 1], *tb3[IFLA_PORT_MAX + 1]; -- struct ifinfomsg ifinfo; -- char *ifname; -- int rem; -+ int rc = 0; - -- if (status) -- *status = -1; -- if (nlh->nlmsg_type == NLMSG_ERROR) { -- if (status) -- *status = showerror(nlh); -- return; -- } -- memset(mybuf, 0, sizeof mybuf); -- addit("\tnlh.nl_pid:%d nlh_type:%d nlh_seq:%#x nlh_len:%#x\n", -- nlh->nlmsg_pid, nlh->nlmsg_type, nlh->nlmsg_seq, nlh->nlmsg_len); -- memcpy(&ifinfo, NLMSG_DATA(nlh), sizeof ifinfo); -- addit("\tifinfo.family:%#x type:%#x index:%d flags:%#x change:%#x\n", -- ifinfo.ifi_family, ifinfo.ifi_type, ifinfo.ifi_index, -- ifinfo.ifi_flags, ifinfo.ifi_change); -- if (nlmsg_parse(nlh, sizeof ifinfo, -- (struct nlattr **)&tb, IFLA_MAX, NULL)) { -- fprintf(stderr, "%s error parsing request...\n", progname); -- return; -- } -- if (verbose >= 3) -- show_nlas(tb, IFLA_MAX); -- if (tb[IFLA_IFNAME]) { -- ifname = (char *)RTA_DATA(tb[IFLA_IFNAME]); -- addit("\tIFLA_IFNAME=%s\n", ifname); -- } -- if (tb[IFLA_OPERSTATE]) { -- rem = *(unsigned short *)RTA_DATA(tb[IFLA_OPERSTATE]); -- addit("\tIFLA_OPERSTATE=%d\n", rem); -- } -- if (tb[IFLA_VFINFO_LIST]) -- parse_vfinfolist(tb[IFLA_VFINFO_LIST]); -- if (tb[IFLA_VF_PORTS]) { -- struct nlattr *tb_vf_ports; -- -- addit("\tfound IFLA_VF_PORTS\n"); -- nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) { -- -- if (nla_type(tb_vf_ports) != IFLA_VF_PORT) { -- fprintf(stderr, "%s not a IFLA_VF_PORT, " -- " skipping\n", progname); -- continue; -- } -- if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb_vf_ports, -- ifla_port_policy)) { -- fprintf(stderr, "%s nested parsing on level 2" -- " failed\n", progname); -- } -- if (tb3[IFLA_PORT_VF]) -- addit("\tIFLA_PORT_VF=%d\n", -- *(uint32_t *) RTA_DATA(tb3[IFLA_PORT_VF])); -- if (tb3[IFLA_PORT_VSI_TYPE]) { -- struct ifla_port_vsi *pvsi; -- int tid = 0; -- -- pvsi = (struct ifla_port_vsi *) -- RTA_DATA(tb3[IFLA_PORT_VSI_TYPE]); -- tid = pvsi->vsi_type_id[2] << 16 | -- pvsi->vsi_type_id[1] << 8 | -- pvsi->vsi_type_id[0]; -- addit("\tIFLA_PORT_VSI_TYPE=mgr_id:%d " -- " type_id:%d typeid_version:%d\n", -- pvsi->vsi_mgr_id, tid, -- pvsi->vsi_type_version); -- } -- if (tb3[IFLA_PORT_INSTANCE_UUID]) { -- char uuidbuf[64]; -- unsigned char *uuid; -+ if (verbose >= 2) { -+ char uuidbuf[64]; - -- uuid = (unsigned char *) -- RTA_DATA(tb3[IFLA_PORT_INSTANCE_UUID]); -- uuid2buf(uuid, uuidbuf); -- addit("\tIFLA_PORT_INSTANCE_UUID=%s\n", -- uuidbuf); -- } -- if (tb3[IFLA_PORT_REQUEST]) -- addit("\tIFLA_PORT_REQUEST=%d\n", *(uint8_t *) -- RTA_DATA(tb3[IFLA_PORT_REQUEST])); -- if (tb3[IFLA_PORT_RESPONSE]) { -- addit("\tIFLA_PORT_RESPONSE=%d\n", *(uint16_t *) -- RTA_DATA(tb3[IFLA_PORT_RESPONSE])); -- *status = *(int *) -- RTA_DATA(tb3[IFLA_PORT_RESPONSE]); -- } -- } -+ uuid2buf(p->vsi_uuid, uuidbuf); -+ printf("%s uuid:%s response:%d no_vlanid:%hd\n", progname, -+ uuidbuf, p->response, p->macsz); - } -- if (verbose >= 2) -- printf("%s", mybuf); -+ rc = compare_fid(p, vdp); -+ return rc; - } - - /* -@@ -314,35 +947,38 @@ static void showmsg(struct nlmsghdr *nlh, int *status) - * - * Return number of bytes received. 0 means timeout and -1 on error. - */ --static int waitmsg(struct command *cp, int *status) -+static int lldp_waitmsg(int waittime, unsigned char *msgbuf, size_t msgbuf_len) - { -- struct msghdr msg; -+ struct timeval tv1, tv2, tv_res; - struct sockaddr_nl dest_addr; -- struct iovec iov; -- unsigned char msgbuf[1024]; -- struct nlmsghdr *nlh = (struct nlmsghdr *)msgbuf; -+ struct iovec iov = { -+ .iov_base = msgbuf, -+ .iov_len = msgbuf_len -+ }; -+ struct msghdr msg = { -+ .msg_name = &dest_addr, -+ .msg_namelen = sizeof(dest_addr), -+ .msg_iov = &iov, -+ .msg_iovlen = 1, -+ .msg_controllen = 0, -+ .msg_control = 0 -+ }; - int n, result = 0; - fd_set readfds; - - struct timeval tv = { -- .tv_sec = cp->waittime -+ .tv_sec = waittime - }; - -- memset(&msgbuf, 0, sizeof msgbuf); -- memset(&dest_addr, 0, sizeof dest_addr); -- iov.iov_base = (void *)nlh; -- iov.iov_len = sizeof msgbuf; -- msg.msg_name = (void *)&dest_addr; -- msg.msg_namelen = sizeof(dest_addr); -- msg.msg_iov = &iov; -- msg.msg_iovlen = 1; -- - if (verbose) - printf("%s Waiting %d seconds for message...\n", progname, -- cp->waittime); -+ waittime); - FD_ZERO(&readfds); - FD_SET(my_sock, &readfds); -+ gettimeofday(&tv1, NULL); - n = select(my_sock + 1, &readfds, NULL, NULL, &tv); -+ gettimeofday(&tv2, NULL); -+ timersub(&tv2, &tv1, &tv_res); - if (n <= 0) { - if (n < 0) - fprintf(stderr, "%s error netlink socket:%s\n", -@@ -353,88 +989,119 @@ static int waitmsg(struct command *cp, int *status) - progname); - return n; - } -+ memset(msgbuf, 0, msgbuf_len); -+ memset(&dest_addr, 0, sizeof(dest_addr)); - result = recvmsg(my_sock, &msg, MSG_DONTWAIT); - if (result < 0) -- fprintf(stderr, "%s receive error:%s\n", -- progname, strerror(errno)); -- else { -- if (verbose) -- printf("%s received %d bytes from %d\n", -- progname, result, dest_addr.nl_pid); -- showmsg(nlh, status); -- } -+ fprintf(stderr, "%s receive error:%s wait:%ld:%06ld\n\n", -+ progname, strerror(errno), tv_res.tv_sec, -+ tv_res.tv_usec); -+ else if (verbose) -+ printf("%s received %d bytes from %d wait:%ld:%06ld\n", -+ progname, result, dest_addr.nl_pid, tv_res.tv_sec, -+ tv_res.tv_usec); - return result; - } - --static int lldp_wait(struct command *cp) --{ -- int rc = 0; -- unsigned int cnt; -- -- for (cnt = 0; cnt < cp->repeats && rc >= 0; ++cnt) -- if ((rc = waitmsg(cp, 0))) { -- cp->rc = 1; -- break; -- } -- return rc; --} -- - /* -- * Construct the GETLINK message to lldpad. -+ * Find out which vdp this unsolicited message was sent for. - */ --static int mk_nlas(char *buf) -+static struct vdpdata *finduuid(unsigned char *uuid) - { -- int total; -- struct nlattr *nlap; -- char *cp; -- struct ifinfomsg *to = (struct ifinfomsg *)buf; -+ unsigned int i; - -- to->ifi_index = ifindex; -- to->ifi_family = AF_UNSPEC; -- total = NLMSG_ALIGN(sizeof *to); -- nlap = (struct nlattr *)(buf + NLMSG_ALIGN(sizeof *to)); -- nlap->nla_type = IFLA_IFNAME; -- nlap->nla_len = NLA_HDRLEN + NLA_ALIGN(1 + strlen(ifname)); -- total += nlap->nla_len; -- cp = (char *)nlap + NLA_HDRLEN; -- strcpy(cp, ifname); -- return total; -+ for (i = 0; i < DIM(vsidata); ++i) -+ if (!memcmp(vsidata[i].uuid, uuid, sizeof(vsidata[i].uuid))) -+ return &vsidata[i]; -+ return 0; -+} -+ -+static int trigger_test(struct vdpnl_vsi *p) -+{ -+ char uuid[64]; -+ int rc = -1; -+ -+ uuid2buf(p->vsi_uuid, uuid); -+ if (finduuid(p->vsi_uuid)) { -+ if (p->response == PORT_REQUEST_DISASSOCIATE) -+ rc = 1; -+ } -+ if (p->maclist) -+ free(p->maclist); -+ if (verbose >= 2) -+ printf("%s switch dis-assoc %s rc:%d\n", progname, uuid, rc); -+ return rc; -+} -+ -+int vdpnl_trigger_parse(struct vdpnl_vsi *, unsigned char *, size_t); -+ -+static void lldp_wait(struct command *cp) -+{ -+ int rc = 0; -+ unsigned int cnt; -+ unsigned char rcvbuf[2 * 1024]; -+ struct vdpnl_vsi p; -+ -+ for (cnt = 0; cnt < cp->repeats && rc >= 0; ++cnt) { -+ cp->sys_rc = cp->rc = 0; -+ rc = lldp_waitmsg(cp->waittime, rcvbuf, sizeof(rcvbuf)); -+ if (rc < 0) { -+ cp->sys_rc = rc; -+ break; -+ } -+ if (rc > 0) { /* Check for de-assoc message */ -+ memset(&p, 0, sizeof(p)); -+ rc = vdpnl_trigger_parse(&p, rcvbuf, sizeof(rcvbuf)); -+ if (rc < 0) -+ cp->sys_rc = rc; -+ else -+ cp->rc = trigger_test(&p); -+ break; -+ } -+ } - } - - /* - * Send a GETLINK message to lldpad to query the status of the operation. - */ --static int getlink(void) -+static int lldp_getlink(void) - { -- struct sockaddr_nl d_nladdr; -- struct msghdr msg; -- char buffer[256]; -- struct nlmsghdr *nlh = (struct nlmsghdr *)buffer; -- struct iovec iov; -+ char msgbuf[256]; -+ struct iovec iov = { -+ .iov_base = msgbuf, -+ .iov_len = sizeof(msgbuf), -+ }; -+ struct sockaddr_nl dest_addr; -+ struct msghdr msg = { -+ .msg_name = &dest_addr, -+ .msg_namelen = sizeof(dest_addr), -+ .msg_iov = &iov, -+ .msg_iovlen = 1, -+ .msg_controllen = 0, -+ .msg_control = 0 -+ }; -+ struct nlmsghdr *nlh = (struct nlmsghdr *)msgbuf; -+ struct ifinfomsg ifinfo; - int rc; - -- memset(buffer, 0, sizeof buffer); -- /* Destination address */ -- memset(&d_nladdr, 0, sizeof d_nladdr); -- d_nladdr.nl_family = PF_NETLINK; -- d_nladdr.nl_pid = lldpad; -+ memset(msgbuf, 0, sizeof(msgbuf)); -+ ifinfo.ifi_index = ifindex; -+ ifinfo.ifi_family = AF_UNSPEC; - - /* Fill the netlink message header */ -- nlh->nlmsg_len = NLMSG_HDRLEN + mk_nlas((char *)NLMSG_DATA(nlh)); - nlh->nlmsg_pid = getpid(); - nlh->nlmsg_flags = NLM_F_REQUEST; - nlh->nlmsg_type = RTM_GETLINK; -+ nlh->nlmsg_len = NLMSG_SPACE(sizeof(ifinfo)); -+ memcpy(NLMSG_DATA(nlh), &ifinfo, sizeof(ifinfo)); -+ mynla_put(nlh, IFLA_IFNAME, 1 + strlen(ifname), ifname); -+ iov.iov_len = nlh->nlmsg_len; - -- /* Iov structure */ -- iov.iov_base = (void *)nlh; -- iov.iov_len = nlh->nlmsg_len; -+ /* Destination address */ -+ memset(&dest_addr, 0, sizeof(dest_addr)); -+ dest_addr.nl_family = PF_NETLINK; -+ dest_addr.nl_pid = lldpad; - -- /* Msg */ -- memset(&msg, 0, sizeof msg); -- msg.msg_name = (void *)&d_nladdr; -- msg.msg_namelen = sizeof d_nladdr; -- msg.msg_iov = &iov; -- msg.msg_iovlen = 1; - if ((rc = sendmsg(my_sock, &msg, 0)) == -1) - perror(progname); - if (verbose) -@@ -445,195 +1112,219 @@ static int getlink(void) - /* - * Send a RTM_GETLINK message and retrieve the status of the pending - * command. -+ * -+ * Return -+ * <0 send/receive error -+ * 0 send/receive ok, but returned netlink message contains netlink error -+ * 1 send/receive ok, returned netlink message contains parsed response -+ * 2 send/receive ok, but no message returned at all - */ --static int lldp_ack(struct command *cp) -+int vdpnl_getreply_error(unsigned char *, size_t, int *); -+int vdpnl_getreply_parse(struct vdpnl_vsi *, unsigned char *, size_t); -+ -+static int lldp_recv(struct command *cp, struct vdpnl_vsi *p) - { -- int bytes; -- int status; -- -- bytes = getlink(); -- if (bytes <= 0) -- return bytes; -- bytes = waitmsg(cp, &status); -- if (bytes <= 0) -- return bytes; -- cp->rc = status; -+ unsigned int cnt; -+ int rc, rc2, bytes; -+ unsigned char rcvbuf[2 * 1024]; -+ -+ for (bytes = 0, cnt = 0; cnt < cp->repeats && bytes == 0; ++cnt) { -+ usleep(cp->delay * 1000); -+ cp->sys_rc = lldp_getlink(); -+ if (cp->sys_rc < 0) -+ return cp->sys_rc; -+ cp->rc = cp->sys_rc = 0; -+ bytes = lldp_waitmsg(cp->waittime, rcvbuf, sizeof(rcvbuf)); -+ if (bytes < 0) /* Error */ -+ return cp->sys_rc = bytes; -+ if (bytes > 0) { /* Got reply */ -+ rc2 = vdpnl_getreply_error(rcvbuf, sizeof(rcvbuf), &rc); -+ if (rc2 < 0) { /* Parsing failed */ -+ if (verbose) -+ printf("%s getlink errmsg parse " -+ "error:%d\n", progname, rc2); -+ return cp->sys_rc = cp->rc = rc2; -+ } else if (rc2 == 1) { /* Error reply */ -+ if (verbose) -+ printf("%s getlink error response:%d\n", -+ progname, rc); -+ cp->rc = rc; -+ return 0; -+ } -+ /* Normal reply, parsed ok */ -+ rc2 = vdpnl_getreply_parse(p, rcvbuf, sizeof(rcvbuf)); -+ if (rc2 < 0) { /* Parsing failed */ -+ if (verbose) -+ printf("%s getlink parse error rc:%d\n", -+ progname, rc2); -+ return cp->sys_rc = cp->rc = rc2; -+ } else if (rc2 == 1) { /* Found reply */ -+ cp->rc = p->response; -+ return 1; -+ } else if (rc2 == 0) { -+ /* Reply without UUID/RESPONSE attribute */ -+ if (verbose >= 2) -+ printf("%s getlink parse UUID/RESPONSE" -+ " missing\n", progname); -+ cp->rc = -1; -+ } -+ } -+ } -+ return 2; -+} -+ -+static int check_sendack(struct nlmsghdr *nlh, int *ack) -+{ -+ struct nlmsgerr *err = NLMSG_DATA(nlh); -+ -+ if (nlh->nlmsg_type != NLMSG_ERROR) -+ return -1; - if (verbose) -- printf("%s lldp_ack status:%d\n", progname, cp->rc); -- return bytes; --} -- --static int addvfs(struct nl_msg *nl_msg, struct vdpdata *vdp, unsigned char cmd) --{ -- struct nlattr *vfports, *vfport; -- struct ifla_port_vsi vsi; -- unsigned char op; -- -- switch (cmd) { -- case CMD_ASSOC: -- op = PORT_REQUEST_ASSOCIATE; -- break; -- case CMD_DEASSOC: -- op = PORT_REQUEST_DISASSOCIATE; -- break; -- case CMD_PREASSOC: -- op = PORT_REQUEST_PREASSOCIATE; -- break; -- case CMD_RRPREASSOC: -- op = PORT_REQUEST_PREASSOCIATE_RR; -- break; -- } -- -- vsi.vsi_mgr_id = vdp->mgrid; -- vsi.vsi_type_version = vdp->typeidver; -- vsi.vsi_type_id[2] = vdp->typeid >> 16; -- vsi.vsi_type_id[1] = vdp->typeid >> 8; -- vsi.vsi_type_id[0] = vdp->typeid; -- -- if (!(vfports = nla_nest_start(nl_msg, IFLA_VF_PORTS))) -- return -ENOMEM; -- if (!(vfport = nla_nest_start(nl_msg, IFLA_VF_PORT))) -- return -ENOMEM; -- if (nla_put(nl_msg, IFLA_PORT_VSI_TYPE, sizeof vsi, &vsi) < 0) -- return -ENOMEM; -- if (nla_put(nl_msg, IFLA_PORT_INSTANCE_UUID, UUIDLEN, vdp->uuid) < 0) -- return -ENOMEM; -- if (nla_put(nl_msg, IFLA_PORT_REQUEST, sizeof op, &op) < 0) -- return -ENOMEM; -- nla_nest_end(nl_msg, vfport); -- nla_nest_end(nl_msg, vfports); -+ printf("%s setlink response:%d\n", progname, err->error); -+ *ack = err->error; - return 0; - } - --static int addmacs(struct nl_msg *nl_msg, struct vdpdata *vdp) --{ -- int i; -- struct nlattr *vfinfolist, *vfinfo; -- -- if (vdp->pairs == 0) -- return 0; -- if (!(vfinfolist = nla_nest_start(nl_msg, IFLA_VFINFO_LIST))) -- return -ENOMEM; -- for (i = 0; i < vdp->pairs; ++i) { -- if (!(vfinfo = nla_nest_start(nl_msg, IFLA_VF_INFO))) -- return -ENOMEM; -- -- if (vdp->addr[i].mac) { -- struct ifla_vf_mac ifla_vf_mac; -- -- ifla_vf_mac.vf = PORT_SELF_VF; -- memcpy(ifla_vf_mac.mac, vdp->addr[i].mac, ETH_ALEN); -- if (nla_put(nl_msg, IFLA_VF_MAC, sizeof ifla_vf_mac, -- &ifla_vf_mac) < 0) -- return -ENOMEM; -- } -- -- if (vdp->addr[i].vlanid) { -- struct ifla_vf_vlan ifla_vf_vlan = { -- .vf = PORT_SELF_VF, -- .vlan = vdp->addr[i].vlanid, -- .qos = 0, -- }; -- -- if (nla_put(nl_msg, IFLA_VF_VLAN, sizeof ifla_vf_vlan, -- &ifla_vf_vlan) < 0) -- return -ENOMEM; -- } -- nla_nest_end(nl_msg, vfinfo); -- } -- nla_nest_end(nl_msg, vfinfolist); -- return 0; --} -- --/* -- * Build the netlink message, return total length of message -- */ --static int buildmsg(unsigned char *buf, size_t len, unsigned char cmd, -- struct vdpdata *vdp) --{ -- struct nlmsghdr *nlh; -- struct nl_msg *nl_msg; -- struct ifinfomsg ifinfo; -- -- nl_msg = nlmsg_alloc(); -- if (!nl_msg) -- goto err_exit; -- ifinfo.ifi_index = ifindex; -- ifinfo.ifi_family = AF_UNSPEC; -- if (nlmsg_append(nl_msg, &ifinfo, sizeof ifinfo, NLMSG_ALIGNTO) < 0) -- goto err_exit; -- if (addmacs(nl_msg, vdp)) -- goto err_exit; -- if (addvfs(nl_msg, vdp, cmd)) -- goto err_exit; -- /* -- * Fill the netlink message header -- */ -- nlh = nlmsg_hdr(nl_msg); -- nlh->nlmsg_type = RTM_SETLINK; -- nlh->nlmsg_pid = getpid(); -- nlh->nlmsg_flags = NLM_F_REQUEST; -- if (len < nlh->nlmsg_len) -- goto err_exit; -- memcpy(buf, nlh, nlh->nlmsg_len); -- nlmsg_free(nl_msg); -- return 0; -- --err_exit: -- if (nl_msg) -- nlmsg_free(nl_msg); -- fprintf(stderr, "%s: can not build netlink message\n", progname); -- return -ENOMEM; --} -- - /* - * Send a netlink message to lldpad. Its a SETLINK message to trigger an - * action. LLDPAD responds with an error netlink message indicating if the - * profile was accepted. - * LLDPAD sends negative numbers as error indicators. - */ --static int lldp_send(struct command *cp, struct vdpdata *vdp) -+static int lldp_send(struct vdpnl_vsi *vsi, int waittime, int *ack) - { -- unsigned char sndbuf[1024]; -- struct iovec iov; -- struct msghdr msg; -- struct sockaddr_nl d_nladdr; -- struct nlmsghdr *nlh = (struct nlmsghdr *)sndbuf; -- int rc, vsiok = 0; -+ unsigned char msgbuf[2 * 1024]; -+ struct iovec iov = { -+ .iov_base = msgbuf, -+ .iov_len = sizeof(msgbuf), -+ }; -+ struct sockaddr_nl dest_addr = { -+ .nl_family = AF_NETLINK, -+ .nl_groups = 0, -+ .nl_pid = lldpad /* Target PID */ -+ }; -+ struct msghdr msg = { -+ .msg_name = &dest_addr, -+ .msg_namelen = sizeof(dest_addr), -+ .msg_iov = &iov, -+ .msg_iovlen = 1, -+ .msg_controllen = 0, -+ .msg_control = 0 -+ }; -+ struct nlmsghdr *nlh = (struct nlmsghdr *)msgbuf; -+ int rc; - -- memset(&d_nladdr, 0, sizeof d_nladdr); -- d_nladdr.nl_family = AF_NETLINK; -- d_nladdr.nl_pid = lldpad; /* Target PID */ -+ memset(msgbuf, 0, sizeof msgbuf); -+ rc = vdpnl_request_build(vsi, msgbuf, sizeof(msgbuf)); -+ if (rc < 0) { -+ fprintf(stderr, "%s: can not build netlink msg (ver %d): %d\n", -+ progname, vsi->nl_version, rc); -+ return rc; -+ } - -- memset(sndbuf, 0, sizeof sndbuf); -- rc = buildmsg(sndbuf, sizeof sndbuf, cp->cmd, vdp); -- if (rc) -- return -ENOMEM; -- iov.iov_base = (void *)nlh; -- iov.iov_len = nlh->nlmsg_len; -- -- /* Msg */ -- memset(&msg, 0, sizeof msg); -- msg.msg_name = (void *)&d_nladdr; -- msg.msg_namelen = sizeof d_nladdr; -- msg.msg_iov = &iov; -- msg.msg_iovlen = 1; -+ iov.iov_len = nlh->nlmsg_len; /* Set msg length */ - rc = sendmsg(my_sock, &msg, 0); -- if (rc < 0) -+ if (rc < 0){ - perror(progname); -- else { -- if (verbose) -- printf("%s send message to %d --> rc:%d\n", progname, -- lldpad, rc); -- rc = waitmsg(cp, &vsiok); -- if (rc > 0) -- rc = vsiok; -- else if (rc == 0) /* Time out */ -- rc = -1; -+ return rc; - } -+ if (verbose) -+ printf("%s send message to %d --> rc:%d\n", progname, lldpad, -+ rc); -+ rc = lldp_waitmsg(waittime, msgbuf, sizeof(msgbuf)); -+ if (rc > 0) -+ rc = check_sendack(nlh, ack); -+ else if (rc == 0) /* Time out */ -+ rc = -1; - return rc; - } - -+static unsigned char cvt_request(unsigned char cmd) -+{ -+ switch (cmd) { -+ case CMD_ASSOC: -+ return PORT_REQUEST_ASSOCIATE; -+ case CMD_DEASSOC: -+ return PORT_REQUEST_DISASSOCIATE; -+ case CMD_PREASSOC: -+ return PORT_REQUEST_PREASSOCIATE; -+ case CMD_RRPREASSOC: -+ return PORT_REQUEST_PREASSOCIATE_RR; -+ } -+ return PORT_REQUEST_PREASSOCIATE; -+} -+ -+/* -+ * Convert vdp to vsi structure. -+ */ -+static void vdp2vsi(struct vdpnl_vsi *p, unsigned char cmd, struct vdpdata *vdp) -+{ -+ int i; -+ static unsigned long nlseq; -+ struct vdpnl_mac *mac = p->maclist; -+ -+ strncpy(p->ifname, ifname, sizeof(p->ifname) - 1); -+ p->ifindex = ifindex; -+ p->vf = PORT_SELF_VF; -+ p->nl_version = vdp->nlmsg_v; -+ p->request = cvt_request(cmd); -+ p->req_seq = ++nlseq; -+ p->vsi_typeversion = vdp->typeidver; -+ p->vsi_typeid = vdp->typeid; -+ p->vsi_mgrid = vdp->mgrid; -+ p->hints = vdp->hints; -+ p->vsi_idfmt = VDP22_ID_UUID; -+ memcpy(p->vsi_uuid, vdp->uuid, sizeof(p->vsi_uuid)); -+ memcpy(p->vsi_mgrid2, vdp->mgrid2, sizeof(p->vsi_mgrid2)); -+ p->filter_fmt = vdp->fif; -+ for (i = 0; i < p->macsz; ++ i, ++mac) { -+ mac->vlan = vdp->addr[i].vlanid; -+ mac->gpid = vdp->addr[i].gpid; -+ memcpy(mac->mac, vdp->addr[i].mac, sizeof(mac->mac)); -+ } -+} -+ -+static void clear_vsi(struct vdpnl_vsi *vsi, struct vdpnl_mac *macp, size_t sz) -+{ -+ memset(vsi, 0, sizeof(*vsi)); -+ memset(macp, 0, sizeof(*macp) * sz); -+ vsi->macsz = sz; -+ vsi->maclist = macp; -+} -+ -+/* -+ * Convey a message to lldpad. -+ * -+ * Return -+ * 1 for response from lldpad GETLINK command -+ * 0 for error response as sendack from lldpad (in cp->rc) -+ * -1 for system error (in cp->sys_rc) -+ */ -+static void cmd_lldp(struct command *cp, struct vdpdata *vdp) -+{ -+ int lldpad_cmdack; -+ struct vdpnl_mac mac[vdp->pairs]; -+ struct vdpnl_vsi vsi; -+ -+ /* Send command */ -+ clear_vsi(&vsi, mac, vdp->pairs); -+ vdp2vsi(&vsi, cp->cmd, vdp); -+ cp->rc = 0; -+ cp->sys_rc = lldp_send(&vsi, cp->waittime, &lldpad_cmdack); -+ if (cp->sys_rc < 0) -+ return; -+ cp->rc = lldpad_cmdack; -+ if (cp->rc) -+ return; -+ /* Receive reply */ -+ clear_vsi(&vsi, mac, vdp->pairs); -+ memcpy(vsi.vsi_uuid, vdp->uuid, sizeof(vsi.vsi_uuid)); -+ if (lldp_recv(cp, &vsi) == 1) { -+ if (vsi.macsz) -+ cp->rc = compare_vsi(&vsi, vdp); -+ } -+} -+ - /* - * Open netlink socket to talk to lldpad daemon. - */ -@@ -689,13 +1380,14 @@ static void lldpad_pid(void) - static unsigned long getnumber(char *key, char *word, char stopchar, int *ec) - { - char *endp; -- unsigned long no = strtoul(word, &endp, 0); -+ unsigned long no; - - if (word == 0 || *word == '\0') { - fprintf(stderr, "key %s has missing number\n", key); - *ec = 1; - return 0; - } -+ no = strtoul(word, &endp, 0); - #ifdef MYDEBUG - printf("%s:stopchar:%c endp:%c\n", __func__, stopchar, *endp); - #endif -@@ -759,37 +1451,78 @@ static struct vdpdata *nextfree() - - static int check_map(char *value, struct vdpdata *profile) - { -- char *delim = strchr(value, '-'); -- unsigned long vlan; -- int i, ec, x[ETH_ALEN]; -+ char *delim2 = 0, *slash, *delim = strchr(value, '-'); -+ unsigned long vlan, newvlan = 0, gpid = 0; -+ int fif, i, ec, x[ETH_ALEN]; -+ int have_mac = 1, have_gpid = 1; - -- if (!delim) { -- fprintf(stderr, "%s invalid map format %s\n", progname, value); -- return -1; -+ if (!delim) -+ have_gpid = have_mac = 0; -+ else { -+ *delim = '\0'; -+ delim2 = strchr(delim + 1, '-'); -+ if (!delim2) -+ have_gpid = 0; -+ else { -+ *delim2 = '\0'; -+ if (delim + 1 == delim2) /* -- and no mac */ -+ have_mac = 0; -+ } - } -- vlan = getnumber("map", value, '-', &ec); -+ memset(x, 0, sizeof(x)); -+ slash = strchr(value, '/'); -+ if (slash) { /* Expect replacement vid incl. changed QoS */ -+ *slash = '\0'; -+ newvlan = getnumber("map", slash + 1, '\0', &ec); -+ if (ec) { -+ fprintf(stderr, "%s invalid new vlanid %s\n", progname, -+ value); -+ return -1; -+ } -+ if (newvlan >= 0x10000) { -+ fprintf(stderr, "%s new vlanid %#lx too high\n", -+ progname, newvlan); -+ return -1; -+ } -+ profile->nlmsg_v = vdpnl_nlf2; -+ } -+ vlan = getnumber("map", value, '\0', &ec); - if (ec) { - fprintf(stderr, "%s invalid vlanid %s\n", progname, value); - return -1; - } -- if (vlan >= 4095) { -+ if (vlan >= 0x10000) { - fprintf(stderr, "%s vlanid %ld too high\n", progname, vlan); - return -1; - } -- ++delim; -- ec = sscanf(delim, "%02x:%02x:%02x:%02x:%02x:%02x", &x[0], &x[1], -- &x[2], &x[3], &x[4], &x[5]); -- if (ec != ETH_ALEN) { -- fprintf(stderr, "%s mac %s invalid\n", progname, delim); -- return -1; -+ fif = VDP22_FFMT_VID; -+ if (have_mac) { -+ ec = sscanf(delim + 1, "%02x:%02x:%02x:%02x:%02x:%02x", &x[0], -+ &x[1], &x[2], &x[3], &x[4], &x[5]); -+ if (ec != ETH_ALEN) { -+ fprintf(stderr, "%s mac %s invalid\n", progname, delim); -+ return -1; -+ } -+ /* Check for last character */ -+ delim = strrchr(delim + 1, ':') + 2; -+ if (*delim && (strchr("0123456789abcdefABCDEF", *delim) == 0 -+ || *(delim + 1) != '\0')) { -+ fprintf(stderr, "%s last mac part %s invalid\n", -+ progname, delim); -+ return -1; -+ } -+ fif = VDP22_FFMT_MACVID; - } -- /* Check for last character */ -- delim = strrchr(value, ':') + 2; -- if (*delim && (strchr("0123456789abcdefABCDEF", *delim) == 0 -- || *(delim + 1) != '\0')) { -- fprintf(stderr, "%s last mac part %s invalid\n", progname, -- delim); -- return -1; -+ /* Check for optional group identifier */ -+ if (have_gpid && *(delim2 + 1)) { -+ gpid = getnumber("group", delim2 + 1, '\0', &ec); -+ if (ec) { -+ fprintf(stderr, "%s invalid groupid %s\n", progname, -+ delim2 + 1); -+ return -1; -+ } -+ fif += 2; -+ profile->nlmsg_v = vdpnl_nlf2; - } - #ifdef MYDEBUG - for (i = 0; i < ETH_ALEN; ++i) -@@ -797,18 +1530,34 @@ static int check_map(char *value, struct vdpdata *profile) - puts(""); - - #endif -+ if (profile->fif && profile->fif != fif) { -+ fprintf(stderr, "%s invalid filter info format %d use %d\n", -+ progname, fif, profile->fif); -+ return -1; -+ } -+ profile->fif = fif; - for (ec = 0; ec < profile->pairs; ++ec) { -- for (i = 0; i < ETH_ALEN; ++i) -- if (profile->addr[ec].mac[i] != x[i]) -- break; -- if (i == ETH_ALEN) { -- fprintf(stderr, "%s duplicate mac address %s\n", -- progname, value); -+ if (DIM(profile->addr) == i) { -+ fprintf(stderr, "%s too many filter addresses\n", -+ progname); - return -1; - } -+ if (profile->fif == VDP22_FFMT_MACVID -+ || profile->fif == VDP22_FFMT_GROUPMACVID) { -+ for (i = 0; i < ETH_ALEN; ++i) -+ if (profile->addr[ec].mac[i] != x[i]) -+ break; -+ if (i == ETH_ALEN) { -+ fprintf(stderr, "%s duplicate mac address %s\n", -+ progname, value); -+ return -1; -+ } -+ } - } - ec = profile->pairs++; - profile->addr[ec].vlanid = vlan; -+ profile->addr[ec].newvid = newvlan; -+ profile->addr[ec].gpid = gpid; - for (i = 0; i < ETH_ALEN; ++i) - profile->addr[ec].mac[i] = x[i]; - profile->modified |= 1 << f_map; -@@ -818,7 +1567,7 @@ static int check_map(char *value, struct vdpdata *profile) - static int check_uuid(char *value, struct vdpdata *profile) - { - unsigned int rc; -- unsigned int p[UUIDLEN]; -+ unsigned int p[PORT_UUID_MAX]; - - rc = sscanf(value, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x-%02x%02x%02x%02x%02x%02x", -@@ -828,11 +1577,11 @@ static int check_uuid(char *value, struct vdpdata *profile) - int i; - - printf("cc=%d\n", rc); -- for (i = 0; i < UUIDLEN; ++i) -+ for (i = 0; i < PORT_UUID_MAX; ++i) - printf("p[%d]=%#x ", i, p[i]); - puts(""); - #endif -- if (rc != UUIDLEN) { -+ if (rc != PORT_UUID_MAX) { - fprintf(stderr, "%s invalid uuid %s\n", progname, value); - return -1; - } -@@ -858,7 +1607,7 @@ static int check_typeid(char *value, struct vdpdata *profile) - progname, no); - } - #ifdef MYDEBUG -- printf("%s:typeid:%d ec:%d\n", __func__, profile->mgrid, ec); -+ printf("%s:typeid:%d ec:%d\n", __func__, profile->typeid, ec); - #endif - } - return ec; -@@ -880,7 +1629,8 @@ static int check_typeidversion(char *value, struct vdpdata *profile) - progname, no); - } - #ifdef MYDEBUG -- printf("%s:typeidver:%d ec:%d\n", __func__, profile->mgrid, ec); -+ printf("%s:typeidver:%d ec:%d\n", __func__, profile->typeidver, -+ ec); - #endif - } - return ec; -@@ -891,11 +1641,17 @@ static int check_mgrid(char *value, struct vdpdata *profile) - unsigned long no; - int ec; - -+ if (profile->nlmsg_v == vdpnl_nlf2) { -+ fprintf(stderr, "%s: mgrid and 2mgrid specified\n", progname); -+ return -1; -+ } - no = getnumber("mgrid", value, '\0', &ec); - if (!ec) { -- if (no <= 255) { -+ if (no <= 255 && no > 0) { -+ profile->nlmsg_v = vdpnl_nlf1; - profile->mgrid = no; - profile->modified |= 1 << f_mgrid; -+ memset(profile->mgrid2, 0, sizeof(profile->mgrid2)); - } else { - ec = -1; - fprintf(stderr, "%s: invalid mgrid %ld\n", progname, -@@ -908,6 +1664,44 @@ static int check_mgrid(char *value, struct vdpdata *profile) - return ec; - } - -+static int check_2mgrid(char *value, struct vdpdata *profile) -+{ -+ if (profile->nlmsg_v == vdpnl_nlf1) { -+ fprintf(stderr, "%s: mgrid and 2mgrid specified\n", progname); -+ return -1; -+ } -+ memcpy(profile->mgrid2, value, sizeof(profile->mgrid2) - 1); -+ profile->mgrid2[sizeof(profile->mgrid2) - 1] = '\0'; -+ profile->mgrid = 0; -+ profile->modified |= 1 << f_mgrid; -+ profile->nlmsg_v = vdpnl_nlf2; -+ return 0; -+} -+ -+static int check_hints(char *value, struct vdpdata *profile) -+{ -+ int rc = 0; -+ -+ if(!strcmp(value, "to")) { -+ profile->hints = VDP22_MIGTO; -+ profile->modified |= 1 << f_hints; -+ profile->nlmsg_v = vdpnl_nlf2; -+ } else if(!strcmp(value, "from")) { -+ profile->hints = VDP22_MIGFROM; -+ profile->modified |= 1 << f_hints; -+ profile->nlmsg_v = vdpnl_nlf2; -+ } else if(!strcmp(value, "none")) { -+ profile->hints = 0; -+ profile->modified |= 1 << f_hints; -+ profile->nlmsg_v = vdpnl_nlf2; -+ } else { -+ fprintf(stderr, "%s: invalid hints %s\n", progname, value); -+ rc = -1; -+ } -+ return rc; -+} -+ -+ - /* - * Return true if the character is valid for a key - */ -@@ -956,7 +1750,9 @@ static char *keytable[] = { - "typeidver", - "typeid", - "uuid", -- "name" -+ "name", -+ "2mgrid", -+ "hints" - }; - - static int findkeyword(char *word) -@@ -995,6 +1791,12 @@ static int checkword(char *word, char *value, struct vdpdata *profile) - case 5: - rc = check_name(value, profile); - break; -+ case 6: -+ rc = check_2mgrid(value, profile); -+ break; -+ case 7: -+ rc = check_hints(value, profile); -+ break; - } - #ifdef MYDEBUG - printf("%s word:%s value:%s rc:%d\n", __func__, word, value, rc); -@@ -1034,14 +1836,22 @@ static int has_key(struct vdpdata *found) - static void print_pairs(struct vdpdata *found) - { - int i; -- char buf[32]; - - for (i = 0; i < found->pairs; ++i) { -- unsigned char *xp = found->addr[i].mac; -+ printf("\t%hu", found->addr[i].vlanid); -+ if (found->addr[i].newvid) -+ printf("/%hu", found->addr[i].newvid); -+ if (found->fif == VDP22_FFMT_MACVID || -+ found->fif == VDP22_FFMT_GROUPMACVID) { -+ unsigned char *xp = found->addr[i].mac; - -- sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", -- xp[0], xp[1], xp[2], xp[3], xp[4], xp[5]); -- printf("\t%hd %s\n", found->addr[i].vlanid, buf); -+ printf(" %02x:%02x:%02x:%02x:%02x:%02x", -+ xp[0], xp[1], xp[2], xp[3], xp[4], xp[5]); -+ } -+ if (found->fif == VDP22_FFMT_GROUPVID || -+ found->fif == VDP22_FFMT_GROUPMACVID) -+ printf(" %ld", found->addr[i].gpid); -+ printf("\n"); - } - } - -@@ -1049,8 +1859,16 @@ static void print_profile(struct vdpdata *found) - { - char uuid[64]; - -- printf("key:%s mgrid:%d typeid:%#x typeidver:%d\n", -- found->key, found->mgrid, found->typeid, found->typeidver); -+ if (found->mgrid) -+ sprintf(uuid, "%d", found->mgrid); -+ else -+ strcpy(uuid, (char *)found->mgrid2); -+ printf("key:%s version:%d fif:%d mgrid:%s typeid:%#x typeidver:%d", -+ found->key, found->nlmsg_v, found->fif, uuid, found->typeid, -+ found->typeidver); -+ if (found->hints) -+ printf(" hints:%s", found->hints == VDP22_MIGTO ? "to" : "from"); -+ printf("\n"); - uuid2buf(found->uuid, uuid); - printf("\tuuid:%s\n", uuid); - if (found->pairs) -@@ -1063,17 +1881,23 @@ static int change_profile(struct vdpdata *change, struct vdpdata *alter) - printf("%s alter->modified:%#x\n", __func__, alter->modified); - #endif - if ((alter->modified & (1 << f_map))) { -+ change->fif = alter->fif; - change->pairs = alter->pairs; - memcpy(change->addr, alter->addr, sizeof alter->addr); - } -- if ((alter->modified & (1 << f_mgrid))) -+ if ((alter->modified & (1 << f_mgrid))) { - change->mgrid = alter->mgrid; -+ memcpy(change->mgrid2, alter->mgrid2, sizeof(change->mgrid2)); -+ } - if ((alter->modified & (1 << f_typeid))) - change->typeid = alter->typeid; - if ((alter->modified & (1 << f_typeidver))) - change->typeidver = alter->typeidver; - if ((alter->modified & (1 << f_uuid))) - memcpy(change->uuid, alter->uuid, sizeof change->uuid); -+ if ((alter->modified & (1 << f_hints))) -+ change->hints = alter->hints; -+ change->nlmsg_v = alter->nlmsg_v; - return 0; - } - -@@ -1094,7 +1918,7 @@ static void show_profiles(char *thisone) - - /* - * Parse the profile string of the form -- * key=###,mgrid=###,typeid=###,typeidver=###,uuid=###,mac=xxx,vlan=xxx{1,10} -+ * key=###,mgrid=###|2mgrid=xxx,typeid=###,typeidver=###,uuid=xxx,map=xxx{1,10} - */ - static int parse_profile(char *profile, struct vdpdata *target) - { -@@ -1158,20 +1982,34 @@ static void find_field(unsigned char mode, char *buf) - strcat(buf, ","); - strcat(buf, "uuid"); - } -+ if ((mode & (1 << f_hints)) == 0) { -+ if (comma) -+ strcat(buf, ","); -+ strcat(buf, "hints"); -+ } - } - --static void isvalid_profile(struct vdpdata *vdp) -+static int isvalid_profile(struct vdpdata *vdp) - { - char buf[64]; - unsigned char mode = 1 << f_map | 1 << f_mgrid | -- 1 << f_typeid | 1 << f_typeidver | 1 << f_uuid; -+ 1 << f_typeid | 1 << f_typeidver | 1 << f_uuid; -+ unsigned char optmode = 1 << f_hints; - -- if (vdp->modified != mode) { -+ if ((vdp->modified & ~optmode) != mode) { - find_field(vdp->modified, buf); - fprintf(stderr, "%s key %s misses profile fields %s\n", - progname, vdp->key, buf); - memset(vdp->key, 0, sizeof vdp->key); -+ return -1; - } -+ if (vdp->nlmsg_v != vdpnl_nlf2 && vdp->nlmsg_v != vdpnl_nlf1) { -+ fprintf(stderr, "%s key %s has wrong netlink msg format\n", -+ progname, vdp->key); -+ memset(vdp->key, 0, sizeof vdp->key); -+ return -1; -+ } -+ return 0; - } - - static int make_profiles(char *profile, char *newkey) -@@ -1199,16 +2037,22 @@ static int make_profiles(char *profile, char *newkey) - progname, nextone.key); - return -1; - } -+ if (!strcmp(newkey, found->key) || findkey(newkey)) { -+ fprintf(stderr, "%s target key %s already exits\n", -+ progname, newkey); -+ return -1; -+ } - if (!(vdp = nextfree())) { - fprintf(stderr, "%s too many profiles\n", progname); - return -1; - } - *vdp = *found; - strncpy(vdp->key, newkey, sizeof vdp->key); -+ if (!nextone.nlmsg_v) /* Test for netlink format */ -+ nextone.nlmsg_v = vdp->nlmsg_v; - change_profile(vdp, &nextone); - } -- isvalid_profile(vdp); -- return 0; -+ return isvalid_profile(vdp); - } - - static int del_profiles(char *name) -@@ -1233,7 +2077,7 @@ static int copy_profiles(char *profile) - fprintf(stderr, "%s missing key new=name\n", progname); - return -1; - } -- newkey = profile + 4; -+ newkey = profile + strlen(COPY_OP); - newprofile = strchr(newkey, ','); - if (!newprofile) { - fprintf(stderr, "%s invalid copy command\n", progname); -@@ -1500,6 +2344,11 @@ static int cmd_checkrc(struct command *cmdp) - { - int i; - -+ if (cmdp->sys_rc) { -+ printf("FAILURE sys_rc:%d ", cmdp->sys_rc); -+ show_command(cmdp, 1); -+ return -1; -+ } - for (i = 0; i < cmdp->no_err; ++i) - if (cmdp->rc == cmdp->errors[i]) { - if (verbose) -@@ -1542,40 +2391,282 @@ static void cmd_sleep(struct command *cmdp) - cmdp->rc |= sleep(cmdp->waittime); - } - --static int rc_ok(struct command *cmdp) -+/* -+ * Code to use the command line interface via clif_xxx functions. -+ */ -+static int tool_use; -+static struct clif *tool_conn; -+ -+static void tool_open() -+{ -+ tool_conn = clif_open(); -+ if (!tool_conn) { -+ fprintf(stderr, "%s can not open connection to LLDPAD\n", -+ progname); -+ exit(5); -+ } -+ if (clif_attach(tool_conn, "80c4")) { -+ fprintf(stderr, "%s can not attach to LLDPAD\n", -+ progname); -+ clif_close(tool_conn); -+ tool_conn = NULL; -+ exit(5); -+ } -+} -+ -+static void tool_close(void) -+{ -+ if (tool_conn) { -+ clif_detach(tool_conn); -+ clif_close(tool_conn); -+ tool_conn = NULL; -+ } -+} -+ -+/* -+ * Convert VSI command mode to string. -+ */ -+static unsigned int request2tlvid(unsigned char cmd) -+{ -+ switch (cmd) { -+ case CMD_ASSOC: -+ return VDP22_ASSOC; -+ case CMD_DEASSOC: -+ return VDP22_DEASSOC; -+ case CMD_PREASSOC: -+ return VDP22_PREASSOC; -+ case CMD_RRPREASSOC: -+ return VDP22_PREASSOC_WITH_RR; -+ } -+ return 0; -+} -+ -+static const char *request2str(unsigned char cmd) -+{ -+ switch (cmd) { -+ case CMD_ASSOC: -+ return "assoc"; -+ case CMD_DEASSOC: -+ return "deassoc"; -+ case CMD_PREASSOC: -+ return "preassoc"; -+ case CMD_RRPREASSOC: -+ return "preassoc-rr"; -+ } -+ return "unknown"; -+} -+ -+/* -+ * Convert hint bits to string. -+ */ -+static const char *hints2str(unsigned char hint) -+{ -+ switch (hint) { -+ case VDP22_MIGTO: -+ return "to"; -+ case VDP22_MIGFROM: -+ return "from"; -+ default: -+ return "none"; -+ } -+} -+ -+/* -+ * Create a command string understood by vdp22 module to forward it to -+ * the vdp22 module. -+ */ -+static size_t vdp2str(char *cmd, size_t cmd_len, char oper, struct vdpdata *vdp) - { - int i; -+ size_t len; -+ char uuidbuf[64], mgrid[64]; - -- for (i = 0; i < cmdp->no_err; ++i) -- if (cmdp->rc == cmdp->errors[i]) -- return 1; -+ uuid2buf(vdp->uuid, uuidbuf); -+ if (vdp->nlmsg_v == vdpnl_nlf1) -+ sprintf(mgrid, "%d", vdp->mgrid); -+ else -+ strcpy(mgrid, (char *)vdp->mgrid2); -+ snprintf(cmd, cmd_len, "%s,%s,%d,%d,%s,%s", -+ request2str(oper), mgrid, vdp->typeid, -+ vdp->typeidver, uuidbuf, hints2str(vdp->hints)); -+ -+ /* Add Filter information data */ -+ for (i = 0; i < vdp->pairs; ++i) { -+ len = strlen(cmd); -+ snprintf(cmd + len, cmd_len - len, ",%d", -+ vdp->addr[i].vlanid); -+ if (vdp->fif == VDP22_FFMT_MACVID || -+ vdp->fif == VDP22_FFMT_GROUPMACVID) { -+ len = strlen(cmd); -+ snprintf(cmd + len, cmd_len - len, -+ "-%02x:%02x:%02x:%02x:%02x:%02x", -+ vdp->addr[i].mac[0], vdp->addr[i].mac[1], -+ vdp->addr[i].mac[2], vdp->addr[i].mac[3], -+ vdp->addr[i].mac[4], vdp->addr[i].mac[5]); -+ } -+ if (vdp->fif == VDP22_FFMT_GROUPVID || -+ vdp->fif == VDP22_FFMT_GROUPMACVID) { -+ len = strlen(cmd); -+ snprintf(cmd + len, cmd_len - len, "-%ld", -+ vdp->addr[i].gpid); -+ } -+ } -+ return strlen(cmd); -+} -+ -+/* -+ * Convert ascii string to vdp. Return command. -+ */ -+static char *str2vdp(char *ok, struct vdpdata *p, int *response) -+{ -+ int i, ec; -+ char *token, *cmd = NULL; -+ -+ for (i = 0, token = strtok(ok, ","); token; -+ ++i, token = strtok(NULL, ",")) { -+ if (i == 0) -+ cmd = token; -+ if (i == 1) { -+ char *myend; -+ unsigned long x = strtol(token, &myend, 10); -+ -+ if (*myend || x > 255) -+ strcpy((char *)p->mgrid2, token); -+ else -+ p->mgrid = x; -+ } -+ if (i == 2) { -+ p->typeid = getnumber("typeid", token, '\0', &ec); -+ if (ec) -+ return NULL; -+ } -+ if (i == 3) { -+ p->typeidver = getnumber("typeidver", token, '\0', &ec); -+ if (ec) -+ return NULL; -+ } -+ if (i == 4 && check_uuid(token, p)) -+ return NULL; -+ /* Hints field contains response */ -+ if (i == 5) { -+ char *myend; -+ unsigned long x = strtol(token, &myend, 10); -+ -+ if (*myend) -+ return NULL; -+ *response = x; -+ } -+ if (i >= 6 && check_map(token, p)) -+ return NULL; -+ } -+ p->modified = 0; -+ return cmd; -+} -+ -+/* -+ * Test data of association. -+ */ -+static int check_vsi(struct vdpdata *p, struct vdpdata *back) -+{ -+ int i; -+ -+ if (p->mgrid && p->mgrid != back->mgrid) { -+ if (verbose >= 2) -+ printf("invalid mgrid identifer %d (expected %d)\n", -+ back->mgrid, p->mgrid); -+ return -EINVAL; -+ } -+ if (p->pairs != back->pairs) { -+ if (verbose >= 2) -+ printf("invalid fid pairs %d (expected %d)\n", -+ back->pairs, p->pairs); -+ return -ENFILE; -+ } -+ for (i = 0; i < p->pairs; ++i) { -+ if (p->addr[i].newvid) { -+ if (p->addr[i].newvid != back->addr[i].vlanid) { -+ if (verbose >= 2) { -+ printf("invalid vlanid[%d]:%#hx " -+ "(expected %#hx)\n", -+ i, back->addr[i].vlanid, -+ p->addr[i].newvid); -+ return -EMFILE; -+ } -+ } -+ } else if (p->addr[i].vlanid) { -+ if (p->addr[i].vlanid != back->addr[i].vlanid) { -+ if (verbose >= 2) { -+ printf("unexpected vlanid[%d]:%#hx " -+ "(expected %#hx)\n", -+ i, back->addr[i].vlanid, -+ p->addr[i].vlanid); -+ return -ENOTTY; -+ } -+ } -+ } else { -+ printf("invalid vlanid input[%d]:%#hx " -+ "(expected %#hx)\n", -+ i, back->addr[i].vlanid, -+ p->addr[i].newvid); -+ return -ETXTBSY; -+ } -+ } - return 0; - } - -+static void tool_lldp(struct command *cmdp, struct vdpdata *vdp) -+{ -+ char cmd[MAX_CLIF_MSGBUF], ok[MAX_CLIF_MSGBUF]; -+ size_t ok_len = sizeof(ok); -+ struct vdpdata back; -+ -+ memset(&back, 0, sizeof(back)); -+ cmdp->sys_rc = cmdp->rc = 0; -+ vdp2str(cmd, sizeof(cmd), cmdp->cmd, vdp); -+ cmdp->rc = clif_vsiwait(tool_conn, ifname, request2tlvid(cmdp->cmd), -+ cmd, ok, &ok_len, cmdp->waittime); -+ if (!cmdp->rc) { -+ char *cmd = str2vdp(ok, &back, &cmdp->rc); -+ if (!cmd) -+ cmdp->rc = -EINVAL; -+ if (!strcmp(cmd, request2str(cmdp->cmd)) && !cmdp->rc) -+ cmdp->rc = check_vsi(vdp, &back); -+ } -+} -+ -+/* -+ * Return 0 with command executed as expected. -+ * Maybe with expected error. -+ */ - static void cmd_profile(struct command *cmdp) - { - struct vdpdata *vdp = findkey(cmdp->key); -- int got_ack = 0; -- unsigned int i; - - if (!vdp) { - cmdp->rc = ENFILE; - return; - } -- if ((cmdp->rc = lldp_send(cmdp, vdp)) >= 0) -- for (i = 0; got_ack == 0 && i < cmdp->repeats; ++i) { -- usleep(cmdp->delay * 1000); -- got_ack = lldp_ack(cmdp); -- if (got_ack < 0) { /* Error */ -- cmdp->rc = -1; -- break; -- } else if (got_ack > 0) { /* Got ack */ -- if (rc_ok(cmdp)) -- break; -- else -- got_ack = 0; -- } -- } -+ if (vdp->nlmsg_v == vdpnl_nlf2 || tool_use) -+ tool_lldp(cmdp, vdp); -+ else -+ cmd_lldp(cmdp, vdp); -+} -+ -+/* -+ * Wait for unsolicited messsage from lldpad vdp22 module. -+ */ -+static void tool_wait(struct command *cmdp) -+{ -+ char ok[MAX_CLIF_MSGBUF]; -+ size_t ok_len = sizeof(ok); -+ -+ cmdp->sys_rc = cmdp->rc = 0; -+ cmdp->rc = clif_vsievt(tool_conn, ok, &ok_len, cmdp->waittime); -+ if (cmdp->rc == -EAGAIN) /* No message received */ -+ cmdp->rc = 0; -+ else if (cmdp->rc == 0 && !strncmp(ok, "deassoc", strlen("deassoc"))) -+ /* Data received and dessaoc command */ -+ cmdp->rc = 1; - } - - static int runcmds() -@@ -1604,7 +2695,10 @@ static int runcmds() - cmd_echo(&cmds[i]); - break; - case CMD_GETMSG: -- lldp_wait(&cmds[i]); -+ if (tool_use) -+ tool_wait(&cmds[i]); -+ else -+ lldp_wait(&cmds[i]); - break; - } - rc = cmd_checkrc(&cmds[i]); -@@ -1614,6 +2708,29 @@ static int runcmds() - return rc; - } - -+/* -+ * Check for VSI draft 0.2 and draft 2.2 input format on one command line. -+ */ -+static void inputformats(void) -+{ -+ int f1 = 0, f2 = 0; -+ unsigned int i; -+ -+ for (i = 0; i < DIM(cmds) && i < cmdidx; ++i) { -+ if (vsidata[i].nlmsg_v == vdpnl_nlf1) -+ ++f1; -+ if (vsidata[i].nlmsg_v == vdpnl_nlf2) -+ ++f2; -+ } -+ if (f1 && f2) { -+ fprintf(stderr, "%s mixed input format of VSI draft 0.2" -+ " and draft 2.2 not supported\n", progname); -+ exit(1); -+ } -+ if (!f1) /* Draft 2,2 with clif only */ -+ tool_use = 1; -+} -+ - #include - - int main(int argc, char **argv) -@@ -1624,7 +2741,7 @@ int main(int argc, char **argv) - char *slash, mybuf[32]; - - progname = (slash = strrchr(argv[0], '/')) ? slash + 1 : argv[0]; -- while ((ch = getopt(argc, argv, ":A:C:D:F:S::a:d:e:E:g:p:r:s::i:v")) -+ while ((ch = getopt(argc, argv, ":A:C:D:F:S::a:d:e:E:g:p:r:s::i:vn")) - != EOF) - switch (ch) { - case '?': -@@ -1635,6 +2752,9 @@ int main(int argc, char **argv) - fprintf(stderr, "%s missing option argument for -%c\n", - progname, optopt); - exit(1); -+ case 'n': -+ tool_use = 1; -+ break; - case 'F': - read_profiles(optarg); - break; -@@ -1663,8 +2783,8 @@ int main(int argc, char **argv) - break; - case CMD_SLEEP: - if (!optarg) { -- optarg = mybuf, -- strncpy(mybuf, "w=1", sizeof mybuf); -+ optarg = mybuf; -+ strncpy(mybuf, "w=1", sizeof mybuf); - } - parse_cmd(ch, optarg); - break; -@@ -1683,6 +2803,7 @@ int main(int argc, char **argv) - for (; optind < argc; ++optind) - printf("%d %s\n", optind, argv[optind]); - #endif -+ inputformats(); - if (!needif) - exit(0); - if (!ifname) { -@@ -1690,14 +2811,27 @@ int main(int argc, char **argv) - progname); - exit(2); - } -- lldpad_pid(); -- if ((my_sock = open_socket(NETLINK_ROUTE)) < 0) -- exit(4); -- if (verbose >= 2) -+ if (tool_use) -+ tool_open(); -+ else { -+ lldpad_pid(); -+ if ((my_sock = open_socket(NETLINK_ROUTE)) < 0) -+ exit(4); -+ } -+ if (verbose >= 2) { -+ printf("\nTests to run:\n"); - show_commands(0); -+ } -+ if (verbose >= 2) -+ printf("\nExecution:\n"); - rc = runcmds(); -- close(my_sock); -- if (verbose >= 2) -+ if (tool_use) -+ tool_close(); -+ else -+ close(my_sock); -+ if (verbose >= 2) { -+ printf("\nSummary:\n"); - show_commands(1); -+ } - return rc; - } -diff --git a/tlv_dcbx.c b/tlv_dcbx.c -index 14eab58..bae9b51 100644 ---- a/tlv_dcbx.c -+++ b/tlv_dcbx.c -@@ -107,7 +107,7 @@ struct unpacked_tlv *bld_dcbx1_tlv(struct dcbx_tlvs *dcbx) - struct unpacked_tlv *tlv = create_tlv(); - struct packed_tlv *ptlv = NULL; - u8 oui[DCB_OUI_LEN] = INIT_DCB_OUI; -- u8 subtype = dcbx_subtype1; -+ u8 subtype = DCBX_SUBTYPE1; - u32 offset = 0; - - if (!tlv) -@@ -211,7 +211,7 @@ struct unpacked_tlv *bld_dcbx2_tlv(struct dcbx_tlvs *dcbx) - struct unpacked_tlv *tlv = create_tlv(); - struct packed_tlv *ptlv = NULL; - u8 oui[DCB_OUI_LEN] = INIT_DCB_OUI; -- u8 subtype = dcbx_subtype2; -+ u8 subtype = DCBX_SUBTYPE2; - u32 offset = 0; - - if (!tlv) -@@ -448,14 +448,14 @@ struct unpacked_tlv *bld_dcbx2_pg_tlv(struct dcbx_tlvs *dcbx, bool *success) - - for (j=0,k=0 ; k < MAX_BANDWIDTH_GROUPS; j++, k=k+2) { - tmpbyte = 0; -- if (pg_cfg.tx.up[k].strict_priority == dcb_link) -+ if (pg_cfg.tx.up[k].strict_priority == DCB_LINK) - tmpbyte = 0xf; - else - tmpbyte = pg_cfg.tx.up[k].pgid & 0xf; - - tmpbyte <<= 4; - -- if (pg_cfg.tx.up[k+1].strict_priority == dcb_link) -+ if (pg_cfg.tx.up[k+1].strict_priority == DCB_LINK) - tmpbyte |= 0xf; - else - tmpbyte |= (pg_cfg.tx.up[k+1].pgid & 0xf); -@@ -873,7 +873,7 @@ bool unpack_dcbx1_tlvs(struct port *port, struct lldp_agent *agent, - break; - case DCB_PRIORITY_GROUPS_TLV: - /* store if subtype 2 is not present */ -- if (agent->rx.dcbx_st == dcbx_subtype1) { -+ if (agent->rx.dcbx_st == DCBX_SUBTYPE1) { - if (tlvs->manifest->dcbx_pg == NULL) { - tlvs->dcbdu |= RCVD_DCBX_TLV_PG; - tlvs->manifest->dcbx_pg = dcbtlv; -@@ -888,7 +888,7 @@ bool unpack_dcbx1_tlvs(struct port *port, struct lldp_agent *agent, - break; - case DCB_PRIORITY_FLOW_CONTROL_TLV: - /* store if subtype 2 is not present */ -- if (agent->rx.dcbx_st == dcbx_subtype1) { -+ if (agent->rx.dcbx_st == DCBX_SUBTYPE1) { - if (tlvs->manifest->dcbx_pfc == NULL) { - tlvs->dcbdu |= RCVD_DCBX_TLV_PFC; - tlvs->manifest->dcbx_pfc = dcbtlv; -@@ -903,7 +903,7 @@ bool unpack_dcbx1_tlvs(struct port *port, struct lldp_agent *agent, - break; - case DCB_APPLICATION_TLV: - /* store if subtype 2 is not present */ -- if ((agent->rx.dcbx_st == dcbx_subtype1) && -+ if ((agent->rx.dcbx_st == DCBX_SUBTYPE1) && - (dcbtlv->info[DCBX_HDR_SUB_TYPE_OFFSET] - == APP_FCOE_STYPE)) { - if (tlvs->manifest->dcbx_app == NULL) { -@@ -1213,7 +1213,7 @@ bool process_dcbx_pg_tlv(struct port *port, struct lldp_agent *agent) - if (agent == NULL) - return false; - -- if (agent->rx.dcbx_st == dcbx_subtype2) { -+ if (agent->rx.dcbx_st == DCBX_SUBTYPE2) { - if (tlvs->manifest->dcbx_pg->length != DCBX2_PG_LEN) { - LLDPAD_DBG("process_dcbx2_pg_tlv: ERROR - len\n"); - return(false); -@@ -1258,7 +1258,7 @@ bool process_dcbx_pg_tlv(struct port *port, struct lldp_agent *agent) - peer_pg.protocol.Error_Flag |= DUP_DCBX_TLV_PG; - } - -- if (agent->rx.dcbx_st == dcbx_subtype2) { -+ if (agent->rx.dcbx_st == DCBX_SUBTYPE2) { - memset(used, false, sizeof(used)); - for (j=0,k=0 ; k < MAX_BANDWIDTH_GROUPS; j++, k=k+2) { - u8 tmpbyte = tlvs->manifest->dcbx_pg->info -@@ -1268,14 +1268,14 @@ bool process_dcbx_pg_tlv(struct port *port, struct lldp_agent *agent) - peer_pg.tx.up[k].pgid = (tmpbyte >> 4) & 0xf; - peer_pg.rx.up[k].pgid = (tmpbyte >> 4) & 0xf; - if (peer_pg.tx.up[k+1].pgid == LINK_STRICT_PGID) { -- peer_pg.tx.up[k+1].strict_priority = dcb_link; -- peer_pg.rx.up[k+1].strict_priority = dcb_link; -+ peer_pg.tx.up[k+1].strict_priority = DCB_LINK; -+ peer_pg.rx.up[k+1].strict_priority = DCB_LINK; - } else { - used[peer_pg.tx.up[k+1].pgid] = true; - } - if (peer_pg.tx.up[k].pgid == LINK_STRICT_PGID) { -- peer_pg.tx.up[k].strict_priority = dcb_link; -- peer_pg.rx.up[k].strict_priority = dcb_link; -+ peer_pg.tx.up[k].strict_priority = DCB_LINK; -+ peer_pg.rx.up[k].strict_priority = DCB_LINK; - } else { - used[peer_pg.tx.up[k].pgid] = true; - } -@@ -1360,7 +1360,7 @@ bool process_dcbx_pfc_tlv(struct port *port, struct lldp_agent *agent) - if (agent == NULL) - return false; - -- if (agent->rx.dcbx_st == dcbx_subtype2) { -+ if (agent->rx.dcbx_st == DCBX_SUBTYPE2) { - if (tlvs->manifest->dcbx_pfc->length != DCBX2_PFC_LEN) { - LLDPAD_DBG("process_dcbx2_pfc_tlv: ERROR - len\n"); - return(false); -@@ -1410,7 +1410,7 @@ bool process_dcbx_pfc_tlv(struct port *port, struct lldp_agent *agent) - temp = tlvs->manifest->dcbx_pfc->info[DCBX_PFC_MAP_OFFSET]; - peer_pfc.admin[i] = (pfc_type)((temp >> i) & BIT0); - } -- if (agent->rx.dcbx_st == dcbx_subtype2) { -+ if (agent->rx.dcbx_st == DCBX_SUBTYPE2) { - peer_pfc.num_tcs = tlvs->manifest->dcbx_pfc->info - [DCBX2_PFC__NUM_TC_OFFSET]; - } -@@ -1437,7 +1437,7 @@ bool process_dcbx_app_tlv(struct port *port, struct lldp_agent *agent) - return false; - - len = tlvs->manifest->dcbx_app->length; -- if (agent->rx.dcbx_st == dcbx_subtype2) { -+ if (agent->rx.dcbx_st == DCBX_SUBTYPE2) { - if (len < DCBX2_APP_LEN) { - LLDPAD_DBG("process_dcbx2_app_tlv: ERROR - len\n"); - return(false); -@@ -1481,7 +1481,7 @@ bool process_dcbx_app_tlv(struct port *port, struct lldp_agent *agent) - peer_app.protocol.Error_Flag |= DUP_DCBX_TLV_APP; - } - -- if (agent->rx.dcbx_st == dcbx_subtype2) { -+ if (agent->rx.dcbx_st == DCBX_SUBTYPE2) { - /* processs upper layer protocol IDs until we - * match Selector Field, FCoE or FIP ID and OUI */ - len -= DCBX2_APP_DATA_OFFSET; -@@ -1550,7 +1550,7 @@ bool process_dcbx_app_tlv(struct port *port, struct lldp_agent *agent) - put_peer_app(port->ifname, APP_ISCSI_STYPE, &peer_app); - if (!fip) - put_peer_app(port->ifname, APP_FIP_STYPE, &peer_app); -- } else if (agent->rx.dcbx_st == dcbx_subtype1) { -+ } else if (agent->rx.dcbx_st == DCBX_SUBTYPE1) { - sub_type = pBuf[DCBX_HDR_SUB_TYPE_OFFSET]; - len = tlvs->manifest->dcbx_app->length - - sizeof(struct dcbx_tlv_header); diff --git a/lldpad.spec b/lldpad.spec index 4c424b5..d4c6ab2 100644 --- a/lldpad.spec +++ b/lldpad.spec @@ -3,17 +3,40 @@ # https://fedoraproject.org/wiki/Packaging:Guidelines#Compiler_flags %global _hardened_build 1 -%global checkout 48a5f38 +%global checkout 986eb2e Name: lldpad -Version: 0.9.46 -Release: 8.git%{checkout}%{?dist} +Version: 1.0.1 +Release: 1.git%{checkout}%{?dist} Summary: Intel LLDP Agent Group: System Environment/Daemons License: GPLv2 URL: http://open-lldp.org/ Source0: %{name}-%{version}.tar.gz -Patch0: %{name}-%{version}-123-g48a5f38.patch +Patch1: open-lldp-v1.0.1-1-VDP-vdp22_cmds-retrieve-vsi-paramenter-data.patch +Patch2: open-lldp-v1.0.1-2-VDP-vdptool-first-version.patch +Patch3: open-lldp-v1.0.1-3-VDP-vdptool-test-cases-Some-test-cases-to-test-the-n.patch +Patch4: open-lldp-v1.0.1-4-VDP-Changes-to-make-the-interface-to-VDP22-in-lldpad.patch +Patch5: open-lldp-v1.0.1-5-VDP-Support-for-get-tlv-in-vdptool-and-VDP22.patch +Patch6: open-lldp-v1.0.1-6-VDP-Support-in-VDP22-for-correct-error-code-status-t.patch +Patch7: open-lldp-v1.0.1-7-VDP-Support-for-OUI-infrastructure-in-VDP22.patch +Patch8: open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch +Patch9: open-lldp-v1.0.1-9-VDP-Support-for-OUI-infrastructure-in-vdp22.patch +Patch10: open-lldp-v1.0.1-10-VDP-Support-for-OUI-infrastructure-in-vdp22.patch +Patch11: open-lldp-v1.0.1-11-VDP-Support-for-Cisco-specific-OUI-extensions-to-VDP.patch +Patch12: open-lldp-v1.0.1-12-VDP22-Fix-the-ack-timeout-handler-to-set-the-right-t.patch +Patch13: open-lldp-v1.0.1-13-VDP-Changes-in-OUI-infra-for-get-tlv.patch +Patch14: open-lldp-v1.0.1-14-VDP-Changes-in-Cisco-OUI-handlers-to-support-get-tlv.patch +Patch15: open-lldp-v1.0.1-15-VDP-Add-vdptool-man-page-to-Makefile.patch +Patch16: open-lldp-v1.0.1-16-VDP-Fixed-DBG-print-compile-errors-in-32-bit-systems.patch +Patch17: open-lldp-v1.0.1-17-lldp-automake-fixes-for-dist-distcheck.patch +Patch18: open-lldp-v1.0.1-18-enabled-test-tool-building-for-distcheck.patch +Patch19: open-lldp-v1.0.1-19-nltest-build-error.patch +Patch20: open-lldp-v1.0.1-20-lldp-automake-fix-drop-prefix-on-vdptool_LDADD.patch +Patch21: open-lldp-v1.0.1-21-lldpad-Fix-DCBX-event-generation-from-lldpad.patch +Patch22: open-lldp-v1.0.1-22-vdp-Fixed-the-memory-leak-for-modify-VSI-support-for.patch +Patch23: open-lldp-v1.0.1-23-lldp-make-TTL-TLV-configurable.patch +Patch24: open-lldp-v1.0.1-24-fix-build-warnings.patch BuildRequires: automake autoconf libtool BuildRequires: flex >= 2.5.33 @@ -44,8 +67,7 @@ The %{name}-devel package contains header files for developing applications that use %{name}. %prep -%setup -q -%patch0 -p1 +%autosetup -p1 %build ./bootstrap.sh @@ -79,6 +101,7 @@ rm -f %{buildroot}%{_libdir}/liblldp_clif.la %{_unitdir}/%{name}.socket %dir %{_sysconfdir}/bash_completion.d/ %{_sysconfdir}/bash_completion.d/* +%{_mandir}/man3/* %{_mandir}/man8/* %files devel @@ -87,6 +110,9 @@ rm -f %{buildroot}%{_libdir}/liblldp_clif.la %{_libdir}/liblldp_clif.so %changelog +* Wed Jun 17 2015 Chris Leech - 1.0.1-1.git986eb2e +- rebased to upstream v1.0.1-23-g986eb2e + * Thu Oct 23 2014 Chris Leech - 0.9.46-8.git48a5f38 - sync to upstream v0.9.46-123-g48a5f38 diff --git a/open-lldp-v1.0.1-1-VDP-vdp22_cmds-retrieve-vsi-paramenter-data.patch b/open-lldp-v1.0.1-1-VDP-vdp22_cmds-retrieve-vsi-paramenter-data.patch new file mode 100644 index 0000000..fb2968a --- /dev/null +++ b/open-lldp-v1.0.1-1-VDP-vdp22_cmds-retrieve-vsi-paramenter-data.patch @@ -0,0 +1,106 @@ +From dff810b2e546eb74e8b9cebb7185ca5bcb5ecc9d Mon Sep 17 00:00:00 2001 +From: Thomas Richter +Date: Wed, 21 Jan 2015 03:35:59 +0000 +Subject: [PATCH] VDP: vdp22_cmds retrieve vsi paramenter data + +This patch adds support for the retrieval of the +vsi parameter data to a command line client. + +Signed-off-by: Thomas Richter +Signed-off-by: John Fastabend +--- + include/qbg_vdpnl.h | 1 + + qbg/vdp22_cmds.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 64 insertions(+) + +diff --git a/include/qbg_vdpnl.h b/include/qbg_vdpnl.h +index 7b26bc7..510a20c 100644 +--- a/include/qbg_vdpnl.h ++++ b/include/qbg_vdpnl.h +@@ -78,4 +78,5 @@ int event_trigger(struct nlmsghdr *, pid_t); + int vdp_str2vdpnl(char *, struct vdpnl_vsi *, char *); + int vdp_vdpnl2str(struct vdpnl_vsi *, char *, size_t); + int vdp22_sendevent(struct vdpnl_vsi *); ++void vdp22_freemaclist(struct vdpnl_vsi *); + #endif +diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c +index a75c02d..f055441 100644 +--- a/qbg/vdp22_cmds.c ++++ b/qbg/vdp22_cmds.c +@@ -471,10 +471,73 @@ static int test_arg_vsi(struct cmd *cmd, UNUSED char *arg, char *argvalue, + return set_arg_vsi2(cmd, argvalue, true); + } + ++/* ++ * Concatenate all VSI information into one string. ++ * Return length of string in bytes. ++ */ ++static int catvsis(struct vdpnl_vsi *vsi, char *out, size_t out_len) ++{ ++ int rc, i; ++ size_t used = 0; ++ unsigned char wanted_req = vsi->request; ++ ++ for (i = 1; vdp22_status(i, vsi, 1) > 0; ++i) { ++ if (wanted_req != vsi->request) { ++ vdp22_freemaclist(vsi); ++ continue; ++ } ++ rc = vdp_vdpnl2str(vsi, out + used, out_len - used); ++ vdp22_freemaclist(vsi); ++ if (rc) { ++ strcat(out, ";"); ++ used = strlen(out); ++ } else ++ return 0; ++ } ++ return used; ++} ++ ++/* ++ * Return all VSIs on a particular interface into one string. ++ */ ++static int get_arg_vsi(struct cmd *cmd, char *arg, UNUSED char *argvalue, ++ char *obuf, int obuf_len) ++{ ++ cmd_status good_cmd = vdp22_cmdok(cmd, cmd_gettlv); ++ struct vdpnl_vsi vsi; ++ char vsi_str[MAX_CLIF_MSGBUF]; ++ int rc; ++ ++ if (good_cmd != cmd_success) ++ return good_cmd; ++ if (!port_find_by_ifindex(get_ifidx(cmd->ifname))) ++ return cmd_device_not_found; ++ good_cmd = ifok(cmd); ++ if (good_cmd != cmd_success) ++ return good_cmd; ++ ++ memset(obuf, 0, obuf_len); ++ memset(&vsi, 0, sizeof(vsi)); ++ vsi.request = cmd->tlvid; ++ strncpy(vsi.ifname, cmd->ifname, sizeof(vsi.ifname) - 1); ++ good_cmd = cmd_failed; ++ if (!catvsis(&vsi, vsi_str, sizeof(vsi_str))) ++ goto out; ++ rc = snprintf(obuf, obuf_len, "%02x%s%04x%s", ++ (unsigned int)strlen(arg), arg, (unsigned int)strlen(vsi_str), ++ vsi_str); ++ if (rc > 0 || rc < obuf_len) ++ good_cmd = cmd_success; ++out: ++ return good_cmd; ++} ++ ++ + static struct arg_handlers arg_handlers[] = { + { + .arg = ARG_VDP22_VSI, + .arg_class = TLV_ARG, ++ .handle_get = get_arg_vsi, + .handle_set = set_arg_vsi, + .handle_test = test_arg_vsi + }, +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-10-VDP-Support-for-OUI-infrastructure-in-vdp22.patch b/open-lldp-v1.0.1-10-VDP-Support-for-OUI-infrastructure-in-vdp22.patch new file mode 100644 index 0000000..9f8ab5e --- /dev/null +++ b/open-lldp-v1.0.1-10-VDP-Support-for-OUI-infrastructure-in-vdp22.patch @@ -0,0 +1,172 @@ +From 7289ac24898ae74a3a47fb4e4378d1535c21adba Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:39:47 +0000 +Subject: [PATCH] VDP: Support for OUI infrastructure in vdp22. + +This commit is a framework for supporting OUI fields +in VDP22. This specific patch adds helper functions +(functions exported by VDP to OUI code) to be called by OUI +specific handler code. + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + Makefile.am | 2 +- + include/qbg_utils.h | 1 + + include/qbg_vdp22_oui.h | 48 +++++++++++++++++++++++++++++++++++++ + qbg/vdp22_oui.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 113 insertions(+), 1 deletion(-) + create mode 100644 qbg/vdp22_oui.c + +diff --git a/Makefile.am b/Makefile.am +index 403088b..f63311c 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -70,7 +70,7 @@ include/lldp_evb22.h lldp_evb22.c lldp_evb22_cmds.c \ + include/qbg22.h include/qbg_ecp22.h qbg/ecp22.c \ + include/qbg_vdp22.h qbg/vdp22.c qbg/vdpnl.c qbg/vdp22sm.c qbg/vdp22br.c \ + include/qbg_vdp22def.h qbg/vdp22_cmds.c qbg/vdp_ascii.c \ +-include/qbg_vdp22_oui.h ++include/qbg_vdp22_oui.h qbg/vdp22_oui.c + + lib_LTLIBRARIES = liblldp_clif.la + liblldp_clif_la_LDFLAGS = -version-info 1:0:0 +diff --git a/include/qbg_utils.h b/include/qbg_utils.h +index 6033556..963cb87 100644 +--- a/include/qbg_utils.h ++++ b/include/qbg_utils.h +@@ -42,4 +42,5 @@ int modules_notify(int, int, char *, void *); + + /* Convert VSI IDs to strings */ + int vdp_uuid2str(const unsigned char *, char *, size_t); ++int vdp_str2uuid(unsigned char *, char *, size_t); + #endif +diff --git a/include/qbg_vdp22_oui.h b/include/qbg_vdp22_oui.h +index 0cce31e..79e1ff5 100644 +--- a/include/qbg_vdp22_oui.h ++++ b/include/qbg_vdp22_oui.h +@@ -92,4 +92,52 @@ struct vdp22_oui_handler_s { + unsigned long (*oui_ptlv_size_hndlr)(void *); + }; + ++unsigned char vdp22_oui_get_vsi22_fmt(void *); ++unsigned char *vdp22_oui_get_vsi22_len(void *, unsigned char *); ++int oui_vdp_str2uuid(unsigned char *, char *, size_t); ++bool oui_vdp_hndlr_init(struct vdp22_oui_handler_s *); ++int oui_vdp_hexstr2bin(const char *hex, unsigned char *buf, size_t len); ++ ++static inline size_t oui_append_1o(unsigned char *cp, const unsigned char data) ++{ ++ *cp = data; ++ return 1; ++} ++ ++static inline size_t oui_append_2o(unsigned char *cp, const unsigned short data) ++{ ++ *cp = (data >> 8) & 0xff; ++ *(cp + 1) = data & 0xff; ++ return 2; ++} ++ ++static inline size_t oui_append_3o(unsigned char *cp, const unsigned long data) ++{ ++ *cp = (data >> 16) & 0xff; ++ *(cp + 1) = (data >> 8) & 0xff; ++ *(cp + 2) = data & 0xff; ++ return 3; ++} ++static inline size_t oui_append_4o(unsigned char *cp, const unsigned long data) ++{ ++ *cp = (data >> 24) & 0xff; ++ *(cp + 1) = (data >> 16) & 0xff; ++ *(cp + 2) = (data >> 8) & 0xff; ++ *(cp + 3) = data & 0xff; ++ return 4; ++} ++ ++static inline size_t oui_append_nb(unsigned char *cp, const unsigned char *data, ++ const size_t nlen) ++{ ++ memcpy(cp, data, nlen); ++ return nlen; ++} ++ ++static inline unsigned short oui_get_tlv_head(unsigned short type, ++ unsigned short len) ++{ ++ return (type & 0x7f) << 9 | (len & 0x1ff); ++} ++ + #endif /* __VDP22_OUI_H__ */ +diff --git a/qbg/vdp22_oui.c b/qbg/vdp22_oui.c +new file mode 100644 +index 0000000..3a2d0cc +--- /dev/null ++++ b/qbg/vdp22_oui.c +@@ -0,0 +1,63 @@ ++/******************************************************************************* ++ ++ Implementation of OUI Functionality for VDP2.2 ++ This file contains the exported functions from VDP to the OUI handlers file. ++ Copyright (c) 2012-2014 by Cisco Systems, Inc. ++ ++ Author(s): Padmanabhan Krishnan ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms and conditions of the GNU General Public License, ++ version 2, as published by the Free Software Foundation. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++*******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include "messages.h" ++#include "lldp_util.h" ++#include "qbg_vdp22.h" ++#include "qbg_utils.h" ++#include "qbg_vdp22_oui.h" ++ ++unsigned char vdp22_oui_get_vsi22_fmt(void *vsi_data) ++{ ++ if (vsi_data != NULL) ++ return ((struct vsi22 *)(vsi_data))->vsi_fmt; ++ LLDPAD_ERR("%s: NULL Arg\n", __func__); ++ return 0; ++} ++ ++unsigned char *vdp22_oui_get_vsi22_len(void *vsi_data, unsigned char *len) ++{ ++ if ((vsi_data != NULL) && (len != NULL)) { ++ *len = VDP22_IDSZ; ++ return ((struct vsi22 *)(vsi_data))->vsi; ++ } ++ LLDPAD_ERR("%s: NULL Arg\n", __func__); ++ return NULL; ++} ++ ++int oui_vdp_str2uuid(unsigned char *to, char *buffer, size_t max) ++{ ++ return vdp_str2uuid(to, buffer, max); ++} ++ ++int oui_vdp_hexstr2bin(const char *hex, unsigned char *buf, size_t len) ++{ ++ return hexstr2bin(hex, buf, len); ++} +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-11-VDP-Support-for-Cisco-specific-OUI-extensions-to-VDP.patch b/open-lldp-v1.0.1-11-VDP-Support-for-Cisco-specific-OUI-extensions-to-VDP.patch new file mode 100644 index 0000000..de37ade --- /dev/null +++ b/open-lldp-v1.0.1-11-VDP-Support-for-Cisco-specific-OUI-extensions-to-VDP.patch @@ -0,0 +1,650 @@ +From 409b8d4027d391a401b1d3c0f56569d6402679f7 Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:40:09 +0000 +Subject: [PATCH] VDP: Support for Cisco specific OUI extensions to VDP22 + +This commit has Cisco specific extensions to VDP22. vdptool is also +modified to carry Cisco's extensions for OUI. +The parameters to vdptool that are added for supporting Cisco OUI are: +"-c oui=cisco,vm_name=myname -c oui=cisco,ipv4_addr=a.b.c.d -c oui=cisco,vm_uuid=aaa" + +The description of the files are: + +vdp22cisco_oui.c: +----------------- +This file contain all the handler implementation. +vdp_cisco.h: +------------ +Cisco specific OUI definitions and structures. +vdptool_cisco_oui.c: +-------------------- +Cisco specific OUI extensions for user input. + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + Makefile.am | 5 +- + include/vdp_cisco.h | 121 ++++++++++++++++++ + qbg/vdp22.c | 2 + + qbg/vdp22cisco_oui.c | 355 +++++++++++++++++++++++++++++++++++++++++++++++++++ + vdptool.c | 2 + + vdptool_cisco_oui.c | 58 +++++++++ + 6 files changed, 541 insertions(+), 2 deletions(-) + create mode 100644 include/vdp_cisco.h + create mode 100644 qbg/vdp22cisco_oui.c + create mode 100644 vdptool_cisco_oui.c + +diff --git a/Makefile.am b/Makefile.am +index f63311c..abc9348 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -70,14 +70,15 @@ include/lldp_evb22.h lldp_evb22.c lldp_evb22_cmds.c \ + include/qbg22.h include/qbg_ecp22.h qbg/ecp22.c \ + include/qbg_vdp22.h qbg/vdp22.c qbg/vdpnl.c qbg/vdp22sm.c qbg/vdp22br.c \ + include/qbg_vdp22def.h qbg/vdp22_cmds.c qbg/vdp_ascii.c \ +-include/qbg_vdp22_oui.h qbg/vdp22_oui.c ++include/qbg_vdp22_oui.h qbg/vdp22_oui.c include/vdp_cisco.h \ ++qbg/vdp22cisco_oui.c + + lib_LTLIBRARIES = liblldp_clif.la + liblldp_clif_la_LDFLAGS = -version-info 1:0:0 + liblldp_clif_includedir = ${srcdir}/include + liblldp_clif_la_SOURCES = clif.c + +-vdptool_SOURCES = vdptool.c lldp_util.c qbg/vdp22_clif.c ++vdptool_SOURCES = vdptool.c lldp_util.c qbg/vdp22_clif.c vdptool_cisco_oui.c + vdptool_LDADD = ${srcdir}/liblldp_clif.la + vdptool_LDFLAGS = -llldp_clif $(LIBNL_LIBS) + +diff --git a/include/vdp_cisco.h b/include/vdp_cisco.h +new file mode 100644 +index 0000000..339d479 +--- /dev/null ++++ b/include/vdp_cisco.h +@@ -0,0 +1,121 @@ ++/******************************************************************************* ++ ++ Implementation of Cisco Specific OUI for VDP2.2 ++ Copyright (c) 2012-2014 by Cisco Systems, Inc. ++ ++ Author(s): Padmanabhan Krishnan ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms and conditions of the GNU General Public License, ++ version 2, as published by the Free Software Foundation. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++*******************************************************************************/ ++ ++#ifndef __VDP22_VISCO_H__ ++#define __VDP22_VISCO_H__ ++ ++#include "lldp.h" ++#include ++#include ++#include "qbg_vdp22_oui.h" ++ ++#define MAX_VM_NAME 100 ++#define CISCO_OUI_VAL "00000C" ++#define CISCO_OUI_HEX 0xC ++ ++#define CISCO_OUI_NAME_ARG_STR "vm_name" ++#define CISCO_OUI_NAME_UUID_ARG_STR "vm_uuid" ++#define CISCO_OUI_L3V4ADDR_ARG_STR "ipv4_addr" ++#define MAX_VM_AF 3 ++ ++#define KEYLEN 16 ++#define PORT_UUID_MAX 16 ++ ++enum oui_key_arg { ++ CISCO_OUI_NAME_ARG = 0, ++ CISCO_OUI_NAME_UUID_ARG, ++ CISCO_OUI_L3V4ADDR_ARG, ++ CISCO_OUI_INVALID_ARG ++}; ++ ++enum cisco_oui_subtype { ++ CISCO_OUI_NAME_SUBTYPE = 0xF1, ++ CISCO_OUI_L3ADDR_SUBTYPE = 0xF2, ++}; ++ ++/* ++ * Name SubTLV ++ * OUI: => 3B = 00-00-0C ++ * subtype => 1B = 0xF1 ++ * VSI ID Frmt => 1B ++ * VSI ID => 16B ++ * VM ID Frmt => 1B ++ * VM ID => 16B ++ * VM Name => Variable ++ * Total => 38 + VM name len ++ */ ++ ++/* ++ * L3 Addr SubTLV ++ * OUI: => 3B = 00-00-0C ++ * subtype => 1B = 0xF2 ++ * VSI ID Frmt => 1B ++ * VSI ID => 16B ++ * AFI => 2B ++ * L3 Addr => Variable ++ * Total => 23 + L3 Addr Len ++ */ ++ ++ /* Subtype Len w/o the 3B Cisco OUI Len */ ++enum cisco_oui_subtype_len { ++ CISCO_VM_NAME_TLV_LEN = 35, /* minus the variable name len */ ++ CISCO_VM_L3ADDR_TLV_LEN = 20 /* minus the variable addr len */ ++}; ++ ++struct oui_keyword_handler { ++ char *keyword; ++ enum oui_key_arg val; ++}; ++ ++typedef union l3_addrtype_ { ++ struct in_addr ipv4_address; ++ struct in6_addr ipv6_address; ++} l3_addr_t; ++ ++typedef struct vdp_cisco_oui_s { ++ char key[KEYLEN]; /* Profile name */ ++ u8 uuid[PORT_UUID_MAX]; /* Instance ID */ ++ size_t vm_name_len; ++ char vm_name[MAX_VM_NAME]; ++ u16 afi; ++ u8 vm_addr_len; ++ l3_addr_t l3_addr; ++} vdp_cisco_oui_t; ++ ++bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *, char *); ++bool cisco_vdp_free_oui(struct vdp22_oui_data_s *); ++bool cisco_vdpnl2vsi22_hndlr(void *, struct vdpnl_oui_data_s *, ++ struct vdp22_oui_data_s *); ++size_t cisco_vdp_tx_hndlr(char unsigned *, struct vdp22_oui_data_s *, size_t); ++bool cisco_vdp_rx_hndlr(); ++unsigned long cisco_vdp_oui_ptlvsize(void *); ++ ++static inline void fill_cisco_oui_type(unsigned char *oui_type) ++{ ++ oui_type[0] = 0x00; ++ oui_type[1] = 0x00; ++ oui_type[2] = 0x0c; ++} ++ ++#endif /* __VDP22_VISCO_H__ */ +diff --git a/qbg/vdp22.c b/qbg/vdp22.c +index 5cae83f..ab170ed 100644 +--- a/qbg/vdp22.c ++++ b/qbg/vdp22.c +@@ -48,6 +48,7 @@ + #define EXTERN_FN(name)\ + extern bool name##_oui_init() + ++EXTERN_FN(cisco); + /* Init handlers for OUI. OUI handlers should be added in vdp22_oui_init_list. + * First argument specifies the OUI code assigned to the Organization. + * Second argument is the string which should match with the CLI and the third +@@ -55,6 +56,7 @@ extern bool name##_oui_init() + */ + + struct vdp22_oui_init_s vdp22_oui_init_list[] = { ++ {{0x00, 0x00, 0x0c}, "cisco", INIT_FN(cisco)} + }; + + struct vdp22_oui_handler_s vdp22_oui_list[MAX_NUM_OUI]; +diff --git a/qbg/vdp22cisco_oui.c b/qbg/vdp22cisco_oui.c +new file mode 100644 +index 0000000..ef6c307 +--- /dev/null ++++ b/qbg/vdp22cisco_oui.c +@@ -0,0 +1,355 @@ ++/******************************************************************************* ++ ++ Implementation of Cisco Specific OUI for VDP2.2 ++ Copyright (c) 2012-2014 by Cisco Systems, Inc. ++ ++ Author(s): Padmanabhan Krishnan ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms and conditions of the GNU General Public License, ++ version 2, as published by the Free Software Foundation. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++*******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include "messages.h" ++#include "qbg_vdp22def.h" ++#include "vdp_cisco.h" ++ ++struct vdp22_oui_handler_s cisco_oui_hndlr = { ++ {0x00, 0x00, 0x0c}, "cisco", cisco_str2vdpnl_hndlr, ++ cisco_vdpnl2vsi22_hndlr, ++ cisco_vdp_tx_hndlr, cisco_vdp_rx_hndlr, cisco_vdp_free_oui, ++ cisco_vdp_oui_ptlvsize}; ++ ++struct oui_keyword_handler oui_key_handle[] = { ++ {CISCO_OUI_NAME_ARG_STR, CISCO_OUI_NAME_ARG}, ++ {CISCO_OUI_NAME_UUID_ARG_STR, CISCO_OUI_NAME_UUID_ARG}, ++ {CISCO_OUI_L3V4ADDR_ARG_STR, CISCO_OUI_L3V4ADDR_ARG} }; ++ ++enum oui_key_arg get_oui_key(char *token, u8 key_len) ++{ ++ int count, key_str_size; ++ ++ key_str_size = sizeof(oui_key_handle) / sizeof(oui_key_handle[0]); ++ for (count = 0; count < key_str_size; count++) { ++ if ((key_len <= strlen(token)) && ++ (!strncmp(token, oui_key_handle[count].keyword, key_len))) ++ return oui_key_handle[count].val; ++ } ++ return CISCO_OUI_INVALID_ARG; ++} ++ ++/* ++ * This function fills the vdpnl structure of OUI from the command separated ++ * arguments containing the OUI information. ++ * The input to this function is right from the OUI data after the ORG specific ++ * OUI Type. ++ */ ++ ++bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *vdp_oui_p, char *token) ++{ ++ vdp_cisco_oui_t *vdp_cisco_oui_p; ++ char *uuid, *v4_addr_str; ++ int ret, offset = 0, len; ++ bool vm_name_flag = false, l3_addr_flag = false; ++ enum oui_key_arg oui_argtype; ++ u16 data_len; ++ u8 key_len; ++ ++ if ((vdp_oui_p == NULL) || (token == NULL)) { ++ LLDPAD_ERR("%s: NULL arg\n", __func__); ++ return false; ++ } ++ fill_cisco_oui_type(vdp_oui_p->oui_type); ++ vdp_oui_p->len = sizeof(vdp_cisco_oui_t); ++ vdp_cisco_oui_p = (vdp_cisco_oui_t *)vdp_oui_p->data; ++ len = strlen(token); ++ while (offset < len) { ++ oui_vdp_hexstr2bin(token, &key_len, sizeof(key_len)); ++ token += 2; ++ offset += 2; ++ oui_argtype = get_oui_key(token, key_len); ++ token += key_len; ++ offset += key_len; ++ oui_vdp_hexstr2bin(token, (u8 *)&data_len, sizeof(data_len)); ++ data_len = htons(data_len); ++ token += 4; ++ offset += 4; ++ if ((offset + data_len) > len) { ++ LLDPAD_ERR("%s Incorrect len offset %d key %d data %d" ++ " Len %d\n", __func__, offset, key_len, ++ data_len, len); ++ return false; ++ } ++ switch (oui_argtype) { ++ case CISCO_OUI_NAME_ARG: ++ if (vm_name_flag) { ++ LLDPAD_ERR("%s: Incorrect arguments: Single VSI" ++ " containing multiple VM Name\n", ++ __func__); ++ return false; ++ } ++ vm_name_flag = true; ++ strncpy(vdp_cisco_oui_p->vm_name, token, data_len); ++ vdp_cisco_oui_p->vm_name[data_len] = '\0'; ++ vdp_cisco_oui_p->vm_name_len = data_len; ++ LLDPAD_DBG("Name %s Len %ld\n", ++ vdp_cisco_oui_p->vm_name, ++ vdp_cisco_oui_p->vm_name_len); ++ break; ++ case CISCO_OUI_NAME_UUID_ARG: ++ uuid = calloc(data_len, sizeof(char)); ++ if (uuid == NULL) { ++ LLDPAD_ERR("%s: NULL uuid\n", __func__); ++ return false; ++ } ++ strncpy(uuid, token, data_len); ++ if (oui_vdp_str2uuid(vdp_cisco_oui_p->uuid, uuid, ++ sizeof(vdp_cisco_oui_p->uuid))) ++ memset(vdp_cisco_oui_p->uuid, 0, ++ sizeof(vdp_cisco_oui_p->uuid)); ++ free(uuid); ++ break; ++ case CISCO_OUI_L3V4ADDR_ARG: ++ if (l3_addr_flag) { ++ LLDPAD_ERR("%s: Incorrect arguments: Single VSI" ++ " containing multiple L3 Address\n", ++ __func__); ++ return true; ++ } ++ l3_addr_flag = true; ++ vdp_cisco_oui_p->afi = MANADDR_IPV4; ++ vdp_cisco_oui_p->vm_addr_len = ++ sizeof(vdp_cisco_oui_p->l3_addr.ipv4_address); ++ v4_addr_str = calloc(data_len, sizeof(char)); ++ if (v4_addr_str == NULL) { ++ LLDPAD_ERR("%s: NULL L3 Address\n", __func__); ++ return false; ++ } ++ strncpy(v4_addr_str, token, data_len); ++ ret = inet_aton(v4_addr_str, ++ &vdp_cisco_oui_p->l3_addr.ipv4_address); ++ LLDPAD_DBG("V4adr %s 0x%lx\n", v4_addr_str, ++ (unsigned long) ++ vdp_cisco_oui_p->l3_addr.ipv4_address.s_addr); ++ free(v4_addr_str); ++ if (!ret) { ++ LLDPAD_ERR("%s: Incorrect addr\n", __func__); ++ return false; ++ } ++ break; ++ default: ++ LLDPAD_ERR("%s: unknown subtype %d\n", __func__, ++ oui_argtype); ++ return false; ++ } ++ token += data_len; ++ offset += data_len; ++ } ++ return true; ++} ++ ++/* ++ * This function converts the OUI information from vdpnl struct to vdp22 struct ++ * vsi is not used here, but can be used for storing the pointer to the parent ++ * struct ++ */ ++ ++bool cisco_vdpnl2vsi22_hndlr(void *vsi_data, struct vdpnl_oui_data_s *from, ++ struct vdp22_oui_data_s *to) ++{ ++ if ((from == NULL) || (to == NULL)) { ++ LLDPAD_ERR("%s: NULL arg\n", __func__); ++ return false; ++ } ++ to->data = calloc(1, from->len); ++ if (to->data == NULL) { ++ LLDPAD_ERR("%s: calloc failure\n", __func__); ++ return false; ++ } ++ memcpy(to->oui_type, from->oui_type, sizeof(to->oui_type)); ++ strncpy(to->oui_name, from->oui_name, sizeof(to->oui_name)); ++ /* Parent Pointer */ ++ to->vsi_data = vsi_data; ++ to->len = from->len; ++ memcpy(to->data, from->data, to->len); ++ return true; ++} ++ ++/* ++ * This function deletes the OUI information associated with a VSI ++ */ ++ ++bool cisco_vdp_free_oui(struct vdp22_oui_data_s *vdp_oui_p) ++{ ++ if ((vdp_oui_p == NULL) || (vdp_oui_p->data == NULL)) { ++ LLDPAD_ERR("%s: NULL arg\n", __func__); ++ return false; ++ } ++ free(vdp_oui_p->data); ++ vdp_oui_p->len = 0; ++ vdp_oui_p->data = NULL; ++ return true; ++} ++ ++/* ++ * This gets called for any VDP specific response. Currently not implemented. ++ */ ++ ++bool cisco_vdp_rx_hndlr() ++{ ++ return true; ++} ++ ++static inline unsigned long cisco_vdp_name_subtlv_len(vdp_cisco_oui_t *ptr) ++{ ++ return CISCO_VM_NAME_TLV_LEN + ptr->vm_name_len; ++} ++ ++static inline unsigned long cisco_vdp_l3addr_subtlv_len(vdp_cisco_oui_t *ptr) ++{ ++ return CISCO_VM_L3ADDR_TLV_LEN + ptr->vm_addr_len; ++} ++ ++/* ++ * Returns the size ++ * ORG TLV's are sent separately for Name and IP, which is why the T,L of 2B ++ * and 3B for OUI_TYPE_LEN is added for both. This is done to be compatible ++ * with Cisco switch implementation. ++ */ ++ ++unsigned long cisco_vdp_oui_ptlvsize(void *arg_ptr) ++{ ++ vdp_cisco_oui_t *ptr = (vdp_cisco_oui_t *)arg_ptr; ++ unsigned long cnt = 0; ++ ++ if (ptr == NULL) { ++ LLDPAD_ERR("%s: Incorrect arg\n", __func__); ++ return 0; ++ } ++ if (ptr->vm_name_len != 0) { ++ cnt += 2 + VDP22_OUI_TYPE_LEN; ++ cnt += cisco_vdp_name_subtlv_len(ptr); ++ } ++ /* Only V4 or V6 is supported */ ++ if ((ptr->afi == MANADDR_IPV4) || (ptr->afi == MANADDR_IPV6)) { ++ cnt += 2 + VDP22_OUI_TYPE_LEN; ++ cnt += cisco_vdp_l3addr_subtlv_len(ptr); ++ } ++ return cnt; ++} ++ ++static inline size_t cisco_vdp22_gen_l3addr(char unsigned *cp, size_t offset, ++ struct vdp22_oui_data_s *oui_ptr) ++{ ++ vdp_cisco_oui_t *vdp_cisco_oui_str; ++ unsigned char *vsi = NULL; ++ unsigned short head; ++ unsigned char len = 0; ++ unsigned long net_l3_addr; ++ ++ vdp_cisco_oui_str = (vdp_cisco_oui_t *)oui_ptr->data; ++ head = oui_get_tlv_head(VDP22_OUI, VDP22_OUI_TYPE_LEN + ++ cisco_vdp_l3addr_subtlv_len(oui_ptr->data)); ++ offset += oui_append_2o(cp + offset, head); ++ offset += oui_append_3o(cp + offset, CISCO_OUI_HEX); ++ offset += oui_append_1o(cp + offset, CISCO_OUI_L3ADDR_SUBTYPE); ++ offset += oui_append_1o(cp + offset, ++ vdp22_oui_get_vsi22_fmt(oui_ptr->vsi_data)); ++ vsi = vdp22_oui_get_vsi22_len(oui_ptr->vsi_data, &len); ++ if (vsi != NULL) ++ offset += oui_append_nb(cp + offset, vsi, len); ++ else ++ LLDPAD_ERR("%s: get vsi22 return error\n", __func__); ++ offset += oui_append_2o(cp + offset, vdp_cisco_oui_str->afi); ++ if (vdp_cisco_oui_str->afi == MANADDR_IPV4) { ++ net_l3_addr = htonl(vdp_cisco_oui_str->l3_addr. ++ ipv4_address.s_addr); ++ offset += oui_append_4o(cp + offset, net_l3_addr); ++ } else { ++ offset += oui_append_4o(cp + offset, 0); ++ LLDPAD_ERR("%s: Not supported for now\n", __func__); ++ } ++ LLDPAD_DBG("%s: Valid VM Addr offset %ld\n", __func__, offset); ++ return offset; ++} ++ ++static inline size_t cisco_vdp22_gen_vmname(char unsigned *cp, size_t offset, ++ struct vdp22_oui_data_s *oui_ptr) ++{ ++ vdp_cisco_oui_t *vdp_cisco_oui_str; ++ unsigned char *vsi = NULL; ++ unsigned short head; ++ unsigned char len = 0; ++ ++ vdp_cisco_oui_str = (vdp_cisco_oui_t *)oui_ptr->data; ++ head = oui_get_tlv_head(VDP22_OUI, VDP22_OUI_TYPE_LEN + ++ cisco_vdp_name_subtlv_len(oui_ptr->data)); ++ offset += oui_append_2o(cp + offset, head); ++ offset += oui_append_3o(cp + offset, CISCO_OUI_HEX); ++ offset += oui_append_1o(cp + offset, CISCO_OUI_NAME_SUBTYPE); ++ offset += oui_append_1o(cp + offset, ++ vdp22_oui_get_vsi22_fmt(oui_ptr->vsi_data)); ++ vsi = vdp22_oui_get_vsi22_len(oui_ptr->vsi_data, &len); ++ if (vsi != NULL) ++ offset += oui_append_nb(cp + offset, vsi, len); ++ else ++ LLDPAD_ERR("%s: get vsi22 return error\n", __func__); ++ offset += oui_append_1o(cp + offset, VDP22_ID_UUID); ++ offset += oui_append_nb(cp + offset, vdp_cisco_oui_str->uuid, ++ sizeof(vdp_cisco_oui_str->uuid)); ++ offset += oui_append_nb(cp + offset, ++ (char unsigned *)vdp_cisco_oui_str->vm_name, ++ vdp_cisco_oui_str->vm_name_len); ++ LLDPAD_DBG("%s: Valid VM Name offset %ld\n", __func__, offset); ++ return offset; ++} ++ ++/* ++ * This function takes care of converting the OUI for Tx. ++ */ ++ ++size_t cisco_vdp_tx_hndlr(char unsigned *cp, struct vdp22_oui_data_s *oui_ptr, ++ size_t offset) ++{ ++ vdp_cisco_oui_t *vdp_cisco_oui_str; ++ ++ if ((cp == NULL) || (oui_ptr == NULL) || (oui_ptr->data == NULL)) { ++ LLDPAD_ERR("%s: NULL Arguments\n", __func__); ++ return 0; ++ } ++ vdp_cisco_oui_str = (vdp_cisco_oui_t *)oui_ptr->data; ++ if (vdp_cisco_oui_str->vm_name_len != 0) ++ offset = cisco_vdp22_gen_vmname(cp, offset, oui_ptr); ++ if (vdp_cisco_oui_str->vm_addr_len != 0) ++ offset = cisco_vdp22_gen_l3addr(cp, offset, oui_ptr); ++ return offset; ++} ++ ++bool cisco_oui_init() ++{ ++ bool ret; ++ ++ ret = oui_vdp_hndlr_init(&cisco_oui_hndlr); ++ if (!ret) { ++ LLDPAD_ERR("%s: handler init return err\n", __func__); ++ return false; ++ } ++ return true; ++} +diff --git a/vdptool.c b/vdptool.c +index c857a85..8edd6ca 100644 +--- a/vdptool.c ++++ b/vdptool.c +@@ -65,10 +65,12 @@ + * here. The corresponding decoder handler should be in lldpad. + */ + ++EXTERN_OUI_FN(cisco); + + /* The OUI specific handlers should be added here */ + + vdptool_oui_hndlr_tbl_t oui_hndlr_tbl[] = { ++ {"cisco", OUI_ENCODE_HNDLR(cisco)} + }; + + +diff --git a/vdptool_cisco_oui.c b/vdptool_cisco_oui.c +new file mode 100644 +index 0000000..4a846ad +--- /dev/null ++++ b/vdptool_cisco_oui.c +@@ -0,0 +1,58 @@ ++/******************************************************************************* ++ ++ Implementation of Cisco Specific OUI for vdptool ++ Copyright (c) 2012-2014 by Cisco Systems, Inc. ++ ++ Author(s): Padmanabhan Krishnan ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms and conditions of the GNU General Public License, ++ version 2, as published by the Free Software Foundation. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++*******************************************************************************/ ++ ++#include ++#include ++#include ++#include "vdp_cisco.h" ++ ++bool cisco_oui_encode_hndlr(char *dst, char *src, int len) ++{ ++ char *src_temp = strdup(src); ++ char *key, *data; ++ bool flag = false; ++ ++ if (!src_temp) ++ return false; ++ key = src_temp; ++ data = strchr(key, '='); ++ if (!data) { ++ free(src_temp); ++ return false; ++ } ++ *data = '\0'; ++ data++; ++ if ((!strcmp(key, CISCO_OUI_NAME_ARG_STR)) || ++ (!strcmp(key, CISCO_OUI_L3V4ADDR_ARG_STR)) || ++ (!strcmp(key, CISCO_OUI_NAME_UUID_ARG_STR))) { ++ snprintf(dst, MAX_OUI_DATA_LEN - len, "%02x%s%04x%s", ++ (unsigned int)strlen(key), key, ++ (unsigned int)strlen(data), data); ++ flag = true; ++ } else ++ printf("Incorrect Cisco OUI %s\n", key); ++ free(src_temp); ++ return flag; ++} ++ +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-12-VDP22-Fix-the-ack-timeout-handler-to-set-the-right-t.patch b/open-lldp-v1.0.1-12-VDP22-Fix-the-ack-timeout-handler-to-set-the-right-t.patch new file mode 100644 index 0000000..0cb20fb --- /dev/null +++ b/open-lldp-v1.0.1-12-VDP22-Fix-the-ack-timeout-handler-to-set-the-right-t.patch @@ -0,0 +1,33 @@ +From c26e175bea45306657c3435dc1ac2203584cf77a Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:40:32 +0000 +Subject: [PATCH] VDP22: Fix the ack timeout handler to set the right timeout + variable + +Currently the acktimeout handler sets the keepalive timeout boolean +variable as a result of which the profiles don't get deleted when +there's a timeout. This diff sets the acktimeout variable in the +acktimeout handler. + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + qbg/vdp22sm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/qbg/vdp22sm.c b/qbg/vdp22sm.c +index db0e413..14356ac 100644 +--- a/qbg/vdp22sm.c ++++ b/qbg/vdp22sm.c +@@ -439,7 +439,7 @@ static void vdp22st_handle_ackto(UNUSED void *ctx, void *data) + LLDPAD_DBG("%s:%s timeout ack timer for %p(%02x) ackreceived:%d\n", + __func__, p->vdp->ifname, p, p->vsi[0], p->smi.ackreceived); + if (!p->smi.ackreceived) { +- p->smi.kato = true; ++ p->smi.acktimeout = true; + vdp22st_run(p); + } + } +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-13-VDP-Changes-in-OUI-infra-for-get-tlv.patch b/open-lldp-v1.0.1-13-VDP-Changes-in-OUI-infra-for-get-tlv.patch new file mode 100644 index 0000000..85a4305 --- /dev/null +++ b/open-lldp-v1.0.1-13-VDP-Changes-in-OUI-infra-for-get-tlv.patch @@ -0,0 +1,333 @@ +From 0bc166920c14081ed90d4774a52ca38813fc1739 Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:40:52 +0000 +Subject: [PATCH] VDP: Changes in OUI infra for get-tlv + +Changes made in OUI infra code to support retrieving OUI parameters +during get-tlv + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + include/qbg_vdp22_oui.h | 7 +++++++ + include/qbg_vdpnl.h | 1 + + qbg/vdp22.c | 32 ++++++++++++++++++++++++++++++++ + qbg/vdp22_cmds.c | 4 ++++ + qbg/vdp22_oui.c | 5 +++++ + qbg/vdp_ascii.c | 37 +++++++++++++++++++++++++++++++++++++ + qbg/vdpnl.c | 14 ++++++++++++++ + vdptool.c | 38 ++++++++++++++++++++++++++++++++++---- + 8 files changed, 134 insertions(+), 4 deletions(-) + +diff --git a/include/qbg_vdp22_oui.h b/include/qbg_vdp22_oui.h +index 79e1ff5..923e19f 100644 +--- a/include/qbg_vdp22_oui.h ++++ b/include/qbg_vdp22_oui.h +@@ -53,6 +53,7 @@ typedef struct vdptool_oui_data_s { + typedef struct vdptool_oui_hndlr_tbl_s { + char *oui_name; + bool (*oui_cli_encode_hndlr)(char *dst, char *src, size_t len); ++ void (*oui_print_decode_hndlr)(char *dst); + } vdptool_oui_hndlr_tbl_t; + + struct vdpnl_oui_data_s { +@@ -81,6 +82,11 @@ struct vdp22_oui_handler_s { + /* This handler converts the vdpnl structure to vsi22 structure */ + bool (*vdpnl2vsi22_hndlr)(void *, struct vdpnl_oui_data_s *, + struct vdp22_oui_data_s *); ++ /* This handler converts the vdpnl structure to string */ ++ bool (*vdpnl2str_hndlr)(struct vdpnl_oui_data_s *, char *, ++ int *, int); ++ bool (*vsi2vdpnl_hndlr)(void *, struct vdp22_oui_data_s *, ++ struct vdpnl_oui_data_s *); + /* This handler creates the OUI fields for Tx */ + size_t (*vdp_tx_hndlr)(char unsigned *, + struct vdp22_oui_data_s *, size_t); +@@ -95,6 +101,7 @@ struct vdp22_oui_handler_s { + unsigned char vdp22_oui_get_vsi22_fmt(void *); + unsigned char *vdp22_oui_get_vsi22_len(void *, unsigned char *); + int oui_vdp_str2uuid(unsigned char *, char *, size_t); ++int oui_vdp_uuid2str(unsigned char *, char *, size_t); + bool oui_vdp_hndlr_init(struct vdp22_oui_handler_s *); + int oui_vdp_hexstr2bin(const char *hex, unsigned char *buf, size_t len); + +diff --git a/include/qbg_vdpnl.h b/include/qbg_vdpnl.h +index bf18e71..cb7efca 100644 +--- a/include/qbg_vdpnl.h ++++ b/include/qbg_vdpnl.h +@@ -81,6 +81,7 @@ int vdp_str2vdpnl(char *, struct vdpnl_vsi *, char *); + int vdp_vdpnl2str(struct vdpnl_vsi *, char *, size_t); + int vdp22_sendevent(struct vdpnl_vsi *); + void vdp22_freemaclist(struct vdpnl_vsi *); ++void vsinl_delete_oui(struct vdpnl_vsi *); + int vdp22_parse_str_vdpnl(struct vdpnl_vsi *, unsigned short *, char *); + struct vsi22 *vdp22_alloc_vsi_ext(struct vdpnl_vsi *, int *); + void copy_vsi_external(struct vdpnl_vsi *, struct vsi22 *, int); +diff --git a/qbg/vdp22.c b/qbg/vdp22.c +index ab170ed..10b80a4 100644 +--- a/qbg/vdp22.c ++++ b/qbg/vdp22.c +@@ -1010,6 +1010,37 @@ static void copy_fid(struct vdpnl_vsi *vsi, struct vsi22 *p) + } + + /* ++ * This function copies the OUI from VSI22 to vdpnl structure. ++ */ ++ ++static void copy_oui(struct vdpnl_vsi *vsi, struct vsi22 *p) ++{ ++ struct vdp22_oui_handler_s *oui_hndlr; ++ bool ret; ++ int idx; ++ ++ vsi->oui_list = calloc(p->no_ouidata, sizeof(*vsi->oui_list)); ++ if (!vsi->oui_list) ++ return; ++ vsi->ouisz = p->no_ouidata; ++ for (idx = 0; idx < p->no_ouidata; idx++) { ++ struct vdpnl_oui_data_s *to = &vsi->oui_list[idx]; ++ struct vdp22_oui_data_s *from = &p->oui_str_data[idx]; ++ ++ oui_hndlr = vdp22_get_oui_hndlr(from->oui_name); ++ if (oui_hndlr == NULL) { ++ LLDPAD_ERR("%s: No handler registered for OUI %s\n", ++ __func__, from->oui_name); ++ continue; ++ } ++ ret = oui_hndlr->vsi2vdpnl_hndlr(p, from, to); ++ if (!ret) ++ LLDPAD_ERR("%s: handler return error for oui %s\n", ++ __func__, from->oui_name); ++ } ++} ++ ++/* + * Fill the VSI data to return to caller. Currently returned data depends + * on requestor: + * 1. Via netlink message from libvirtd and vdptest: +@@ -1033,6 +1064,7 @@ static void copy_vsi(struct vdpnl_vsi *vsi, struct vsi22 *p, int clif) + if (clif || (p->flags & VDP22_RETURN_VID)) { + copy_fid(vsi, p); + p->flags &= ~VDP22_RETURN_VID; ++ copy_oui(vsi, p); + } + } + +diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c +index 5b5788f..79ea9ca 100644 +--- a/qbg/vdp22_cmds.c ++++ b/qbg/vdp22_cmds.c +@@ -434,6 +434,7 @@ static int catvsis(struct vdpnl_vsi *vsi, char *out, size_t out_len) + for (i = 1; vdp22_status(i, vsi, 1) > 0; ++i) { + if (wanted_req != vsi->request) { + vdp22_freemaclist(vsi); ++ vsinl_delete_oui(vsi); + continue; + } + rc = vdp_vdpnl2str(vsi, tmp_buf, out_len - used); +@@ -443,6 +444,7 @@ static int catvsis(struct vdpnl_vsi *vsi, char *out, size_t out_len) + if ((c < 0) || ((unsigned)c >= (out_len - used))) + return 0; + vdp22_freemaclist(vsi); ++ vsinl_delete_oui(vsi); + if (rc) { + used = strlen(out); + } else +@@ -533,6 +535,8 @@ static int get_vsi_partial_arg(UNUSED char *arg, char *orig_argvalue, + len = strlen(tmp_buf); + c = snprintf(out + used, out_len - used, "%04x%s", + len, tmp_buf); ++ vdp22_freemaclist(vsinl); ++ vsinl_delete_oui(vsinl); + if ((c < 0) || ((unsigned)c >= (out_len - used))) + goto out_delvsi; + if (rc) +diff --git a/qbg/vdp22_oui.c b/qbg/vdp22_oui.c +index 3a2d0cc..4960324 100644 +--- a/qbg/vdp22_oui.c ++++ b/qbg/vdp22_oui.c +@@ -57,6 +57,11 @@ int oui_vdp_str2uuid(unsigned char *to, char *buffer, size_t max) + return vdp_str2uuid(to, buffer, max); + } + ++int oui_vdp_uuid2str(unsigned char *from, char *buffer, size_t max) ++{ ++ return vdp_uuid2str(from, buffer, max); ++} ++ + int oui_vdp_hexstr2bin(const char *hex, unsigned char *buf, size_t len) + { + return hexstr2bin(hex, buf, len); +diff --git a/qbg/vdp_ascii.c b/qbg/vdp_ascii.c +index 80a4419..709ffd9 100644 +--- a/qbg/vdp_ascii.c ++++ b/qbg/vdp_ascii.c +@@ -244,6 +244,10 @@ static bool oui_str2vdpnl(struct vdpnl_vsi *vsi, char *p, unsigned short idx) + oui_hndlr = vdp22_get_oui_hndlr(oui_name); + if (!oui_hndlr) + return false; ++ if (!vsi->oui_list) { ++ LLDPAD_ERR("%s: Null OUI List\n", __func__); ++ return false; ++ } + strncpy(vsi->oui_list[idx].oui_name, oui_name, + sizeof(vsi->oui_list[idx].oui_name)); + if (oui_hndlr->str2vdpnl_hndlr) +@@ -597,11 +601,16 @@ static void mgrid2str(char *to, struct vdpnl_vsi *p, size_t to_len) + /* + * Convert a vdpnl_vsi to string. + */ ++ + int vdp_vdpnl2str(struct vdpnl_vsi *p, char *s, size_t length) + { + int c, i; + size_t total = 0; + char instance[VDP_UUID_STRLEN + 2]; ++ struct vdp22_oui_handler_s *oui_hndlr; ++ int oui_total = 0; ++ int ret; ++ int idx; + + mgrid2str(instance, p, sizeof(instance)); + c = snprintf(s, length, "%02x%s%04x%s%02x%s%04x%s%02x%s%04x%lu%02x%s" +@@ -642,6 +651,34 @@ int vdp_vdpnl2str(struct vdpnl_vsi *p, char *s, size_t length) + if (!c) + goto out; + } ++ for (idx = 0; idx < p->ouisz; idx++) { ++ struct vdpnl_oui_data_s *from = &p->oui_list[idx]; ++ ++ oui_total = 0; ++ oui_hndlr = vdp22_get_oui_hndlr(from->oui_name); ++ if (oui_hndlr == NULL) { ++ LLDPAD_ERR("%s: Unknown OUI Name %s\n", __func__, ++ from->oui_name); ++ } else { ++ c = snprintf(s, length, "%02x%s", ++ (unsigned int)strlen(VSI22_ARG_OUI_STR), ++ VSI22_ARG_OUI_STR); ++ s = check_and_update(&total, &length, s, c); ++ if (!s) ++ goto out; ++ ret = oui_hndlr->vdpnl2str_hndlr(from, s, &oui_total, ++ length); ++ if (!ret) { ++ LLDPAD_ERR("%s: handler return error for " ++ "oui %s\n", __func__, ++ from->oui_name); ++ goto out; ++ } ++ s = check_and_update(&total, &length, s, oui_total); ++ if (!s) ++ goto out; ++ } ++ } + + out: + return s ? total : 0; +diff --git a/qbg/vdpnl.c b/qbg/vdpnl.c +index 5c0ffd4..9b8fcdd 100644 +--- a/qbg/vdpnl.c ++++ b/qbg/vdpnl.c +@@ -365,6 +365,19 @@ static int vdpnl_get(struct vdpnl_vsi *p, struct nlmsghdr *nlh) + } + + /* ++ * Delete the OUI structures of VSI22 ++ */ ++ ++void vsinl_delete_oui(struct vdpnl_vsi *p) ++{ ++ if ((p->ouisz == 0) || (p->oui_list == NULL)) ++ return; ++ p->ouisz = 0; ++ free(p->oui_list); ++ p->oui_list = NULL; ++} ++ ++/* + * Free an malloc'ed maclist array. + */ + void vdp22_freemaclist(struct vdpnl_vsi *vsi) +@@ -419,6 +432,7 @@ static int vdpnl_getlink(struct nlmsghdr *nlh, size_t len) + nla_nest_end(msg, vf_port); + } + vdp22_freemaclist(&p); ++ vsinl_delete_oui(&p); + } while (rc == 1); + nla_nest_end(msg, vf_ports); + if (rc < 0) { +diff --git a/vdptool.c b/vdptool.c +index 8edd6ca..b805372 100644 +--- a/vdptool.c ++++ b/vdptool.c +@@ -58,8 +58,11 @@ + #include "qbg_vdp22_oui.h" + + #define OUI_ENCODE_HNDLR(name) name##_oui_encode_hndlr ++#define OUI_PRNT_DECODE_HNDLR(name) name##_oui_print_decode_hndlr ++ + #define EXTERN_OUI_FN(name) \ +- extern bool name##_oui_encode_hndlr(char *, char *, size_t) ++ extern bool name##_oui_encode_hndlr(char *, char *, size_t); \ ++ extern void name##_oui_print_decode_hndlr(char *) + + /* The handler declaration for encoding OUI specific information should be + * here. The corresponding decoder handler should be in lldpad. +@@ -70,7 +73,7 @@ EXTERN_OUI_FN(cisco); + /* The OUI specific handlers should be added here */ + + vdptool_oui_hndlr_tbl_t oui_hndlr_tbl[] = { +- {"cisco", OUI_ENCODE_HNDLR(cisco)} ++ {"cisco", OUI_ENCODE_HNDLR(cisco), OUI_PRNT_DECODE_HNDLR(cisco)} + }; + + +@@ -508,6 +511,29 @@ void print_vsi_err_msg(char *key_val) + printf("\tInternal Error : %s\n", VSI22_TX_ERR_STR); + } + ++static void print_oui_vals(char *argvals) ++{ ++ char oui_name[VDP22_OUI_MAX_NAME]; ++ char *temp_argval = argvals; ++ char *oui_val; ++ int tbl_size, cnt; ++ u8 oui_name_len; ++ ++ hexstr2bin(argvals, &oui_name_len, sizeof(oui_name_len)); ++ if (oui_name_len >= VDP22_OUI_MAX_NAME) ++ return; ++ temp_argval = argvals + 2 * sizeof(oui_name_len); ++ oui_val = temp_argval + oui_name_len; ++ strncpy(oui_name, temp_argval, oui_name_len); ++ oui_name[oui_name_len] = '\0'; ++ tbl_size = sizeof(oui_hndlr_tbl) / sizeof(vdptool_oui_hndlr_tbl_t); ++ for (cnt = 0; cnt < tbl_size; cnt++) { ++ if (!strncmp(oui_hndlr_tbl[cnt].oui_name, oui_name, ++ VDP22_OUI_MAX_NAME)) ++ oui_hndlr_tbl[cnt].oui_print_decode_hndlr(oui_val); ++ } ++} ++ + static void print_vsi(char **args, char **argvals, int numargs, + bool err_flag) + { +@@ -517,8 +543,12 @@ static void print_vsi(char **args, char **argvals, int numargs, + if (err_flag && (!strcmp(args[i], VSI22_ARG_HINTS_STR))) + print_vsi_err_msg(argvals[i]); + else { +- printf("\t%s", args[i]); +- printf(" = %s\n", argvals[i]); ++ if (!strcmp(args[i], VSI22_ARG_OUI_STR)) { ++ print_oui_vals(argvals[i]); ++ } else { ++ printf("\t%s", args[i]); ++ printf(" = %s\n", argvals[i]); ++ } + } + } + } +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-14-VDP-Changes-in-Cisco-OUI-handlers-to-support-get-tlv.patch b/open-lldp-v1.0.1-14-VDP-Changes-in-Cisco-OUI-handlers-to-support-get-tlv.patch new file mode 100644 index 0000000..71466e0 --- /dev/null +++ b/open-lldp-v1.0.1-14-VDP-Changes-in-Cisco-OUI-handlers-to-support-get-tlv.patch @@ -0,0 +1,283 @@ +From ead7bc6267c87e0816ba2367b9036d8a647f3099 Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:41:14 +0000 +Subject: [PATCH] VDP: Changes in Cisco OUI handlers to support get-tlv + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + include/vdp_cisco.h | 22 ++++++++++ + qbg/vdp22cisco_oui.c | 120 ++++++++++++++++++++++++++++++++++++++++++--------- + vdptool_cisco_oui.c | 54 +++++++++++++++++++++++ + 3 files changed, 175 insertions(+), 21 deletions(-) + +diff --git a/include/vdp_cisco.h b/include/vdp_cisco.h +index 339d479..821db68 100644 +--- a/include/vdp_cisco.h ++++ b/include/vdp_cisco.h +@@ -96,6 +96,7 @@ typedef union l3_addrtype_ { + typedef struct vdp_cisco_oui_s { + char key[KEYLEN]; /* Profile name */ + u8 uuid[PORT_UUID_MAX]; /* Instance ID */ ++ bool uuid_set; + size_t vm_name_len; + char vm_name[MAX_VM_NAME]; + u16 afi; +@@ -103,10 +104,18 @@ typedef struct vdp_cisco_oui_s { + l3_addr_t l3_addr; + } vdp_cisco_oui_t; + ++struct oui_keyword_handler oui_key_handle[] = { ++ {CISCO_OUI_NAME_ARG_STR, CISCO_OUI_NAME_ARG}, ++ {CISCO_OUI_NAME_UUID_ARG_STR, CISCO_OUI_NAME_UUID_ARG}, ++ {CISCO_OUI_L3V4ADDR_ARG_STR, CISCO_OUI_L3V4ADDR_ARG} }; ++ + bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *, char *); + bool cisco_vdp_free_oui(struct vdp22_oui_data_s *); + bool cisco_vdpnl2vsi22_hndlr(void *, struct vdpnl_oui_data_s *, + struct vdp22_oui_data_s *); ++bool cisco_vdpnl2str_hndlr(struct vdpnl_oui_data_s *, char *, int *, int); ++bool cisco_vsi2vdpnl_hndlr(void *, struct vdp22_oui_data_s *, ++ struct vdpnl_oui_data_s *); + size_t cisco_vdp_tx_hndlr(char unsigned *, struct vdp22_oui_data_s *, size_t); + bool cisco_vdp_rx_hndlr(); + unsigned long cisco_vdp_oui_ptlvsize(void *); +@@ -118,4 +127,17 @@ static inline void fill_cisco_oui_type(unsigned char *oui_type) + oui_type[2] = 0x0c; + } + ++enum oui_key_arg get_oui_key(char *token, u8 key_len) ++{ ++ int count, key_str_size; ++ ++ key_str_size = sizeof(oui_key_handle) / sizeof(oui_key_handle[0]); ++ for (count = 0; count < key_str_size; count++) { ++ if ((key_len <= strlen(token)) && ++ (!strncmp(token, oui_key_handle[count].keyword, key_len))) ++ return oui_key_handle[count].val; ++ } ++ return CISCO_OUI_INVALID_ARG; ++} ++ + #endif /* __VDP22_VISCO_H__ */ +diff --git a/qbg/vdp22cisco_oui.c b/qbg/vdp22cisco_oui.c +index ef6c307..e8a824c 100644 +--- a/qbg/vdp22cisco_oui.c ++++ b/qbg/vdp22cisco_oui.c +@@ -29,31 +29,14 @@ + #include + #include "messages.h" + #include "qbg_vdp22def.h" ++#include "qbg_utils.h" + #include "vdp_cisco.h" + + struct vdp22_oui_handler_s cisco_oui_hndlr = { + {0x00, 0x00, 0x0c}, "cisco", cisco_str2vdpnl_hndlr, +- cisco_vdpnl2vsi22_hndlr, +- cisco_vdp_tx_hndlr, cisco_vdp_rx_hndlr, cisco_vdp_free_oui, +- cisco_vdp_oui_ptlvsize}; +- +-struct oui_keyword_handler oui_key_handle[] = { +- {CISCO_OUI_NAME_ARG_STR, CISCO_OUI_NAME_ARG}, +- {CISCO_OUI_NAME_UUID_ARG_STR, CISCO_OUI_NAME_UUID_ARG}, +- {CISCO_OUI_L3V4ADDR_ARG_STR, CISCO_OUI_L3V4ADDR_ARG} }; +- +-enum oui_key_arg get_oui_key(char *token, u8 key_len) +-{ +- int count, key_str_size; +- +- key_str_size = sizeof(oui_key_handle) / sizeof(oui_key_handle[0]); +- for (count = 0; count < key_str_size; count++) { +- if ((key_len <= strlen(token)) && +- (!strncmp(token, oui_key_handle[count].keyword, key_len))) +- return oui_key_handle[count].val; +- } +- return CISCO_OUI_INVALID_ARG; +-} ++ cisco_vdpnl2vsi22_hndlr, cisco_vdpnl2str_hndlr, ++ cisco_vsi2vdpnl_hndlr, cisco_vdp_tx_hndlr, cisco_vdp_rx_hndlr, ++ cisco_vdp_free_oui, cisco_vdp_oui_ptlvsize}; + + /* + * This function fills the vdpnl structure of OUI from the command separated +@@ -124,6 +107,7 @@ bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *vdp_oui_p, char *token) + sizeof(vdp_cisco_oui_p->uuid))) + memset(vdp_cisco_oui_p->uuid, 0, + sizeof(vdp_cisco_oui_p->uuid)); ++ vdp_cisco_oui_p->uuid_set = true; + free(uuid); + break; + case CISCO_OUI_L3V4ADDR_ARG: +@@ -193,6 +177,100 @@ bool cisco_vdpnl2vsi22_hndlr(void *vsi_data, struct vdpnl_oui_data_s *from, + } + + /* ++ * This function converts the OUI information from vdpnl struct to string ++ */ ++ ++bool cisco_vdpnl2str_hndlr(struct vdpnl_oui_data_s *from, char *out_buf, ++ int *total, int rem_len) ++{ ++ char tmp_out_buf[MAX_OUI_DATA_LEN]; ++ char uuid_str[VDP_UUID_STRLEN + 2]; ++ char *tmp_oui_buf; ++ vdp_cisco_oui_t *vdp_cisco_oui_p; ++ int c = 0, num_str_bytes; ++ int tmp_buf_len = sizeof(tmp_out_buf); ++ ++ tmp_oui_buf = tmp_out_buf; ++ if ((from == NULL) || (out_buf == NULL)) { ++ LLDPAD_ERR("%s: NULL arg\n", __func__); ++ return false; ++ } ++ vdp_cisco_oui_p = (vdp_cisco_oui_t *)from->data; ++ c = snprintf(tmp_oui_buf, tmp_buf_len, "%02x%s", ++ (unsigned int)strlen("cisco"), "cisco"); ++ tmp_buf_len -= c; ++ tmp_oui_buf += c; ++ if (vdp_cisco_oui_p->vm_name_len != 0) { ++ c = snprintf(tmp_oui_buf, tmp_buf_len, ++ "%02x%s%04x%s", ++ (unsigned int)strlen(CISCO_OUI_NAME_ARG_STR), ++ CISCO_OUI_NAME_ARG_STR, ++ (unsigned int)vdp_cisco_oui_p->vm_name_len, ++ vdp_cisco_oui_p->vm_name); ++ if ((c < 0) || (c >= tmp_buf_len)) ++ return false; ++ tmp_buf_len -= c; ++ tmp_oui_buf += c; ++ } ++ if (vdp_cisco_oui_p->uuid_set) { ++ oui_vdp_uuid2str(vdp_cisco_oui_p->uuid, uuid_str, ++ sizeof(uuid_str)); ++ c = snprintf(tmp_oui_buf, tmp_buf_len, ++ "%02x%s%04x%s", ++ (unsigned int)strlen(CISCO_OUI_NAME_UUID_ARG_STR), ++ CISCO_OUI_NAME_UUID_ARG_STR, ++ (unsigned int)strlen(uuid_str), uuid_str); ++ if ((c < 0) || (c >= tmp_buf_len)) ++ return false; ++ tmp_buf_len -= c; ++ tmp_oui_buf += c; ++ } ++ if (vdp_cisco_oui_p->vm_addr_len != 0) { ++ num_str_bytes = snprintf(NULL, 0, "%ul", ++ vdp_cisco_oui_p->l3_addr. ++ ipv4_address.s_addr); ++ c = snprintf(tmp_oui_buf, tmp_buf_len, "%02x%s%04x%ul", ++ (unsigned int)strlen(CISCO_OUI_L3V4ADDR_ARG_STR), ++ CISCO_OUI_L3V4ADDR_ARG_STR, num_str_bytes, ++ vdp_cisco_oui_p->l3_addr.ipv4_address.s_addr); ++ if ((c < 0) || (c >= tmp_buf_len)) ++ return false; ++ tmp_buf_len -= c; ++ tmp_oui_buf += c; ++ } ++ c = snprintf(out_buf, rem_len, "%04x%s", ++ (unsigned int)strlen(tmp_out_buf), ++ tmp_out_buf); ++ if ((c < 0) || (c >= rem_len)) ++ return false; ++ rem_len -= c; ++ out_buf += c; ++ *total += c; ++ return true; ++} ++ ++/* ++ * This function converts the OUI information from vsi22 struct to vdpnl struct ++ * vsi is not used here, but can be used for storing the pointer to the parent ++ * struct ++ */ ++ ++bool cisco_vsi2vdpnl_hndlr(UNUSED void *vsi_data, struct vdp22_oui_data_s *from, ++ struct vdpnl_oui_data_s *to) ++{ ++ if ((from == NULL) || (to == NULL)) { ++ LLDPAD_ERR("%s: NULL arg\n", __func__); ++ return false; ++ } ++ memcpy(to->oui_type, from->oui_type, sizeof(to->oui_type)); ++ strncpy(to->oui_name, from->oui_name, sizeof(to->oui_name)); ++ to->len = from->len; ++ memcpy(to->data, from->data, to->len); ++ return true; ++} ++ ++ ++/* + * This function deletes the OUI information associated with a VSI + */ + +diff --git a/vdptool_cisco_oui.c b/vdptool_cisco_oui.c +index 4a846ad..7003521 100644 +--- a/vdptool_cisco_oui.c ++++ b/vdptool_cisco_oui.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include "lldp_util.h" + #include "vdp_cisco.h" + + bool cisco_oui_encode_hndlr(char *dst, char *src, int len) +@@ -56,3 +57,56 @@ bool cisco_oui_encode_hndlr(char *dst, char *src, int len) + return flag; + } + ++void cisco_oui_print_decode_hndlr(char *token) ++{ ++ struct in_addr vm_inet; ++ char *v4_addr_str; ++ unsigned long vm_ip_addr; ++ int offset = 0, len; ++ u16 data_len; ++ u8 key_len; ++ enum oui_key_arg oui_argtype; ++ ++ if (token == NULL) ++ return; ++ len = strlen(token); ++ while (offset < len) { ++ hexstr2bin(token, &key_len, sizeof(key_len)); ++ token += 2; ++ offset += 2; ++ oui_argtype = get_oui_key(token, key_len); ++ token += key_len; ++ offset += key_len; ++ hexstr2bin(token, (u8 *)&data_len, sizeof(data_len)); ++ data_len = htons(data_len); ++ token += 4; ++ offset += 4; ++ if ((offset + data_len) > len) ++ return; ++ switch (oui_argtype) { ++ case CISCO_OUI_NAME_ARG: ++ printf("\t%s", "VM Name"); ++ printf(" = %.*s\n", data_len, token); ++ break; ++ case CISCO_OUI_NAME_UUID_ARG: ++ printf("\t%s", "VM UUID"); ++ printf(" = %.*s\n", data_len, token); ++ break; ++ case CISCO_OUI_L3V4ADDR_ARG: ++ v4_addr_str = calloc(data_len, sizeof(char)); ++ if (!v4_addr_str) ++ return; ++ strncpy(v4_addr_str, token, data_len); ++ vm_ip_addr = strtoul(v4_addr_str, NULL, 10); ++ vm_inet.s_addr = vm_ip_addr; ++ printf("\t%s", "VM IP Address"); ++ printf(" = %s\n", inet_ntoa(vm_inet)); ++ free(v4_addr_str); ++ break; ++ default: ++ break; ++ } ++ token += data_len; ++ offset += data_len; ++ } ++} +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-15-VDP-Add-vdptool-man-page-to-Makefile.patch b/open-lldp-v1.0.1-15-VDP-Add-vdptool-man-page-to-Makefile.patch new file mode 100644 index 0000000..9bc32b5 --- /dev/null +++ b/open-lldp-v1.0.1-15-VDP-Add-vdptool-man-page-to-Makefile.patch @@ -0,0 +1,27 @@ +From 5add0baccd0c888742a00af4b17754990dbcbf93 Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:41:38 +0000 +Subject: [PATCH] VDP: Add vdptool man page to Makefile + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index abc9348..27dffc2 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -109,7 +109,7 @@ dist_man_MANS = docs/lldpad.8 docs/dcbtool.8 docs/lldptool.8 \ + docs/lldptool-ets.8 docs/lldptool-pfc.8 docs/lldptool-app.8 \ + docs/lldptool-evb.8 docs/lldptool-vdp.8 docs/lldptool-med.8 \ + docs/lldptool-dcbx.8 \ +- docs/lldptool-evb22.8 ++ docs/lldptool-evb22.8 docs/vdptool.8 + if BUILD_DEBUG + nodist_man_MANS = test/qbg22sim.1 test/vdptest.1 + endif +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-16-VDP-Fixed-DBG-print-compile-errors-in-32-bit-systems.patch b/open-lldp-v1.0.1-16-VDP-Fixed-DBG-print-compile-errors-in-32-bit-systems.patch new file mode 100644 index 0000000..2cc1c3a --- /dev/null +++ b/open-lldp-v1.0.1-16-VDP-Fixed-DBG-print-compile-errors-in-32-bit-systems.patch @@ -0,0 +1,45 @@ +From b6c5d86ea57594893d4fd95a0bf8043c45c953a4 Mon Sep 17 00:00:00 2001 +From: Paddu Krishnan +Date: Wed, 21 Jan 2015 03:42:01 +0000 +Subject: [PATCH] VDP: Fixed DBG print compile errors in 32-bit systems + +Signed-off-by: Paddu Krishnan +Signed-off-by: John Fastabend +--- + qbg/vdp22cisco_oui.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/qbg/vdp22cisco_oui.c b/qbg/vdp22cisco_oui.c +index e8a824c..272d480 100644 +--- a/qbg/vdp22cisco_oui.c ++++ b/qbg/vdp22cisco_oui.c +@@ -92,7 +92,7 @@ bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *vdp_oui_p, char *token) + strncpy(vdp_cisco_oui_p->vm_name, token, data_len); + vdp_cisco_oui_p->vm_name[data_len] = '\0'; + vdp_cisco_oui_p->vm_name_len = data_len; +- LLDPAD_DBG("Name %s Len %ld\n", ++ LLDPAD_DBG("Name %s Len %zu\n", + vdp_cisco_oui_p->vm_name, + vdp_cisco_oui_p->vm_name_len); + break; +@@ -364,7 +364,7 @@ static inline size_t cisco_vdp22_gen_l3addr(char unsigned *cp, size_t offset, + offset += oui_append_4o(cp + offset, 0); + LLDPAD_ERR("%s: Not supported for now\n", __func__); + } +- LLDPAD_DBG("%s: Valid VM Addr offset %ld\n", __func__, offset); ++ LLDPAD_DBG("%s: Valid VM Addr offset %zu\n", __func__, offset); + return offset; + } + +@@ -395,7 +395,7 @@ static inline size_t cisco_vdp22_gen_vmname(char unsigned *cp, size_t offset, + offset += oui_append_nb(cp + offset, + (char unsigned *)vdp_cisco_oui_str->vm_name, + vdp_cisco_oui_str->vm_name_len); +- LLDPAD_DBG("%s: Valid VM Name offset %ld\n", __func__, offset); ++ LLDPAD_DBG("%s: Valid VM Name offset %zu\n", __func__, offset); + return offset; + } + +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-17-lldp-automake-fixes-for-dist-distcheck.patch b/open-lldp-v1.0.1-17-lldp-automake-fixes-for-dist-distcheck.patch new file mode 100644 index 0000000..2c7e1e3 --- /dev/null +++ b/open-lldp-v1.0.1-17-lldp-automake-fixes-for-dist-distcheck.patch @@ -0,0 +1,130 @@ +From c986aa5bc5f509f3cbc033212e0808a992ec48bf Mon Sep 17 00:00:00 2001 +From: John Fastabend +Date: Fri, 30 Jan 2015 08:32:07 -0800 +Subject: [PATCH] lldp: automake fixes for dist/distcheck + +This fixes the dist and distcheck automake targets for making release +archives. + +All missing header files that have been added to git are listed in +noinst_HEADERS, so they get added to the release archive but are not +installed. Some of these ( qgb_vdp22_(cmds|clif).h ) may be part of the +client API and need to be moved to lldpad_include_HEADERS? + +The srcdir prefix was removed from references to liblldp_clif.la, it's +not needed and breaks builds where the output dir is different from the +source dir as this is a generated file. + +The liblldp_clid-vdp22.3 man page was added. + +The qbg22sim and vdptest man pages were added to the release archive, +but still should only be installed if debug is configured. + +lldpad.init was added to dist_noinst_DATA to add to the release + +The custom systemd unit file install rule was replaced with a dist_DATA +definition, letting automake build the rules to handle them. Before +they were being left out of the release archive. + +Same thing with the bash completion files, just tell automake where they +go. + +Compared to git-archive, make dist now gets almost everything. +I left the test data files out for now, even though the binaries and +man pages are being included. + +Signed-off-by: Chris Leech +Signed-off-by: John Fastabend +--- + Makefile.am | 42 ++++++++++++++++++------------------------ + 1 file changed, 18 insertions(+), 24 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 27dffc2..69deda2 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -43,7 +43,10 @@ include/lldp_8023_clif.h include/lldp_dcbx_clif.h include/lldp_evb_clif.h \ + include/lldp_evb22_clif.h include/qbg_vdp_clif.h include/qbg_vdpnl.h \ + include/qbg_vdp22_clif.h include/lldp_8021qaz_clif.h \ + include/lldp_orgspec_clif.h include/lldp_cisco_clif.h \ +-include/lldptool.h include/lldp_rtnl.h include/dcbtool.h include/lldp_dcbx_cfg.h ++include/lldptool.h include/lldp_rtnl.h include/dcbtool.h include/lldp_dcbx_cfg.h \ ++include/qbg_vdp22_cmds.h include/qbg_vdp22_clif.h \ ++include/linux/ethtool.h include/linux/if_bonding.h include/linux/if_bridge.h \ ++include/linux/if.h include/linux/if_link.h include/linux/if_vlan.h + + lldpad_SOURCES = lldpad.c config.c lldp_dcbx_nl.c ctrl_iface.c \ + event_iface.c eloop.c lldp_dcbx_cmds.c log.c lldpad_shm.c \ +@@ -84,7 +87,7 @@ vdptool_LDFLAGS = -llldp_clif $(LIBNL_LIBS) + + dcbtool_SOURCES = dcbtool.c dcbtool_cmds.c parse_cli.l \ + weak_readline.c $(lldpad_include_HEADERS) $(noinst_HEADERS) +-dcbtool_LDADD = ${srcdir}/liblldp_clif.la ++dcbtool_LDADD = liblldp_clif.la + dcbtool_LDFLAGS = -ldl -llldp_clif + + lldptool_SOURCES = lldptool.c lldptool_cmds.c lldp_rtnl.c \ +@@ -93,7 +96,7 @@ lldptool_SOURCES = lldptool.c lldptool_cmds.c lldp_rtnl.c \ + lldp_8021qaz_clif.c lldp_evb_clif.c qbg/vdp_clif.c \ + lldp_orgspec_clif.c lldp_cisco_clif.c lldp_evb22_clif.c \ + weak_readline.c $(lldpad_include_HEADERS) $(noinst_HEADERS) +-lldptool_LDADD = ${srcdir}/liblldp_clif.la ++lldptool_LDADD = liblldp_clif.la + lldptool_LDFLAGS = -ldl -llldp_clif $(LIBNL_LIBS) + + if BUILD_DEBUG +@@ -104,14 +107,20 @@ qbg22sim_SOURCES = test/qbg22sim.c + qbg22sim_LDFLAGS = -lrt + endif + ++## put a spec file and documentation in the distribution archive ++dist_noinst_DATA = lldpad.spec README COPYING ChangeLog lldpad.init ++ + ## man pages + dist_man_MANS = docs/lldpad.8 docs/dcbtool.8 docs/lldptool.8 \ + docs/lldptool-ets.8 docs/lldptool-pfc.8 docs/lldptool-app.8 \ + docs/lldptool-evb.8 docs/lldptool-vdp.8 docs/lldptool-med.8 \ + docs/lldptool-dcbx.8 \ +- docs/lldptool-evb22.8 docs/vdptool.8 ++ docs/lldptool-evb22.8 docs/vdptool.8 \ ++ docs/liblldp_clif-vdp22.3 + if BUILD_DEBUG +-nodist_man_MANS = test/qbg22sim.1 test/vdptest.1 ++dist_man_MANS += test/qbg22sim.1 test/vdptest.1 ++else ++dist_noinst_DATA += test/qbg22sim.1 test/vdptest.1 + endif + + ## force the creation of an empty configuration directory at install time +@@ -124,24 +133,9 @@ install-data-hook: installdirs-local + pkgconfigdir = ${libdir}/pkgconfig + pkgconfig_DATA = lldpad.pc liblldp_clif.pc + +-## put a spec file and documentation in the distribution archive +-dist_noinst_DATA = lldpad.spec README COPYING ChangeLog ++systemdsystemunitdir = $(prefix)/lib/systemd/system ++dist_systemdsystemunit_DATA = lldpad.service lldpad.socket + +-## special hooks to handle the init script +-install-data-local: lldpad.service lldpad.socket +- $(MKDIR_P) $(DESTDIR)/usr/lib/systemd/system +- $(INSTALL_DATA) lldpad.service $(DESTDIR)/usr/lib/systemd/system/lldpad.service +- $(INSTALL_DATA) lldpad.socket $(DESTDIR)/usr/lib/systemd/system/lldpad.socket +- +-BASH_COMPLETION_DIR=/etc/bash_completion.d/ +- +-install-data-hook: +- ## provide support for bash completion +- $(MKDIR_P) $(DESTDIR)/$(BASH_COMPLETION_DIR) +- $(INSTALL_DATA) ${srcdir}/contrib/bash_completion/* $(DESTDIR)/$(BASH_COMPLETION_DIR) +- +-uninstall-local: +- rm -f '$(DESTDIR)/usr/lib/systemd/system/lldpad.*' +- rm -f '$(includedir)/dcbd/clif_cmds.h' +- rm -f '$(includedir)/dcbd' ++bashcompletiondir = $(sysconfdir)/bash_completion.d ++dist_bashcompletion_DATA = contrib/bash_completion/lldpad contrib/bash_completion/lldptool + +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-18-enabled-test-tool-building-for-distcheck.patch b/open-lldp-v1.0.1-18-enabled-test-tool-building-for-distcheck.patch new file mode 100644 index 0000000..6590ef8 --- /dev/null +++ b/open-lldp-v1.0.1-18-enabled-test-tool-building-for-distcheck.patch @@ -0,0 +1,26 @@ +From 0d2fa5cd29b8ce60c5b1dfc2a68e09794e9073c8 Mon Sep 17 00:00:00 2001 +From: Chris Leech +Date: Fri, 30 Jan 2015 08:21:41 +0000 +Subject: [PATCH] enabled test tool building for distcheck + +set the --enable-debug flag when running distcheck, to test build the +debug tools as well + +Signed-off-by: Chris Leech +Signed-off-by: John Fastabend +--- + Makefile.am | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Makefile.am b/Makefile.am +index 69deda2..b1c381b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -139,3 +139,4 @@ dist_systemdsystemunit_DATA = lldpad.service lldpad.socket + bashcompletiondir = $(sysconfdir)/bash_completion.d + dist_bashcompletion_DATA = contrib/bash_completion/lldpad contrib/bash_completion/lldptool + ++AM_DISTCHECK_CONFIGURE_FLAGS = --enable-debug +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-19-nltest-build-error.patch b/open-lldp-v1.0.1-19-nltest-build-error.patch new file mode 100644 index 0000000..d0427a4 --- /dev/null +++ b/open-lldp-v1.0.1-19-nltest-build-error.patch @@ -0,0 +1,40 @@ +From 53ebbfd6dd8cf475884fd523207e354696a0670d Mon Sep 17 00:00:00 2001 +From: Chris Leech +Date: Fri, 30 Jan 2015 08:21:42 +0000 +Subject: [PATCH] nltest build error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +test/nltest.c: In function ‘set_hw_bcn’: +test/nltest.c:994:38: error: iteration 8u invokes undefined behavior +[-Werror=aggressive-loop-optimizations] + bcn_data->up_settings[i].rp_admin = 1; + ^ +test/nltest.c:993:3: note: containing loop + for (i = 0; i <= 8; i++) { + ^ +cc1: all warnings being treated as errors + +Signed-off-by: Chris Leech +Signed-off-by: John Fastabend +--- + test/nltest.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/nltest.c b/test/nltest.c +index da05463..cd28977 100644 +--- a/test/nltest.c ++++ b/test/nltest.c +@@ -990,7 +990,7 @@ static int set_hw_bcn(char *device_name, bcn_cfg *bcn_data, + oper_mode = 1; + + { +- for (i = 0; i <= 8; i++) { ++ for (i = 0; i < 8; i++) { + bcn_data->up_settings[i].rp_admin = 1; + } + bcn_data->rp_alpha = 0.5; +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-2-VDP-vdptool-first-version.patch b/open-lldp-v1.0.1-2-VDP-vdptool-first-version.patch new file mode 100644 index 0000000..f1918c7 --- /dev/null +++ b/open-lldp-v1.0.1-2-VDP-vdptool-first-version.patch @@ -0,0 +1,1671 @@ +From 3b559d8d0b52e6a254dc3f59833de4308e18711e Mon Sep 17 00:00:00 2001 +From: Thomas Richter +Date: Wed, 21 Jan 2015 03:36:26 +0000 +Subject: [PATCH] VDP: vdptool first version + +This is the first version of a vdp command line interface +tool to send and retrieve data to the vdp22 module. +This tool follows similar concept as the lldptool. +The command line options are similar and some intended +functionality (such as -n to retrieve neighbor inforamtion, +that is tlv data send by bridges) is not yet implemented. + +Signed-off-by: Thomas Richter +Signed-off-by: John Fastabend +--- + .gitignore | 1 + + Makefile.am | 8 +- + docs/vdptool.8 | 280 +++++++++++ + include/qbg_vdp22_clif.h | 2 + + qbg/vdp22_clif.c | 141 ++++++ + vdptool.c | 1149 ++++++++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 1579 insertions(+), 2 deletions(-) + create mode 100644 docs/vdptool.8 + create mode 100644 qbg/vdp22_clif.c + create mode 100644 vdptool.c + +diff --git a/.gitignore b/.gitignore +index c2ac5d7..e2230d9 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -31,6 +31,7 @@ missing + dcbtool + lldpad + lldptool ++vdptool + nltest + vdptest + qbg22sim +diff --git a/Makefile.am b/Makefile.am +index 4889d32..fc4f8d6 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,5 +1,5 @@ + # target programs to be installed in ${sbindir} +-sbin_PROGRAMS = lldpad dcbtool lldptool ++sbin_PROGRAMS = lldpad dcbtool lldptool vdptool + + # package nltest and vdptest, but do not install it anywhere + if BUILD_DEBUG +@@ -41,7 +41,7 @@ include/parse_cli.h include/version.h include/lldptool_cli.h include/list.h \ + include/lldp_mand_clif.h include/lldp_basman_clif.h include/lldp_med_clif.h \ + include/lldp_8023_clif.h include/lldp_dcbx_clif.h include/lldp_evb_clif.h \ + include/lldp_evb22_clif.h include/qbg_vdp_clif.h include/qbg_vdpnl.h \ +-include/lldp_8021qaz_clif.h \ ++include/qbg_vdp22_clif.h include/lldp_8021qaz_clif.h \ + include/lldp_orgspec_clif.h include/lldp_cisco_clif.h \ + include/lldptool.h include/lldp_rtnl.h include/dcbtool.h include/lldp_dcbx_cfg.h + +@@ -76,6 +76,10 @@ liblldp_clif_la_LDFLAGS = -version-info 1:0:0 + liblldp_clif_includedir = ${srcdir}/include + liblldp_clif_la_SOURCES = clif.c + ++vdptool_SOURCES = vdptool.c lldp_util.c qbg/vdp22_clif.c ++vdptool_LDADD = ${srcdir}/liblldp_clif.la ++vdptool_LDFLAGS = -llldp_clif $(LIBNL_LIBS) ++ + dcbtool_SOURCES = dcbtool.c dcbtool_cmds.c parse_cli.l \ + weak_readline.c $(lldpad_include_HEADERS) $(noinst_HEADERS) + dcbtool_LDADD = ${srcdir}/liblldp_clif.la +diff --git a/docs/vdptool.8 b/docs/vdptool.8 +new file mode 100644 +index 0000000..5110bb9 +--- /dev/null ++++ b/docs/vdptool.8 +@@ -0,0 +1,280 @@ ++.\" LICENSE ++.\" ++.\" This software program is released under the terms of a license agreement ++.\" between you ('Licensee') and Intel. Do not use or load this software or ++.\" any associated materials (collectively, the 'Software') until you have ++.\" carefully read the full terms and conditions of the LICENSE located in this ++.\" software package. By loading or using the Software, you agree to the ++.\" terms of this Agreement. If you do not agree with the terms of this ++.\" Agreement, do not install or use the Software. ++.\" ++.\" * Other names and brands may be claimed as the property of others. ++.\" ++.TH vdptool 8 "April 2014" "open-lldp" "Linux" ++.SH NAME ++vdptool \- manage the VSI associations and status of lldpad ++.SH SYNOPSIS ++.B vdptool [options] [argument] ++.br ++.SH DESCRIPTION ++.B vdptool ++is used to query and configure the VSI associations in ++.B lldpad. ++Only the ratified stardard version of the VDP protocol ++(also refered to as vdp22) is supported. ++It connects to the client interface of ++.B lldpad ++to perform these operations. ++.B vdptool ++will operate in interactive mode if it is executed without a \fIcommand\fR. ++In interactive mode, ++.B vdptool ++will also function as an event listener to print out events ++as they are received asynchronously from ++.BR lldpad "(still to be done)." ++It will use libreadline for interactive input when available ++(still to be done). ++.SH OPTIONS ++.TP ++.B \-i [ifname] ++specifies the network interface to which the command applies. Most ++.B vdptool ++commands require specifying a network interface. ++.TP ++.B -V [tlvid] ++specifies the VDP tlv identifier to be set or queried. ++.br ++The tlvid is an integer value used to identify specific ++VDP TLVs. The tlvid value is the type value for types not equal ++to 127 (the organizationally specific type). ++For organizationally specific ++TLVs, the tlvid is the value represented by the 3 byte OUI and 1 byte ++subtype - where the subtype is the lowest order byte of the tlvid. ++.br ++The tlvid can be entered as a numerical value (e.g. 10 or 0xa), or for ++supported TLVs, as a keyword (such as assoc, deassoc, preassoc, ++preassoc-rr, etc). ++Review the ++.B vdptool ++help output to see the list of supported TLV keywords. ++.sp 1 ++Use option -c to specify the parameters and its values to be set or queried. ++.TP ++.B \-n ++"neighbor" option for commands which can use it (e.g. get-tlv). ++Use this flag to retrieve the last VDP22 data returned from the ++bridge. ++(not yet supported). ++.TP ++.B \-c ++Specifies additional parameters for TLV queries and associations commands. ++The argument list varies, depending on the command option ++.B (-T) ++or ++.BR (-t) . ++To establish a VSI association use the command option ++.B (-T) ++and specify additional information as arguments in the form ++of key=value. See the ++.I "VSI Parameter" ++subsection and ++.I Example ++section below. ++To query a VSI specific association use the command option ++.B (-t) ++and specify the value of the ++VSI Instance Identifier (keywork uuid followed be the VSI ++UUID value) ++of the VSI association as configuration parameter. ++.TP ++.B \-r ++show raw client interface messages ++.TP ++.B \-R ++show only raw Client interface messages ++.SS VSI Parameter ++Each VDP22 TLVs contains a command mode, manager identifier, ++type identifier, type identifier version, VSI instance identifier, ++migiration hints and filter information. ++The fields are explained next: ++.TP ++.B "mode (Command Mode):" ++The command mode determines the type ++of the VSI association to be established. ++It is an ascii string can be one of: ++.RS ++.IP assoc: ++Create an VSI association. ++.IP preassoc: ++Create an VSI preassociation. The association ++is only announced to the switch. ++.IP preassoc-rr: ++Create an VSI preassociation. The association ++is only announced to the switch and the ++switch should reserve the resources. ++.IP deassoc: ++Delete an VSI association. ++.RE ++Other strings are not recognized and return an error. ++.TP ++.B "mgrid2 (Manager identifier):" ++The manager identifier is a string of up to 16 ++alphanumeric characters. ++It can also be an UUID according to RFC 4122 ++with optional dashes in between. ++.TP ++.B "typeid (Type Identifier):" ++The type identifier is a number in the range ++of 0 to 2^24 - 1. ++.TP ++.B "typeidver (Type Identifier Version):" ++The type identifer version is a number ++in the range of 0 to 255. ++.TP ++.B "uuid (VSI Instance Identifier):" ++The VSI instance identifier is ++an UUID according to RFC 4122 ++with optional dashes in between. ++.TP ++.B "hints (Migration Hints):" ++The migiration hints is a string aiding in ++migration of virtual machines: ++.RS ++.IP none: ++No hints available. ++.IP from: ++The virtual machine is migrating away. ++.IP to: ++The virtual machine is migrating to. ++.RE ++.TP ++.B "fid (Filter Information Data):" ++The filter information data can be supplied in four ++different formats identified by numbers in parathesis. ++Multiple filter information fields can be supplied, ++but all have to be of the same format. ++.RS ++.IP "vlan (1)" ++A vlan number only, also known as filter information format 1. ++The vlan identifier is a number in the range of 1 to 2^16 - 1. ++The high order 4 bits are used as quality of service bits. ++The vlan identifier can be zero, a vlan identifier is then ++selected by the switch. Refer to IEEE 802.1 Qbg ratified ++standard for details. ++.IP "vlan-mac (2)" ++A vlan number and MAC address delimited by a slash ('-'), ++also known as filter information format 2. ++The MAC address is specified in the format xx:xx:xx:xx:xx:xx. ++The colons are mandatory. ++For vlan details see (1). ++.IP "vlan-mac-group (4)" ++A vlan number, MAC address and group identifier, ++each delimited by a slash ('-'), ++also known as filter information format 4. ++The group identifier is a 32 bit number. ++For vlan and MAC address details see (1) and (2). ++.IP "vlan--group (3)" ++A vlan number and group identifier, ++delimited by two slashes ('--'), ++also known as filter information format 3. ++For vlan and group details see (1) and (4). ++.RE ++.SH COMMANDS ++.TP ++.B license ++show license information ++.TP ++.B \-h, help ++show usage information ++.TP ++.B \-v, version ++show version information ++.TP ++.B \-t, get-tlv ++get TLV information for the specified interface ++.TP ++.B \-T, set-tlv ++set TLV information for the specified interface ++.TP ++.B \-p, ping ++display the process identifier of the running lldpad process ++.TP ++.B \-q, quit ++exit from interactive mode ++.PP ++.SH NOTES ++This tool is in its early design and development phase. ++It it buggy, incomplete and most of the ideas have not even ++been thought of.... ++It reflects the current state of development when ++I had been given another work assignment. ++I append it so some else can continue to work on this. ++.SH EXAMPLES ++.TP ++Display process identifier of lldpad ++.br ++vdptool -p ++.TP ++Create a VSI association on interface eth2 ++.br ++.nf ++Supported today: One config parameter and comma separated list ++vdptool -i eth2 -T -V assoc -c vsi=assoc,blabla,5, \\ ++ 1122,4,none,2-52:00:00:11:22:33-200 ++ ++Planned for the future: ++vdptool -i eth2 -T -V assoc -c mgrid2=blabla -c typeid=5 \\ ++ -c uuid=1122 -c typeidver=4 -c hints=none -c fid=2-52:00:00:11:22:33-200 ++.fi ++.TP ++Query all VSI association on interface eth2 ++.br ++vdptool -i eth2 -t -V assoc ++.SH SEE ALSO ++.BR lldptool-dcbx (8), ++.BR lldptool-ets (8), ++.BR lldptool-pfc (8), ++.BR lldptool-app (8), ++.BR lldptool-med (8), ++.BR lldptool-vdp (8), ++.BR lldptool-evb (8), ++.BR lldptool-evb22 (8), ++.BR dcbtool (8), ++.BR lldpad (8) ++.br ++.SH COPYRIGHT ++vdptool - VSI configuration utility ++.br ++.IP Copyright(c) ++(c) 2014 IBM Corporation. ++.BR ++Portions of vdptool are based on: ++.IP open-lldp-0.96 ++.IP "lldptool - LLDP agent configuration utility" ++.IP Copyright(c) ++2007-2012 Intel Corporation. ++.BR ++Portions of lldptool are based on: ++.IP hostapd-0.5.7 ++.IP Copyright ++(c) 2004-2008, Jouni Malinen ++ ++.SH LICENSE ++This program is free software; you can redistribute it and/or modify it ++under the terms and conditions of the GNU General Public License, ++version 2, as published by the Free Software Foundation. ++.LP ++This program is distributed in the hope it will be useful, but WITHOUT ++ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++more details. ++.LP ++You should have received a copy of the GNU General Public License along with ++this program; if not, write to the Free Software Foundation, Inc., ++51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++.LP ++The full GNU General Public License is included in this distribution in ++the file called "COPYING". ++.SH SUPPORT ++Contact Information: ++open-lldp Mailing List +diff --git a/include/qbg_vdp22_clif.h b/include/qbg_vdp22_clif.h +index 20330b8..008022a 100644 +--- a/include/qbg_vdp22_clif.h ++++ b/include/qbg_vdp22_clif.h +@@ -52,4 +52,6 @@ typedef enum { + op_delete = 0x20, + op_key = 0x40 + } vdp22_op; ++ ++struct lldp_module *vdp22_cli_register(void); + #endif +diff --git a/qbg/vdp22_clif.c b/qbg/vdp22_clif.c +new file mode 100644 +index 0000000..649305d +--- /dev/null ++++ b/qbg/vdp22_clif.c +@@ -0,0 +1,141 @@ ++/******************************************************************************* ++ ++ Implementation of VDP 22 (ratified standard) according to IEEE 802.1Qbg ++ (c) Copyright IBM Corp. 2014 ++ ++ Author(s): Thomas Richter ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms and conditions of the GNU General Public License, ++ version 2, as published by the Free Software Foundation. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++*******************************************************************************/ ++ ++#include ++#include ++#include ++#include ++ ++#include "lldp_mod.h" ++#include "clif_msgs.h" ++#include "lldp.h" ++#include "qbg22.h" ++#include "qbg_vdp22def.h" ++#include "qbg_vdpnl.h" ++#include "qbg_vdp22_cmds.h" ++#include "qbg_vdp22_clif.h" ++#include "qbg_vdp22def.h" ++ ++static struct type_name_info vdp22_tlv_names[] = { ++ { ++ .name = "VDP VSI Association", ++ .key = "assoc", ++ .type = VDP22_ASSOC ++ }, ++ { ++ .name = "VDP VSI Deassociation", ++ .key = "deassoc", ++ .type = VDP22_DEASSOC ++ }, ++ { ++ .name = "VDP VSI Preassociation", ++ .key = "preassoc", ++ .type = VDP22_PREASSOC ++ }, ++ { ++ .name = "VDP VSI Preassociation with resource reservation", ++ .key = "preassoc-rr", ++ .type = VDP22_PREASSOC_WITH_RR ++ }, ++ { ++ .type = INVALID_TLVID ++ } ++}; ++ ++static int vdp22_print_help(void) ++{ ++ struct type_name_info *tn = &vdp22_tlv_names[0]; ++ ++ while (tn->type != INVALID_TLVID) { ++ if (tn->key && strlen(tn->key) && tn->name) { ++ printf(" %s", tn->key); ++ if (strlen(tn->key) + 3 < 8) ++ printf("\t"); ++ printf("\t: %s\n", tn->name); ++ } ++ tn++; ++ } ++ return 0; ++} ++ ++static u32 vdp22_lookup_tlv_name(char *tlvid_str) ++{ ++ struct type_name_info *tn = &vdp22_tlv_names[0]; ++ ++ while (tn->type != INVALID_TLVID) { ++ if (!strcasecmp(tn->key, tlvid_str)) ++ return tn->type; ++ tn++; ++ } ++ return INVALID_TLVID; ++} ++ ++static void vdp22_cli_unregister(struct lldp_module *mod) ++{ ++ free(mod); ++} ++ ++/* return 1: if it printed the TLV ++ * 0: if it did not ++ */ ++static int vdp22_print_tlv(u32 tlvid, u16 len, char *info) ++{ ++ struct type_name_info *tn = &vdp22_tlv_names[0]; ++ ++ while (tn->type != INVALID_TLVID) { ++ if (tlvid == tn->type) { ++ printf("%s\n", tn->name); ++ if (tn->print_info) { ++ printf("\t"); ++ tn->print_info(len - 4, info); ++ } ++ return 1; ++ } ++ tn++; ++ } ++ return 0; ++} ++ ++static const struct lldp_mod_ops vdp22_ops_clif = { ++ .lldp_mod_register = vdp22_cli_register, ++ .lldp_mod_unregister = vdp22_cli_unregister, ++ .print_tlv = vdp22_print_tlv, ++ .lookup_tlv_name = vdp22_lookup_tlv_name, ++ .print_help = vdp22_print_help, ++}; ++ ++struct lldp_module *vdp22_cli_register(void) ++{ ++ struct lldp_module *mod; ++ ++ mod = malloc(sizeof(*mod)); ++ if (!mod) { ++ fprintf(stderr, "failed to malloc module data\n"); ++ return NULL; ++ } ++ mod->id = LLDP_MOD_VDP22; ++ mod->ops = &vdp22_ops_clif; ++ return mod; ++} +diff --git a/vdptool.c b/vdptool.c +new file mode 100644 +index 0000000..e7d384a +--- /dev/null ++++ b/vdptool.c +@@ -0,0 +1,1149 @@ ++/******************************************************************************* ++ ++ LLDP Agent Daemon (LLDPAD) Software ++ Copyright(c) IBM Corp. 2014 ++ ++ Substantially modified from: ++ hostapd-0.5.7 ++ Copyright (c) 2002-2007, Jouni Malinen and ++ contributors ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms and conditions of the GNU General Public License, ++ version 2, as published by the Free Software Foundation. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++ ++ Contact Information: ++ open-lldp Mailing List ++ ++*******************************************************************************/ ++ ++/* ++ * Thomas Richter, IBM LTC Boeblingen, Germany, Feb 2014 ++ * ++ * Command line interface tool to connect to vdp module of lldpad to ++ * set and query VSI profile settings. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "version.h" ++#include "clif.h" ++#include "clif_msgs.h" ++#include "lldp_mod.h" ++ ++#include "qbg22.h" ++#include "qbg_vdp22_clif.h" ++ ++static char *print_status(cmd_status status) ++{ ++ char *str; ++ ++ switch (status) { ++ case cmd_success: ++ str = "Successful"; ++ break; ++ case cmd_failed: ++ str = "Failed"; ++ break; ++ case cmd_device_not_found: ++ str = "Device not found or inactive"; ++ break; ++ case cmd_agent_not_found: ++ str = "Agent instance for device not found"; ++ break; ++ case cmd_invalid: ++ str = "Invalid command"; ++ break; ++ case cmd_bad_params: ++ str = "Invalid parameters"; ++ break; ++ case cmd_peer_not_present: ++ str = "Peer feature not present"; ++ break; ++ case cmd_ctrl_vers_not_compatible: ++ str = "Version not compatible"; ++ break; ++ case cmd_not_capable: ++ str = "Device not capable"; ++ break; ++ case cmd_not_applicable: ++ str = "Command not applicable"; ++ break; ++ case cmd_no_access: ++ str = "Access denied"; ++ break; ++ case cmd_agent_not_supported: ++ str = "TLV does not support agent type"; ++ break; ++ default: ++ str = "Unknown status"; ++ break; ++ } ++ return str; ++} ++ ++static void get_arg_value(char *str, char **arg, char **argval) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < strlen(str); i++) ++ if (!isprint(str[i])) ++ return; ++ ++ for (i = 0; i < strlen(str); i++) ++ if (str[i] == '=') ++ break; ++ ++ if (i < strlen(str)) { ++ str[i] = '\0'; ++ *argval = &str[i+1]; ++ } ++ *arg = str; ++} ++ ++static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals) ++{ ++ int len; ++ int i; ++ ++ len = sizeof(cmd->obuf); ++ ++ /* all command messages begin this way */ ++ snprintf(cmd->obuf, len, "%c%08x%c%1x%02x%08x%02x%s%02x%08x", ++ MOD_CMD, cmd->module_id, CMD_REQUEST, CLIF_MSG_VERSION, ++ cmd->cmd, cmd->ops, (unsigned int) strlen(cmd->ifname), ++ cmd->ifname, cmd->type, cmd->tlvid); ++#if PADDU ++ if (cmd->cmd == cmd_settlv) { ++ size_t len2 = 0; ++ /* ++ * Get total length and append it plus any args and argvals ++ * to the command message ++ */ ++ for (i = 0; i < argc; i++) { ++ if (args[i]) ++ len2 += 2 + strlen(args[i]); ++ if (argvals[i]) ++ len2 += 4 + strlen(argvals[i]); ++ } ++ snprintf(cmd->obuf + strlen(cmd->obuf), len - strlen(cmd->obuf), ++ "%04zx", len2); ++ } ++#endif ++ /* Add any args and argvals to the command message */ ++ for (i = 0; i < argc; i++) { ++ if (args[i]) ++ snprintf(cmd->obuf + strlen(cmd->obuf), ++ len - strlen(cmd->obuf), ++ "%02x%s", (unsigned int)strlen(args[i]), ++ args[i]); ++ if (argvals[i]) ++ snprintf(cmd->obuf + strlen(cmd->obuf), ++ len - strlen(cmd->obuf), "%04x%s", ++ (unsigned int)strlen(argvals[i]), argvals[i]); ++ } ++ return strlen(cmd->obuf); ++} ++ ++int vdp_clif_command(struct clif *, char *, int); ++ ++static int vdp_cmd_gettlv(struct clif *clif, int argc, char *argv[], ++ struct cmd *cmd, int raw) ++{ ++ int numargs = 0; ++ char **args; ++ char **argvals; ++ int i; ++ ++ if (cmd->cmd != cmd_gettlv) ++ return cmd_invalid; ++ ++ args = calloc(argc, sizeof(char *)); ++ if (!args) ++ return cmd_failed; ++ ++ argvals = calloc(argc, sizeof(char *)); ++ if (!argvals) { ++ free(args); ++ return cmd_failed; ++ } ++ ++ for (i = 0; i < argc; i++) ++ get_arg_value(argv[i], &args[i], &argvals[i]); ++ numargs = i; ++ ++ /* Default is local tlv query */ ++ if (!(cmd->ops & op_neighbor)) ++ cmd->ops |= op_local; ++ ++ if (numargs) { ++ /* Only commands with the config option should have arguments.*/ ++ if (!(cmd->ops & op_config)) { ++ printf("%s\n", print_status(cmd_invalid)); ++ goto out; ++ } ++ ++ /* Commands to get neighbor TLVs cannot have arguments. */ ++ if (cmd->ops & op_neighbor) { ++ printf("%s\n", print_status(cmd_invalid)); ++ goto out; ++ } ++ cmd->ops |= op_arg; ++ } ++ ++ for (i = 0; i < numargs; i++) { ++ if (argvals[i]) { ++ printf("%s\n", print_status(cmd_invalid)); ++ goto out; ++ } ++ } ++ ++ render_cmd(cmd, argc, args, argvals); ++ free(args); ++ free(argvals); ++ return vdp_clif_command(clif, cmd->obuf, raw); ++out: ++ free(args); ++ free(argvals); ++ return cmd_invalid; ++} ++ ++static int vdp_cmd_settlv(struct clif *clif, int argc, char *argv[], ++ struct cmd *cmd, int raw) ++{ ++ int numargs = 0; ++ char **args; ++ char **argvals; ++ int i; ++ ++ if (cmd->cmd != cmd_settlv) ++ return cmd_invalid; ++ args = calloc(argc, sizeof(char *)); ++ if (!args) ++ return cmd_failed; ++ ++ argvals = calloc(argc, sizeof(char *)); ++ if (!argvals) { ++ free(args); ++ return cmd_failed; ++ } ++ ++ for (i = 0; i < argc; i++) ++ get_arg_value(argv[i], &args[i], &argvals[i]); ++ numargs = i; ++ ++ for (i = 0; i < numargs; i++) { ++ if (!argvals[i]) { ++ printf("%s\n", print_status(cmd_invalid)); ++ goto out; ++ } ++ } ++ ++ if (numargs) ++ cmd->ops |= (op_arg | op_argval); ++ ++ render_cmd(cmd, argc, args, argvals); ++ free(args); ++ free(argvals); ++ return vdp_clif_command(clif, cmd->obuf, raw); ++out: ++ free(args); ++ free(argvals); ++ return cmd_invalid; ++} ++ ++static int hex2u8(char *b) ++{ ++ int hex = -1; ++ ++ if (isxdigit(*b) && isxdigit(*(b + 1))) ++ sscanf(b, "%02x", &hex); ++ return hex; ++} ++ ++static int hex2u16(char *b) ++{ ++ int hex = -1; ++ ++ if (isxdigit(*b) && isxdigit(*(b + 1)) && isxdigit(*(b + 2)) ++ && isxdigit(*(b + 3))) ++ sscanf(b, "%04x", &hex); ++ return hex; ++} ++ ++static int hex2u32(char *b) ++{ ++ int hex; ++ char *b_old = b; ++ ++ for (hex = 0; hex < 8; ++hex) ++ if (!isxdigit(*b++)) ++ return -1; ++ sscanf(b_old, "%08x", &hex); ++ return hex; ++} ++ ++static int vdp_parse_response(char *buf) ++{ ++ return hex2u8(buf + CLIF_STAT_OFF); ++} ++ ++static void print_pair(char *arg, size_t arglen, char *value, size_t valuelen) ++{ ++ while (arglen--) ++ putchar(*arg++); ++ putchar('='); ++ while (valuelen--) ++ putchar(*value++); ++ putchar('\n'); ++} ++ ++static int print_arg_value(char *ibuf) ++{ ++ int arglen, valuelen, offset = 0, ilen = strlen(ibuf); ++ char *arg, *value; ++ ++ while (offset < ilen) { ++ /* Length of argument */ ++ arglen = hex2u8(ibuf + offset); ++ if (arglen < 0) ++ break; ++ offset += 2; ++ arg = ibuf + offset; ++ offset += arglen; ++ ++ /* Length of argument value */ ++ valuelen = hex2u16(ibuf + offset); ++ if (valuelen < 0) ++ break; ++ offset += 4; ++ value = ibuf + offset; ++ offset += valuelen; ++ ++ print_pair(arg, arglen, value, valuelen); ++ } ++ return offset; ++} ++ ++static int get_tlvid(char *ibuf) ++{ ++ return hex2u32(ibuf); ++} ++ ++/* ++ * Print a TLV. ++ */ ++static void print_tlv2(char *ibuf) ++{ ++ size_t ilen = strlen(ibuf); ++ u16 tlv_type; ++ u16 tlv_len; ++ u32 tlvid; ++ int offset = 0; ++ int printed; ++ struct lldp_module *np; ++ ++ while (ilen > 0) { ++ tlv_len = 2 * sizeof(u16); ++ if (ilen < 2 * sizeof(u16)) { ++ printf("corrupted TLV ilen:%zd, tlv_len:%d\n", ++ ilen, tlv_len); ++ break; ++ } ++ tlv_type = hex2u16(ibuf + offset); ++ tlv_len = tlv_type; ++ tlv_type >>= 9; ++ tlv_len &= 0x01ff; ++ offset += 2 * sizeof(u16); ++ ilen -= 2 * sizeof(u16); ++ ++ if (ilen < (unsigned) 2 * tlv_len) { ++ printf("corrupted TLV ilen:%zd, tlv_len:%d\n", ++ ilen, tlv_len); ++ break; ++ } ++ tlvid = tlv_type; ++ if (tlvid == INVALID_TLVID) { ++ tlvid = get_tlvid(ibuf + offset); ++ offset += 8; ++ } ++ printed = 0; ++ LIST_FOREACH(np, &lldp_head, lldp) { ++ if (np->ops->print_tlv(tlvid, tlv_len, ibuf + offset)) { ++ printed = 1; ++ break; ++ } ++ } ++ ++ if (!printed) { ++ if (tlvid < INVALID_TLVID) ++ printf("Unidentified TLV\n\ttype:%d %*.*s\n", ++ tlv_type, tlv_len*2, tlv_len*2, ++ ibuf+offset); ++ else ++ printf("Unidentified Org Specific TLV\n\t" ++ "OUI: 0x%06x, Subtype: %d, Info: %*.*s\n", ++ tlvid >> 8, tlvid & 0x0ff, ++ tlv_len*2-8, tlv_len*2-8, ++ ibuf+offset); ++ } ++ if (tlvid > INVALID_TLVID) ++ offset += (2 * tlv_len - 8); ++ else ++ offset += 2 * tlv_len; ++ ilen -= 2 * tlv_len; ++ if (tlvid == END_OF_LLDPDU_TLV) ++ break; ++ } ++} ++ ++/* Print reply from get command */ ++static void print_tlvs(struct cmd *cmd, char *ibuf) ++{ ++ if (cmd->ops & op_config) { ++ print_arg_value(ibuf); ++ return; ++ } ++ print_tlv2(ibuf); ++} ++ ++static void print_cmd_response(char *ibuf, int status) ++{ ++ struct cmd cmd; ++ unsigned char len; ++ int ioff; ++ ++ if (status != cmd_success) { ++ printf("%s\n", print_status(status)); ++ return; ++ } ++ ++ cmd.cmd = hex2u8(ibuf + CMD_CODE); ++ cmd.ops = hex2u32(ibuf + CMD_OPS); ++ len = hex2u8(ibuf + CMD_IF_LEN); ++ ioff = CMD_IF; ++ if (len < sizeof(cmd.ifname)) { ++ memcpy(cmd.ifname, ibuf + CMD_IF, len); ++ } else { ++ printf("Response ifname too long: %*s\n", (int)len, cmd.ifname); ++ return; ++ } ++ cmd.ifname[len] = '\0'; ++ ioff += len; ++ ++ if (cmd.cmd == cmd_gettlv || cmd.cmd == cmd_settlv) { ++ cmd.tlvid = hex2u32(ibuf + ioff); ++ ioff += 2 * sizeof(cmd.tlvid); ++ } ++ ++ switch (cmd.cmd) { ++ case cmd_gettlv: ++ print_tlvs(&cmd, ibuf + ioff); ++ break; ++ case cmd_settlv: ++ printf("%s", ibuf + ioff); ++ break; ++ default: ++ return; ++ } ++} ++ ++static void vdp_print_response(char *buf, int status) ++{ ++ switch (buf[CLIF_RSP_OFF]) { ++ case PING_CMD: ++ if (status) ++ printf("FAILED:%s\n", print_status(status)); ++ else ++ printf("%s\n", buf + CLIF_RSP_OFF + 5); ++ break; ++ case ATTACH_CMD: ++ case DETACH_CMD: ++ if (status) ++ printf("FAILED:%s\n", print_status(status)); ++ else ++ printf("OK\n"); ++ break; ++ case CMD_REQUEST: ++ print_cmd_response(buf + CLIF_RSP_OFF, status); ++ break; ++ default: ++ printf("Unknown VDP command response: %s\n", buf); ++ break; ++ } ++} ++ ++static void vdp_print_event_msg(char *buf) ++{ ++ printf("%s buf:%s\n", __func__, buf); ++} ++ ++/* ++ * Dummy function to avoid linkage of many sources ++ */ ++int get_perm_hwaddr(UNUSED const char *ifname, UNUSED unsigned char *buf_perm, ++ UNUSED unsigned char *buf_san) ++{ ++ return -EIO; ++} ++ ++static int show_raw; ++ ++static const char *cli_version = ++ "vdptool v" LLDPTOOL_VERSION "\n" ++ "Copyright (c) 2014, IBM Corporation\n"; ++ ++ ++static const char *cli_license = ++"This program is free software. You can distribute it and/or modify it\n" ++"under the terms of the GNU General Public License version 2.\n" ++"\n"; ++/* ++"Alternatively, this software may be distributed under the terms of the\n" ++"BSD license. See README and COPYING for more details.\n"; ++*/ ++ ++static const char *cli_full_license = ++"This program is free software; you can redistribute it and/or modify\n" ++"it under the terms of the GNU General Public License version 2 as\n" ++"published by the Free Software Foundation.\n" ++"\n" ++"This program is distributed in the hope that it will be useful,\n" ++"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" ++"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" ++"GNU General Public License for more details.\n" ++"\n" ++"You should have received a copy of the GNU General Public License\n" ++"along with this program; if not, write to the Free Software\n" ++"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n" ++"\n" ++"Alternatively, this software may be distributed under the terms of the\n" ++"BSD license.\n" ++"\n" ++"Redistribution and use in source and binary forms, with or without\n" ++"modification, are permitted provided that the following conditions are\n" ++"met:\n" ++"\n" ++"1. Redistributions of source code must retain the above copyright\n" ++" notice, this list of conditions and the following disclaimer.\n" ++"\n" ++"2. Redistributions in binary form must reproduce the above copyright\n" ++" notice, this list of conditions and the following disclaimer in the\n" ++" documentation and/or other materials provided with the distribution.\n" ++"\n" ++"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" ++" names of its contributors may be used to endorse or promote products\n" ++" derived from this software without specific prior written permission.\n" ++"\n" ++"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" ++"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" ++"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" ++"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" ++"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" ++"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" ++"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" ++"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" ++"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" ++"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" ++"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" ++"\n"; ++ ++static const char *commands_usage = ++"Usage:\n" ++" vdptool [options] [arg] general command line usage format\n" ++" vdptool go into interactive mode\n" ++" [options] [arg] general interactive command format\n"; ++ ++static const char *commands_options = ++"Options:\n" ++" -i [ifname] network interface\n" ++" -V [tlvid] TLV identifier\n" ++" may be numeric or keyword (see below)\n" ++" -c used with get TLV command to specify\n" ++" that the list of configuration elements\n" ++" -n \"neighbor\" option for command (To be done)\n" ++" -r show raw message\n" ++" -R show only raw messages\n"; ++ ++static const char *commands_help = ++"Commands:\n" ++" license show license information\n" ++" -h|help show command usage information\n" ++" -v|version show version\n" ++" -p|ping ping lldpad and query pid of lldpad\n" ++" -q|quit exit lldptool (interactive mode)\n" ++" -t|get-tlv get tlvid value\n" ++" -T|set-tlv set arg for tlvid to value\n"; ++ ++static struct clif *clif_conn; ++static int cli_quit; ++static int cli_attached; ++ ++/* ++ * insert to head, so first one is last ++ */ ++struct lldp_module *(*register_tlv_table[])(void) = { ++ vdp22_cli_register, ++ NULL, ++}; ++ ++static void init_modules(void) ++{ ++ struct lldp_module *module; ++ struct lldp_module *premod = NULL; ++ int i = 0; ++ ++ LIST_INIT(&lldp_head); ++ for (i = 0; register_tlv_table[i]; i++) { ++ module = register_tlv_table[i](); ++ if (premod) ++ LIST_INSERT_AFTER(premod, module, lldp); ++ else ++ LIST_INSERT_HEAD(&lldp_head, module, lldp); ++ premod = module; ++ } ++} ++ ++void deinit_modules(void) ++{ ++ struct lldp_module *module; ++ ++ while (lldp_head.lh_first != NULL) { ++ module = lldp_head.lh_first; ++ LIST_REMOVE(lldp_head.lh_first, lldp); ++ module->ops->lldp_mod_unregister(module); ++ } ++} ++ ++static void usage(void) ++{ ++ fprintf(stderr, "%s\n", cli_version); ++ fprintf(stderr, "\n%s\n%s\n%s\n", ++ commands_usage, commands_options, commands_help); ++} ++ ++static void print_raw_message(char *msg, int print) ++{ ++ if (!print || !(print & SHOW_RAW)) ++ return; ++ ++ if (!(print & SHOW_RAW_ONLY)) { ++ switch (msg[MSG_TYPE]) { ++ case EVENT_MSG: ++ printf("event: "); ++ break; ++ case CMD_RESPONSE: ++ printf("rsp: "); ++ break; ++ default: ++ printf("cmd: "); ++ break; ++ } ++ } ++ printf("%s\n", msg); ++} ++ ++static int parse_print_message(char *msg, int print) ++{ ++ int status = 0; ++ ++ status = vdp_parse_response(msg); ++ print_raw_message(msg, print); ++ if (print & SHOW_RAW_ONLY) ++ return status; ++ ++ if (msg[MSG_TYPE] == CMD_RESPONSE) ++ vdp_print_response(msg, status); ++ else if (msg[MSG_TYPE] == MOD_CMD && msg[MOD_MSG_TYPE] == EVENT_MSG) ++ vdp_print_event_msg(&msg[MOD_MSG_TYPE]); ++ return status; ++} ++ ++static void cli_close_connection(void) ++{ ++ if (clif_conn == NULL) ++ return; ++ ++ if (cli_attached) { ++ clif_detach(clif_conn); ++ cli_attached = 0; ++ } ++ clif_close(clif_conn); ++ clif_conn = NULL; ++} ++ ++ ++static void cli_msg_cb(char *msg, UNUSED size_t len) ++{ ++ parse_print_message(msg, SHOW_OUTPUT | show_raw); ++} ++ ++ ++/* structure of the print argument bitmap: ++ * SHOW_NO_OUTPUT (0x0) - don't print anything for the command ++ * SHOW_OUTPUT (0x01) - print output for the command ++ * SHOW_RAW (0x02) - print the raw clif command messages ++ * SHOW_RAW_ONLY (0x04) - print only the raw clif command messages ++*/ ++static int _clif_command(struct clif *clif, char *cmd, int print) ++{ ++ char buf[MAX_CLIF_MSGBUF]; ++ size_t len; ++ int ret; ++ ++ print_raw_message(cmd, print); ++ ++ if (clif_conn == NULL) { ++ printf("Not connected to lldpad - command dropped.\n"); ++ return -1; ++ } ++ len = sizeof(buf) - 1; ++ ret = clif_request(clif, cmd, strlen(cmd), buf, &len, cli_msg_cb); ++ if (ret == -2) { ++ printf("'%s' command timed out.\n", cmd); ++ return -2; ++ } else if (ret < 0) { ++ printf("'%s' command failed.\n", cmd); ++ return -1; ++ } ++ if (print) { ++ buf[len] = '\0'; ++ ret = parse_print_message(buf, print); ++ } ++ ++ return ret; ++} ++ ++int vdp_clif_command(struct clif *clif, char *cmd, int raw) ++{ ++ return _clif_command(clif, cmd, SHOW_OUTPUT | raw); ++} ++ ++static int cli_cmd_ping(struct clif *clif, UNUSED int argc, UNUSED char *argv[], ++ UNUSED struct cmd *command, int raw) ++{ ++ return vdp_clif_command(clif, "P", raw); ++} ++ ++static int ++cli_cmd_nop(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[], ++ UNUSED struct cmd *command, UNUSED int raw) ++{ ++ return 0; ++} ++ ++static int ++cli_cmd_help(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[], ++ UNUSED struct cmd *command, UNUSED int raw) ++{ ++ struct lldp_module *np; ++ ++ printf("%s\n%s\n%s", commands_usage, commands_options, commands_help); ++ ++ printf("\nTLV identifiers:\n"); ++ LIST_FOREACH(np, &lldp_head, lldp) ++ if (np->ops->print_help) ++ np->ops->print_help(); ++ return 0; ++} ++ ++static int ++cli_cmd_version(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[], ++ UNUSED struct cmd *command, UNUSED int raw) ++{ ++ printf("%s\n", cli_version); ++ return 0; ++} ++ ++static int ++cli_cmd_license(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[], ++ UNUSED struct cmd *command, UNUSED int raw) ++{ ++ printf("%s\n", cli_full_license); ++ return 0; ++} ++ ++static int ++cli_cmd_quit(UNUSED struct clif *clif, UNUSED int argc, UNUSED char *argv[], ++ UNUSED struct cmd *command, UNUSED int raw) ++{ ++ cli_quit = 1; ++ return 0; ++} ++ ++static struct cli_cmd { ++ vdp22_cmd cmdcode; ++ const char *cmdstr; ++ int (*handler)(struct clif *clif, int argc, char *argv[], ++ struct cmd *cmd, int raw); ++} cli_commands[] = { ++ { cmd_ping, "ping", cli_cmd_ping }, ++ { cmd_help, "help", cli_cmd_help }, ++ { cmd_license, "license", cli_cmd_license }, ++ { cmd_version, "version", cli_cmd_version }, ++ { cmd_quit, "quit", cli_cmd_quit }, ++ { cmd_gettlv, "gettlv", vdp_cmd_gettlv }, ++ { cmd_gettlv, "get-tlv", vdp_cmd_gettlv }, ++ { cmd_settlv, "settlv", vdp_cmd_settlv }, ++ { cmd_settlv, "set-tlv", vdp_cmd_settlv }, ++ { cmd_nop, NULL, cli_cmd_nop } ++}; ++ ++u32 lookup_tlvid(char *tlvid_str) ++{ ++ struct lldp_module *np; ++ u32 tlvid = INVALID_TLVID; ++ ++ LIST_FOREACH(np, &lldp_head, lldp) { ++ if (np->ops->lookup_tlv_name) { ++ tlvid = np->ops->lookup_tlv_name(tlvid_str); ++ if (tlvid != INVALID_TLVID) ++ break; ++ } ++ } ++ ++ return tlvid; ++} ++ ++void print_args(int argc, char *argv[]) ++{ ++ int i; ++ ++ for (i = 0; i < argc; i++) ++ printf("\tremaining arg %d = %s\n", i, argv[i]); ++} ++ ++static struct option lldptool_opts[] = { ++ {"help", 0, NULL, 'h'}, ++ {"version", 0, NULL, 'v'}, ++ {"stats", 0, NULL, 'S'}, ++ {"get-tlv", 0, NULL, 't'}, ++ {"set-tlv", 0, NULL, 'T'}, ++ {"get-lldp", 0, NULL, 'l'}, ++ {"set-lldp", 0, NULL, 'L'}, ++ {0, 0, 0, 0} ++}; ++ ++static int request(struct clif *clif, int argc, char *argv[]) ++{ ++ struct cli_cmd *cmd, *match = NULL; ++ struct cmd command; ++ int count; ++ int ret = 0; ++ int newraw = 0; ++ int numargs = 0; ++ char **argptr = &argv[0]; ++ char *end; ++ int c; ++ int option_index; ++ ++ memset((void *)&command, 0, sizeof(command)); ++ command.cmd = cmd_nop; ++ command.type = NEAREST_CUSTOMER_BRIDGE; ++ command.module_id = LLDP_MOD_VDP22; ++ command.tlvid = INVALID_TLVID; ++ ++ opterr = 0; ++ for (;;) { ++ c = getopt_long(argc, argv, "i:tThcnvrRpqV:", ++ lldptool_opts, &option_index); ++ if (c < 0) ++ break; ++ switch (c) { ++ case '?': ++ printf("missing argument for option %s\n\n", ++ argv[optind-1]); ++ usage(); ++ return -1; ++ case 'i': ++ strncpy(command.ifname, optarg, IFNAMSIZ); ++ command.ifname[IFNAMSIZ] = '\0'; ++ break; ++ case 'V': ++ if (command.tlvid != INVALID_TLVID) { ++ printf("\nInvalid command: multiple TLV identifiers: %s\n", ++ optarg); ++ return -1; ++ } ++ ++ /* Currently tlvid unset lookup and verify parameter */ ++ errno = 0; ++ command.tlvid = strtoul(optarg, &end, 0); ++ if (!command.tlvid || errno || *end != '\0' || ++ end == optarg) ++ command.tlvid = lookup_tlvid(optarg); ++ if (command.tlvid == INVALID_TLVID) { ++ printf("\nInvalid TLV identifier: %s\n", ++ optarg); ++ return -1; ++ } ++ break; ++ case 'p': ++ command.cmd = cmd_ping; ++ break; ++ case 'q': ++ command.cmd = cmd_quit; ++ break; ++ case 't': ++ command.cmd = cmd_gettlv; ++ break; ++ case 'T': ++ command.cmd = cmd_settlv; ++ break; ++ case 'c': ++ command.ops |= op_config; ++ break; ++ case 'n': ++ command.ops |= op_neighbor; ++ break; ++ case 'h': ++ command.cmd = cmd_help; ++ break; ++ case 'r': ++ if (newraw) { ++ usage(); ++ return -1; ++ } ++ newraw = SHOW_RAW; ++ break; ++ case 'R': ++ if (newraw) { ++ usage(); ++ return -1; ++ } ++ newraw = (SHOW_RAW | SHOW_RAW_ONLY); ++ break; ++ case 'v': ++ command.cmd = cmd_version; ++ break; ++ default: ++ usage(); ++ ret = -1; ++ } ++ } ++ ++ /* if no command was supplied via an option flag, then ++ * the first remaining argument should be the command. ++ */ ++ count = 0; ++ if (command.cmd == cmd_nop && optind < argc) { ++ cmd = cli_commands; ++ while (cmd->cmdcode != cmd_nop) { ++ if (strncasecmp(cmd->cmdstr, argv[optind], ++ strlen(argv[optind])) == 0) { ++ match = cmd; ++ command.cmd = match->cmdcode; ++ count++; ++ } ++ cmd++; ++ } ++ } ++ ++ if (count > 1) { ++ printf("Ambiguous command '%s'; possible commands:", ++ argv[optind]); ++ cmd = cli_commands; ++ while (cmd->cmdstr) { ++ if (strncasecmp(cmd->cmdstr, argv[optind], ++ strlen(argv[optind])) == 0) ++ printf(" %s", cmd->cmdstr); ++ cmd++; ++ } ++ printf("\n"); ++ ret = -1; ++ } else { ++ if (!match) { ++ cmd = cli_commands; ++ while (cmd->cmdcode != command.cmd) ++ cmd++; ++ match = cmd; ++ } ++ numargs = argc-optind - count; ++ if (numargs) ++ argptr = &argv[argc-numargs]; ++ ret = match->handler(clif, numargs, argptr, &command, newraw); ++ } ++ return ret; ++} ++ ++static void cli_recv_pending(struct clif *clif, int in_read) ++{ ++ int first = 1; ++ ++ if (clif == NULL) ++ return; ++ while (clif_pending(clif)) { ++ char buf[256]; ++ size_t len = sizeof(buf) - 1; ++ if (clif_recv(clif, buf, &len) == 0) { ++ buf[len] = '\0'; ++ if (in_read && first) ++ printf("\n"); ++ first = 0; ++ cli_msg_cb(buf, len); ++ } else { ++ printf("Could not read pending message.\n"); ++ break; ++ } ++ } ++} ++ ++static char *do_readline(const char *prompt) ++{ ++ size_t size = 0; ++ ssize_t rc; ++ char *line = NULL; ++ ++ fputs(prompt, stdout); ++ fflush(stdout); ++ ++ rc = getline(&line, &size, stdin); ++ if (rc <= 0) ++ return NULL; ++ if (line[rc - 1] == '\n') ++ line[rc - 1] = 0; ++ return line; ++} ++ ++static void cli_interactive(void) ++{ ++ const int max_args = 20; ++ char *cmd, *argv[max_args], *pos; ++ int argc; ++ ++ setlinebuf(stdout); ++ printf("\nInteractive mode\n\n"); ++ do { ++ cli_recv_pending(clif_conn, 0); ++ alarm(1); ++ cmd = do_readline("> "); ++ alarm(0); ++ if (!cmd) ++ break; ++ argc = 1; ++ pos = cmd; ++ for (;;) { ++ while (*pos == ' ') ++ pos++; ++ if (*pos == '\0') ++ break; ++ argv[argc] = pos; ++ argc++; ++ if (argc == max_args) ++ break; ++ while (*pos != '\0' && *pos != ' ') ++ pos++; ++ if (*pos == ' ') ++ *pos++ = '\0'; ++ } ++ if (argc) { ++ optind = 0; ++ request(clif_conn, argc, argv); ++ } ++ free(cmd); ++ } while (!cli_quit); ++} ++ ++static void cli_terminate(UNUSED int sig) ++{ ++ cli_close_connection(); ++ exit(0); ++} ++ ++static void cli_alarm(UNUSED int sig) ++{ ++ if (clif_conn && _clif_command(clif_conn, "P", SHOW_NO_OUTPUT)) { ++ printf("Connection to lldpad lost - trying to reconnect\n"); ++ cli_close_connection(); ++ } ++ if (!clif_conn) { ++ clif_conn = clif_open(); ++ if (clif_conn) { ++ char attach_str[9] = ""; ++ u32 mod_id = LLDP_MOD_VDP22; ++ bin2hexstr((u8 *)&mod_id, 4, attach_str, 8); ++ printf("Connection to lldpad re-established\n"); ++ if (clif_attach(clif_conn, attach_str) == 0) ++ cli_attached = 1; ++ else ++ printf("Warning: Failed to attach to lldpad.\n"); ++ } ++ } ++ if (clif_conn) ++ cli_recv_pending(clif_conn, 1); ++ alarm(1); ++} ++ ++ ++int main(int argc, char *argv[]) ++{ ++ int interactive = 1; ++ int warning_displayed = 0; ++ int ret = 0; ++ ++ if (argc > 1) ++ interactive = 0; ++ if (interactive) ++ printf("%s\n\n%s\n\n", cli_version, cli_license); ++ for (;;) { ++ clif_conn = clif_open(); ++ if (clif_conn) { ++ if (warning_displayed) ++ printf("Connection established.\n"); ++ break; ++ } ++ ++ if (!interactive) { ++ perror("Failed to connect to lldpad - clif_open"); ++ return -1; ++ } ++ ++ if (!warning_displayed) { ++ printf("Could not connect to lldpad - re-trying\n"); ++ warning_displayed = 1; ++ } ++ sleep(1); ++ } ++ ++ init_modules(); ++ signal(SIGINT, cli_terminate); ++ signal(SIGTERM, cli_terminate); ++ signal(SIGALRM, cli_alarm); ++ ++ if (interactive) { ++ char attach_str[9] = ""; ++ u32 mod_id = LLDP_MOD_VDP22; ++ bin2hexstr((u8 *)&mod_id, 4, attach_str, 8); ++ if (clif_attach(clif_conn, attach_str) == 0) ++ cli_attached = 1; ++ else ++ printf("Warning: Failed to attach to lldpad.\n"); ++ cli_interactive(); ++ } else { ++ ret = request(clif_conn, argc, &argv[0]); ++ ret = !!ret; ++ } ++ cli_close_connection(); ++ deinit_modules(); ++ return ret; ++} +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-20-lldp-automake-fix-drop-prefix-on-vdptool_LDADD.patch b/open-lldp-v1.0.1-20-lldp-automake-fix-drop-prefix-on-vdptool_LDADD.patch new file mode 100644 index 0000000..eb1ff0f --- /dev/null +++ b/open-lldp-v1.0.1-20-lldp-automake-fix-drop-prefix-on-vdptool_LDADD.patch @@ -0,0 +1,34 @@ +From 7a7150e3e6443e2fff0f3967995fa16a4b8665d7 Mon Sep 17 00:00:00 2001 +From: John Fastabend +Date: Fri, 30 Jan 2015 08:55:00 -0800 +Subject: [PATCH] lldp: automake fix, drop prefix on vdptool_LDADD + +Add another fix to the Makefile to drop prefix in vdptool_LDADD +this resolves the following error from 'make distcheck' + +libtool: link: cannot find the library `../liblldp_clif.la' or unhandled argument `../liblldp_clif.la' +make[1]: *** [vdptool] Error 1 +make[1]: Leaving directory `/home/john/git/lldp/lldpad/lldpad-1.0.1/_build' +make: *** [distcheck] Error 1 + +Signed-off-by: John Fastabend +--- + Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index b1c381b..84d68ee 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -82,7 +82,7 @@ liblldp_clif_includedir = ${srcdir}/include + liblldp_clif_la_SOURCES = clif.c + + vdptool_SOURCES = vdptool.c lldp_util.c qbg/vdp22_clif.c vdptool_cisco_oui.c +-vdptool_LDADD = ${srcdir}/liblldp_clif.la ++vdptool_LDADD = liblldp_clif.la + vdptool_LDFLAGS = -llldp_clif $(LIBNL_LIBS) + + dcbtool_SOURCES = dcbtool.c dcbtool_cmds.c parse_cli.l \ +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-21-lldpad-Fix-DCBX-event-generation-from-lldpad.patch b/open-lldp-v1.0.1-21-lldpad-Fix-DCBX-event-generation-from-lldpad.patch new file mode 100644 index 0000000..735cc3d --- /dev/null +++ b/open-lldp-v1.0.1-21-lldpad-Fix-DCBX-event-generation-from-lldpad.patch @@ -0,0 +1,141 @@ +From 9ad33e441e018352a95621f2cecfb31234bd6b00 Mon Sep 17 00:00:00 2001 +From: Neerav Parikh +Date: Fri, 20 Mar 2015 05:38:09 +0000 +Subject: [PATCH] lldpad: Fix DCBX event generation from lldpad + +Whenever there is a change in LLDP TLVs lldpad notifies clients that +may have registered for event notification based on TLV type. +For legacy clients like "fcoemon" lldpad by default registers them +for any changes to CEE DCBX TLV type; when such clients attach to +lldpad clif interface. + +Now, the lldpad code that registers such clients for CEE DCBX TLV +types is not generating correct DCBX TLV module id when it registers +these clients for change event notification. Hence, whenever there +is a change in such TLVs lldpad determines that the client is not +registered for CEE DCBX TLV change notification and does not notify +these clients. + +These results in clients not taking appropriate actions based on +changes to CEE DCBX TLVs. + +The patch fixes the issue by setting the correct module id value for +the CEE DCBX for legacy clients like "fcoemon". + +Tested-by: Jack Morgan +Signed-off-by: Neerav Parikh +Signed-off-by: John Fastabend +--- + ctrl_iface.c | 68 +++++++++++++++++++++++++++++++----------------------------- + lldpad.c | 2 ++ + 2 files changed, 37 insertions(+), 33 deletions(-) + +diff --git a/ctrl_iface.c b/ctrl_iface.c +index e4fd0b7..1734f49 100644 +--- a/ctrl_iface.c ++++ b/ctrl_iface.c +@@ -173,46 +173,44 @@ int clif_iface_attach(struct clif_data *clifd, + */ + /* set default string to DCBX Events */ + if (ibuf[1] == '\0') { +- u32 hex = LLDP_MOD_DCBX; +- tlv = malloc(sizeof(char) * (8 + 2)); +- if (!tlv) ++ dst->tlv_types = malloc(sizeof(u32) * 2); ++ if (!dst->tlv_types) + goto err_tlv; +- tlv[0] = 'A'; +- tlv[9] = 0; +- bin2hexstr((u8*)&hex, 4, &tlv[1], 8); +- } else ++ dst->tlv_types[0] = LLDP_MOD_DCBX; ++ /* Insert Termination Pattern */ ++ dst->tlv_types[1] = ~0; ++ } else { + tlv = strdup(ibuf); +- +- str = tlv; +- str++; +- /* Count number of TLV Modules */ +- tokenize = strtok(str, delim); +- tlv_count++; +- do { +- tokenize = strtok(NULL, delim); ++ str = tlv; ++ str++; ++ /* Count number of TLV Modules */ ++ tokenize = strtok(str, delim); + tlv_count++; +- } while (tokenize); ++ do { ++ tokenize = strtok(NULL, delim); ++ tlv_count++; ++ } while (tokenize); + +- dst->tlv_types = malloc(sizeof(u32) * tlv_count); +- if (!dst->tlv_types) +- goto err_types; +- memset(dst->tlv_types, 0, sizeof(u32) * tlv_count); +- +- /* Populate tlv_types from comma separated string */ +- tokenize = strtok(str, delim); +- for (i=0; tokenize; i++) { +- char *myend; +- +- dst->tlv_types[i] = strtol(tokenize, &myend, 16); +- if (*myend) /* No hexnumber for module id */ ++ dst->tlv_types = malloc(sizeof(u32) * tlv_count); ++ if (!dst->tlv_types) + goto err_types; +- tokenize = strtok(NULL, delim); ++ memset(dst->tlv_types, 0, sizeof(u32) * tlv_count); ++ ++ /* Populate tlv_types from comma separated string */ ++ tokenize = strtok(str, delim); ++ for (i = 0; tokenize; i++) { ++ char *myend; ++ ++ dst->tlv_types[i] = strtol(tokenize, &myend, 16); ++ if (*myend) /* No hexnumber for module id */ ++ goto err_types; ++ tokenize = strtok(NULL, delim); ++ } ++ free(tlv); ++ /* Insert Termination Pattern */ ++ dst->tlv_types[i] = ~0; + } + +- /* Insert Termination Pattern */ +- dst->tlv_types[i] = ~0; +- free(tlv); +- + /* Insert new node at beginning */ + dst->next = clifd->ctrl_dst; + clifd->ctrl_dst = dst; +@@ -595,6 +593,10 @@ void ctrl_iface_send(struct clif_data *clifd, int level, u32 moduleid, + dst->addrlen); + } + } else { ++ fprintf(stderr, ++ "CTRL_IFACE monitor[%d][%d] %d:%s: ", ++ idx, clifd->ctrl_sock, dst->addrlen, ++ dst->addr.sun_path); + dst->errors = 0; + } + } +diff --git a/lldpad.c b/lldpad.c +index 406dcd5..72ab69d 100644 +--- a/lldpad.c ++++ b/lldpad.c +@@ -150,6 +150,8 @@ void send_event(int level, u32 moduleid, char *msg) + { + struct clif_data *cd = NULL; + ++ LLDPAD_DBG("lldpad: send_event level=%d moduleid=%d msg=%s\n", ++ level, moduleid, msg); + cd = (struct clif_data *) eloop_get_user_data(); + if (cd) + ctrl_iface_send(cd, level, moduleid, msg, strlen(msg)); +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-22-vdp-Fixed-the-memory-leak-for-modify-VSI-support-for.patch b/open-lldp-v1.0.1-22-vdp-Fixed-the-memory-leak-for-modify-VSI-support-for.patch new file mode 100644 index 0000000..3285467 --- /dev/null +++ b/open-lldp-v1.0.1-22-vdp-Fixed-the-memory-leak-for-modify-VSI-support-for.patch @@ -0,0 +1,223 @@ +From 73e0c42cc00f537fee1f58e5475cab1f2193e3cc Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Fri, 10 Apr 2015 09:03:24 +0000 +Subject: [PATCH] vdp: Fixed the memory leak for modify VSI, support for OUI + modify + +This patch has a fix for freeing the memory after a VSI update. +Support for modifying the OUI parameters have been added +to the infra. +Cisco specific handler is also added to support OUI modify. + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + include/qbg_vdp22.h | 2 +- + include/qbg_vdp22_oui.h | 3 +++ + include/vdp_cisco.h | 2 ++ + qbg/vdp22.c | 5 +++-- + qbg/vdp22cisco_oui.c | 44 +++++++++++++++++++++++++++++++++++++++++--- + qbg/vdp22sm.c | 35 ++++++++++++++++++++++++++++++++--- + 6 files changed, 82 insertions(+), 9 deletions(-) + +diff --git a/include/qbg_vdp22.h b/include/qbg_vdp22.h +index 6585a10..b1896a5 100644 +--- a/include/qbg_vdp22.h ++++ b/include/qbg_vdp22.h +@@ -181,7 +181,7 @@ void vdp22_stop(char *); + int vdp22_from_ecp22(struct vdp22 *); + int vdp22_query(const char *); + struct vdp22 *vdp22_getvdp(const char *); +-int vdp22_addreq(struct vsi22 *, struct vdp22 *); ++int vdp22_addreq(struct vsi22 *, struct vdp22 *, bool *); + int vdp22_nlback(struct vsi22 *); + int vdp22_clntback(struct vsi22 *); + struct vsi22 *vdp22_copy_vsi(struct vsi22 *); +diff --git a/include/qbg_vdp22_oui.h b/include/qbg_vdp22_oui.h +index 923e19f..d60075d 100644 +--- a/include/qbg_vdp22_oui.h ++++ b/include/qbg_vdp22_oui.h +@@ -82,6 +82,9 @@ struct vdp22_oui_handler_s { + /* This handler converts the vdpnl structure to vsi22 structure */ + bool (*vdpnl2vsi22_hndlr)(void *, struct vdpnl_oui_data_s *, + struct vdp22_oui_data_s *); ++ /* This handler modifies the existing OUI parameters */ ++ bool (*vsi22_mod_hndlr)(void *, struct vdp22_oui_data_s *, ++ struct vdp22_oui_data_s *); + /* This handler converts the vdpnl structure to string */ + bool (*vdpnl2str_hndlr)(struct vdpnl_oui_data_s *, char *, + int *, int); +diff --git a/include/vdp_cisco.h b/include/vdp_cisco.h +index 821db68..4abe802 100644 +--- a/include/vdp_cisco.h ++++ b/include/vdp_cisco.h +@@ -113,6 +113,8 @@ bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *, char *); + bool cisco_vdp_free_oui(struct vdp22_oui_data_s *); + bool cisco_vdpnl2vsi22_hndlr(void *, struct vdpnl_oui_data_s *, + struct vdp22_oui_data_s *); ++bool cisco_vsi22_mod_hndlr(void *, struct vdp22_oui_data_s *, ++ struct vdp22_oui_data_s *); + bool cisco_vdpnl2str_hndlr(struct vdpnl_oui_data_s *, char *, int *, int); + bool cisco_vsi2vdpnl_hndlr(void *, struct vdp22_oui_data_s *, + struct vdpnl_oui_data_s *); +diff --git a/qbg/vdp22.c b/qbg/vdp22.c +index 10b80a4..8f14fdd 100644 +--- a/qbg/vdp22.c ++++ b/qbg/vdp22.c +@@ -900,6 +900,7 @@ int vdp22_request(struct vdpnl_vsi *vsi, int clif) + int rc; + struct vsi22 *p; + struct vdp22 *vdp; ++ bool modf_vsi = false; + + LLDPAD_DBG("%s:%s clif:%d\n", __func__, vsi->ifname, clif); + vdp = vdp22_findif(vsi->ifname, NULL); +@@ -917,8 +918,8 @@ int vdp22_request(struct vdpnl_vsi *vsi, int clif) + vsi->request += 1; + p = vdp22_alloc_vsi_int(vsi, vdp, &rc, true); + if (p) { +- rc = vdp22_addreq(p, vdp); +- if (rc) ++ rc = vdp22_addreq(p, vdp, &modf_vsi); ++ if (rc || modf_vsi) + vdp22_delete_vsi(p); + } + } else +diff --git a/qbg/vdp22cisco_oui.c b/qbg/vdp22cisco_oui.c +index 272d480..da6ce24 100644 +--- a/qbg/vdp22cisco_oui.c ++++ b/qbg/vdp22cisco_oui.c +@@ -34,8 +34,9 @@ + + struct vdp22_oui_handler_s cisco_oui_hndlr = { + {0x00, 0x00, 0x0c}, "cisco", cisco_str2vdpnl_hndlr, +- cisco_vdpnl2vsi22_hndlr, cisco_vdpnl2str_hndlr, +- cisco_vsi2vdpnl_hndlr, cisco_vdp_tx_hndlr, cisco_vdp_rx_hndlr, ++ cisco_vdpnl2vsi22_hndlr, cisco_vsi22_mod_hndlr, ++ cisco_vdpnl2str_hndlr, cisco_vsi2vdpnl_hndlr, ++ cisco_vdp_tx_hndlr, cisco_vdp_rx_hndlr, + cisco_vdp_free_oui, cisco_vdp_oui_ptlvsize}; + + /* +@@ -104,9 +105,11 @@ bool cisco_str2vdpnl_hndlr(struct vdpnl_oui_data_s *vdp_oui_p, char *token) + } + strncpy(uuid, token, data_len); + if (oui_vdp_str2uuid(vdp_cisco_oui_p->uuid, uuid, +- sizeof(vdp_cisco_oui_p->uuid))) ++ sizeof(vdp_cisco_oui_p->uuid))) { + memset(vdp_cisco_oui_p->uuid, 0, + sizeof(vdp_cisco_oui_p->uuid)); ++ vdp_cisco_oui_p->uuid_set = false; ++ } else + vdp_cisco_oui_p->uuid_set = true; + free(uuid); + break; +@@ -177,6 +180,41 @@ bool cisco_vdpnl2vsi22_hndlr(void *vsi_data, struct vdpnl_oui_data_s *from, + } + + /* ++ * This converts modifies the existing OUI parameters ++ */ ++ ++bool cisco_vsi22_mod_hndlr(UNUSED void *vsi_data, struct vdp22_oui_data_s *from, ++ struct vdp22_oui_data_s *to) ++{ ++ vdp_cisco_oui_t *from_oui; ++ vdp_cisco_oui_t *to_oui; ++ ++ from_oui = (vdp_cisco_oui_t *)from->data; ++ to_oui = (vdp_cisco_oui_t *)to->data; ++ if ((!from_oui) || (!to_oui)) { ++ LLDPAD_DBG("%s: NULL OUI data\n", __func__); ++ return false; ++ } ++ if (from_oui->vm_name_len != 0) { ++ to_oui->vm_name_len = from_oui->vm_name_len; ++ strncpy(to_oui->vm_name, from_oui->vm_name, ++ to_oui->vm_name_len); ++ } ++ /* UUID can be modified only if not set */ ++ if (!to_oui->uuid_set) { ++ memcpy(to_oui->uuid, from_oui->uuid, sizeof(to_oui->uuid)); ++ to_oui->uuid_set = true; ++ } ++ if (from_oui->vm_addr_len != 0) { ++ to_oui->vm_addr_len = from_oui->vm_addr_len; ++ to_oui->afi = from_oui->afi; ++ memcpy(&(to_oui->l3_addr), &(from_oui->l3_addr), ++ sizeof(to_oui->l3_addr)); ++ } ++ return true; ++} ++ ++/* + * This function converts the OUI information from vdpnl struct to string + */ + +diff --git a/qbg/vdp22sm.c b/qbg/vdp22sm.c +index 14356ac..be838a9 100644 +--- a/qbg/vdp22sm.c ++++ b/qbg/vdp22sm.c +@@ -184,10 +184,36 @@ static inline size_t vsi22_ptlv_sz(struct vsi22 *vp) + } + + /* ++ * This function modifies the existing OUI parameters in a VSI. ++ */ ++static void vdp22_modoui(struct vsi22 *p, struct vsi22 *vsip) ++{ ++ struct vdp22_oui_handler_s *oui_hndlr; ++ int idx, inn_idx, ret; ++ ++ for (idx = 0; idx < vsip->no_ouidata; idx++) { ++ struct vdp22_oui_data_s *from = &vsip->oui_str_data[idx]; ++ ++ for (inn_idx = 0; inn_idx < p->no_ouidata; inn_idx++) { ++ struct vdp22_oui_data_s *to = &p->oui_str_data[inn_idx]; ++ ++ if (!strncmp(to->oui_name, from->oui_name, ++ sizeof(to->oui_name))) { ++ oui_hndlr = vdp22_get_oui_hndlr(to->oui_name); ++ ret = oui_hndlr->vsi22_mod_hndlr(p, from, to); ++ if (!ret) ++ LLDPAD_ERR("%s: handler return error for oui %s\n", ++ __func__, from->oui_name); ++ return; ++ } ++ } ++ } ++} ++ ++/* + * This function calls the registered OUI handlers that returns the size of + * the OUI data. + */ +- + static inline size_t oui22_ptlv_sz(struct vsi22 *vp) + { + struct vdp22_oui_handler_s *oui_hndlr; +@@ -1054,7 +1080,7 @@ bool vdp22_cmp_fdata(struct vsi22 *p, struct vsi22 *vsip) + /* + * Handle a new request. + */ +-int vdp22_addreq(struct vsi22 *vsip, struct vdp22 *vdp) ++int vdp22_addreq(struct vsi22 *vsip, struct vdp22 *vdp, bool *modf_vsi) + { + int rc = 0; + struct vsi22 *p; +@@ -1094,8 +1120,11 @@ int vdp22_addreq(struct vsi22 *vsip, struct vdp22 *vdp) + LLDPAD_DBG("%s:%s TODO mismatch filter data [%02x]\n", + __func__, vsip->vdp->ifname, vsip->vsi[0]); + rc = -EINVAL; +- } else ++ } else { ++ vdp22_modoui(p, vsip); + rc = vdp22_modvsi(p, vsip->vsi_mode); ++ *modf_vsi = true; ++ } + } + out: + LLDPAD_DBG("%s:%s rc:%d\n", __func__, vsip->vdp->ifname, rc); +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-23-lldp-make-TTL-TLV-configurable.patch b/open-lldp-v1.0.1-23-lldp-make-TTL-TLV-configurable.patch new file mode 100644 index 0000000..51cbc9b --- /dev/null +++ b/open-lldp-v1.0.1-23-lldp-make-TTL-TLV-configurable.patch @@ -0,0 +1,312 @@ +From 986eb2e84fd3339a30a4ab09c6d788c63236fed6 Mon Sep 17 00:00:00 2001 +From: Gary Loughnane +Date: Tue, 21 Apr 2015 17:45:41 +0000 +Subject: [PATCH] lldp: make TTL TLV configurable + +This allows the TTL TLV to be configured. + +Currently the Time To Live TLV is a static value set to 120 seconds. +LLDP specification says this can be a value of between 0 and 65535 +seconds. This patch makes the TTL TLV a configurable entity. + +Signed-off-by: Gary Loughnane +Signed-off-by: John Fastabend +--- + include/lldp_mand.h | 1 + + include/lldp_mand_cmds.h | 4 +++ + lldp/agent.c | 2 +- + lldp/ports.c | 3 +- + lldp/states.h | 2 +- + lldp/tx.c | 30 ++++++++++++++-- + lldp_mand.c | 21 ++++++++--- + lldp_mand_cmds.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++ + 8 files changed, 141 insertions(+), 12 deletions(-) + +diff --git a/include/lldp_mand.h b/include/lldp_mand.h +index 9154b7c..fc21ede 100644 +--- a/include/lldp_mand.h ++++ b/include/lldp_mand.h +@@ -93,4 +93,5 @@ void mand_unregister(struct lldp_module *mod); + struct packed_tlv *mand_gettlv(struct port *, struct lldp_agent *); + void mand_ifdown(char *, struct lldp_agent *); + void mand_ifup(char *, struct lldp_agent *); ++void mand_update_ttl(const char *, u16); + #endif /* _LLDP_MAND_H */ +diff --git a/include/lldp_mand_cmds.h b/include/lldp_mand_cmds.h +index aacac7c..8effc6e 100644 +--- a/include/lldp_mand_cmds.h ++++ b/include/lldp_mand_cmds.h +@@ -28,6 +28,10 @@ + #define _LLDP_MAND_CMDS_H + + #define ARG_MAND_SUBTYPE "subtype" ++#define ARG_TTL_VALUE "value" ++ ++#define TTL_MIN_VAL 0x0 ++#define TTL_MAX_VAL 0xFFFF + + struct arg_handlers *mand_get_arg_handlers(); + +diff --git a/lldp/agent.c b/lldp/agent.c +index 4bc5394..73ab054 100644 +--- a/lldp/agent.c ++++ b/lldp/agent.c +@@ -101,7 +101,7 @@ void lldp_init_agent(struct port *port, struct lldp_agent *agent, int type) + + /* init TX path */ + txInitializeTimers(agent); +- txInitializeLLDP(agent); ++ txInitializeLLDP(port, agent); + } + + int lldp_add_agent(const char *ifname, enum agent_type type) +diff --git a/lldp/ports.c b/lldp/ports.c +index 3bd6a2a..6384f14 100644 +--- a/lldp/ports.c ++++ b/lldp/ports.c +@@ -230,7 +230,6 @@ int reinit_port(const char *ifname) + /* Reset relevant state variables */ + agent->tx.state = TX_LLDP_INITIALIZE; + agent->rx.state = LLDP_WAIT_PORT_OPERATIONAL; +- agent->tx.txTTL = 0; + agent->msap.length1 = 0; + agent->msap.msap1 = NULL; + agent->msap.length2 = 0; +@@ -243,7 +242,7 @@ int reinit_port(const char *ifname) + + /* init TX path */ + txInitializeTimers(agent); +- txInitializeLLDP(agent); ++ txInitializeLLDP(port, agent); + } + + return 0; +diff --git a/lldp/states.h b/lldp/states.h +index fa5f11f..7cf69b8 100644 +--- a/lldp/states.h ++++ b/lldp/states.h +@@ -52,7 +52,7 @@ enum { + * The txInitializeLLDP () procedure initializes the LLDP transmit module as + * defined in 10.1.1. + */ +-void txInitializeLLDP(struct lldp_agent *agent); ++void txInitializeLLDP(struct port *port, struct lldp_agent *agent); + + /** + * The mibConstrInfoLLDPDU () procedure constructs an information LLDPDU as +diff --git a/lldp/tx.c b/lldp/tx.c +index 69c1a1a..c3a5c62 100644 +--- a/lldp/tx.c ++++ b/lldp/tx.c +@@ -34,6 +34,8 @@ + #include "lldp_tlv.h" + #include "lldp_mod.h" + #include "lldp_mand.h" ++#include "config.h" ++#include "lldp_mand_clif.h" + + bool mibConstrInfoLLDPDU(struct port *port, struct lldp_agent *agent) + { +@@ -110,7 +112,29 @@ error: + return false; + } + +-void txInitializeLLDP(struct lldp_agent *agent) ++static u16 get_ttl_init_val(char *ifname, struct lldp_agent *agent) ++{ ++ u16 ttl; ++ int config_ttl; ++ int read_config_err; ++ char arg_path[512] = { 0 }; ++ ++ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", ++ TLVID_PREFIX, ++ TLVID_NOUI(TIME_TO_LIVE_TLV), ++ ARG_TTL_VALUE); ++ read_config_err = get_config_setting(ifname, agent->type, ++ arg_path, &config_ttl, CONFIG_TYPE_INT); ++ ++ if (read_config_err) ++ ttl = DEFAULT_TX_HOLD * DEFAULT_TX_INTERVAL; ++ else ++ ttl = (u16)(config_ttl); ++ ++ return ttl; ++} ++ ++void txInitializeLLDP(struct port *port, struct lldp_agent *agent) + { + if (agent->tx.frameout) { + free(agent->tx.frameout); +@@ -125,7 +149,7 @@ void txInitializeLLDP(struct lldp_agent *agent) + agent->timers.msgTxInterval = DEFAULT_TX_INTERVAL; + agent->timers.msgFastTx = FAST_TX_INTERVAL; + +- agent->tx.txTTL = 0; ++ agent->tx.txTTL = get_ttl_init_val(port->ifname, agent); + agent->msap.length1 = 0; + agent->msap.msap1 = NULL; + agent->msap.length2 = 0; +@@ -240,7 +264,7 @@ void run_tx_sm(struct port *port, struct lldp_agent *agent) + do { + switch(agent->tx.state) { + case TX_LLDP_INITIALIZE: +- txInitializeLLDP(agent); ++ txInitializeLLDP(port, agent); + break; + case TX_IDLE: + process_tx_idle(agent); +diff --git a/lldp_mand.c b/lldp_mand.c +index b269d3f..652a454 100644 +--- a/lldp_mand.c ++++ b/lldp_mand.c +@@ -446,11 +446,7 @@ static int mand_bld_ttl_tlv(struct mand_data *md, struct lldp_agent *agent) + } + memset(tlv->info, 0, tlv->length); + +- if (agent->tx.txTTL) +- ttl = htons(agent->tx.txTTL); +- else +- ttl = htons(DEFAULT_TX_HOLD * DEFAULT_TX_INTERVAL); +- ++ ttl = htons(agent->tx.txTTL); + memcpy(tlv->info, &ttl, tlv->length); + LLDPAD_DBG("%s:%s:done:type=%d length=%d ttl=%d\n", __func__, + md->ifname, tlv->type, tlv->length, ntohs(ttl)); +@@ -685,3 +681,18 @@ void mand_unregister(struct lldp_module *mod) + free(mod); + LLDPAD_INFO("%s:done\n", __func__); + } ++ ++void mand_update_ttl(const char *ifname, u16 ttl_val) ++{ ++ struct port *port = port_find_by_ifindex(get_ifidx(ifname)); ++ struct lldp_agent *agent; ++ ++ if (!port) ++ return; ++ ++ LIST_FOREACH(agent, &port->agent_head, entry) { ++ agent->tx.txTTL = ttl_val; ++ agent->tx.localChange = 1; ++ agent->tx.txFast = agent->timers.txFastInit; ++ } ++} +diff --git a/lldp_mand_cmds.c b/lldp_mand_cmds.c +index 532337b..7d24bf8 100644 +--- a/lldp_mand_cmds.c ++++ b/lldp_mand_cmds.c +@@ -58,6 +58,11 @@ static int get_mand_subtype(struct cmd *, char *, char *, char *, int); + static int set_mand_subtype(struct cmd *, char *, char *, char *, int); + static int test_mand_subtype(struct cmd *, char *, char *, char *, int); + ++ ++static int get_mand_ttl_value(struct cmd *, char *, char *, char *, int); ++static int set_mand_ttl_value(struct cmd *, char *, char *, char *, int); ++static int test_mand_ttl_value(struct cmd *, char *, char *, char *, int); ++ + static struct arg_handlers arg_handlers[] = { + { .arg = ARG_ADMINSTATUS, .arg_class = LLDP_ARG, + .handle_get = get_arg_adminstatus, +@@ -72,6 +77,11 @@ static struct arg_handlers arg_handlers[] = { + .handle_get = get_mand_subtype, + .handle_set = set_mand_subtype, + .handle_test = test_mand_subtype, }, ++ { .arg = ARG_TTL_VALUE, ++ .arg_class = TLV_ARG, ++ .handle_get = get_mand_ttl_value, ++ .handle_set = set_mand_ttl_value, ++ .handle_test = test_mand_ttl_value, }, + { .arg = 0 } + }; + +@@ -271,6 +281,86 @@ static int _set_mand_subtype(struct cmd *cmd, char *arg, char *argvalue, + return 0; + } + ++static int get_mand_ttl_value(struct cmd *cmd, char *arg, ++ UNUSED char *argvalue, char *obuf, int obuf_len) ++{ ++ int ttl_val; ++ char string[8], arg_path[256]; ++ ++ if (cmd->cmd != cmd_gettlv) ++ return cmd_invalid; ++ ++ switch (cmd->tlvid) { ++ case TIME_TO_LIVE_TLV: ++ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", ++ TLVID_PREFIX, TLVID_NOUI(TIME_TO_LIVE_TLV), ++ ARG_TTL_VALUE); ++ get_config_setting(cmd->ifname, cmd->type, arg_path, ++ &ttl_val, CONFIG_TYPE_INT); ++ break; ++ case INVALID_TLVID: ++ return cmd_invalid; ++ default: ++ return cmd_not_applicable; ++ } ++ ++ snprintf(string, sizeof(string), "%d", ttl_val); ++ snprintf(obuf, obuf_len, "%02x%s%04x%s", ++ (unsigned int) strlen(arg), arg, ++ (unsigned int)strlen(string), string); ++ ++ return 0; ++} ++ ++static int _set_mand_ttl_value(struct cmd *cmd, char *arg, char *argvalue, ++ char *obuf, int obuf_len, bool test) ++{ ++ int ttl_val; ++ char *end; ++ char arg_path[256]; ++ ++ if (cmd->cmd != cmd_settlv) ++ return cmd_invalid; ++ ++ switch (cmd->tlvid) { ++ case TIME_TO_LIVE_TLV: ++ break; ++ case INVALID_TLVID: ++ return cmd_invalid; ++ default: ++ return cmd_not_applicable; ++ } ++ ++ ttl_val = strtoul(argvalue, &end, 0); ++ if ((*end) || (TTL_MIN_VAL > ttl_val) || (ttl_val > TTL_MAX_VAL)) ++ return cmd_bad_params; ++ ++ if (test) ++ return cmd_success; ++ ++ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", TLVID_PREFIX, ++ cmd->tlvid, arg); ++ snprintf(obuf, obuf_len, "%s=%s\n", arg, argvalue); ++ set_config_setting(cmd->ifname, cmd->type, ++ arg_path, &ttl_val, CONFIG_TYPE_INT); ++ ++ mand_update_ttl(cmd->ifname, ttl_val); ++ ++ return 0; ++} ++ ++static int set_mand_ttl_value(struct cmd *cmd, char *arg, char *argvalue, ++ char *obuf, int obuf_len) ++{ ++ return _set_mand_ttl_value(cmd, arg, argvalue, obuf, obuf_len, false); ++} ++ ++static int test_mand_ttl_value(struct cmd *cmd, char *arg, char *argvalue, ++ char *obuf, int obuf_len) ++{ ++ return _set_mand_ttl_value(cmd, arg, argvalue, obuf, obuf_len, true); ++} ++ + static int set_mand_subtype(struct cmd *cmd, char *arg, char *argvalue, + char *obuf, int obuf_len) + { +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-24-fix-build-warnings.patch b/open-lldp-v1.0.1-24-fix-build-warnings.patch new file mode 100644 index 0000000..f0facdb --- /dev/null +++ b/open-lldp-v1.0.1-24-fix-build-warnings.patch @@ -0,0 +1,59 @@ +From 2b5539cbf6baa72da39881f1d2b13aa325509998 Mon Sep 17 00:00:00 2001 +From: Chris Leech +Date: Wed, 17 Jun 2015 10:40:34 -0700 +Subject: [PATCH] fix build warnings + +--- + include/lldp_8021qaz.h | 6 ------ + lldp_util.c | 4 ++-- + 2 files changed, 2 insertions(+), 8 deletions(-) + +diff --git a/include/lldp_8021qaz.h b/include/lldp_8021qaz.h +index 55353b8..09dee20 100644 +--- a/include/lldp_8021qaz.h ++++ b/include/lldp_8021qaz.h +@@ -218,9 +218,6 @@ int ieee8021qaz_mod_app(struct app_tlv_head *head, int peer, + u8 prio, u8 sel, u16 proto, u32 ops); + int ieee8021qaz_app_sethw(char *ifname, struct app_tlv_head *head); + +-inline int get_prio_map(u32 prio_map, int tc); +-inline void set_prio_map(u32 *prio_map, u8 prio, int tc); +- + struct ieee8021qaz_tlvs *ieee8021qaz_data(const char *); + + int ieee8021qaz_tlvs_rxed(const char *ifname); +@@ -234,9 +231,6 @@ int ieee8021qaz_rchange(struct port *port, struct lldp_agent *, + void ieee8021qaz_ifup(char *ifname, struct lldp_agent *); + void ieee8021qaz_ifdown(char *ifname, struct lldp_agent *); + u8 ieee8021qaz_mibDeleteObject(struct port *port, struct lldp_agent *); +-inline int ieee8021qaz_clif_cmd(void *data, struct sockaddr_un *from, +- socklen_t fromlen, char *ibuf, int ilen, +- char *rbuf); + int ieee8021qaz_check_operstate(void); + int get_dcbx_hw(const char *ifname, __u8 *dcbx); + +diff --git a/lldp_util.c b/lldp_util.c +index f1fb7b9..f36033d 100644 +--- a/lldp_util.c ++++ b/lldp_util.c +@@ -1177,7 +1177,7 @@ int check_link_status(const char *ifname) + int get_arg_val_list(char *ibuf, int ilen, int *ioff, + char **args, char **argvals) + { +- u8 arglen; ++ u8 arglen = 0; + u16 argvalue_len; + int *arglens = NULL; + int *argvallens = NULL; +@@ -1245,7 +1245,7 @@ int get_arg_val_list(char *ibuf, int ilen, int *ioff, + + int get_arg_list(char *ibuf, int ilen, int *ioff, char **args) + { +- u8 arglen; ++ u8 arglen = 0; + int *arglens = NULL; + int *p; + int numargs; +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-3-VDP-vdptool-test-cases-Some-test-cases-to-test-the-n.patch b/open-lldp-v1.0.1-3-VDP-vdptool-test-cases-Some-test-cases-to-test-the-n.patch new file mode 100644 index 0000000..76430d9 --- /dev/null +++ b/open-lldp-v1.0.1-3-VDP-vdptool-test-cases-Some-test-cases-to-test-the-n.patch @@ -0,0 +1,2722 @@ +From 61965537b574e8dcd1d7b61ef543ab11fcbbbe6b Mon Sep 17 00:00:00 2001 +From: Thomas Richter +Date: Wed, 21 Jan 2015 03:36:48 +0000 +Subject: [PATCH] VDP: vdptool test cases Some test cases to test the new + vdptool. + +Signed-off-by: Thomas Richter +Signed-off-by: John Fastabend +--- + test/qbg22/vdp22/300-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/300.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/300.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/301-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/301.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/301.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/302-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/302.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/302.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/303-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/303.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/303.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/304-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/304.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/304.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/305-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/305.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/305.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/306-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/306.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/306.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/307-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/307.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/307.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/308-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/308.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/308.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/309-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/309.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/309.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/310-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/310.nlc | 54 +++++++++++++++++++++++ + test/qbg22/vdp22/310.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/320-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/320.nlc | 65 +++++++++++++++++++++++++++ + test/qbg22/vdp22/320.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/321-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/321.nlc | 78 +++++++++++++++++++++++++++++++++ + test/qbg22/vdp22/321.vdp | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/322-lldpad.conf | 55 +++++++++++++++++++++++ + test/qbg22/vdp22/322.nlc | 95 ++++++++++++++++++++++++++++++++++++++++ + test/qbg22/vdp22/322.vdp | 55 +++++++++++++++++++++++ + 42 files changed, 2372 insertions(+) + create mode 100644 test/qbg22/vdp22/300-lldpad.conf + create mode 100755 test/qbg22/vdp22/300.nlc + create mode 100644 test/qbg22/vdp22/300.vdp + create mode 100644 test/qbg22/vdp22/301-lldpad.conf + create mode 100755 test/qbg22/vdp22/301.nlc + create mode 100644 test/qbg22/vdp22/301.vdp + create mode 100644 test/qbg22/vdp22/302-lldpad.conf + create mode 100755 test/qbg22/vdp22/302.nlc + create mode 100644 test/qbg22/vdp22/302.vdp + create mode 100644 test/qbg22/vdp22/303-lldpad.conf + create mode 100755 test/qbg22/vdp22/303.nlc + create mode 100644 test/qbg22/vdp22/303.vdp + create mode 100644 test/qbg22/vdp22/304-lldpad.conf + create mode 100755 test/qbg22/vdp22/304.nlc + create mode 100644 test/qbg22/vdp22/304.vdp + create mode 100644 test/qbg22/vdp22/305-lldpad.conf + create mode 100755 test/qbg22/vdp22/305.nlc + create mode 100644 test/qbg22/vdp22/305.vdp + create mode 100644 test/qbg22/vdp22/306-lldpad.conf + create mode 100755 test/qbg22/vdp22/306.nlc + create mode 100644 test/qbg22/vdp22/306.vdp + create mode 100644 test/qbg22/vdp22/307-lldpad.conf + create mode 100755 test/qbg22/vdp22/307.nlc + create mode 100644 test/qbg22/vdp22/307.vdp + create mode 100644 test/qbg22/vdp22/308-lldpad.conf + create mode 100755 test/qbg22/vdp22/308.nlc + create mode 100644 test/qbg22/vdp22/308.vdp + create mode 100644 test/qbg22/vdp22/309-lldpad.conf + create mode 100755 test/qbg22/vdp22/309.nlc + create mode 100644 test/qbg22/vdp22/309.vdp + create mode 100644 test/qbg22/vdp22/310-lldpad.conf + create mode 100755 test/qbg22/vdp22/310.nlc + create mode 100644 test/qbg22/vdp22/310.vdp + create mode 100644 test/qbg22/vdp22/320-lldpad.conf + create mode 100755 test/qbg22/vdp22/320.nlc + create mode 100644 test/qbg22/vdp22/320.vdp + create mode 100644 test/qbg22/vdp22/321-lldpad.conf + create mode 100755 test/qbg22/vdp22/321.nlc + create mode 100644 test/qbg22/vdp22/321.vdp + create mode 100644 test/qbg22/vdp22/322-lldpad.conf + create mode 100755 test/qbg22/vdp22/322.nlc + create mode 100644 test/qbg22/vdp22/322.vdp + +diff --git a/test/qbg22/vdp22/300-lldpad.conf b/test/qbg22/vdp22/300-lldpad.conf +new file mode 100644 +index 0000000..6027a6d +--- /dev/null ++++ b/test/qbg22/vdp22/300-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04CA802A1EE5D1"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03CA802A1EE5D1"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/300.nlc b/test/qbg22/vdp22/300.nlc +new file mode 100755 +index 0000000..ea801b2 +--- /dev/null ++++ b/test/qbg22/vdp22/300.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2013 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# Wrong association command ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V assoc -c vsi=Xassoc,hello,1,2,001122334-455667788-99aabbccddee,none,22222-a:b:c:0:0:0) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/300.vdp b/test/qbg22/vdp22/300.vdp +new file mode 100644 +index 0000000..cb9bacd +--- /dev/null ++++ b/test/qbg22/vdp22/300.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "041E64AF9A93DF"; ++ }; ++ tlvid00000002 : ++ { ++ info = "031E64AF9A93DF"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/301-lldpad.conf b/test/qbg22/vdp22/301-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/301-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/301.nlc b/test/qbg22/vdp22/301.nlc +new file mode 100755 +index 0000000..90409d7 +--- /dev/null ++++ b/test/qbg22/vdp22/301.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# Wrong manager identifier ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V assoc -c vsi=assoc,\\hello,1,2,001122334-455667788-99aabbccddee,none,22222-a:b:c:0:0:0) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/301.vdp b/test/qbg22/vdp22/301.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/301.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/302-lldpad.conf b/test/qbg22/vdp22/302-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/302-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/302.nlc b/test/qbg22/vdp22/302.nlc +new file mode 100755 +index 0000000..1f0dfed +--- /dev/null ++++ b/test/qbg22/vdp22/302.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# Wrong type identifier ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V assoc -c vsi=assoc,hello,1000000999,2,001122334-455667788-99aabbccddee,none,22222-a:b:c:0:0:0) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/302.vdp b/test/qbg22/vdp22/302.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/302.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/303-lldpad.conf b/test/qbg22/vdp22/303-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/303-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/303.nlc b/test/qbg22/vdp22/303.nlc +new file mode 100755 +index 0000000..b40e6c6 +--- /dev/null ++++ b/test/qbg22/vdp22/303.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# Wrong typeidversion ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V assoc -c vsi=assoc,hello,1,257,001122334-455667788-99aabbccddee,none,22222-a:b:c:0:0:0) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/303.vdp b/test/qbg22/vdp22/303.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/303.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/304-lldpad.conf b/test/qbg22/vdp22/304-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/304-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/304.nlc b/test/qbg22/vdp22/304.nlc +new file mode 100755 +index 0000000..3bae87e +--- /dev/null ++++ b/test/qbg22/vdp22/304.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# Wrong hints ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V assoc -c vsi=assoc,hello,1,255,001122334-455667788-99aabbccddee,nix,22222-a:b:c:0:0:0) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/304.vdp b/test/qbg22/vdp22/304.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/304.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/305-lldpad.conf b/test/qbg22/vdp22/305-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/305-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/305.nlc b/test/qbg22/vdp22/305.nlc +new file mode 100755 +index 0000000..ae951e1 +--- /dev/null ++++ b/test/qbg22/vdp22/305.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# FID missing ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Unknown status" ++reply=$(../../../vdptool -i veth0 -T -V deassoc -c vsi=deassoc,hello,1,254,001122334-455667788-99aabbccddee,-) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/305.vdp b/test/qbg22/vdp22/305.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/305.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/306-lldpad.conf b/test/qbg22/vdp22/306-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/306-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/306.nlc b/test/qbg22/vdp22/306.nlc +new file mode 100755 +index 0000000..817a35b +--- /dev/null ++++ b/test/qbg22/vdp22/306.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# FID bad vlan ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V deassoc -c vsi=deassoc,hello,1,253,001122334-455667788-99aabbccddee,-,65536) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/306.vdp b/test/qbg22/vdp22/306.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/306.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/307-lldpad.conf b/test/qbg22/vdp22/307-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/307-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/307.nlc b/test/qbg22/vdp22/307.nlc +new file mode 100755 +index 0000000..d252568 +--- /dev/null ++++ b/test/qbg22/vdp22/307.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# FID bad mac ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V deassoc -c vsi=deassoc,hello,1,253,001122334-455667788-99aabbccddee,-,3-00:11:cc:ddd:e:f) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/307.vdp b/test/qbg22/vdp22/307.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/307.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/308-lldpad.conf b/test/qbg22/vdp22/308-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/308-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/308.nlc b/test/qbg22/vdp22/308.nlc +new file mode 100755 +index 0000000..9ab72bc +--- /dev/null ++++ b/test/qbg22/vdp22/308.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# FID format vlan-mac and mac ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V preassoc -c vsi=preassoc,hello,1,253,001122334-455667788-99aabbccddee,-,3-00:11:cc:d:e:f,4444) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/308.vdp b/test/qbg22/vdp22/308.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/308.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/309-lldpad.conf b/test/qbg22/vdp22/309-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/309-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/309.nlc b/test/qbg22/vdp22/309.nlc +new file mode 100755 +index 0000000..8de0f86 +--- /dev/null ++++ b/test/qbg22/vdp22/309.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# FID bad group ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V preassoc -c vsi=preassoc,hello,1,253,001122334-455667788-99aabbccddee,-,333-00:11:cc:d:e:f-44a44) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/309.vdp b/test/qbg22/vdp22/309.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/309.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/310-lldpad.conf b/test/qbg22/vdp22/310-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/310-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/310.nlc b/test/qbg22/vdp22/310.nlc +new file mode 100755 +index 0000000..ae90509 +--- /dev/null ++++ b/test/qbg22/vdp22/310.nlc +@@ -0,0 +1,54 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc with wrong user input using vdptool. ++# FID same mac several times ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi_ok="Invalid parameters" ++reply=$(../../../vdptool -i veth0 -T -V preassoc -c vsi=preassoc,hello,1,253,001122334-455667788-99aabbccddee,-,333-00:11:cc:d:e:f-44444,222-00:11:cc:d:e:f-44444) ++rc=$? ++if [ "$rc" -eq 1 ] ++then ++ if [ "$reply" != "$vsi_ok" ] ++ then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ else ++ let rc=0 ++ fi ++else ++ echo "vdptool unexpected success" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/310.vdp b/test/qbg22/vdp22/310.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/310.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/320-lldpad.conf b/test/qbg22/vdp22/320-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/320-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/320.nlc b/test/qbg22/vdp22/320.nlc +new file mode 100755 +index 0000000..2dca2c2 +--- /dev/null ++++ b/test/qbg22/vdp22/320.nlc +@@ -0,0 +1,65 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute a simple assoc input using vdptool. Expect success. ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi1="assoc,hello,1,2,00112233-4455-6677-8899-aabbccddeeff" ++vsi2="22222-0a:0b:0c:00:00:00" ++vsi_cmd="$vsi1,none,$vsi2" ++vsi_ok="vsi=$vsi1,0,$vsi2;" ++ ++../../../vdptool -i veth0 -T -V assoc -c vsi=$vsi_cmd ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 1)" ++ exit $rc ++fi ++ ++sleep 30 ++reply="$(../../../vdptool -i veth0 -t -V assoc -c vsi)" ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 2)" ++ exit $rc ++fi ++ ++if [ "$reply" != "$vsi_ok" ] ++then ++ echo "vdptool reply mismatch" ++ echo "expected reply:$vsi_ok" ++ echo "returned reply:$reply" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/320.vdp b/test/qbg22/vdp22/320.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/320.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/321-lldpad.conf b/test/qbg22/vdp22/321-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/321-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/321.nlc b/test/qbg22/vdp22/321.nlc +new file mode 100755 +index 0000000..1d5247a +--- /dev/null ++++ b/test/qbg22/vdp22/321.nlc +@@ -0,0 +1,78 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute two simple assoc input via vdptool. Expect success. ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi1="assoc,hello,1,2,00112233-4455-6677-8899-aabbccddeeff" ++vsi2="22222-0a:0b:0c:00:00:00" ++vsi_cmd="$vsi1,none,$vsi2" ++vsi_ok="$vsi1,0,$vsi2;" ++vsi1b="assoc,world,1,2,00112233-4455-6677-8899-ffeeddccbbaa" ++vsi2b="2-aa:bb:cc:00:00:00" ++vsib_cmd="$vsi1b,none,$vsi2b" ++vsib_ok="$vsi1b,0,$vsi2b;" ++ ++../../../vdptool -i veth0 -T -V assoc -c vsi=$vsi_cmd ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 1)" ++ exit $rc ++fi ++ ++sleep 30 ++../../../vdptool -i veth0 -T -V assoc -c vsi=$vsib_cmd ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 2)" ++ exit $rc ++fi ++ ++sleep 30 ++reply="$(../../../vdptool -i veth0 -t -V assoc -c vsi)" ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 3)" ++ exit $rc ++fi ++ ++if [ "$reply" != "vsi=$vsib_ok$vsi_ok" ] ++then ++ echo "vdptool reply mismatch" ++ echo "expected reply:vsi=$vsib_ok$vsi_ok" ++ echo "returned reply:$reply" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/321.vdp b/test/qbg22/vdp22/321.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/321.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/322-lldpad.conf b/test/qbg22/vdp22/322-lldpad.conf +new file mode 100644 +index 0000000..11ed7a2 +--- /dev/null ++++ b/test/qbg22/vdp22/322-lldpad.conf +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad station mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth0 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "station"; ++ evbrrcap = false; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +diff --git a/test/qbg22/vdp22/322.nlc b/test/qbg22/vdp22/322.nlc +new file mode 100755 +index 0000000..5b5840e +--- /dev/null ++++ b/test/qbg22/vdp22/322.nlc +@@ -0,0 +1,95 @@ ++#!/bin/bash ++# ++# Test case for LLDPAD VDP testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# ++# Thomas Richter, IBM Research & Development, Boeblingen, Germany, 20-Apr-2013 ++# ++# Execute assoc/preassoc input via vdptool. Expect success. ++# ++ ++sleep 30 # Must: Wait some time for lldpad to start up and initialize ++outfile=$(basename $0) ++dirfile=$(dirname $0) ++cd $dirfile ++ ++vsi1="assoc,hello,1,2,00112233-4455-6677-8899-aabbccddeeff" ++vsi2="22222-0a:0b:0c:00:00:00" ++vsi_cmd="$vsi1,none,$vsi2" ++vsi_ok="$vsi1,0,$vsi2;" ++vsi1b="preassoc,world,1,2,00112233-4455-6677-8899-ffeeddccbbaa" ++vsi2b="2-aa:bb:cc:00:00:00" ++vsib_cmd="$vsi1b,none,$vsi2b" ++vsib_ok="$vsi1b,0,$vsi2b;" ++ ++../../../vdptool -i veth0 -T -V assoc -c vsi=$vsi_cmd ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 1)" ++ exit $rc ++fi ++ ++sleep 30 ++../../../vdptool -i veth0 -T -V preassoc -c vsi=$vsib_cmd ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 2)" ++ exit $rc ++fi ++ ++sleep 30 ++reply="$(../../../vdptool -i veth0 -t -V assoc -c vsi)" ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 3)" ++ exit $rc ++fi ++ ++if [ "$reply" != "vsi=$vsi_ok" ] ++then ++ echo "vdptool reply mismatch (step 3)" ++ echo "expected reply:vsi=$vsi_ok" ++ echo "returned reply:$reply" ++ exit 6 ++fi ++ ++sleep 5 ++reply="$(../../../vdptool -i veth0 -t -V preassoc -c vsi)" ++rc=$? ++if [ "$rc" -ne 0 ] ++then ++ echo "vdptool failure (step 4)" ++ exit $rc ++fi ++ ++if [ "$reply" != "vsi=$vsib_ok" ] ++then ++ echo "vdptool reply mismatch (step 4)" ++ echo "expected reply:vsi=$vsib_ok" ++ echo "returned reply:$reply" ++ let rc=1 ++fi ++ ++sleep 5 ++exit $rc +diff --git a/test/qbg22/vdp22/322.vdp b/test/qbg22/vdp22/322.vdp +new file mode 100644 +index 0000000..0c7e96a +--- /dev/null ++++ b/test/qbg22/vdp22/322.vdp +@@ -0,0 +1,55 @@ ++# ++# Test case for LLDPAD testing according to IEEE 802.1Qbg ratified standard ++# ++# Copyright (c) International Business Machines Corp., 2014 ++# ++# Author(s): Thomas Richter ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms and conditions of the GNU General Public License, ++# version 2, as published by the Free Software Foundation. ++# ++# This program is distributed in the hope it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++# more details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., ++# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++# ++ ++# Configuration file for lldpad bridge mode setup. ++ ++dcbx : ++{ ++ version = "1.0"; ++ dcbx_version = 2; ++}; ++nearest_customer_bridge : ++{ ++ veth2 : ++ { ++ tlvid00000001 : ++ { ++ info = "04C68829509676"; ++ }; ++ tlvid00000002 : ++ { ++ info = "03C68829509676"; ++ }; ++ adminStatus = 3; ++ tlvid0080c20d : ++ { ++ enableTx = true; ++ evbmode = "bridge"; ++ evbrrcap = true; ++ evbrrreq = true; ++ evbgpid = false; ++ ecpretries = 3; ++ ecprte = 14; ++ vdprwd = 20; ++ vdprka = 20; ++ }; ++ }; ++}; +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-4-VDP-Changes-to-make-the-interface-to-VDP22-in-lldpad.patch b/open-lldp-v1.0.1-4-VDP-Changes-to-make-the-interface-to-VDP22-in-lldpad.patch new file mode 100644 index 0000000..341acd8 --- /dev/null +++ b/open-lldp-v1.0.1-4-VDP-Changes-to-make-the-interface-to-VDP22-in-lldpad.patch @@ -0,0 +1,593 @@ +From e3f6d0eab95ef6b7336aaea2f44ecb79ead4216d Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:37:09 +0000 +Subject: [PATCH] VDP: Changes to make the interface to VDP22 (in lldpad) as + TLV + +Changes to make the interface to VDP22 (in lldpad) as len, key, len, +value, which is in sync with other modules of lldpad. + +Currently, the VSI parameters of VDP22 to LLDPAD are comma separated. +This patch has changes to have VSI Parameters being given to VDP22 as +Keyword_len followed by Keyword followed by value_len followed by +value. vdptool is also modified to reflect the same. This is +synchronous with other interface of lldpad like lldptool. + +As an example, if vdptool is invoked as: + +"vdptool -i eth2 -T -S -V assoc -c mode=assoc -c mgrid2=0 \ + -c typeid=0 -c typeidver=0 -c uuid=00000000-3333-2222-888a-aabbccddee72 \ + -c hints=none -c filter=0-00:00:00:11:22:72-90001", + +the input to lldpad will be: + +"M000080c4C3020000011c04eth2020000000304mode0005assoc06mgrid20001006typeid0001009typeidver0001004uuid002400000000-3333-2222-888a-aabbccddee7205hints0004none06filter00190-00:00:00:11:22:72-90001" + +Another option is also added to vdptool to wait and print the response +from the bridge. + +Signed-off-by: padkrish +--- + include/qbg_vdp22.h | 5 ++ + include/qbg_vdp22_clif.h | 7 +++ + include/qbg_vdp22def.h | 24 ++++++++ + qbg/vdp22_cmds.c | 125 +++++++------------------------------- + qbg/vdp_ascii.c | 152 +++++++++++++++++++++++++++++++---------------- + vdptool.c | 53 +++++++++++------ + 6 files changed, 193 insertions(+), 173 deletions(-) + +diff --git a/include/qbg_vdp22.h b/include/qbg_vdp22.h +index b345602..45f44d5 100644 +--- a/include/qbg_vdp22.h ++++ b/include/qbg_vdp22.h +@@ -163,6 +163,11 @@ struct vdp22_user_data { /* Head for all VDP data */ + LIST_HEAD(vdp22_head, vdp22) head; + }; + ++struct vsi_keyword_handler { ++ char *keyword; ++ enum vsi_mand_arg val; ++}; ++ + struct lldp_module *vdp22_register(void); + void vdp22_unregister(struct lldp_module *); + void vdp22_start(const char *, int); +diff --git a/include/qbg_vdp22_clif.h b/include/qbg_vdp22_clif.h +index 008022a..8346b98 100644 +--- a/include/qbg_vdp22_clif.h ++++ b/include/qbg_vdp22_clif.h +@@ -29,6 +29,10 @@ + + #ifndef QBG_VDP22_CLIF_H + #define QBG_VDP22_CLIF_H ++ ++#define OP_FID_POS 8 /* Second Byte */ ++#define OP_OUI_POS 16 /* Third Byte */ ++ + typedef enum { + cmd_getstats, + cmd_gettlv, +@@ -51,6 +55,9 @@ typedef enum { + op_config = 0x10, + op_delete = 0x20, + op_key = 0x40 ++ /* Second Byte is used for signifying the number of Filter fields and ++ * the third byte is used for signifying the number of OUI fields. ++ */ + } vdp22_op; + + struct lldp_module *vdp22_cli_register(void); +diff --git a/include/qbg_vdp22def.h b/include/qbg_vdp22def.h +index 52f4502..21ba15d 100644 +--- a/include/qbg_vdp22def.h ++++ b/include/qbg_vdp22def.h +@@ -72,4 +72,28 @@ enum vdp22_migration_hints { + VDP22_MIGFROM = 32 /* S-bit migrate from hint */ + }; + ++enum vsi_mand_arg { ++ VSI_MODE_ARG = 0, ++ VSI_MGRID2_ARG, ++ VSI_TYPEID_ARG, ++ VSI_TYPEIDVER_ARG, ++/* VSI_VSIIDFRMT_ARG, TODO */ ++ VSI_VSIID_ARG, ++ VSI_FILTER_ARG, ++ VSI_MAND_NUM_ARG, ++ VSI_HINTS_ARG, ++ VSI_INVALID_ARG ++}; ++ ++#define VSI22_ARG_MODE_STR "mode" ++#define VSI22_ARG_MGRID_STR "mgrid2" ++#define VSI22_ARG_TYPEID_STR "typeid" ++#define VSI22_ARG_TYPEIDVER_STR "typeidver" ++#define VSI22_ARG_VSIIDFRMT_STR "vsiidfrmt" ++/*#define VSI22_ARG_VSIID_STR "vsiid" TODO*/ ++#define VSI22_ARG_VSIID_STR "uuid" ++#define VSI22_ARG_HINTS_STR "hints" ++#define VSI22_ARG_FILTER_STR "filter" ++#define VSI22_ARG_OUI_STR "oui" ++ + #endif +diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c +index f055441..dde4669 100644 +--- a/qbg/vdp22_cmds.c ++++ b/qbg/vdp22_cmds.c +@@ -104,37 +104,6 @@ static int handle_get_arg(struct cmd *cmd, char *arg, char *argvalue, + return status; + } + +-static int handle_get(struct cmd *cmd, UNUSED char *arg, char *argvalue, +- char *obuf, int obuf_len) +-{ +- struct arg_handlers *ah; +- int rval; +- char *nbuf; +- int nbuf_len; +- +- memset(obuf, 0, obuf_len); +- nbuf = obuf + 12; +- nbuf_len = obuf_len - 12; +- +- ah = get_my_arghndl(cmd->module_id); +- if (!ah) +- return cmd_not_applicable; +- for (; ah->arg; ++ah) { +- if (strcmp(ah->arg, ARG_VDP22_VSI)) +- continue; +- if (ah->handle_get && (ah->arg_class == TLV_ARG)) { +- rval = ah->handle_get(cmd, ah->arg, argvalue, +- nbuf, nbuf_len); +- if (rval != cmd_success && rval != cmd_not_applicable) +- return rval; +- +- nbuf_len -= strlen(nbuf); +- nbuf = nbuf + strlen(nbuf); +- } +- } +- return cmd_success; +-} +- + static int handle_test_arg(struct cmd *cmd, char *arg, char *argvalue, + char *obuf, int obuf_len) + { +@@ -223,17 +192,13 @@ static int handle_set_arg(struct cmd *cmd, char *arg, char *argvalue, + */ + int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, + UNUSED socklen_t fromlen, +- char *ibuf, int ilen, char *rbuf, int rlen) ++ char *ibuf, UNUSED int ilen, char *rbuf, int rlen) + { + struct cmd cmd; + u8 len, version; + int ioff, roff; + int rstatus = cmd_invalid; +- char **args; +- char **argvals; + bool test_failed = false; +- int numargs = 0; +- int i, offset; + + memset(&cmd, 0, sizeof(cmd)); + cmd.module_id = LLDP_MOD_VDP22; +@@ -275,32 +240,6 @@ int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, + if (!(cmd.ops & op_config)) + return cmd_invalid; + +- /* Count args and argvalues */ +- offset = ioff; +- for (numargs = 0; (ilen - offset) > 2; numargs++) { +- offset += 2; +- if (ilen - offset > 0) { +- offset++; +- if (ilen - offset > 4) +- offset += 4; +- } +- } +- +- args = calloc(numargs, sizeof(char *)); +- if (!args) +- return cmd_failed; +- +- argvals = calloc(numargs, sizeof(char *)); +- if (!argvals) { +- free(args); +- return cmd_failed; +- } +- +- if ((cmd.ops & op_arg) && (cmd.ops & op_argval)) +- numargs = get_arg_val_list(ibuf, ilen, &ioff, args, argvals); +- else if (cmd.ops & op_arg) +- numargs = get_arg_list(ibuf, ilen, &ioff, args); +- + snprintf(rbuf, rlen, "%c%1x%02x%08x%02x%s", + CMD_REQUEST, CLIF_MSG_VERSION, + cmd.cmd, cmd.ops, +@@ -309,42 +248,29 @@ int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, + + /* Confirm port is a valid LLDP port */ + if (!get_ifidx(cmd.ifname) || !is_valid_lldp_device(cmd.ifname)) { +- free(argvals); +- free(args); + return cmd_device_not_found; + } + + snprintf(rbuf + roff, rlen - roff, "%08x", cmd.tlvid); + roff += 8; + if (cmd.cmd == cmd_gettlv) { +- if (!numargs) +- rstatus = handle_get(&cmd, NULL, NULL, +- rbuf + strlen(rbuf), +- rlen - strlen(rbuf)); +- else +- for (i = 0; i < numargs; i++) +- rstatus = handle_get_arg(&cmd, args[i], NULL, +- rbuf + strlen(rbuf), +- rlen - strlen(rbuf)); ++ rstatus = handle_get_arg(&cmd, ARG_VDP22_VSI, ++ NULL, ++ rbuf + strlen(rbuf), ++ rlen - strlen(rbuf)); + } else { +- for (i = 0; i < numargs; i++) { +- rstatus = handle_test_arg(&cmd, args[i], argvals[i], +- rbuf + strlen(rbuf), +- rlen - strlen(rbuf)); +- if (rstatus != cmd_not_applicable && +- rstatus != cmd_success) +- test_failed = true; +- } ++ rstatus = handle_test_arg(&cmd, ARG_VDP22_VSI, ++ ibuf + ioff, ++ rbuf + strlen(rbuf), ++ rlen - strlen(rbuf)); ++ if (rstatus != cmd_not_applicable && rstatus != cmd_success) ++ test_failed = true; + if (!test_failed) +- for (i = 0; i < numargs; i++) +- rstatus = handle_set_arg(&cmd, args[i], +- argvals[i], +- rbuf + strlen(rbuf), +- rlen - strlen(rbuf)); ++ rstatus = handle_set_arg(&cmd, ++ ARG_VDP22_VSI, ibuf + ioff, ++ rbuf + strlen(rbuf), ++ rlen - strlen(rbuf)); + } +- +- free(argvals); +- free(args); + return rstatus; + } + +@@ -436,27 +362,16 @@ out: + return good_cmd; + } + +-/* +- * Count the number of fid data fields in the argument value. +- */ +-#define VDP22_FID_IDX 6 /* Min index of fid data */ +-static int count_fid(char *argvalue) +-{ +- char *p = argvalue; +- int i; +- +- for (i = 0; (p = strchr(p, ',')); ++i, ++p) +- ; +- return i + 1 - VDP22_FID_IDX; +-} +- + static int set_arg_vsi2(struct cmd *cmd, char *argvalue, bool test) + { +- int no = count_fid(argvalue); ++ int no = (cmd->ops >> OP_FID_POS) & 0xff; + + if (no <= 0) + return -EINVAL; +- return set_arg_vsi3(cmd, argvalue, test, no); ++ if ((cmd->ops & op_arg) && (cmd->ops & op_argval)) ++ return set_arg_vsi3(cmd, argvalue, test, no); ++ else /* Not supported for now */ ++ return cmd_failed; + } + + static int set_arg_vsi(struct cmd *cmd, UNUSED char *arg, char *argvalue, +diff --git a/qbg/vdp_ascii.c b/qbg/vdp_ascii.c +index 0ace562..09e53c6 100644 +--- a/qbg/vdp_ascii.c ++++ b/qbg/vdp_ascii.c +@@ -43,6 +43,17 @@ + #include "qbg_vdp22.h" + #include "qbg_vdpnl.h" + #include "qbg_utils.h" ++#include "lldp_util.h" ++ ++struct vsi_keyword_handler vsi_key_handle[] = { ++ {VSI22_ARG_MODE_STR, VSI_MODE_ARG}, ++ {VSI22_ARG_MGRID_STR, VSI_MGRID2_ARG}, ++ {VSI22_ARG_TYPEID_STR, VSI_TYPEID_ARG}, ++ {VSI22_ARG_TYPEIDVER_STR, VSI_TYPEIDVER_ARG}, ++/* {VSI22_ARG_VSIIDFRMT_STR, VSI_VSIIDFRMT_ARG}, TODO*/ ++ {VSI22_ARG_VSIID_STR, VSI_VSIID_ARG}, ++ {VSI22_ARG_HINTS_STR, VSI_HINTS_ARG}, ++ {VSI22_ARG_FILTER_STR, VSI_FILTER_ARG} }; + + /* + * Check if it is a UUID and consists of hexadecimal digits and dashes only. +@@ -253,6 +264,18 @@ static bool getmode(struct vdpnl_vsi *p, char *s) + return true; + } + ++enum vsi_mand_arg get_keywork_val(char *keyword) ++{ ++ int count, key_str_size; ++ ++ key_str_size = sizeof(vsi_key_handle) / sizeof(vsi_key_handle[0]); ++ for (count = 0; count < key_str_size; count++) { ++ if (!strcmp(keyword, vsi_key_handle[count].keyword)) ++ return vsi_key_handle[count].val; ++ } ++ return VSI_INVALID_ARG; ++} ++ + /* + * Parse the mode parameter to create/change an VSI assoication. + * The format is a comma separated list of tokens: +@@ -276,66 +299,95 @@ static bool getmode(struct vdpnl_vsi *p, char *s) + * mac := xx:xx:xx:xx:xx:xx + */ + +-static int str2vdpnl(char *argvalue, struct vdpnl_vsi *vsi) ++static int str2vdpnl(char *orig_argvalue, struct vdpnl_vsi *vsi) + { ++ char **args; ++ char **argvals; ++ char *argvalue; + int rc = -ENOMEM; + unsigned int no; +- unsigned short idx; +- char *cmdstring, *token; ++ unsigned short idx = 0; ++ int i, ioff = 0, offset; ++ int ilen = strlen(orig_argvalue); ++ int numargs; ++ enum vsi_mand_arg vsi_key; ++ u16 vsi_mand_mask = (1 << VSI_MAND_NUM_ARG) - 1; ++ u16 num_arg_keys = 0; + +- cmdstring = strdup(argvalue); +- if (!cmdstring) +- goto out_free; +- rc = -EINVAL; +- /* 1st field is VSI command */ +- token = strtok(cmdstring, ","); +- if (!token || !getmode(vsi, token)) +- goto out_free; ++ argvalue = strdup(orig_argvalue); ++ if (!argvalue) ++ goto out; ++ /* Count args and argvalues */ ++ offset = ioff; ++ for (numargs = 0; (ilen - offset) > 2; numargs++) { ++ offset += 2; ++ if (ilen - offset > 0) { ++ offset++; ++ if (ilen - offset > 4) ++ offset += 4; ++ } ++ } ++ args = calloc(numargs, sizeof(char *)); ++ if (!args) ++ goto out_argvalue; + +- /* 2nd field is VSI Manager Identifer (16 bytes maximum) */ +- token = strtok(NULL, ","); +- if (!token || !getmgr2id(vsi, token)) +- goto out_free; +- +- /* 3rd field is type identifier */ +- token = strtok(NULL, ","); +- if (!token || !getnumber(token, 0, 0xffffff, &no)) +- goto out_free; +- vsi->vsi_typeid = no; +- +- /* 4th field is type version identifier */ +- token = strtok(NULL, ","); +- if (!token || !getnumber(token, 0, 0xff, &no)) +- goto out_free; +- vsi->vsi_typeversion = no; +- +- /* 5th field is filter VSI UUID */ +- token = strtok(NULL, ","); +- if (!token || vdp_str2uuid(vsi->vsi_uuid, token, sizeof(vsi->vsi_uuid))) +- goto out_free; +- vsi->vsi_idfmt = VDP22_ID_UUID; +- +- /* 6th field is migration hints */ +- token = strtok(NULL, ","); +- if (!token || !gethints(vsi, token)) +- goto out_free; +- +- /* +- * 7th and remaining fields are filter information format data. +- * All fields must have the same format. The first fid field determines +- * the format. +- */ +- for (idx = 0, token = strtok(NULL, ","); token != NULL; +- ++idx, token = strtok(NULL, ",")) { +- if (idx < vsi->macsz && !getfid(vsi, token, idx)) ++ argvals = calloc(numargs, sizeof(char *)); ++ if (!argvals) ++ goto out_args; ++ numargs = get_arg_val_list(argvalue, ilen, &ioff, args, argvals); ++ for (i = 0; i < numargs; i++) { ++ vsi_key = get_keywork_val(args[i]); ++ switch (vsi_key) { ++ case VSI_MODE_ARG: ++ if (!argvals[i] || !getmode(vsi, argvals[i])) ++ goto out_free; ++ break; ++ case VSI_MGRID2_ARG: ++ if (!argvals[i] || !getmgr2id(vsi, argvals[i])) ++ goto out_free; ++ break; ++ case VSI_TYPEID_ARG: ++ if (!argvals[i] || ++ !getnumber(argvals[i], 0, 0xffffff, &no)) ++ goto out_free; ++ vsi->vsi_typeid = no; ++ break; ++ case VSI_TYPEIDVER_ARG: ++ if (!argvals[i] || !getnumber(argvals[i], 0, 0xff, &no)) ++ goto out_free; ++ vsi->vsi_typeversion = no; ++ break; ++ case VSI_VSIID_ARG: ++ if (!argvals[i] || ++ vdp_str2uuid(vsi->vsi_uuid, argvals[i], ++ sizeof(vsi->vsi_uuid))) ++ goto out_free; ++ vsi->vsi_idfmt = VDP22_ID_UUID; ++ break; ++ case VSI_FILTER_ARG: ++ if (idx < vsi->macsz && !getfid(vsi, argvals[i], idx)) ++ goto out_free; ++ idx++; ++ break; ++ case VSI_HINTS_ARG: ++ if (!argvals[i] || !gethints(vsi, argvals[i])) ++ goto out_free; ++ break; ++ default: + goto out_free; ++ } ++ num_arg_keys |= (1 << vsi_key); + } +- + /* Return error if no filter information provided */ +- if (idx) ++ if ((num_arg_keys & vsi_mand_mask) == vsi_mand_mask) + rc = 0; + out_free: +- free(cmdstring); ++ free(argvals); ++out_args: ++ free(args); ++out_argvalue: ++ free(argvalue); ++out: + return rc; + } + +diff --git a/vdptool.c b/vdptool.c +index e7d384a..f506020 100644 +--- a/vdptool.c ++++ b/vdptool.c +@@ -125,31 +125,28 @@ static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals) + { + int len; + int i; ++ int fid = 0, oui = 0; + + len = sizeof(cmd->obuf); + ++ if (cmd->cmd == cmd_settlv) { ++ for (i = 0; i < argc; i++) { ++ if (args[i]) { ++ if (!strncasecmp(args[i], "filter", ++ strlen("filter"))) ++ fid++; ++ else if (!strncasecmp(args[i], "oui", ++ strlen("oui"))) ++ oui++; ++ } ++ } ++ } ++ cmd->ops |= (fid << OP_FID_POS) | (oui << OP_OUI_POS); + /* all command messages begin this way */ + snprintf(cmd->obuf, len, "%c%08x%c%1x%02x%08x%02x%s%02x%08x", + MOD_CMD, cmd->module_id, CMD_REQUEST, CLIF_MSG_VERSION, + cmd->cmd, cmd->ops, (unsigned int) strlen(cmd->ifname), + cmd->ifname, cmd->type, cmd->tlvid); +-#if PADDU +- if (cmd->cmd == cmd_settlv) { +- size_t len2 = 0; +- /* +- * Get total length and append it plus any args and argvals +- * to the command message +- */ +- for (i = 0; i < argc; i++) { +- if (args[i]) +- len2 += 2 + strlen(args[i]); +- if (argvals[i]) +- len2 += 4 + strlen(argvals[i]); +- } +- snprintf(cmd->obuf + strlen(cmd->obuf), len - strlen(cmd->obuf), +- "%04zx", len2); +- } +-#endif + /* Add any args and argvals to the command message */ + for (i = 0; i < argc; i++) { + if (args[i]) +@@ -710,6 +707,9 @@ static int _clif_command(struct clif *clif, char *cmd, int print) + char buf[MAX_CLIF_MSGBUF]; + size_t len; + int ret; ++ int rc; ++ char reply[100]; ++ size_t reply_len2 = sizeof(reply); + + print_raw_message(cmd, print); + +@@ -730,6 +730,13 @@ static int _clif_command(struct clif *clif, char *cmd, int print) + buf[len] = '\0'; + ret = parse_print_message(buf, print); + } ++ if (cli_attached) { ++ rc = clif_vsievt(clif, reply, &reply_len2, 5); ++ printf("\nReturn from vsievt %d ret %d Reply %s\n", rc, ret, ++ reply); ++ if (!rc) ++ printf("\nMsg is %s\n", reply); ++ } + + return ret; + } +@@ -854,6 +861,7 @@ static int request(struct clif *clif, int argc, char *argv[]) + int numargs = 0; + char **argptr = &argv[0]; + char *end; ++ char attach_str[9] = ""; + int c; + int option_index; + +@@ -865,7 +873,7 @@ static int request(struct clif *clif, int argc, char *argv[]) + + opterr = 0; + for (;;) { +- c = getopt_long(argc, argv, "i:tThcnvrRpqV:", ++ c = getopt_long(argc, argv, "i:tTWhcnvrRpqV:", + lldptool_opts, &option_index); + if (c < 0) + break; +@@ -936,6 +944,15 @@ static int request(struct clif *clif, int argc, char *argv[]) + case 'v': + command.cmd = cmd_version; + break; ++ case 'W': ++ snprintf(attach_str, sizeof(attach_str), "%x", ++ LLDP_MOD_VDP22); ++ if (clif_attach(clif, attach_str) != 0) { ++ printf("Warning: Failed to attach to lldpad.\n"); ++ return -1; ++ } ++ cli_attached = 1; ++ break; + default: + usage(); + ret = -1; +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-5-VDP-Support-for-get-tlv-in-vdptool-and-VDP22.patch b/open-lldp-v1.0.1-5-VDP-Support-for-get-tlv-in-vdptool-and-VDP22.patch new file mode 100644 index 0000000..d880bb5 --- /dev/null +++ b/open-lldp-v1.0.1-5-VDP-Support-for-get-tlv-in-vdptool-and-VDP22.patch @@ -0,0 +1,1194 @@ +From 0a21b0c0b9674f90cb9185e7fe097ae83657328f Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:37:31 +0000 +Subject: [PATCH] VDP: Support for get-tlv in vdptool and VDP22 + +This commit has the following changes: +a. Change in VDP22 and vdptool to support get-tlv. This actually refers to +get-vsi. Support for querying and printing all VSI's, partial VSI's is added. +The vdptool man page document is also modified accordingly. +b. The response from lldpad (VDP22) is modified to support to the +len, key, len, value format. Earlier, only the meessage to VDP22 has the +format. The response from VDP22 followed the comma separated format for VSI +parameters. +c. Fix some formatting issues + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + docs/vdptool.8 | 47 +++++++----- + include/lldp_util.h | 1 + + include/qbg_vdp22.h | 5 +- + include/qbg_vdp22def.h | 11 ++- + include/qbg_vdpnl.h | 3 + + lldp_util.c | 52 ++++++++++---- + qbg/vdp22.c | 28 ++++++-- + qbg/vdp22_cmds.c | 135 +++++++++++++++++++++++++++++++---- + qbg/vdp22sm.c | 5 +- + qbg/vdp_ascii.c | 190 +++++++++++++++++++++++++++++++------------------ + vdptool.c | 152 +++++++++++---------------------------- + 11 files changed, 395 insertions(+), 234 deletions(-) + +diff --git a/docs/vdptool.8 b/docs/vdptool.8 +index 5110bb9..02b4e8e 100644 +--- a/docs/vdptool.8 ++++ b/docs/vdptool.8 +@@ -70,17 +70,17 @@ bridge. + Specifies additional parameters for TLV queries and associations commands. + The argument list varies, depending on the command option + .B (-T) +-or ++or + .BR (-t) . +-To establish a VSI association use the command option ++To establish a VSI association use the command option + .B (-T) + and specify additional information as arguments in the form +-of key=value. See the ++of key=value. See the + .I "VSI Parameter" + subsection and + .I Example + section below. +-To query a VSI specific association use the command option ++To query a VSI specific association use the command option + .B (-t) + and specify the value of the + VSI Instance Identifier (keywork uuid followed be the VSI +@@ -92,6 +92,9 @@ show raw client interface messages + .TP + .B \-R + show only raw Client interface messages ++.TP ++.B \-W ++Wait for the bridge response message + .SS VSI Parameter + Each VDP22 TLVs contains a command mode, manager identifier, + type identifier, type identifier version, VSI instance identifier, +@@ -99,7 +102,7 @@ migiration hints and filter information. + The fields are explained next: + .TP + .B "mode (Command Mode):" +-The command mode determines the type ++The command mode determines the type + of the VSI association to be established. + It is an ascii string can be one of: + .RS +@@ -110,7 +113,7 @@ Create an VSI preassociation. The association + is only announced to the switch. + .IP preassoc-rr: + Create an VSI preassociation. The association +-is only announced to the switch and the ++is only announced to the switch and the + switch should reserve the resources. + .IP deassoc: + Delete an VSI association. +@@ -137,7 +140,7 @@ an UUID according to RFC 4122 + with optional dashes in between. + .TP + .B "hints (Migration Hints):" +-The migiration hints is a string aiding in ++The migiration hints is a string aiding in + migration of virtual machines: + .RS + .IP none: +@@ -168,13 +171,13 @@ The MAC address is specified in the format xx:xx:xx:xx:xx:xx. + The colons are mandatory. + For vlan details see (1). + .IP "vlan-mac-group (4)" +-A vlan number, MAC address and group identifier, ++A vlan number, MAC address and group identifier, + each delimited by a slash ('-'), + also known as filter information format 4. + The group identifier is a 32 bit number. + For vlan and MAC address details see (1) and (2). + .IP "vlan--group (3)" +-A vlan number and group identifier, ++A vlan number and group identifier, + delimited by two slashes ('--'), + also known as filter information format 3. + For vlan and group details see (1) and (4). +@@ -218,18 +221,30 @@ vdptool -p + Create a VSI association on interface eth2 + .br + .nf +-Supported today: One config parameter and comma separated list +-vdptool -i eth2 -T -V assoc -c vsi=assoc,blabla,5, \\ +- 1122,4,none,2-52:00:00:11:22:33-200 ++vdptool -i eth2 -T -V assoc -c mode=assoc -c mgrid2=blabla \\ ++ -c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\ ++ -c filter=2-52:00:00:11:22:33-200 ++.fi ++.TP ++Create a VSI association on interface eth2 and wait for the response from the bridge ++.br ++.nf ++vdptool -i eth2 -T -W -V assoc -c mode=assoc -c mgrid2=blabla \\ ++ -c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\ ++ -c filter=0-52:00:00:11:22:33-200 ++.fi + +-Planned for the future: +-vdptool -i eth2 -T -V assoc -c mgrid2=blabla -c typeid=5 \\ +- -c uuid=1122 -c typeidver=4 -c hints=none -c fid=2-52:00:00:11:22:33-200 +-.fi + .TP + Query all VSI association on interface eth2 + .br + vdptool -i eth2 -t -V assoc ++ ++.TP ++Query VSI association on interface eth2 that matches specific VSI parameters. Any of the VSI parameters below can be omitted. ++.br ++vdptool -i eth2 -t -V assoc -t -V assoc -c mode=assoc \\ ++ -c mgrid2=blabla -c typeid=5 -c uuid=1122 \\ ++ -c typeidver=4 -c hints=none + .SH SEE ALSO + .BR lldptool-dcbx (8), + .BR lldptool-ets (8), +diff --git a/include/lldp_util.h b/include/lldp_util.h +index 5767d4e..878426b 100644 +--- a/include/lldp_util.h ++++ b/include/lldp_util.h +@@ -170,6 +170,7 @@ int check_link_status(const char *ifname); + int get_arg_val_list(char *ibuf, int ilen, int *ioff, + char **args, char **argvals); + int get_arg_list(char *ibuf, int ilen, int *ioff, char **args); ++int get_vsistr_arg_count(int ioff, int ilen); + + #define ntohll(x) be64_to_cpu(x) + #define htonll(x) cpu_to_be64(x) +diff --git a/include/qbg_vdp22.h b/include/qbg_vdp22.h +index 45f44d5..af0aa15 100644 +--- a/include/qbg_vdp22.h ++++ b/include/qbg_vdp22.h +@@ -165,7 +165,7 @@ struct vdp22_user_data { /* Head for all VDP data */ + + struct vsi_keyword_handler { + char *keyword; +- enum vsi_mand_arg val; ++ enum vsi_key_arg val; + }; + + struct lldp_module *vdp22_register(void); +@@ -175,6 +175,7 @@ void vdp22_showvsi(struct vsi22 *p); + void vdp22_stop(char *); + int vdp22_from_ecp22(struct vdp22 *); + int vdp22_query(const char *); ++struct vdp22 *vdp22_getvdp(const char *); + int vdp22_addreq(struct vsi22 *, struct vdp22 *); + int vdp22_nlback(struct vsi22 *); + int vdp22_clntback(struct vsi22 *); +@@ -184,6 +185,8 @@ int vdp22br_resources(struct vsi22 *, int *); + int vdp22_info(const char *); + void vdp22_stop_timers(struct vsi22 *); + int vdp22_start_localchange_timer(struct vsi22 *); ++bool vdp22_cmp_fdata(struct vsi22 *, struct vsi22 *); ++void vdp22_delete_vsi(struct vsi22 *); + + /* + * Functions to get and set vlan identifier and qos. +diff --git a/include/qbg_vdp22def.h b/include/qbg_vdp22def.h +index 21ba15d..ff4270c 100644 +--- a/include/qbg_vdp22def.h ++++ b/include/qbg_vdp22def.h +@@ -30,6 +30,15 @@ + #define QBG_VDP22DEF_H + + /* ++ * Define for length of vid-mac-gid ++ * VID in string cannot be more than 4B (Max is 4K) ++ * MAC when represented as 11:22:33:44:55:66 has 17B ++ * GID is 4B ++ * The below should be more than sufficient. ++ */ ++#define MAX_GID_MAC_VID_STR 50 ++ ++/* + * Define VDP22 filter formats. + */ + enum vdp22_ffmt { /* Format of filter information */ +@@ -72,7 +81,7 @@ enum vdp22_migration_hints { + VDP22_MIGFROM = 32 /* S-bit migrate from hint */ + }; + +-enum vsi_mand_arg { ++enum vsi_key_arg { + VSI_MODE_ARG = 0, + VSI_MGRID2_ARG, + VSI_TYPEID_ARG, +diff --git a/include/qbg_vdpnl.h b/include/qbg_vdpnl.h +index 510a20c..c5c93ed 100644 +--- a/include/qbg_vdpnl.h ++++ b/include/qbg_vdpnl.h +@@ -79,4 +79,7 @@ int vdp_str2vdpnl(char *, struct vdpnl_vsi *, char *); + int vdp_vdpnl2str(struct vdpnl_vsi *, char *, size_t); + int vdp22_sendevent(struct vdpnl_vsi *); + void vdp22_freemaclist(struct vdpnl_vsi *); ++int vdp22_parse_str_vdpnl(struct vdpnl_vsi *, unsigned short *, char *); ++struct vsi22 *vdp22_alloc_vsi_ext(struct vdpnl_vsi *, int *); ++void copy_vsi_external(struct vdpnl_vsi *, struct vsi22 *, int); + #endif +diff --git a/lldp_util.c b/lldp_util.c +index 754b0cd..f1fb7b9 100644 +--- a/lldp_util.c ++++ b/lldp_util.c +@@ -199,7 +199,7 @@ int is_bond(const char *ifname) + */ + int is_san_mac(u8 *addr) + { +- int i; ++ int i; + + for ( i = 0; i < ETH_ALEN; i++) { + if ( addr[i]!= 0xff ) +@@ -215,7 +215,7 @@ int is_san_mac(u8 *addr) + * @addr: address of buffer in which to return the selected MAC address + * + * Checks to see if ifname is a slave of the bond port. If it is, +- * then a ++ * then a + * Returns 0 if a source MAC from the bond could not be found. 1 is + * returned if the slave was found in the bond. addr is updated with + * the source MAC that should be used. +@@ -287,7 +287,7 @@ int get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr) + + switch (ifb.bond_mode) { + case BOND_MODE_ACTIVEBACKUP: +- /* If current port is not the active slave, then ++ /* If current port is not the active slave, then + * if the bond MAC is equal to the port's + * permanent MAC, then find and return + * the permanent MAC of the active +@@ -297,7 +297,7 @@ int get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr) + if (strncmp(ifname, act_ifname, IFNAMSIZ)) + if (get_perm_hwaddr(ifname, addr, san_mac) == 0) + if (!memcmp(bond_mac, addr, ETH_ALEN)) +- get_perm_hwaddr(act_ifname, addr, ++ get_perm_hwaddr(act_ifname, addr, + san_mac); + break; + default: +@@ -346,7 +346,7 @@ int get_ifflags(const char *ifname) + int flags = 0; + struct ifreq ifr; + +- /* use ioctl */ ++ /* use ioctl */ + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +@@ -382,7 +382,7 @@ int get_ifpflags(const char *ifname) + int flags = 0; + struct ifreq ifr; + +- /* use ioctl */ ++ /* use ioctl */ + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +@@ -417,7 +417,7 @@ int get_iflink(const char *ifname) + snprintf(path, sizeof(path), "/sys/class/net/%s/iflink", ifname); + return read_int(path); + } +- ++ + int is_ether(const char *ifname) + { + /* check for bridge in sysfs */ +@@ -486,7 +486,7 @@ int is_slave(const char *ifmaster, const char *ifslave) + } + } + } +- ++ + out_done: + return rc; + } +@@ -562,13 +562,13 @@ int is_bridge(const char *ifname) + if (dirp) { + closedir(dirp); + rc = 1; +- } else { +- /* use ioctl */ ++ } else { ++ /* use ioctl */ + fd = get_ioctl_socket(); + if (fd >= 0) { + struct ifreq ifr; + struct __bridge_info bi; +- unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO, ++ unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO, + (unsigned long) &bi, 0, 0 }; + + ifr.ifr_data = (char *)args; +@@ -748,7 +748,7 @@ int is_autoneg_supported(const char *ifname) + int fd; + struct ifreq ifr; + struct ethtool_cmd cmd; +- ++ + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +@@ -769,7 +769,7 @@ int is_autoneg_enabled(const char *ifname) + int fd; + struct ifreq ifr; + struct ethtool_cmd cmd; +- ++ + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +@@ -806,7 +806,7 @@ int get_maucaps(const char *ifname) + u16 caps = MAUCAPADV_bOther; + struct ifreq ifr; + struct ethtool_cmd cmd; +- ++ + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +@@ -940,7 +940,7 @@ u16 get_caps(const char *ifname) + + /* how to find TPID to determine C-VLAN vs. S-VLAN ? */ + if (is_vlan(ifname)) +- caps |= SYSCAP_CVLAN; ++ caps |= SYSCAP_CVLAN; + + if (is_bridge(ifname)) + caps |= SYSCAP_BRIDGE; +@@ -1282,3 +1282,25 @@ int get_arg_list(char *ibuf, int ilen, int *ioff, char **args) + free(arglens); + return numargs; + } ++ ++/* ++ * This functionality can be seen in many places to convert a LenData to a ++ * argument array. ++ */ ++ ++int get_vsistr_arg_count(int ioff, int ilen) ++{ ++ int offset; ++ int numargs; ++ ++ offset = ioff; ++ for (numargs = 0; (ilen - offset) > 2; numargs++) { ++ offset += 2; ++ if (ilen - offset > 0) { ++ offset++; ++ if (ilen - offset > 4) ++ offset += 4; ++ } ++ } ++ return numargs; ++} +diff --git a/qbg/vdp22.c b/qbg/vdp22.c +index a3cb7c9..af11af8 100644 +--- a/qbg/vdp22.c ++++ b/qbg/vdp22.c +@@ -219,7 +219,7 @@ void vdp22_showvsi(struct vsi22 *p) + /* + * Delete a complete VSI node not on queue. + */ +-static void vdp22_delete_vsi(struct vsi22 *p) ++void vdp22_delete_vsi(struct vsi22 *p) + { + LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, + p->vsi[0]); +@@ -477,14 +477,15 @@ static bool filter_ok(unsigned char ffmt, struct fid22 *fp, + * Allocate a VSI node with filter information data. + * Check if input data is valid. + */ +-static struct vsi22 *vdp22_alloc_vsi(struct vdpnl_vsi *vsi, struct vdp22 *vdp, +- int *rc) ++static struct vsi22 *vdp22_alloc_vsi_int(struct vdpnl_vsi *vsi, ++ struct vdp22 *vdp, ++ int *rc, bool vsinl_chk) + { + struct vsi22 *p; + int i; + + *rc = -EINVAL; +- if (!check_vsinl(vsi)) ++ if (vsinl_chk && (!check_vsinl(vsi))) + return NULL; + p = calloc(1, sizeof(*p)); + if (!p) { +@@ -546,6 +547,16 @@ error1: + return NULL; + } + ++struct vsi22 *vdp22_alloc_vsi_ext(struct vdpnl_vsi *vsinl, int *rc) ++{ ++ struct vdp22 *vdp; ++ ++ vdp = vdp22_getvdp(vsinl->ifname); ++ if (!vdp) ++ return NULL; ++ return vdp22_alloc_vsi_int(vsinl, vdp, rc, false); ++} ++ + /* + * Allocate a VSI node with filter information data. + * Check if input data is valid. Data was received by bridge from unknown +@@ -750,7 +761,7 @@ static struct vdp22 *vdp22_create(const char *ifname, + /* + * Query the supported VDP protocol on an interface. + */ +-static struct vdp22 *vdp22_getvdp(const char *ifname) ++struct vdp22 *vdp22_getvdp(const char *ifname) + { + struct vdp22 *vdp; + +@@ -820,7 +831,7 @@ int vdp22_request(struct vdpnl_vsi *vsi, int clif) + /* Adjust numbering for VDP 0.2 protocol from netlink */ + if (!clif) + vsi->request += 1; +- p = vdp22_alloc_vsi(vsi, vdp, &rc); ++ p = vdp22_alloc_vsi_int(vsi, vdp, &rc, true); + if (p) { + rc = vdp22_addreq(p, vdp); + if (rc) +@@ -1079,3 +1090,8 @@ int vdp22_info(const char *ifname) + return rc; + + } ++ ++void copy_vsi_external(struct vdpnl_vsi *vsi, struct vsi22 *p, int clif) ++{ ++ copy_vsi(vsi, p, clif); ++} +diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c +index dde4669..409858d 100644 +--- a/qbg/vdp22_cmds.c ++++ b/qbg/vdp22_cmds.c +@@ -237,7 +237,7 @@ int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, + return cmd_not_applicable; + } + +- if (!(cmd.ops & op_config)) ++ if (!(cmd.ops & op_config) && (cmd.cmd != cmd_gettlv)) + return cmd_invalid; + + snprintf(rbuf, rlen, "%c%1x%02x%08x%02x%s", +@@ -254,10 +254,9 @@ int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, + snprintf(rbuf + roff, rlen - roff, "%08x", cmd.tlvid); + roff += 8; + if (cmd.cmd == cmd_gettlv) { +- rstatus = handle_get_arg(&cmd, ARG_VDP22_VSI, +- NULL, +- rbuf + strlen(rbuf), +- rlen - strlen(rbuf)); ++ rstatus = handle_get_arg(&cmd, ARG_VDP22_VSI, ibuf + ioff, ++ rbuf + strlen(rbuf), ++ rlen - strlen(rbuf)); + } else { + rstatus = handle_test_arg(&cmd, ARG_VDP22_VSI, + ibuf + ioff, +@@ -392,19 +391,25 @@ static int test_arg_vsi(struct cmd *cmd, UNUSED char *arg, char *argvalue, + */ + static int catvsis(struct vdpnl_vsi *vsi, char *out, size_t out_len) + { +- int rc, i; ++ int rc, i, len, c; + size_t used = 0; + unsigned char wanted_req = vsi->request; ++ char tmp_buf[MAX_CLIF_MSGBUF]; + ++ memset(tmp_buf, 0, sizeof(tmp_buf)); + for (i = 1; vdp22_status(i, vsi, 1) > 0; ++i) { + if (wanted_req != vsi->request) { + vdp22_freemaclist(vsi); + continue; + } +- rc = vdp_vdpnl2str(vsi, out + used, out_len - used); ++ rc = vdp_vdpnl2str(vsi, tmp_buf, out_len - used); ++ len = strlen(tmp_buf); ++ c = snprintf(out + used, out_len - used, "%04x%s", len, ++ tmp_buf); ++ if ((c < 0) || ((unsigned)c >= (out_len - used))) ++ return 0; + vdp22_freemaclist(vsi); + if (rc) { +- strcat(out, ";"); + used = strlen(out); + } else + return 0; +@@ -413,15 +418,113 @@ static int catvsis(struct vdpnl_vsi *vsi, char *out, size_t out_len) + } + + /* ++ * Based on the VSI arguments specified, checks if it matches. ++ * This does't check for all VSI parameters. ++ */ ++ ++static bool vdp22_partial_vsi_equal(struct vsi22 *p1, struct vsi22 *p2, ++ enum vsi_key_arg vsi_arg_key_flags) ++{ ++ enum vsi_key_arg key_enum; ++ ++ for (key_enum = VSI_MODE_ARG; key_enum < VSI_INVALID_ARG; key_enum++) { ++ if (!((1 << key_enum) & vsi_arg_key_flags)) ++ continue; ++ switch (key_enum) { ++ case VSI_MODE_ARG: ++ break; ++ case VSI_MGRID2_ARG: ++ if (memcmp(p1->mgrid, p2->mgrid, ++ sizeof(p2->mgrid))) ++ return false; ++ case VSI_TYPEID_ARG: ++ if (p1->type_id != p2->type_id) ++ return false; ++ break; ++ case VSI_TYPEIDVER_ARG: ++ if (p1->type_ver != p2->type_ver) ++ return false; ++ break; ++#ifdef LATER ++/* Currently not supported */ ++ case VSI_VSIIDFRMT_ARG: ++ if (p1->vsi_fmt != p2->vsi_fmt) ++ return false; ++ break; ++#endif ++ case VSI_VSIID_ARG: ++ if (memcmp(p1->vsi, p2->vsi, sizeof(p1->vsi))) ++ return false; ++ break; ++ case VSI_FILTER_ARG: ++ if ((p1->fif != p2->fif) || (!vdp22_cmp_fdata(p1, p2))) ++ return false; ++ break; ++ case VSI_HINTS_ARG: ++ break; ++ default: ++ return false; ++ } ++ } ++ return true; ++} ++ ++static int get_vsi_partial_arg(UNUSED char *arg, char *orig_argvalue, ++ struct vdpnl_vsi *vsinl, char *out, ++ size_t out_len) ++{ ++ char tmp_buf[MAX_CLIF_MSGBUF]; ++ struct vsi22 *p, *vsi; ++ struct vdp22 *vdp; ++ size_t used = 0; ++ int rc = -ENOMEM, len, c; ++ u16 vsi_arg_key_flags = 0; ++ ++ if (vdp22_parse_str_vdpnl(vsinl, &vsi_arg_key_flags, orig_argvalue)) ++ goto out; ++ vdp = vdp22_getvdp(vsinl->ifname); ++ if (!vdp) ++ goto out; ++ ++ vsi = vdp22_alloc_vsi_ext(vsinl, &rc); ++ if (!vsi) ++ goto out; ++ LIST_FOREACH(p, &vdp->vsi22_que, node) { ++ if (p->vsi_mode != vsi->vsi_mode) ++ continue; ++ if (vdp22_partial_vsi_equal(p, vsi, vsi_arg_key_flags)) { ++ copy_vsi_external(vsinl, p, 1); ++ rc = vdp_vdpnl2str(vsinl, tmp_buf, out_len - used); ++ len = strlen(tmp_buf); ++ c = snprintf(out + used, out_len - used, "%04x%s", ++ len, tmp_buf); ++ vdp22_freemaclist(vsinl); ++ if ((c < 0) || ((unsigned)c >= (out_len - used))) ++ goto out_delvsi; ++ if (rc) ++ used = strlen(out); ++ else ++ goto out_delvsi; ++ } ++ } ++out_delvsi: ++ vdp22_delete_vsi(vsi); ++out: ++ return rc; ++} ++ ++/* + * Return all VSIs on a particular interface into one string. + */ +-static int get_arg_vsi(struct cmd *cmd, char *arg, UNUSED char *argvalue, ++static int get_arg_vsi(struct cmd *cmd, char *arg, char *argvalue, + char *obuf, int obuf_len) + { + cmd_status good_cmd = vdp22_cmdok(cmd, cmd_gettlv); + struct vdpnl_vsi vsi; + char vsi_str[MAX_CLIF_MSGBUF]; + int rc; ++ int fsize = (cmd->ops >> OP_FID_POS) & 0xff; ++ struct vdpnl_mac mac[fsize]; + + if (good_cmd != cmd_success) + return good_cmd; +@@ -433,14 +536,20 @@ static int get_arg_vsi(struct cmd *cmd, char *arg, UNUSED char *argvalue, + + memset(obuf, 0, obuf_len); + memset(&vsi, 0, sizeof(vsi)); ++ memset(vsi_str, 0, sizeof(vsi_str)); + vsi.request = cmd->tlvid; + strncpy(vsi.ifname, cmd->ifname, sizeof(vsi.ifname) - 1); + good_cmd = cmd_failed; +- if (!catvsis(&vsi, vsi_str, sizeof(vsi_str))) ++ if ((cmd->ops & op_config) && (cmd->ops & op_arg)) { ++ memset(&mac, 0, sizeof(mac)); ++ vsi.macsz = fsize; ++ vsi.maclist = mac; ++ if (!get_vsi_partial_arg(arg, argvalue, &vsi, vsi_str, ++ sizeof(vsi_str))) ++ goto out; ++ } else if (!catvsis(&vsi, vsi_str, sizeof(vsi_str))) + goto out; +- rc = snprintf(obuf, obuf_len, "%02x%s%04x%s", +- (unsigned int)strlen(arg), arg, (unsigned int)strlen(vsi_str), +- vsi_str); ++ rc = snprintf(obuf, obuf_len, "%s", vsi_str); + if (rc > 0 || rc < obuf_len) + good_cmd = cmd_success; + out: +diff --git a/qbg/vdp22sm.c b/qbg/vdp22sm.c +index d1f65b4..6264f74 100644 +--- a/qbg/vdp22sm.c ++++ b/qbg/vdp22sm.c +@@ -944,7 +944,8 @@ static bool cmp_fdata1(struct fid22 *p1, struct fid22 *p2, unsigned char fif) + + if (fif == VDP22_FFMT_MACVID || fif == VDP22_FFMT_GROUPMACVID) + is_good = !memcmp(p1->mac, p2->mac, sizeof(p1->mac)); +- if (fif == VDP22_FFMT_GROUPVID || fif == VDP22_FFMT_GROUPMACVID) ++ if (is_good && ++ (fif == VDP22_FFMT_GROUPVID || fif == VDP22_FFMT_GROUPMACVID)) + is_good = (p1->grpid == p2->grpid); + if (is_good) { + if (vdp22_get_vlanid(p1->vlan)) +@@ -956,7 +957,7 @@ static bool cmp_fdata1(struct fid22 *p1, struct fid22 *p2, unsigned char fif) + return is_good; + } + +-static bool vdp22_cmp_fdata(struct vsi22 *p, struct vsi22 *vsip) ++bool vdp22_cmp_fdata(struct vsi22 *p, struct vsi22 *vsip) + { + int i; + +diff --git a/qbg/vdp_ascii.c b/qbg/vdp_ascii.c +index 09e53c6..76dde4a 100644 +--- a/qbg/vdp_ascii.c ++++ b/qbg/vdp_ascii.c +@@ -110,6 +110,15 @@ static bool getnumber(char *s, unsigned int min, unsigned int max, + } + + /* ++ * Returns the byte length of a given number ++ */ ++ ++static int get_strlen_num(unsigned long no) ++{ ++ return snprintf(NULL, 0, "%lu", no); ++} ++ ++/* + * Read filter information data. The format is an ascii string: + * filter-data filter-format + * vlan 1 +@@ -264,7 +273,7 @@ static bool getmode(struct vdpnl_vsi *p, char *s) + return true; + } + +-enum vsi_mand_arg get_keywork_val(char *keyword) ++enum vsi_key_arg get_keywork_val(char *keyword) + { + int count, key_str_size; + +@@ -276,65 +285,36 @@ enum vsi_mand_arg get_keywork_val(char *keyword) + return VSI_INVALID_ARG; + } + +-/* +- * Parse the mode parameter to create/change an VSI assoication. +- * The format is a comma separated list of tokens: +- * cmd,mgrid,typeid,typeidversion,vsiid,hints,fid[,fid,fid,...] +- * with +- * cmd := "assoc" | "deassoc" | "preassoc" | "preassoc-rr" +- * mgrid := less or equal to 16 byte alphanumeric characters +- * | UUID (with dashes in between) +- * typeid := number in range of 1 - 2^24 -1 +- * typeidversion:= number in range of 1 - 255 +- * vsiid := UUID (with dashes in between) +- * hints := varies between input (command) and output (event message) +- * on input --> dash (-) | "none" | "from" | "to" +- * on output --> response (number between 0..255) +- * fid := vlan +- * | vlan-mac +- * | vlan--group +- * | vlan-mac-group +- * vlan := number in range of 1..2^16 -1 +- * group := number in range of 1..2^32 - 1 +- * mac := xx:xx:xx:xx:xx:xx +- */ +- +-static int str2vdpnl(char *orig_argvalue, struct vdpnl_vsi *vsi) ++int vdp22_parse_str_vdpnl(struct vdpnl_vsi *vsi, u16 *key_flags, ++ char *orig_argvalue) + { +- char **args; + char **argvals; ++ char **args; + char *argvalue; ++ enum vsi_key_arg vsi_key; + int rc = -ENOMEM; ++ int i, ioff = 0, numargs; ++ int ilen = strlen(orig_argvalue); + unsigned int no; + unsigned short idx = 0; +- int i, ioff = 0, offset; +- int ilen = strlen(orig_argvalue); +- int numargs; +- enum vsi_mand_arg vsi_key; +- u16 vsi_mand_mask = (1 << VSI_MAND_NUM_ARG) - 1; + u16 num_arg_keys = 0; + + argvalue = strdup(orig_argvalue); + if (!argvalue) + goto out; + /* Count args and argvalues */ +- offset = ioff; +- for (numargs = 0; (ilen - offset) > 2; numargs++) { +- offset += 2; +- if (ilen - offset > 0) { +- offset++; +- if (ilen - offset > 4) +- offset += 4; +- } +- } ++ numargs = get_vsistr_arg_count(ioff, ilen); ++ if (numargs == 0) ++ goto out_argvalue; + args = calloc(numargs, sizeof(char *)); + if (!args) + goto out_argvalue; +- + argvals = calloc(numargs, sizeof(char *)); + if (!argvals) + goto out_args; + numargs = get_arg_val_list(argvalue, ilen, &ioff, args, argvals); ++ if (numargs == 0) ++ goto out_free; + for (i = 0; i < numargs; i++) { + vsi_key = get_keywork_val(args[i]); + switch (vsi_key) { +@@ -378,9 +358,9 @@ static int str2vdpnl(char *orig_argvalue, struct vdpnl_vsi *vsi) + } + num_arg_keys |= (1 << vsi_key); + } +- /* Return error if no filter information provided */ +- if ((num_arg_keys & vsi_mand_mask) == vsi_mand_mask) +- rc = 0; ++ *key_flags = num_arg_keys; ++ rc = 0; ++ + out_free: + free(argvals); + out_args: +@@ -392,6 +372,44 @@ out: + } + + /* ++ * Parse the mode parameter to create/change an VSI assoication. ++ * The format is a comma separated list of tokens: ++ * cmd,mgrid,typeid,typeidversion,vsiid,hints,fid[,fid,fid,...] ++ * with ++ * cmd := "assoc" | "deassoc" | "preassoc" | "preassoc-rr" ++ * mgrid := less or equal to 16 byte alphanumeric characters ++ * | UUID (with dashes in between) ++ * typeid := number in range of 1 - 2^24 -1 ++ * typeidversion:= number in range of 1 - 255 ++ * vsiid := UUID (with dashes in between) ++ * hints := varies between input (command) and output (event message) ++ * on input --> dash (-) | "none" | "from" | "to" ++ * on output --> response (number between 0..255) ++ * fid := vlan ++ * | vlan-mac ++ * | vlan--group ++ * | vlan-mac-group ++ * vlan := number in range of 1..2^16 -1 ++ * group := number in range of 1..2^32 - 1 ++ * mac := xx:xx:xx:xx:xx:xx ++ */ ++ ++static int str2vdpnl(char *orig_argvalue, struct vdpnl_vsi *vsi) ++{ ++ int rc = -ENOMEM; ++ u16 vsi_mand_mask = (1 << VSI_MAND_NUM_ARG) - 1; ++ u16 num_arg_keys = 0; ++ ++ if (vdp22_parse_str_vdpnl(vsi, &num_arg_keys, orig_argvalue)) ++ goto out; ++ /* Return error if no filter information provided */ ++ if ((num_arg_keys & vsi_mand_mask) == vsi_mand_mask) ++ rc = 0; ++out: ++ return rc; ++} ++ ++/* + * Fill the vdpnl_vsi structure from the string. + * Allocate the maclist. Must be free'ed by caller. + */ +@@ -426,6 +444,7 @@ static char *check_and_update(size_t *total, size_t *length, char *s, int c) + /* + * Convert VSI association to string. + */ ++#ifdef LATER_USE + static const char *mode2str(unsigned char x) + { + if (x == VDP22_ASSOC) +@@ -438,6 +457,7 @@ static const char *mode2str(unsigned char x) + return "deassoc"; + return "unknown"; + } ++#endif + + /* + * Convert filter information format into vlan[-mac][-group] string. +@@ -448,26 +468,50 @@ static int fid2str(char *s, size_t length, int fif, struct vdpnl_mac *p) + { + int c; + size_t total = 0; ++ char tmp_buf[MAX_GID_MAC_VID_STR]; + +- c = snprintf(s, length, "%d", vdp22_set_qos(p->qos) | +- vdp22_set_vlanid(p->vlan)); ++ c = snprintf(s, length, "%02x%s", ++ (unsigned int)strlen(VSI22_ARG_FILTER_STR), ++ VSI22_ARG_FILTER_STR); + s = check_and_update(&total, &length, s, c); + if (!s) + goto out; +- if (fif == VDP22_FFMT_MACVID || fif == VDP22_FFMT_GROUPMACVID) { +- c = snprintf(s, length, "-%02x:%02x:%02x:%02x:%02x:%02x", +- p->mac[0], p->mac[1], p->mac[2], p->mac[3], +- p->mac[4], p->mac[5]); +- s = check_and_update(&total, &length, s, c); +- if (!s) +- goto out; +- } +- if (fif == VDP22_FFMT_GROUPVID || fif == VDP22_FFMT_GROUPMACVID) { +- c = snprintf(s, length, "-%ld", p->gpid); +- s = check_and_update(&total, &length, s, c); +- if (!s) +- goto out; ++ memset(tmp_buf, 0, sizeof(tmp_buf)); ++ switch (fif) { ++ case VDP22_FFMT_VID: ++ snprintf(tmp_buf, MAX_GID_MAC_VID_STR, "%d", ++ vdp22_set_qos(p->qos) | ++ vdp22_set_vlanid(p->vlan)); ++ break; ++ case VDP22_FFMT_MACVID: ++ snprintf(tmp_buf, MAX_GID_MAC_VID_STR, ++ "%d-%02x:%02x:%02x:%02x:%02x:%02x", ++ vdp22_set_qos(p->qos) | ++ vdp22_set_vlanid(p->vlan), ++ p->mac[0], p->mac[1], p->mac[2], p->mac[3], ++ p->mac[4], p->mac[5]); ++ break; ++ case VDP22_FFMT_GROUPVID: ++ snprintf(tmp_buf, MAX_GID_MAC_VID_STR, ++ "%d-%ld", ++ vdp22_set_qos(p->qos) | vdp22_set_vlanid(p->vlan), ++ p->gpid); ++ break; ++ case VDP22_FFMT_GROUPMACVID: ++ snprintf(tmp_buf, MAX_GID_MAC_VID_STR, ++ "%d-%02x:%02x:%02x:%02x:%02x:%02x-%ld", ++ vdp22_set_qos(p->qos) | vdp22_set_vlanid(p->vlan), ++ p->mac[0], p->mac[1], p->mac[2], p->mac[3], ++ p->mac[4], p->mac[5], p->gpid); ++ break; ++ default: ++ break; + } ++ c = snprintf(s, length, "%04x%s", (unsigned int)strlen(tmp_buf), ++ tmp_buf); ++ s = check_and_update(&total, &length, s, c); ++ if (!s) ++ goto out; + out: + return s ? total : 0; + } +@@ -500,15 +544,28 @@ int vdp_vdpnl2str(struct vdpnl_vsi *p, char *s, size_t length) + char instance[VDP_UUID_STRLEN + 2]; + + mgrid2str(instance, p, sizeof(instance)); +- c = snprintf(s, length, "%s,%s,%ld,%d,", +- mode2str(p->request), instance, p->vsi_typeid, +- p->vsi_typeversion); ++ c = snprintf(s, length, "%02x%s%04x%s%02x%s%04x%lu%02x%s%04x%d", ++ (unsigned int)strlen(VSI22_ARG_MGRID_STR), ++ VSI22_ARG_MGRID_STR, ++ (unsigned int)strlen(instance), instance, ++ (unsigned int)strlen(VSI22_ARG_TYPEID_STR), ++ VSI22_ARG_TYPEID_STR, get_strlen_num(p->vsi_typeid), ++ p->vsi_typeid, ++ (unsigned int)strlen(VSI22_ARG_TYPEIDVER_STR), ++ VSI22_ARG_TYPEIDVER_STR, ++ get_strlen_num(p->vsi_typeversion), p->vsi_typeversion); + s = check_and_update(&total, &length, s, c); + if (!s) + goto out; + + vdp_uuid2str(p->vsi_uuid, instance, sizeof(instance)); +- c = snprintf(s, length, "%s,%d,", instance, p->response); ++ c = snprintf(s, length, "%02x%s%04x%s%02x%s%04x%d", ++ (unsigned int)strlen(VSI22_ARG_VSIID_STR), ++ VSI22_ARG_VSIID_STR, (unsigned int)strlen(instance), ++ instance, ++ (unsigned int)strlen(VSI22_ARG_HINTS_STR), ++ VSI22_ARG_HINTS_STR, ++ get_strlen_num(p->response), p->response); + s = check_and_update(&total, &length, s, c); + if (!s) + goto out; +@@ -519,13 +576,8 @@ int vdp_vdpnl2str(struct vdpnl_vsi *p, char *s, size_t length) + s = check_and_update(&total, &length, s, c); + if (!c) + goto out; +- if (p->macsz > 1 && i < p->macsz - 1) { +- c = snprintf(s, length, ","); +- s = check_and_update(&total, &length, s, c); +- if (!s) +- goto out; +- } + } ++ + out: + return s ? total : 0; + } +diff --git a/vdptool.c b/vdptool.c +index f506020..551e829 100644 +--- a/vdptool.c ++++ b/vdptool.c +@@ -53,6 +53,7 @@ + + #include "qbg22.h" + #include "qbg_vdp22_clif.h" ++#include "lldp_util.h" + + static char *print_status(cmd_status status) + { +@@ -129,7 +130,7 @@ static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals) + + len = sizeof(cmd->obuf); + +- if (cmd->cmd == cmd_settlv) { ++ if ((cmd->cmd == cmd_settlv) || (cmd->cmd == cmd_gettlv)) { + for (i = 0; i < argc; i++) { + if (args[i]) { + if (!strncasecmp(args[i], "filter", +@@ -208,13 +209,6 @@ static int vdp_cmd_gettlv(struct clif *clif, int argc, char *argv[], + cmd->ops |= op_arg; + } + +- for (i = 0; i < numargs; i++) { +- if (argvals[i]) { +- printf("%s\n", print_status(cmd_invalid)); +- goto out; +- } +- } +- + render_cmd(cmd, argc, args, argvals); + free(args); + free(argvals); +@@ -305,125 +299,61 @@ static int vdp_parse_response(char *buf) + return hex2u8(buf + CLIF_STAT_OFF); + } + +-static void print_pair(char *arg, size_t arglen, char *value, size_t valuelen) ++int get_vsi_args(char *ibuf) + { +- while (arglen--) +- putchar(*arg++); +- putchar('='); +- while (valuelen--) +- putchar(*value++); +- putchar('\n'); +-} ++ int ioff = 0; ++ char **args; ++ char **argvals; ++ int numargs, i; ++ int ilen = strlen(ibuf); + +-static int print_arg_value(char *ibuf) +-{ +- int arglen, valuelen, offset = 0, ilen = strlen(ibuf); +- char *arg, *value; ++ /* count args and argvalus */ ++ numargs = get_vsistr_arg_count(ioff, ilen); + +- while (offset < ilen) { +- /* Length of argument */ +- arglen = hex2u8(ibuf + offset); +- if (arglen < 0) +- break; +- offset += 2; +- arg = ibuf + offset; +- offset += arglen; ++ args = calloc(numargs, sizeof(char *)); ++ if (!args) ++ return cmd_failed; + +- /* Length of argument value */ +- valuelen = hex2u16(ibuf + offset); +- if (valuelen < 0) +- break; +- offset += 4; +- value = ibuf + offset; +- offset += valuelen; ++ argvals = calloc(numargs, sizeof(char *)); ++ if (!argvals) { ++ free(args); ++ return cmd_failed; ++ } + +- print_pair(arg, arglen, value, valuelen); ++ numargs = get_arg_val_list(ibuf, ilen, &ioff, args, argvals); ++ for (i = 0; i < numargs; i++) { ++ printf("\t%s", args[i]); ++ printf(" = %s\n", argvals[i]); + } +- return offset; +-} + +-static int get_tlvid(char *ibuf) +-{ +- return hex2u32(ibuf); ++ free(args); ++ free(argvals); ++ return ioff; + } + +-/* +- * Print a TLV. +- */ +-static void print_tlv2(char *ibuf) ++static void print_all_vsis(char *ibuf) + { + size_t ilen = strlen(ibuf); +- u16 tlv_type; +- u16 tlv_len; +- u32 tlvid; +- int offset = 0; +- int printed; +- struct lldp_module *np; ++ u16 vsi_len; ++ int offset = 0, vsi_cnt = 0; ++ char tmp_ibuf[strlen(ibuf)]; + + while (ilen > 0) { +- tlv_len = 2 * sizeof(u16); +- if (ilen < 2 * sizeof(u16)) { +- printf("corrupted TLV ilen:%zd, tlv_len:%d\n", +- ilen, tlv_len); +- break; +- } +- tlv_type = hex2u16(ibuf + offset); +- tlv_len = tlv_type; +- tlv_type >>= 9; +- tlv_len &= 0x01ff; ++ vsi_len = hex2u16(ibuf + offset); ++ if (vsi_len > ilen) ++ return; + offset += 2 * sizeof(u16); + ilen -= 2 * sizeof(u16); +- +- if (ilen < (unsigned) 2 * tlv_len) { +- printf("corrupted TLV ilen:%zd, tlv_len:%d\n", +- ilen, tlv_len); +- break; +- } +- tlvid = tlv_type; +- if (tlvid == INVALID_TLVID) { +- tlvid = get_tlvid(ibuf + offset); +- offset += 8; +- } +- printed = 0; +- LIST_FOREACH(np, &lldp_head, lldp) { +- if (np->ops->print_tlv(tlvid, tlv_len, ibuf + offset)) { +- printed = 1; +- break; +- } +- } +- +- if (!printed) { +- if (tlvid < INVALID_TLVID) +- printf("Unidentified TLV\n\ttype:%d %*.*s\n", +- tlv_type, tlv_len*2, tlv_len*2, +- ibuf+offset); +- else +- printf("Unidentified Org Specific TLV\n\t" +- "OUI: 0x%06x, Subtype: %d, Info: %*.*s\n", +- tlvid >> 8, tlvid & 0x0ff, +- tlv_len*2-8, tlv_len*2-8, +- ibuf+offset); +- } +- if (tlvid > INVALID_TLVID) +- offset += (2 * tlv_len - 8); +- else +- offset += 2 * tlv_len; +- ilen -= 2 * tlv_len; +- if (tlvid == END_OF_LLDPDU_TLV) +- break; ++ strncpy(tmp_ibuf, ibuf + offset, vsi_len); ++ tmp_ibuf[vsi_len] = '\0'; ++ printf("%s %d:\n", "VSI ", vsi_cnt); ++ get_vsi_args(tmp_ibuf); ++ offset += vsi_len; ++ ilen -= vsi_len; ++ vsi_cnt++; + } + } + +-/* Print reply from get command */ +-static void print_tlvs(struct cmd *cmd, char *ibuf) +-{ +- if (cmd->ops & op_config) { +- print_arg_value(ibuf); +- return; +- } +- print_tlv2(ibuf); +-} +- + static void print_cmd_response(char *ibuf, int status) + { + struct cmd cmd; +@@ -455,7 +385,7 @@ static void print_cmd_response(char *ibuf, int status) + + switch (cmd.cmd) { + case cmd_gettlv: +- print_tlvs(&cmd, ibuf + ioff); ++ print_all_vsis(ibuf + ioff); + break; + case cmd_settlv: + printf("%s", ibuf + ioff); +@@ -708,7 +638,7 @@ static int _clif_command(struct clif *clif, char *cmd, int print) + size_t len; + int ret; + int rc; +- char reply[100]; ++ char reply[200]; + size_t reply_len2 = sizeof(reply); + + print_raw_message(cmd, print); +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-6-VDP-Support-in-VDP22-for-correct-error-code-status-t.patch b/open-lldp-v1.0.1-6-VDP-Support-in-VDP22-for-correct-error-code-status-t.patch new file mode 100644 index 0000000..0c54df6 --- /dev/null +++ b/open-lldp-v1.0.1-6-VDP-Support-in-VDP22-for-correct-error-code-status-t.patch @@ -0,0 +1,894 @@ +From faf19bd8bdb1a6ca0dd98843cd09fd96b1f2f901 Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:37:57 +0000 +Subject: [PATCH] VDP: Support in VDP22 for correct error code/status to + vdptool + +This commit has the following changes: +a. Returning the status or error code to vdptool for the error cases. Errors +can be Tx error, invalid parameters, incorrect configuration etc. The vdptool + is modified to print the error messages from lldpad. +b. Modify the vdptool option from set-tlv/get-tlv to set-vsi/get-vsi. The + vdptool man page document is also modified accordingly. +c. Re-arrange the definitions in header files. +d. Fix some formatting issues. + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + docs/vdptool.8 | 12 ++-- + include/lldpad_status.h | 25 +++++---- + include/qbg_vdp22.h | 50 +++++++++-------- + include/qbg_vdp22_clif.h | 8 +++ + include/qbg_vdp22def.h | 39 +++++++++++++ + qbg/vdp22.c | 20 ++++++- + qbg/vdp22_cmds.c | 63 +++++++++++++++------ + qbg/vdp22sm.c | 15 ----- + qbg/vdp_ascii.c | 56 +++++++++++++++---- + vdptool.c | 141 ++++++++++++++++++++++++++++++++++++++--------- + 10 files changed, 316 insertions(+), 113 deletions(-) + +diff --git a/docs/vdptool.8 b/docs/vdptool.8 +index 02b4e8e..0b50a13 100644 +--- a/docs/vdptool.8 ++++ b/docs/vdptool.8 +@@ -98,7 +98,7 @@ Wait for the bridge response message + .SS VSI Parameter + Each VDP22 TLVs contains a command mode, manager identifier, + type identifier, type identifier version, VSI instance identifier, +-migiration hints and filter information. ++migration hints and filter information. + The fields are explained next: + .TP + .B "mode (Command Mode):" +@@ -140,7 +140,7 @@ an UUID according to RFC 4122 + with optional dashes in between. + .TP + .B "hints (Migration Hints):" +-The migiration hints is a string aiding in ++The migration hints is a string aiding in + migration of virtual machines: + .RS + .IP none: +@@ -193,11 +193,11 @@ show usage information + .B \-v, version + show version information + .TP +-.B \-t, get-tlv +-get TLV information for the specified interface ++.B \-t, get-vsi ++get VSI information for the specified interface + .TP +-.B \-T, set-tlv +-set TLV information for the specified interface ++.B \-T, set-vsi ++set VSI information for the specified interface + .TP + .B \-p, ping + display the process identifier of the running lldpad process +diff --git a/include/lldpad_status.h b/include/lldpad_status.h +index df6e0f7..568063b 100644 +--- a/include/lldpad_status.h ++++ b/include/lldpad_status.h +@@ -33,18 +33,19 @@ + #define LLDPAD_STATUS_H + + typedef enum { +- cmd_success = 0, +- cmd_failed, +- cmd_device_not_found, +- cmd_agent_not_found, +- cmd_invalid, +- cmd_bad_params, +- cmd_peer_not_present, +- cmd_ctrl_vers_not_compatible, +- cmd_not_capable, +- cmd_not_applicable, +- cmd_no_access, +- cmd_agent_not_supported, ++ cmd_success = 0, ++ cmd_failed, ++ cmd_device_not_found, ++ cmd_agent_not_found, ++ cmd_invalid, ++ cmd_bad_params, ++ cmd_peer_not_present, ++ cmd_ctrl_vers_not_compatible, ++ cmd_not_capable, ++ cmd_not_applicable, ++ cmd_no_access, ++ cmd_agent_not_supported, ++ cmd_max_status, + } cmd_status; + + #endif /* LLDPAD_STATUS_H */ +diff --git a/include/qbg_vdp22.h b/include/qbg_vdp22.h +index af0aa15..6c3c9ee 100644 +--- a/include/qbg_vdp22.h ++++ b/include/qbg_vdp22.h +@@ -65,22 +65,36 @@ enum vdp22_role { /* State for VDP22 bridge processing */ + VDP22_STATION /* State role */ + }; + +-enum vdp22_cmdresp { /* VDP22 Protocol command responses */ +- VDP22_RESP_SUCCESS = 0, /* Success */ +- VDP22_RESP_INVALID_FORMAT = 1, +- VDP22_RESP_NO_RESOURCES = 2, +- VDP22_RESP_NO_VSIMGR = 3, /* No contact to VSI manager */ +- VDP22_RESP_OTHER = 4, /* Other reasons */ +- VDP22_RESP_NOADDR = 5, /* Invalid VID, MAC, GROUP etc */ +- VDP22_RESP_DEASSOC = 252, /* Deassoc response */ +- VDP22_RESP_TIMEOUT = 253, /* Timeout response */ +- VDP22_RESP_KEEP = 254, /* Keep response */ +- VDP22_RESP_NONE = 255 /* No response returned so far */ ++/* ++ * VSI information. One node per matching entry (same mgrid, type_id, type_ver, ++ * id_fmt, id and fif). Filter data can be added and removed. ++ */ ++enum vsi22_flags { /* Flags (or'ed in) */ ++ VDP22_BUSY = 1, /* This node is under work */ ++ VDP22_DELETE_ME = 2, /* Deallocate this node */ ++ VDP22_RETURN_VID = 4, /* Return wildcard vlan id */ ++ VDP22_NOTIFY = 8, /* Send netlink message to requestor */ ++ VDP22_NLCMD = 16 /* Netlink command pending */ ++}; ++ ++enum { /* VDP22 Protocol command responses */ ++ USEC_PER_SEC = 1000000, /* Microseconds per second */ ++ VDP22_RESBIT = 0x80, /* VSI reserved bit */ ++ VDP22_ACKBIT = 0x40, /* VSI Acknowledgement bit */ ++ VDP22_KEEPBIT = 0x20, /* VSI keep error bit */ ++ VDP22_HARDBIT = 0x10, /* VSI hard error bit */ ++ VDP22_STATUS_MASK = 0x0f, /* Status mask */ ++ VDP22_STATUS_SHIFT = 0, /* Status offset */ + }; + + enum { + VDP22_MGRIDSZ = 16, /* Size of manager identifier */ +- VDP22_IDSZ = 16 /* Size of vsi identifier */ ++ VDP22_IDSZ = 16, /* Size of vsi identifier */ ++}; ++ ++struct vdp22_ptlv { /* Packed TLV for VDP data exchange */ ++ unsigned short head; /* TLV 16 bit header */ ++ unsigned char data[]; /* TLV Data buffer */ + }; + + struct vsi_origin { /* Originator of VSI request */ +@@ -99,18 +113,6 @@ struct fid22 { /* Filter data: GROUP,MAC,VLAN entry */ + struct vsi_origin requestor; + }; + +-/* +- * VSI information. One node per matching entry (same mgrid, type_id, type_ver, +- * id_fmt, id and fif). Filter data can be added and removed. +- */ +-enum vsi22_flags { /* Flags (or'ed in) */ +- VDP22_BUSY = 1, /* This node is under work */ +- VDP22_DELETE_ME = 2, /* Deallocate this node */ +- VDP22_RETURN_VID = 4, /* Return wildcard vlan id */ +- VDP22_NOTIFY = 8, /* Send netlink message to requestor */ +- VDP22_NLCMD = 16 /* Netlink command pending */ +-}; +- + struct vdp22smi { /* Data structure for VDP22 state machine */ + int state; /* State of VDP state machine for VSI */ + bool kato; /* VSI KA ACK timeout hit for this VSI */ +diff --git a/include/qbg_vdp22_clif.h b/include/qbg_vdp22_clif.h +index 8346b98..0cc603e 100644 +--- a/include/qbg_vdp22_clif.h ++++ b/include/qbg_vdp22_clif.h +@@ -33,6 +33,8 @@ + #define OP_FID_POS 8 /* Second Byte */ + #define OP_OUI_POS 16 /* Third Byte */ + ++#include "lldpad_status.h" ++ + typedef enum { + cmd_getstats, + cmd_gettlv, +@@ -60,5 +62,11 @@ typedef enum { + */ + } vdp22_op; + ++enum vdp22_cmd_status { ++ cmd_vdp_prot_no_support = cmd_max_status + 1, ++ cmd_vdp_nomem, ++ cmd_vdp_busy, ++}; ++ + struct lldp_module *vdp22_cli_register(void); + #endif +diff --git a/include/qbg_vdp22def.h b/include/qbg_vdp22def.h +index ff4270c..c305a2b 100644 +--- a/include/qbg_vdp22def.h ++++ b/include/qbg_vdp22def.h +@@ -94,6 +94,31 @@ enum vsi_key_arg { + VSI_INVALID_ARG + }; + ++enum vdp22_cmdresp { /* VDP22 Protocol command responses */ ++ VDP22_RESP_SUCCESS = 0, /* Success */ ++ VDP22_RESP_INVALID_FORMAT = 1, ++ VDP22_RESP_NO_RESOURCES = 2, ++ VDP22_RESP_NO_VSIMGR = 3, /* No contact to VSI manager */ ++ VDP22_RESP_OTHER = 4, /* Other reasons */ ++ VDP22_RESP_NOADDR = 5, /* Invalid VID, MAC, GROUP etc */ ++ VDP22_RESP_DEASSOC = 252, /* Deassoc response */ ++ VDP22_RESP_TIMEOUT = 253, /* Timeout response */ ++ VDP22_RESP_KEEP = 254, /* Keep response */ ++ VDP22_RESP_NONE = 255 /* No response returned so far */ ++}; ++ ++/* ++ * Errors applicable mostly for VDP22_RESP_NONE ++ */ ++ ++enum vdp22_cmderr { ++ VDP22_KATO = 0, ++ VDP22_ACKTO, ++ VDP22_TXERR ++}; ++ ++#define VDP22_STATUS_BITS 8 /* Number of bits in Status field */ ++ + #define VSI22_ARG_MODE_STR "mode" + #define VSI22_ARG_MGRID_STR "mgrid2" + #define VSI22_ARG_TYPEID_STR "typeid" +@@ -105,4 +130,18 @@ enum vsi_key_arg { + #define VSI22_ARG_FILTER_STR "filter" + #define VSI22_ARG_OUI_STR "oui" + ++#define VSI22_KATO_ERR_STR "Keepalive Timeout" ++#define VSI22_ACKTO_ERR_STR "Ack not received from bridge" ++#define VSI22_TX_ERR_STR "Transmission Error" ++ ++#define VSI22_INVALID_FRMT_ERR_STR "VDP TLV Format is Invalid" ++#define VSI22_NO_RES_ERR_STR "Insufficient resources at bridge" ++#define VSI22_NO_VSIMGR_ERR_STR "Unable to contact VSI Mgr" ++#define VSI22_OTHER_ERR_STR "Other Failures" ++#define VSI22_NOADDR_ERR_STR "Invalid VID, GroupID or MAC address field" ++#define VSI22_DEASS_ERR_STR "Deassoc received from switch" ++#define VSI22_TIMEOUT_ERR_STR "Timeout Error" ++#define VSI22_KEEP_ERR_STR "Command rejected by bridge and state prior to" \ ++ " requested command is kept" ++ + #endif +diff --git a/qbg/vdp22.c b/qbg/vdp22.c +index af11af8..d7aa648 100644 +--- a/qbg/vdp22.c ++++ b/qbg/vdp22.c +@@ -42,6 +42,7 @@ + #include "qbg_vdp22.h" + #include "qbg_utils.h" + #include "qbg_vdp22_cmds.h" ++#include "qbg_vdp22def.h" + + /* + * VDP22 helper functions +@@ -469,7 +470,8 @@ static bool filter_ok(unsigned char ffmt, struct fid22 *fp, + else + rc = false; + } +- LLDPAD_DBG("%s:rc:%d\n", __func__, rc); ++ LLDPAD_DBG("%s: ffmt:%d gpid_on:%d rc:%d\n", __func__, ffmt, ++ gpid_on, rc); + return rc; + } + +@@ -1007,12 +1009,26 @@ static pid_t havepid(struct vsi22 *vsi) + return mypid; + } + ++unsigned char vdp22_getsm_errcode(struct vsi22 *vsi) ++{ ++ unsigned char err_code = 0; ++ ++ if (vsi->smi.kato) ++ err_code |= (1 << VDP22_KATO); ++ if (vsi->smi.acktimeout) ++ err_code |= (1 << VDP22_ACKTO); ++ if (vsi->smi.txmit_error) ++ err_code |= (1 << VDP22_TXERR); ++ return err_code; ++} ++ + /* + * Convert and VSI22 to VDP netlink format and send it back to the originator. + */ + static int vdp22_back(struct vsi22 *vsi, pid_t to, + int (*fct)(struct vdpnl_vsi *)) + { ++ unsigned char err_code; + int i; + struct vdpnl_vsi nl; + struct vdpnl_mac nlmac[vsi->no_fdata]; +@@ -1025,6 +1041,8 @@ static int vdp22_back(struct vsi22 *vsi, pid_t to, + memcpy(nl.ifname, vsi->vdp->ifname, sizeof(nl.ifname)); + nl.request = vsi->vsi_mode; + nl.response = vsi->status; ++ err_code = vdp22_getsm_errcode(vsi); ++ nl.response |= (err_code << VDP22_STATUS_BITS); + nl.vsi_mgrid = vsi->mgrid[0]; + memcpy(nl.vsi_mgrid2, vsi->mgrid, sizeof(nl.vsi_mgrid2)); + nl.vsi_typeversion = vsi->type_ver; +diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c +index 409858d..5d5ef6b 100644 +--- a/qbg/vdp22_cmds.c ++++ b/qbg/vdp22_cmds.c +@@ -165,7 +165,8 @@ static int handle_set_arg(struct cmd *cmd, char *arg, char *argvalue, + * bb: C for command and 2 or 3 for message version number + * cc: 1 for get command and 2 for set command + * dddddddd: 8 hex digits options, supported are op_arg, op_argval, op_conifg +- * and op_local ++ * and op_local. The number of filter (fid) parameters are encoded ++ * here (second byte from right). + * ee: 2 hex digit length of interface name + * ffff: string for interface name + * gg: 2 hex digit for bridge type (nearest customer bridge only) +@@ -179,7 +180,7 @@ static int handle_set_arg(struct cmd *cmd, char *arg, char *argvalue, + * The total input length can be used to determine the number of arguaments. + * + * The member ops of struct cmd settings depends on the invoked with +- * -T (cmd_gettlv) -a assoc: ++ * -T (cmd_getvsi) -a assoc: + * -c key --> ops=(0x15) op_config,op_arg,op_local), numargs > 0 + * -c key=abc --> ops=(0x1d) op_config,op_arg,op_argval,op_local), numargs > 0 + * -c --> ops=0x11 (op_config,op_local), numargs = 0 +@@ -279,8 +280,16 @@ int vdp22_clif_cmd(UNUSED void *data, UNUSED struct sockaddr_un *from, + int vdp22_sendevent(struct vdpnl_vsi *p) + { + char msg[MAX_CLIF_MSGBUF]; ++ char tmp_buf[MAX_CLIF_MSGBUF]; ++ int c, len; + +- vdp_vdpnl2str(p, msg, sizeof(msg)); ++ vdp_vdpnl2str(p, tmp_buf, sizeof(msg)); ++ len = strlen(tmp_buf); ++ if ((unsigned)len > sizeof(msg)) ++ return 0; ++ c = snprintf(msg, sizeof(msg), "%04x%s", len, tmp_buf); ++ if ((c < 0) || ((unsigned)c >= sizeof(msg))) ++ return 0; + LLDPAD_DBG("%s:%s vsi:%p(%#2x), len:%zd msg:%s\n", __func__, + p->ifname, p, p->vsi_uuid[0], strlen(msg), msg); + send_event(16, LLDP_MOD_VDP22, msg); +@@ -324,6 +333,29 @@ static int ifok(struct cmd *cmd) + return good_cmd; + } + ++static int get_vdp22_retval(int rc) ++{ ++ if (!rc) ++ return cmd_success; ++ ++ switch (rc) { ++ case -EPROTONOSUPPORT: ++ return cmd_vdp_prot_no_support; ++ case -EOPNOTSUPP: ++ return cmd_not_capable; ++ case -EINVAL: ++ return cmd_bad_params; ++ case -ENOMEM: ++ return cmd_vdp_nomem; ++ case -EBUSY: ++ return cmd_vdp_busy; ++ case -ENODEV: ++ return cmd_device_not_found; ++ default: ++ return cmd_failed; ++ } ++} ++ + static int set_arg_vsi3(struct cmd *cmd, char *argvalue, bool test, int size) + { + cmd_status good_cmd = vdp22_cmdok(cmd, cmd_settlv); +@@ -340,7 +372,7 @@ static int set_arg_vsi3(struct cmd *cmd, char *argvalue, bool test, int size) + vsi.macsz = size; + rc = vdp_str2vdpnl(argvalue, &vsi, cmd->ifname); + if (rc) { +- good_cmd = cmd_bad_params; ++ good_cmd = get_vdp22_retval(rc); + goto out; + } + if (!port_find_by_ifindex(get_ifidx(cmd->ifname))) { +@@ -351,12 +383,8 @@ static int set_arg_vsi3(struct cmd *cmd, char *argvalue, bool test, int size) + if (good_cmd != cmd_success || test) + goto out; + rc = vdp22_request(&vsi, 1); +- if (!rc) +- good_cmd = cmd_success; +- else if (rc == -ENODEV) +- good_cmd = cmd_device_not_found; +- else +- good_cmd = cmd_failed; ++ good_cmd = get_vdp22_retval(rc); ++ + out: + return good_cmd; + } +@@ -480,7 +508,8 @@ static int get_vsi_partial_arg(UNUSED char *arg, char *orig_argvalue, + int rc = -ENOMEM, len, c; + u16 vsi_arg_key_flags = 0; + +- if (vdp22_parse_str_vdpnl(vsinl, &vsi_arg_key_flags, orig_argvalue)) ++ rc = vdp22_parse_str_vdpnl(vsinl, &vsi_arg_key_flags, orig_argvalue); ++ if (rc) + goto out; + vdp = vdp22_getvdp(vsinl->ifname); + if (!vdp) +@@ -498,7 +527,6 @@ static int get_vsi_partial_arg(UNUSED char *arg, char *orig_argvalue, + len = strlen(tmp_buf); + c = snprintf(out + used, out_len - used, "%04x%s", + len, tmp_buf); +- vdp22_freemaclist(vsinl); + if ((c < 0) || ((unsigned)c >= (out_len - used))) + goto out_delvsi; + if (rc) +@@ -544,11 +572,14 @@ static int get_arg_vsi(struct cmd *cmd, char *arg, char *argvalue, + memset(&mac, 0, sizeof(mac)); + vsi.macsz = fsize; + vsi.maclist = mac; +- if (!get_vsi_partial_arg(arg, argvalue, &vsi, vsi_str, +- sizeof(vsi_str))) +- goto out; +- } else if (!catvsis(&vsi, vsi_str, sizeof(vsi_str))) ++ rc = get_vsi_partial_arg(arg, argvalue, &vsi, vsi_str, ++ sizeof(vsi_str)); ++ } else ++ rc = catvsis(&vsi, vsi_str, sizeof(vsi_str)); ++ if (!rc) { ++ good_cmd = get_vdp22_retval(rc); + goto out; ++ } + rc = snprintf(obuf, obuf_len, "%s", vsi_str); + if (rc > 0 || rc < obuf_len) + good_cmd = cmd_success; +diff --git a/qbg/vdp22sm.c b/qbg/vdp22sm.c +index 6264f74..83a97fb 100644 +--- a/qbg/vdp22sm.c ++++ b/qbg/vdp22sm.c +@@ -46,21 +46,6 @@ + #include "qbg_vdp22.h" + #include "qbg_utils.h" + +-struct vdp22_ptlv { /* Packed TLV for VDP data exchange */ +- unsigned short head; /* TLV 16 bit header */ +- unsigned char data[]; /* TLV Data buffer */ +-}; +- +-enum { /* VDP22 Protocol command responses */ +- USEC_PER_SEC = 1000000, /* Microseconds per second */ +- VDP22_RESBIT = 0x80, /* VSI reserved bit */ +- VDP22_ACKBIT = 0x40, /* VSI Acknowledgement bit */ +- VDP22_KEEPBIT = 0x20, /* VSI keep error bit */ +- VDP22_HARDBIT = 0x10, /* VSI hard error bit */ +- VDP22_STATUS_MASK = 0x0f, /* Status mask */ +- VDP22_STATUS_SHIFT = 0, /* Status offset */ +-}; +- + /* + * Set status code + */ +diff --git a/qbg/vdp_ascii.c b/qbg/vdp_ascii.c +index 76dde4a..70ec79b 100644 +--- a/qbg/vdp_ascii.c ++++ b/qbg/vdp_ascii.c +@@ -44,6 +44,7 @@ + #include "qbg_vdpnl.h" + #include "qbg_utils.h" + #include "lldp_util.h" ++#include "messages.h" + + struct vsi_keyword_handler vsi_key_handle[] = { + {VSI22_ARG_MODE_STR, VSI_MODE_ARG}, +@@ -285,6 +286,24 @@ enum vsi_key_arg get_keywork_val(char *keyword) + return VSI_INVALID_ARG; + } + ++/* ++ * If the ordering is maintained in vsi_key_handle, then this function is not ++ * necessary as the keyword can be retrieved using ++ * 'vsi_key_handle[keyval].keyword'. ++ */ ++ ++char *get_keyword_str(enum vsi_key_arg keyval) ++{ ++ int count, key_str_size; ++ ++ key_str_size = sizeof(vsi_key_handle) / sizeof(vsi_key_handle[0]); ++ for (count = 0; count < key_str_size; count++) { ++ if (vsi_key_handle[count].val == keyval) ++ return vsi_key_handle[count].keyword; ++ } ++ return NULL; ++} ++ + int vdp22_parse_str_vdpnl(struct vdpnl_vsi *vsi, u16 *key_flags, + char *orig_argvalue) + { +@@ -315,52 +334,57 @@ int vdp22_parse_str_vdpnl(struct vdpnl_vsi *vsi, u16 *key_flags, + numargs = get_arg_val_list(argvalue, ilen, &ioff, args, argvals); + if (numargs == 0) + goto out_free; ++ rc = -EINVAL; + for (i = 0; i < numargs; i++) { + vsi_key = get_keywork_val(args[i]); + switch (vsi_key) { + case VSI_MODE_ARG: + if (!argvals[i] || !getmode(vsi, argvals[i])) +- goto out_free; ++ goto out_err; + break; + case VSI_MGRID2_ARG: + if (!argvals[i] || !getmgr2id(vsi, argvals[i])) +- goto out_free; ++ goto out_err; + break; + case VSI_TYPEID_ARG: + if (!argvals[i] || + !getnumber(argvals[i], 0, 0xffffff, &no)) +- goto out_free; ++ goto out_err; + vsi->vsi_typeid = no; + break; + case VSI_TYPEIDVER_ARG: + if (!argvals[i] || !getnumber(argvals[i], 0, 0xff, &no)) +- goto out_free; ++ goto out_err; + vsi->vsi_typeversion = no; + break; + case VSI_VSIID_ARG: + if (!argvals[i] || + vdp_str2uuid(vsi->vsi_uuid, argvals[i], + sizeof(vsi->vsi_uuid))) +- goto out_free; ++ goto out_err; + vsi->vsi_idfmt = VDP22_ID_UUID; + break; + case VSI_FILTER_ARG: + if (idx < vsi->macsz && !getfid(vsi, argvals[i], idx)) +- goto out_free; ++ goto out_err; + idx++; + break; + case VSI_HINTS_ARG: + if (!argvals[i] || !gethints(vsi, argvals[i])) +- goto out_free; ++ goto out_err; + break; + default: +- goto out_free; ++ goto out_err; + } + num_arg_keys |= (1 << vsi_key); + } + *key_flags = num_arg_keys; + rc = 0; + ++out_err: ++ if (rc) ++ LLDPAD_ERR("Incorrect arguments specified for key %s\n", ++ get_keyword_str(vsi_key)); + out_free: + free(argvals); + out_args: +@@ -400,11 +424,16 @@ static int str2vdpnl(char *orig_argvalue, struct vdpnl_vsi *vsi) + u16 vsi_mand_mask = (1 << VSI_MAND_NUM_ARG) - 1; + u16 num_arg_keys = 0; + +- if (vdp22_parse_str_vdpnl(vsi, &num_arg_keys, orig_argvalue)) ++ rc = vdp22_parse_str_vdpnl(vsi, &num_arg_keys, orig_argvalue); ++ if (rc) { ++ LLDPAD_ERR("%s: Incorrect arguments\n", __func__); + goto out; ++ } + /* Return error if no filter information provided */ + if ((num_arg_keys & vsi_mand_mask) == vsi_mand_mask) + rc = 0; ++ else ++ LLDPAD_ERR("%s: Incomplete arguments\n", __func__); + out: + return rc; + } +@@ -444,7 +473,6 @@ static char *check_and_update(size_t *total, size_t *length, char *s, int c) + /* + * Convert VSI association to string. + */ +-#ifdef LATER_USE + static const char *mode2str(unsigned char x) + { + if (x == VDP22_ASSOC) +@@ -457,7 +485,6 @@ static const char *mode2str(unsigned char x) + return "deassoc"; + return "unknown"; + } +-#endif + + /* + * Convert filter information format into vlan[-mac][-group] string. +@@ -544,7 +571,12 @@ int vdp_vdpnl2str(struct vdpnl_vsi *p, char *s, size_t length) + char instance[VDP_UUID_STRLEN + 2]; + + mgrid2str(instance, p, sizeof(instance)); +- c = snprintf(s, length, "%02x%s%04x%s%02x%s%04x%lu%02x%s%04x%d", ++ c = snprintf(s, length, "%02x%s%04x%s%02x%s%04x%s%02x%s%04x%lu%02x%s" ++ "%04x%d", ++ (unsigned int)strlen(VSI22_ARG_MODE_STR), ++ VSI22_ARG_MODE_STR, ++ (unsigned int)strlen(mode2str(p->request)), ++ mode2str(p->request), + (unsigned int)strlen(VSI22_ARG_MGRID_STR), + VSI22_ARG_MGRID_STR, + (unsigned int)strlen(instance), instance, +diff --git a/vdptool.c b/vdptool.c +index 551e829..f7fd288 100644 +--- a/vdptool.c ++++ b/vdptool.c +@@ -54,6 +54,28 @@ + #include "qbg22.h" + #include "qbg_vdp22_clif.h" + #include "lldp_util.h" ++#include "qbg_vdp22def.h" ++ ++static char *print_vdp_status(enum vdp22_cmd_status status) ++{ ++ char *str; ++ ++ switch (status) { ++ case cmd_vdp_prot_no_support: ++ str = "VDP protocol not supported on interface"; ++ break; ++ case cmd_vdp_nomem: ++ str = "Not enough memory"; ++ break; ++ case cmd_vdp_busy: ++ str = "VSI association in progress"; ++ break; ++ default: ++ str = "Unknown status"; ++ break; ++ } ++ return str; ++} + + static char *print_status(cmd_status status) + { +@@ -97,7 +119,7 @@ static char *print_status(cmd_status status) + str = "TLV does not support agent type"; + break; + default: +- str = "Unknown status"; ++ str = print_vdp_status(status); + break; + } + return str; +@@ -165,7 +187,7 @@ static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals) + + int vdp_clif_command(struct clif *, char *, int); + +-static int vdp_cmd_gettlv(struct clif *clif, int argc, char *argv[], ++static int vdp_cmd_getvsi(struct clif *clif, int argc, char *argv[], + struct cmd *cmd, int raw) + { + int numargs = 0; +@@ -219,7 +241,7 @@ out: + return cmd_invalid; + } + +-static int vdp_cmd_settlv(struct clif *clif, int argc, char *argv[], ++static int vdp_cmd_setvsi(struct clif *clif, int argc, char *argv[], + struct cmd *cmd, int raw) + { + int numargs = 0; +@@ -299,12 +321,77 @@ static int vdp_parse_response(char *buf) + return hex2u8(buf + CLIF_STAT_OFF); + } + +-int get_vsi_args(char *ibuf) ++void print_vsi_err_msg(char *key_val) ++{ ++ unsigned long errcode; ++ int resp_err, smi_err; ++ ++ errcode = strtol(key_val, NULL, 10); ++ resp_err = errcode & 0xff; ++ smi_err = (errcode >> VDP22_STATUS_BITS) & 0xff; ++ ++ switch (resp_err) { ++ case VDP22_RESP_INVALID_FORMAT: ++ printf("\tError returned by Bridge: %s\n", ++ VSI22_INVALID_FRMT_ERR_STR); ++ break; ++ case VDP22_RESP_NO_RESOURCES: ++ printf("\tError returned by Bridge: %s\n", ++ VSI22_NO_RES_ERR_STR); ++ break; ++ case VDP22_RESP_NO_VSIMGR: ++ printf("\tError returned by Bridge: %s\n", ++ VSI22_NO_VSIMGR_ERR_STR); ++ break; ++ case VDP22_RESP_OTHER: ++ printf("\tError returned by Bridge: %s\n", VSI22_OTHER_ERR_STR); ++ break; ++ case VDP22_RESP_NOADDR: ++ printf("\tError returned by Bridge: %s\n", ++ VSI22_NOADDR_ERR_STR); ++ break; ++ case VDP22_RESP_DEASSOC: ++ printf("\tError returned by Bridge: %s\n", VSI22_DEASS_ERR_STR); ++ break; ++ case VDP22_RESP_TIMEOUT: ++ printf("\tError returned by Bridge: %s\n", ++ VSI22_TIMEOUT_ERR_STR); ++ break; ++ case VDP22_RESP_KEEP: ++ printf("\tError returned by Bridge: %s\n", VSI22_KEEP_ERR_STR); ++ break; ++ default: ++ break; ++ } ++ if (smi_err & (1 << VDP22_KATO)) ++ printf("\tInternal Error : %s\n", VSI22_KATO_ERR_STR); ++ if (smi_err & (1 << VDP22_ACKTO)) ++ printf("\tInternal Error : %s\n", VSI22_ACKTO_ERR_STR); ++ if (smi_err & (1 << VDP22_TXERR)) ++ printf("\tInternal Error : %s\n", VSI22_TX_ERR_STR); ++} ++ ++static void print_vsi(char **args, char **argvals, int numargs, ++ bool err_flag) ++{ ++ int i; ++ ++ for (i = 0; i < numargs; i++) { ++ if (err_flag && (!strcmp(args[i], VSI22_ARG_HINTS_STR))) ++ print_vsi_err_msg(argvals[i]); ++ else { ++ printf("\t%s", args[i]); ++ printf(" = %s\n", argvals[i]); ++ } ++ } ++} ++ ++int get_vsi_args(char *ibuf, bool print_err_code) + { + int ioff = 0; + char **args; + char **argvals; +- int numargs, i; ++ int numargs; + int ilen = strlen(ibuf); + + /* count args and argvalus */ +@@ -321,17 +408,14 @@ int get_vsi_args(char *ibuf) + } + + numargs = get_arg_val_list(ibuf, ilen, &ioff, args, argvals); +- for (i = 0; i < numargs; i++) { +- printf("\t%s", args[i]); +- printf(" = %s\n", argvals[i]); +- } ++ print_vsi(args, argvals, numargs, print_err_code); + + free(args); + free(argvals); + return ioff; + } + +-static void print_all_vsis(char *ibuf) ++static void print_all_vsis(char *ibuf, bool err_code, char *msg) + { + size_t ilen = strlen(ibuf); + u16 vsi_len; +@@ -346,8 +430,11 @@ static void print_all_vsis(char *ibuf) + ilen -= 2 * sizeof(u16); + strncpy(tmp_ibuf, ibuf + offset, vsi_len); + tmp_ibuf[vsi_len] = '\0'; +- printf("%s %d:\n", "VSI ", vsi_cnt); +- get_vsi_args(tmp_ibuf); ++ if (msg) ++ printf("%s\n", msg); ++ else ++ printf("%s %d:\n", "VSI ", vsi_cnt); ++ get_vsi_args(tmp_ibuf, err_code); + offset += vsi_len; + ilen -= vsi_len; + vsi_cnt++; +@@ -361,7 +448,7 @@ static void print_cmd_response(char *ibuf, int status) + int ioff; + + if (status != cmd_success) { +- printf("%s\n", print_status(status)); ++ printf("FAILED: %s\n", print_status(status)); + return; + } + +@@ -385,7 +472,7 @@ static void print_cmd_response(char *ibuf, int status) + + switch (cmd.cmd) { + case cmd_gettlv: +- print_all_vsis(ibuf + ioff); ++ print_all_vsis(ibuf + ioff, false, NULL); + break; + case cmd_settlv: + printf("%s", ibuf + ioff); +@@ -423,6 +510,7 @@ static void vdp_print_response(char *buf, int status) + static void vdp_print_event_msg(char *buf) + { + printf("%s buf:%s\n", __func__, buf); ++ print_all_vsis(buf + CLIF_RSP_OFF, true, "Response from VDP"); + } + + /* +@@ -519,8 +607,8 @@ static const char *commands_help = + " -v|version show version\n" + " -p|ping ping lldpad and query pid of lldpad\n" + " -q|quit exit lldptool (interactive mode)\n" +-" -t|get-tlv get tlvid value\n" +-" -T|set-tlv set arg for tlvid to value\n"; ++" -t|get-vsi get VSI association(s)\n" ++" -T|set-vsi set VSI association\n"; + + static struct clif *clif_conn; + static int cli_quit; +@@ -638,7 +726,7 @@ static int _clif_command(struct clif *clif, char *cmd, int print) + size_t len; + int ret; + int rc; +- char reply[200]; ++ char reply[MAX_CLIF_MSGBUF]; + size_t reply_len2 = sizeof(reply); + + print_raw_message(cmd, print); +@@ -653,7 +741,8 @@ static int _clif_command(struct clif *clif, char *cmd, int print) + printf("'%s' command timed out.\n", cmd); + return -2; + } else if (ret < 0) { +- printf("'%s' command failed.\n", cmd); ++ printf("'%s' command failed with error %s.\n", cmd, ++ strerror(errno)); + return -1; + } + if (print) { +@@ -662,10 +751,8 @@ static int _clif_command(struct clif *clif, char *cmd, int print) + } + if (cli_attached) { + rc = clif_vsievt(clif, reply, &reply_len2, 5); +- printf("\nReturn from vsievt %d ret %d Reply %s\n", rc, ret, +- reply); + if (!rc) +- printf("\nMsg is %s\n", reply); ++ print_all_vsis(reply, true, "Response from VDP"); + } + + return ret; +@@ -739,10 +826,10 @@ static struct cli_cmd { + { cmd_license, "license", cli_cmd_license }, + { cmd_version, "version", cli_cmd_version }, + { cmd_quit, "quit", cli_cmd_quit }, +- { cmd_gettlv, "gettlv", vdp_cmd_gettlv }, +- { cmd_gettlv, "get-tlv", vdp_cmd_gettlv }, +- { cmd_settlv, "settlv", vdp_cmd_settlv }, +- { cmd_settlv, "set-tlv", vdp_cmd_settlv }, ++ { cmd_gettlv, "getvsi", vdp_cmd_getvsi }, ++ { cmd_gettlv, "get-vsi", vdp_cmd_getvsi }, ++ { cmd_settlv, "setvsi", vdp_cmd_setvsi }, ++ { cmd_settlv, "set-vsi", vdp_cmd_setvsi }, + { cmd_nop, NULL, cli_cmd_nop } + }; + +@@ -774,8 +861,8 @@ static struct option lldptool_opts[] = { + {"help", 0, NULL, 'h'}, + {"version", 0, NULL, 'v'}, + {"stats", 0, NULL, 'S'}, +- {"get-tlv", 0, NULL, 't'}, +- {"set-tlv", 0, NULL, 'T'}, ++ {"get-vsi", 0, NULL, 't'}, ++ {"set-vsi", 0, NULL, 'T'}, + {"get-lldp", 0, NULL, 'l'}, + {"set-lldp", 0, NULL, 'L'}, + {0, 0, 0, 0} +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-7-VDP-Support-for-OUI-infrastructure-in-VDP22.patch b/open-lldp-v1.0.1-7-VDP-Support-for-OUI-infrastructure-in-VDP22.patch new file mode 100644 index 0000000..aa2c193 --- /dev/null +++ b/open-lldp-v1.0.1-7-VDP-Support-for-OUI-infrastructure-in-VDP22.patch @@ -0,0 +1,158 @@ +From 64c9ba3c03c735e8031964edf52e148373ec29ce Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:38:24 +0000 +Subject: [PATCH] VDP: Support for OUI infrastructure in VDP22. + +This patch contains the header field changes for a general framework +for supporting OUI fields in VDP22 at the station side. The specific +changes are described below. + +qbg_vdpnl.h: +------------- +Couple of parameters are added to the vdpnl_vsi structure. One is +the number of OUI parameters. Generally, this will be 1, as the +chances of having different OUI in a single message for VDP22 is +quite low. Nevertheless, there's support for having multiple OUI +in a single VSI. The other field is a general structure of len,opaque +data format for carrying the OUI data. + +qbg_vdp22_oui.h: +---------------- +This is a new header file added for supporting the OUI framework. This +file contains the OUI specific sub-structures for vdpnl and vsi22 +structures and function handler structure.:w + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + Makefile.am | 3 ++- + include/qbg_vdp22.h | 4 ++++ + include/qbg_vdp22_oui.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + include/qbg_vdp22def.h | 1 + + include/qbg_vdpnl.h | 2 ++ + 5 files changed, 55 insertions(+), 1 deletion(-) + create mode 100644 include/qbg_vdp22_oui.h + +diff --git a/Makefile.am b/Makefile.am +index fc4f8d6..403088b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -69,7 +69,8 @@ lldp_8021qaz_cmds.c include/lldp_8021qaz_cmds.h \ + include/lldp_evb22.h lldp_evb22.c lldp_evb22_cmds.c \ + include/qbg22.h include/qbg_ecp22.h qbg/ecp22.c \ + include/qbg_vdp22.h qbg/vdp22.c qbg/vdpnl.c qbg/vdp22sm.c qbg/vdp22br.c \ +-include/qbg_vdp22def.h qbg/vdp22_cmds.c qbg/vdp_ascii.c ++include/qbg_vdp22def.h qbg/vdp22_cmds.c qbg/vdp_ascii.c \ ++include/qbg_vdp22_oui.h + + lib_LTLIBRARIES = liblldp_clif.la + liblldp_clif_la_LDFLAGS = -version-info 1:0:0 +diff --git a/include/qbg_vdp22.h b/include/qbg_vdp22.h +index 6c3c9ee..6585a10 100644 +--- a/include/qbg_vdp22.h ++++ b/include/qbg_vdp22.h +@@ -59,6 +59,7 @@ + #include + + #include ++#include + + enum vdp22_role { /* State for VDP22 bridge processing */ + VDP22_BRIDGE = 1, /* Bridge role */ +@@ -140,6 +141,8 @@ struct vsi22 { + unsigned char fif; /* Filter info format */ + unsigned short no_fdata; /* Entries in filter data */ + struct fid22 *fdata; /* Filter data variable length */ ++ unsigned short no_ouidata; /* Entries in OUI data */ ++ struct vdp22_oui_data_s *oui_str_data; /* OUI data variable length */ + struct vdp22 *vdp; /* Back pointer to VDP head */ + unsigned long flags; /* Flags, see above */ + struct vdp22smi smi; /* State machine information */ +@@ -189,6 +192,7 @@ void vdp22_stop_timers(struct vsi22 *); + int vdp22_start_localchange_timer(struct vsi22 *); + bool vdp22_cmp_fdata(struct vsi22 *, struct vsi22 *); + void vdp22_delete_vsi(struct vsi22 *); ++struct vdp22_oui_handler_s * vdp22_get_oui_hndlr(char *); + + /* + * Functions to get and set vlan identifier and qos. +diff --git a/include/qbg_vdp22_oui.h b/include/qbg_vdp22_oui.h +new file mode 100644 +index 0000000..0aeb7b9 +--- /dev/null ++++ b/include/qbg_vdp22_oui.h +@@ -0,0 +1,46 @@ ++/******************************************************************************* ++ ++ Implementation of OUI for VDP2.2 ++ Copyright (c) 2012-2014 by Cisco Systems, Inc. ++ ++ Author(s): Padmanabhan Krishnan ++ ++ This program is free software; you can redistribute it and/or modify it ++ under the terms and conditions of the GNU General Public License, ++ version 2, as published by the Free Software Foundation. ++ ++ This program is distributed in the hope it will be useful, but WITHOUT ++ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ You should have received a copy of the GNU General Public License along with ++ this program; if not, write to the Free Software Foundation, Inc., ++ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ ++ The full GNU General Public License is included in this distribution in ++ the file called "COPYING". ++*******************************************************************************/ ++ ++#ifndef __VDP22_OUI_H__ ++#define __VDP22_OUI_H__ ++ ++#include ++ ++/* ++ * Generic OUI related defines ++ */ ++enum vdp22_oui { ++ VDP22_OUI_TYPE_LEN = 3, /* Size of OUI Type field */ ++ VDP22_OUI_MAX_NAME = 20, ++}; ++ ++struct vdp22_oui_data_s { ++ void *vsi_data; ++ unsigned char oui_type[VDP22_OUI_TYPE_LEN]; ++ char oui_name[VDP22_OUI_MAX_NAME]; ++ int len; ++ void *data; ++}; ++ ++#endif /* __VDP22_OUI_H__ */ +diff --git a/include/qbg_vdp22def.h b/include/qbg_vdp22def.h +index c305a2b..a2d2654 100644 +--- a/include/qbg_vdp22def.h ++++ b/include/qbg_vdp22def.h +@@ -91,6 +91,7 @@ enum vsi_key_arg { + VSI_FILTER_ARG, + VSI_MAND_NUM_ARG, + VSI_HINTS_ARG, ++ VSI_OUI_ARG, + VSI_INVALID_ARG + }; + +diff --git a/include/qbg_vdpnl.h b/include/qbg_vdpnl.h +index c5c93ed..bf18e71 100644 +--- a/include/qbg_vdpnl.h ++++ b/include/qbg_vdpnl.h +@@ -66,6 +66,8 @@ struct vdpnl_vsi { /* Data structure for VSI data via netlink */ + unsigned char filter_fmt; /* Filter format type */ + int macsz; /* Entries in mac-vlan pair list */ + struct vdpnl_mac *maclist; /* List of MAC-VLAN pairs */ ++ int ouisz; /* No of OUI entries */ ++ struct vdpnl_oui_data_s *oui_list; /* OUI Entries */ + }; + + int vdpnl_recv(unsigned char *, size_t); +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch b/open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch new file mode 100644 index 0000000..674f448 --- /dev/null +++ b/open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch @@ -0,0 +1,355 @@ +From 321bfe6c5cbad58e97fbb2df3c93564c89f1e09b Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:38:53 +0000 +Subject: [PATCH] VDP: Support for OUI infrastructure in vdptool. + +This patch contains the changes made in vdptool to support OUI fields +in vdptool. This commit has only the infra-structure changes needed +for supporting OUI. No specific OUI fields are added as a part of this +commit. The man page for vdptool is also modified accordingly. + +The OUI data can be given as input to vdptool in different ways. It +could be + + vdptool .... -c oui=companyA,Data1 -c oui=companyB,Data2 -c oui=companyA,Data3 + + Or + + vdptool .... -c oui=companyA,Data1Data3 -c oui=companyB,data2 + +where companyA and companyB are the name of the Organizations. +Anything after the comma in OUI data field is Org specific and it's +upto the respective organization specific handlers to encode it so +that it could be decoded appropriately by the ORG specific handlers +inside lldpad. That is, Data1 and Data3 is specific to Organization +'companyA' and the OUI handlers of companyA in vdptool and lldpad is +responsible for encoding/decoding the data. The common code in vdptool +and lldpad just treats it as opaque data. 'companyA' or 'companyB' +above is the key using which the right handlers will be called. + +Irrespective of how the command line interface to vdptool is, the +input to lldpad is always the same. i.e. KeywordlenKeywordDatalenData +For OUI, the data field will have the complete OUI data starting with +ORG name (e.g companyA). So, in order to call the right handler +routine, the OUI data field is split as OUInamelenOUInameOUIData. + +OUInamelen is 2B. + +For example if the following is given: + +vdptool -T -W -i eth2 -V assoc \ + -c mode=assoc -c mgrid2=0 -c typeid=0 -c typeidver=0 \ + -c uuid=18ea3452-b364-4e13-a1a2-9c6524deb685 -c hints=none \ + -c filter=0-fa:16:3e:4c:2d:85-90001 -c oui=companyA,val1=data1 + +The data sent to lldpad by vdptool will be as follows assuming +companyA encode handlers in vdptool encodes it the same way: + +04mode0005assoc06mgrid20001006typeid0001009typeidver0001004uuid002418ea3452-b364-4e13-a1a2-9c6524deb68505hints0004none06filter00190-fa:16:3e:4c:2d:85-9000103oui001408companyAval1=data1 + +This commit will not insert the oui fields as given above because no OUI +specific handlers are added. + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + docs/vdptool.8 | 50 +++++++++++++++- + include/qbg_vdp22_oui.h | 11 ++++ + vdptool.c | 149 +++++++++++++++++++++++++++++++++++++++++++++--- + 3 files changed, 201 insertions(+), 9 deletions(-) + +diff --git a/docs/vdptool.8 b/docs/vdptool.8 +index 0b50a13..4580c71 100644 +--- a/docs/vdptool.8 ++++ b/docs/vdptool.8 +@@ -182,6 +182,31 @@ delimited by two slashes ('--'), + also known as filter information format 3. + For vlan and group details see (1) and (4). + .RE ++.TP ++.B "oui (Organizationally Unique Identifier):" ++This defines the optional Organizationally ++defined information field. This contains the ++specific sets of values for this entry. There ++can be multiple organizational specific fields, ++in which case there will be multiple keywords ++.I oui= ++followed by the values. ++The value is of the following format: ++.EX ++oui=OUI,[Organization specific values ] ++.EE ++The OUI specifies the name of the Organization ++that is responsible for defining ++this content. A comma is mandatory after the OUI ++field. The fields following this ++ is specified by the organization and ++hence will be decoded based on the value of this ++OUI field. Currently, the following values for ++OUI are supported. ++.RS ++.IP cisco - ++Specifies Cisco defined OUI. ++.TP + .SH COMMANDS + .TP + .B license +@@ -226,13 +251,33 @@ vdptool -i eth2 -T -V assoc -c mode=assoc -c mgrid2=blabla \\ + -c filter=2-52:00:00:11:22:33-200 + .fi + .TP +-Create a VSI association on interface eth2 and wait for the response from the bridge ++Create a VSI association on interface eth2 and wait for the ++response from the bridge + .br + .nf + vdptool -i eth2 -T -W -V assoc -c mode=assoc -c mgrid2=blabla \\ + -c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\ + -c filter=0-52:00:00:11:22:33-200 + .fi ++.TP ++Create a VSI association on interface eth2 wth OUI parameters ++and wait for the response from the bridge ++.br ++.nf ++vdptool -i eth2 -T -W -V assoc -c mode=assoc -c mgrid2=blabla \\ ++ -c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\ ++ -c filter=0-52:00:00:11:22:33-200 -c oui=CompanyA,data ++.fi ++.TP ++Create a VSI association on interface eth2 wth multiple OUI parameters ++and wait for the response from the bridge ++.br ++.nf ++vdptool -i eth2 -T -W -V assoc -c mode=assoc -c mgrid2=blabla \\ ++ -c typeid=5 -c uuid=1122 -c typeidver=4 -c hints=none \\ ++ -c filter=0-52:00:00:11:22:33-200 -c oui=CompanyA,data \\ ++ -c oui=CompanyB,data ++.fi + + .TP + Query all VSI association on interface eth2 +@@ -240,7 +285,8 @@ Query all VSI association on interface eth2 + vdptool -i eth2 -t -V assoc + + .TP +-Query VSI association on interface eth2 that matches specific VSI parameters. Any of the VSI parameters below can be omitted. ++Query VSI association on interface eth2 that matches specific ++VSI parameters. Any of the VSI parameters below can be omitted. + .br + vdptool -i eth2 -t -V assoc -t -V assoc -c mode=assoc \\ + -c mgrid2=blabla -c typeid=5 -c uuid=1122 \\ +diff --git a/include/qbg_vdp22_oui.h b/include/qbg_vdp22_oui.h +index 0aeb7b9..d31c6ad 100644 +--- a/include/qbg_vdp22_oui.h ++++ b/include/qbg_vdp22_oui.h +@@ -33,6 +33,7 @@ + enum vdp22_oui { + VDP22_OUI_TYPE_LEN = 3, /* Size of OUI Type field */ + VDP22_OUI_MAX_NAME = 20, ++ MAX_OUI_DATA_LEN = 200 + }; + + struct vdp22_oui_data_s { +@@ -43,4 +44,14 @@ struct vdp22_oui_data_s { + void *data; + }; + ++typedef struct vdptool_oui_data_s { ++ char oui_name[VDP22_OUI_MAX_NAME]; ++ char data[MAX_OUI_DATA_LEN]; ++} vdptool_oui_data_t; ++ ++typedef struct vdptool_oui_hndlr_tbl_s { ++ char *oui_name; ++ bool (*oui_cli_encode_hndlr)(char *dst, char *src, size_t len); ++} vdptool_oui_hndlr_tbl_t; ++ + #endif /* __VDP22_OUI_H__ */ +diff --git a/vdptool.c b/vdptool.c +index f7fd288..c857a85 100644 +--- a/vdptool.c ++++ b/vdptool.c +@@ -55,6 +55,22 @@ + #include "qbg_vdp22_clif.h" + #include "lldp_util.h" + #include "qbg_vdp22def.h" ++#include "qbg_vdp22_oui.h" ++ ++#define OUI_ENCODE_HNDLR(name) name##_oui_encode_hndlr ++#define EXTERN_OUI_FN(name) \ ++ extern bool name##_oui_encode_hndlr(char *, char *, size_t) ++ ++/* The handler declaration for encoding OUI specific information should be ++ * here. The corresponding decoder handler should be in lldpad. ++ */ ++ ++ ++/* The OUI specific handlers should be added here */ ++ ++vdptool_oui_hndlr_tbl_t oui_hndlr_tbl[] = { ++}; ++ + + static char *print_vdp_status(enum vdp22_cmd_status status) + { +@@ -144,23 +160,137 @@ static void get_arg_value(char *str, char **arg, char **argval) + *arg = str; + } + +-static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals) ++static char *get_oui_name(char *argvals) ++{ ++ char *oui_loc; ++ ++ oui_loc = strchr(argvals, ','); ++ if (oui_loc == NULL) ++ return NULL; ++ *oui_loc = '\0'; ++ return oui_loc + 1; ++} ++ ++static void fill_oui_hdr(vdptool_oui_data_t *oui_data, char *oui_name) ++{ ++ strncpy(oui_data->oui_name, oui_name, sizeof(oui_data->oui_name)); ++ snprintf(oui_data->data, sizeof(oui_data->data), "%02x%s", ++ (unsigned int)strlen(oui_data->oui_name), oui_data->oui_name); ++} ++ ++static bool run_vdptool_oui_hndlr(vdptool_oui_data_t *oui_data, char *argvals) ++{ ++ int cnt = 0, tbl_size; ++ char *dst; ++ size_t len = 0; ++ ++ tbl_size = sizeof(oui_hndlr_tbl) / sizeof(vdptool_oui_hndlr_tbl_t); ++ for (cnt = 0; cnt < tbl_size; cnt++) { ++ if (!strncmp(oui_hndlr_tbl[cnt].oui_name, oui_data->oui_name, ++ VDP22_OUI_MAX_NAME)) { ++ len = strlen(oui_data->data); ++ if (len >= sizeof(oui_data->data)) ++ return false; ++ dst = oui_data->data + len; ++ return oui_hndlr_tbl[cnt].oui_cli_encode_hndlr(dst, ++ argvals, len); ++ } ++ } ++ return false; ++} ++ ++/* ++ * The OUI can be input in many ways. ++ * It could be vdptool .... -c oui=companyA,Data1 -c oui=companyB,Data2 \ ++ * -c oui=companyA,Data3 ++ * Or ++ * vdptool .... -c oui=companyA,Data1Data3 -c oui=companyB,data2 ++ * This function takes care of both the case cases ++ * ++ * Anything after the comma in OUI data field is Org specific and it's upto ++ * the respective organization specific handlers to encode it so that it could ++ * be decoded appropriately by the ORG specific handlers inside lldpad. ++ * That is, Data1 and Data3 is ORG companyA specific and the OUI handlers ++ * of ORG companyA in vdptool and lldpad is responsible for encoding/decoding. ++ * ++ * Irrespective of how the command line interface to vdptool is, the input to ++ * lldpad is always the same. i.e. KeywordlenKeywordDatalenData ++ * For OUI, the data field will have the complete OUI data starting with ++ * ORG name (e.g companyA). So, in order to call the right handler routine, ++ * the OUI data field is split as OUInamelenOUInameOUIData. ++ * OUInamelen is 2B. ++ */ ++ ++static bool rewrite_oui_argval(char *argvals, vdptool_oui_data_t **oui_data, ++ int total_oui) ++{ ++ char *new_oui_argvals, *new_oui_name, *exist_oui_name; ++ bool flag = true, ret = false; ++ int cnt; ++ ++ new_oui_argvals = get_oui_name(argvals); ++ if (!new_oui_argvals) { ++ printf("Incorrect OUI Value, missing comma as delimited for " ++ "OUI Type\n"); ++ return false; ++ } ++ new_oui_name = argvals; ++ for (cnt = 0; cnt < total_oui; cnt++) { ++ if (!oui_data[cnt]) ++ continue; ++ exist_oui_name = oui_data[cnt]->oui_name; ++ if (!strncmp(new_oui_name, exist_oui_name, ++ VDP22_OUI_MAX_NAME)) { ++ flag = false; ++ break; ++ } ++ } ++ if (flag) { ++ oui_data[total_oui] = calloc(1, sizeof(vdptool_oui_data_t)); ++ fill_oui_hdr(oui_data[total_oui], new_oui_name); ++ ret = run_vdptool_oui_hndlr(oui_data[total_oui], ++ new_oui_argvals); ++ } else ++ ret = run_vdptool_oui_hndlr(oui_data[cnt], new_oui_argvals); ++ if (!ret) ++ return false; ++ return flag; ++} ++ ++int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals) + { + int len; + int i; + int fid = 0, oui = 0; ++ vdptool_oui_data_t **oui_data; ++ bool is_new; + + len = sizeof(cmd->obuf); + ++ /* To avoid another loop to figure the number of OUI's */ ++ oui_data = calloc(argc, sizeof(vdptool_oui_data_t *)); ++ if (!oui_data) { ++ printf("Not enough memory\n"); ++ return 0; ++ } ++ + if ((cmd->cmd == cmd_settlv) || (cmd->cmd == cmd_gettlv)) { + for (i = 0; i < argc; i++) { +- if (args[i]) { +- if (!strncasecmp(args[i], "filter", +- strlen("filter"))) +- fid++; +- else if (!strncasecmp(args[i], "oui", +- strlen("oui"))) ++ if (!args[i]) ++ continue; ++ if (!strncasecmp(args[i], "filter", strlen("filter"))) ++ fid++; ++ else if (!strncasecmp(args[i], "oui", strlen("oui"))) { ++ is_new = rewrite_oui_argval(argvals[i], ++ oui_data, ++ oui); ++ if (is_new) { ++ argvals[i] = oui_data[oui]->data; + oui++; ++ } else { ++ args[i] = NULL; ++ argvals[i] = NULL; ++ } + } + } + } +@@ -182,6 +312,11 @@ static int render_cmd(struct cmd *cmd, int argc, char **args, char **argvals) + len - strlen(cmd->obuf), "%04x%s", + (unsigned int)strlen(argvals[i]), argvals[i]); + } ++ for (i = 0; i < oui; i++) { ++ if (oui_data[i]) ++ free(oui_data[i]); ++ } ++ free(oui_data); + return strlen(cmd->obuf); + } + +-- +2.1.0 + diff --git a/open-lldp-v1.0.1-9-VDP-Support-for-OUI-infrastructure-in-vdp22.patch b/open-lldp-v1.0.1-9-VDP-Support-for-OUI-infrastructure-in-vdp22.patch new file mode 100644 index 0000000..47c73ac --- /dev/null +++ b/open-lldp-v1.0.1-9-VDP-Support-for-OUI-infrastructure-in-vdp22.patch @@ -0,0 +1,524 @@ +From 19bdcc3fe966dc7d6fc154d7d29addfe200c6afc Mon Sep 17 00:00:00 2001 +From: padkrish +Date: Wed, 21 Jan 2015 03:39:19 +0000 +Subject: [PATCH] VDP: Support for OUI infrastructure in vdp22. + +This commit is a framework for supporting OUI fields +in VDP22. This specific patch has changes for converting +OUI input to vdpnl structure, vdpnl to VSI + and place-holders for calling the OUI handlers. +The specific changes are: + +vdp22.c: +------- +Currently, the OUI handler code is linked statically to the lldpad (vdp22). +Some more enhancements are needed to support the dynamic linking of OUI +handler code. This is the general flow: +All the OUI handlers specify their init function in vdp22_oui_init_list. When +VDP22 receives a command with the OUI fields, then based on the OUI value, +it calls the appropriate init function. The OUI specific init function +implemented in the OUI specific file (not in this file) then registers its +handlers with VDP22. The handlers prototype is in qbg_vdp22_oui.h and it +currently has: +1. Handler for converting the OUI string to OUI structure which is a member of vdpnl structure. +2. Handler for converting the OUI structure from vdpnl structure to a OUI structure which is a member of vsi22 structure +3. Handler for creating the OUI fields for Tx. +4. handler for processing/Rx the OUI information +5. Handler for freeing the OUI structure +6. Handler to return the size of OUI PTLV + +Then, accordingly the respective handlers are called. +Function 'vdp22_delete_oui' calls each of the registered handlers for freeing +its OUI specific fields. +Function 'vdpnl_alloc_vsi_oui' calls each of the registered handlers for +creating a OUI structure in vsi22 structure. +Function 'oui_vdp_hndlr_init' is called by OUI specific code to register +its handlers. +Function 'vdp22_oui_init' calls the OUI specific init function. +Comments are embedded in the other functions added. + +vdp22sm.c: +---------- +Function 'oui22_ptlv_sz' calls each of the handlers in its VSI structure +to get the size of the OUI specific PTLV size. +Function 'oui22_2tlv' calls the handler for generating the OUI data for Tx. + +vdp22_cmds.c: +------------- +This file has a minor modification to get the number of OUI fields which is +encoded in the input to lldpad. + +vdp_ascii.c: +------------ +Function 'oui_str2vdpnl' calls the respective handler to convert the OUI input +string to the OUI structure stored in vdpnl structure. + +Signed-off-by: padkrish +Signed-off-by: John Fastabend +--- + include/qbg_vdp22_oui.h | 38 ++++++++++++ + qbg/vdp22.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++ + qbg/vdp22_cmds.c | 10 ++- + qbg/vdp22sm.c | 54 +++++++++++++++- + qbg/vdp_ascii.c | 37 ++++++++++- + 5 files changed, 293 insertions(+), 5 deletions(-) + +diff --git a/include/qbg_vdp22_oui.h b/include/qbg_vdp22_oui.h +index d31c6ad..0cce31e 100644 +--- a/include/qbg_vdp22_oui.h ++++ b/include/qbg_vdp22_oui.h +@@ -32,6 +32,7 @@ + */ + enum vdp22_oui { + VDP22_OUI_TYPE_LEN = 3, /* Size of OUI Type field */ ++ MAX_NUM_OUI = 10, + VDP22_OUI_MAX_NAME = 20, + MAX_OUI_DATA_LEN = 200 + }; +@@ -54,4 +55,41 @@ typedef struct vdptool_oui_hndlr_tbl_s { + bool (*oui_cli_encode_hndlr)(char *dst, char *src, size_t len); + } vdptool_oui_hndlr_tbl_t; + ++struct vdpnl_oui_data_s { ++ unsigned char oui_type[VDP22_OUI_TYPE_LEN]; ++ char oui_name[VDP22_OUI_MAX_NAME]; ++ int len; ++ char data[MAX_OUI_DATA_LEN]; ++ /* If vdpnl structure is used for IPC, then this cannot be a ptr as ++ * otherwise it needs to be flattened out. If this is just used within ++ * lldpad then this can be made a ptr instead of a static array. ++ * May need to revisit later TODO ++ */ ++}; ++ ++struct vdp22_oui_init_s { ++ unsigned char oui_type[VDP22_OUI_TYPE_LEN]; ++ char oui_name[VDP22_OUI_MAX_NAME]; ++ bool (*oui_init)(); ++}; ++ ++struct vdp22_oui_handler_s { ++ unsigned char oui_type[VDP22_OUI_TYPE_LEN]; ++ char oui_name[VDP22_OUI_MAX_NAME]; ++ /* This handler converts the OUI string to vdpnl structure */ ++ bool (*str2vdpnl_hndlr)(struct vdpnl_oui_data_s *, char *); ++ /* This handler converts the vdpnl structure to vsi22 structure */ ++ bool (*vdpnl2vsi22_hndlr)(void *, struct vdpnl_oui_data_s *, ++ struct vdp22_oui_data_s *); ++ /* This handler creates the OUI fields for Tx */ ++ size_t (*vdp_tx_hndlr)(char unsigned *, ++ struct vdp22_oui_data_s *, size_t); ++ /* This handler is called for processing/Rx the OUI information */ ++ bool (*vdp_rx_hndlr)(); ++ /* This handler frees the OUI structures */ ++ bool (*vdp_free_oui_hndlr)(struct vdp22_oui_data_s *); ++ /* This handler returns the size of OUI PTLV */ ++ unsigned long (*oui_ptlv_size_hndlr)(void *); ++}; ++ + #endif /* __VDP22_OUI_H__ */ +diff --git a/qbg/vdp22.c b/qbg/vdp22.c +index d7aa648..5cae83f 100644 +--- a/qbg/vdp22.c ++++ b/qbg/vdp22.c +@@ -44,6 +44,22 @@ + #include "qbg_vdp22_cmds.h" + #include "qbg_vdp22def.h" + ++#define INIT_FN(name) name##_oui_init ++#define EXTERN_FN(name)\ ++extern bool name##_oui_init() ++ ++/* Init handlers for OUI. OUI handlers should be added in vdp22_oui_init_list. ++ * First argument specifies the OUI code assigned to the Organization. ++ * Second argument is the string which should match with the CLI and the third ++ * argument is the init handler. ++ */ ++ ++struct vdp22_oui_init_s vdp22_oui_init_list[] = { ++}; ++ ++struct vdp22_oui_handler_s vdp22_oui_list[MAX_NUM_OUI]; ++unsigned char g_oui_index; ++ + /* + * VDP22 helper functions + */ +@@ -218,6 +234,36 @@ void vdp22_showvsi(struct vsi22 *p) + } + + /* ++ * Delete the OUI structures of VSI22 ++ * This calls the respective OUI handlers which are responsible for freeing ++ * the OUI specific 'data' element of 'vdp22_oui_data_s' structure. ++ */ ++ ++static void vdp22_delete_oui(struct vsi22 *p) ++{ ++ struct vdp22_oui_data_s *oui_str; ++ struct vdp22_oui_handler_s *oui_hndlr; ++ int idx; ++ bool ret; ++ ++ if ((p->no_ouidata == 0) || (!p->oui_str_data)) ++ return; ++ for (idx = 0; idx < p->no_ouidata; idx++) { ++ oui_str = &p->oui_str_data[idx]; ++ oui_hndlr = vdp22_get_oui_hndlr(oui_str->oui_name); ++ if (!oui_hndlr) ++ LLDPAD_ERR("%s: Unknown OUI %s\n", ++ __func__, oui_str->oui_name); ++ else { ++ ret = oui_hndlr->vdp_free_oui_hndlr(oui_str); ++ LLDPAD_DBG("%s: Free handler returned %d\n", __func__, ++ ret); ++ } ++ } ++ free(p->oui_str_data); ++} ++ ++/* + * Delete a complete VSI node not on queue. + */ + void vdp22_delete_vsi(struct vsi22 *p) +@@ -225,6 +271,7 @@ void vdp22_delete_vsi(struct vsi22 *p) + LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, p->vdp->ifname, p, + p->vsi[0]); + free(p->fdata); ++ vdp22_delete_oui(p); + free(p); + } + +@@ -475,6 +522,38 @@ static bool filter_ok(unsigned char ffmt, struct fid22 *fp, + return rc; + } + ++static void vdpnl_alloc_vsi_oui(struct vdpnl_vsi *vsi, struct vsi22 *p) ++{ ++ struct vdp22_oui_handler_s *oui_hndlr; ++ bool ret; ++ int idx; ++ ++ if (vsi->ouisz == 0) ++ return; ++ p->no_ouidata = vsi->ouisz; ++ p->oui_str_data = calloc(vsi->ouisz, sizeof(struct vdp22_oui_data_s)); ++ if (!p->oui_str_data) { ++ LLDPAD_ERR("%s: calloc return failure\n", __func__); ++ return; ++ } ++ for (idx = 0; idx < vsi->ouisz; idx++) { ++ struct vdpnl_oui_data_s *from = &vsi->oui_list[idx]; ++ struct vdp22_oui_data_s *to = &p->oui_str_data[idx]; ++ ++ oui_hndlr = vdp22_get_oui_hndlr(from->oui_name); ++ if (!oui_hndlr) ++ LLDPAD_ERR("%s: Unknown OUI Name %s\n", ++ __func__, from->oui_name); ++ else { ++ ret = oui_hndlr->vdpnl2vsi22_hndlr(p, from, to); ++ if (!ret) ++ LLDPAD_ERR("%s: handler return error for " ++ "oui %s\n", __func__, ++ from->oui_name); ++ } ++ } ++} ++ + /* + * Allocate a VSI node with filter information data. + * Check if input data is valid. +@@ -540,6 +619,7 @@ static struct vsi22 *vdp22_alloc_vsi_int(struct vdpnl_vsi *vsi, + fp->requestor.req_pid = vsi->req_pid; + fp->requestor.req_seq = vsi->req_seq; + } ++ vdpnl_alloc_vsi_oui(vsi, p); + *rc = 0; + LLDPAD_DBG("%s:%s vsi:%p(%02x)\n", __func__, vsi->ifname, p, p->vsi[0]); + return p; +@@ -1113,3 +1193,82 @@ void copy_vsi_external(struct vdpnl_vsi *vsi, struct vsi22 *p, int clif) + { + copy_vsi(vsi, p, clif); + } ++ ++/* ++ * This is called by the ORG specific code to register its handlers. ++ */ ++ ++bool oui_vdp_hndlr_init(struct vdp22_oui_handler_s *handler_ptr) ++{ ++ if (!handler_ptr) { ++ LLDPAD_DBG("%s: NULL handler\n", __func__); ++ return false; ++ } ++ memcpy(&(vdp22_oui_list[g_oui_index]), handler_ptr, ++ sizeof(vdp22_oui_list[g_oui_index])); ++ g_oui_index++; ++ return true; ++} ++ ++/* ++ * This calls the ORG specific init function. Then the ORG specific init ++ * function registers its handlers. ++ */ ++ ++static void vdp22_oui_init(char *oui_name) ++{ ++ int total; ++ int idx; ++ ++ total = sizeof(vdp22_oui_init_list) / sizeof(vdp22_oui_init_list[0]); ++ for (idx = 0; idx < total; idx++) { ++ if (!strncmp(vdp22_oui_init_list[idx].oui_name, oui_name, ++ sizeof(vdp22_oui_init_list[idx].oui_name))) { ++ if (!vdp22_oui_init_list[idx].oui_init()) ++ LLDPAD_ERR("%s: oui init return error for OUI " ++ "%s\n", __func__, oui_name); ++ } ++ } ++} ++ ++static struct vdp22_oui_handler_s *get_oui_hndlr_internal(char *oui_name) ++{ ++ int total; ++ int idx; ++ ++ total = g_oui_index; ++ for (idx = 0; idx < total; idx++) { ++ if (!strncmp(vdp22_oui_list[idx].oui_name, oui_name, ++ sizeof(vdp22_oui_list[idx].oui_name))) ++ return &vdp22_oui_list[idx]; ++ } ++ return NULL; ++} ++ ++/* ++ * Return the handler structure associated with this OUI. ++ * If the handler is already registered, then get_oui_hndlr_internal function ++ * will return it. Otherwise, vdp22_oui_init is called so that the handler ++ * init function is called which will register its handlers. This is done so ++ * that the ORG specific handlers are registered only on demand. ++ */ ++ ++struct vdp22_oui_handler_s *vdp22_get_oui_hndlr(char *oui_name) ++{ ++ struct vdp22_oui_handler_s *hndlr; ++ ++ if (oui_name == NULL) { ++ LLDPAD_ERR("%s: NULL arg\n", __func__); ++ return NULL; ++ } ++ /* ++ * First check if the handler exists. ++ * If not the OUI plugin is probably not initialized ++ * Initialize the handlers ++ */ ++ hndlr = get_oui_hndlr_internal(oui_name); ++ if (hndlr != NULL) ++ return hndlr; ++ vdp22_oui_init(oui_name); ++ return get_oui_hndlr_internal(oui_name); ++} +diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c +index 5d5ef6b..5b5788f 100644 +--- a/qbg/vdp22_cmds.c ++++ b/qbg/vdp22_cmds.c +@@ -356,20 +356,25 @@ static int get_vdp22_retval(int rc) + } + } + +-static int set_arg_vsi3(struct cmd *cmd, char *argvalue, bool test, int size) ++static int set_arg_vsi3(struct cmd *cmd, char *argvalue, bool test, int size, ++ int oui_size) + { + cmd_status good_cmd = vdp22_cmdok(cmd, cmd_settlv); + int rc; + struct vdpnl_vsi vsi; + struct vdpnl_mac mac[size]; ++ struct vdpnl_oui_data_s oui[oui_size]; + + if (good_cmd != cmd_success) + return good_cmd; + + memset(&vsi, 0, sizeof(vsi)); + memset(&mac, 0, sizeof(mac)); ++ memset(&oui, 0, sizeof(oui)); + vsi.maclist = mac; + vsi.macsz = size; ++ vsi.oui_list = (struct vdpnl_oui_data_s *)oui; ++ vsi.ouisz = oui_size; + rc = vdp_str2vdpnl(argvalue, &vsi, cmd->ifname); + if (rc) { + good_cmd = get_vdp22_retval(rc); +@@ -392,11 +397,12 @@ out: + static int set_arg_vsi2(struct cmd *cmd, char *argvalue, bool test) + { + int no = (cmd->ops >> OP_FID_POS) & 0xff; ++ int oui_no = (cmd->ops >> OP_OUI_POS) & 0xff; + + if (no <= 0) + return -EINVAL; + if ((cmd->ops & op_arg) && (cmd->ops & op_argval)) +- return set_arg_vsi3(cmd, argvalue, test, no); ++ return set_arg_vsi3(cmd, argvalue, test, no, oui_no); + else /* Not supported for now */ + return cmd_failed; + } +diff --git a/qbg/vdp22sm.c b/qbg/vdp22sm.c +index 83a97fb..db0e413 100644 +--- a/qbg/vdp22sm.c ++++ b/qbg/vdp22sm.c +@@ -184,6 +184,33 @@ static inline size_t vsi22_ptlv_sz(struct vsi22 *vp) + } + + /* ++ * This function calls the registered OUI handlers that returns the size of ++ * the OUI data. ++ */ ++ ++static inline size_t oui22_ptlv_sz(struct vsi22 *vp) ++{ ++ struct vdp22_oui_handler_s *oui_hndlr; ++ struct vdp22_oui_data_s *oui_str; ++ size_t size = 0; ++ int idx; ++ ++ if (vp->no_ouidata == 0) ++ return 0; ++ for (idx = 0; idx < vp->no_ouidata; idx++) { ++ oui_str = &(vp->oui_str_data[idx]); ++ oui_hndlr = vdp22_get_oui_hndlr(oui_str->oui_name); ++ if (!oui_hndlr) { ++ LLDPAD_ERR("%s: No handler registered for OUI %s\n", ++ __func__, oui_str->oui_name); ++ continue; ++ } ++ size += oui_hndlr->oui_ptlv_size_hndlr(oui_str->data); ++ } ++ return size; ++} ++ ++/* + * Extract 1, 2, 3, 4 byte integers in network byte format. + * Extract n bytes. + * Assume enough space available. +@@ -309,6 +336,29 @@ static size_t vsi22_2tlv_fdata(unsigned char *cp, struct fid22 *p, + return nbytes; + } + ++static void oui22_2tlv(struct vsi22 *vp, char unsigned *cp) ++{ ++ struct vdp22_oui_handler_s *oui_hndlr; ++ struct vdp22_oui_data_s *oui_str; ++ size_t offset = 0; ++ size_t temp_offset = 0; ++ int idx; ++ ++ if (vp->no_ouidata == 0) ++ return; ++ for (idx = 0; idx < vp->no_ouidata; idx++) { ++ oui_str = &(vp->oui_str_data[idx]); ++ oui_hndlr = vdp22_get_oui_hndlr(oui_str->oui_name); ++ if (!oui_hndlr) { ++ LLDPAD_ERR("%s: No handler registered for OUI %s\n", ++ __func__, oui_str->oui_name); ++ continue; ++ } ++ temp_offset = oui_hndlr->vdp_tx_hndlr(cp, oui_str, offset); ++ offset += temp_offset; ++ } ++} ++ + static void vsi22_2tlv(struct vsi22 *vp, char unsigned *cp, unsigned char stat) + { + size_t offset = 0, i; +@@ -478,7 +528,8 @@ static void vdp22st_wait_syscmd(struct vsi22 *vsip) + */ + static void vdp22st_process(struct vsi22 *vsi) + { +- unsigned short len = mgr22_ptlv_sz() + vsi22_ptlv_sz(vsi); ++ unsigned short len = mgr22_ptlv_sz() + vsi22_ptlv_sz(vsi) + ++ oui22_ptlv_sz(vsi); + unsigned char buf[len]; + struct qbg22_imm qbg; + +@@ -487,6 +538,7 @@ static void vdp22st_process(struct vsi22 *vsi) + qbg.u.c.data = buf; + mgr22_2tlv(vsi, buf); + vsi22_2tlv(vsi, buf + mgr22_ptlv_sz(), vsi->hints); ++ oui22_2tlv(vsi, buf + mgr22_ptlv_sz() + vsi22_ptlv_sz(vsi)); + vsi->smi.txmit_error = modules_notify(LLDP_MOD_ECP22, LLDP_MOD_VDP22, + vsi->vdp->ifname, &qbg); + if (!vsi->smi.txmit_error) { +diff --git a/qbg/vdp_ascii.c b/qbg/vdp_ascii.c +index 70ec79b..80a4419 100644 +--- a/qbg/vdp_ascii.c ++++ b/qbg/vdp_ascii.c +@@ -54,7 +54,8 @@ struct vsi_keyword_handler vsi_key_handle[] = { + /* {VSI22_ARG_VSIIDFRMT_STR, VSI_VSIIDFRMT_ARG}, TODO*/ + {VSI22_ARG_VSIID_STR, VSI_VSIID_ARG}, + {VSI22_ARG_HINTS_STR, VSI_HINTS_ARG}, +- {VSI22_ARG_FILTER_STR, VSI_FILTER_ARG} }; ++ {VSI22_ARG_FILTER_STR, VSI_FILTER_ARG}, ++ {VSI22_ARG_OUI_STR, VSI_OUI_ARG} }; + + /* + * Check if it is a UUID and consists of hexadecimal digits and dashes only. +@@ -225,6 +226,33 @@ static bool gethints(struct vdpnl_vsi *p, char *s) + return true; + } + ++static bool oui_str2vdpnl(struct vdpnl_vsi *vsi, char *p, unsigned short idx) ++{ ++ struct vdp22_oui_handler_s *oui_hndlr; ++ char *temp_argval = p; ++ char *oui_val; ++ char oui_name[VDP22_OUI_MAX_NAME]; ++ u8 oui_name_len; ++ ++ hexstr2bin(p, &oui_name_len, sizeof(oui_name_len)); ++ if (oui_name_len >= VDP22_OUI_MAX_NAME) ++ return false; ++ temp_argval = p + 2 * sizeof(oui_name_len); ++ oui_val = temp_argval + oui_name_len; ++ strncpy(oui_name, temp_argval, oui_name_len); ++ oui_name[oui_name_len] = '\0'; ++ oui_hndlr = vdp22_get_oui_hndlr(oui_name); ++ if (!oui_hndlr) ++ return false; ++ strncpy(vsi->oui_list[idx].oui_name, oui_name, ++ sizeof(vsi->oui_list[idx].oui_name)); ++ if (oui_hndlr->str2vdpnl_hndlr) ++ return oui_hndlr->str2vdpnl_hndlr(&(vsi->oui_list[idx]), ++ oui_val); ++ else ++ return false; ++} ++ + /* + * Read VSI association mode. If can be followed by an error code in brackets. + * For vdp22 protocol the allowed words are assoc, preassoc, preassoc-rr and +@@ -315,7 +343,7 @@ int vdp22_parse_str_vdpnl(struct vdpnl_vsi *vsi, u16 *key_flags, + int i, ioff = 0, numargs; + int ilen = strlen(orig_argvalue); + unsigned int no; +- unsigned short idx = 0; ++ unsigned short idx = 0, oui_idx = 0; + u16 num_arg_keys = 0; + + argvalue = strdup(orig_argvalue); +@@ -373,6 +401,11 @@ int vdp22_parse_str_vdpnl(struct vdpnl_vsi *vsi, u16 *key_flags, + if (!argvals[i] || !gethints(vsi, argvals[i])) + goto out_err; + break; ++ case VSI_OUI_ARG: ++ if (!oui_str2vdpnl(vsi, argvals[i], oui_idx)) ++ goto out_err; ++ oui_idx++; ++ break; + default: + goto out_err; + } +-- +2.1.0 + diff --git a/sources b/sources index 342b6ec..8d8da30 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -95a38cc51ad340edce65647d53740f7e lldpad-0.9.46.tar.gz +3bc1ce1b50b52a0583d25316211a9d78 lldpad-1.0.1.tar.gz