From db86b38beea96a242a3995235d5dbf33068f281f Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 8 Nov 2022 02:03:01 -0500 Subject: [PATCH] import lldpad-1.0.1-19.git036e314.el8 --- .gitignore | 1 + .lldpad.metadata | 1 + ...convert-command-parsing-to-null-term.patch | 29 + .../0002-macvtap-fix-error-condition.patch | 31 + ...021qaz-squelch-initialization-errors.patch | 31 + ...-8021Qaz-check-for-rx-block-validity.patch | 126 + ...-return-address-when-pulling-address.patch | 31 + ...reset-frame-status-on-message-delete.patch | 30 + ...07-Avoiding-null-pointer-dereference.patch | 71 + ...face-index-instead-of-name-in-libcon.patch | 192 + ...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 + ...en-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 ++ ...rom-sysv-to-posix-shared-memory-apis.patch | 424 ++ ...correctly-process-return-value-of-ge.patch | 37 + ...pability-incorrect-advertised-as-sta.patch | 72 + ...en-lldp-v1.0.1-27-fix-build-warnings.patch | 94 + .../open-lldp-v1.0.1-28-fix-oid-display.patch | 51 + ...p-v1.0.1-29-memleak-on-received-TLVs.patch | 109 + ...-cases-Some-test-cases-to-test-the-n.patch | 2722 ++++++++++++ ...ldp-v1.0.1-30-support-DSCP-selectors.patch | 42 + ...-31-Rebase-to-open-lldp-branch-1.1.0.patch | 3849 +++++++++++++++++ ...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 +++ SPECS/lldpad.spec | 366 ++ 42 files changed, 16253 insertions(+) create mode 100644 .gitignore create mode 100644 .lldpad.metadata create mode 100644 SOURCES/0001-vdp22-convert-command-parsing-to-null-term.patch create mode 100644 SOURCES/0002-macvtap-fix-error-condition.patch create mode 100644 SOURCES/0003-8021qaz-squelch-initialization-errors.patch create mode 100644 SOURCES/0004-8021Qaz-check-for-rx-block-validity.patch create mode 100644 SOURCES/0005-basman-use-return-address-when-pulling-address.patch create mode 100644 SOURCES/0006-agent-reset-frame-status-on-message-delete.patch create mode 100644 SOURCES/0007-Avoiding-null-pointer-dereference.patch create mode 100644 SOURCES/0008-Revert-Use-interface-index-instead-of-name-in-libcon.patch create mode 100644 SOURCES/open-lldp-v1.0.1-1-VDP-vdp22_cmds-retrieve-vsi-paramenter-data.patch create mode 100644 SOURCES/open-lldp-v1.0.1-10-VDP-Support-for-OUI-infrastructure-in-vdp22.patch create mode 100644 SOURCES/open-lldp-v1.0.1-11-VDP-Support-for-Cisco-specific-OUI-extensions-to-VDP.patch create mode 100644 SOURCES/open-lldp-v1.0.1-12-VDP22-Fix-the-ack-timeout-handler-to-set-the-right-t.patch create mode 100644 SOURCES/open-lldp-v1.0.1-13-VDP-Changes-in-OUI-infra-for-get-tlv.patch create mode 100644 SOURCES/open-lldp-v1.0.1-14-VDP-Changes-in-Cisco-OUI-handlers-to-support-get-tlv.patch create mode 100644 SOURCES/open-lldp-v1.0.1-15-VDP-Add-vdptool-man-page-to-Makefile.patch create mode 100644 SOURCES/open-lldp-v1.0.1-16-VDP-Fixed-DBG-print-compile-errors-in-32-bit-systems.patch create mode 100644 SOURCES/open-lldp-v1.0.1-17-lldp-automake-fixes-for-dist-distcheck.patch create mode 100644 SOURCES/open-lldp-v1.0.1-18-enabled-test-tool-building-for-distcheck.patch create mode 100644 SOURCES/open-lldp-v1.0.1-19-nltest-build-error.patch create mode 100644 SOURCES/open-lldp-v1.0.1-2-VDP-vdptool-first-version.patch create mode 100644 SOURCES/open-lldp-v1.0.1-20-lldp-automake-fix-drop-prefix-on-vdptool_LDADD.patch create mode 100644 SOURCES/open-lldp-v1.0.1-21-lldpad-Fix-DCBX-event-generation-from-lldpad.patch create mode 100644 SOURCES/open-lldp-v1.0.1-22-vdp-Fixed-the-memory-leak-for-modify-VSI-support-for.patch create mode 100644 SOURCES/open-lldp-v1.0.1-23-lldp-make-TTL-TLV-configurable.patch create mode 100644 SOURCES/open-lldp-v1.0.1-24-switch-from-sysv-to-posix-shared-memory-apis.patch create mode 100644 SOURCES/open-lldp-v1.0.1-25-l2_linux_packet-correctly-process-return-value-of-ge.patch create mode 100644 SOURCES/open-lldp-v1.0.1-26-lldpad-system-capability-incorrect-advertised-as-sta.patch create mode 100644 SOURCES/open-lldp-v1.0.1-27-fix-build-warnings.patch create mode 100644 SOURCES/open-lldp-v1.0.1-28-fix-oid-display.patch create mode 100644 SOURCES/open-lldp-v1.0.1-29-memleak-on-received-TLVs.patch create mode 100644 SOURCES/open-lldp-v1.0.1-3-VDP-vdptool-test-cases-Some-test-cases-to-test-the-n.patch create mode 100644 SOURCES/open-lldp-v1.0.1-30-support-DSCP-selectors.patch create mode 100644 SOURCES/open-lldp-v1.0.1-31-Rebase-to-open-lldp-branch-1.1.0.patch create mode 100644 SOURCES/open-lldp-v1.0.1-4-VDP-Changes-to-make-the-interface-to-VDP22-in-lldpad.patch create mode 100644 SOURCES/open-lldp-v1.0.1-5-VDP-Support-for-get-tlv-in-vdptool-and-VDP22.patch create mode 100644 SOURCES/open-lldp-v1.0.1-6-VDP-Support-in-VDP22-for-correct-error-code-status-t.patch create mode 100644 SOURCES/open-lldp-v1.0.1-7-VDP-Support-for-OUI-infrastructure-in-VDP22.patch create mode 100644 SOURCES/open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch create mode 100644 SOURCES/open-lldp-v1.0.1-9-VDP-Support-for-OUI-infrastructure-in-vdp22.patch create mode 100644 SPECS/lldpad.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57b7885 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/lldpad-1.0.1.tar.gz diff --git a/.lldpad.metadata b/.lldpad.metadata new file mode 100644 index 0000000..b6c69a4 --- /dev/null +++ b/.lldpad.metadata @@ -0,0 +1 @@ +238c6c548b8dd013d52ee996841d8dc69f8eeedf SOURCES/lldpad-1.0.1.tar.gz diff --git a/SOURCES/0001-vdp22-convert-command-parsing-to-null-term.patch b/SOURCES/0001-vdp22-convert-command-parsing-to-null-term.patch new file mode 100644 index 0000000..3cf417d --- /dev/null +++ b/SOURCES/0001-vdp22-convert-command-parsing-to-null-term.patch @@ -0,0 +1,29 @@ +From cadb2e55d3a751b4eb0e7c5b34ed037af43a164c Mon Sep 17 00:00:00 2001 +From: Aaron Conole +Date: Wed, 25 Aug 2021 10:19:16 -0400 +Subject: [PATCH 1/8] vdp22: convert command parsing to null term + +There is a theoretical buffer escape here. + +closes https://github.com/intel/openlldp/issues/74 +Signed-off-by: Aaron Conole +--- + qbg/vdp22_cmds.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c +index a8025ee..0ded0f1 100644 +--- a/qbg/vdp22_cmds.c ++++ b/qbg/vdp22_cmds.c +@@ -577,7 +577,7 @@ static int get_arg_vsi(struct cmd *cmd, char *arg, char *argvalue, + memset(&vsi, 0, sizeof(vsi)); + memset(vsi_str, 0, sizeof(vsi_str)); + vsi.request = cmd->tlvid; +- strncpy(vsi.ifname, cmd->ifname, sizeof(vsi.ifname)); ++ STRNCPY_TERMINATED(vsi.ifname, cmd->ifname, sizeof(vsi.ifname)); + good_cmd = cmd_failed; + if ((cmd->ops & op_config) && (cmd->ops & op_arg)) { + memset(&mac, 0, sizeof(mac)); +-- +2.31.1 + diff --git a/SOURCES/0002-macvtap-fix-error-condition.patch b/SOURCES/0002-macvtap-fix-error-condition.patch new file mode 100644 index 0000000..25261e9 --- /dev/null +++ b/SOURCES/0002-macvtap-fix-error-condition.patch @@ -0,0 +1,31 @@ +From cf7e43786749fcb1325d5b8e4cf0816f0eed3556 Mon Sep 17 00:00:00 2001 +From: Aaron Conole +Date: Wed, 25 Aug 2021 10:22:20 -0400 +Subject: [PATCH 2/8] macvtap: fix error condition + +If the socket() call fails, we will jump to out and pass a +negative value to close() which is not allowed. + +Fixes: d43abb0267f3 ("lldpad: do not use macv[tap/lan] interfaces as ports") +closes https://github.com/intel/openlldp/issues/75 +Signed-off-by: Aaron Conole +--- + lldp_util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lldp_util.c b/lldp_util.c +index 1e58b1e..be1333e 100644 +--- a/lldp_util.c ++++ b/lldp_util.c +@@ -681,7 +681,7 @@ int is_macvtap(const char *ifname) + s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + + if (s < 0) { +- goto out; ++ return false; + } + + nlh = malloc(NLMSG_SIZE); +-- +2.31.1 + diff --git a/SOURCES/0003-8021qaz-squelch-initialization-errors.patch b/SOURCES/0003-8021qaz-squelch-initialization-errors.patch new file mode 100644 index 0000000..8a8f974 --- /dev/null +++ b/SOURCES/0003-8021qaz-squelch-initialization-errors.patch @@ -0,0 +1,31 @@ +From ff70e2edbf79355527660c4df7a554bd66d3a1fb Mon Sep 17 00:00:00 2001 +From: Aaron Conole +Date: Wed, 25 Aug 2021 10:29:19 -0400 +Subject: [PATCH 3/8] 8021qaz: squelch initialization errors + +Some static analysis tools (like coverity) flag this array +as accessed without proper initialization. Squelch by forcing +initialization. + +closes https://github.com/intel/openlldp/issues/77 +Signed-off-by: Aaron Conole +--- + lldp_8021qaz_clif.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lldp_8021qaz_clif.c b/lldp_8021qaz_clif.c +index f776392..9031cb0 100644 +--- a/lldp_8021qaz_clif.c ++++ b/lldp_8021qaz_clif.c +@@ -253,7 +253,7 @@ static void ieee8021qaz_print_app_tlv(u16 len, char *info) + { + u8 app, app_idx, app_prio, app_sel; + u16 proto, offset = 2; +- u8 dscp[MAX_USER_PRIORITIES][MAX_APP_ENTRIES]; ++ u8 dscp[MAX_USER_PRIORITIES][MAX_APP_ENTRIES] = {0}; + u8 dscp_count[MAX_USER_PRIORITIES] = {0}; + u8 i, j; + bool first_app = true; +-- +2.31.1 + diff --git a/SOURCES/0004-8021Qaz-check-for-rx-block-validity.patch b/SOURCES/0004-8021Qaz-check-for-rx-block-validity.patch new file mode 100644 index 0000000..ea60605 --- /dev/null +++ b/SOURCES/0004-8021Qaz-check-for-rx-block-validity.patch @@ -0,0 +1,126 @@ +From bcb3ef5ab848eb648f05a840030df1f230976a70 Mon Sep 17 00:00:00 2001 +From: Aaron Conole +Date: Wed, 25 Aug 2021 10:37:22 -0400 +Subject: [PATCH 4/8] 8021Qaz: check for rx block validity + +There is a slim but possible race in the 8021Qaz processing when handling +TLVs during ifdown windows. To address this, check for the rx block +before dereferencing it. + +closes https://github.com/intel/openlldp/issues/78 +Signed-off-by: Aaron Conole +--- + lldp_8021qaz.c | 41 ++++++++++++++++++++++++++++------------- + 1 file changed, 28 insertions(+), 13 deletions(-) + +diff --git a/lldp_8021qaz.c b/lldp_8021qaz.c +index 045bd45..8bb2bc9 100644 +--- a/lldp_8021qaz.c ++++ b/lldp_8021qaz.c +@@ -1563,48 +1563,63 @@ static bool unpack_ieee8021qaz_tlvs(struct port *port, + /* Process */ + switch (tlv->info[OUI_SIZE]) { + case IEEE8021QAZ_ETSCFG_TLV: +- if (tlvs->rx->etscfg == NULL) { ++ if (tlvs->rx && tlvs->rx->etscfg == NULL) { + tlvs->ieee8021qazdu |= RCVD_IEEE8021QAZ_TLV_ETSCFG; + tlvs->rx->etscfg = tlv; +- } else { ++ } else if (tlvs->rx) { + LLDPAD_WARN("%s: %s: 802.1Qaz Duplicate ETSCFG TLV\n", + __func__, port->ifname); + agent->rx.dupTlvs |= DUP_IEEE8021QAZ_TLV_ETSCFG; + return false; ++ } else { ++ LLDPAD_INFO("%s: %s: 802.1Qaz port IFDOWN\n", ++ __func__, port->ifname); ++ return false; + } + break; + case IEEE8021QAZ_ETSREC_TLV: +- if (tlvs->rx->etsrec == NULL) { ++ if (tlvs->rx && tlvs->rx->etsrec == NULL) { + tlvs->ieee8021qazdu |= RCVD_IEEE8021QAZ_TLV_ETSREC; + tlvs->rx->etsrec = tlv; +- } else { ++ } else if (tlvs->rx) { + LLDPAD_WARN("%s: %s: 802.1Qaz Duplicate ETSREC TLV\n", + __func__, port->ifname); + agent->rx.dupTlvs |= DUP_IEEE8021QAZ_TLV_ETSREC; + return false; ++ } else { ++ LLDPAD_INFO("%s: %s: 802.1Qaz port IFDOWN\n", ++ __func__, port->ifname); ++ return false; + } + break; +- + case IEEE8021QAZ_PFC_TLV: +- if (tlvs->rx->pfc == NULL) { ++ if (tlvs->rx && tlvs->rx->pfc == NULL) { + tlvs->ieee8021qazdu |= RCVD_IEEE8021QAZ_TLV_PFC; + tlvs->rx->pfc = tlv; +- } else { ++ } else if (tlvs->rx) { + LLDPAD_WARN("%s: %s: 802.1Qaz Duplicate PFC TLV\n", + __func__, port->ifname); + agent->rx.dupTlvs |= DUP_IEEE8021QAZ_TLV_PFC; + return false; ++ } else { ++ LLDPAD_INFO("%s: %s: 802.1Qaz port IFDOWN\n", ++ __func__, port->ifname); ++ return false; + } + break; + case IEEE8021QAZ_APP_TLV: +- if (tlvs->rx->app == NULL) { ++ if (tlvs->rx && tlvs->rx->app == NULL) { + tlvs->ieee8021qazdu |= RCVD_IEEE8021QAZ_TLV_APP; + tlvs->rx->app = tlv; +- } else { ++ } else if (tlvs->rx) { + LLDPAD_WARN("%s: %s: 802.1Qaz Duplicate APP TLV\n", + __func__, port->ifname); + agent->rx.dupTlvs |= DUP_IEEE8021QAZ_TLV_APP; + return false; ++ } else { ++ LLDPAD_INFO("%s: %s: 802.1Qaz port IFDOWN\n", ++ __func__, port->ifname); ++ return false; + } + break; + default: +@@ -1891,26 +1906,26 @@ static void ieee8021qaz_mibUpdateObjects(struct port *port) + + tlvs = ieee8021qaz_data(port->ifname); + +- if (tlvs->rx->etscfg) { ++ if (tlvs->rx && tlvs->rx->etscfg) { + process_ieee8021qaz_etscfg_tlv(port); + } else if (tlvs->ets->cfgr) { + free(tlvs->ets->cfgr); + tlvs->ets->cfgr = NULL; + } + +- if (tlvs->rx->etsrec) { ++ if (tlvs->rx && tlvs->rx->etsrec) { + process_ieee8021qaz_etsrec_tlv(port); + } else if (tlvs->ets->recr) { + free(tlvs->ets->recr); + tlvs->ets->recr = NULL; + } + +- if (tlvs->rx->pfc) ++ if (tlvs->rx && tlvs->rx->pfc) + process_ieee8021qaz_pfc_tlv(port); + else if (tlvs->pfc) + tlvs->pfc->remote_param = false; + +- if (tlvs->rx->app) ++ if (tlvs->rx && tlvs->rx->app) + process_ieee8021qaz_app_tlv(port); + else + ieee8021qaz_app_reset(&tlvs->app_head); +-- +2.31.1 + diff --git a/SOURCES/0005-basman-use-return-address-when-pulling-address.patch b/SOURCES/0005-basman-use-return-address-when-pulling-address.patch new file mode 100644 index 0000000..6fd0f27 --- /dev/null +++ b/SOURCES/0005-basman-use-return-address-when-pulling-address.patch @@ -0,0 +1,31 @@ +From f1488bbb0991f99d823d384b00f6fb1de385baa3 Mon Sep 17 00:00:00 2001 +From: Aaron Conole +Date: Wed, 10 Nov 2021 16:40:20 -0500 +Subject: [PATCH 5/8] basman: use return address when pulling address + +The managed address pulling routine will fail to reset the return +value from a previous attempt if no IPv4 and IPv6 addresses are +available. Use the return address of the hwaddr fetch. + +Resolves: https://github.com/intel/openlldp/issues/82 +Signed-off-by: Aaron Conole +--- + lldp_basman.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lldp_basman.c b/lldp_basman.c +index 25e7d9e..cb0c50c 100644 +--- a/lldp_basman.c ++++ b/lldp_basman.c +@@ -515,7 +515,7 @@ static int basman_bld_manaddr_tlv(struct basman_data *bd, + if (rc) { + rc = basman_get_manaddr_sub(bd, agent, MANADDR_IPV6); + if (rc) +- basman_get_manaddr_sub(bd, agent, MANADDR_ALL802); ++ rc = basman_get_manaddr_sub(bd, agent, MANADDR_ALL802); + } + out_err: + return rc; +-- +2.31.1 + diff --git a/SOURCES/0006-agent-reset-frame-status-on-message-delete.patch b/SOURCES/0006-agent-reset-frame-status-on-message-delete.patch new file mode 100644 index 0000000..eb2e97a --- /dev/null +++ b/SOURCES/0006-agent-reset-frame-status-on-message-delete.patch @@ -0,0 +1,30 @@ +From fae175635442577605e06b10133306f86863f395 Mon Sep 17 00:00:00 2001 +From: Rajesh B M <59466308+rajeshm-elisity@users.noreply.github.com> +Date: Mon, 8 Mar 2021 23:29:32 +0530 +Subject: [PATCH 6/8] agent: reset frame status on message delete + +Currently, when the agent state machine transitions out of +DELETE_INFO, it leaves the rcvFrame flag set. This flag should +be cleared since the frame info is no longer considered usable. + +Signed-off-by: Rajesh B M +Signed-off-by: Aaron Conole +--- + lldp/rx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lldp/rx.c b/lldp/rx.c +index 9a0c758..f0c8002 100644 +--- a/lldp/rx.c ++++ b/lldp/rx.c +@@ -568,6 +568,7 @@ void process_delete_info(struct port *port, struct lldp_agent *agent) + + agent->rx.sizein = 0; + agent->rx.remoteChange = true; ++ agent->rx.rcvFrame = false; + return; + } + +-- +2.31.1 + diff --git a/SOURCES/0007-Avoiding-null-pointer-dereference.patch b/SOURCES/0007-Avoiding-null-pointer-dereference.patch new file mode 100644 index 0000000..a865991 --- /dev/null +++ b/SOURCES/0007-Avoiding-null-pointer-dereference.patch @@ -0,0 +1,71 @@ +From 2a352d36e2ecc3df4b1c2155b3fd2fa11f95e0bc Mon Sep 17 00:00:00 2001 +From: klebertarcisio +Date: Fri, 2 Apr 2021 19:54:03 -0300 +Subject: [PATCH 7/8] Avoiding null pointer dereference + +--- + ctrl_iface.c | 2 ++ + dcbtool_cmds.c | 2 ++ + lldp_8021qaz.c | 4 ++++ + lldp_dcbx.c | 4 ++++ + 4 files changed, 12 insertions(+) + +diff --git a/ctrl_iface.c b/ctrl_iface.c +index 666f7c8..5f86fd2 100644 +--- a/ctrl_iface.c ++++ b/ctrl_iface.c +@@ -180,6 +180,8 @@ int clif_iface_attach(struct clif_data *clifd, + } else { + tlv = strdup(ibuf); + str = tlv; ++ if (!str) ++ goto err_tlv; + str++; + /* Count number of TLV Modules */ + tokenize = strtok(str, delim); +diff --git a/dcbtool_cmds.c b/dcbtool_cmds.c +index 0846f83..e1c76c4 100644 +--- a/dcbtool_cmds.c ++++ b/dcbtool_cmds.c +@@ -373,6 +373,8 @@ int handle_dcb_cmds(struct clif *clif, int argc, char *argv[], int raw) + } + + cmd_args = get_cmd_args(); ++ if (!cmd_args) ++ return -1; + + if (get_feature() == FEATURE_DCBX) + snprintf(cbuf, sizeof(cbuf), "%c%01x%02x%02x%s", +diff --git a/lldp_8021qaz.c b/lldp_8021qaz.c +index 8bb2bc9..5fccbe4 100644 +--- a/lldp_8021qaz.c ++++ b/lldp_8021qaz.c +@@ -1959,6 +1959,10 @@ int ieee8021qaz_rchange(struct port *port, struct lldp_agent *agent, + if (tlv->type == TYPE_1) { + clear_ieee8021qaz_rx(qaz_tlvs); + rx = malloc(sizeof(*rx)); ++ if (!rx) { ++ LLDPAD_INFO("failed malloc for rx\n"); ++ return TLV_ERR; ++ } + memset(rx, 0, sizeof(*rx)); + qaz_tlvs->rx = rx; + qaz_tlvs->ieee8021qazdu = 0; +diff --git a/lldp_dcbx.c b/lldp_dcbx.c +index 3567634..66df857 100644 +--- a/lldp_dcbx.c ++++ b/lldp_dcbx.c +@@ -695,6 +695,10 @@ int dcbx_rchange(struct port *port, struct lldp_agent *agent, struct unpacked_tl + */ + if (tlv->type == TYPE_1) { + manifest = malloc(sizeof(*manifest)); ++ if (!manifest) { ++ LLDPAD_INFO("failed malloc for manifest\n"); ++ return TLV_ERR; ++ } + memset(manifest, 0, sizeof(*manifest)); + dcbx->manifest = manifest; + dcbx->dcbdu = 0; +-- +2.31.1 + diff --git a/SOURCES/0008-Revert-Use-interface-index-instead-of-name-in-libcon.patch b/SOURCES/0008-Revert-Use-interface-index-instead-of-name-in-libcon.patch new file mode 100644 index 0000000..ea700dc --- /dev/null +++ b/SOURCES/0008-Revert-Use-interface-index-instead-of-name-in-libcon.patch @@ -0,0 +1,192 @@ +From 79658533561990d93a74fd25b4d1b26c01182a8e Mon Sep 17 00:00:00 2001 +From: Aaron Conole +Date: Mon, 20 Sep 2021 16:27:56 -0400 +Subject: [PATCH 8/8] Revert "Use interface index instead of name in libconfig" + +This reverts commit e272d34f45bc15d52424228f824c1ad96932867e. + +During production, it was found that the ifindex can be unstable. +See discussion at https://github.com/intel/openlldp/pull/3 + +Signed-off-by: Aaron Conole +(cherry picked from commit 2c7dd5e4a0db201a850f8037b957acbd14950297) +--- + config.c | 35 ++++++++--------------------------- + include/config.h | 3 --- + lldp_dcbx_cfg.c | 24 +++++++----------------- + 3 files changed, 15 insertions(+), 47 deletions(-) + +diff --git a/config.c b/config.c +index 41b5045..7e969b9 100644 +--- a/config.c ++++ b/config.c +@@ -55,21 +55,6 @@ + + config_t lldpad_cfg; + +-/* +- * config_ifkey - Generates a config key +- * +- * Given an interface name this functions generates +- * a key (based on interface's index) suitable +- * to pass to libconfig. +- * +- */ +-void config_ifkey(const char *name, char *ifkey) { +- int index = if_nametoindex(name); +- +- if(index) +- sprintf(ifkey, "if%d", index); +-} +- + /* + * init_cfg - initialze the global lldpad_cfg via config_init + * +@@ -466,15 +451,14 @@ static int lookup_config_value(char *path, union cfg_get v, int type) + int get_config_setting(const char *ifname, int agenttype, char *path, + union cfg_get v, int type) + { +- char p[1024], ifkey[IFNAMSIZ]; ++ char p[1024]; + int rval = CONFIG_FALSE; + const char *section = agent_type2section(agenttype); + + /* look for setting in section->ifname area first */ + if (ifname) { +- config_ifkey(ifname, ifkey); + snprintf(p, sizeof(p), "%s.%s.%s", +- section, ifkey, path); ++ section, ifname, path); + rval = lookup_config_value(p, v, type); + } + +@@ -491,16 +475,15 @@ int get_config_setting(const char *ifname, int agenttype, char *path, + int remove_config_setting(const char *ifname, int agenttype, char *parent, + char *name) + { +- char p[1024], ifkey[IFNAMSIZ]; ++ char p[1024]; + int rval = CONFIG_FALSE; + config_setting_t *setting = NULL; + const char *section = agent_type2section(agenttype); + + /* look for setting in section->ifname area first */ +- if (ifname) { +- config_ifkey(ifname, ifkey); ++ if (ifname) { + snprintf(p, sizeof(p), "%s.%s.%s", +- section, ifkey, parent); ++ section, ifname, parent); + setting = config_lookup(&lldpad_cfg, p); + } + +@@ -587,17 +570,15 @@ int set_config_setting(const char *ifname, int agenttype, char *path, + union cfg_set v, int type) + { + config_setting_t *setting = NULL; +- char p[1024], ifkey[IFNAMSIZ]; ++ char p[1024]; + int rval = cmd_success; + const char *section = agent_type2section(agenttype); + + LLDPAD_DBG("%s(%i): \n", __func__, __LINE__); + +- if (strlen(ifname)){ +- config_ifkey(ifname, ifkey); ++ if (strlen(ifname)) + snprintf(p, sizeof(p), "%s.%s.%s", +- section, ifkey, path); +- } ++ section, ifname, path); + else + snprintf(p, sizeof(p), "%s.%s.%s", + section, LLDP_COMMON, path); +diff --git a/include/config.h b/include/config.h +index 3abf8e8..61cb5da 100644 +--- a/include/config.h ++++ b/include/config.h +@@ -111,7 +111,4 @@ void destroy_cfg(void); + int check_cfg_file(void); + int check_for_old_file_format(void); + void init_ports(void); +- +-void config_ifkey(const char *name, char *ifkey); +- + #endif /* _CONFIG_H_ */ +diff --git a/lldp_dcbx_cfg.c b/lldp_dcbx_cfg.c +index 40cabb2..ab9cc35 100644 +--- a/lldp_dcbx_cfg.c ++++ b/lldp_dcbx_cfg.c +@@ -99,15 +99,12 @@ static config_setting_t *construct_new_setting(char *device_name) + config_setting_t *tmp2_setting = NULL; + char abuf[32]; + int i; +- char device_name_sanitized[IFNAMSIZ]; + + dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING); + if (!dcbx_setting) + return NULL; + +- config_ifkey(device_name, device_name_sanitized); +- +- eth_setting = config_setting_add(dcbx_setting, device_name_sanitized, ++ eth_setting = config_setting_add(dcbx_setting, device_name, + CONFIG_TYPE_GROUP); + if (!eth_setting) + goto set_error; +@@ -374,13 +371,11 @@ static int _set_persistent(char *device_name, int dcb_enable, + config_setting_t *setting_value = NULL; + char abuf[2*DCB_MAX_TLV_LENGTH + 1]; + int result, i; +- char device_name_sanitized[IFNAMSIZ]; + + dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING); +- config_ifkey(device_name, device_name_sanitized); + if (dcbx_setting) + eth_settings = config_setting_get_member(dcbx_setting, +- device_name_sanitized); ++ device_name); + + /* init the internal data store for device_name */ + if (NULL == eth_settings) { +@@ -787,15 +782,13 @@ int get_persistent(char *device_name, full_dcb_attribs *attribs) + int result = cmd_failed, i; + int results[MAX_USER_PRIORITIES]; + int len; +- char abuf[32], device_name_sanitized[IFNAMSIZ]; ++ char abuf[32]; + + memset(attribs, 0, sizeof(*attribs)); + dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING); +- +- config_ifkey(device_name, device_name_sanitized); + if (dcbx_setting) +- eth_settings = config_setting_get_member(dcbx_setting, +- device_name_sanitized); ++ eth_settings = config_setting_get_member(dcbx_setting, ++ device_name); + + /* init the internal data store for device_name */ + result = get_default_persistent(device_name, attribs); +@@ -1074,16 +1067,13 @@ int get_dcb_enable_state(char *ifname, int *result) + int rc = EINVAL; + config_setting_t *settings = NULL; + char path[sizeof(DCBX_SETTING) + IFNAMSIZ + 16]; +- char ifkey[IFNAMSIZ]; +- +- config_ifkey(ifname, ifkey); + + memset(path, 0, sizeof(path)); +- snprintf(path, sizeof(path), "%s.%s.dcb_enable", DCBX_SETTING, ifkey); ++ snprintf(path, sizeof(path), "%s.%s.dcb_enable", DCBX_SETTING, ifname); + settings = config_lookup(&lldpad_cfg, path); + if (!settings) { + LLDPAD_INFO("### %s:%s:failed on %s\n", __func__, ifname, path); +- snprintf(path, sizeof(path), "%s.dcb_enable", ifkey); ++ snprintf(path, sizeof(path), "%s.dcb_enable", ifname); + settings = config_lookup(&lldpad_cfg, path); + if (!settings) { + LLDPAD_INFO("### %s:%s:failed again %s\n", __func__, ifname, path); +-- +2.31.1 + diff --git a/SOURCES/open-lldp-v1.0.1-1-VDP-vdp22_cmds-retrieve-vsi-paramenter-data.patch b/SOURCES/open-lldp-v1.0.1-1-VDP-vdp22_cmds-retrieve-vsi-paramenter-data.patch new file mode 100644 index 0000000..fb2968a --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-10-VDP-Support-for-OUI-infrastructure-in-vdp22.patch b/SOURCES/open-lldp-v1.0.1-10-VDP-Support-for-OUI-infrastructure-in-vdp22.patch new file mode 100644 index 0000000..9f8ab5e --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-11-VDP-Support-for-Cisco-specific-OUI-extensions-to-VDP.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-12-VDP22-Fix-the-ack-timeout-handler-to-set-the-right-t.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-13-VDP-Changes-in-OUI-infra-for-get-tlv.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-14-VDP-Changes-in-Cisco-OUI-handlers-to-support-get-tlv.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-15-VDP-Add-vdptool-man-page-to-Makefile.patch b/SOURCES/open-lldp-v1.0.1-15-VDP-Add-vdptool-man-page-to-Makefile.patch new file mode 100644 index 0000000..9bc32b5 --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-16-VDP-Fixed-DBG-print-compile-errors-in-32-bit-systems.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-17-lldp-automake-fixes-for-dist-distcheck.patch b/SOURCES/open-lldp-v1.0.1-17-lldp-automake-fixes-for-dist-distcheck.patch new file mode 100644 index 0000000..2c7e1e3 --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-18-enabled-test-tool-building-for-distcheck.patch b/SOURCES/open-lldp-v1.0.1-18-enabled-test-tool-building-for-distcheck.patch new file mode 100644 index 0000000..6590ef8 --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-19-nltest-build-error.patch b/SOURCES/open-lldp-v1.0.1-19-nltest-build-error.patch new file mode 100644 index 0000000..d0427a4 --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-2-VDP-vdptool-first-version.patch b/SOURCES/open-lldp-v1.0.1-2-VDP-vdptool-first-version.patch new file mode 100644 index 0000000..f1918c7 --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-20-lldp-automake-fix-drop-prefix-on-vdptool_LDADD.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-21-lldpad-Fix-DCBX-event-generation-from-lldpad.patch b/SOURCES/open-lldp-v1.0.1-21-lldpad-Fix-DCBX-event-generation-from-lldpad.patch new file mode 100644 index 0000000..735cc3d --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-22-vdp-Fixed-the-memory-leak-for-modify-VSI-support-for.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-23-lldp-make-TTL-TLV-configurable.patch b/SOURCES/open-lldp-v1.0.1-23-lldp-make-TTL-TLV-configurable.patch new file mode 100644 index 0000000..51cbc9b --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-24-switch-from-sysv-to-posix-shared-memory-apis.patch b/SOURCES/open-lldp-v1.0.1-24-switch-from-sysv-to-posix-shared-memory-apis.patch new file mode 100644 index 0000000..bbf3908 --- /dev/null +++ b/SOURCES/open-lldp-v1.0.1-24-switch-from-sysv-to-posix-shared-memory-apis.patch @@ -0,0 +1,424 @@ +From 1add5db5feaafe7cbc41f2896f5c2887c96bff92 Mon Sep 17 00:00:00 2001 +From: Chris Leech +Date: Sun, 16 Aug 2015 21:00:58 -0700 +Subject: [PATCH] lldpad: switch from sysv to posix shared memory apis + +The use of SysV shared memory, to pass state between running instances of +lldpad in the initramfs and then from the root fs, is difficult to work +with from a security policy. When lldpad runs in the initramfs there is +no security policy loaded. Then when it's restarted after an SELinux +policy has been loaded, there is no way to correct the context on the +already existing shared memory segment. This would result in the need +for an overly permissive policy for lldpad. + +By switching to POSIX APIs the segment is mapped from a tmpfs file with +a directory entry under /dev/shm/. This lets us add a file contents +entry to the SELinux policy that matches that path, and a proper +security context can be restored to it before restarting lldpad. + +Signed-off-by: Chris Leech +Signed-off-by: John Fastabend +--- + Makefile.am | 2 +- + include/lldpad_shm.h | 2 +- + lldpad_shm.c | 169 ++++++++++++++++++++++++++++++--------------------- + 3 files changed, 103 insertions(+), 70 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 84d68ee..551d4c7 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -17,7 +17,7 @@ parse_cli.o: CFLAGS+=-U_FORTIFY_SOURCE -Wno-error + + ## system requires a shared libconfig + AM_CFLAGS = -Wall -Werror -Wextra -Wformat=2 $(LIBCONFIG_CFLAGS) $(LIBNL_CFLAGS) +-AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS) ++AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS) -lrt + + ## header files to be installed, for programs using the client interface to lldpad + lldpad_includedir= ${includedir}/lldpad +diff --git a/include/lldpad_shm.h b/include/lldpad_shm.h +index 00d20eb..587b555 100644 +--- a/include/lldpad_shm.h ++++ b/include/lldpad_shm.h +@@ -31,7 +31,7 @@ + #include "lldpad.h" + #include "lldp_rtnl.h" + +-#define LLDPAD_SHM_KEY ((('l'<<24) | ('l'<<16) | ('d'<<8) | ('p')) + 'a' + 'd' + 1) ++#define LLDPAD_SHM_PATH "/lldpad.state" + #define LLDPAD_SHM_SIZE 4096 + + /* PID value used to indicate pid field is uninitialized */ +diff --git a/lldpad_shm.c b/lldpad_shm.c +index 4afcf73..d8bc0c5 100644 +--- a/lldpad_shm.c ++++ b/lldpad_shm.c +@@ -29,7 +29,9 @@ + #include + #include + #include +-#include ++#include ++#include ++#include + #include + #include + #include +@@ -39,16 +41,7 @@ + + void mark_lldpad_shm_for_removal() + { +- int shmid; +- struct shmid_ds shminfo; +- +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); +- +- if (shmid < 0) +- return; +- +- if (shmctl(shmid, IPC_RMID, &shminfo) < 0) +- return; ++ shm_unlink(LLDPAD_SHM_PATH); + } + + /* return: 1 = success, 0 = failed */ +@@ -101,16 +94,21 @@ int lldpad_shm_get_msap(const char *device_name, int type, char *info, size_t *l + unsigned num_entries; + int version; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); +- if (shmid < 0 && errno == ENOENT) +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, +- IPC_CREAT | IPC_EXCL | 0x180); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return rval; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ if (ftruncate(shmid, LLDPAD_SHM_SIZE)) { ++ close(shmid); ++ return rval; ++ } ++ ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return rval; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -147,7 +145,7 @@ int lldpad_shm_get_msap(const char *device_name, int type, char *info, size_t *l + rval = 1; + } + done: +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return rval; + } +@@ -162,16 +160,21 @@ int lldpad_shm_set_msap(const char *device_name, int type, char *info, size_t le + int version; + unsigned num_entries; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); +- if (shmid < 0 && errno == ENOENT) +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, +- IPC_CREAT | IPC_EXCL | 0x180); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return rval; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ if (ftruncate(shmid, LLDPAD_SHM_SIZE)) { ++ close(shmid); ++ return rval; ++ } ++ ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return rval; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -212,7 +215,7 @@ int lldpad_shm_set_msap(const char *device_name, int type, char *info, size_t le + } + + done: +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return rval; + } +@@ -226,16 +229,21 @@ int lldpad_shm_get_dcbx(const char *device_name) + unsigned num_entries; + int version; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); +- if (shmid < 0 && errno == ENOENT) +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, +- IPC_CREAT | IPC_EXCL | 0x180); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return rval; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ if (ftruncate(shmid, LLDPAD_SHM_SIZE)) { ++ close(shmid); ++ return rval; ++ } ++ ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return rval; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -264,7 +272,7 @@ int lldpad_shm_get_dcbx(const char *device_name) + } + + done: +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return rval; + } +@@ -279,16 +287,21 @@ int lldpad_shm_set_dcbx(const char *device_name, int dcbx_mode) + unsigned num_entries; + int version; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); +- if (shmid < 0 && errno == ENOENT) +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, +- IPC_CREAT | IPC_EXCL | 0x180); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return rval; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ if (ftruncate(shmid, LLDPAD_SHM_SIZE)) { ++ close(shmid); ++ return rval; ++ } ++ ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return rval; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -330,7 +343,7 @@ int lldpad_shm_set_dcbx(const char *device_name, int dcbx_mode) + } + + done: +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return rval; + } +@@ -346,16 +359,21 @@ pid_t lldpad_shm_getpid() + pid_t rval = -1; + int version; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); +- if (shmid < 0 && errno == ENOENT) +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, +- IPC_CREAT | IPC_EXCL | 0x180); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return rval; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ if (ftruncate(shmid, LLDPAD_SHM_SIZE)) { ++ close(shmid); ++ return rval; ++ } ++ ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return rval; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -366,7 +384,7 @@ pid_t lldpad_shm_getpid() + + rval = shmaddr->pid; + +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return rval; + } +@@ -379,13 +397,16 @@ int lldpad_shm_setpid(pid_t pid) + pid_t rval = 0; + int version; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return rval; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return rval; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -396,7 +417,7 @@ int lldpad_shm_setpid(pid_t pid) + + shmaddr->pid = pid; + +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return 1; + } +@@ -410,13 +431,16 @@ int clear_dcbx_state() + int version; + unsigned num_entries; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return 0; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return 0; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -437,7 +461,7 @@ int clear_dcbx_state() + sizeof(dcbx_state)); + + done: +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + return 1; + } + +@@ -451,13 +475,16 @@ int set_dcbx_state(const char *device_name, dcbx_state *state) + int version; + unsigned num_entries; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return rval; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return rval; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -487,7 +514,7 @@ int set_dcbx_state(const char *device_name, dcbx_state *state) + } + + done: +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return rval; + } +@@ -505,13 +532,16 @@ int get_dcbx_state(const char *device_name, dcbx_state *state) + int version; + unsigned num_entries; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR); + + if (shmid < 0) + return rval; + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); +- if ((long) shmaddr == -1) ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) + return rval; + + version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT; +@@ -537,7 +567,7 @@ int get_dcbx_state(const char *device_name, dcbx_state *state) + } + + done: +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return rval; + } +@@ -562,17 +592,20 @@ int print_lldpad_shm() + int ent_size; + struct lldpad_shm_entry *entry_ptr = NULL; + +- shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0); ++ shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR); + + if (shmid < 0) { +- printf("failed to shmget\n"); ++ printf("failed to shm_open\n"); + return rval; + } + +- shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0); ++ shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED, shmid, 0); + shmaddr_ver0 = (struct lldpad_shm_tbl_ver0 *)shmaddr; +- if ((long) shmaddr == -1) { +- printf("failed to shmat\n"); ++ close(shmid); ++ if (shmaddr == MAP_FAILED) { ++ printf("failed to mmap\n"); + return rval; + } + +@@ -633,7 +666,7 @@ int print_lldpad_shm() + rval = 1; + + done: +- shmdt(shmaddr); ++ munmap(shmaddr, LLDPAD_SHM_SIZE); + + return rval; + } +-- +2.5.0 + diff --git a/SOURCES/open-lldp-v1.0.1-25-l2_linux_packet-correctly-process-return-value-of-ge.patch b/SOURCES/open-lldp-v1.0.1-25-l2_linux_packet-correctly-process-return-value-of-ge.patch new file mode 100644 index 0000000..0af32c7 --- /dev/null +++ b/SOURCES/open-lldp-v1.0.1-25-l2_linux_packet-correctly-process-return-value-of-ge.patch @@ -0,0 +1,37 @@ +From e212eb214afaea300194333f652b950941299339 Mon Sep 17 00:00:00 2001 +From: Johannes Thumshirn +Date: Wed, 20 May 2015 16:14:37 +0000 +Subject: [PATCH] l2_linux_packet: correctly process return value of + get_perm_hwaddr + +On success get_perm_hwaddr() returns the number of bytes read from the +netlink socket. + +l2_packet_init() checked for 0 as a successful return value. + +Adopt get_perm_hwaddr() to return 0 on success. + +Refrence: bsc#929171 + +Signed-off-by: Johannes Thumshirn +Signed-off-by: John Fastabend +--- + lldp_rtnl.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/lldp_rtnl.c b/lldp_rtnl.c +index 33b4d19..8d4f0cc 100644 +--- a/lldp_rtnl.c ++++ b/lldp_rtnl.c +@@ -322,6 +322,8 @@ int get_perm_hwaddr(const char *ifname, u8 *buf_perm, u8 *buf_san) + + memcpy(buf_perm, RTA_DATA(rta), ETH_ALEN); + memcpy(buf_san, RTA_DATA(rta) + ETH_ALEN, ETH_ALEN); ++ ++ rc = 0; + out: + close(s); + out_nosock: +-- +2.5.0 + diff --git a/SOURCES/open-lldp-v1.0.1-26-lldpad-system-capability-incorrect-advertised-as-sta.patch b/SOURCES/open-lldp-v1.0.1-26-lldpad-system-capability-incorrect-advertised-as-sta.patch new file mode 100644 index 0000000..d065cec --- /dev/null +++ b/SOURCES/open-lldp-v1.0.1-26-lldpad-system-capability-incorrect-advertised-as-sta.patch @@ -0,0 +1,72 @@ +From 036e314bd93602f7388262cc37faf8b626980af1 Mon Sep 17 00:00:00 2001 +From: Gary Loughnane +Date: Mon, 17 Aug 2015 21:19:24 +0000 +Subject: [PATCH] lldpad: system capability incorrect advertised as station + only + +Fix system capability TLV on switch. On our switches we have found +that the system capability was being advertised as Station Only. This +patch changes the capability to Bridge. + +Signed-off-by: Gary Loughnane +Signed-off-by: John Fastabend +--- + include/lldp_util.h | 1 + + lldp_util.c | 22 +++++++++++++++++++++- + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/include/lldp_util.h b/include/lldp_util.h +index 878426b..69b67b1 100644 +--- a/include/lldp_util.h ++++ b/include/lldp_util.h +@@ -125,6 +125,7 @@ int is_active(const char *ifname); + int is_bond(const char *ifname); + int is_san_mac(u8 *addr); + int is_bridge(const char *ifname); ++int is_bridge_port(const char *ifname); + int is_vlan(const char *ifname); + int is_vlan_capable(const char *ifname); + int is_wlan(const char *ifname); +diff --git a/lldp_util.c b/lldp_util.c +index f1fb7b9..62f0af8 100644 +--- a/lldp_util.c ++++ b/lldp_util.c +@@ -580,6 +580,26 @@ int is_bridge(const char *ifname) + return rc; + } + ++int is_bridge_port(const char *ifname) ++{ ++ int rc = 0; ++ char path[256]; ++ DIR *dirp; ++ ++ if (!is_ether(ifname)) { ++ return 0; ++ } ++ /* check if the given ifname is a bridge port in sysfs */ ++ snprintf(path, sizeof(path), "/sys/class/net/%s/brport/", ifname); ++ dirp = opendir(path); ++ if (dirp) { ++ closedir(dirp); ++ rc = 1; ++ } ++ ++ return rc; ++} ++ + int is_vlan(const char *ifname) + { + int fd; +@@ -942,7 +962,7 @@ u16 get_caps(const char *ifname) + if (is_vlan(ifname)) + caps |= SYSCAP_CVLAN; + +- if (is_bridge(ifname)) ++ if (is_bridge_port(ifname)) + caps |= SYSCAP_BRIDGE; + + if (is_router()) +-- +2.5.0 + diff --git a/SOURCES/open-lldp-v1.0.1-27-fix-build-warnings.patch b/SOURCES/open-lldp-v1.0.1-27-fix-build-warnings.patch new file mode 100644 index 0000000..5686fed --- /dev/null +++ b/SOURCES/open-lldp-v1.0.1-27-fix-build-warnings.patch @@ -0,0 +1,94 @@ +From 80fb9db6598440d3af6bdcbcd4f6788f7e660bbe 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/agent.c | 5 +++++ + lldp/agent.h | 6 +++--- + lldp_util.c | 4 ++-- + 4 files changed, 10 insertions(+), 11 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/agent.c b/lldp/agent.c +index 73ab054..333929a 100644 +--- a/lldp/agent.c ++++ b/lldp/agent.c +@@ -36,6 +36,11 @@ + #include "lldp_mand_clif.h" + #include "lldp/agent.h" + ++/* IEEE 802.1AB-2009 - Table 7-1: group MAC addresses used by LLDP */ ++const u8 nearest_bridge[ETH_ALEN] = {0x01,0x80,0xc2,0x00,0x00,0x0e}; ++const u8 nearest_nontpmr_bridge[ETH_ALEN] = {0x01,0x80,0xc2,0x00,0x00,0x03}; ++const u8 nearest_customer_bridge[ETH_ALEN] = {0x01,0x80,0xc2,0x00,0x00,0x00}; ++ + static const u8 * agent_groupmacs[AGENT_MAX] = { + nearest_bridge, + nearest_nontpmr_bridge, +diff --git a/lldp/agent.h b/lldp/agent.h +index a54f72f..90da3e0 100644 +--- a/lldp/agent.h ++++ b/lldp/agent.h +@@ -48,9 +48,9 @@ enum agent_type { + }; + + /* IEEE 802.1AB-2009 - Table 7-1: group MAC addresses used by LLDP */ +-static const u8 nearest_bridge[ETH_ALEN] = {0x01,0x80,0xc2,0x00,0x00,0x0e}; +-static const u8 nearest_nontpmr_bridge[ETH_ALEN] = {0x01,0x80,0xc2,0x00,0x00,0x03}; +-static const u8 nearest_customer_bridge[ETH_ALEN] = {0x01,0x80,0xc2,0x00,0x00,0x00}; ++extern const u8 nearest_bridge[ETH_ALEN]; ++extern const u8 nearest_nontpmr_bridge[ETH_ALEN]; ++extern const u8 nearest_customer_bridge[ETH_ALEN]; + + struct agenttimers { + /* Tx */ +diff --git a/lldp_util.c b/lldp_util.c +index 62f0af8..f12d46b 100644 +--- a/lldp_util.c ++++ b/lldp_util.c +@@ -1197,7 +1197,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; +@@ -1265,7 +1265,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.5.0 + diff --git a/SOURCES/open-lldp-v1.0.1-28-fix-oid-display.patch b/SOURCES/open-lldp-v1.0.1-28-fix-oid-display.patch new file mode 100644 index 0000000..257afa1 --- /dev/null +++ b/SOURCES/open-lldp-v1.0.1-28-fix-oid-display.patch @@ -0,0 +1,51 @@ +From cf3f54d1883e5bc23e4c4006a63e1dde88684013 Mon Sep 17 00:00:00 2001 +From: Aaron Conole +Date: Thu, 21 Jun 2018 13:28:48 -0400 +Subject: [PATCH] basman_clif: print the OID properly + +When invoking the lldp tool to view the management information, the display +for the OID is printed as the actual binary bits, rather than the +OID dotted-notation form. + +This change will display the OID as expected. + +Signed-off-by: Aaron Conole +--- + lldp_basman_clif.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/lldp_basman_clif.c b/lldp_basman_clif.c +index 7dba9d2..abd152d 100644 +--- a/lldp_basman_clif.c ++++ b/lldp_basman_clif.c +@@ -272,8 +272,15 @@ void print_mng_addr(u16 len, char *info) + memset(buf, 0, sizeof(buf)); + if (hexstr2bin(info+offset, (u8 *)&buf, oidlen)) + printf("\tOID: Error parsing OID\n"); +- else +- printf("\tOID: %s\n", buf); ++ else { ++ printf("\tOID: 0."); ++ for (i = 0; i < oidlen; ++i) { ++ printf("%d", buf[i]); ++ if (i != (oidlen - 1)) ++ printf("."); ++ } ++ printf("\n"); ++ } + } else if (oidlen > 128) { + printf("\tOID: Invalid length = %d\n", oidlen); + } +@@ -310,3 +317,10 @@ u32 basman_lookup_tlv_name(char *tlvid_str) + } + return INVALID_TLVID; + } ++ ++/* Local Variables: */ ++/* c-indent-level: 8 */ ++/* c-basic-offset: 8 */ ++/* tab-width: 8 */ ++/* indent-tabs-mode: t */ ++/* End: */ +-- +2.14.3 diff --git a/SOURCES/open-lldp-v1.0.1-29-memleak-on-received-TLVs.patch b/SOURCES/open-lldp-v1.0.1-29-memleak-on-received-TLVs.patch new file mode 100644 index 0000000..0d8d7c2 --- /dev/null +++ b/SOURCES/open-lldp-v1.0.1-29-memleak-on-received-TLVs.patch @@ -0,0 +1,109 @@ +From 9b0389837d7532909a8070d5a08f0175c367c12e Mon Sep 17 00:00:00 2001 +From: Chris Leech +Date: Wed, 23 May 2018 16:37:51 -0700 +Subject: [PATCH] memleak on received TLVs from modules + +Most of the TLV modules that have an rchange handler for received TLVs +seem to get the return values wrong, returning 0 or TLV_OK without +freeing or storing the unpacked TLV to be freed later. That leaks the +allocation, as rxProcessFrame believes the module has claimed ownership. + +In a test setup, it's probably easiest to see by enabling some TLV type +on one side of a connection only. Or, any unexpected TLV that doesn't +get handled will be erroneously leaked by the EVB modules. +--- + lldp_8021qaz.c | 4 ++-- + lldp_evb.c | 8 +++++--- + lldp_evb22.c | 8 +++++--- + 3 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/lldp_8021qaz.c b/lldp_8021qaz.c +index 094676d..198ebcf 100644 +--- a/lldp_8021qaz.c ++++ b/lldp_8021qaz.c +@@ -1924,7 +1924,7 @@ int ieee8021qaz_rchange(struct port *port, struct lldp_agent *agent, + struct ieee8021qaz_unpkd_tlvs *rx; + + if (agent->type != NEAREST_BRIDGE) +- return 0; ++ return SUBTYPE_INVALID; + + qaz_tlvs = ieee8021qaz_data(port->ifname); + if (!qaz_tlvs) +@@ -2005,7 +2005,7 @@ int ieee8021qaz_rchange(struct port *port, struct lldp_agent *agent, + } + } + +- return TLV_OK; ++ return SUBTYPE_INVALID; + } + + static void ieee8021qaz_free_rx(struct ieee8021qaz_unpkd_tlvs *rx) +diff --git a/lldp_evb.c b/lldp_evb.c +index 4b3752e..07f5ffb 100644 +--- a/lldp_evb.c ++++ b/lldp_evb.c +@@ -210,7 +210,8 @@ static int evb_rchange(struct port *port, struct lldp_agent *agent, + u8 oui_subtype[OUI_SUB_SIZE] = LLDP_OUI_SUBTYPE; + + if (agent->type != NEAREST_CUSTOMER_BRIDGE) +- return 0; ++ return SUBTYPE_INVALID; ++ + ed = evb_data(port->ifname, agent->type); + + if (!ed) +@@ -229,7 +230,7 @@ static int evb_rchange(struct port *port, struct lldp_agent *agent, + if (!ed->txmit) { + LLDPAD_WARN("%s:%s agent %d EVB Config disabled\n", + __func__, ed->ifname, agent->type); +- return TLV_OK; ++ return SUBTYPE_INVALID; + } + + LLDPAD_DBG("%s:%s agent %d received tlv:\n", __func__, +@@ -246,7 +247,8 @@ static int evb_rchange(struct port *port, struct lldp_agent *agent, + evb_print_tlvinfo(ed->ifname, &ed->tie); + vdp_update(port->ifname, ed->tie.ccap); + } +- return TLV_OK; ++ ++ return SUBTYPE_INVALID; + } + + /* +diff --git a/lldp_evb22.c b/lldp_evb22.c +index 85c6abc..64b04e0 100644 +--- a/lldp_evb22.c ++++ b/lldp_evb22.c +@@ -305,7 +305,8 @@ static int evb22_rchange(struct port *port, struct lldp_agent *agent, + u8 oui_subtype[OUI_SUB_SIZE] = LLDP_MOD_EVB22_OUI; + + if (agent->type != NEAREST_CUSTOMER_BRIDGE) +- return 0; ++ return SUBTYPE_INVALID; ++ + ed = evb22_data(port->ifname, agent->type); + + if (!ed) +@@ -324,7 +325,7 @@ static int evb22_rchange(struct port *port, struct lldp_agent *agent, + if (!ed->txmit) { + LLDPAD_WARN("%s:%s agent %d EVB Config disabled\n", + __func__, ed->ifname, agent->type); +- return TLV_OK; ++ return SUBTYPE_INVALID; + } + + LLDPAD_DBG("%s:%s agent %d received tlv:\n", __func__, +@@ -341,7 +342,8 @@ static int evb22_rchange(struct port *port, struct lldp_agent *agent, + evb22_print_tlvinfo(ed->ifname, &ed->out); + /* TODO vdp_update(port->ifname, ed->tie.ccap); */ + } +- return TLV_OK; ++ ++ return SUBTYPE_INVALID; + } + + /* +-- +2.19.1 diff --git a/SOURCES/open-lldp-v1.0.1-3-VDP-vdptool-test-cases-Some-test-cases-to-test-the-n.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-30-support-DSCP-selectors.patch b/SOURCES/open-lldp-v1.0.1-30-support-DSCP-selectors.patch new file mode 100644 index 0000000..e7540d9 --- /dev/null +++ b/SOURCES/open-lldp-v1.0.1-30-support-DSCP-selectors.patch @@ -0,0 +1,42 @@ +From c8e438d610bc8af109c19479ee0f568b271d4030 Mon Sep 17 00:00:00 2001 +From: Petr Machata +Date: Mon, 9 Jul 2018 21:43:41 +0300 +Subject: [PATCH] lldpad: Support DSCP selectors in APP TLV's + +The P802.1Qcd/D2.1 standard draft introduces a new APP TLV: DSCP, with +selector value of 5. Don't reject APP TLV's with selector 5, and +sanitize the PID value to not be out of bounds for DSCP. + +Signed-off-by: Petr Machata +--- + lldp_8021qaz_cmds.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lldp_8021qaz_cmds.c b/lldp_8021qaz_cmds.c +index 8cb225e..e017e2a 100644 +--- a/lldp_8021qaz_cmds.c ++++ b/lldp_8021qaz_cmds.c +@@ -1290,7 +1290,7 @@ static int _set_arg_app(struct cmd *cmd, char *args, char *arg_value, + obuf_len - strlen(obuf) - 2); + goto err; + } +- if (sel < 1 || sel > 4) { ++ if (sel < 1 || sel > 5) { + strncat(obuf, ": selector out of range", + obuf_len - strlen(obuf) - 2); + goto err; +@@ -1305,6 +1305,11 @@ static int _set_arg_app(struct cmd *cmd, char *args, char *arg_value, + obuf_len - strlen(obuf) - 2); + goto err; + } ++ if (sel == 5 && pid > 63) { ++ strncat(obuf, ": DSCP > 63", ++ obuf_len - strlen(obuf) - 2); ++ goto err; ++ } + + free(parse); + +-- +2.21.0 + diff --git a/SOURCES/open-lldp-v1.0.1-31-Rebase-to-open-lldp-branch-1.1.0.patch b/SOURCES/open-lldp-v1.0.1-31-Rebase-to-open-lldp-branch-1.1.0.patch new file mode 100644 index 0000000..bf714f1 --- /dev/null +++ b/SOURCES/open-lldp-v1.0.1-31-Rebase-to-open-lldp-branch-1.1.0.patch @@ -0,0 +1,3849 @@ +From: Aaron Conole +Date: Wed, 09 Jun 2021 15:12:06 +0000 +Subject: [PATCH] lldpad: Rebase to openlldp branch 1.1.0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Open-LLDP released 1.1.0 which includes a number of important fixes +relevant to customers. The biggest changes are documented in the +changelog. + +This patch updates the lldpad package to 1.1.0 branch as of +4c75fa274230 "tx: rename variable" + +Signed-off-by: Aaron Conole +--- + ChangeLog | 15 +++ + Makefile.am | 26 +++++ + README | 4 + config.c | 45 ++++++--- + configure.ac | 39 ++++++++ + ctrl_iface.c | 4 + dcb_protocol.c | 19 +--- + dcb_rule_chk.c | 2 + dcbtool.c | 2 + dcbtool_cmds.c | 24 ----- + docs/liblldp_clif-vdp22.3 | 2 + docs/lldptool.8 | 4 + event_iface.c | 22 +++- + include/config.h | 3 + include/linux/if_link.h | 100 ++++++++++++++++++++- + include/lldp.h | 13 ++ + include/lldp_basman_clif.h | 6 - + include/lldp_mod.h | 2 + include/lldp_tlv.h | 16 ++- + include/lldp_util.h | 4 + include/lldptool.h | 3 + include/qbg_ecp22.h | 4 + include/qbg_vdpnl.h | 1 + lldp/agent.c | 4 + lldp/l2_packet.h | 7 - + lldp/l2_packet_linux.c | 6 - + lldp/ports.c | 2 + lldp/rx.c | 41 ++++---- + lldp/states.h | 2 + lldp/tx.c | 31 ++++-- + lldp_8021qaz.c | 52 ++++++----- + lldp_8021qaz_clif.c | 80 ++++++++++++----- + lldp_8021qaz_cmds.c | 2 + lldp_8023.c | 14 +-- + lldp_basman.c | 10 -- + lldp_basman_cmds.c | 90 +++++++++++++++++++ + lldp_dcbx.c | 111 +++++++++--------------- + lldp_dcbx_cfg.c | 32 ++++-- + lldp_dcbx_cmds.c | 13 ++ + lldp_dcbx_nl.c | 20 +--- + lldp_evb.c | 8 - + lldp_evb22.c | 8 - + lldp_evb22_cmds.c | 2 + lldp_evb_cmds.c | 2 + lldp_mand.c | 41 +++++--- + lldp_mand_cmds.c | 17 ++- + lldp_med.c | 8 - + lldp_med_cmds.c | 1 + lldp_rtnl.c | 3 + lldp_tlv.c | 12 -- + lldp_util.c | 206 +++++++++++++++++++++++++++++---------------- + lldpad.c | 21 +++- + lldpad.service | 2 + lldpad.socket | 3 + lldpad.spec.in | 36 +++++-- + lldptool.c | 38 ++------ + lldptool_cmds.c | 3 + log.c | 1 + parse_cli.l | 3 + qbg/ecp.c | 8 - + qbg/ecp22.c | 21 +++- + qbg/vdp.c | 16 +-- + qbg/vdp22.c | 12 +- + qbg/vdp22_cmds.c | 7 - + qbg/vdp22sm.c | 4 + qbg/vdp_cmds.c | 2 + qbg/vdpnl.c | 8 - + qbg_utils.c | 3 + tlv_dcbx.c | 33 ++++--- + vdptool.c | 23 ++--- + vdptool_cisco_oui.c | 2 + weak_readline.c | 16 ++- + 72 files changed, 935 insertions(+), 512 deletions(-) + +diff -upr a/ChangeLog b/ChangeLog +--- a/ChangeLog 2015-01-20 13:42:56.000000000 -0500 ++++ b/ChangeLog 2021-06-09 11:00:02.478019444 -0400 +@@ -1,3 +1,18 @@ ++Changes from 1.1.0 to ++Changes from 1.0.1 to 1.1 ++- VDP: introduce vdptool ++- VDP: support retrieving vsi parameter ++- VDP: TLV support ++- VDP: Support OUI infrastructure ++- Switch from SysV to posix shared memory ++- DCBX: ignore PG configurations ++- DCBX: Allow for read-only LLDP configuration ++- Support multicast MAC ++- autoconf: Suport systemd or sysv for init system ++- 802.1qaz: print prio map ++- lldptool: Allow to modify optional TLV content ++- CVE-2018-10932: Don't print raw bytes from mngAddr ++- Misc. bug fixes + Changes from 0.9.46 to 1.0.1 + Mostly fixes and man page updates + Added more testing infrastructure mostly for EVB +diff -upr a/config.c b/config.c +--- a/config.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/config.c 2020-10-23 14:12:58.973289274 -0400 +@@ -56,6 +56,21 @@ + config_t lldpad_cfg; + + /* ++ * config_ifkey - Generates a config key ++ * ++ * Given an interface name this functions generates ++ * a key (based on interface's index) suitable ++ * to pass to libconfig. ++ * ++ */ ++void config_ifkey(const char *name, char *ifkey) { ++ int index = if_nametoindex(name); ++ ++ if(index) ++ sprintf(ifkey, "if%d", index); ++} ++ ++/* + * init_cfg - initialze the global lldpad_cfg via config_init + * + * Returns true (1) for succes and false (0) for failed +@@ -170,7 +185,7 @@ void scan_port(UNUSED void *eloop_data, + LIST_FOREACH(agent, &port->agent_head, entry) { + LLDPAD_DBG("%s: calling ifdown for agent %p.\n", + __func__, agent); +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + ops = np->ops; + if (ops->lldp_mod_ifdown) + ops->lldp_mod_ifdown(ifname, agent); +@@ -219,7 +234,7 @@ int check_cfg_file(void) + } + } else { + retval = errno; +- LLDPAD_ERR("%s is not readable and writeable", ++ LLDPAD_ERR("%s is not readable and writeable\n", + cfg_file_name); + } + } +@@ -295,7 +310,7 @@ int get_int_config(config_setting_t *s, + } + + if (!rval) +- LLDPAD_ERR("invalid value for %s", attr); ++ LLDPAD_ERR("invalid value for %s\n", attr); + + return rval; + } +@@ -339,7 +354,7 @@ int get_array_config(config_setting_t *s + } + + if (!rval) +- LLDPAD_ERR("invalid setting for %s", attr); ++ LLDPAD_ERR("invalid setting for %s\n", attr); + + return rval; + } +@@ -379,7 +394,7 @@ void init_ports(void) + LIST_FOREACH(agent, &port->agent_head, entry) { + LLDPAD_DBG("%s: calling ifup for agent %p.\n", + __func__, agent); +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (np->ops->lldp_mod_ifup) + np->ops->lldp_mod_ifup(p->if_name, agent); + } +@@ -451,14 +466,15 @@ static int lookup_config_value(char *pat + int get_config_setting(const char *ifname, int agenttype, char *path, + union cfg_get v, int type) + { +- char p[1024]; ++ char p[1024], ifkey[IFNAMSIZ]; + int rval = CONFIG_FALSE; + const char *section = agent_type2section(agenttype); + + /* look for setting in section->ifname area first */ + if (ifname) { ++ config_ifkey(ifname, ifkey); + snprintf(p, sizeof(p), "%s.%s.%s", +- section, ifname, path); ++ section, ifkey, path); + rval = lookup_config_value(p, v, type); + } + +@@ -475,15 +491,16 @@ int get_config_setting(const char *ifnam + int remove_config_setting(const char *ifname, int agenttype, char *parent, + char *name) + { +- char p[1024]; ++ char p[1024], ifkey[IFNAMSIZ]; + int rval = CONFIG_FALSE; + config_setting_t *setting = NULL; + const char *section = agent_type2section(agenttype); + + /* look for setting in section->ifname area first */ +- if (ifname) { ++ if (ifname) { ++ config_ifkey(ifname, ifkey); + snprintf(p, sizeof(p), "%s.%s.%s", +- section, ifname, parent); ++ section, ifkey, parent); + setting = config_lookup(&lldpad_cfg, p); + } + +@@ -570,15 +587,17 @@ int set_config_setting(const char *ifnam + union cfg_set v, int type) + { + config_setting_t *setting = NULL; +- char p[1024]; ++ char p[1024], ifkey[IFNAMSIZ]; + int rval = cmd_success; + const char *section = agent_type2section(agenttype); + + LLDPAD_DBG("%s(%i): \n", __func__, __LINE__); + +- if (strlen(ifname)) ++ if (strlen(ifname)){ ++ config_ifkey(ifname, ifkey); + snprintf(p, sizeof(p), "%s.%s.%s", +- section, ifname, path); ++ section, ifkey, path); ++ } + else + snprintf(p, sizeof(p), "%s.%s.%s", + section, LLDP_COMMON, path); +diff -upr a/configure.ac b/configure.ac +--- a/configure.ac 2015-01-20 13:42:56.000000000 -0500 ++++ b/configure.ac 2021-06-09 11:00:02.479019457 -0400 +@@ -1,4 +1,4 @@ +-AC_INIT([lldpad], [1.0.1], [lldp-devel@open-lldp.org]) ++AC_INIT([lldpad], [1.1.0], [lldp-devel@open-lldp.org]) + AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) + + m4_pattern_allow([AM_PROG_AR]) +@@ -25,6 +25,43 @@ then + AC_MSG_ERROR([no suitable flex found. Please install the 'flex' package.]) + fi + ++dnl Begin determine the systemd use and location ++PKG_CHECK_MODULES([SYSTEMD], [systemd], use_systemd=yes, use_systemd=no) ++ ++dnl Configure developer type flags ++OPENLLDP_CHECK_WARNINGS ++OPENLLDP_CHECK_ERROR ++ ++dnl Set sysvinit values, if system has systemd it will be rewritten ++AC_SUBST(SPEC_BUILD_REQUIRES_POST, "chkconfig") ++AC_SUBST(SPEC_BUILD_REQUIRES_PREUN, "chkconfig initscripts") ++AC_SUBST(SPEC_BUILD_REQUIRES_POSTUN, "initscripts") ++specfile_install="%{_sysconfdir}/init.d/lldpad" ++specfile_install_socket="" ++ ++if test "x$use_systemd" == xyes; then ++ dir="" ++ AC_ARG_WITH([systemdsystemunitdir], ++ AS_HELP_STRING([--with-systemdsystem unitdir=DIR], ++ [Directory for systemd service files default from pkg-config variable systemdsystemunitdir]), ++ [dir=${withval}], ++ [dir="$($PKG_CONFIG --variable=systemdsystemunitdir systemd)"]) ++ ++ systemdsystemunitdir=${dir} ++ AC_SUBST(SYSTEMD_SYSTEM_UNIT_DIR, [$systemdsystemunitdir]) ++ specfile_install="$systemdsystemunitdir/lldpad.service" ++ specfile_install_socket="$systemdsystemunitdir/lldpad.socket" ++ ++ AC_SUBST(SPEC_BUILD_REQUIRES_POST, "systemd") ++ AC_SUBST(SPEC_BUILD_REQUIRES_PREUN, "systemd") ++ AC_SUBST(SPEC_BUILD_REQUIRES_POSTUN, "systemd") ++fi ++ ++AM_CONDITIONAL(SYSTEMD_SYSTEM, test "x$use_systemd" == xyes) ++AC_SUBST(SPEC_FILE_LLDPAD_SERVICE, $specfile_install) ++AC_SUBST(SPEC_FILE_LLDPAD_SOCKET, $specfile_install_socket) ++dnl End systemd stuff ++ + PKG_CHECK_MODULES([LIBCONFIG], [libconfig >= 1.3.2]) + PKG_CHECK_MODULES([LIBNL], [libnl-3.0 >= 3.2]) + +diff -upr a/ctrl_iface.c b/ctrl_iface.c +--- a/ctrl_iface.c 2021-06-09 10:58:59.208200552 -0400 ++++ b/ctrl_iface.c 2020-11-03 09:08:48.057229002 -0500 +@@ -53,8 +53,6 @@ + #include "lldp_util.h" + #include "messages.h" + +-extern struct lldp_head lldp_head; +- + struct ctrl_dst { + struct ctrl_dst *next; + struct sockaddr_un addr; +@@ -116,7 +114,7 @@ int clif_iface_module(struct clif_data * + return cmd_invalid; + } + +- mod = find_module_by_id(&lldp_head, module_id); ++ mod = find_module_by_id(&lldp_mod_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); +diff -upr a/dcb_protocol.c b/dcb_protocol.c +--- a/dcb_protocol.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/dcb_protocol.c 2020-09-23 08:50:52.647813847 -0400 +@@ -75,7 +75,7 @@ void pg_insert(struct pghead *head, char + entry = (struct pg_store1 *)malloc(sizeof(struct pg_store1)); + if (!entry) + return; +- strncpy(entry->ifname, ifname, sizeof(entry->ifname)); ++ STRNCPY_TERMINATED(entry->ifname, ifname, sizeof(entry->ifname)); + entry->second = store; + LIST_INSERT_HEAD(head, entry, entries); + } +@@ -1100,7 +1100,7 @@ int dcbx_remove_adapter(char *device_nam + assert(device_name); + not_default = memcmp(DEF_CFG_STORE, device_name, + strlen(DEF_CFG_STORE)); +- strncpy (devName, device_name, MAX_DEVICE_NAME_LEN); ++ STRNCPY_TERMINATED (devName, device_name, MAX_DEVICE_NAME_LEN); + + if (not_default) + handle_opermode_true(device_name); +@@ -2257,13 +2257,8 @@ cmd_status get_bwg_descrpt(char *device_ + + if ((it != NULL) && + (bwgid < it->second->max_pgid_desc)) { +- size = (int)strlen(it->second->pgid_desc[bwgid]) + +- sizeof(char); /* Localization OK */ +- *name = (char*)malloc(size); +- if (*name != NULL) { +- strncpy(*name, it->second->pgid_desc[bwgid], +- size); /* Localization OK */ +- } else { ++ *name = strdup(it->second->pgid_desc[bwgid]); ++ if (*name == NULL) { + goto Error; + } + } else { +@@ -2272,11 +2267,9 @@ cmd_status get_bwg_descrpt(char *device_ + size = (int)strlen( + attribs.descript.pgid_desc[bwgid]) + + sizeof(char); +- *name = (char*)malloc(size); ++ *name = (char*)calloc(size, sizeof(char)); + if (*name != NULL) { +- strncpy(*name, +- attribs.descript.pgid_desc[bwgid], +- size); /* Localization OK */ ++ memcpy(*name, attribs.descript.pgid_desc[bwgid], size - 1); /* Localization OK */ + } else { + goto Error; + } +diff -upr a/dcb_rule_chk.c b/dcb_rule_chk.c +--- a/dcb_rule_chk.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/dcb_rule_chk.c 2020-09-23 08:50:52.647813847 -0400 +@@ -206,6 +206,8 @@ static int dcb_fixup_pg(struct pg_attrib + strict = 0; + if (be == cbe) + be = 0; ++ if (pgid < 0) ++ continue; + } + + if (pg_done[i] == false) { +diff -upr a/dcbtool.c b/dcbtool.c +--- a/dcbtool.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/dcbtool.c 2020-09-23 08:50:52.647813847 -0400 +@@ -47,6 +47,7 @@ + #define UNUSED __attribute__((__unused__)) + + static int show_raw; ++extern void close_history(void); + + static const char *cli_version = + "dcbtool v" DCBTOOL_VERSION "\n" +@@ -460,6 +461,7 @@ static void cli_interactive(int raw) + request(clif_conn, argc, argv, raw); + free(cmd); + } while (!cli_quit); ++ close_history(); + } + + static void cli_terminate(UNUSED int sig) +diff -upr a/dcbtool_cmds.c b/dcbtool_cmds.c +--- a/dcbtool_cmds.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/dcbtool_cmds.c 2020-09-23 08:50:52.647813847 -0400 +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include "clif.h" + #include "dcbtool.h" + #include "lldp_dcbx_cmds.h" +@@ -38,7 +39,6 @@ + + static char *print_status(cmd_status status); + static char *get_pgdesc_args(int cmd); +-static int hex2int(char *b); + static void free_cmd_args(char *args); + static char *get_dcb_args(void); + static char *get_dcbx_args(void); +@@ -93,28 +93,6 @@ static char *print_status(cmd_status sta + return str; + } + +-/* assumes input is pointer to two hex digits */ +-/* returns -1 on error */ +-static int hex2int(char *b) +-{ +- int i; +- int n=0; +- int m; +- +- for (i=0,m=1; i<2; i++,m--) { +- if (isxdigit(*(b+i))) { +- if (*(b+i) <= '9') +- n |= (*(b+i) & 0x0f) << (4*m); +- else +- n |= ((*(b+i) & 0x0f) + 9) << (4*m); +- } +- else { +- return -1; +- } +- } +- return n; +-} +- + static char *get_dcb_args(void) + { + char buf[8]; +diff -upr a/docs/liblldp_clif-vdp22.3 b/docs/liblldp_clif-vdp22.3 +--- a/docs/liblldp_clif-vdp22.3 2015-01-20 13:42:56.000000000 -0500 ++++ b/docs/liblldp_clif-vdp22.3 2020-11-03 09:08:48.058229019 -0500 +@@ -1,6 +1,6 @@ + .TH liblldp_clif 3 "February 2014" "open-lldp" "Linux" + .SH NAME +-clif_vsi,clif_vsievt,clif_vsiwait \- Manipulate VDP IEEE 802.1 Ratified Standard Assocications ++clif_vsi,clif_vsievt,clif_vsiwait \- Manipulate VDP IEEE 802.1 Ratified Standard Associations + .SH SYNOPSIS + #include "include/clif.h" + .sp 1 +diff -upr a/docs/lldptool.8 b/docs/lldptool.8 +--- a/docs/lldptool.8 2015-01-20 13:42:56.000000000 -0500 ++++ b/docs/lldptool.8 2020-11-03 09:08:48.058229019 -0500 +@@ -160,9 +160,9 @@ Query the LLDP adminStatus for interface + + .TP + Query the LLDP statistics for interface \fIeth3\fR +-.B lldptool -S -i eth3 adminStatus ++.B lldptool -S -i eth3 + .br +-.B lldptool stats -i eth3 adminStatus ++.B lldptool stats -i eth3 + + .TP + Query the local TLVs which are being transmitted for a given interface: +diff -upr a/event_iface.c b/event_iface.c +--- a/event_iface.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/event_iface.c 2021-01-06 11:05:30.808649405 -0500 +@@ -77,7 +77,7 @@ static void event_if_decode_rta(int type + LLDPAD_DBG(" IFLA_BROADCAST\n"); + break; + case IFLA_IFNAME: +- strncpy(d, (char *)RTA_DATA(rta), IFNAMSIZ); ++ STRNCPY_TERMINATED(d, (char *)RTA_DATA(rta), IFNAMSIZ); + LLDPAD_DBG(" IFLA_IFNAME\n"); + LLDPAD_DBG(" device name is %s\n", d); + break; +@@ -205,6 +205,9 @@ int oper_add_device(char *device_name) + port = newport; + } else if (is_bond(device_name) || !port->portEnabled) + reinit_port(device_name); ++ else if (port->portEnabled) { ++ return 0; ++ } + + lldp_add_agent(device_name, NEAREST_BRIDGE); + lldp_add_agent(device_name, NEAREST_NONTPMR_BRIDGE); +@@ -213,7 +216,7 @@ int oper_add_device(char *device_name) + LIST_FOREACH(agent, &port->agent_head, entry) { + LLDPAD_DBG("%s: calling ifup for agent %p.\n", + __func__, agent); +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (np->ops->lldp_mod_ifup) + np->ops->lldp_mod_ifup(device_name, agent); + } +@@ -280,7 +283,7 @@ static void event_if_decode_nlmsg(int ro + LIST_FOREACH(agent, &port->agent_head, entry) { + LLDPAD_DBG("%s: calling ifdown for agent %p.\n", + __func__, agent); +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + ops = np->ops; + if (ops->lldp_mod_ifdown) + ops->lldp_mod_ifdown(device_name, +@@ -415,7 +418,8 @@ event_iface_receive(int sock, UNUSED voi + int event_iface_init() + { + int fd; +- int rcv_size = MAX_PAYLOAD; ++ int rcv_size = 0; ++ socklen_t rcv_len = sizeof(int); + struct sockaddr_nl snl; + + fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); +@@ -423,10 +427,18 @@ int event_iface_init() + if (fd < 0) + return fd; + +- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_size, sizeof(int)) < 0) { ++ /* is receive buffer size too small? */ ++ if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_size, &rcv_len) < 0) { + close(fd); + return -EIO; + } ++ if (rcv_size < MIN_RCVBUF_SIZE) { ++ rcv_size = MIN_RCVBUF_SIZE >> 1; /* we get back 2x what we set */ ++ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcv_size, rcv_len) < 0) { ++ close(fd); ++ return -EIO; ++ } ++ } + + memset((void *)&snl, 0, sizeof(struct sockaddr_nl)); + snl.nl_family = AF_NETLINK; +diff -upr a/include/config.h b/include/config.h +--- a/include/config.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/include/config.h 2020-09-23 08:50:52.647813847 -0400 +@@ -111,4 +111,7 @@ void destroy_cfg(void); + int check_cfg_file(void); + int check_for_old_file_format(void); + void init_ports(void); ++ ++void config_ifkey(const char *name, char *ifkey); ++ + #endif /* _CONFIG_H_ */ +diff -upr a/include/linux/if_link.h b/include/linux/if_link.h +--- a/include/linux/if_link.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/include/linux/if_link.h 2020-09-23 08:50:52.648813865 -0400 +@@ -116,15 +116,34 @@ enum { + IFLA_STATS64, + IFLA_VF_PORTS, + IFLA_PORT_SELF, +- IFLA_AF_SPEC, +- IFLA_GROUP, /* Group the device belongs to */ +- IFLA_NET_NS_FD, +- IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ +- IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */ ++ IFLA_AF_SPEC, ++ IFLA_GROUP, /* Group the device belongs to */ ++ IFLA_NET_NS_FD, ++ IFLA_EXT_MASK, /* Extended info mask, VFs, etc */ ++ IFLA_PROMISCUITY, /* Promiscuity count: > 0 means acts PROMISC */ + #define IFLA_PROMISCUITY IFLA_PROMISCUITY +- IFLA_NUM_TX_QUEUES, +- IFLA_NUM_RX_QUEUES, +- IFLA_CARRIER, ++ IFLA_NUM_TX_QUEUES, ++ IFLA_NUM_RX_QUEUES, ++ IFLA_CARRIER, ++ IFLA_PHYS_PORT_ID, ++ IFLA_CARRIER_CHANGES, ++ IFLA_PHYS_SWITCH_ID, ++ IFLA_LINK_NETNSID, ++ IFLA_PHYS_PORT_NAME, ++ IFLA_PROTO_DOWN, ++ IFLA_GSO_MAX_SEGS, ++ IFLA_GSO_MAX_SIZE, ++ IFLA_PAD, ++ IFLA_XDP, ++ IFLA_EVENT, ++ IFLA_NEW_NETNSID, ++ IFLA_IF_NETNSID, ++ IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */ ++ IFLA_CARRIER_UP_COUNT, ++ IFLA_CARRIER_DOWN_COUNT, ++ IFLA_NEW_IFINDEX, ++ IFLA_MIN_MTU, ++ IFLA_MAX_MTU, + __IFLA_MAX + }; + +@@ -192,6 +211,8 @@ enum { + IFLA_INFO_KIND, + IFLA_INFO_DATA, + IFLA_INFO_XSTATS, ++ IFLA_INFO_SLAVE_KIND, ++ IFLA_INFO_SLAVE_DATA, + __IFLA_INFO_MAX, + }; + +@@ -243,6 +264,69 @@ enum macvlan_mode { + MACVLAN_MODE_BRIDGE = 4, /* talk to bridge ports directly */ + }; + ++/* Bonding section */ ++ ++enum { ++ IFLA_BOND_UNSPEC, ++ IFLA_BOND_MODE, ++ IFLA_BOND_ACTIVE_SLAVE, ++ IFLA_BOND_MIIMON, ++ IFLA_BOND_UPDELAY, ++ IFLA_BOND_DOWNDELAY, ++ IFLA_BOND_USE_CARRIER, ++ IFLA_BOND_ARP_INTERVAL, ++ IFLA_BOND_ARP_IP_TARGET, ++ IFLA_BOND_ARP_VALIDATE, ++ IFLA_BOND_ARP_ALL_TARGETS, ++ IFLA_BOND_PRIMARY, ++ IFLA_BOND_PRIMARY_RESELECT, ++ IFLA_BOND_FAIL_OVER_MAC, ++ IFLA_BOND_XMIT_HASH_POLICY, ++ IFLA_BOND_RESEND_IGMP, ++ IFLA_BOND_NUM_PEER_NOTIF, ++ IFLA_BOND_ALL_SLAVES_ACTIVE, ++ IFLA_BOND_MIN_LINKS, ++ IFLA_BOND_LP_INTERVAL, ++ IFLA_BOND_PACKETS_PER_SLAVE, ++ IFLA_BOND_AD_LACP_RATE, ++ IFLA_BOND_AD_SELECT, ++ IFLA_BOND_AD_INFO, ++ IFLA_BOND_AD_ACTOR_SYS_PRIO, ++ IFLA_BOND_AD_USER_PORT_KEY, ++ IFLA_BOND_AD_ACTOR_SYSTEM, ++ IFLA_BOND_TLB_DYNAMIC_LB, ++ __IFLA_BOND_MAX, ++}; ++ ++#define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1) ++ ++enum { ++ IFLA_BOND_AD_INFO_UNSPEC, ++ IFLA_BOND_AD_INFO_AGGREGATOR, ++ IFLA_BOND_AD_INFO_NUM_PORTS, ++ IFLA_BOND_AD_INFO_ACTOR_KEY, ++ IFLA_BOND_AD_INFO_PARTNER_KEY, ++ IFLA_BOND_AD_INFO_PARTNER_MAC, ++ __IFLA_BOND_AD_INFO_MAX, ++}; ++ ++#define IFLA_BOND_AD_INFO_MAX (__IFLA_BOND_AD_INFO_MAX - 1) ++ ++enum { ++ IFLA_BOND_SLAVE_UNSPEC, ++ IFLA_BOND_SLAVE_STATE, ++ IFLA_BOND_SLAVE_MII_STATUS, ++ IFLA_BOND_SLAVE_LINK_FAILURE_COUNT, ++ IFLA_BOND_SLAVE_PERM_HWADDR, ++ IFLA_BOND_SLAVE_QUEUE_ID, ++ IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, ++ IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, ++ IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, ++ __IFLA_BOND_SLAVE_MAX, ++}; ++ ++#define IFLA_BOND_SLAVE_MAX (__IFLA_BOND_SLAVE_MAX - 1) ++ + /* SR-IOV virtual function management section */ + + enum { +diff -upr a/include/lldp_basman_clif.h b/include/lldp_basman_clif.h +--- a/include/lldp_basman_clif.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/include/lldp_basman_clif.h 2020-09-23 08:50:52.648813865 -0400 +@@ -31,7 +31,7 @@ struct lldp_module *basman_cli_register( + void basman_cli_unregister(struct lldp_module *); + int basman_print_tlv(u32, u16, char *); + +-#define ARG_IPV4_ADDR "ipv4" +-#define ARG_IPV6_ADDR "ipv6" +- ++#define ARG_IPV4_ADDR "ipv4" ++#define ARG_IPV6_ADDR "ipv6" ++#define ARG_TLVINFO "info" + #endif +diff -upr a/include/lldp.h b/include/lldp.h +--- a/include/lldp.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/include/lldp.h 2020-09-23 08:50:52.648813865 -0400 +@@ -51,6 +51,13 @@ typedef __u64 u64; + __x > __y ? __x : __y; \ + }) + ++/* Use strncpy with N-1 and ensure the string is terminated. */ ++#define STRNCPY_TERMINATED(DEST, SRC, N) \ ++ do { \ ++ strncpy (DEST, SRC, N - 1); \ ++ DEST[N - 1] = '\0'; \ ++ } while (false) ++ + /* + * Organizationally Unique Identifier (OUI) + * http://standards.ieee.org/regauth/oui/oui.txt +@@ -248,5 +255,11 @@ enum { + #define LLDP_EVB_DEFAULT_RTE 15 + #define LLDP_EVB_DEFAULT_MAX_RTE 31 + ++#ifndef _MSC_VER ++#define STRUCT_PACKED(STRUCT) STRUCT __attribute__((__packed__)) ++#else ++#define STRUCT_PACKED(STRUCT) __pragma(pack(push, 1)) STRUCT __pragma(pack(pop)) ++#endif ++ + void somethingChangedLocal(const char *ifname, int type); + #endif /* _LLDP_H */ +diff -upr a/include/lldp_mod.h b/include/lldp_mod.h +--- a/include/lldp_mod.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/include/lldp_mod.h 2020-10-23 14:12:58.974289292 -0400 +@@ -96,7 +96,7 @@ struct lldp_module { + }; + + LIST_HEAD(lldp_head, lldp_module); +-struct lldp_head lldp_head; ++extern struct lldp_head lldp_mod_head; + + static inline struct lldp_module *find_module_by_id(struct lldp_head *head, int id) + { +diff -upr a/include/lldp_tlv.h b/include/lldp_tlv.h +--- a/include/lldp_tlv.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/include/lldp_tlv.h 2020-09-23 08:50:52.648813865 -0400 +@@ -104,8 +104,8 @@ struct packed_tlv *pack_tlv(struct unpac + struct unpacked_tlv *unpack_tlv(struct packed_tlv *tlv); + int pack_tlv_after(struct unpacked_tlv *, struct packed_tlv *, int); + +-struct unpacked_tlv *free_unpkd_tlv(struct unpacked_tlv *tlv); +-struct packed_tlv *free_pkd_tlv(struct packed_tlv *tlv); ++void free_unpkd_tlv(struct unpacked_tlv *tlv); ++void free_pkd_tlv(struct packed_tlv *tlv); + struct unpacked_tlv *create_tlv(void); + struct packed_tlv *create_ptlv(void); + struct unpacked_tlv *bld_end_tlv(void); +@@ -115,14 +115,18 @@ int tlv_ok(struct unpacked_tlv *tlv); + + #define FREE_UNPKD_TLV(d, f) \ + { \ +- if ((d)->f) \ +- (d)->f = free_unpkd_tlv((d)->f); \ ++ if ((d)->f) { \ ++ free_unpkd_tlv((d)->f); \ ++ (d)->f = NULL; \ ++ } \ + } + + #define FREE_PKD_TLV(d, f) \ + { \ +- if ((d)->f) \ +- (d)->f = free_pkd_tlv((d)->f); \ ++ if ((d)->f) { \ ++ free_pkd_tlv((d)->f); \ ++ (d)->f = NULL; \ ++ } \ + } + + #define PACK_TLV_AFTER(t, p, l, g) \ +diff -upr a/include/lldptool.h b/include/lldptool.h +--- a/include/lldptool.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/include/lldptool.h 2020-09-23 08:50:52.648813865 -0400 +@@ -29,9 +29,8 @@ + + #include "clif.h" + +-struct lldp_head lldp_cli_head; ++extern struct lldp_head lldp_cli_head; + +-int hex2int(char *b); + int clif_command(struct clif *clif, char *cmd, int raw); + void print_raw_message(char *msg, int print); + int parse_print_message(char *msg, int print); +diff -upr a/include/lldp_util.h b/include/lldp_util.h +--- a/include/lldp_util.h 2021-06-09 10:58:59.214200629 -0400 ++++ b/include/lldp_util.h 2021-04-05 12:02:17.318590504 -0400 +@@ -119,6 +119,7 @@ + + int hexstr2bin(const char *hex, u8 *buf, size_t len); + int bin2hexstr(const u8 *hex, size_t hexlen, char *buf, size_t buflen); ++int hex2int(char *b); + + int is_valid_lldp_device(const char *ifname); + int is_active(const char *ifname); +@@ -149,8 +150,7 @@ int get_mautype(const char *); + int get_ifpflags(const char *); + int get_iftype(const char *); + int get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr); +-int get_mac(const char *ifname, u8 mac[]); +-int get_macstr(const char *ifname, char *addr, size_t size); ++int get_mac(const char *ifname, u8 mac[], bool perm_mac); + int get_saddr(const char *ifname, struct sockaddr_in *saddr); + int get_ipaddr(const char *ifname, struct in_addr *); + int get_ipaddrstr(const char *ifname, char *ipaddr, size_t size); +diff -upr a/include/qbg_ecp22.h b/include/qbg_ecp22.h +--- a/include/qbg_ecp22.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/include/qbg_ecp22.h 2020-09-23 08:50:52.649813883 -0400 +@@ -49,10 +49,10 @@ enum { /* ECP Transmit states */ + ECP22_TX_ERROR + }; + +-enum { ++enum ecp22_mode { + ECP22_REQUEST = 0, + ECP22_ACK +-} ecp22_mode; ++}; + + struct ecp22_hdr { /* ECP22 header */ + u16 ver_op_sub; /* ECP22 version, operation, subtype */ +diff -upr a/include/qbg_vdpnl.h b/include/qbg_vdpnl.h +--- a/include/qbg_vdpnl.h 2021-06-09 10:58:59.201200461 -0400 ++++ b/include/qbg_vdpnl.h 2021-01-06 11:05:30.810649436 -0500 +@@ -33,6 +33,7 @@ + #include + + #define MAX_PAYLOAD 4096 /* Maximum Payload Size */ ++#define MIN_RCVBUF_SIZE (MAX_PAYLOAD << 5) /* SO_RCVBUF min */ + + enum { + vdpnl_nlf1 = 1, /* Netlink message format 1 (draft 0.2) */ +diff -upr a/lldp/agent.c b/lldp/agent.c +--- a/lldp/agent.c 2021-06-09 10:58:59.215200642 -0400 ++++ b/lldp/agent.c 2021-01-06 11:05:30.811649451 -0500 +@@ -163,7 +163,7 @@ static void timer(UNUSED void *eloop_dat + run_rx_sm(port, agent); + update_rx_timers(agent); + +- LIST_FOREACH(n, &lldp_head, lldp) { ++ LIST_FOREACH(n, &lldp_mod_head, lldp) { + if (n->ops && n->ops->timer) + n->ops->timer(port, agent); + } +@@ -200,7 +200,7 @@ void clean_lldp_agents(void) + LLDPAD_DBG("Send shutdown frame on port %s\n", + port->ifname); + LIST_FOREACH(agent, &port->agent_head, entry) { +- process_tx_shutdown_frame(port, agent); ++ process_tx_shutdown_frame(port, agent, false); + } + } else { + LLDPAD_DBG("No shutdown frame is sent on port %s\n", +diff -upr a/lldp/l2_packet.h b/lldp/l2_packet.h +--- a/lldp/l2_packet.h 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp/l2_packet.h 2020-09-23 08:50:52.649813883 -0400 +@@ -37,7 +37,9 @@ + #define IP2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] + #define IPSTR "%02x:%02x:%02x:%02x:%02x:%02x" + ++#ifndef ETH_P_LLDP + #define ETH_P_LLDP 0x88cc ++#endif + + #define ETH_P_ECP 0x88b7 /* Draft 0.2 */ + #define ETH_P_ECP22 0x8940 /* Ratified standard */ +@@ -56,12 +58,11 @@ + */ + struct l2_packet_data; + +- +-struct l2_ethhdr { ++STRUCT_PACKED(struct l2_ethhdr { + u8 h_dest[ETH_ALEN]; + u8 h_source[ETH_ALEN]; + u16 h_proto; +-} STRUCT_PACKED; ++}); + + /** + * l2_packet_init - Initialize l2_packet interface +diff -upr a/lldp/l2_packet_linux.c b/lldp/l2_packet_linux.c +--- a/lldp/l2_packet_linux.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp/l2_packet_linux.c 2020-09-23 08:50:52.649813883 -0400 +@@ -60,7 +60,7 @@ struct l2_packet_data { + + int l2_packet_get_own_src_addr(struct l2_packet_data *l2, u8 *addr) + { +- if (is_san_mac(l2->san_mac_addr)) ++ if (is_valid_mac(l2->san_mac_addr)) + memcpy(addr, l2->san_mac_addr, ETH_ALEN); + else { + /* get an appropriate src MAC to use if the port is +@@ -169,7 +169,7 @@ struct l2_packet_data * l2_packet_init( + if (l2 == NULL) + return NULL; + memset(l2, 0, sizeof(*l2)); +- strncpy(l2->ifname, ifname, sizeof(l2->ifname)); ++ STRNCPY_TERMINATED(l2->ifname, ifname, sizeof(l2->ifname)); + l2->rx_callback = rx_callback; + l2->rx_callback_ctx = rx_callback_ctx; + l2->l2_hdr = l2_hdr; +@@ -183,7 +183,7 @@ struct l2_packet_data * l2_packet_init( + return NULL; + } + +- strncpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); + if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) { + perror("ioctl[SIOCGIFINDEX]"); + close(l2->fd); +diff -upr a/lldp/ports.c b/lldp/ports.c +--- a/lldp/ports.c 2021-06-09 10:58:59.211200590 -0400 ++++ b/lldp/ports.c 2020-12-07 13:15:10.579203256 -0500 +@@ -264,7 +264,7 @@ struct port *add_port(int ifindex, const + memset(newport, 0, sizeof(*newport)); + newport->ifindex = ifindex; + newport->next = NULL; +- strncpy(newport->ifname, ifname, IFNAMSIZ); ++ strncpy(newport->ifname, ifname, IFNAMSIZ - 1); + + newport->bond_master = is_bond(ifname); + /* Initialize relevant port variables */ +diff -upr a/lldp/rx.c b/lldp/rx.c +--- a/lldp/rx.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp/rx.c 2021-06-09 11:00:02.480019469 -0400 +@@ -139,7 +139,16 @@ void rxProcessFrame(struct port *port, s + int err; + struct lldp_module *np; + +- assert(agent->rx.framein && agent->rx.sizein); ++ if (!agent->rx.framein) { ++ LLDPAD_DBG("ERROR - agent framein not set, " ++ "has the neighbour MAC changed? " ++ "Ignoring packet.\n"); ++ return; ++ } ++ if (!agent->rx.sizein) { ++ LLDPAD_DBG("Size-0 packet received, ignoring packet\n"); ++ return; ++ } + agent->lldpdu = 0; + agent->rx.dupTlvs = 0; + +@@ -359,7 +368,7 @@ void rxProcessFrame(struct port *port, s + } + + /* rx per lldp module */ +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (!np->ops || !np->ops->lldp_mod_rchange) + continue; + +@@ -377,7 +386,7 @@ void rxProcessFrame(struct port *port, s + if (!tlv_stored) { + LLDPAD_INFO("%s: allocated TLV %u was not stored! %p\n", + __func__, tlv->type, tlv); +- tlv = free_unpkd_tlv(tlv); ++ free_unpkd_tlv(tlv); + agent->stats.statsTLVsUnrecognizedTotal++; + } + tlv = NULL; +@@ -402,7 +411,7 @@ u8 mibDeleteObjects(struct port *port, s + { + struct lldp_module *np; + +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (!np->ops || !np->ops->lldp_mod_mibdelete) + continue; + np->ops->lldp_mod_mibdelete(port, agent); +@@ -638,29 +647,21 @@ void rx_change_state(struct lldp_agent * + void clear_manifest(struct lldp_agent *agent) + { + if (agent->rx.manifest->mgmtadd) +- agent->rx.manifest->mgmtadd = +- free_unpkd_tlv(agent->rx.manifest->mgmtadd); ++ free_unpkd_tlv(agent->rx.manifest->mgmtadd); + if (agent->rx.manifest->syscap) +- agent->rx.manifest->syscap = +- free_unpkd_tlv(agent->rx.manifest->syscap); ++ free_unpkd_tlv(agent->rx.manifest->syscap); + if (agent->rx.manifest->sysdesc) +- agent->rx.manifest->sysdesc = +- free_unpkd_tlv(agent->rx.manifest->sysdesc); ++ free_unpkd_tlv(agent->rx.manifest->sysdesc); + if (agent->rx.manifest->sysname) +- agent->rx.manifest->sysname = +- free_unpkd_tlv(agent->rx.manifest->sysname); ++ free_unpkd_tlv(agent->rx.manifest->sysname); + if (agent->rx.manifest->portdesc) +- agent->rx.manifest->portdesc = +- free_unpkd_tlv(agent->rx.manifest->portdesc); ++ free_unpkd_tlv(agent->rx.manifest->portdesc); + if (agent->rx.manifest->ttl) +- agent->rx.manifest->ttl = +- free_unpkd_tlv(agent->rx.manifest->ttl); ++ free_unpkd_tlv(agent->rx.manifest->ttl); + if (agent->rx.manifest->portid) +- agent->rx.manifest->portid = +- free_unpkd_tlv(agent->rx.manifest->portid); ++ free_unpkd_tlv(agent->rx.manifest->portid); + if (agent->rx.manifest->chassis) +- agent->rx.manifest->chassis = +- free_unpkd_tlv(agent->rx.manifest->chassis); ++ free_unpkd_tlv(agent->rx.manifest->chassis); + free(agent->rx.manifest); + agent->rx.manifest = NULL; + } +diff -upr a/lldp/states.h b/lldp/states.h +--- a/lldp/states.h 2021-06-09 10:58:59.211200590 -0400 ++++ b/lldp/states.h 2021-01-06 11:05:30.811649451 -0500 +@@ -85,7 +85,7 @@ u8 txFrame(struct port *port, struct lld + void run_tx_sm(struct port *, struct lldp_agent *); + void process_tx_initialize_sm(struct port *); + void process_tx_idle(struct lldp_agent *); +-void process_tx_shutdown_frame(struct port *, struct lldp_agent *); ++void process_tx_shutdown_frame(struct port *, struct lldp_agent *, bool); + void process_tx_info_frame(struct port *, struct lldp_agent *); + void update_tx_timers(struct lldp_agent *); + void run_tx_timers_sm(struct port *, struct lldp_agent *); +diff -upr a/lldp/tx.c b/lldp/tx.c +--- a/lldp/tx.c 2021-06-09 10:58:59.211200590 -0400 ++++ b/lldp/tx.c 2021-01-06 11:05:30.812649467 -0500 +@@ -71,7 +71,7 @@ bool mibConstrInfoLLDPDU(struct port *po + fb_offset += sizeof(struct l2_ethhdr); + + /* Generic TLV Pack */ +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (!np->ops || !np->ops->lldp_mod_gettlv) + continue; + +@@ -83,7 +83,7 @@ bool mibConstrInfoLLDPDU(struct port *po + ptlv->tlv, ptlv->size); + datasize += ptlv->size; + fb_offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + } + } + +@@ -94,7 +94,7 @@ bool mibConstrInfoLLDPDU(struct port *po + memcpy(agent->tx.frameout + fb_offset, ptlv->tlv, ptlv->size); + datasize += ptlv->size; + fb_offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + + if (datasize < ETH_MIN_DATA_LEN) + agent->tx.sizeout = ETH_ZLEN; +@@ -104,7 +104,7 @@ bool mibConstrInfoLLDPDU(struct port *po + return true; + + error: +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + if (agent->tx.frameout) + free(agent->tx.frameout); + agent->tx.frameout = NULL; +@@ -206,7 +206,7 @@ bool mibConstrShutdownLLDPDU(struct port + memcpy(agent->tx.frameout, (void *)ð, sizeof(struct l2_ethhdr)); + fb_offset += sizeof(struct l2_ethhdr); + +- np = find_module_by_id(&lldp_head, LLDP_MOD_MAND); ++ np = find_module_by_id(&lldp_mod_head, LLDP_MOD_MAND); + if (!np) + goto error; + if (!np->ops || !np->ops->lldp_mod_gettlv) +@@ -220,7 +220,7 @@ bool mibConstrShutdownLLDPDU(struct port + memcpy(agent->tx.frameout + fb_offset, ptlv->tlv, ptlv->size); + datasize += ptlv->size; + fb_offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + } + + /* The End TLV marks the end of the LLDP PDU */ +@@ -230,7 +230,7 @@ bool mibConstrShutdownLLDPDU(struct port + memcpy(agent->tx.frameout + fb_offset, ptlv->tlv, ptlv->size); + datasize += ptlv->size; + fb_offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + + if (datasize < ETH_MIN_DATA_LEN) + agent->tx.sizeout = ETH_ZLEN; +@@ -239,7 +239,7 @@ bool mibConstrShutdownLLDPDU(struct port + return true; + + error: +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + if (agent->tx.frameout) + free(agent->tx.frameout); + agent->tx.frameout = NULL; +@@ -270,7 +270,7 @@ void run_tx_sm(struct port *port, struct + process_tx_idle(agent); + break; + case TX_SHUTDOWN_FRAME: +- process_tx_shutdown_frame(port, agent); ++ process_tx_shutdown_frame(port, agent, true); + break; + case TX_INFO_FRAME: + process_tx_info_frame(port, agent); +@@ -330,8 +330,19 @@ void process_tx_idle(UNUSED struct lldp_ + return; + } + +-void process_tx_shutdown_frame(struct port *port, struct lldp_agent *agent) ++/* we ignore 'adminStatus' in the case that we have recently transitioned ++ * to the shutdown state (in the case of the 'tx' state change) to allow ++ * for transmitting the ttl==0 as required by the IEEE standard. */ ++void process_tx_shutdown_frame(struct port *port, struct lldp_agent *agent, ++ bool ignoreStatus) + { ++ if (agent->adminStatus != enabledRxTx && ++ agent->adminStatus != enabledTxOnly) { ++ if (!ignoreStatus) { ++ return; ++ } ++ } ++ + if (agent->timers.txShutdownWhile == 0) { + if (mibConstrShutdownLLDPDU(port, agent)) + txFrame(port, agent); +diff -upr a/lldp_8021qaz.c b/lldp_8021qaz.c +--- a/lldp_8021qaz.c 2021-06-09 10:58:59.217200668 -0400 ++++ b/lldp_8021qaz.c 2020-11-03 09:08:48.059229036 -0500 +@@ -48,8 +48,8 @@ + #include "lldp_dcbx.h" + + +-struct lldp_head lldp_head; +-struct config_t lldpad_cfg; ++extern config_t lldpad_cfg; ++extern bool read_only_8021qaz; + + static int ieee8021qaz_check_pending(struct port *port, struct lldp_agent *); + static void run_all_sm(struct port *port, struct lldp_agent *agent); +@@ -83,7 +83,7 @@ static int ieee8021qaz_check_pending(str + if (!port->portEnabled) + return 0; + +- iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ); ++ iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ); + if (iud) { + LIST_FOREACH(tlv, &iud->head, entry) { + if (!strncmp(port->ifname, tlv->ifname, IFNAMSIZ)) { +@@ -111,14 +111,14 @@ struct lldp_module *ieee8021qaz_register + + mod = malloc(sizeof(*mod)); + if (!mod) { +- LLDPAD_ERR("Failed to malloc LLDP-8021QAZ module data"); ++ LLDPAD_ERR("Failed to malloc LLDP-8021QAZ module data\n"); + goto out_err; + } + + iud = malloc(sizeof(*iud)); + if (!iud) { + free(mod); +- LLDPAD_ERR("Failed to malloc LLDP-8021QAZ module user data"); ++ LLDPAD_ERR("Failed to malloc LLDP-8021QAZ module user data\n"); + goto out_err; + } + memset((void *) iud, 0, sizeof(struct ieee8021qaz_user_data)); +@@ -142,7 +142,7 @@ struct ieee8021qaz_tlvs *ieee8021qaz_dat + struct ieee8021qaz_user_data *iud; + struct ieee8021qaz_tlvs *tlv = NULL; + +- iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ); ++ iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ); + if (iud) { + LIST_FOREACH(tlv, &iud->head, entry) { + if (!strncmp(tlv->ifname, ifname, IFNAMSIZ)) +@@ -396,7 +396,7 @@ static int read_cfg_file(char *ifname, s + return 0; + } + +-inline int get_prio_map(u32 prio_map, int prio) ++static int get_prio_map(u32 prio_map, int prio) + { + if (prio > 7) + return 0; +@@ -404,7 +404,7 @@ inline int get_prio_map(u32 prio_map, in + return (prio_map >> (4 * (7-prio))) & 0xF; + } + +-inline void set_prio_map(u32 *prio_map, u8 prio, int tc) ++static void set_prio_map(u32 *prio_map, u8 prio, int tc) + { + u32 mask = ~(0xffffffff & (0xF << (4 * (7-prio)))); + *prio_map &= mask; +@@ -590,7 +590,7 @@ void ieee8021qaz_ifup(char *ifname, stru + memset(tlvs->rx, 0, sizeof(*tlvs->rx)); + + /* Initializing the ieee8021qaz_tlvs struct */ +- strncpy(tlvs->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(tlvs->ifname, ifname, IFNAMSIZ); + tlvs->port = port; + tlvs->ieee8021qazdu = 0; + l2_packet_get_own_src_addr(port->l2, tlvs->local_mac); +@@ -628,7 +628,7 @@ void ieee8021qaz_ifup(char *ifname, stru + LIST_INIT(&tlvs->app_head); + read_cfg_file(port->ifname, agent, tlvs); + +- iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ); ++ iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ); + LIST_INSERT_HEAD(&iud->head, tlvs, entry); + + initialized: +@@ -959,6 +959,9 @@ static int del_ieee_hw(const char *ifnam + .dcb_pad = 0 + }; + ++ if (read_only_8021qaz) ++ return 0; ++ + nlsocket = nl_socket_alloc(); + if (!nlsocket) { + LLDPAD_WARN("%s: %s: nl_handle_alloc failed\n", +@@ -1042,6 +1045,9 @@ static int set_ieee_hw(const char *ifnam + .dcb_pad = 0 + }; + ++ if (read_only_8021qaz) ++ return 0; ++ + nlsocket = nl_socket_alloc(); + if (!nlsocket) { + LLDPAD_WARN("%s: %s: nl_handle_alloc failed\n", +@@ -1618,15 +1624,15 @@ static void clear_ieee8021qaz_rx(struct + return; + + if (tlvs->rx->ieee8021qaz) +- tlvs->rx->ieee8021qaz = free_unpkd_tlv(tlvs->rx->ieee8021qaz); ++ free_unpkd_tlv(tlvs->rx->ieee8021qaz); + if (tlvs->rx->etscfg) +- tlvs->rx->etscfg = free_unpkd_tlv(tlvs->rx->etscfg); ++ free_unpkd_tlv(tlvs->rx->etscfg); + if (tlvs->rx->etsrec) +- tlvs->rx->etsrec = free_unpkd_tlv(tlvs->rx->etsrec); ++ free_unpkd_tlv(tlvs->rx->etsrec); + if (tlvs->rx->pfc) +- tlvs->rx->pfc = free_unpkd_tlv(tlvs->rx->pfc); ++ free_unpkd_tlv(tlvs->rx->pfc); + if (tlvs->rx->app) +- tlvs->rx->app = free_unpkd_tlv(tlvs->rx->app); ++ free_unpkd_tlv(tlvs->rx->app); + + free(tlvs->rx); + tlvs->rx = NULL; +@@ -2014,13 +2020,13 @@ static void ieee8021qaz_free_rx(struct i + return; + + if (rx->etscfg) +- rx->etscfg = free_unpkd_tlv(rx->etscfg); ++ free_unpkd_tlv(rx->etscfg); + if (rx->etsrec) +- rx->etsrec = free_unpkd_tlv(rx->etsrec); ++ free_unpkd_tlv(rx->etsrec); + if (rx->pfc) +- rx->pfc = free_unpkd_tlv(rx->pfc); ++ free_unpkd_tlv(rx->pfc); + if (rx->app) +- rx->app = free_unpkd_tlv(rx->app); ++ free_unpkd_tlv(rx->app); + + return; + } +@@ -2106,9 +2112,9 @@ static void ieee8021qaz_free_tlv(struct + return; + + if (tlvs->ets) +- tlvs->ets = free_ets_tlv(tlvs->ets); ++ free_ets_tlv(tlvs->ets); + if (tlvs->pfc) +- tlvs->pfc = free_pfc_tlv(tlvs->pfc); ++ free_pfc_tlv(tlvs->pfc); + + /* Remove _all_ existing application data */ + LIST_FOREACH(np, &tlvs->app_head, entry) +@@ -2172,7 +2178,7 @@ int ieee8021qaz_tlvs_rxed(const char *if + struct ieee8021qaz_user_data *iud; + struct ieee8021qaz_tlvs *tlv = NULL; + +- iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ); ++ iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ); + if (iud) { + LIST_FOREACH(tlv, &iud->head, entry) { + if (!strncmp(tlv->ifname, ifname, IFNAMSIZ)) +@@ -2191,7 +2197,7 @@ int ieee8021qaz_check_active(const char + struct ieee8021qaz_user_data *iud; + struct ieee8021qaz_tlvs *tlv = NULL; + +- iud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8021QAZ); ++ iud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8021QAZ); + if (iud) { + LIST_FOREACH(tlv, &iud->head, entry) { + if (!strncmp(tlv->ifname, ifname, IFNAMSIZ)) +diff -upr a/lldp_8021qaz_clif.c b/lldp_8021qaz_clif.c +--- a/lldp_8021qaz_clif.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_8021qaz_clif.c 2020-09-23 08:50:52.650813901 -0400 +@@ -251,40 +251,70 @@ static void ieee8021qaz_print_pfc_tlv(UN + + static void ieee8021qaz_print_app_tlv(u16 len, char *info) + { +- u8 offset = 2; +- u8 app; +- u16 proto; ++ u8 app, app_idx, app_prio, app_sel; ++ u16 proto, offset = 2; ++ u8 dscp[MAX_USER_PRIORITIES][MAX_APP_ENTRIES]; ++ u8 dscp_count[MAX_USER_PRIORITIES] = {0}; ++ u8 i, j; ++ bool first_app = true; + + while (offset < len*2) { + hexstr2bin(info + offset, &app, 1); + hexstr2bin(info + offset + 2, (u8 *)&proto, 2); + +- if (offset > 6) +- printf("\t"); +- printf("App#%i:\n", offset/6); +- printf("\t Priority: %i\n", (app & 0xE0) >> 5); +- printf("\t Sel: %i\n", app & 0x07); +- switch (app & 0x07) { +- case 1: +- printf("\t Ethertype: 0x%04x\n", ntohs(proto)); +- break; +- case 2: +- printf("\t {S}TCP Port: %i\n", ntohs(proto)); +- break; +- case 3: +- printf("\t UDP or DCCP Port: %i\n", ntohs(proto)); +- break; +- case 4: +- printf("\t TCP/STCP/UDP/DCCP Port: %i\n", ntohs(proto)); +- break; +- default: +- printf("\t Reserved Port: %i\n", ntohs(proto)); +- break; ++ app_idx = offset/6; ++ app_prio = (app & 0xE0) >> 5; ++ app_sel = app & 0x07; ++ ++ // Selector five is DSCP. Save value to print table at the end ++ if (app_sel == 5) { ++ dscp[app_prio][dscp_count[app_prio]] = ntohs(proto) & 0x3F; ++ dscp_count[app_prio]++; ++ } else { ++ if (first_app) ++ first_app = false; ++ else ++ printf("\t"); ++ printf("App# %3i \t Prio %1i \t Sel %1i \t P-ID", ++ app_idx, app_prio, app_sel); ++ ++ switch (app_sel) { ++ case 1: ++ printf("\t Ethertype: 0x%04x\n", ntohs(proto)); ++ break; ++ case 2: ++ printf("\t {S}TCP Port: %i\n", ntohs(proto)); ++ break; ++ case 3: ++ printf("\t UDP or DCCP Port: %i\n", ntohs(proto)); ++ break; ++ case 4: ++ printf("\t TCP/STCP/UDP/DCCP Port: %i\n", ntohs(proto)); ++ break; ++ default: ++ printf("\t Reserved Port: %i\n", ntohs(proto)); ++ break; ++ } + } + +- printf("\n"); + offset += 6; + } ++ ++ for(i=0; ihead, entry) { + if (!strncmp(ifname, bd->ifname, IFNAMSIZ) && +@@ -401,7 +399,7 @@ struct packed_tlv *ieee8023_gettlv(struc + PACK_TLV_AFTER(bd->maxfs, ptlv, size, out_free); + return ptlv; + out_free: +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + out_err: + LLDPAD_DBG("%s:%s: failed\n", __func__, port->ifname); + return NULL; +@@ -447,7 +445,7 @@ void ieee8023_ifup(char *ifname, struct + goto out_err; + } + memset(bd, 0, sizeof(struct ieee8023_data)); +- strncpy(bd->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(bd->ifname, ifname, IFNAMSIZ); + bd->agenttype = agent->type; + + if (ieee8023_bld_tlv(bd, agent)) { +@@ -456,7 +454,7 @@ void ieee8023_ifup(char *ifname, struct + goto out_err; + } + +- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8023); ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_8023); + LIST_INSERT_HEAD(&ud->head, bd, entry); + LLDPAD_INFO("%s:port %s added\n", __func__, ifname); + return; +@@ -472,13 +470,13 @@ struct lldp_module *ieee8023_register(vo + + mod = malloc(sizeof(*mod)); + if (!mod) { +- LLDPAD_ERR("failed to malloc LLDP 802.3 module data"); ++ LLDPAD_ERR("failed to malloc LLDP 802.3 module data\n"); + goto out_err; + } + ud = malloc(sizeof(struct ieee8023_user_data)); + if (!ud) { + free(mod); +- LLDPAD_ERR("failed to malloc LLDP 802.3 module user data"); ++ LLDPAD_ERR("failed to malloc LLDP 802.3 module user data\n"); + goto out_err; + } + LIST_INIT(&ud->head); +diff -upr a/lldpad.c b/lldpad.c +--- a/lldpad.c 2021-06-09 10:58:59.208200552 -0400 ++++ b/lldpad.c 2021-04-05 12:02:17.320590536 -0400 +@@ -80,10 +80,13 @@ struct lldp_module *(*register_tlv_table + NULL, + }; + ++struct lldp_head lldp_mod_head; ++ + char *cfg_file_name = NULL; + bool daemonize = 0; + int loglvl = LOG_WARNING; + int omit_tstamp; ++bool read_only_8021qaz = false; + + static const char *lldpad_version = + "lldpad v" VERSION_STR "\n" +@@ -97,7 +100,7 @@ static void init_modules(void) + struct lldp_module *premod = NULL; + int i = 0; + +- LIST_INIT(&lldp_head); ++ LIST_INIT(&lldp_mod_head); + for (i = 0; register_tlv_table[i]; i++) { + module = register_tlv_table[i](); + if (!module) +@@ -105,7 +108,7 @@ static void init_modules(void) + if (premod) + LIST_INSERT_AFTER(premod, module, lldp); + else +- LIST_INSERT_HEAD(&lldp_head, module, lldp); ++ LIST_INSERT_HEAD(&lldp_mod_head, module, lldp); + premod = module; + } + } +@@ -114,9 +117,9 @@ 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); ++ while (lldp_mod_head.lh_first != NULL) { ++ module = lldp_mod_head.lh_first; ++ LIST_REMOVE(lldp_mod_head.lh_first, lldp); + module->ops->lldp_mod_unregister(module); + } + } +@@ -136,7 +139,8 @@ static void usage(void) + " -t omit timestamps in log messages\n" + " -v show version\n" + " -f use configfile instead of default\n" +- " -V set syslog level\n"); ++ " -V set syslog level\n" ++ " -R run 8021qaz module in read_only mode\n"); + + exit(1); + } +@@ -236,7 +240,7 @@ int main(int argc, char *argv[]) + int rc = 1; + + for (;;) { +- c = getopt(argc, argv, "hdksptvf:V:"); ++ c = getopt(argc, argv, "hdksptvf:RV:"); + if (c < 0) + break; + switch (c) { +@@ -259,6 +263,9 @@ int main(int argc, char *argv[]) + case 'p': + pid_file = 0; + break; ++ case 'R': ++ read_only_8021qaz = true; ++ break; + case 't': + omit_tstamp = 1; + break; +diff -upr a/lldpad.service b/lldpad.service +--- a/lldpad.service 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldpad.service 2020-09-23 08:50:52.655813990 -0400 +@@ -1,9 +1,11 @@ + [Unit] + Description=Link Layer Discovery Protocol Agent Daemon. + After=syslog.target network.target ++Requires=lldpad.socket + + [Service] + Type=simple ++Restart=always + ExecStart=/usr/sbin/lldpad -t + ExecReload=/bin/kill -HUP $MAINPID + +diff -upr a/lldpad.socket b/lldpad.socket +--- a/lldpad.socket 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldpad.socket 2020-09-23 08:50:52.655813990 -0400 +@@ -1,3 +1,6 @@ ++[Unit] ++Description=Link Layer Discovery Protocol Agent Socket. ++ + [Socket] + ListenDatagram=@/com/intel/lldpad + PassCredentials=true +diff -upr a/lldpad.spec.in b/lldpad.spec.in +--- a/lldpad.spec.in 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldpad.spec.in 2020-09-23 08:50:52.655813990 -0400 +@@ -10,9 +10,9 @@ Source0: http://downloads.sourcef + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + + # BuildRequires: +-Requires(post): chkconfig +-Requires(preun): chkconfig initscripts +-Requires(postun): initscripts ++Requires(post): @SPEC_BUILD_REQUIRES_POST@ ++Requires(preun): @SPEC_BUILD_REQUIRES_PREUN@ ++Requires(postun): @SPEC_BUILD_REQUIRES_POSTUN@ + + %description + This package contains the Linux user space daemon and configuration tool for +@@ -46,20 +46,36 @@ rm -rf $RPM_BUILD_ROOT + + + %post +-/sbin/chkconfig --add lldpad ++if [ -e /etc/init.d/%{name} ] && [ -e /sbin/chkconfig ]; then ++ /sbin/chkconfig --add %{name} ++fi ++if type systemctl >/dev/null 2>&1; then ++ # Scriplet only runs preset. Run enable/start manually ++ %systemd_post %{name}.socket %{name}.service ++fi + + %preun + if [ $1 = 0 ]; then +- /sbin/service lldpad stop +- /sbin/chkconfig --del lldpad ++ if [ -e /etc/init.d/%{name} ] && [ -e /sbin/chkconfig ]; then ++ /sbin/service %{name} stop ++ /sbin/chkconfig --del %{name} ++ fi ++ if type systemctl >/dev/null 2>&1; then ++ %systemd_preun %{name}.service %{name}.socket ++ fi + fi + + %postun + if [ $1 = 1 ]; then +- /sbin/service lldpad condrestart ++ # Package upgrade, not uninstall ++ if [ -e /etc/init.d/%{name} ] && [ -e /sbin/chkconfig ]; then ++ /sbin/service %{name} condrestart ++ fi ++ if type systemctl >/dev/null 2>&1; then ++ %systemd_postun_with_restart %{name}.socket %{name}.service ++ fi + fi + +- + %files + %defattr(-,root,root,-) + %doc COPYING +@@ -67,11 +83,13 @@ fi + %doc ChangeLog + %{_sbindir}/* + %dir /var/lib/lldpad +-%{_sysconfdir}/init.d/lldpad ++@SPEC_FILE_LLDPAD_SERVICE@ ++@SPEC_FILE_LLDPAD_SOCKET@ + %{_sysconfdir}/bash_completion.d/lldpad + %{_sysconfdir}/bash_completion.d/lldptool + %{_mandir}/man8/* + %{_libdir}/liblldp_clif.* ++%{_mandir}/man3/liblldp_clif-vdp22.* + + %files devel + %defattr(-,root,root,-) +diff -upr a/lldp_basman.c b/lldp_basman.c +--- a/lldp_basman.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_basman.c 2020-11-03 09:08:48.059229036 -0500 +@@ -75,8 +75,6 @@ struct tlv_info_manaddr { + struct tlv_info_maoid o; + } __attribute__ ((__packed__)); + +-extern struct lldp_head lldp_head; +- + static const struct lldp_mod_ops basman_ops = { + .lldp_mod_register = basman_register, + .lldp_mod_unregister = basman_unregister, +@@ -91,7 +89,7 @@ static struct basman_data *basman_data(c + struct basman_user_data *bud; + struct basman_data *bd = NULL; + +- bud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_BASIC); ++ bud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_BASIC); + if (bud) { + LIST_FOREACH(bd, &bud->head, entry) { + if (!strncmp(ifname, bd->ifname, IFNAMSIZ) && +@@ -636,7 +634,7 @@ struct packed_tlv *basman_gettlv(struct + PACK_TLV_AFTER(bd->manaddr[i], ptlv, size, out_free); + return ptlv; + out_free: +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + out_err: + LLDPAD_DBG("%s:%s: failed\n", __func__, port->ifname); + return NULL; +@@ -679,7 +677,7 @@ void basman_ifup(char *ifname, struct ll + goto out_err; + } + memset(bd, 0, sizeof(struct basman_data)); +- strncpy(bd->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(bd->ifname, ifname, IFNAMSIZ); + bd->agenttype = agent->type; + + if (basman_bld_tlv(bd, agent)) { +@@ -688,7 +686,7 @@ void basman_ifup(char *ifname, struct ll + goto out_err; + } + +- bud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_BASIC); ++ bud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_BASIC); + LIST_INSERT_HEAD(&bud->head, bd, entry); + LLDPAD_DBG("%s:port %s added\n", __func__, ifname); + return; +diff -upr a/lldp_basman_cmds.c b/lldp_basman_cmds.c +--- a/lldp_basman_cmds.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_basman_cmds.c 2020-09-23 08:50:52.652813936 -0400 +@@ -51,6 +51,9 @@ static int test_arg_ipv6(struct cmd *, c + static int get_arg_tlvtxenable(struct cmd *, char *, char *, char *, int); + static int set_arg_tlvtxenable(struct cmd *, char *, char *, char *, int); + static int test_arg_tlvtxenable(struct cmd *, char *, char *, char *, int); ++static int get_arg_info(struct cmd *, char *, char *, char *, int); ++static int set_arg_info(struct cmd *, char *, char *, char *, int); ++static int test_arg_info(struct cmd *, char *, char *, char *, int); + + static struct arg_handlers arg_handlers[] = { + { .arg = ARG_IPV4_ADDR, .arg_class = TLV_ARG, +@@ -65,6 +68,10 @@ static struct arg_handlers arg_handlers[ + .handle_get = get_arg_tlvtxenable, + .handle_set = set_arg_tlvtxenable, + .handle_test = test_arg_tlvtxenable }, ++ { .arg = ARG_TLVINFO, .arg_class = TLV_ARG, ++ .handle_get = get_arg_info, ++ .handle_set = set_arg_info, ++ .handle_test = test_arg_info }, + { .arg = 0 } + }; + +@@ -166,6 +173,89 @@ static int test_arg_tlvtxenable(struct c + return _set_arg_tlvtxenable(cmd, arg, argvalue, obuf, obuf_len, true); + } + ++static int get_arg_info(struct cmd *cmd, char *arg, UNUSED char *argvalue, ++ char *obuf, int obuf_len) ++{ ++ const char *info_str = NULL; ++ char arg_path[256]; ++ ++ if (cmd->cmd != cmd_gettlv) ++ return cmd_invalid; ++ ++ switch (cmd->tlvid) { ++ case PORT_DESCRIPTION_TLV: ++ case SYSTEM_NAME_TLV: ++ case SYSTEM_DESCRIPTION_TLV: ++ case SYSTEM_CAPABILITIES_TLV: ++ case MANAGEMENT_ADDRESS_TLV: ++ snprintf(arg_path, sizeof(arg_path), "%s%08x.%s", ++ TLVID_PREFIX, cmd->tlvid, arg); ++ ++ get_config_setting(cmd->ifname, cmd->type, arg_path, ++ &info_str, CONFIG_TYPE_STRING); ++ break; ++ case INVALID_TLVID: ++ return cmd_invalid; ++ default: ++ return cmd_not_applicable; ++ } ++ ++ if (info_str) ++ snprintf(obuf, obuf_len, "%02x%s%04x%s", ++ (unsigned int)strlen(arg), arg, ++ (unsigned int)strlen(info_str), info_str); ++ ++ return cmd_success; ++} ++ ++static int _set_arg_info(struct cmd *cmd, UNUSED char *arg, char *argvalue, ++ char *obuf, int obuf_len, bool test) ++{ ++ if (cmd->cmd != cmd_settlv) ++ return cmd_invalid; ++ ++ switch (cmd->tlvid) { ++ case PORT_DESCRIPTION_TLV: ++ case SYSTEM_NAME_TLV: ++ case SYSTEM_DESCRIPTION_TLV: ++ case SYSTEM_CAPABILITIES_TLV: ++ case MANAGEMENT_ADDRESS_TLV: ++ break; ++ case INVALID_TLVID: ++ return cmd_invalid; ++ default: ++ return cmd_not_applicable; ++ } ++ ++ if (strlen(argvalue) < 1) ++ return cmd_invalid; ++ ++ if (test) ++ return cmd_success; ++ ++ if (set_config_tlvinfo_str(cmd->ifname, cmd->type, ++ cmd->tlvid, argvalue)) ++ return cmd_failed; ++ ++ snprintf(obuf, obuf_len, "enableTx = %s\n", argvalue); ++ ++ somethingChangedLocal(cmd->ifname, cmd->type); ++ ++ return cmd_success; ++} ++ ++static int set_arg_info(struct cmd *cmd, char *arg, char *argvalue, ++ char *obuf, int obuf_len) ++{ ++ return _set_arg_info(cmd, arg, argvalue, obuf, obuf_len, false); ++} ++ ++static int test_arg_info(struct cmd *cmd, char *arg, char *argvalue, ++ char *obuf, int obuf_len) ++{ ++ return _set_arg_info(cmd, arg, argvalue, obuf, obuf_len, true); ++} ++ + struct arg_handlers *basman_get_arg_handlers() + { + return &arg_handlers[0]; +diff -upr a/lldp_dcbx.c b/lldp_dcbx.c +--- a/lldp_dcbx.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_dcbx.c 2020-10-23 14:12:58.975289310 -0400 +@@ -129,7 +129,7 @@ struct dcbx_tlvs *dcbx_data(const char * + struct dcbd_user_data *dud; + struct dcbx_tlvs *tlv = NULL; + +- dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX); ++ dud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_DCBX); + if (dud) { + LIST_FOREACH(tlv, &dud->head, entry) { + if (!strncmp(tlv->ifname, ifname, IFNAMSIZ)) +@@ -148,7 +148,7 @@ int dcbx_tlvs_rxed(const char *ifname, s + if (agent->type != NEAREST_BRIDGE) + return 0; + +- dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX); ++ dud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_DCBX); + if (dud) { + LIST_FOREACH(tlv, &dud->head, entry) { + if (!strncmp(tlv->ifname, ifname, IFNAMSIZ)) +@@ -172,7 +172,7 @@ int dcbx_check_active(const char *ifname + struct dcbd_user_data *dud; + struct dcbx_tlvs *tlv = NULL; + +- dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX); ++ dud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_DCBX); + if (dud) { + LIST_FOREACH(tlv, &dud->head, entry) { + if (!strncmp(tlv->ifname, ifname, IFNAMSIZ)) +@@ -194,6 +194,8 @@ int dcbx_bld_tlv(struct port *newport, s + return 0; + + tlvs = dcbx_data(newport->ifname); ++ if (!tlvs) ++ return 0; + + get_config_setting(newport->ifname, agent->type, ARG_ADMINSTATUS, + &adminstatus, CONFIG_TYPE_INT); +@@ -283,20 +285,20 @@ void dcbx_free_manifest(struct dcbx_mani + return; + + if (manifest->dcbx1) +- manifest->dcbx1 = free_unpkd_tlv(manifest->dcbx1); ++ free_unpkd_tlv(manifest->dcbx1); + if (manifest->dcbx2) +- manifest->dcbx2 = free_unpkd_tlv(manifest->dcbx2); ++ free_unpkd_tlv(manifest->dcbx2); + if (manifest->dcbx_ctrl) +- manifest->dcbx_ctrl = free_unpkd_tlv(manifest->dcbx_ctrl); ++ free_unpkd_tlv(manifest->dcbx_ctrl); + if (manifest->dcbx_pg) +- manifest->dcbx_pg = free_unpkd_tlv(manifest->dcbx_pg); ++ free_unpkd_tlv(manifest->dcbx_pg); + if (manifest->dcbx_pfc) +- manifest->dcbx_pfc = free_unpkd_tlv(manifest->dcbx_pfc); ++ free_unpkd_tlv(manifest->dcbx_pfc); + if (manifest->dcbx_app) +- manifest->dcbx_app = free_unpkd_tlv(manifest->dcbx_app); ++ free_unpkd_tlv(manifest->dcbx_app); + if (manifest->dcbx_llink) +- manifest->dcbx_llink = free_unpkd_tlv(manifest->dcbx_llink); +- ++ free_unpkd_tlv(manifest->dcbx_llink); ++ free(manifest); + return; + } + +@@ -305,44 +307,27 @@ void dcbx_free_tlv(struct dcbx_tlvs *tlv + if (!tlvs) + return; + +- if (tlvs->control != NULL) { +- tlvs->control = free_unpkd_tlv(tlvs->control); +- } +- +- if (tlvs->pg1 != NULL) { +- tlvs->pg1 = free_unpkd_tlv(tlvs->pg1); +- } +- +- if (tlvs->pg2 != NULL) { +- tlvs->pg2 = free_unpkd_tlv(tlvs->pg2); +- } +- +- if (tlvs->pfc1 != NULL) { +- tlvs->pfc1 = free_unpkd_tlv(tlvs->pfc1); +- } +- +- if (tlvs->pfc2 != NULL) { +- tlvs->pfc2 = free_unpkd_tlv(tlvs->pfc2); +- } +- +- if (tlvs->app1 != NULL) { +- tlvs->app1 = free_unpkd_tlv(tlvs->app1); +- } +- +- if (tlvs->app2 != NULL) +- tlvs->app2 = free_unpkd_tlv(tlvs->app2); ++ if (tlvs->control) ++ free_unpkd_tlv(tlvs->control); ++ if (tlvs->pg1) ++ free_unpkd_tlv(tlvs->pg1); ++ if (tlvs->pg2) ++ free_unpkd_tlv(tlvs->pg2); ++ if (tlvs->pfc1) ++ free_unpkd_tlv(tlvs->pfc1); ++ if (tlvs->pfc2) ++ free_unpkd_tlv(tlvs->pfc2); ++ if (tlvs->app1) ++ free_unpkd_tlv(tlvs->app1); ++ if (tlvs->app2) ++ free_unpkd_tlv(tlvs->app2); ++ if (tlvs->llink) ++ free_unpkd_tlv(tlvs->llink); ++ if (tlvs->dcbx1) ++ free_unpkd_tlv(tlvs->dcbx1); ++ if (tlvs->dcbx2) ++ free_unpkd_tlv(tlvs->dcbx2); + +- if (tlvs->llink != NULL) { +- tlvs->llink = free_unpkd_tlv(tlvs->llink); +- } +- +- if (tlvs->dcbx1 != NULL) { +- tlvs->dcbx1 = free_unpkd_tlv(tlvs->dcbx1); +- } +- +- if (tlvs->dcbx2 != NULL) { +- tlvs->dcbx2 = free_unpkd_tlv(tlvs->dcbx2); +- } + return; + } + +@@ -362,6 +347,7 @@ struct packed_tlv* dcbx_gettlv(struct po + return NULL; + + dcbx_free_tlv(tlvs); ++ memset(tlvs, 0, sizeof(struct dcbx_tlvs)); + + dcbx_bld_tlv(port, agent); + if (tlvs->dcbx_st == DCBX_SUBTYPE2) { +@@ -386,7 +372,6 @@ static void dcbx_free_data(struct dcbd_u + LIST_REMOVE(dd, entry); + dcbx_free_tlv(dd); + dcbx_free_manifest(dd->manifest); +- free(dd->manifest); + free(dd); + } + } +@@ -408,7 +393,7 @@ struct lldp_module * dcbx_register(void) + if (get_dcbx_version(&dcbx_version)) { + gdcbx_subtype = dcbx_version; + } else { +- LLDPAD_ERR("failed to get DCBX version"); ++ LLDPAD_ERR("failed to get DCBX version\n"); + goto out_err; + } + +@@ -505,7 +490,7 @@ void dcbx_ifup(char *ifname, struct lldp + ifindex = get_ifidx(ifname); + port = port_find_by_ifindex(ifindex); + +- dud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_DCBX); ++ dud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_DCBX); + tlvs = dcbx_data(ifname); + + if (!port) +@@ -582,7 +567,7 @@ void dcbx_ifup(char *ifname, struct lldp + memset(manifest, 0, sizeof(*manifest)); + + tlvs->manifest = manifest; +- strncpy(tlvs->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(tlvs->ifname, ifname, IFNAMSIZ); + tlvs->port = port; + tlvs->dcbdu = 0; + tlvs->dcbx_st = gdcbx_subtype & MASK_DCBX_FORCE; +@@ -654,7 +639,6 @@ void dcbx_ifdown(char *device_name, stru + LIST_REMOVE(tlvs, entry); + dcbx_free_tlv(tlvs); + dcbx_free_manifest(tlvs->manifest); +- free(tlvs->manifest); + free(tlvs); + } + +@@ -664,26 +648,19 @@ void clear_dcbx_manifest(struct dcbx_tlv + return; + + if (dcbx->manifest->dcbx_llink) +- dcbx->manifest->dcbx_llink = +- free_unpkd_tlv(dcbx->manifest->dcbx_llink); ++ free_unpkd_tlv(dcbx->manifest->dcbx_llink); + if (dcbx->manifest->dcbx_app) +- dcbx->manifest->dcbx_app = +- free_unpkd_tlv(dcbx->manifest->dcbx_app); ++ free_unpkd_tlv(dcbx->manifest->dcbx_app); + if (dcbx->manifest->dcbx_pfc) +- dcbx->manifest->dcbx_pfc = +- free_unpkd_tlv(dcbx->manifest->dcbx_pfc); ++ free_unpkd_tlv(dcbx->manifest->dcbx_pfc); + if (dcbx->manifest->dcbx_pg) +- dcbx->manifest->dcbx_pg = +- free_unpkd_tlv(dcbx->manifest->dcbx_pg); ++ free_unpkd_tlv(dcbx->manifest->dcbx_pg); + if (dcbx->manifest->dcbx_ctrl) +- dcbx->manifest->dcbx_ctrl = +- free_unpkd_tlv(dcbx->manifest->dcbx_ctrl); ++ free_unpkd_tlv(dcbx->manifest->dcbx_ctrl); + if (dcbx->manifest->dcbx1) +- dcbx->manifest->dcbx1 = +- free_unpkd_tlv(dcbx->manifest->dcbx1); ++ free_unpkd_tlv(dcbx->manifest->dcbx1); + if (dcbx->manifest->dcbx2) +- dcbx->manifest->dcbx2 = +- free_unpkd_tlv(dcbx->manifest->dcbx2); ++ free_unpkd_tlv(dcbx->manifest->dcbx2); + free(dcbx->manifest); + dcbx->manifest = NULL; + } +diff -upr a/lldp_dcbx_cfg.c b/lldp_dcbx_cfg.c +--- a/lldp_dcbx_cfg.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_dcbx_cfg.c 2020-09-23 08:50:52.652813936 -0400 +@@ -99,12 +99,15 @@ static config_setting_t *construct_new_s + config_setting_t *tmp2_setting = NULL; + char abuf[32]; + int i; ++ char device_name_sanitized[IFNAMSIZ]; + + dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING); + if (!dcbx_setting) + return NULL; + +- eth_setting = config_setting_add(dcbx_setting, device_name, ++ config_ifkey(device_name, device_name_sanitized); ++ ++ eth_setting = config_setting_add(dcbx_setting, device_name_sanitized, + CONFIG_TYPE_GROUP); + if (!eth_setting) + goto set_error; +@@ -371,11 +374,13 @@ static int _set_persistent(char *device_ + config_setting_t *setting_value = NULL; + char abuf[2*DCB_MAX_TLV_LENGTH + 1]; + int result, i; ++ char device_name_sanitized[IFNAMSIZ]; + + dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING); ++ config_ifkey(device_name, device_name_sanitized); + if (dcbx_setting) + eth_settings = config_setting_get_member(dcbx_setting, +- device_name); ++ device_name_sanitized); + + /* init the internal data store for device_name */ + if (NULL == eth_settings) { +@@ -698,7 +703,7 @@ static int _set_persistent(char *device_ + return 0; + + set_error: +- LLDPAD_ERR("update of config file %s failed for %s", ++ LLDPAD_ERR("update of config file %s failed for %s\n", + cfg_file_name, device_name); + return cmd_failed; + } +@@ -782,22 +787,20 @@ int get_persistent(char *device_name, fu + int result = cmd_failed, i; + int results[MAX_USER_PRIORITIES]; + int len; +- char abuf[32]; ++ char abuf[32], device_name_sanitized[IFNAMSIZ]; + + memset(attribs, 0, sizeof(*attribs)); + dcbx_setting = config_lookup(&lldpad_cfg, DCBX_SETTING); ++ ++ config_ifkey(device_name, device_name_sanitized); + if (dcbx_setting) +- eth_settings = config_setting_get_member(dcbx_setting, +- device_name); ++ eth_settings = config_setting_get_member(dcbx_setting, ++ device_name_sanitized); + + /* init the internal data store for device_name */ + result = get_default_persistent(device_name, attribs); +- if (NULL == eth_settings) { +- assert(memcmp(device_name, DEF_CFG_STORE, +- strlen(DEF_CFG_STORE))); +- ++ if (NULL == eth_settings) + return result; +- } + + /* Read pfc setting */ + if (get_int_config(eth_settings, "pfc_enable", TYPE_BOOL, +@@ -1071,13 +1074,16 @@ int get_dcb_enable_state(char *ifname, i + int rc = EINVAL; + config_setting_t *settings = NULL; + char path[sizeof(DCBX_SETTING) + IFNAMSIZ + 16]; ++ char ifkey[IFNAMSIZ]; ++ ++ config_ifkey(ifname, ifkey); + + memset(path, 0, sizeof(path)); +- snprintf(path, sizeof(path), "%s.%s.dcb_enable", DCBX_SETTING, ifname); ++ snprintf(path, sizeof(path), "%s.%s.dcb_enable", DCBX_SETTING, ifkey); + settings = config_lookup(&lldpad_cfg, path); + if (!settings) { + LLDPAD_INFO("### %s:%s:failed on %s\n", __func__, ifname, path); +- snprintf(path, sizeof(path), "%s.dcb_enable", ifname); ++ snprintf(path, sizeof(path), "%s.dcb_enable", ifkey); + settings = config_lookup(&lldpad_cfg, path); + if (!settings) { + LLDPAD_INFO("### %s:%s:failed again %s\n", __func__, ifname, path); +diff -upr a/lldp_dcbx_cmds.c b/lldp_dcbx_cmds.c +--- a/lldp_dcbx_cmds.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_dcbx_cmds.c 2020-09-23 08:50:52.653813954 -0400 +@@ -259,8 +259,12 @@ static cmd_status set_dcb_state(char *po + + if (ilen == (off + CFG_DCB_DLEN)) { + state = (*(ibuf+off+DCB_STATE)) ^ '0'; +- set_hw_state(port_id, state); +- rval = save_dcb_enable_state(port_id, state); ++ ++ if(set_hw_state(port_id, state) < 0) { ++ rval = cmd_not_capable; ++ } else { ++ rval = save_dcb_enable_state(port_id, state); ++ } + } else { + printf("error - setcommand has invalid argument length\n"); + rval = cmd_bad_params; +@@ -943,6 +947,10 @@ static int set_pg_config(pg_attribs *pg_ + bool used[MAX_BANDWIDTH_GROUPS]; + bool uppcts_changed = false; + ++ /* If PG is disabled, skip changing any other attributes */ ++ if (!(pg_data->protocol.Enable)) ++ goto done; ++ + plen=strlen(port_id); + off = DCB_PORT_OFF + plen + CFG_LEN; + +@@ -1067,6 +1075,7 @@ static int set_pg_config(pg_attribs *pg_ + return status; + } + ++done: + is_pfc = get_pfc(port_id, &pfc_data); + if (is_pfc == cmd_success) + status = put_pg(port_id, pg_data, &pfc_data); +diff -upr a/lldp_dcbx_nl.c b/lldp_dcbx_nl.c +--- a/lldp_dcbx_nl.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_dcbx_nl.c 2020-09-23 08:50:52.653813954 -0400 +@@ -152,16 +152,17 @@ static int send_msg(struct nlmsghdr *nlh + { + struct sockaddr_nl nladdr; + void *buf = (void *)nlh; +- int r, len = nlh->nlmsg_len; ++ int r; + + if (nlh == NULL) + return 1; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; +- ++ + do { +- r = sendto(nl_sd, buf, len, 0, (struct sockaddr *)&nladdr, ++ r = sendto(nl_sd, buf, nlh->nlmsg_len, 0, ++ (struct sockaddr *)&nladdr, + sizeof(nladdr)); + LLDPAD_DBG("send_msg: sendto = %d\n", r); + +@@ -561,7 +562,7 @@ int get_dcb_numtcs(const char *ifname, u + + seq = nlh->nlmsg_seq; + +- strncpy(name, ifname, sizeof(name)); ++ STRNCPY_TERMINATED (name, ifname, sizeof(name)); + add_rta(nlh, DCB_ATTR_IFNAME, (void *)name, strlen(name) + 1); + rta_parent = add_rta(nlh, DCB_ATTR_NUMTCS, NULL, 0); + +@@ -801,17 +802,6 @@ int set_hw_app(char *ifname, appgroup_at + return(recv_msg(DCB_CMD_SAPP, DCB_ATTR_APP, seq)); + } + +-int run_cmd(char *cmd, ...) +-{ +- char cbuf[128]; +- va_list args; +- +- va_start(args, cmd); +- vsprintf(cbuf, cmd, args); +- va_end(args); +- return system(cbuf); +-} +- + int set_hw_all(char *ifname) + { + struct nlmsghdr *nlh; +diff -upr a/lldp_evb22.c b/lldp_evb22.c +--- a/lldp_evb22.c 2021-06-09 10:58:59.218200681 -0400 ++++ b/lldp_evb22.c 2020-11-03 09:08:48.060229053 -0500 +@@ -37,14 +37,12 @@ + #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); ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_EVB22); + if (ud) { + LIST_FOREACH(ed, &ud->head, entry) { + if (!strncmp(ifname, ed->ifname, IFNAMSIZ) && +@@ -450,10 +448,10 @@ static void evb22_ifup(char *ifname, str + __func__, ifname, agent->type, sizeof *ed); + return; + } +- strncpy(ed->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(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); ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_EVB22); + LIST_INSERT_HEAD(&ud->head, ed, entry); + LLDPAD_DBG("%s:%s agent %d added\n", __func__, ifname, agent->type); + } +diff -upr a/lldp_evb22_cmds.c b/lldp_evb22_cmds.c +--- a/lldp_evb22_cmds.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_evb22_cmds.c 2020-09-23 08:50:52.653813954 -0400 +@@ -225,7 +225,7 @@ int evb22_conf_enabletx(char *ifname, en + TLVID(OUI_IEEE_8021Qbg22, LLDP_EVB22_SUBTYPE)); + } + +-static int evb22_cmdok(struct cmd *cmd, cmd_status expected) ++static int evb22_cmdok(struct cmd *cmd, int expected) + { + if (cmd->cmd != expected) + return cmd_invalid; +diff -upr a/lldp_evb.c b/lldp_evb.c +--- a/lldp_evb.c 2021-06-09 10:58:59.217200668 -0400 ++++ b/lldp_evb.c 2021-04-05 12:02:17.318590504 -0400 +@@ -36,14 +36,12 @@ + #include "messages.h" + #include "config.h" + +-extern struct lldp_head lldp_head; +- + struct evb_data *evb_data(char *ifname, enum agent_type type) + { + struct evb_user_data *ud; + struct evb_data *ed = NULL; + +- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB); ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_EVB); + if (ud) { + LIST_FOREACH(ed, &ud->head, entry) { + if (!strncmp(ifname, ed->ifname, IFNAMSIZ) && +@@ -342,12 +340,12 @@ static void evb_ifup(char *ifname, struc + __func__, ifname, agent->type, sizeof(*ed)); + return; + } +- strncpy(ed->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(ed->ifname, ifname, IFNAMSIZ); + ed->agenttype = agent->type; + + evb_init_tlv(ed, agent); + +- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_EVB); ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_EVB); + LIST_INSERT_HEAD(&ud->head, ed, entry); + LLDPAD_DBG("%s:%s agent %d added\n", __func__, ifname, agent->type); + } +diff -upr a/lldp_evb_cmds.c b/lldp_evb_cmds.c +--- a/lldp_evb_cmds.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_evb_cmds.c 2020-09-23 08:50:52.653813954 -0400 +@@ -163,7 +163,7 @@ int evb_conf_enabletx(char *ifname, enum + return is_tlv_txenabled(ifname, type, TLVID_8021Qbg(LLDP_EVB_SUBTYPE)); + } + +-static int evb_cmdok(struct cmd *cmd, cmd_status expected) ++static int evb_cmdok(struct cmd *cmd, int expected) + { + if (cmd->cmd != expected) + return cmd_invalid; +diff -upr a/lldp_mand.c b/lldp_mand.c +--- a/lldp_mand.c 2021-06-09 10:58:59.211200590 -0400 ++++ b/lldp_mand.c 2020-11-03 09:08:48.061229070 -0500 +@@ -42,8 +42,6 @@ + #include "lldp/l2_packet.h" + #include "lldp_tlv.h" + +-extern struct lldp_head lldp_head; +- + static const struct lldp_mod_ops mand_ops = { + .lldp_mod_register = mand_register, + .lldp_mod_unregister = mand_unregister, +@@ -59,7 +57,7 @@ struct mand_data *mand_data(const char * + struct mand_user_data *mud; + struct mand_data *md = NULL; + +- mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MAND); ++ mud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_MAND); + if (mud) { + LIST_FOREACH(md, &mud->head, entry) { + if (!strncmp(ifname, md->ifname, IFNAMSIZ) && +@@ -100,7 +98,7 @@ static int mand_bld_end_tlv(struct mand_ + static int mand_bld_mac_chassis(struct mand_data *md, + struct tlv_info_chassis *chassis) + { +- get_mac(md->ifname, chassis->id.mac); ++ get_mac(md->ifname, chassis->id.mac, false); + if (is_valid_mac(chassis->id.mac)) + chassis->sub = CHASSIS_ID_MAC_ADDRESS; + return sizeof(chassis->id.mac) + sizeof(chassis->sub); +@@ -112,11 +110,13 @@ static int mand_bld_ip_chassis(struct ma + { + unsigned int len; + +- if (!get_ipaddr(md->ifname, &chassis->id.na.ip.v4)) { ++ void *v4_ptr = &chassis->id.na.ip.v4; ++ void *v6_ptr = &chassis->id.na.ip.v6; ++ if (!get_ipaddr(md->ifname, v4_ptr)) { + chassis->sub = CHASSIS_ID_NETWORK_ADDRESS; + chassis->id.na.type = MANADDR_IPV4; + len = sizeof(chassis->id.na.ip.v4); +- } else if (!get_ipaddr6(md->ifname, &chassis->id.na.ip.v6)) { ++ } else if (!get_ipaddr6(md->ifname, v6_ptr)) { + chassis->sub = CHASSIS_ID_NETWORK_ADDRESS; + chassis->id.na.type = MANADDR_IPV6; + len = sizeof(chassis->id.na.ip.v6); +@@ -217,6 +217,7 @@ static int mand_bld_chassis_tlv(struct m + if (length > 0) + break; + /* Fall through on IP error */ ++ /* FALLTHROUGH */ + case CHASSIS_ID_MAC_ADDRESS: + default: + length = mand_bld_mac_chassis(md, &chassis); +@@ -234,6 +235,7 @@ static int mand_bld_chassis_tlv(struct m + if (length > 0) + break; + /* Fall through on IP error */ ++ /* FALLTHROUGH */ + case LLDP_MED_DEVTYPE_NETWORK_CONNECTIVITY: + default: + length = mand_bld_ifname_chassis(md, &chassis); +@@ -361,16 +363,18 @@ static int mand_bld_portid_tlv(struct ma + switch (subtype) { + default: + case PORT_ID_MAC_ADDRESS: +- get_mac(md->ifname, portid.id.mac); ++ get_mac(md->ifname, portid.id.mac, true); + if (is_valid_mac(portid.id.mac)) { + portid.sub = PORT_ID_MAC_ADDRESS; + length = sizeof(portid.id.mac) + + sizeof(portid.sub); + break; + } +- case PORT_ID_NETWORK_ADDRESS: ++ /* FALLTHROUGH */ ++ case PORT_ID_NETWORK_ADDRESS: { + /* uses ipv4 first */ +- if (!get_ipaddr(md->ifname, &portid.id.na.ip.v4)) { ++ void *v4_ptr = &portid.id.na.ip.v4; ++ if (!get_ipaddr(md->ifname, v4_ptr)) { + portid.sub = PORT_ID_NETWORK_ADDRESS; + portid.id.na.type = MANADDR_IPV4; + length = sizeof(portid.id.na.type) + +@@ -379,7 +383,8 @@ static int mand_bld_portid_tlv(struct ma + break; + } + /* ipv4 fails, get ipv6 */ +- if (!get_ipaddr6(md->ifname, &portid.id.na.ip.v6)) { ++ void *v6_ptr = &portid.id.na.ip.v6; ++ if (!get_ipaddr6(md->ifname, v6_ptr)) { + portid.sub = PORT_ID_NETWORK_ADDRESS; + portid.id.na.type = MANADDR_IPV6; + length = sizeof(portid.id.na.type) + +@@ -387,6 +392,8 @@ static int mand_bld_portid_tlv(struct ma + sizeof(portid.sub); + break; + } ++ } ++ /* FALLTHROUGH */ + case PORT_ID_INTERFACE_NAME: + portid.sub = PORT_ID_INTERFACE_NAME; + strncpy((char *)portid.id.ifname, md->ifname, IFNAMSIZ); +@@ -508,9 +515,11 @@ struct packed_tlv *mand_gettlv(struct po + } + + err = mand_bld_tlv(md, agent); +- if (err) ++ if (err) { + LLDPAD_DBG("%s:%s: building mandotory TLV error.\n", + __func__, port->ifname); ++ goto out_err; ++ } + + size = TLVSIZE(md->chassis) + + TLVSIZE(md->portid) +@@ -532,7 +541,7 @@ struct packed_tlv *mand_gettlv(struct po + PACK_TLV_AFTER(md->ttl, ptlv, size, out_free); + return ptlv; + out_free: +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + out_err: + LLDPAD_DBG("%s:%s: failed\n", __func__, port->ifname); + return NULL; +@@ -596,10 +605,10 @@ void mand_ifup(char *ifname, struct lldp + return; + } + memset(md, 0, sizeof(struct mand_data)); +- strncpy(md->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(md->ifname, ifname, IFNAMSIZ); + md->agenttype = agent->type; + +- mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MAND); ++ mud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_MAND); + LIST_INSERT_HEAD(&mud->head, md, entry); + } + +@@ -627,7 +636,7 @@ struct lldp_module *mand_register(void) + LLDPAD_ERR("failed to malloc LLDP Mandatory module data\n"); + goto out_err; + } +- mud = malloc(sizeof(struct mand_user_data)); ++ mud = malloc(sizeof(struct mand_user_data)); + if (!mud) { + free(mod); + LLDPAD_ERR("failed to malloc LLDP Mandatory module user data\n"); +@@ -635,8 +644,8 @@ struct lldp_module *mand_register(void) + } + LIST_INIT(&mud->head); + mod->id = LLDP_MOD_MAND; ++ mod->data = mud; + mod->ops = &mand_ops; +- mod->data = mud; + LLDPAD_INFO("%s:done\n", __func__); + return mod; + out_err: +diff -upr a/lldp_mand_cmds.c b/lldp_mand_cmds.c +--- a/lldp_mand_cmds.c 2021-06-09 10:58:59.211200590 -0400 ++++ b/lldp_mand_cmds.c 2020-10-23 14:12:58.975289310 -0400 +@@ -44,6 +44,9 @@ + #include "lldp/states.h" + #include "lldp_util.h" + #include "messages.h" ++#include "lldp_8021qaz.h" ++ ++extern bool read_only_8021qaz; + + static int get_arg_adminstatus(struct cmd *, char *, char *, char *, int); + static int set_arg_adminstatus(struct cmd *, char *, char *, char *, int); +@@ -463,7 +466,7 @@ int handle_get_args(struct cmd *cmd, UNU + nbuf = obuf; + nbuf_len = obuf_len; + +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (!np->ops->get_arg_handler) + continue; + if (!(ah = np->ops->get_arg_handler())) +@@ -493,7 +496,7 @@ int handle_get_arg(struct cmd *cmd, char + struct arg_handlers *ah; + int rval, status = cmd_not_applicable; + +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (!np->ops->get_arg_handler) + continue; + if (!(ah = np->ops->get_arg_handler())) +@@ -590,11 +593,14 @@ int handle_test_arg(struct cmd *cmd, cha + struct arg_handlers *ah; + int rval, status = cmd_not_applicable; + +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (!np->ops->get_arg_handler) + continue; + if (!(ah = np->ops->get_arg_handler())) + continue; ++ /* 8021QAZ set operations not allowed in read-only mode */ ++ if (np->id == LLDP_MOD_8021QAZ && read_only_8021qaz) ++ return cmd_no_access; + while (ah->arg) { + if (!strcasecmp(ah->arg, arg) && ah->handle_test) { + rval = ah->handle_test(cmd, ah->arg, argvalue, +@@ -620,11 +626,14 @@ int handle_set_arg(struct cmd *cmd, char + struct arg_handlers *ah; + int rval, status = cmd_not_applicable; + +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (!np->ops->get_arg_handler) + continue; + if (!(ah = np->ops->get_arg_handler())) + continue; ++ /* 8021QAZ set operations not allowed in read-only mode */ ++ if (np->id == LLDP_MOD_8021QAZ && read_only_8021qaz) ++ return cmd_no_access; + while (ah->arg) { + if (!strcasecmp(ah->arg, arg) && ah->handle_set) { + rval = ah->handle_set(cmd, ah->arg, argvalue, +diff -upr a/lldp_med.c b/lldp_med.c +--- a/lldp_med.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_med.c 2020-11-03 09:08:48.061229070 -0500 +@@ -40,8 +40,6 @@ + #include "lldp_mand_clif.h" + #include "lldp_med_cmds.h" + +-extern struct lldp_head lldp_head; +- + struct tlv_info_medcaps { + u8 oui[OUI_SIZE]; + u8 subtype; +@@ -95,7 +93,7 @@ static struct med_data *med_data(const c + struct med_user_data *mud; + struct med_data *md = NULL; + +- mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MED); ++ mud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_MED); + if (mud) { + LIST_FOREACH(md, &mud->head, entry) { + if (!strncmp(ifname, md->ifname, IFNAMSIZ) && +@@ -905,7 +903,7 @@ void med_ifup(char *ifname, struct lldp_ + goto out_err; + } + memset(md, 0, sizeof(struct med_data)); +- strncpy(md->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(md->ifname, ifname, IFNAMSIZ); + md->agenttype = agent->type; + + if (med_bld_tlv(md, agent)) { +@@ -914,7 +912,7 @@ void med_ifup(char *ifname, struct lldp_ + free(md); + goto out_err; + } +- mud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_MED); ++ mud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_MED); + LIST_INSERT_HEAD(&mud->head, md, entry); + LLDPAD_INFO("%s:port %s added\n", __func__, ifname); + return; +diff -upr a/lldp_med_cmds.c b/lldp_med_cmds.c +--- a/lldp_med_cmds.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_med_cmds.c 2020-09-23 08:50:52.654813972 -0400 +@@ -303,6 +303,7 @@ static int _set_arg_med_devtype(struct c + case LLDP_MED_DEVTYPE_ENDPOINT_CLASS_III: + case LLDP_MED_DEVTYPE_ENDPOINT_CLASS_II: + tlv_enabletx(cmd->ifname, cmd->type, (OUI_TIA_TR41 << 8) | LLDP_MED_NETWORK_POLICY); ++ /* FALLTHROUGH */ + case LLDP_MED_DEVTYPE_ENDPOINT_CLASS_I: + case LLDP_MED_DEVTYPE_NETWORK_CONNECTIVITY: + tlv_enabletx(cmd->ifname, cmd->type, (OUI_TIA_TR41 << 8) | LLDP_MED_RESERVED); +diff -upr a/lldp_rtnl.c b/lldp_rtnl.c +--- a/lldp_rtnl.c 2021-06-09 10:58:59.213200616 -0400 ++++ b/lldp_rtnl.c 2021-04-05 12:02:17.319590520 -0400 +@@ -103,7 +103,8 @@ static void add_rtattr(struct nlmsghdr * + + rta->rta_type = type; + rta->rta_len = len; +- memcpy(RTA_DATA(rta), data, alen); ++ if (data) ++ memcpy(RTA_DATA(rta), data, alen); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); + } + +diff -upr a/lldp_tlv.c b/lldp_tlv.c +--- a/lldp_tlv.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldp_tlv.c 2020-09-23 08:50:52.654813972 -0400 +@@ -112,13 +112,13 @@ int pack_tlv_after(struct unpacked_tlv * + return -1; + + if (ptlv->size + mtlv->size > length) { +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + return -1; + } + + memcpy(&mtlv->tlv[mtlv->size], ptlv->tlv, ptlv->size); + mtlv->size += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + return 0; + } + +@@ -158,7 +158,7 @@ struct unpacked_tlv *unpack_tlv(struct p + return upkd_tlv; + } + +-struct unpacked_tlv *free_unpkd_tlv(struct unpacked_tlv *tlv) ++void free_unpkd_tlv(struct unpacked_tlv *tlv) + { + if (tlv != NULL) { + if (tlv->info != NULL) { +@@ -166,12 +166,10 @@ struct unpacked_tlv *free_unpkd_tlv(stru + tlv->info = NULL; + } + free(tlv); +- tlv = NULL; + } +- return NULL; + } + +-struct packed_tlv *free_pkd_tlv(struct packed_tlv *tlv) ++void free_pkd_tlv(struct packed_tlv *tlv) + { + if (tlv != NULL) { + if (tlv->tlv != NULL) { +@@ -179,9 +177,7 @@ struct packed_tlv *free_pkd_tlv(struct p + tlv->tlv = NULL; + } + free(tlv); +- tlv = NULL; + } +- return NULL; + } + + struct packed_tlv *create_ptlv() +diff -upr a/lldptool.c b/lldptool.c +--- a/lldptool.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldptool.c 2020-10-30 09:35:19.614361934 -0400 +@@ -64,6 +64,9 @@ + #include "lldp_util.h" + #include "lldpad_status.h" + ++struct lldp_head lldp_cli_head; ++struct lldp_head lldp_mod_head; ++extern void close_history(void); + static int show_raw; + + static const char *cli_version = +@@ -199,7 +202,7 @@ static void init_modules(void) + if (premod) + LIST_INSERT_AFTER(premod, module, lldp); + else +- LIST_INSERT_HEAD(&lldp_head, module, lldp); ++ LIST_INSERT_HEAD(&lldp_mod_head, module, lldp); + premod = module; + } + } +@@ -208,9 +211,9 @@ 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); ++ while (lldp_mod_head.lh_first != NULL) { ++ module = lldp_mod_head.lh_first; ++ LIST_REMOVE(lldp_mod_head.lh_first, lldp); + module->ops->lldp_mod_unregister(module); + } + } +@@ -222,28 +225,6 @@ static void usage(void) + commands_usage, commands_options, commands_help); + } + +-/* assumes input is pointer to two hex digits */ +-/* returns -1 on error */ +-int hex2int(char *b) +-{ +- int i; +- int n=0; +- int m; +- +- for (i=0,m=1; i<2; i++,m--) { +- if (isxdigit(*(b+i))) { +- if (*(b+i) <= '9') +- n |= (*(b+i) & 0x0f) << (4*m); +- else +- n |= ((*(b+i) & 0x0f) + 9) << (4*m); +- } +- else { +- return -1; +- } +- } +- return n; +-} +- + void print_raw_message(char *msg, int print) + { + if (!print || !(print & SHOW_RAW)) +@@ -368,7 +349,7 @@ cli_cmd_help(UNUSED struct clif *clif, U + printf("%s\n%s\n%s", commands_usage, commands_options, commands_help); + + printf("\nTLV identifiers:\n"); +- LIST_FOREACH(np, &lldp_head, lldp) ++ LIST_FOREACH(np, &lldp_mod_head, lldp) + if (np->ops->print_help) + np->ops->print_help(); + return 0; +@@ -428,7 +409,7 @@ u32 lookup_tlvid(char *tlvid_str) + struct lldp_module *np; + u32 tlvid = INVALID_TLVID; + +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (np->ops->lookup_tlv_name) { + tlvid = np->ops->lookup_tlv_name(tlvid_str); + if (tlvid != INVALID_TLVID) +@@ -711,6 +692,7 @@ static void cli_interactive() + } + free(cmd); + } while (!cli_quit); ++ close_history(); + } + + static void cli_terminate(UNUSED int sig) +diff -upr a/lldptool_cmds.c b/lldptool_cmds.c +--- a/lldptool_cmds.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/lldptool_cmds.c 2020-10-23 14:12:58.976289329 -0400 +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include "clif.h" + #include "dcb_types.h" + #include "lldptool.h" +@@ -464,7 +465,7 @@ static void print_tlvs(struct cmd *cmd, + offset += 8; + + printed = 0; +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (np->ops->print_tlv(tlvid, tlv_len, ibuf+offset)) { + printed = 1; + break; +diff -upr a/lldp_util.c b/lldp_util.c +--- a/lldp_util.c 2021-06-09 10:58:59.215200642 -0400 ++++ b/lldp_util.c 2020-09-23 08:50:52.654813972 -0400 +@@ -24,6 +24,7 @@ + + *******************************************************************************/ + ++#include + #include + #include + #include +@@ -122,6 +123,28 @@ int hexstr2bin(const char *hex, u8 *buf, + return 0; + } + ++/* assumes input is pointer to two hex digits */ ++/* returns -1 on error */ ++int hex2int(char *b) ++{ ++ int i; ++ int n=0; ++ int m; ++ ++ for (i=0,m=1; i<2; i++,m--) { ++ if (isxdigit(*(b+i))) { ++ if (*(b+i) <= '9') ++ n |= (*(b+i) & 0x0f) << (4*m); ++ else ++ n |= ((*(b+i) & 0x0f) + 9) << (4*m); ++ } ++ else { ++ return -1; ++ } ++ } ++ return n; ++} ++ + char *print_mac(char *mac, char *buf) + { + sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", +@@ -189,26 +212,6 @@ int is_bond(const char *ifname) + } + + /** +- * is_san_mac - check if address is a san mac addr +- * @addr: san mac address +- * +- * Returns 0 if addr is NOT san mac, 1 if it is a san mac. +- * +- * BUG: this does not do anything to prove it's a sanmac!!!! +- * SAN MAC is no different than LAN MAC, no way to tell!!! +- */ +-int is_san_mac(u8 *addr) +-{ +- int i; +- +- for ( i = 0; i < ETH_ALEN; i++) { +- if ( addr[i]!= 0xff ) +- return 1; +- } +- return 0; +-} +- +-/** + * get_src_mac_from_bond - select a source MAC to use for slave + * @bond_port: pointer to port structure for a bond interface + * @ifname: interface name of the slave port +@@ -314,11 +317,24 @@ int get_src_mac_from_bond(struct port *b + */ + int is_valid_mac(const u8 *mac) + { +- 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; ++ static const u8 zero_mac[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; ++ static const u8 ff_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; ++ static const u8 iana_mcast[ETH_ALEN] = {0x01, 0x00, 0x5E}; ++ static const u8 ipv6_mcast[ETH_ALEN] = {0x33, 0x33}; ++ ++ if(memcmp(mac, zero_mac, ETH_ALEN) == 0 || ++ memcmp(mac, ff_mac, ETH_ALEN) == 0) ++ return 0; ++ ++ /* IANA multicast and ipv6 multicast mac address ++ * For reference check document: ++ * https://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml ++ */ ++ if(memcmp(mac, iana_mcast, 3) == 0 || ++ memcmp(mac, ipv6_mcast, 2) == 0) ++ return 0; ++ ++ return 1; + } + + int read_int(const char *path) +@@ -350,7 +366,7 @@ int get_ifflags(const char *ifname) + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) + flags = ifr.ifr_flags; + } +@@ -386,7 +402,7 @@ int get_ifpflags(const char *ifname) + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFPFLAGS, &ifr) == 0) + flags = ifr.ifr_flags; + } +@@ -470,7 +486,7 @@ int is_slave(const char *ifmaster, const + + memset(&ifr, 0, sizeof(ifr)); + memset(&ifb, 0, sizeof(ifb)); +- strncpy(ifr.ifr_name, ifmaster, IFNAMSIZ); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifmaster, IFNAMSIZ); + ifr.ifr_data = (caddr_t)&ifb; + if (ioctl(fd, SIOCBONDINFOQUERY, &ifr)) + goto out_done; +@@ -500,7 +516,7 @@ int get_ifidx(const char *ifname) + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifreq, 0, sizeof(ifreq)); +- strncpy(ifreq.ifr_name, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(ifreq.ifr_name, ifname, IFNAMSIZ); + if (ioctl(fd, SIOCGIFINDEX, &ifreq) == 0) + idx = ifreq.ifr_ifindex; + } +@@ -572,7 +588,7 @@ int is_bridge(const char *ifname) + (unsigned long) &bi, 0, 0 }; + + ifr.ifr_data = (char *)args; +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCDEVPRIVATE, &ifr) == 0) + rc = 1; + } +@@ -610,7 +626,7 @@ int is_vlan(const char *ifname) + if (fd >= 0) { + memset(&ifv, 0, sizeof(ifv)); + ifv.cmd = GET_VLAN_REALDEV_NAME_CMD; +- strncpy(ifv.device1, ifname, sizeof(ifv.device1)); ++ STRNCPY_TERMINATED(ifv.device1, ifname, sizeof(ifv.device1)); + if (ioctl(fd, SIOCGIFVLAN, &ifv) == 0) + rc = 1; + } +@@ -637,7 +653,7 @@ int is_wlan(const char *ifname) + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&iwreq, 0, sizeof(iwreq)); +- strncpy(iwreq.ifr_name, ifname, sizeof(iwreq.ifr_name)); ++ STRNCPY_TERMINATED(iwreq.ifr_name, ifname, sizeof(iwreq.ifr_name)); + if (ioctl(fd, SIOCGIWNAME, &iwreq) == 0) + rc = 1; + } +@@ -650,6 +666,8 @@ static struct nla_policy ifla_info_polic + { + [IFLA_INFO_KIND] = { .type = NLA_STRING}, + [IFLA_INFO_DATA] = { .type = NLA_NESTED }, ++ [IFLA_INFO_SLAVE_KIND] = { .type = NLA_STRING}, ++ [IFLA_INFO_SLAVE_DATA] = { .type = NLA_NESTED }, + }; + + int is_macvtap(const char *ifname) +@@ -754,7 +772,7 @@ int is_active(const char *ifname) + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) + if (ifr.ifr_flags & IFF_UP) + rc = 1; +@@ -775,7 +793,7 @@ int is_autoneg_supported(const char *ifn + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = ETHTOOL_GSET; + ifr.ifr_data = &cmd; +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) + if (cmd.supported & SUPPORTED_Autoneg) + rc = 1; +@@ -796,7 +814,7 @@ int is_autoneg_enabled(const char *ifnam + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = ETHTOOL_GSET; + ifr.ifr_data = &cmd; +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) + rc = cmd.autoneg; + } +@@ -833,7 +851,7 @@ int get_maucaps(const char *ifname) + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = ETHTOOL_GSET; + ifr.ifr_data = &cmd; +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) { + if (cmd.advertising & ADVERTISED_10baseT_Half) + caps |= MAUCAPADV_b10baseT; +@@ -872,7 +890,7 @@ int get_mautype(const char *ifname) + memset(&cmd, 0, sizeof(cmd)); + cmd.cmd = ETHTOOL_GSET; + ifr.ifr_data = &cmd; +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) { + /* TODO: too many dot3MauTypes, + * should check duplex, speed, and port */ +@@ -899,7 +917,7 @@ int get_mtu(const char *ifname) + fd = get_ioctl_socket(); + if (fd >= 0) { + memset(&ifr, 0, sizeof(ifr)); +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFMTU, &ifr) == 0) + rc = ifr.ifr_mtu; + } +@@ -921,38 +939,86 @@ int get_mfs(const char *ifname) + return mfs; + } + +-int get_mac(const char *ifname, u8 mac[]) ++int get_mac(const char *ifname, u8 mac[], bool perm_mac) + { +- int fd; +- int rc = EINVAL; +- struct ifreq ifr; ++ int ret, s; ++ struct nlmsghdr *nlh; ++ struct ifinfomsg *ifinfo; ++ struct nlattr *tb[IFLA_MAX+1], ++ *tb2[IFLA_INFO_MAX+1]; + +- memset(mac, 0, 6); +- fd = get_ioctl_socket(); +- if (fd >= 0) { +- ifr.ifr_addr.sa_family = AF_INET; +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); +- if (!ioctl(fd, SIOCGIFHWADDR, &ifr)) { +- memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); +- rc = 0; +- } ++ s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); ++ ++ if (s < 0) { ++ goto out; + } +- return rc; +-} + +-int get_macstr(const char *ifname, char *addr, size_t size) +-{ +- u8 mac[6]; +- int rc; ++ nlh = malloc(NLMSG_SIZE); + +- rc = get_mac(ifname, mac); +- if (rc == 0) { +- snprintf(addr, size, "%02x:%02x:%02x:%02x:%02x:%02x", +- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ if (!nlh) { ++ goto out; + } +- return rc; +-} + ++ memset(nlh, 0, NLMSG_SIZE); ++ ++ nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); ++ nlh->nlmsg_type = RTM_GETLINK; ++ nlh->nlmsg_flags = NLM_F_REQUEST; ++ ++ ifinfo = NLMSG_DATA(nlh); ++ ifinfo->ifi_family = AF_UNSPEC; ++ ifinfo->ifi_index = get_ifidx(ifname); ++ ++ ret = send(s, nlh, nlh->nlmsg_len, 0); ++ ++ if (ret < 0) { ++ goto out_free; ++ } ++ ++ memset(nlh, 0, NLMSG_SIZE); ++ ++ do { ++ ret = recv(s, (void *) nlh, NLMSG_SIZE, MSG_DONTWAIT); ++ } while ((ret < 0) && errno == EINTR); ++ ++ if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), ++ (struct nlattr **)&tb, IFLA_MAX, NULL)) { ++ goto out_free; ++ } ++ ++ if (tb[IFLA_ADDRESS]) ++ memcpy(mac, (char*)(RTA_DATA(tb[IFLA_ADDRESS])), 6); ++ ++ /* Check for the permanent mac address on bonding slaves */ ++ if (perm_mac && tb[IFLA_LINKINFO]) { ++ char *kind; ++ struct nlattr *tb3; ++ int off = 0; ++ ++ if (nla_parse_nested(tb2, IFLA_INFO_MAX, tb[IFLA_LINKINFO], ++ ifla_info_policy)) { ++ goto out_free; ++ } ++ if (!tb2[IFLA_INFO_SLAVE_KIND]) ++ goto out_free; ++ ++ kind = (char*)(RTA_DATA(tb2[IFLA_INFO_SLAVE_KIND])); ++ if (strcmp(kind, "bond") && !tb2[IFLA_INFO_SLAVE_DATA]) ++ goto out_free; ++ ++ nla_for_each_nested(tb3, tb2[IFLA_INFO_SLAVE_DATA], off) { ++ if (nla_type(tb3) == IFLA_BOND_SLAVE_PERM_HWADDR) { ++ memcpy(mac, nla_data(tb3), nla_len(tb3)); ++ } ++ } ++ } ++ ++out_free: ++ free(nlh); ++out: ++ close(s); ++ return 0; ++} + + u16 get_caps(const char *ifname) + { +@@ -998,7 +1064,7 @@ int get_saddr(const char *ifname, struct + fd = get_ioctl_socket(); + if (fd >= 0) { + ifr.ifr_addr.sa_family = AF_INET; +- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ++ STRNCPY_TERMINATED(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) { + memcpy(saddr, &ifr.ifr_addr, sizeof(*saddr)); + rc = 0; +@@ -1039,9 +1105,11 @@ int get_saddr6(const char *ifname, struc + + rc = getifaddrs(&ifaddr); + if (rc == 0) { ++ rc = -1; + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { +- if ((ifa->ifa_addr->sa_family == AF_INET6) && +- (strncmp(ifa->ifa_name, ifname, IFNAMSIZ) == 0)) { ++ if (strncmp(ifa->ifa_name, ifname, IFNAMSIZ)) ++ continue; ++ if (ifa->ifa_addr && (ifa->ifa_addr->sa_family == AF_INET6)) { + memcpy(saddr, ifa->ifa_addr, sizeof(*saddr)); + rc = 0; + break; +@@ -1092,7 +1160,7 @@ int get_addr(const char *ifname, int dom + else if (domain == AF_INET6) + return get_ipaddr6(ifname, (struct in6_addr *)buf); + else if (domain == AF_UNSPEC) +- return get_mac(ifname, (u8 *)buf); ++ return get_mac(ifname, (u8 *)buf, false); + else + return -1; + } +@@ -1227,7 +1295,7 @@ int get_arg_val_list(char *ibuf, int ile + } + hexstr2bin(ibuf+*ioff, &arglen, sizeof(arglen)); + *ioff += 2 * (int)sizeof(arglen); +- if (ilen - *ioff >= arglen) { ++ if (ilen - *ioff >= 0) { + args[i] = ibuf+*ioff; + *ioff += arglen; + *(arglens+i) = arglen; +@@ -1237,7 +1305,7 @@ int get_arg_val_list(char *ibuf, int ile + sizeof(argvalue_len)); + argvalue_len = ntohs(argvalue_len); + *ioff += 2*sizeof(argvalue_len); +- if (ilen - *ioff >= argvalue_len) { ++ if (ilen - *ioff >= 0) { + argvals[i] = ibuf+*ioff; + *ioff += argvalue_len; + *(argvallens+i) = argvalue_len; +diff -upr a/log.c b/log.c +--- a/log.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/log.c 2020-09-23 08:50:52.655813990 -0400 +@@ -65,4 +65,5 @@ void log_message(int level, const char * + bypass_time = strchr(format, '\n') == 0; + } + va_end(va); ++ va_end(vb); + } +diff -upr a/Makefile.am b/Makefile.am +--- a/Makefile.am 2021-06-09 10:58:59.212200603 -0400 ++++ b/Makefile.am 2021-04-05 12:02:17.315590455 -0400 +@@ -1,6 +1,9 @@ + # target programs to be installed in ${sbindir} + sbin_PROGRAMS = lldpad dcbtool lldptool vdptool + ++check_PROGRAMS = lldp_clif_test ++TESTS = $(check_PROGRAMS) ++ + # package nltest and vdptest, but do not install it anywhere + if BUILD_DEBUG + noinst_PROGRAMS = nltest vdptest qbg22sim +@@ -16,7 +19,7 @@ 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) $(LIBNL_CFLAGS) ++AM_CFLAGS = $(LIBCONFIG_CFLAGS) $(LIBNL_CFLAGS) + AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS) -lrt + + ## header files to be installed, for programs using the client interface to lldpad +@@ -86,9 +89,11 @@ vdptool_LDADD = 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) ++ weak_readline.c lldp_rtnl.c lldp_util.c \ ++ $(lldpad_include_HEADERS) $(noinst_HEADERS) ++ + dcbtool_LDADD = liblldp_clif.la +-dcbtool_LDFLAGS = -ldl -llldp_clif ++dcbtool_LDFLAGS = -ldl -llldp_clif $(LIBNL_LIBS) + + lldptool_SOURCES = lldptool.c lldptool_cmds.c lldp_rtnl.c \ + lldp_mand_clif.c lldp_basman_clif.c lldp_med_clif.c \ +@@ -140,3 +145,18 @@ bashcompletiondir = $(sysconfdir)/bash_c + dist_bashcompletion_DATA = contrib/bash_completion/lldpad contrib/bash_completion/lldptool + + AM_DISTCHECK_CONFIGURE_FLAGS = --enable-debug ++ ++lldp_clif_test_SOURCES = test/lldp_clif_test.c lldp_basman_clif.c lldp_util.c \ ++ lldp_rtnl.c ++lldp_clif_test_LDFLAGS = -lrt $(LIBNL_LIBS) ++ ++RPMBUILD_TOP = $(abs_top_builddir)/rpm/rpmbuild ++RPMBUILD_OPT ?= --without check ++ ++# Build user-space RPMs ++rpm: dist $(srcdir)/lldpad.spec ++ ${MKDIR_P} ${RPMBUILD_TOP}/SOURCES ++ cp ${DIST_ARCHIVES} ${RPMBUILD_TOP}/SOURCES ++ rpmbuild ${RPMBUILD_OPT} \ ++ -D "_topdir ${RPMBUILD_TOP}" \ ++ -ba $(srcdir)/lldpad.spec +diff -upr a/parse_cli.l b/parse_cli.l +--- a/parse_cli.l 2015-01-20 13:42:56.000000000 -0500 ++++ b/parse_cli.l 2020-09-23 08:50:52.655813990 -0400 +@@ -494,7 +494,8 @@ gp { if (!cmd) { + yyless(0); + } + +-[0-7] { up2tc_a[up2tc_idx++] = atoi(yytext); ++[0-7] { up2tc_a[up2tc_idx] = atoi(yytext); ++ up2tc_idx++; + if (up2tc_idx == 8) { + BEGIN(getpgargs); + } +diff -upr a/qbg/ecp22.c b/qbg/ecp22.c +--- a/qbg/ecp22.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/qbg/ecp22.c 2020-10-23 14:12:58.976289329 -0400 +@@ -119,7 +119,8 @@ static void ecp22_append(u8 *buffer, u32 + */ + void ecp22_putnode(struct ecp22_freelist *list, struct ecp22_payload_node *elm) + { +- elm->ptlv = free_pkd_tlv(elm->ptlv); ++ free_pkd_tlv(elm->ptlv); ++ elm->ptlv = NULL; + if (list->freecnt > ecp22_maxpayload) + free(elm); + else { +@@ -154,6 +155,7 @@ static bool ecp22_build_ecpdu(struct ecp + memset(ecp->tx.frame, 0, sizeof ecp->tx.frame); + ecp22_append(ecp->tx.frame, &fb_offset, (void *)ð, sizeof eth); + ++ memset(&ecph, 0, sizeof(struct ecp22_hdr)); + ecp22_hdr_set_version(&ecph, 1); + ecp22_hdr_set_op(&ecph, ECP22_REQUEST); + ecp22_hdr_set_subtype(&ecph, ECP22_VDP); +@@ -749,7 +751,7 @@ static struct ecp22 *ecp22_create(char * + ifname); + return NULL; + } +- strncpy(ecp->ifname, ifname, sizeof ecp->ifname); ++ STRNCPY_TERMINATED(ecp->ifname, ifname, sizeof ecp->ifname); + ecp->l2 = l2_packet_init(ecp->ifname, 0, ETH_P_ECP22, + ecp22_rx_receiveframe, ecp, 1); + +@@ -774,7 +776,7 @@ void ecp22_start(char *ifname) + struct ecp22 *ecp; + + LLDPAD_DBG("%s:%s start ecp\n", __func__, ifname); +- eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); ++ eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22); + if (!eud) { + LLDPAD_DBG("%s:%s no ECP module\n", __func__, ifname); + return; +@@ -782,6 +784,10 @@ void ecp22_start(char *ifname) + ecp = find_ecpdata(ifname, eud); + if (!ecp) + ecp = ecp22_create(ifname, eud); ++ if (!ecp) { ++ LLDPAD_DBG("%s:%s failed creating ECP22 instance\n", __func__, ifname); ++ return; ++ } + ecp->max_retries = ECP22_MAX_RETRIES_DEFAULT; + ecp->max_rte = ECP22_ACK_TIMER_DEFAULT; + LIST_INIT(&ecp->inuse.head); +@@ -803,7 +809,7 @@ static void ecp22_removelist(ecp22_list + + while ((np = LIST_FIRST(ptr))) { + LIST_REMOVE(np, node); +- np->ptlv = free_pkd_tlv(np->ptlv); ++ free_pkd_tlv(np->ptlv); + free(np); + } + } +@@ -816,6 +822,7 @@ static void ecp22_remove(struct ecp22 *e + ecp22_removelist(&ecp->isfree.head); + ecp->isfree.freecnt = 0; + LIST_REMOVE(ecp, node); ++ l2_packet_deinit(ecp->l2); + free(ecp); + } + +@@ -832,7 +839,7 @@ void ecp22_stop(char *ifname) + struct ecp22 *ecp; + + LLDPAD_DBG("%s:%s stop ecp\n", __func__, ifname); +- eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); ++ eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22); + ecp = find_ecpdata(ifname, eud); + if (ecp) + ecp22_remove(ecp); +@@ -847,7 +854,7 @@ static int ecp22_data_from_evb(char *ifn + struct ecp22_user_data *eud; + struct ecp22 *ecp; + +- eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); ++ eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22); + ecp = find_ecpdata(ifname, eud); + if (ecp) { + ecp->max_rte = ptr->max_rte; +@@ -925,7 +932,7 @@ static int ecp22_req2send(char *ifname, + + LLDPAD_DBG("%s:%s subtype:%d\n", __func__, ifname, subtype); + +- eud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_ECP22); ++ eud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_ECP22); + ecp = find_ecpdata(ifname, eud); + if (!ecp) { + rc = -ENODEV; +diff -upr a/qbg/ecp.c b/qbg/ecp.c +--- a/qbg/ecp.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/qbg/ecp.c 2020-09-23 08:50:52.656814007 -0400 +@@ -299,7 +299,7 @@ static bool ecp_build_ECPDU(struct vdp_d + + rc = ecp_append(vd->ecp.tx.frame, &fb_offset, ptlv->tlv, + ptlv->size); +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + if (rc) + p->seqnr = vd->ecp.lastSequence; + else +@@ -682,7 +682,7 @@ static void ecp_rx_ReceiveFrame(void *ct + } + + if (hdr->h_proto != example_hdr.h_proto) { +- LLDPAD_ERR("%s:%s ERROR ethertype %#x not ECP ethertype", ++ LLDPAD_ERR("%s:%s ERROR ethertype %#x not ECP ethertype\n", + __func__, vd->ecp.ifname, htons(hdr->h_proto)); + frame_error++; + return; +@@ -795,7 +795,7 @@ int ecp_init(char *ifname) + __func__, ifname); + return -1; + } +- strncpy(vd->ecp.ifname, ifname, sizeof vd->ecp.ifname); ++ STRNCPY_TERMINATED(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); +@@ -969,7 +969,7 @@ static void ecp_rx_ProcessFrame(struct v + 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); ++ free_unpkd_tlv(tlv); + vd->ecp.stats.statsTLVsUnrecognizedTotal++; + } + tlv = NULL; +diff -upr a/qbg/vdp22.c b/qbg/vdp22.c +--- a/qbg/vdp22.c 2021-06-09 10:58:59.210200578 -0400 ++++ b/qbg/vdp22.c 2020-10-23 14:12:58.977289347 -0400 +@@ -455,10 +455,10 @@ static void copy_filter(unsigned char fi + fp->grpid = from->gpid; + if (fif == VDP22_FFMT_GROUPVID) + goto vid; +- /* Fall through intended */ ++ /* FALLTHROUGH */ + case VDP22_FFMT_MACVID: + memcpy(fp->mac, from->mac, sizeof(fp->mac)); +- /* Fall through intended */ ++ /* FALLTHROUGH */ + case VDP22_FFMT_VID: + vid: + fp->vlan = vdp22_set_vlanid(from->vlan) +@@ -694,7 +694,7 @@ static struct vdp22 *vdp22_findif(const + struct vdp22 *vdp = 0; + + if (!ud) { +- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP22); + if (!ud) + LLDPAD_DBG("%s:%s no VDP22 module\n", __func__, + ifname); +@@ -794,7 +794,7 @@ void vdp22_stop(char *ifname) + struct vsi22 *vsi; + + LLDPAD_DBG("%s:%s stop vdp\n", __func__, ifname); +- vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); ++ vud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP22); + if (!vud) { + LLDPAD_ERR("%s:%s no VDP22 module\n", __func__, ifname); + return; +@@ -834,7 +834,7 @@ static struct vdp22 *vdp22_create(const + ifname); + return NULL; + } +- strncpy(vdp->ifname, ifname, sizeof vdp->ifname); ++ STRNCPY_TERMINATED(vdp->ifname, ifname, sizeof vdp->ifname); + vdp->myrole = role; + LIST_INIT(&vdp->vsi22_que); + LIST_INSERT_HEAD(&eud->head, vdp, node); +@@ -874,7 +874,7 @@ void vdp22_start(const char *ifname, int + struct vsi22 *vsi; + + LLDPAD_DBG("%s:%s start vdp\n", __func__, ifname); +- vud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP22); ++ vud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP22); + if (!vud) { + LLDPAD_ERR("%s:%s no VDP22 module\n", __func__, ifname); + return; +diff -upr a/qbg/vdp22_cmds.c b/qbg/vdp22_cmds.c +--- a/qbg/vdp22_cmds.c 2021-06-09 10:58:59.201200461 -0400 ++++ b/qbg/vdp22_cmds.c 2020-10-23 14:12:58.977289347 -0400 +@@ -57,7 +57,7 @@ static struct lldp_module *get_my_module + { + struct lldp_module *np = NULL; + +- LIST_FOREACH(np, &lldp_head, lldp) ++ LIST_FOREACH(np, &lldp_mod_head, lldp) + if (thisid == np->id) + break; + return np; +@@ -296,7 +296,7 @@ int vdp22_sendevent(struct vdpnl_vsi *p) + return 0; + } + +-static int vdp22_cmdok(struct cmd *cmd, cmd_status expected) ++static int vdp22_cmdok(struct cmd *cmd, int expected) + { + if (cmd->cmd != expected) + return cmd_invalid; +@@ -473,6 +473,7 @@ static bool vdp22_partial_vsi_equal(stru + if (memcmp(p1->mgrid, p2->mgrid, + sizeof(p2->mgrid))) + return false; ++ /* FALLTHROUGH */ + case VSI_TYPEID_ARG: + if (p1->type_id != p2->type_id) + return false; +@@ -576,7 +577,7 @@ static int get_arg_vsi(struct cmd *cmd, + 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); ++ strncpy(vsi.ifname, cmd->ifname, sizeof(vsi.ifname)); + good_cmd = cmd_failed; + if ((cmd->ops & op_config) && (cmd->ops & op_arg)) { + memset(&mac, 0, sizeof(mac)); +diff -upr a/qbg/vdp22sm.c b/qbg/vdp22sm.c +--- a/qbg/vdp22sm.c 2021-06-09 10:58:59.210200578 -0400 ++++ b/qbg/vdp22sm.c 2020-09-23 08:50:52.657814025 -0400 +@@ -1521,7 +1521,7 @@ static void vdp22br_process(struct vsi22 + case VDP22_RESP_DEASSOC: + if (error > VDP22_STATUS_MASK) + p->status = VDP22_HARDBIT; +- /* Fall through intended */ ++ /* FALLTHROUGH */ + case VDP22_RESP_SUCCESS: + rest: + p->status |= VDP22_ACKBIT | make_status(error); +@@ -1768,7 +1768,7 @@ static void vdp22br_run(struct vsi22 *p) + break; + case VDP22_BR_END: + vdp22br_end(p); +- break; ++ return; + } + } while (vdp22br_move_state(p) == true); + } +diff -upr a/qbg/vdp.c b/qbg/vdp.c +--- a/qbg/vdp.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/qbg/vdp.c 2020-10-23 14:12:58.977289347 -0400 +@@ -188,7 +188,7 @@ 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); ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP02); + if (ud) { + LIST_FOREACH(vd, &ud->head, entry) { + if (!strncmp(ifname, vd->ifname, IFNAMSIZ)) +@@ -879,7 +879,7 @@ static bool vdp_vsi_set_bridge_state(str + { + switch(profile->state) { + case VSI_UNASSOCIATED: +- if ((profile->mode == VDP_MODE_DEASSOCIATE)) /* || (INACTIVE)) */ { ++ if (profile->mode == VDP_MODE_DEASSOCIATE) { + vdp_vsi_change_bridge_state(profile, VSI_DEASSOC_PROCESSING); + return true; + } else if (profile->mode == VDP_MODE_ASSOCIATE) { +@@ -1198,9 +1198,9 @@ int vdp_indicate(struct vdp_data *vd, st + /* put it in the list */ + profile->state = VSI_UNASSOCIATED; + LIST_INSERT_HEAD(&vd->profile_head, profile, profile); +- } + +- vdp_vsi_sm_bridge(profile); ++ vdp_vsi_sm_bridge(profile); ++ } + } + + return 0; +@@ -1357,7 +1357,7 @@ struct packed_tlv *vdp_gettlv(struct vdp + return ptlv; + + out_free: +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); + out_err: + LLDPAD_ERR("%s: %s failed\n", __func__, vd->ifname); + return NULL; +@@ -1607,7 +1607,7 @@ void vdp_ifup(char *ifname, struct lldp_ + __func__, ifname, sizeof(*vd)); + goto out_err; + } +- strncpy(vd->ifname, ifname, IFNAMSIZ); ++ STRNCPY_TERMINATED(vd->ifname, ifname, IFNAMSIZ); + + vd->role = VDP_ROLE_STATION; + vd->enabletx = enabletx; +@@ -1624,7 +1624,7 @@ void vdp_ifup(char *ifname, struct lldp_ + + LIST_INIT(&vd->profile_head); + +- ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_VDP02); ++ ud = find_module_user_data_by_id(&lldp_mod_head, LLDP_MOD_VDP02); + LIST_INSERT_HEAD(&ud->head, vd, entry); + + out_start_again: +@@ -1882,7 +1882,7 @@ int vdp_trigger(struct vsi_profile *prof + if (!macp->req_pid) + return 0; + sleep(1); /* Delay message notification */ +- if (!profile->port || !profile->port->ifname) { ++ if (!profile->port || !profile->port->ifname[0]) { + LLDPAD_ERR("%s: no ifname found for profile %p:\n", __func__, + profile); + goto error_exit; +diff -upr a/qbg/vdp_cmds.c b/qbg/vdp_cmds.c +--- a/qbg/vdp_cmds.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/qbg/vdp_cmds.c 2020-09-23 08:50:52.658814043 -0400 +@@ -85,7 +85,7 @@ static char *print_mode(char *s, size_t + return s; + } + +-static int vdp_cmdok(struct cmd *cmd, cmd_status expected) ++static int vdp_cmdok(struct cmd *cmd, int expected) + { + if (cmd->cmd != expected) + return cmd_invalid; +diff -upr a/qbg/vdpnl.c b/qbg/vdpnl.c +--- a/qbg/vdpnl.c 2021-06-09 10:58:59.201200461 -0400 ++++ b/qbg/vdpnl.c 2020-09-23 08:50:52.658814043 -0400 +@@ -233,7 +233,7 @@ static int vdpnl_set(struct nlmsghdr *nl + + vsi->ifindex = ifinfo->ifi_index; + if (tb[IFLA_IFNAME]) +- strncpy(vsi->ifname, (char *)RTA_DATA(tb[IFLA_IFNAME]), ++ STRNCPY_TERMINATED(vsi->ifname, (char *)RTA_DATA(tb[IFLA_IFNAME]), + sizeof vsi->ifname); + else { + if (!if_indextoname(ifinfo->ifi_index, vsi->ifname)) { +@@ -304,9 +304,9 @@ 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 */ ++ + 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; + } + +diff -upr a/qbg_utils.c b/qbg_utils.c +--- a/qbg_utils.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/qbg_utils.c 2020-11-03 09:08:48.062229088 -0500 +@@ -36,7 +36,6 @@ + #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 +@@ -73,7 +72,7 @@ void hexdump_frame(const char *ifname, c + */ + int modules_notify(int id, int sender_id, char *ifname, void *data) + { +- struct lldp_module *mp = find_module_by_id(&lldp_head, id); ++ struct lldp_module *mp = find_module_by_id(&lldp_mod_head, id); + int rc = 0; + + if (mp && mp->ops->lldp_mod_notify) +diff -upr a/README b/README +--- a/README 2015-01-20 13:42:56.000000000 -0500 ++++ b/README 2020-09-23 08:50:52.646813830 -0400 +@@ -186,7 +186,9 @@ lldpad Application Install + lldpad will create the lldpad.conf file if it does not exist. + + For development purposes, 'lldpad' can be run directly from the build +- directory. ++ directory. To run the unit tests associated with openlldpd, execute: ++ ++ ./bootstrap.sh; ./configure; make check + + Options + ------- +diff -upr a/tlv_dcbx.c b/tlv_dcbx.c +--- a/tlv_dcbx.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/tlv_dcbx.c 2020-09-23 08:50:52.659814061 -0400 +@@ -154,7 +154,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + if (tlv_ok(dcbx->pg1)) { + ptlv = pack_tlv(dcbx->pg1); +@@ -162,7 +163,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + if (tlv_ok(dcbx->pfc1)) { + ptlv = pack_tlv(dcbx->pfc1); +@@ -170,7 +172,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + if (tlv_ok(dcbx->app1)) { + ptlv = pack_tlv(dcbx->app1); +@@ -178,7 +181,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + + if (tlv_ok(dcbx->llink)) { +@@ -187,7 +191,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + + if (offset != tlv->length) +@@ -196,7 +201,8 @@ struct unpacked_tlv *bld_dcbx1_tlv(struc + return tlv; + + error: +- ptlv = free_pkd_tlv(ptlv); ++ if (ptlv) ++ free_pkd_tlv(ptlv); + if (tlv) { + if (tlv->info) + free(tlv->info); +@@ -254,7 +260,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + if (tlv_ok(dcbx->pg2)) { + ptlv = pack_tlv(dcbx->pg2); +@@ -262,7 +269,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + if (tlv_ok(dcbx->pfc2)) { + ptlv = pack_tlv(dcbx->pfc2); +@@ -270,7 +278,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + if (tlv_ok(dcbx->app2)) { + ptlv = pack_tlv(dcbx->app2); +@@ -278,7 +287,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc + goto error; + memcpy(&tlv->info[offset], ptlv->tlv, ptlv->size); + offset += ptlv->size; +- ptlv = free_pkd_tlv(ptlv); ++ free_pkd_tlv(ptlv); ++ ptlv = NULL; + } + + if (offset != tlv->length) +@@ -287,7 +297,8 @@ struct unpacked_tlv *bld_dcbx2_tlv(struc + return tlv; + + error: +- ptlv = free_pkd_tlv(ptlv); ++ if (ptlv) ++ free_pkd_tlv(ptlv); + if (tlv) { + if (tlv->info) + free(tlv->info); +diff -upr a/vdptool.c b/vdptool.c +--- a/vdptool.c 2021-06-09 10:58:59.202200474 -0400 ++++ b/vdptool.c 2020-10-23 14:12:58.978289365 -0400 +@@ -36,6 +36,7 @@ + * set and query VSI profile settings. + */ + ++#define _GNU_SOURCE + #include + #include + #include +@@ -60,6 +61,8 @@ + #define OUI_ENCODE_HNDLR(name) name##_oui_encode_hndlr + #define OUI_PRNT_DECODE_HNDLR(name) name##_oui_print_decode_hndlr + ++struct lldp_head lldp_mod_head; ++ + #define EXTERN_OUI_FN(name) \ + extern bool name##_oui_encode_hndlr(char *, char *, size_t); \ + extern void name##_oui_print_decode_hndlr(char *) +@@ -140,7 +143,7 @@ static char *print_status(cmd_status sta + str = "TLV does not support agent type"; + break; + default: +- str = print_vdp_status(status); ++ str = print_vdp_status((enum vdp22_cmd_status)status); + break; + } + return str; +@@ -178,7 +181,7 @@ static char *get_oui_name(char *argvals) + + 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)); ++ STRNCPY_TERMINATED(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); + } +@@ -587,7 +590,7 @@ static void print_all_vsis(char *ibuf, b + size_t ilen = strlen(ibuf); + u16 vsi_len; + int offset = 0, vsi_cnt = 0; +- char tmp_ibuf[strlen(ibuf)]; ++ char tmp_ibuf[strlen(ibuf) + 1]; + + while (ilen > 0) { + vsi_len = hex2u16(ibuf + offset); +@@ -795,13 +798,13 @@ static void init_modules(void) + struct lldp_module *premod = NULL; + int i = 0; + +- LIST_INIT(&lldp_head); ++ LIST_INIT(&lldp_mod_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); ++ LIST_INSERT_HEAD(&lldp_mod_head, module, lldp); + premod = module; + } + } +@@ -810,9 +813,9 @@ 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); ++ while (lldp_mod_head.lh_first != NULL) { ++ module = lldp_mod_head.lh_first; ++ LIST_REMOVE(lldp_mod_head.lh_first, lldp); + module->ops->lldp_mod_unregister(module); + } + } +@@ -952,7 +955,7 @@ cli_cmd_help(UNUSED struct clif *clif, U + printf("%s\n%s\n%s", commands_usage, commands_options, commands_help); + + printf("\nTLV identifiers:\n"); +- LIST_FOREACH(np, &lldp_head, lldp) ++ LIST_FOREACH(np, &lldp_mod_head, lldp) + if (np->ops->print_help) + np->ops->print_help(); + return 0; +@@ -1005,7 +1008,7 @@ u32 lookup_tlvid(char *tlvid_str) + struct lldp_module *np; + u32 tlvid = INVALID_TLVID; + +- LIST_FOREACH(np, &lldp_head, lldp) { ++ LIST_FOREACH(np, &lldp_mod_head, lldp) { + if (np->ops->lookup_tlv_name) { + tlvid = np->ops->lookup_tlv_name(tlvid_str); + if (tlvid != INVALID_TLVID) +diff -upr a/vdptool_cisco_oui.c b/vdptool_cisco_oui.c +--- a/vdptool_cisco_oui.c 2021-06-09 10:58:59.203200487 -0400 ++++ b/vdptool_cisco_oui.c 2020-09-23 08:50:52.660814079 -0400 +@@ -28,7 +28,7 @@ + #include "lldp_util.h" + #include "vdp_cisco.h" + +-bool cisco_oui_encode_hndlr(char *dst, char *src, int len) ++bool cisco_oui_encode_hndlr(char *dst, char *src, size_t len) + { + char *src_temp = strdup(src); + char *key, *data; +diff -upr a/weak_readline.c b/weak_readline.c +--- a/weak_readline.c 2015-01-20 13:42:56.000000000 -0500 ++++ b/weak_readline.c 2020-09-23 08:50:52.660814079 -0400 +@@ -30,6 +30,9 @@ + #include + + static int inited; ++static void *hist_handle; ++static void *rl_handle; ++ + + static char *(*readline_p)(const char *); + static void (*using_history_p)(void); +@@ -38,9 +41,6 @@ static void (*add_history_p)(const char + + static void weak_readline_init(void) + { +- void *hist_handle; +- void *rl_handle; +- + inited = 1; + hist_handle = dlopen("libhistory.so", RTLD_LAZY | RTLD_GLOBAL); + if (!hist_handle) +@@ -77,6 +77,16 @@ void using_history(void) + using_history_p(); + } + ++void close_history(void) ++{ ++ if (inited) { ++ dlclose(rl_handle); ++ rl_handle = NULL; ++ dlclose(hist_handle); ++ hist_handle = NULL; ++ } ++} ++ + void stifle_history(int max) + { + if (!inited) diff --git a/SOURCES/open-lldp-v1.0.1-4-VDP-Changes-to-make-the-interface-to-VDP22-in-lldpad.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-5-VDP-Support-for-get-tlv-in-vdptool-and-VDP22.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-6-VDP-Support-in-VDP22-for-correct-error-code-status-t.patch b/SOURCES/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/SOURCES/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/SOURCES/open-lldp-v1.0.1-7-VDP-Support-for-OUI-infrastructure-in-VDP22.patch b/SOURCES/open-lldp-v1.0.1-7-VDP-Support-for-OUI-infrastructure-in-VDP22.patch new file mode 100644 index 0000000..aa2c193 --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch b/SOURCES/open-lldp-v1.0.1-8-VDP-Support-for-OUI-infrastructure-in-vdptool.patch new file mode 100644 index 0000000..674f448 --- /dev/null +++ b/SOURCES/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/SOURCES/open-lldp-v1.0.1-9-VDP-Support-for-OUI-infrastructure-in-vdp22.patch b/SOURCES/open-lldp-v1.0.1-9-VDP-Support-for-OUI-infrastructure-in-vdp22.patch new file mode 100644 index 0000000..47c73ac --- /dev/null +++ b/SOURCES/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/SPECS/lldpad.spec b/SPECS/lldpad.spec new file mode 100644 index 0000000..353cea6 --- /dev/null +++ b/SPECS/lldpad.spec @@ -0,0 +1,366 @@ +%global _default_patch_fuzz 2 + +# https://fedoraproject.org/wiki/Packaging:Guidelines#Compiler_flags +%global _hardened_build 1 + +%global checkout 036e314 + +Name: lldpad +Version: 1.0.1 +Release: 19.git%{checkout}%{?dist} +Summary: Intel LLDP Agent +Group: System Environment/Daemons +License: GPLv2 +URL: http://open-lldp.org/ +Source0: %{name}-%{version}.tar.gz +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-switch-from-sysv-to-posix-shared-memory-apis.patch +Patch25: open-lldp-v1.0.1-25-l2_linux_packet-correctly-process-return-value-of-ge.patch +Patch26: open-lldp-v1.0.1-26-lldpad-system-capability-incorrect-advertised-as-sta.patch +Patch27: open-lldp-v1.0.1-27-fix-build-warnings.patch +Patch28: open-lldp-v1.0.1-28-fix-oid-display.patch +Patch29: open-lldp-v1.0.1-29-memleak-on-received-TLVs.patch +Patch30: open-lldp-v1.0.1-30-support-DSCP-selectors.patch +Patch31: open-lldp-v1.0.1-31-Rebase-to-open-lldp-branch-1.1.0.patch + +Patch32: 0001-vdp22-convert-command-parsing-to-null-term.patch +Patch33: 0002-macvtap-fix-error-condition.patch +Patch34: 0003-8021qaz-squelch-initialization-errors.patch +Patch35: 0004-8021Qaz-check-for-rx-block-validity.patch +Patch36: 0005-basman-use-return-address-when-pulling-address.patch +Patch37: 0006-agent-reset-frame-status-on-message-delete.patch +Patch38: 0007-Avoiding-null-pointer-dereference.patch +Patch39: 0008-Revert-Use-interface-index-instead-of-name-in-libcon.patch + +BuildRequires: automake autoconf libtool +BuildRequires: flex +BuildRequires: kernel-headers +BuildRequires: libconfig-devel +BuildRequires: libnl3-devel +BuildRequires: readline-devel +BuildRequires: systemd +Requires: readline +Requires: libconfig +Requires: libnl3 + + +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd + +%description +This package contains the Linux user space daemon and configuration tool for +Intel LLDP Agent with Enhanced Ethernet support for the Data Center. + +%package devel +Summary: Development files for %{name} +Group: Development/Libraries +Requires: %{name}%{?_isa} = %{version}-%{release} +Provides: dcbd-devel = %{version}-%{release} +Obsoletes: dcbd-devel < 0.9.26 + +%description devel +The %{name}-devel package contains header files for developing applications +that use %{name}. + +%prep +%autosetup -p1 + +%build +./bootstrap.sh +CFLAGS=${CFLAGS:-%optflags -Wno-error}; export CFLAGS; +%configure --disable-static +# fix the hardened build flags +sed -i -e 's! \\\$compiler_flags !&\\\$CFLAGS \\\$LDFLAGS !' libtool +make %{?_smp_mflags} + +%install +make install DESTDIR=%{buildroot} +mkdir -p %{buildroot}%{_sharedstatedir}/%{name} +rm -f %{buildroot}%{_libdir}/liblldp_clif.la + +%post +/sbin/ldconfig +%systemd_post %{name}.service %{name}.socket + +%preun +%systemd_preun %{name}.service %{name}.socket + +%postun +/sbin/ldconfig +%systemd_postun_with_restart %{name}.service %{name}.socket + +%files +%doc COPYING README ChangeLog +%{_sbindir}/* +%{_libdir}/liblldp_clif.so.* +%dir %{_sharedstatedir}/%{name} +%{_unitdir}/%{name}.service +%{_unitdir}/%{name}.socket +%{_sysconfdir}/bash_completion.d/* +%{_mandir}/man3/* +%{_mandir}/man8/* + +%files devel +%{_includedir}/* +%{_libdir}/pkgconfig/*.pc +%{_libdir}/liblldp_clif.so + +%changelog +* Fri Aug 26 2022 Aaron Conole - 1.0.1-19.git036e314 +- Update changelog (#1997064) + +* Fri Aug 26 2022 Aaron Conole - 1.0.1-18.git036e314 +- Fix dependency specification (#1997064) + +* Tue Jun 21 2022 Aaron Conole - 1.0.1-17.git036e314 +- Update to the latest branch-1.1, which includes config file fixes (#1997064) + +* Wed Aug 04 2021 Aaron Conole - 1.0.1-16.git036e314 +- Update the changelog + +* Wed Aug 04 2021 Aaron Conole - 1.0.1-15.git036e314 +- Fix the branch compatibility + +* Wed Jun 09 2021 Aaron Conole - 1.0.1-14.git036e314 +- Update to branch-1.1 compatibility +- Fixes to avoid assert in the agent state machine +- Remove the memory constraint on the event socket buffer (#1554110) + +* Tue Aug 13 2019 Aaron Conole - 1.0.1-13.git036e314 +- After gating yml updates + +* Fri Jul 05 2019 Aaron Conole - 1.0.1-12.git036e314 +- Add support for DSCP selectors in APP TLVs (#1704660) + +* Fri Jul 05 2019 Aaron Conole - 1.0.1-11.git036e314 +- Fix memleak on TLV reception (#1727326) + +* Fri Jul 05 2019 Aaron Conole - 1.0.1-10.git036e314 +- Fix the OID display (#1614933) + +* Thu Feb 08 2018 Fedora Release Engineering - 1.0.1-9.git036e314 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Aug 03 2017 Fedora Release Engineering - 1.0.1-8.git036e314 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 1.0.1-7.git036e314 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Sun Feb 12 2017 Chris Leech - 1.0.1-6.git036e314 +- disable -Werror from upstream to rebuild with newer compiler warnings + +* Fri Feb 10 2017 Fedora Release Engineering - 1.0.1-5.git036e314 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Feb 04 2016 Fedora Release Engineering - 1.0.1-4.git036e314 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Mon Feb 01 2016 Chris Leech - 1.0.1-3.git986eb2e +- 1303439 package should not attempt to own /etc/bash_completion.d +- fix more build warning in rawhide + +* Tue Nov 03 2015 Chris Leech - 1.0.1-2.git986eb2e +- convert from sysv shm to posix, to allow selinux restorecon + +* 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 + +* Sun Aug 17 2014 Fedora Release Engineering - 0.9.46-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Tue Jul 22 2014 Peter Robinson 0.9.46-6 +- Add upstream patch to build against libnl3 +- Drop legacy dcbd packaging support, we've not shipped it since F-13 + +* Sat Jun 07 2014 Fedora Release Engineering - 0.9.46-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Mar 11 2014 Petr Šabata - 0.9.46-4 +- Drop the explicit kernel runtime dependency +- Patch configure.ac to build in rawhide + +* Wed Jul 31 2013 Petr Šabata - 0.9.46-3 +- Require 'systemd' instead of 'systemd-units' + +* Tue Jul 02 2013 Petr Šabata - 0.9.46-2 +- Fix the hardened build flags + +* Tue Jun 04 2013 Petr Šabata - 0.9.46-1 +- 0.9.46 bump +- 802.1Qaz fixes to enable support on not CEE DCBX-enabled hardware +- 802.1Qbg EVB module support +- lldpad now supports bonded interfaces + +* Tue Mar 05 2013 Petr Šabata - 0.9.45-5 +- Fix build by patching the sizeof() call in lldp_8021qaz_cmds.c + +* Thu Feb 14 2013 Fedora Release Engineering - 0.9.45-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Tue Aug 28 2012 Petr Šabata - 0.9.45-3 +- Migrate to systemd scriptlets (#850192) + +* Thu Aug 23 2012 Petr Šabata - 0.9.45-2 +- Fix displaying of the Management Address TLV (327ef662) + +* Wed Aug 15 2012 Petr Šabata - 0.9.45-1 +- 0.9.45 bump +- Provide bash-completion and the new clif library + +* Thu Jul 19 2012 Fedora Release Engineering - 0.9.44-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Fri Jan 27 2012 Petr Šabata - 0.9.44-1 +- 0.9.44 bump, patches cleanup +- Correct dependencies a bit +- Require dlopen()'d readline + +* Fri Jan 13 2012 Fedora Release Engineering - 0.9.43-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Thu Oct 06 2011 Petr Sabata - 0.9.43-5 +- Do not enable lldpad by default (#701999) + +* Fri Sep 23 2011 Petr Sabata - 0.9.43-4 +- Enable hardened build + +* Tue Sep 13 2011 Petr Sabata - 0.9.43-3 +- Mute systemd output (#737897) + +* Tue Aug 30 2011 Petr Sabata - 0.9.43-2 +- Apply various upstream 0.9.43 bugfixes +- Include not yet accepted Jens Osterkamp's patch to fix bug #720080 +- Whitespace cleanup, phew + +* Thu Jul 07 2011 Petr Sabata - 0.9.43-1 +- 0.9.43 bump +- Drop the the clean exit patch and our unit file, both are now included upstream + +* Tue Jun 21 2011 Petr Sabata - 0.9.42-2 +- Introduce systemd unit file, drop SysV support +- Call systemctl instead of service and chkconfig +- Enable the service only on new installation (post) +- Clean exit patch + +* Mon Jun 13 2011 Petr Sabata - 0.9.42-1 +- 0.9.42 bump (massive patches cleanup) +- Remove obsolete defattr +- Remove COPYING and README from devel subpackage + +* Wed May 4 2011 Petr Sabata - 0.9.41-3 +- Fix the frequent, power consuming lldpad wake-ups (rhbz#701943) + +* Thu Apr 21 2011 Petr Sabata - 0.9.41-2 +- Bring in upstream 802.1Qbg bugfixes + +* Thu Feb 10 2011 Petr Sabata - 0.9.41-1 +- 0.9.41 bump +- New BR: autotools, flex +- Buildroot garbage removed +- Devel post and preun scriptlets sanitized + +* Tue Feb 08 2011 Fedora Release Engineering - 0.9.38-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Jun 28 2010 Jan Zeleny - 0.9.38-1 +- rebased to 0.9.38 (various enhancements and bugfixes, see + lldpad-0.9.38-relnotes.txt on http://e1000.sf.net for complete list) + +* Mon May 10 2010 Jan Zeleny - 0.9.32-2 +- rebuild to match new libconfig + +* Mon Apr 12 2010 Jan Zeleny - 0.9.32-1 +- rebased to 0.9.32 (various enhancements and bugfixes, see + lldpad-0.9.32-relnotes.txt on http://e1000.sf.net for complete list) + +* Thu Mar 25 2010 Jan Zeleny - 0.9.29-2 +- added Provides and Obsoletes tags to devel subpackage + +* Mon Mar 15 2010 Jan Zeleny - 0.9.29-1 +- updated package to 0.9.29, improved compatibility with fcoe-utils + +* Fri Feb 26 2010 Jan Zeleny - 0.9.26-2 +- updated spec file and LSB init script patch for re-review + (#568641) + +* Thu Feb 25 2010 Jan Zeleny - 0.9.26-1 +- rebased to 0.9.26 +- package renamed to lldpad +- enahanced functionality (LLDP supported as well as DCBX) + +* Fri Nov 13 2009 Jan Zeleny - 0.9.19-2 +- init script patch adding LSB compliance + +* Thu Oct 08 2009 Jan Zeleny - 0.9.19-1 +- update to new upstream version + +* Mon Oct 05 2009 Jan Zeleny - 0.9.15-5 +- replaced the last patch, which was not fully functional, with + the new one + +* Wed Sep 09 2009 Karsten Hopp 0.9.15-4 +- buildrequire libconfig-devel >= 1.3.2, it doesn't build with 1.3.1 due to + the different config_lookup_string api + +* Thu Aug 20 2009 Jan Zeleny - 0.9.15-3 +- update of config_lookup_string() function calls + +* Thu Aug 20 2009 Jan Zeleny - 0.9.15-2 +- rebuild in order to match new libconfig + +* Mon Aug 17 2009 Jan Zeleny - 0.9.15-1 +- rebase to 0.9.15 + +* Fri Jul 24 2009 Fedora Release Engineering - 0.9.7-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Fri Mar 20 2009 Jan Zeleny - 0.9.7-4 +- updated scriptlets in spec file to follow the rules + +* Wed Mar 11 2009 Jan Zeleny - 0.9.7-3 +- added devel files again to support fcoe-utils package +- added kernel >= 2.6.29 to Requires, deleted dcbnl.h, since it is + aviable in kernel 2.6.29-rc7 +- changed config dir from /etc/sysconfig/dcbd to /etc/dcbd +- updated init script: added mandatory Short description tag, + deleted default runlevels, which should start the script + +* Tue Mar 10 2009 Jan Zeleny - 0.9.7-2 +- added patch to enable usage of libconfig shared in system +- removed devel part of package + +* Mon Mar 2 2009 Chris Leech - 0.9.7-1 +- Updated to 0.9.7 +- Added a private copy of dcbnl.h until kernel-headers includes it. + Export patch is making it's way to the upstream kernel via net-2.6, + expected in 2.6.29-rc7 + +* Thu Feb 26 2009 Chris Leech - 0.9.5-1 +- initial RPM packaging